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/IMediaPlayerService.h>
27#include <media/IMediaRecorder.h>
28#include <media/IOMX.h>
29#include <media/IRemoteDisplay.h>
30#include <media/IRemoteDisplayClient.h>
31#include <media/IStreamSource.h>
32
33#include <utils/Errors.h>  // for status_t
34#include <utils/String8.h>
35
36namespace android {
37
38enum {
39    CREATE = IBinder::FIRST_CALL_TRANSACTION,
40    DECODE_URL,
41    DECODE_FD,
42    CREATE_MEDIA_RECORDER,
43    CREATE_METADATA_RETRIEVER,
44    GET_OMX,
45    MAKE_CRYPTO,
46    MAKE_DRM,
47    MAKE_HDCP,
48    ADD_BATTERY_DATA,
49    PULL_BATTERY_DATA,
50    LISTEN_FOR_REMOTE_DISPLAY,
51    UPDATE_PROXY_CONFIG,
52};
53
54class BpMediaPlayerService: public BpInterface<IMediaPlayerService>
55{
56public:
57    BpMediaPlayerService(const sp<IBinder>& impl)
58        : BpInterface<IMediaPlayerService>(impl)
59    {
60    }
61
62    virtual sp<IMediaMetadataRetriever> createMetadataRetriever()
63    {
64        Parcel data, reply;
65        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
66        remote()->transact(CREATE_METADATA_RETRIEVER, data, &reply);
67        return interface_cast<IMediaMetadataRetriever>(reply.readStrongBinder());
68    }
69
70    virtual sp<IMediaPlayer> create(
71            const sp<IMediaPlayerClient>& client, int audioSessionId) {
72        Parcel data, reply;
73        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
74        data.writeStrongBinder(client->asBinder());
75        data.writeInt32(audioSessionId);
76
77        remote()->transact(CREATE, data, &reply);
78        return interface_cast<IMediaPlayer>(reply.readStrongBinder());
79    }
80
81    virtual sp<IMediaRecorder> createMediaRecorder()
82    {
83        Parcel data, reply;
84        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
85        remote()->transact(CREATE_MEDIA_RECORDER, data, &reply);
86        return interface_cast<IMediaRecorder>(reply.readStrongBinder());
87    }
88
89    virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat)
90    {
91        Parcel data, reply;
92        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
93        data.writeCString(url);
94        remote()->transact(DECODE_URL, data, &reply);
95        *pSampleRate = uint32_t(reply.readInt32());
96        *pNumChannels = reply.readInt32();
97        *pFormat = (audio_format_t) reply.readInt32();
98        return interface_cast<IMemory>(reply.readStrongBinder());
99    }
100
101    virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat)
102    {
103        Parcel data, reply;
104        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
105        data.writeFileDescriptor(fd);
106        data.writeInt64(offset);
107        data.writeInt64(length);
108        remote()->transact(DECODE_FD, data, &reply);
109        *pSampleRate = uint32_t(reply.readInt32());
110        *pNumChannels = reply.readInt32();
111        *pFormat = (audio_format_t) reply.readInt32();
112        return interface_cast<IMemory>(reply.readStrongBinder());
113    }
114
115    virtual sp<IOMX> getOMX() {
116        Parcel data, reply;
117        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
118        remote()->transact(GET_OMX, data, &reply);
119        return interface_cast<IOMX>(reply.readStrongBinder());
120    }
121
122    virtual sp<ICrypto> makeCrypto() {
123        Parcel data, reply;
124        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
125        remote()->transact(MAKE_CRYPTO, data, &reply);
126        return interface_cast<ICrypto>(reply.readStrongBinder());
127    }
128
129    virtual sp<IDrm> makeDrm() {
130        Parcel data, reply;
131        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
132        remote()->transact(MAKE_DRM, data, &reply);
133        return interface_cast<IDrm>(reply.readStrongBinder());
134    }
135
136    virtual sp<IHDCP> makeHDCP(bool createEncryptionModule) {
137        Parcel data, reply;
138        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
139        data.writeInt32(createEncryptionModule);
140        remote()->transact(MAKE_HDCP, data, &reply);
141        return interface_cast<IHDCP>(reply.readStrongBinder());
142    }
143
144    virtual void addBatteryData(uint32_t params) {
145        Parcel data, reply;
146        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
147        data.writeInt32(params);
148        remote()->transact(ADD_BATTERY_DATA, data, &reply);
149    }
150
151    virtual status_t pullBatteryData(Parcel* reply) {
152        Parcel data;
153        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
154        return remote()->transact(PULL_BATTERY_DATA, data, reply);
155    }
156
157    virtual sp<IRemoteDisplay> listenForRemoteDisplay(const sp<IRemoteDisplayClient>& client,
158            const String8& iface)
159    {
160        Parcel data, reply;
161        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
162        data.writeStrongBinder(client->asBinder());
163        data.writeString8(iface);
164        remote()->transact(LISTEN_FOR_REMOTE_DISPLAY, data, &reply);
165        return interface_cast<IRemoteDisplay>(reply.readStrongBinder());
166    }
167
168    virtual status_t updateProxyConfig(
169            const char *host, int32_t port, const char *exclusionList) {
170        Parcel data, reply;
171
172        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
173        if (host == NULL) {
174            data.writeInt32(0);
175        } else {
176            data.writeInt32(1);
177            data.writeCString(host);
178            data.writeInt32(port);
179            data.writeCString(exclusionList);
180        }
181
182        remote()->transact(UPDATE_PROXY_CONFIG, data, &reply);
183
184        return reply.readInt32();
185    }
186};
187
188IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.media.IMediaPlayerService");
189
190// ----------------------------------------------------------------------
191
192status_t BnMediaPlayerService::onTransact(
193    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
194{
195    switch (code) {
196        case CREATE: {
197            CHECK_INTERFACE(IMediaPlayerService, data, reply);
198            sp<IMediaPlayerClient> client =
199                interface_cast<IMediaPlayerClient>(data.readStrongBinder());
200            int audioSessionId = data.readInt32();
201            sp<IMediaPlayer> player = create(client, audioSessionId);
202            reply->writeStrongBinder(player->asBinder());
203            return NO_ERROR;
204        } break;
205        case DECODE_URL: {
206            CHECK_INTERFACE(IMediaPlayerService, data, reply);
207            const char* url = data.readCString();
208            uint32_t sampleRate;
209            int numChannels;
210            audio_format_t format;
211            sp<IMemory> player = decode(url, &sampleRate, &numChannels, &format);
212            reply->writeInt32(sampleRate);
213            reply->writeInt32(numChannels);
214            reply->writeInt32((int32_t) format);
215            reply->writeStrongBinder(player->asBinder());
216            return NO_ERROR;
217        } break;
218        case DECODE_FD: {
219            CHECK_INTERFACE(IMediaPlayerService, data, reply);
220            int fd = dup(data.readFileDescriptor());
221            int64_t offset = data.readInt64();
222            int64_t length = data.readInt64();
223            uint32_t sampleRate;
224            int numChannels;
225            audio_format_t format;
226            sp<IMemory> player = decode(fd, offset, length, &sampleRate, &numChannels, &format);
227            reply->writeInt32(sampleRate);
228            reply->writeInt32(numChannels);
229            reply->writeInt32((int32_t) format);
230            reply->writeStrongBinder(player->asBinder());
231            return NO_ERROR;
232        } break;
233        case CREATE_MEDIA_RECORDER: {
234            CHECK_INTERFACE(IMediaPlayerService, data, reply);
235            sp<IMediaRecorder> recorder = createMediaRecorder();
236            reply->writeStrongBinder(recorder->asBinder());
237            return NO_ERROR;
238        } break;
239        case CREATE_METADATA_RETRIEVER: {
240            CHECK_INTERFACE(IMediaPlayerService, data, reply);
241            sp<IMediaMetadataRetriever> retriever = createMetadataRetriever();
242            reply->writeStrongBinder(retriever->asBinder());
243            return NO_ERROR;
244        } break;
245        case GET_OMX: {
246            CHECK_INTERFACE(IMediaPlayerService, data, reply);
247            sp<IOMX> omx = getOMX();
248            reply->writeStrongBinder(omx->asBinder());
249            return NO_ERROR;
250        } break;
251        case MAKE_CRYPTO: {
252            CHECK_INTERFACE(IMediaPlayerService, data, reply);
253            sp<ICrypto> crypto = makeCrypto();
254            reply->writeStrongBinder(crypto->asBinder());
255            return NO_ERROR;
256        } break;
257        case MAKE_DRM: {
258            CHECK_INTERFACE(IMediaPlayerService, data, reply);
259            sp<IDrm> drm = makeDrm();
260            reply->writeStrongBinder(drm->asBinder());
261            return NO_ERROR;
262        } break;
263        case MAKE_HDCP: {
264            CHECK_INTERFACE(IMediaPlayerService, data, reply);
265            bool createEncryptionModule = data.readInt32();
266            sp<IHDCP> hdcp = makeHDCP(createEncryptionModule);
267            reply->writeStrongBinder(hdcp->asBinder());
268            return NO_ERROR;
269        } break;
270        case ADD_BATTERY_DATA: {
271            CHECK_INTERFACE(IMediaPlayerService, data, reply);
272            uint32_t params = data.readInt32();
273            addBatteryData(params);
274            return NO_ERROR;
275        } break;
276        case PULL_BATTERY_DATA: {
277            CHECK_INTERFACE(IMediaPlayerService, data, reply);
278            pullBatteryData(reply);
279            return NO_ERROR;
280        } break;
281        case LISTEN_FOR_REMOTE_DISPLAY: {
282            CHECK_INTERFACE(IMediaPlayerService, data, reply);
283            sp<IRemoteDisplayClient> client(
284                    interface_cast<IRemoteDisplayClient>(data.readStrongBinder()));
285            String8 iface(data.readString8());
286            sp<IRemoteDisplay> display(listenForRemoteDisplay(client, iface));
287            reply->writeStrongBinder(display->asBinder());
288            return NO_ERROR;
289        } break;
290        case UPDATE_PROXY_CONFIG:
291        {
292            CHECK_INTERFACE(IMediaPlayerService, data, reply);
293
294            const char *host = NULL;
295            int32_t port = 0;
296            const char *exclusionList = NULL;
297
298            if (data.readInt32()) {
299                host = data.readCString();
300                port = data.readInt32();
301                exclusionList = data.readCString();
302            }
303
304            reply->writeInt32(updateProxyConfig(host, port, exclusionList));
305
306            return OK;
307        }
308        default:
309            return BBinder::onTransact(code, data, reply, flags);
310    }
311}
312
313// ----------------------------------------------------------------------------
314
315}; // namespace android
316