1/*
2 * Copyright 2015 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 "IDataSource"
19#include <utils/Log.h>
20#include <utils/Timers.h>
21
22#include <media/IDataSource.h>
23
24#include <binder/IMemory.h>
25#include <binder/Parcel.h>
26#include <drm/drm_framework_common.h>
27#include <media/stagefright/foundation/ADebug.h>
28
29namespace android {
30
31enum {
32    GET_IMEMORY = IBinder::FIRST_CALL_TRANSACTION,
33    READ_AT,
34    GET_SIZE,
35    CLOSE,
36    GET_FLAGS,
37    TO_STRING,
38    DRM_INITIALIZATION,
39};
40
41struct BpDataSource : public BpInterface<IDataSource> {
42    BpDataSource(const sp<IBinder>& impl) : BpInterface<IDataSource>(impl) {}
43
44    virtual sp<IMemory> getIMemory() {
45        Parcel data, reply;
46        data.writeInterfaceToken(IDataSource::getInterfaceDescriptor());
47        remote()->transact(GET_IMEMORY, data, &reply);
48        sp<IBinder> binder = reply.readStrongBinder();
49        return interface_cast<IMemory>(binder);
50    }
51
52    virtual ssize_t readAt(off64_t offset, size_t size) {
53        Parcel data, reply;
54        data.writeInterfaceToken(IDataSource::getInterfaceDescriptor());
55        data.writeInt64(offset);
56        data.writeInt64(size);
57        remote()->transact(READ_AT, data, &reply);
58        return reply.readInt64();
59    }
60
61    virtual status_t getSize(off64_t* size) {
62        Parcel data, reply;
63        data.writeInterfaceToken(IDataSource::getInterfaceDescriptor());
64        remote()->transact(GET_SIZE, data, &reply);
65        status_t err = reply.readInt32();
66        *size = reply.readInt64();
67        return err;
68    }
69
70    virtual void close() {
71        Parcel data, reply;
72        data.writeInterfaceToken(IDataSource::getInterfaceDescriptor());
73        remote()->transact(CLOSE, data, &reply);
74    }
75
76    virtual uint32_t getFlags() {
77        Parcel data, reply;
78        data.writeInterfaceToken(IDataSource::getInterfaceDescriptor());
79        remote()->transact(GET_FLAGS, data, &reply);
80        return reply.readUint32();
81    }
82
83    virtual String8 toString() {
84        Parcel data, reply;
85        data.writeInterfaceToken(IDataSource::getInterfaceDescriptor());
86        remote()->transact(TO_STRING, data, &reply);
87        return reply.readString8();
88    }
89
90    virtual sp<DecryptHandle> DrmInitialization(const char *mime) {
91        Parcel data, reply;
92        data.writeInterfaceToken(IDataSource::getInterfaceDescriptor());
93        if (mime == NULL) {
94            data.writeInt32(0);
95        } else {
96            data.writeInt32(1);
97            data.writeCString(mime);
98        }
99        remote()->transact(DRM_INITIALIZATION, data, &reply);
100        sp<DecryptHandle> handle;
101        if (reply.dataAvail() != 0) {
102            handle = new DecryptHandle();
103            handle->decryptId = reply.readInt32();
104            handle->mimeType = reply.readString8();
105            handle->decryptApiType = reply.readInt32();
106            handle->status = reply.readInt32();
107
108            const int bufferLength = data.readInt32();
109            if (bufferLength != -1) {
110                handle->decryptInfo = new DecryptInfo();
111                handle->decryptInfo->decryptBufferLength = bufferLength;
112            }
113
114            size_t size = data.readInt32();
115            for (size_t i = 0; i < size; ++i) {
116                DrmCopyControl key = (DrmCopyControl)data.readInt32();
117                int value = data.readInt32();
118                handle->copyControlVector.add(key, value);
119            }
120
121            size = data.readInt32();
122            for (size_t i = 0; i < size; ++i) {
123                String8 key = data.readString8();
124                String8 value = data.readString8();
125                handle->extendedData.add(key, value);
126            }
127        }
128        return handle;
129    }
130};
131
132IMPLEMENT_META_INTERFACE(DataSource, "android.media.IDataSource");
133
134status_t BnDataSource::onTransact(
135    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
136    switch (code) {
137        case GET_IMEMORY: {
138            CHECK_INTERFACE(IDataSource, data, reply);
139            reply->writeStrongBinder(IInterface::asBinder(getIMemory()));
140            return NO_ERROR;
141        } break;
142        case READ_AT: {
143            CHECK_INTERFACE(IDataSource, data, reply);
144            off64_t offset = (off64_t) data.readInt64();
145            size_t size = (size_t) data.readInt64();
146            reply->writeInt64(readAt(offset, size));
147            return NO_ERROR;
148        } break;
149        case GET_SIZE: {
150            CHECK_INTERFACE(IDataSource, data, reply);
151            off64_t size;
152            status_t err = getSize(&size);
153            reply->writeInt32(err);
154            reply->writeInt64(size);
155            return NO_ERROR;
156        } break;
157        case CLOSE: {
158            CHECK_INTERFACE(IDataSource, data, reply);
159            close();
160            return NO_ERROR;
161        } break;
162        case GET_FLAGS: {
163            CHECK_INTERFACE(IDataSource, data, reply);
164            reply->writeUint32(getFlags());
165            return NO_ERROR;
166        } break;
167        case TO_STRING: {
168            CHECK_INTERFACE(IDataSource, data, reply);
169            reply->writeString8(toString());
170            return NO_ERROR;
171        } break;
172        case DRM_INITIALIZATION: {
173            CHECK_INTERFACE(IDataSource, data, reply);
174            const char *mime = NULL;
175            const int32_t flag = data.readInt32();
176            if (flag != 0) {
177                mime = data.readCString();
178            }
179            sp<DecryptHandle> handle = DrmInitialization(mime);
180            if (handle != NULL) {
181                reply->writeInt32(handle->decryptId);
182                reply->writeString8(handle->mimeType);
183                reply->writeInt32(handle->decryptApiType);
184                reply->writeInt32(handle->status);
185
186                if (handle->decryptInfo != NULL) {
187                    reply->writeInt32(handle->decryptInfo->decryptBufferLength);
188                } else {
189                    reply->writeInt32(-1);
190                }
191
192                size_t size = handle->copyControlVector.size();
193                reply->writeInt32(size);
194                for (size_t i = 0; i < size; ++i) {
195                    reply->writeInt32(handle->copyControlVector.keyAt(i));
196                    reply->writeInt32(handle->copyControlVector.valueAt(i));
197                }
198
199                size = handle->extendedData.size();
200                reply->writeInt32(size);
201                for (size_t i = 0; i < size; ++i) {
202                    reply->writeString8(handle->extendedData.keyAt(i));
203                    reply->writeString8(handle->extendedData.valueAt(i));
204                }
205            }
206            return NO_ERROR;
207        } break;
208
209        default:
210            return BBinder::onTransact(code, data, reply, flags);
211    }
212}
213
214}  // namespace android
215