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     explicit BpDataSource(const sp<IBinder>& impl)
43         : BpInterface<IDataSource>(impl) {}
44 
getIMemoryandroid::BpDataSource45     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 
readAtandroid::BpDataSource53     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 
getSizeandroid::BpDataSource70     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 
closeandroid::BpDataSource79     virtual void close() {
80         Parcel data, reply;
81         data.writeInterfaceToken(IDataSource::getInterfaceDescriptor());
82         remote()->transact(CLOSE, data, &reply);
83     }
84 
getFlagsandroid::BpDataSource85     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 
toStringandroid::BpDataSource92     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 
DrmInitializationandroid::BpDataSource99     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 
141 IMPLEMENT_META_INTERFACE(DataSource, "android.media.IDataSource");
142 
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)143 status_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