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