Home | History | Annotate | Download | only in libstagefright
      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