blob: 15808910df9ac5f9c06aa45338b6d8bfa7c38274 [file] [log] [blame]
Dongwon Kang9c6f7902019-10-14 11:16:39 -07001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "PlayerServiceFileSource"
19#include <utils/Log.h>
20
21#include <datasource/PlayerServiceFileSource.h>
22#include <media/stagefright/foundation/ADebug.h>
23#include <private/android_filesystem_config.h>
24
25namespace android {
26
27PlayerServiceFileSource::PlayerServiceFileSource(const char *filename)
28 : FileSource(filename),
29 mDecryptHandle(NULL),
30 mDrmManagerClient(NULL),
31 mDrmBufOffset(0),
32 mDrmBufSize(0),
33 mDrmBuf(NULL){
34}
35
36PlayerServiceFileSource::PlayerServiceFileSource(int fd, int64_t offset, int64_t length)
37 : FileSource(fd, offset, length),
38 mDecryptHandle(NULL),
39 mDrmManagerClient(NULL),
40 mDrmBufOffset(0),
41 mDrmBufSize(0),
42 mDrmBuf(NULL) {
43}
44
45PlayerServiceFileSource::~PlayerServiceFileSource() {
46 if (mDrmBuf != NULL) {
47 delete[] mDrmBuf;
48 mDrmBuf = NULL;
49 }
50
51 if (mDecryptHandle != NULL) {
52 // To release mDecryptHandle
53 CHECK(mDrmManagerClient);
54 mDrmManagerClient->closeDecryptSession(mDecryptHandle);
55 mDecryptHandle = NULL;
56 }
57
58 if (mDrmManagerClient != NULL) {
59 delete mDrmManagerClient;
60 mDrmManagerClient = NULL;
61 }
62}
63
64ssize_t PlayerServiceFileSource::readAt(off64_t offset, void *data, size_t size) {
65 if (mFd < 0) {
66 return NO_INIT;
67 }
68
69 Mutex::Autolock autoLock(mLock);
70
71 if (mLength >= 0) {
72 if (offset >= mLength) {
73 return 0; // read beyond EOF.
74 }
75 uint64_t numAvailable = mLength - offset;
76 if ((uint64_t)size > numAvailable) {
77 size = numAvailable;
78 }
79 }
80
81 if (mDecryptHandle != NULL && DecryptApiType::CONTAINER_BASED
82 == mDecryptHandle->decryptApiType) {
83 return readAtDRM_l(offset, data, size);
84 } else {
85 return readAt_l(offset, data, size);
86 }
87}
88
89sp<DecryptHandle> PlayerServiceFileSource::DrmInitialization(const char *mime) {
90 if (getuid() == AID_MEDIA_EX) return nullptr; // no DRM in media extractor
91 if (mDrmManagerClient == NULL) {
92 mDrmManagerClient = new DrmManagerClient();
93 }
94
95 if (mDrmManagerClient == NULL) {
96 return NULL;
97 }
98
99 if (mDecryptHandle == NULL) {
100 mDecryptHandle = mDrmManagerClient->openDecryptSession(
101 mFd, mOffset, mLength, mime);
102 }
103
104 if (mDecryptHandle == NULL) {
105 delete mDrmManagerClient;
106 mDrmManagerClient = NULL;
107 }
108
109 return mDecryptHandle;
110}
111
112ssize_t PlayerServiceFileSource::readAtDRM_l(off64_t offset, void *data, size_t size) {
113 size_t DRM_CACHE_SIZE = 1024;
114 if (mDrmBuf == NULL) {
115 mDrmBuf = new unsigned char[DRM_CACHE_SIZE];
116 }
117
118 if (mDrmBuf != NULL && mDrmBufSize > 0 && (offset + mOffset) >= mDrmBufOffset
119 && (offset + mOffset + size) <= static_cast<size_t>(mDrmBufOffset + mDrmBufSize)) {
120 /* Use buffered data */
121 memcpy(data, (void*)(mDrmBuf+(offset+mOffset-mDrmBufOffset)), size);
122 return size;
123 } else if (size <= DRM_CACHE_SIZE) {
124 /* Buffer new data */
125 mDrmBufOffset = offset + mOffset;
126 mDrmBufSize = mDrmManagerClient->pread(mDecryptHandle, mDrmBuf,
127 DRM_CACHE_SIZE, offset + mOffset);
128 if (mDrmBufSize > 0) {
129 int64_t dataRead = 0;
130 dataRead = size > static_cast<size_t>(mDrmBufSize) ? mDrmBufSize : size;
131 memcpy(data, (void*)mDrmBuf, dataRead);
132 return dataRead;
133 } else {
134 return mDrmBufSize;
135 }
136 } else {
137 /* Too big chunk to cache. Call DRM directly */
138 return mDrmManagerClient->pread(mDecryptHandle, data, size, offset + mOffset);
139 }
140}
141
142/* static */
143bool PlayerServiceFileSource::requiresDrm(int fd, int64_t offset, int64_t length, const char *mime) {
144 std::unique_ptr<DrmManagerClient> drmClient(new DrmManagerClient());
145 sp<DecryptHandle> decryptHandle =
146 drmClient->openDecryptSession(fd, offset, length, mime);
147 bool requiresDrm = false;
148 if (decryptHandle != nullptr) {
149 requiresDrm = decryptHandle->decryptApiType == DecryptApiType::CONTAINER_BASED;
150 drmClient->closeDecryptSession(decryptHandle);
151 }
152 return requiresDrm;
153}
154
155} // namespace android