FileSource.cpp revision d066bc8faf68b9fcb034ceb203e8d7e8213dc1ce
120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber/*
220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Copyright (C) 2009 The Android Open Source Project
320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * you may not use this file except in compliance with the License.
620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * You may obtain a copy of the License at
720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber *
1020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * Unless required by applicable law or agreed to in writing, software
1120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * See the License for the specific language governing permissions and
1420111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber * limitations under the License.
1520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber */
1620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
174f82a25c07c3ffc8d44d61797043f9864058afdfMarco Nelissen//#define LOG_NDEBUG 0
184f82a25c07c3ffc8d44d61797043f9864058afdfMarco Nelissen#define LOG_TAG "FileSource"
194f82a25c07c3ffc8d44d61797043f9864058afdfMarco Nelissen#include <utils/Log.h>
204f82a25c07c3ffc8d44d61797043f9864058afdfMarco Nelissen
21f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#include <media/stagefright/foundation/ADebug.h>
2220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber#include <media/stagefright/FileSource.h>
23c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong#include <sys/types.h>
24c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong#include <unistd.h>
25674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong#include <sys/types.h>
26674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong#include <sys/stat.h>
27674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong#include <fcntl.h>
2820111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
2920111aa043c5f404472bc63b90bc5aad906b1101Andreas Hubernamespace android {
3020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
3120111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberFileSource::FileSource(const char *filename)
32674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    : mFd(-1),
3303475f5af25e4aa32d46d41dd2ec756853d8dd9dAndreas Huber      mOffset(0),
34dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mLength(-1),
35dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mDecryptHandle(NULL),
36dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mDrmManagerClient(NULL),
37dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mDrmBufOffset(0),
38dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mDrmBufSize(0),
39dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mDrmBuf(NULL){
40674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong
41674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    mFd = open(filename, O_LARGEFILE | O_RDONLY);
424ee31e2603b4019e4ae76e027115f80b818527aaAndreas Huber
434ee31e2603b4019e4ae76e027115f80b818527aaAndreas Huber    if (mFd >= 0) {
444ee31e2603b4019e4ae76e027115f80b818527aaAndreas Huber        mLength = lseek64(mFd, 0, SEEK_END);
45f4b7d94062c896dca565d849c6188cd3489be257Andreas Huber    } else {
46f4b7d94062c896dca565d849c6188cd3489be257Andreas Huber        ALOGE("Failed to open file '%s'. (%s)", filename, strerror(errno));
474ee31e2603b4019e4ae76e027115f80b818527aaAndreas Huber    }
4803475f5af25e4aa32d46d41dd2ec756853d8dd9dAndreas Huber}
4903475f5af25e4aa32d46d41dd2ec756853d8dd9dAndreas Huber
5003475f5af25e4aa32d46d41dd2ec756853d8dd9dAndreas HuberFileSource::FileSource(int fd, int64_t offset, int64_t length)
51674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    : mFd(fd),
5203475f5af25e4aa32d46d41dd2ec756853d8dd9dAndreas Huber      mOffset(offset),
53dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mLength(length),
54dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mDecryptHandle(NULL),
55dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mDrmManagerClient(NULL),
56dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mDrmBufOffset(0),
57dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mDrmBufSize(0),
58dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang      mDrmBuf(NULL){
5903475f5af25e4aa32d46d41dd2ec756853d8dd9dAndreas Huber    CHECK(offset >= 0);
6003475f5af25e4aa32d46d41dd2ec756853d8dd9dAndreas Huber    CHECK(length >= 0);
6120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
6220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
6320111aa043c5f404472bc63b90bc5aad906b1101Andreas HuberFileSource::~FileSource() {
64674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mFd >= 0) {
65674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        close(mFd);
66674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong        mFd = -1;
6720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    }
68dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
69dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mDrmBuf != NULL) {
70dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        delete[] mDrmBuf;
71dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        mDrmBuf = NULL;
72dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
73889b340ec736a9d3e3e690256d305cc8740f0c4bGloria Wang
74889b340ec736a9d3e3e690256d305cc8740f0c4bGloria Wang    if (mDecryptHandle != NULL) {
75889b340ec736a9d3e3e690256d305cc8740f0c4bGloria Wang        // To release mDecryptHandle
768f64134f749e4f7861a08a3063450fc714c4651dGloria Wang        CHECK(mDrmManagerClient);
77889b340ec736a9d3e3e690256d305cc8740f0c4bGloria Wang        mDrmManagerClient->closeDecryptSession(mDecryptHandle);
78889b340ec736a9d3e3e690256d305cc8740f0c4bGloria Wang        mDecryptHandle = NULL;
79889b340ec736a9d3e3e690256d305cc8740f0c4bGloria Wang    }
80889b340ec736a9d3e3e690256d305cc8740f0c4bGloria Wang
81889b340ec736a9d3e3e690256d305cc8740f0c4bGloria Wang    if (mDrmManagerClient != NULL) {
82889b340ec736a9d3e3e690256d305cc8740f0c4bGloria Wang        delete mDrmManagerClient;
83889b340ec736a9d3e3e690256d305cc8740f0c4bGloria Wang        mDrmManagerClient = NULL;
84889b340ec736a9d3e3e690256d305cc8740f0c4bGloria Wang    }
8520111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
8620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
8734769bc913e9f6bb138e666d94a9d685bf3da217Andreas Huberstatus_t FileSource::initCheck() const {
88674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    return mFd >= 0 ? OK : NO_INIT;
8920111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
9020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
91c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongssize_t FileSource::readAt(off64_t offset, void *data, size_t size) {
92674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mFd < 0) {
933d8055ac96170de7a8c49b9ffbe83ed447ccddceAndreas Huber        return NO_INIT;
943d8055ac96170de7a8c49b9ffbe83ed447ccddceAndreas Huber    }
953d8055ac96170de7a8c49b9ffbe83ed447ccddceAndreas Huber
9620111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber    Mutex::Autolock autoLock(mLock);
9720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
9803475f5af25e4aa32d46d41dd2ec756853d8dd9dAndreas Huber    if (mLength >= 0) {
9903475f5af25e4aa32d46d41dd2ec756853d8dd9dAndreas Huber        if (offset >= mLength) {
10003475f5af25e4aa32d46d41dd2ec756853d8dd9dAndreas Huber            return 0;  // read beyond EOF.
10103475f5af25e4aa32d46d41dd2ec756853d8dd9dAndreas Huber        }
10203475f5af25e4aa32d46d41dd2ec756853d8dd9dAndreas Huber        int64_t numAvailable = mLength - offset;
10303475f5af25e4aa32d46d41dd2ec756853d8dd9dAndreas Huber        if ((int64_t)size > numAvailable) {
10403475f5af25e4aa32d46d41dd2ec756853d8dd9dAndreas Huber            size = numAvailable;
10503475f5af25e4aa32d46d41dd2ec756853d8dd9dAndreas Huber        }
10603475f5af25e4aa32d46d41dd2ec756853d8dd9dAndreas Huber    }
10703475f5af25e4aa32d46d41dd2ec756853d8dd9dAndreas Huber
108dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mDecryptHandle != NULL && DecryptApiType::CONTAINER_BASED
109dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            == mDecryptHandle->decryptApiType) {
110dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return readAtDRM(offset, data, size);
111dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang   } else {
112c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        off64_t result = lseek64(mFd, offset + mOffset, SEEK_SET);
113c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        if (result == -1) {
114ee4e1b1a63758941460ae79a064249d3a5189443Lajos Molnar            ALOGE("seek to %lld failed", (long long)(offset + mOffset));
115dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return UNKNOWN_ERROR;
116dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
11720111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
118c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        return ::read(mFd, data, size);
119dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
12003475f5af25e4aa32d46d41dd2ec756853d8dd9dAndreas Huber}
12103475f5af25e4aa32d46d41dd2ec756853d8dd9dAndreas Huber
122c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongstatus_t FileSource::getSize(off64_t *size) {
1233a13fad63af40a8364fce796b1a54a8f0a2fbf32Andreas Huber    Mutex::Autolock autoLock(mLock);
1243a13fad63af40a8364fce796b1a54a8f0a2fbf32Andreas Huber
125674ebd0b4e1143e38392a4e3bb38b4679a4577bcJames Dong    if (mFd < 0) {
1263d8055ac96170de7a8c49b9ffbe83ed447ccddceAndreas Huber        return NO_INIT;
1273d8055ac96170de7a8c49b9ffbe83ed447ccddceAndreas Huber    }
1283d8055ac96170de7a8c49b9ffbe83ed447ccddceAndreas Huber
1294ee31e2603b4019e4ae76e027115f80b818527aaAndreas Huber    *size = mLength;
13020111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
13103475f5af25e4aa32d46d41dd2ec756853d8dd9dAndreas Huber    return OK;
13220111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}
13320111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber
1349d2f386dd2885eaffa11fd494ae258bb09fe6397James Dongsp<DecryptHandle> FileSource::DrmInitialization(const char *mime) {
135889b340ec736a9d3e3e690256d305cc8740f0c4bGloria Wang    if (mDrmManagerClient == NULL) {
136889b340ec736a9d3e3e690256d305cc8740f0c4bGloria Wang        mDrmManagerClient = new DrmManagerClient();
137889b340ec736a9d3e3e690256d305cc8740f0c4bGloria Wang    }
138889b340ec736a9d3e3e690256d305cc8740f0c4bGloria Wang
139889b340ec736a9d3e3e690256d305cc8740f0c4bGloria Wang    if (mDrmManagerClient == NULL) {
140b371426ce4cf2fa6d8c3d1903b61322feb165d35Gloria Wang        return NULL;
141b371426ce4cf2fa6d8c3d1903b61322feb165d35Gloria Wang    }
142b371426ce4cf2fa6d8c3d1903b61322feb165d35Gloria Wang
143dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mDecryptHandle == NULL) {
144dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        mDecryptHandle = mDrmManagerClient->openDecryptSession(
1459d2f386dd2885eaffa11fd494ae258bb09fe6397James Dong                mFd, mOffset, mLength, mime);
146dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
147dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
148dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mDecryptHandle == NULL) {
149889b340ec736a9d3e3e690256d305cc8740f0c4bGloria Wang        delete mDrmManagerClient;
150dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        mDrmManagerClient = NULL;
151dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
152dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
153dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    return mDecryptHandle;
154dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
155dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
156b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wangvoid FileSource::getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client) {
157b5ce361d19e69fe156f7188c9ee0f4734b259874Gloria Wang    handle = mDecryptHandle;
158dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
159dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    *client = mDrmManagerClient;
160dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
161dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
162c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongssize_t FileSource::readAtDRM(off64_t offset, void *data, size_t size) {
163dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    size_t DRM_CACHE_SIZE = 1024;
164dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mDrmBuf == NULL) {
165dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        mDrmBuf = new unsigned char[DRM_CACHE_SIZE];
166dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
167dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang
168dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    if (mDrmBuf != NULL && mDrmBufSize > 0 && (offset + mOffset) >= mDrmBufOffset
169d066bc8faf68b9fcb034ceb203e8d7e8213dc1cePatrik Lindgren            && (offset + mOffset + size) <= static_cast<size_t>(mDrmBufOffset + mDrmBufSize)) {
170dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        /* Use buffered data */
171dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        memcpy(data, (void*)(mDrmBuf+(offset+mOffset-mDrmBufOffset)), size);
172dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return size;
173dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    } else if (size <= DRM_CACHE_SIZE) {
174dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        /* Buffer new data */
175dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        mDrmBufOffset =  offset + mOffset;
176dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        mDrmBufSize = mDrmManagerClient->pread(mDecryptHandle, mDrmBuf,
177dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang                DRM_CACHE_SIZE, offset + mOffset);
178dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        if (mDrmBufSize > 0) {
179dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            int64_t dataRead = 0;
180d066bc8faf68b9fcb034ceb203e8d7e8213dc1cePatrik Lindgren            dataRead = size > static_cast<size_t>(mDrmBufSize) ? mDrmBufSize : size;
181dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            memcpy(data, (void*)mDrmBuf, dataRead);
182dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return dataRead;
183dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        } else {
184dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang            return mDrmBufSize;
185dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        }
186dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    } else {
187dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        /* Too big chunk to cache. Call DRM directly */
188dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang        return mDrmManagerClient->pread(mDecryptHandle, data, size, offset + mOffset);
189dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang    }
190dcd25efb46c41c8d24a0a9cf61fb57f84149709eGloria Wang}
19120111aa043c5f404472bc63b90bc5aad906b1101Andreas Huber}  // namespace android
192