blob: 3c4dce92e72a2eb4de4c955c6b8e36a1641b59d3 [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
Chris Watkins99f31602015-03-20 13:06:33 -0700130 status_t setDataSource(const sp<IDataSource>& source)
131 {
132 Parcel data, reply;
133 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
134 data.writeStrongBinder(IInterface::asBinder(source));
135 remote()->transact(SET_DATA_SOURCE_CALLBACK, data, &reply);
136 return reply.readInt32();
137 }
138
James Dong16afe2f2010-12-02 17:42:08 -0800139 sp<IMemory> getFrameAtTime(int64_t timeUs, int option)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800140 {
Mark Salyzyn34fb2962014-06-18 16:30:56 -0700141 ALOGV("getTimeAtTime: time(%" PRId64 " us) and option(%d)", timeUs, option);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800142 Parcel data, reply;
143 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
James Dong16afe2f2010-12-02 17:42:08 -0800144 data.writeInt64(timeUs);
145 data.writeInt32(option);
Dave Sparksec4dde72009-11-23 16:51:15 -0800146#ifndef DISABLE_GROUP_SCHEDULE_HACK
147 sendSchedPolicy(data);
148#endif
James Dong16afe2f2010-12-02 17:42:08 -0800149 remote()->transact(GET_FRAME_AT_TIME, data, &reply);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800150 status_t ret = reply.readInt32();
151 if (ret != NO_ERROR) {
152 return NULL;
153 }
154 return interface_cast<IMemory>(reply.readStrongBinder());
155 }
156
157 sp<IMemory> extractAlbumArt()
158 {
159 Parcel data, reply;
160 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
Dave Sparksec4dde72009-11-23 16:51:15 -0800161#ifndef DISABLE_GROUP_SCHEDULE_HACK
162 sendSchedPolicy(data);
163#endif
164 remote()->transact(EXTRACT_ALBUM_ART, data, &reply);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800165 status_t ret = reply.readInt32();
166 if (ret != NO_ERROR) {
167 return NULL;
168 }
169 return interface_cast<IMemory>(reply.readStrongBinder());
170 }
171
172 const char* extractMetadata(int keyCode)
173 {
174 Parcel data, reply;
175 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
Dave Sparksec4dde72009-11-23 16:51:15 -0800176#ifndef DISABLE_GROUP_SCHEDULE_HACK
177 sendSchedPolicy(data);
178#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800179 data.writeInt32(keyCode);
180 remote()->transact(EXTRACT_METADATA, data, &reply);
181 status_t ret = reply.readInt32();
182 if (ret != NO_ERROR) {
183 return NULL;
184 }
Sangkyu Leed01c1482013-02-08 16:26:39 +0900185 const char* str = reply.readCString();
186 if (str != NULL) {
187 String8 value(str);
188 if (mMetadata.indexOfKey(keyCode) < 0) {
189 mMetadata.add(keyCode, value);
190 } else {
191 mMetadata.replaceValueFor(keyCode, value);
192 }
193 return mMetadata.valueFor(keyCode).string();
194 } else {
195 return NULL;
196 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800197 }
Sangkyu Leed01c1482013-02-08 16:26:39 +0900198
199private:
200 KeyedVector<int, String8> mMetadata;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800201};
202
niko56f0cc52009-06-22 08:49:52 -0700203IMPLEMENT_META_INTERFACE(MediaMetadataRetriever, "android.media.IMediaMetadataRetriever");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800204
205// ----------------------------------------------------------------------
206
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800207status_t BnMediaMetadataRetriever::onTransact(
208 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
209{
210 switch (code) {
211 case DISCONNECT: {
212 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
213 disconnect();
214 return NO_ERROR;
215 } break;
216 case SET_DATA_SOURCE_URL: {
217 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
Andreas Huber1b86fe02014-01-29 11:13:26 -0800218
219 sp<IMediaHTTPService> httpService;
220 if (data.readInt32()) {
221 httpService =
222 interface_cast<IMediaHTTPService>(data.readStrongBinder());
223 }
224
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800225 const char* srcUrl = data.readCString();
Andreas Huberaf8791e2011-03-21 10:25:44 -0700226
227 KeyedVector<String8, String8> headers;
Glenn Kastene03dd222014-01-28 11:04:39 -0800228 size_t numHeaders = (size_t) data.readInt64();
229 for (size_t i = 0; i < numHeaders; ++i) {
Andreas Huberaf8791e2011-03-21 10:25:44 -0700230 String8 key = data.readString8();
231 String8 value = data.readString8();
232 headers.add(key, value);
233 }
234
235 reply->writeInt32(
Andreas Huber1b86fe02014-01-29 11:13:26 -0800236 setDataSource(
237 httpService, srcUrl, numHeaders > 0 ? &headers : NULL));
Andreas Huberaf8791e2011-03-21 10:25:44 -0700238
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800239 return NO_ERROR;
240 } break;
241 case SET_DATA_SOURCE_FD: {
242 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
Taiju Tsuiki55203e22015-04-21 17:36:22 +0900243 int fd = data.readFileDescriptor();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800244 int64_t offset = data.readInt64();
245 int64_t length = data.readInt64();
246 reply->writeInt32(setDataSource(fd, offset, length));
247 return NO_ERROR;
248 } break;
Chris Watkins99f31602015-03-20 13:06:33 -0700249 case SET_DATA_SOURCE_CALLBACK: {
250 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
251 sp<IDataSource> source =
252 interface_cast<IDataSource>(data.readStrongBinder());
253 reply->writeInt32(setDataSource(source));
254 return NO_ERROR;
255 } break;
James Dong16afe2f2010-12-02 17:42:08 -0800256 case GET_FRAME_AT_TIME: {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800257 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
James Dong16afe2f2010-12-02 17:42:08 -0800258 int64_t timeUs = data.readInt64();
259 int option = data.readInt32();
Mark Salyzyn34fb2962014-06-18 16:30:56 -0700260 ALOGV("getTimeAtTime: time(%" PRId64 " us) and option(%d)", timeUs, option);
Dave Sparksec4dde72009-11-23 16:51:15 -0800261#ifndef DISABLE_GROUP_SCHEDULE_HACK
262 setSchedPolicy(data);
263#endif
James Dong16afe2f2010-12-02 17:42:08 -0800264 sp<IMemory> bitmap = getFrameAtTime(timeUs, option);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800265 if (bitmap != 0) { // Don't send NULL across the binder interface
266 reply->writeInt32(NO_ERROR);
Marco Nelissen06b46062014-11-14 07:58:25 -0800267 reply->writeStrongBinder(IInterface::asBinder(bitmap));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800268 } else {
269 reply->writeInt32(UNKNOWN_ERROR);
270 }
Dave Sparksec4dde72009-11-23 16:51:15 -0800271#ifndef DISABLE_GROUP_SCHEDULE_HACK
272 restoreSchedPolicy();
273#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800274 return NO_ERROR;
275 } break;
Dave Sparksec4dde72009-11-23 16:51:15 -0800276 case EXTRACT_ALBUM_ART: {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800277 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
Dave Sparksec4dde72009-11-23 16:51:15 -0800278#ifndef DISABLE_GROUP_SCHEDULE_HACK
279 setSchedPolicy(data);
280#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800281 sp<IMemory> albumArt = extractAlbumArt();
282 if (albumArt != 0) { // Don't send NULL across the binder interface
283 reply->writeInt32(NO_ERROR);
Marco Nelissen06b46062014-11-14 07:58:25 -0800284 reply->writeStrongBinder(IInterface::asBinder(albumArt));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800285 } else {
286 reply->writeInt32(UNKNOWN_ERROR);
287 }
Dave Sparksec4dde72009-11-23 16:51:15 -0800288#ifndef DISABLE_GROUP_SCHEDULE_HACK
289 restoreSchedPolicy();
290#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800291 return NO_ERROR;
292 } break;
293 case EXTRACT_METADATA: {
294 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
Dave Sparksec4dde72009-11-23 16:51:15 -0800295#ifndef DISABLE_GROUP_SCHEDULE_HACK
296 setSchedPolicy(data);
297#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800298 int keyCode = data.readInt32();
299 const char* value = extractMetadata(keyCode);
300 if (value != NULL) { // Don't send NULL across the binder interface
301 reply->writeInt32(NO_ERROR);
302 reply->writeCString(value);
303 } else {
304 reply->writeInt32(UNKNOWN_ERROR);
305 }
Dave Sparksec4dde72009-11-23 16:51:15 -0800306#ifndef DISABLE_GROUP_SCHEDULE_HACK
307 restoreSchedPolicy();
308#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800309 return NO_ERROR;
310 } break;
311 default:
312 return BBinder::onTransact(code, data, reply, flags);
313 }
314}
315
316// ----------------------------------------------------------------------------
317
Glenn Kasten40bc9062015-03-20 09:09:33 -0700318} // namespace android