blob: 5ea2e8bbb081fbe731618ee647c34c38650ff315 [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
Mark Salyzyn34fb2962014-06-18 16:30:56 -070018#include <inttypes.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080019#include <stdint.h>
20#include <sys/types.h>
Mark Salyzyn34fb2962014-06-18 16:30:56 -070021
Mathias Agopian75624082009-05-19 19:08:10 -070022#include <binder/Parcel.h>
Chris Watkins99f31602015-03-20 13:06:33 -070023#include <media/IDataSource.h>
Andreas Huber1b86fe02014-01-29 11:13:26 -080024#include <media/IMediaHTTPService.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080025#include <media/IMediaMetadataRetriever.h>
Andreas Huberaf8791e2011-03-21 10:25:44 -070026#include <utils/String8.h>
Sangkyu Leed01c1482013-02-08 16:26:39 +090027#include <utils/KeyedVector.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080028
Dave Sparksec4dde72009-11-23 16:51:15 -080029// The binder is supposed to propagate the scheduler group across
30// the binder interface so that remote calls are executed with
31// the same priority as local calls. This is currently not working
32// so this change puts in a temporary hack to fix the issue with
33// metadata retrieval which can be a huge CPU hit if done on a
34// foreground thread.
35#ifndef DISABLE_GROUP_SCHEDULE_HACK
36
Dave Sparksf311c552009-11-23 19:51:33 -080037#undef LOG_TAG
Dave Sparksec4dde72009-11-23 16:51:15 -080038#define LOG_TAG "IMediaMetadataRetriever"
39#include <utils/Log.h>
40#include <cutils/sched_policy.h>
41
42namespace android {
43
44static void sendSchedPolicy(Parcel& data)
45{
46 SchedPolicy policy;
Glenn Kasten0512ab52011-05-04 17:58:57 -070047 get_sched_policy(gettid(), &policy);
Dave Sparksec4dde72009-11-23 16:51:15 -080048 data.writeInt32(policy);
49}
50
51static void setSchedPolicy(const Parcel& data)
52{
53 SchedPolicy policy = (SchedPolicy) data.readInt32();
Glenn Kasten0512ab52011-05-04 17:58:57 -070054 set_sched_policy(gettid(), policy);
Dave Sparksec4dde72009-11-23 16:51:15 -080055}
56static void restoreSchedPolicy()
57{
Glenn Kasten0512ab52011-05-04 17:58:57 -070058 set_sched_policy(gettid(), SP_FOREGROUND);
Dave Sparksec4dde72009-11-23 16:51:15 -080059}
60}; // end namespace android
61#endif
62
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080063namespace android {
64
65enum {
66 DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
67 SET_DATA_SOURCE_URL,
68 SET_DATA_SOURCE_FD,
Chris Watkins99f31602015-03-20 13:06:33 -070069 SET_DATA_SOURCE_CALLBACK,
James Dong16afe2f2010-12-02 17:42:08 -080070 GET_FRAME_AT_TIME,
Dave Sparksec4dde72009-11-23 16:51:15 -080071 EXTRACT_ALBUM_ART,
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080072 EXTRACT_METADATA,
73};
74
75class BpMediaMetadataRetriever: public BpInterface<IMediaMetadataRetriever>
76{
77public:
Chih-Hung Hsieh090ef602016-04-27 10:39:54 -070078 explicit BpMediaMetadataRetriever(const sp<IBinder>& impl)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080079 : BpInterface<IMediaMetadataRetriever>(impl)
80 {
81 }
82
83 // disconnect from media metadata retriever service
84 void disconnect()
85 {
86 Parcel data, reply;
87 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
88 remote()->transact(DISCONNECT, data, &reply);
89 }
90
Andreas Huberaf8791e2011-03-21 10:25:44 -070091 status_t setDataSource(
Andreas Huber1b86fe02014-01-29 11:13:26 -080092 const sp<IMediaHTTPService> &httpService,
93 const char *srcUrl,
94 const KeyedVector<String8, String8> *headers)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080095 {
96 Parcel data, reply;
97 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
Andreas Huber1b86fe02014-01-29 11:13:26 -080098 data.writeInt32(httpService != NULL);
99 if (httpService != NULL) {
Marco Nelissen06b46062014-11-14 07:58:25 -0800100 data.writeStrongBinder(IInterface::asBinder(httpService));
Andreas Huber1b86fe02014-01-29 11:13:26 -0800101 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800102 data.writeCString(srcUrl);
Andreas Huberaf8791e2011-03-21 10:25:44 -0700103
104 if (headers == NULL) {
105 data.writeInt32(0);
106 } else {
107 // serialize the headers
Glenn Kastene03dd222014-01-28 11:04:39 -0800108 data.writeInt64(headers->size());
Andreas Huberaf8791e2011-03-21 10:25:44 -0700109 for (size_t i = 0; i < headers->size(); ++i) {
110 data.writeString8(headers->keyAt(i));
111 data.writeString8(headers->valueAt(i));
112 }
113 }
114
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800115 remote()->transact(SET_DATA_SOURCE_URL, data, &reply);
116 return reply.readInt32();
117 }
118
119 status_t setDataSource(int fd, int64_t offset, int64_t length)
120 {
121 Parcel data, reply;
122 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
123 data.writeFileDescriptor(fd);
124 data.writeInt64(offset);
125 data.writeInt64(length);
126 remote()->transact(SET_DATA_SOURCE_FD, data, &reply);
127 return reply.readInt32();
128 }
129
Chong Zhang24c15772017-07-26 16:25:28 -0700130 status_t setDataSource(const sp<IDataSource>& source, const char *mime)
Chris Watkins99f31602015-03-20 13:06:33 -0700131 {
132 Parcel data, reply;
133 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
134 data.writeStrongBinder(IInterface::asBinder(source));
Chong Zhang24c15772017-07-26 16:25:28 -0700135
136 if (mime != NULL) {
137 data.writeInt32(1);
138 data.writeCString(mime);
139 } else {
140 data.writeInt32(0);
141 }
Chris Watkins99f31602015-03-20 13:06:33 -0700142 remote()->transact(SET_DATA_SOURCE_CALLBACK, data, &reply);
143 return reply.readInt32();
144 }
145
Chong Zhang24c15772017-07-26 16:25:28 -0700146 sp<IMemory> getFrameAtTime(int64_t timeUs, int option, int colorFormat, bool metaOnly)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800147 {
Chong Zhang24c15772017-07-26 16:25:28 -0700148 ALOGV("getTimeAtTime: time(%" PRId64 " us), option(%d), colorFormat(%d) metaOnly(%d)",
149 timeUs, option, colorFormat, metaOnly);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800150 Parcel data, reply;
151 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
James Dong16afe2f2010-12-02 17:42:08 -0800152 data.writeInt64(timeUs);
153 data.writeInt32(option);
Chong Zhang24c15772017-07-26 16:25:28 -0700154 data.writeInt32(colorFormat);
155 data.writeInt32(metaOnly);
Dave Sparksec4dde72009-11-23 16:51:15 -0800156#ifndef DISABLE_GROUP_SCHEDULE_HACK
157 sendSchedPolicy(data);
158#endif
James Dong16afe2f2010-12-02 17:42:08 -0800159 remote()->transact(GET_FRAME_AT_TIME, data, &reply);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800160 status_t ret = reply.readInt32();
161 if (ret != NO_ERROR) {
162 return NULL;
163 }
164 return interface_cast<IMemory>(reply.readStrongBinder());
165 }
166
167 sp<IMemory> extractAlbumArt()
168 {
169 Parcel data, reply;
170 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
Dave Sparksec4dde72009-11-23 16:51:15 -0800171#ifndef DISABLE_GROUP_SCHEDULE_HACK
172 sendSchedPolicy(data);
173#endif
174 remote()->transact(EXTRACT_ALBUM_ART, data, &reply);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800175 status_t ret = reply.readInt32();
176 if (ret != NO_ERROR) {
177 return NULL;
178 }
179 return interface_cast<IMemory>(reply.readStrongBinder());
180 }
181
182 const char* extractMetadata(int keyCode)
183 {
184 Parcel data, reply;
185 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
Dave Sparksec4dde72009-11-23 16:51:15 -0800186#ifndef DISABLE_GROUP_SCHEDULE_HACK
187 sendSchedPolicy(data);
188#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800189 data.writeInt32(keyCode);
190 remote()->transact(EXTRACT_METADATA, data, &reply);
191 status_t ret = reply.readInt32();
192 if (ret != NO_ERROR) {
193 return NULL;
194 }
Sangkyu Leed01c1482013-02-08 16:26:39 +0900195 const char* str = reply.readCString();
196 if (str != NULL) {
197 String8 value(str);
198 if (mMetadata.indexOfKey(keyCode) < 0) {
199 mMetadata.add(keyCode, value);
200 } else {
201 mMetadata.replaceValueFor(keyCode, value);
202 }
203 return mMetadata.valueFor(keyCode).string();
204 } else {
205 return NULL;
206 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800207 }
Sangkyu Leed01c1482013-02-08 16:26:39 +0900208
209private:
210 KeyedVector<int, String8> mMetadata;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800211};
212
niko56f0cc52009-06-22 08:49:52 -0700213IMPLEMENT_META_INTERFACE(MediaMetadataRetriever, "android.media.IMediaMetadataRetriever");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800214
215// ----------------------------------------------------------------------
216
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800217status_t BnMediaMetadataRetriever::onTransact(
218 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
219{
220 switch (code) {
221 case DISCONNECT: {
222 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
223 disconnect();
224 return NO_ERROR;
225 } break;
226 case SET_DATA_SOURCE_URL: {
227 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
Andreas Huber1b86fe02014-01-29 11:13:26 -0800228
229 sp<IMediaHTTPService> httpService;
230 if (data.readInt32()) {
231 httpService =
232 interface_cast<IMediaHTTPService>(data.readStrongBinder());
233 }
234
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800235 const char* srcUrl = data.readCString();
Andreas Huberaf8791e2011-03-21 10:25:44 -0700236
Wei Jia2afac0c2016-01-07 12:13:07 -0800237 if (httpService == NULL || srcUrl == NULL) {
238 reply->writeInt32(BAD_VALUE);
239 return NO_ERROR;
240 }
241
Andreas Huberaf8791e2011-03-21 10:25:44 -0700242 KeyedVector<String8, String8> headers;
Glenn Kastene03dd222014-01-28 11:04:39 -0800243 size_t numHeaders = (size_t) data.readInt64();
244 for (size_t i = 0; i < numHeaders; ++i) {
Andreas Huberaf8791e2011-03-21 10:25:44 -0700245 String8 key = data.readString8();
246 String8 value = data.readString8();
247 headers.add(key, value);
248 }
249
250 reply->writeInt32(
Andreas Huber1b86fe02014-01-29 11:13:26 -0800251 setDataSource(
252 httpService, srcUrl, numHeaders > 0 ? &headers : NULL));
Andreas Huberaf8791e2011-03-21 10:25:44 -0700253
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800254 return NO_ERROR;
255 } break;
256 case SET_DATA_SOURCE_FD: {
257 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
Taiju Tsuiki55203e22015-04-21 17:36:22 +0900258 int fd = data.readFileDescriptor();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800259 int64_t offset = data.readInt64();
260 int64_t length = data.readInt64();
261 reply->writeInt32(setDataSource(fd, offset, length));
262 return NO_ERROR;
263 } break;
Chris Watkins99f31602015-03-20 13:06:33 -0700264 case SET_DATA_SOURCE_CALLBACK: {
265 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
266 sp<IDataSource> source =
267 interface_cast<IDataSource>(data.readStrongBinder());
Wei Jia2afac0c2016-01-07 12:13:07 -0800268 if (source == NULL) {
269 reply->writeInt32(BAD_VALUE);
270 } else {
Chong Zhang24c15772017-07-26 16:25:28 -0700271 int32_t hasMime = data.readInt32();
272 const char *mime = NULL;
273 if (hasMime) {
274 mime = data.readCString();
275 }
276 reply->writeInt32(setDataSource(source, mime));
Wei Jia2afac0c2016-01-07 12:13:07 -0800277 }
Chris Watkins99f31602015-03-20 13:06:33 -0700278 return NO_ERROR;
279 } break;
James Dong16afe2f2010-12-02 17:42:08 -0800280 case GET_FRAME_AT_TIME: {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800281 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
James Dong16afe2f2010-12-02 17:42:08 -0800282 int64_t timeUs = data.readInt64();
283 int option = data.readInt32();
Chong Zhang24c15772017-07-26 16:25:28 -0700284 int colorFormat = data.readInt32();
285 bool metaOnly = (data.readInt32() != 0);
286 ALOGV("getTimeAtTime: time(%" PRId64 " us), option(%d), colorFormat(%d), metaOnly(%d)",
287 timeUs, option, colorFormat, metaOnly);
Dave Sparksec4dde72009-11-23 16:51:15 -0800288#ifndef DISABLE_GROUP_SCHEDULE_HACK
289 setSchedPolicy(data);
290#endif
Chong Zhang24c15772017-07-26 16:25:28 -0700291 sp<IMemory> bitmap = getFrameAtTime(timeUs, option, colorFormat, metaOnly);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800292 if (bitmap != 0) { // Don't send NULL across the binder interface
293 reply->writeInt32(NO_ERROR);
Marco Nelissen06b46062014-11-14 07:58:25 -0800294 reply->writeStrongBinder(IInterface::asBinder(bitmap));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800295 } else {
296 reply->writeInt32(UNKNOWN_ERROR);
297 }
Dave Sparksec4dde72009-11-23 16:51:15 -0800298#ifndef DISABLE_GROUP_SCHEDULE_HACK
299 restoreSchedPolicy();
300#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800301 return NO_ERROR;
302 } break;
Dave Sparksec4dde72009-11-23 16:51:15 -0800303 case EXTRACT_ALBUM_ART: {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800304 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
Dave Sparksec4dde72009-11-23 16:51:15 -0800305#ifndef DISABLE_GROUP_SCHEDULE_HACK
306 setSchedPolicy(data);
307#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800308 sp<IMemory> albumArt = extractAlbumArt();
309 if (albumArt != 0) { // Don't send NULL across the binder interface
310 reply->writeInt32(NO_ERROR);
Marco Nelissen06b46062014-11-14 07:58:25 -0800311 reply->writeStrongBinder(IInterface::asBinder(albumArt));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800312 } else {
313 reply->writeInt32(UNKNOWN_ERROR);
314 }
Dave Sparksec4dde72009-11-23 16:51:15 -0800315#ifndef DISABLE_GROUP_SCHEDULE_HACK
316 restoreSchedPolicy();
317#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800318 return NO_ERROR;
319 } break;
320 case EXTRACT_METADATA: {
321 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
Dave Sparksec4dde72009-11-23 16:51:15 -0800322#ifndef DISABLE_GROUP_SCHEDULE_HACK
323 setSchedPolicy(data);
324#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800325 int keyCode = data.readInt32();
326 const char* value = extractMetadata(keyCode);
327 if (value != NULL) { // Don't send NULL across the binder interface
328 reply->writeInt32(NO_ERROR);
329 reply->writeCString(value);
330 } else {
331 reply->writeInt32(UNKNOWN_ERROR);
332 }
Dave Sparksec4dde72009-11-23 16:51:15 -0800333#ifndef DISABLE_GROUP_SCHEDULE_HACK
334 restoreSchedPolicy();
335#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800336 return NO_ERROR;
337 } break;
338 default:
339 return BBinder::onTransact(code, data, reply, flags);
340 }
341}
342
343// ----------------------------------------------------------------------------
344
Glenn Kasten40bc9062015-03-20 09:09:33 -0700345} // namespace android