1 /*
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
25 namespace android {
26
PlayerServiceFileSource(const char * filename)27 PlayerServiceFileSource::PlayerServiceFileSource(const char *filename)
28 : FileSource(filename),
29 mDecryptHandle(NULL),
30 mDrmManagerClient(NULL),
31 mDrmBufOffset(0),
32 mDrmBufSize(0),
33 mDrmBuf(NULL){
34 (void) DrmInitialization(nullptr);
35 }
36
PlayerServiceFileSource(int fd,int64_t offset,int64_t length)37 PlayerServiceFileSource::PlayerServiceFileSource(int fd, int64_t offset, int64_t length)
38 : FileSource(fd, offset, length),
39 mDecryptHandle(NULL),
40 mDrmManagerClient(NULL),
41 mDrmBufOffset(0),
42 mDrmBufSize(0),
43 mDrmBuf(NULL) {
44 (void) DrmInitialization(nullptr);
45 }
46
~PlayerServiceFileSource()47 PlayerServiceFileSource::~PlayerServiceFileSource() {
48 if (mDrmBuf != NULL) {
49 delete[] mDrmBuf;
50 mDrmBuf = NULL;
51 }
52
53 if (mDecryptHandle != NULL) {
54 // To release mDecryptHandle
55 CHECK(mDrmManagerClient);
56 mDrmManagerClient->closeDecryptSession(mDecryptHandle);
57 mDecryptHandle = NULL;
58 }
59
60 if (mDrmManagerClient != NULL) {
61 delete mDrmManagerClient;
62 mDrmManagerClient = NULL;
63 }
64 }
65
readAt(off64_t offset,void * data,size_t size)66 ssize_t PlayerServiceFileSource::readAt(off64_t offset, void *data, size_t size) {
67 if (mFd < 0) {
68 return NO_INIT;
69 }
70
71 Mutex::Autolock autoLock(mLock);
72
73 if (mLength >= 0) {
74 if (offset < 0) {
75 return UNKNOWN_ERROR;
76 }
77 if (offset >= mLength) {
78 return 0; // read beyond EOF.
79 }
80 uint64_t numAvailable = mLength - offset;
81 if ((uint64_t)size > numAvailable) {
82 size = numAvailable;
83 }
84 }
85
86 if (mDecryptHandle != NULL && DecryptApiType::CONTAINER_BASED
87 == mDecryptHandle->decryptApiType) {
88 return readAtDRM_l(offset, data, size);
89 } else {
90 return readAt_l(offset, data, size);
91 }
92 }
93
DrmInitialization(const char * mime)94 sp<DecryptHandle> PlayerServiceFileSource::DrmInitialization(const char *mime) {
95 if (getuid() == AID_MEDIA_EX) {
96 return NULL; // no DRM in media extractor
97 }
98 if (mDrmManagerClient == NULL) {
99 mDrmManagerClient = new DrmManagerClient();
100 }
101
102 if (mDrmManagerClient == NULL) {
103 return NULL;
104 }
105
106 if (mDecryptHandle == NULL) {
107 mDecryptHandle = mDrmManagerClient->openDecryptSession(
108 mFd, mOffset, mLength, mime);
109 }
110
111 if (mDecryptHandle == NULL) {
112 delete mDrmManagerClient;
113 mDrmManagerClient = NULL;
114 }
115
116 return mDecryptHandle;
117 }
118
readAtDRM_l(off64_t offset,void * data,size_t size)119 ssize_t PlayerServiceFileSource::readAtDRM_l(off64_t offset, void *data, size_t size) {
120 size_t DRM_CACHE_SIZE = 1024;
121 if (mDrmBuf == NULL) {
122 mDrmBuf = new unsigned char[DRM_CACHE_SIZE];
123 }
124
125 if (mDrmBuf != NULL && mDrmBufSize > 0 && (offset + mOffset) >= mDrmBufOffset
126 && (offset + mOffset + size) <= static_cast<size_t>(mDrmBufOffset + mDrmBufSize)) {
127 /* Use buffered data */
128 memcpy(data, (void*)(mDrmBuf+(offset+mOffset-mDrmBufOffset)), size);
129 return size;
130 } else if (size <= DRM_CACHE_SIZE) {
131 /* Buffer new data */
132 mDrmBufOffset = offset + mOffset;
133 mDrmBufSize = mDrmManagerClient->pread(mDecryptHandle, mDrmBuf,
134 DRM_CACHE_SIZE, offset + mOffset);
135 if (mDrmBufSize > 0) {
136 int64_t dataRead = 0;
137 dataRead = size > static_cast<size_t>(mDrmBufSize) ? mDrmBufSize : size;
138 memcpy(data, (void*)mDrmBuf, dataRead);
139 return dataRead;
140 } else {
141 return mDrmBufSize;
142 }
143 } else {
144 /* Too big chunk to cache. Call DRM directly */
145 return mDrmManagerClient->pread(mDecryptHandle, data, size, offset + mOffset);
146 }
147 }
148
149 /* static */
requiresDrm(int fd,int64_t offset,int64_t length,const char * mime)150 bool PlayerServiceFileSource::requiresDrm(int fd, int64_t offset, int64_t length, const char *mime) {
151 std::unique_ptr<DrmManagerClient> drmClient(new DrmManagerClient());
152 sp<DecryptHandle> decryptHandle =
153 drmClient->openDecryptSession(fd, offset, length, mime);
154 bool requiresDrm = false;
155 if (decryptHandle != nullptr) {
156 requiresDrm = decryptHandle->decryptApiType == DecryptApiType::CONTAINER_BASED;
157 drmClient->closeDecryptSession(decryptHandle);
158 }
159 return requiresDrm;
160 }
161
162 } // namespace android
163