1/*
2**
3** Copyright 2008, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9**     http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#include <stdint.h>
19#include <sys/types.h>
20
21#include <binder/Parcel.h>
22#include <binder/IMemory.h>
23#include <media/ICrypto.h>
24#include <media/IDrm.h>
25#include <media/IHDCP.h>
26#include <media/IMediaCodecList.h>
27#include <media/IMediaHTTPService.h>
28#include <media/IMediaPlayerService.h>
29#include <media/IMediaRecorder.h>
30#include <media/IOMX.h>
31#include <media/IRemoteDisplay.h>
32#include <media/IRemoteDisplayClient.h>
33#include <media/IStreamSource.h>
34
35#include <utils/Errors.h>  // for status_t
36#include <utils/String8.h>
37
38namespace android {
39
40enum {
41    CREATE = IBinder::FIRST_CALL_TRANSACTION,
42    DECODE_URL,
43    DECODE_FD,
44    CREATE_MEDIA_RECORDER,
45    CREATE_METADATA_RETRIEVER,
46    GET_OMX,
47    MAKE_CRYPTO,
48    MAKE_DRM,
49    MAKE_HDCP,
50    ADD_BATTERY_DATA,
51    PULL_BATTERY_DATA,
52    LISTEN_FOR_REMOTE_DISPLAY,
53    GET_CODEC_LIST,
54};
55
56class BpMediaPlayerService: public BpInterface<IMediaPlayerService>
57{
58public:
59    BpMediaPlayerService(const sp<IBinder>& impl)
60        : BpInterface<IMediaPlayerService>(impl)
61    {
62    }
63
64    virtual sp<IMediaMetadataRetriever> createMetadataRetriever()
65    {
66        Parcel data, reply;
67        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
68        remote()->transact(CREATE_METADATA_RETRIEVER, data, &reply);
69        return interface_cast<IMediaMetadataRetriever>(reply.readStrongBinder());
70    }
71
72    virtual sp<IMediaPlayer> create(
73            const sp<IMediaPlayerClient>& client, int audioSessionId) {
74        Parcel data, reply;
75        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
76        data.writeStrongBinder(client->asBinder());
77        data.writeInt32(audioSessionId);
78
79        remote()->transact(CREATE, data, &reply);
80        return interface_cast<IMediaPlayer>(reply.readStrongBinder());
81    }
82
83    virtual sp<IMediaRecorder> createMediaRecorder()
84    {
85        Parcel data, reply;
86        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
87        remote()->transact(CREATE_MEDIA_RECORDER, data, &reply);
88        return interface_cast<IMediaRecorder>(reply.readStrongBinder());
89    }
90
91    virtual status_t decode(
92            const sp<IMediaHTTPService> &httpService,
93            const char* url,
94            uint32_t *pSampleRate,
95            int* pNumChannels,
96            audio_format_t* pFormat,
97            const sp<IMemoryHeap>& heap,
98            size_t *pSize)
99    {
100        Parcel data, reply;
101        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
102        data.writeInt32(httpService != NULL);
103        if (httpService != NULL) {
104            data.writeStrongBinder(httpService->asBinder());
105        }
106        data.writeCString(url);
107        data.writeStrongBinder(heap->asBinder());
108        status_t status = remote()->transact(DECODE_URL, data, &reply);
109        if (status == NO_ERROR) {
110            status = (status_t)reply.readInt32();
111            if (status == NO_ERROR) {
112                *pSampleRate = uint32_t(reply.readInt32());
113                *pNumChannels = reply.readInt32();
114                *pFormat = (audio_format_t)reply.readInt32();
115                *pSize = (size_t)reply.readInt32();
116            }
117        }
118        return status;
119    }
120
121    virtual status_t decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate,
122                               int* pNumChannels, audio_format_t* pFormat,
123                               const sp<IMemoryHeap>& heap, size_t *pSize)
124    {
125        Parcel data, reply;
126        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
127        data.writeFileDescriptor(fd);
128        data.writeInt64(offset);
129        data.writeInt64(length);
130        data.writeStrongBinder(heap->asBinder());
131        status_t status = remote()->transact(DECODE_FD, data, &reply);
132        if (status == NO_ERROR) {
133            status = (status_t)reply.readInt32();
134            if (status == NO_ERROR) {
135                *pSampleRate = uint32_t(reply.readInt32());
136                *pNumChannels = reply.readInt32();
137                *pFormat = (audio_format_t)reply.readInt32();
138                *pSize = (size_t)reply.readInt32();
139            }
140        }
141        return status;
142    }
143
144    virtual sp<IOMX> getOMX() {
145        Parcel data, reply;
146        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
147        remote()->transact(GET_OMX, data, &reply);
148        return interface_cast<IOMX>(reply.readStrongBinder());
149    }
150
151    virtual sp<ICrypto> makeCrypto() {
152        Parcel data, reply;
153        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
154        remote()->transact(MAKE_CRYPTO, data, &reply);
155        return interface_cast<ICrypto>(reply.readStrongBinder());
156    }
157
158    virtual sp<IDrm> makeDrm() {
159        Parcel data, reply;
160        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
161        remote()->transact(MAKE_DRM, data, &reply);
162        return interface_cast<IDrm>(reply.readStrongBinder());
163    }
164
165    virtual sp<IHDCP> makeHDCP(bool createEncryptionModule) {
166        Parcel data, reply;
167        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
168        data.writeInt32(createEncryptionModule);
169        remote()->transact(MAKE_HDCP, data, &reply);
170        return interface_cast<IHDCP>(reply.readStrongBinder());
171    }
172
173    virtual void addBatteryData(uint32_t params) {
174        Parcel data, reply;
175        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
176        data.writeInt32(params);
177        remote()->transact(ADD_BATTERY_DATA, data, &reply);
178    }
179
180    virtual status_t pullBatteryData(Parcel* reply) {
181        Parcel data;
182        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
183        return remote()->transact(PULL_BATTERY_DATA, data, reply);
184    }
185
186    virtual sp<IRemoteDisplay> listenForRemoteDisplay(const sp<IRemoteDisplayClient>& client,
187            const String8& iface)
188    {
189        Parcel data, reply;
190        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
191        data.writeStrongBinder(client->asBinder());
192        data.writeString8(iface);
193        remote()->transact(LISTEN_FOR_REMOTE_DISPLAY, data, &reply);
194        return interface_cast<IRemoteDisplay>(reply.readStrongBinder());
195    }
196
197    virtual sp<IMediaCodecList> getCodecList() const {
198        Parcel data, reply;
199        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
200        remote()->transact(GET_CODEC_LIST, data, &reply);
201        return interface_cast<IMediaCodecList>(reply.readStrongBinder());
202    }
203};
204
205IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.media.IMediaPlayerService");
206
207// ----------------------------------------------------------------------
208
209status_t BnMediaPlayerService::onTransact(
210    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
211{
212    switch (code) {
213        case CREATE: {
214            CHECK_INTERFACE(IMediaPlayerService, data, reply);
215            sp<IMediaPlayerClient> client =
216                interface_cast<IMediaPlayerClient>(data.readStrongBinder());
217            int audioSessionId = data.readInt32();
218            sp<IMediaPlayer> player = create(client, audioSessionId);
219            reply->writeStrongBinder(player->asBinder());
220            return NO_ERROR;
221        } break;
222        case DECODE_URL: {
223            CHECK_INTERFACE(IMediaPlayerService, data, reply);
224            sp<IMediaHTTPService> httpService;
225            if (data.readInt32()) {
226                httpService =
227                    interface_cast<IMediaHTTPService>(data.readStrongBinder());
228            }
229            const char* url = data.readCString();
230            sp<IMemoryHeap> heap = interface_cast<IMemoryHeap>(data.readStrongBinder());
231            uint32_t sampleRate;
232            int numChannels;
233            audio_format_t format;
234            size_t size;
235            status_t status =
236                decode(httpService,
237                       url,
238                       &sampleRate,
239                       &numChannels,
240                       &format,
241                       heap,
242                       &size);
243            reply->writeInt32(status);
244            if (status == NO_ERROR) {
245                reply->writeInt32(sampleRate);
246                reply->writeInt32(numChannels);
247                reply->writeInt32((int32_t)format);
248                reply->writeInt32((int32_t)size);
249            }
250            return NO_ERROR;
251        } break;
252        case DECODE_FD: {
253            CHECK_INTERFACE(IMediaPlayerService, data, reply);
254            int fd = dup(data.readFileDescriptor());
255            int64_t offset = data.readInt64();
256            int64_t length = data.readInt64();
257            sp<IMemoryHeap> heap = interface_cast<IMemoryHeap>(data.readStrongBinder());
258            uint32_t sampleRate;
259            int numChannels;
260            audio_format_t format;
261            size_t size;
262            status_t status = decode(fd, offset, length, &sampleRate, &numChannels, &format,
263                                     heap, &size);
264            reply->writeInt32(status);
265            if (status == NO_ERROR) {
266                reply->writeInt32(sampleRate);
267                reply->writeInt32(numChannels);
268                reply->writeInt32((int32_t)format);
269                reply->writeInt32((int32_t)size);
270            }
271            return NO_ERROR;
272        } break;
273        case CREATE_MEDIA_RECORDER: {
274            CHECK_INTERFACE(IMediaPlayerService, data, reply);
275            sp<IMediaRecorder> recorder = createMediaRecorder();
276            reply->writeStrongBinder(recorder->asBinder());
277            return NO_ERROR;
278        } break;
279        case CREATE_METADATA_RETRIEVER: {
280            CHECK_INTERFACE(IMediaPlayerService, data, reply);
281            sp<IMediaMetadataRetriever> retriever = createMetadataRetriever();
282            reply->writeStrongBinder(retriever->asBinder());
283            return NO_ERROR;
284        } break;
285        case GET_OMX: {
286            CHECK_INTERFACE(IMediaPlayerService, data, reply);
287            sp<IOMX> omx = getOMX();
288            reply->writeStrongBinder(omx->asBinder());
289            return NO_ERROR;
290        } break;
291        case MAKE_CRYPTO: {
292            CHECK_INTERFACE(IMediaPlayerService, data, reply);
293            sp<ICrypto> crypto = makeCrypto();
294            reply->writeStrongBinder(crypto->asBinder());
295            return NO_ERROR;
296        } break;
297        case MAKE_DRM: {
298            CHECK_INTERFACE(IMediaPlayerService, data, reply);
299            sp<IDrm> drm = makeDrm();
300            reply->writeStrongBinder(drm->asBinder());
301            return NO_ERROR;
302        } break;
303        case MAKE_HDCP: {
304            CHECK_INTERFACE(IMediaPlayerService, data, reply);
305            bool createEncryptionModule = data.readInt32();
306            sp<IHDCP> hdcp = makeHDCP(createEncryptionModule);
307            reply->writeStrongBinder(hdcp->asBinder());
308            return NO_ERROR;
309        } break;
310        case ADD_BATTERY_DATA: {
311            CHECK_INTERFACE(IMediaPlayerService, data, reply);
312            uint32_t params = data.readInt32();
313            addBatteryData(params);
314            return NO_ERROR;
315        } break;
316        case PULL_BATTERY_DATA: {
317            CHECK_INTERFACE(IMediaPlayerService, data, reply);
318            pullBatteryData(reply);
319            return NO_ERROR;
320        } break;
321        case LISTEN_FOR_REMOTE_DISPLAY: {
322            CHECK_INTERFACE(IMediaPlayerService, data, reply);
323            sp<IRemoteDisplayClient> client(
324                    interface_cast<IRemoteDisplayClient>(data.readStrongBinder()));
325            String8 iface(data.readString8());
326            sp<IRemoteDisplay> display(listenForRemoteDisplay(client, iface));
327            reply->writeStrongBinder(display->asBinder());
328            return NO_ERROR;
329        } break;
330        case GET_CODEC_LIST: {
331            CHECK_INTERFACE(IMediaPlayerService, data, reply);
332            sp<IMediaCodecList> mcl = getCodecList();
333            reply->writeStrongBinder(mcl->asBinder());
334            return NO_ERROR;
335        } break;
336        default:
337            return BBinder::onTransact(code, data, reply, flags);
338    }
339}
340
341// ----------------------------------------------------------------------------
342
343}; // namespace android
344