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