blob: dd4df99bc5a1bdd31c7554fde1c3aff47a8e448a [file] [log] [blame]
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001/*
2**
3** Copyright (C) 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>
Mathias Agopian75624082009-05-19 19:08:10 -070020#include <binder/Parcel.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080021#include <SkBitmap.h>
22#include <media/IMediaMetadataRetriever.h>
23
24namespace android {
25
26enum {
27 DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
28 SET_DATA_SOURCE_URL,
29 SET_DATA_SOURCE_FD,
30 SET_MODE,
31 GET_MODE,
32 CAPTURE_FRAME,
33 EXTARCT_ALBUM_ART,
34 EXTRACT_METADATA,
35};
36
37class BpMediaMetadataRetriever: public BpInterface<IMediaMetadataRetriever>
38{
39public:
40 BpMediaMetadataRetriever(const sp<IBinder>& impl)
41 : BpInterface<IMediaMetadataRetriever>(impl)
42 {
43 }
44
45 // disconnect from media metadata retriever service
46 void disconnect()
47 {
48 Parcel data, reply;
49 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
50 remote()->transact(DISCONNECT, data, &reply);
51 }
52
53 status_t setDataSource(const char* srcUrl)
54 {
55 Parcel data, reply;
56 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
57 data.writeCString(srcUrl);
58 remote()->transact(SET_DATA_SOURCE_URL, data, &reply);
59 return reply.readInt32();
60 }
61
62 status_t setDataSource(int fd, int64_t offset, int64_t length)
63 {
64 Parcel data, reply;
65 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
66 data.writeFileDescriptor(fd);
67 data.writeInt64(offset);
68 data.writeInt64(length);
69 remote()->transact(SET_DATA_SOURCE_FD, data, &reply);
70 return reply.readInt32();
71 }
72
73 status_t setMode(int mode)
74 {
75 Parcel data, reply;
76 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
77 data.writeInt32(mode);
78 remote()->transact(SET_MODE, data, &reply);
79 return reply.readInt32();
80 }
81
82 status_t getMode(int* mode) const
83 {
84 Parcel data, reply;
85 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
86 remote()->transact(GET_MODE, data, &reply);
87 *mode = reply.readInt32();
88 return reply.readInt32();
89 }
90
91 sp<IMemory> captureFrame()
92 {
93 Parcel data, reply;
94 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
95 remote()->transact(CAPTURE_FRAME, data, &reply);
96 status_t ret = reply.readInt32();
97 if (ret != NO_ERROR) {
98 return NULL;
99 }
100 return interface_cast<IMemory>(reply.readStrongBinder());
101 }
102
103 sp<IMemory> extractAlbumArt()
104 {
105 Parcel data, reply;
106 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
107 remote()->transact(EXTARCT_ALBUM_ART, data, &reply);
108 status_t ret = reply.readInt32();
109 if (ret != NO_ERROR) {
110 return NULL;
111 }
112 return interface_cast<IMemory>(reply.readStrongBinder());
113 }
114
115 const char* extractMetadata(int keyCode)
116 {
117 Parcel data, reply;
118 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
119 data.writeInt32(keyCode);
120 remote()->transact(EXTRACT_METADATA, data, &reply);
121 status_t ret = reply.readInt32();
122 if (ret != NO_ERROR) {
123 return NULL;
124 }
125 return reply.readCString();
126 }
127};
128
129IMPLEMENT_META_INTERFACE(MediaMetadataRetriever, "android.hardware.IMediaMetadataRetriever");
130
131// ----------------------------------------------------------------------
132
133#define CHECK_INTERFACE(interface, data, reply) \
134 do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
135 LOGW("Call incorrectly routed to " #interface); \
136 return PERMISSION_DENIED; \
137 } } while (0)
138
139status_t BnMediaMetadataRetriever::onTransact(
140 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
141{
142 switch (code) {
143 case DISCONNECT: {
144 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
145 disconnect();
146 return NO_ERROR;
147 } break;
148 case SET_DATA_SOURCE_URL: {
149 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
150 const char* srcUrl = data.readCString();
151 reply->writeInt32(setDataSource(srcUrl));
152 return NO_ERROR;
153 } break;
154 case SET_DATA_SOURCE_FD: {
155 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
156 int fd = dup(data.readFileDescriptor());
157 int64_t offset = data.readInt64();
158 int64_t length = data.readInt64();
159 reply->writeInt32(setDataSource(fd, offset, length));
160 return NO_ERROR;
161 } break;
162 case SET_MODE: {
163 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
164 int mode = data.readInt32();
165 reply->writeInt32(setMode(mode));
166 return NO_ERROR;
167 } break;
168 case GET_MODE: {
169 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
170 int mode;
171 status_t status = getMode(&mode);
172 reply->writeInt32(mode);
173 reply->writeInt32(status);
174 return NO_ERROR;
175 } break;
176 case CAPTURE_FRAME: {
177 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
178 sp<IMemory> bitmap = captureFrame();
179 if (bitmap != 0) { // Don't send NULL across the binder interface
180 reply->writeInt32(NO_ERROR);
181 reply->writeStrongBinder(bitmap->asBinder());
182 } else {
183 reply->writeInt32(UNKNOWN_ERROR);
184 }
185 return NO_ERROR;
186 } break;
187 case EXTARCT_ALBUM_ART: {
188 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
189 sp<IMemory> albumArt = extractAlbumArt();
190 if (albumArt != 0) { // Don't send NULL across the binder interface
191 reply->writeInt32(NO_ERROR);
192 reply->writeStrongBinder(albumArt->asBinder());
193 } else {
194 reply->writeInt32(UNKNOWN_ERROR);
195 }
196 return NO_ERROR;
197 } break;
198 case EXTRACT_METADATA: {
199 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
200 int keyCode = data.readInt32();
201 const char* value = extractMetadata(keyCode);
202 if (value != NULL) { // Don't send NULL across the binder interface
203 reply->writeInt32(NO_ERROR);
204 reply->writeCString(value);
205 } else {
206 reply->writeInt32(UNKNOWN_ERROR);
207 }
208 return NO_ERROR;
209 } break;
210 default:
211 return BBinder::onTransact(code, data, reply, flags);
212 }
213}
214
215// ----------------------------------------------------------------------------
216
217}; // namespace android
218