blob: e529d251ec86f18aa40eea0a337cde6a0eb36333 [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
Dave Sparksec4dde72009-11-23 16:51:15 -080024// The binder is supposed to propagate the scheduler group across
25// the binder interface so that remote calls are executed with
26// the same priority as local calls. This is currently not working
27// so this change puts in a temporary hack to fix the issue with
28// metadata retrieval which can be a huge CPU hit if done on a
29// foreground thread.
30#ifndef DISABLE_GROUP_SCHEDULE_HACK
31
32/* desktop Linux needs a little help with gettid() */
33#if defined(HAVE_GETTID) && !defined(HAVE_ANDROID_OS)
34#define __KERNEL__
35# include <linux/unistd.h>
36#ifdef _syscall0
37_syscall0(pid_t,gettid)
38#else
39pid_t gettid() { return syscall(__NR_gettid);}
40#endif
41#undef __KERNEL__
42#endif
43
Dave Sparksf311c552009-11-23 19:51:33 -080044static int myTid() {
45#ifdef HAVE_GETTID
46 return gettid();
47#else
48 return getpid();
49#endif
50}
51
52#undef LOG_TAG
Dave Sparksec4dde72009-11-23 16:51:15 -080053#define LOG_TAG "IMediaMetadataRetriever"
54#include <utils/Log.h>
55#include <cutils/sched_policy.h>
56
57namespace android {
58
59static void sendSchedPolicy(Parcel& data)
60{
61 SchedPolicy policy;
Dave Sparksf311c552009-11-23 19:51:33 -080062 get_sched_policy(myTid(), &policy);
Dave Sparksec4dde72009-11-23 16:51:15 -080063 data.writeInt32(policy);
64}
65
66static void setSchedPolicy(const Parcel& data)
67{
68 SchedPolicy policy = (SchedPolicy) data.readInt32();
Dave Sparksf311c552009-11-23 19:51:33 -080069 set_sched_policy(myTid(), policy);
Dave Sparksec4dde72009-11-23 16:51:15 -080070}
71static void restoreSchedPolicy()
72{
Dave Sparksf311c552009-11-23 19:51:33 -080073 set_sched_policy(myTid(), SP_FOREGROUND);
Dave Sparksec4dde72009-11-23 16:51:15 -080074}
75}; // end namespace android
76#endif
77
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080078namespace android {
79
80enum {
81 DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
82 SET_DATA_SOURCE_URL,
83 SET_DATA_SOURCE_FD,
84 SET_MODE,
85 GET_MODE,
86 CAPTURE_FRAME,
Dave Sparksec4dde72009-11-23 16:51:15 -080087 EXTRACT_ALBUM_ART,
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080088 EXTRACT_METADATA,
89};
90
91class BpMediaMetadataRetriever: public BpInterface<IMediaMetadataRetriever>
92{
93public:
94 BpMediaMetadataRetriever(const sp<IBinder>& impl)
95 : BpInterface<IMediaMetadataRetriever>(impl)
96 {
97 }
98
99 // disconnect from media metadata retriever service
100 void disconnect()
101 {
102 Parcel data, reply;
103 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
104 remote()->transact(DISCONNECT, data, &reply);
105 }
106
107 status_t setDataSource(const char* srcUrl)
108 {
109 Parcel data, reply;
110 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
111 data.writeCString(srcUrl);
112 remote()->transact(SET_DATA_SOURCE_URL, data, &reply);
113 return reply.readInt32();
114 }
115
116 status_t setDataSource(int fd, int64_t offset, int64_t length)
117 {
118 Parcel data, reply;
119 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
120 data.writeFileDescriptor(fd);
121 data.writeInt64(offset);
122 data.writeInt64(length);
123 remote()->transact(SET_DATA_SOURCE_FD, data, &reply);
124 return reply.readInt32();
125 }
126
127 status_t setMode(int mode)
128 {
129 Parcel data, reply;
130 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
131 data.writeInt32(mode);
132 remote()->transact(SET_MODE, data, &reply);
133 return reply.readInt32();
134 }
135
136 status_t getMode(int* mode) const
137 {
138 Parcel data, reply;
139 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
140 remote()->transact(GET_MODE, data, &reply);
141 *mode = reply.readInt32();
142 return reply.readInt32();
143 }
144
145 sp<IMemory> captureFrame()
146 {
147 Parcel data, reply;
148 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
Dave Sparksec4dde72009-11-23 16:51:15 -0800149#ifndef DISABLE_GROUP_SCHEDULE_HACK
150 sendSchedPolicy(data);
151#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800152 remote()->transact(CAPTURE_FRAME, data, &reply);
153 status_t ret = reply.readInt32();
154 if (ret != NO_ERROR) {
155 return NULL;
156 }
157 return interface_cast<IMemory>(reply.readStrongBinder());
158 }
159
160 sp<IMemory> extractAlbumArt()
161 {
162 Parcel data, reply;
163 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
Dave Sparksec4dde72009-11-23 16:51:15 -0800164#ifndef DISABLE_GROUP_SCHEDULE_HACK
165 sendSchedPolicy(data);
166#endif
167 remote()->transact(EXTRACT_ALBUM_ART, data, &reply);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800168 status_t ret = reply.readInt32();
169 if (ret != NO_ERROR) {
170 return NULL;
171 }
172 return interface_cast<IMemory>(reply.readStrongBinder());
173 }
174
175 const char* extractMetadata(int keyCode)
176 {
177 Parcel data, reply;
178 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
Dave Sparksec4dde72009-11-23 16:51:15 -0800179#ifndef DISABLE_GROUP_SCHEDULE_HACK
180 sendSchedPolicy(data);
181#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800182 data.writeInt32(keyCode);
183 remote()->transact(EXTRACT_METADATA, data, &reply);
184 status_t ret = reply.readInt32();
185 if (ret != NO_ERROR) {
186 return NULL;
187 }
188 return reply.readCString();
189 }
190};
191
niko56f0cc52009-06-22 08:49:52 -0700192IMPLEMENT_META_INTERFACE(MediaMetadataRetriever, "android.media.IMediaMetadataRetriever");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800193
194// ----------------------------------------------------------------------
195
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800196status_t BnMediaMetadataRetriever::onTransact(
197 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
198{
199 switch (code) {
200 case DISCONNECT: {
201 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
202 disconnect();
203 return NO_ERROR;
204 } break;
205 case SET_DATA_SOURCE_URL: {
206 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
207 const char* srcUrl = data.readCString();
208 reply->writeInt32(setDataSource(srcUrl));
209 return NO_ERROR;
210 } break;
211 case SET_DATA_SOURCE_FD: {
212 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
213 int fd = dup(data.readFileDescriptor());
214 int64_t offset = data.readInt64();
215 int64_t length = data.readInt64();
216 reply->writeInt32(setDataSource(fd, offset, length));
217 return NO_ERROR;
218 } break;
219 case SET_MODE: {
220 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
221 int mode = data.readInt32();
222 reply->writeInt32(setMode(mode));
223 return NO_ERROR;
224 } break;
225 case GET_MODE: {
226 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
227 int mode;
228 status_t status = getMode(&mode);
229 reply->writeInt32(mode);
230 reply->writeInt32(status);
231 return NO_ERROR;
232 } break;
233 case CAPTURE_FRAME: {
234 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
Dave Sparksec4dde72009-11-23 16:51:15 -0800235#ifndef DISABLE_GROUP_SCHEDULE_HACK
236 setSchedPolicy(data);
237#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800238 sp<IMemory> bitmap = captureFrame();
239 if (bitmap != 0) { // Don't send NULL across the binder interface
240 reply->writeInt32(NO_ERROR);
241 reply->writeStrongBinder(bitmap->asBinder());
242 } else {
243 reply->writeInt32(UNKNOWN_ERROR);
244 }
Dave Sparksec4dde72009-11-23 16:51:15 -0800245#ifndef DISABLE_GROUP_SCHEDULE_HACK
246 restoreSchedPolicy();
247#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800248 return NO_ERROR;
249 } break;
Dave Sparksec4dde72009-11-23 16:51:15 -0800250 case EXTRACT_ALBUM_ART: {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800251 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
Dave Sparksec4dde72009-11-23 16:51:15 -0800252#ifndef DISABLE_GROUP_SCHEDULE_HACK
253 setSchedPolicy(data);
254#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800255 sp<IMemory> albumArt = extractAlbumArt();
256 if (albumArt != 0) { // Don't send NULL across the binder interface
257 reply->writeInt32(NO_ERROR);
258 reply->writeStrongBinder(albumArt->asBinder());
259 } else {
260 reply->writeInt32(UNKNOWN_ERROR);
261 }
Dave Sparksec4dde72009-11-23 16:51:15 -0800262#ifndef DISABLE_GROUP_SCHEDULE_HACK
263 restoreSchedPolicy();
264#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800265 return NO_ERROR;
266 } break;
267 case EXTRACT_METADATA: {
268 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
Dave Sparksec4dde72009-11-23 16:51:15 -0800269#ifndef DISABLE_GROUP_SCHEDULE_HACK
270 setSchedPolicy(data);
271#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800272 int keyCode = data.readInt32();
273 const char* value = extractMetadata(keyCode);
274 if (value != NULL) { // Don't send NULL across the binder interface
275 reply->writeInt32(NO_ERROR);
276 reply->writeCString(value);
277 } else {
278 reply->writeInt32(UNKNOWN_ERROR);
279 }
Dave Sparksec4dde72009-11-23 16:51:15 -0800280#ifndef DISABLE_GROUP_SCHEDULE_HACK
281 restoreSchedPolicy();
282#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800283 return NO_ERROR;
284 } break;
285 default:
286 return BBinder::onTransact(code, data, reply, flags);
287 }
288}
289
290// ----------------------------------------------------------------------------
291
292}; // namespace android