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 
29 namespace android {
30 
31 enum {
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 
41 struct BpDataSource : public BpInterface<IDataSource> {
BpDataSourceandroid::BpDataSource42     BpDataSource(const sp<IBinder>& impl) : BpInterface<IDataSource>(impl) {}
43 
getIMemoryandroid::BpDataSource44     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 
readAtandroid::BpDataSource52     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 
getSizeandroid::BpDataSource61     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 
closeandroid::BpDataSource70     virtual void close() {
71         Parcel data, reply;
72         data.writeInterfaceToken(IDataSource::getInterfaceDescriptor());
73         remote()->transact(CLOSE, data, &reply);
74     }
75 
getFlagsandroid::BpDataSource76     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 
toStringandroid::BpDataSource83     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 
DrmInitializationandroid::BpDataSource90     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 
132 IMPLEMENT_META_INTERFACE(DataSource, "android.media.IDataSource");
133 
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)134 status_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