blob: c7d9d51ad31a2cf892740bc8396b4f7235ebe521 [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>
Andreas Huber1b86fe02014-01-29 11:13:26 -080021#include <media/IMediaHTTPService.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080022#include <media/IMediaMetadataRetriever.h>
Andreas Huberaf8791e2011-03-21 10:25:44 -070023#include <utils/String8.h>
Sangkyu Leed01c1482013-02-08 16:26:39 +090024#include <utils/KeyedVector.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080025
Dave Sparksec4dde72009-11-23 16:51:15 -080026// The binder is supposed to propagate the scheduler group across
27// the binder interface so that remote calls are executed with
28// the same priority as local calls. This is currently not working
29// so this change puts in a temporary hack to fix the issue with
30// metadata retrieval which can be a huge CPU hit if done on a
31// foreground thread.
32#ifndef DISABLE_GROUP_SCHEDULE_HACK
33
Dave Sparksf311c552009-11-23 19:51:33 -080034#undef LOG_TAG
Dave Sparksec4dde72009-11-23 16:51:15 -080035#define LOG_TAG "IMediaMetadataRetriever"
36#include <utils/Log.h>
37#include <cutils/sched_policy.h>
38
39namespace android {
40
41static void sendSchedPolicy(Parcel& data)
42{
43 SchedPolicy policy;
Glenn Kasten0512ab52011-05-04 17:58:57 -070044 get_sched_policy(gettid(), &policy);
Dave Sparksec4dde72009-11-23 16:51:15 -080045 data.writeInt32(policy);
46}
47
48static void setSchedPolicy(const Parcel& data)
49{
50 SchedPolicy policy = (SchedPolicy) data.readInt32();
Glenn Kasten0512ab52011-05-04 17:58:57 -070051 set_sched_policy(gettid(), policy);
Dave Sparksec4dde72009-11-23 16:51:15 -080052}
53static void restoreSchedPolicy()
54{
Glenn Kasten0512ab52011-05-04 17:58:57 -070055 set_sched_policy(gettid(), SP_FOREGROUND);
Dave Sparksec4dde72009-11-23 16:51:15 -080056}
57}; // end namespace android
58#endif
59
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080060namespace android {
61
62enum {
63 DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
64 SET_DATA_SOURCE_URL,
65 SET_DATA_SOURCE_FD,
James Dong16afe2f2010-12-02 17:42:08 -080066 GET_FRAME_AT_TIME,
Dave Sparksec4dde72009-11-23 16:51:15 -080067 EXTRACT_ALBUM_ART,
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080068 EXTRACT_METADATA,
69};
70
71class BpMediaMetadataRetriever: public BpInterface<IMediaMetadataRetriever>
72{
73public:
74 BpMediaMetadataRetriever(const sp<IBinder>& impl)
75 : BpInterface<IMediaMetadataRetriever>(impl)
76 {
77 }
78
79 // disconnect from media metadata retriever service
80 void disconnect()
81 {
82 Parcel data, reply;
83 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
84 remote()->transact(DISCONNECT, data, &reply);
85 }
86
Andreas Huberaf8791e2011-03-21 10:25:44 -070087 status_t setDataSource(
Andreas Huber1b86fe02014-01-29 11:13:26 -080088 const sp<IMediaHTTPService> &httpService,
89 const char *srcUrl,
90 const KeyedVector<String8, String8> *headers)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080091 {
92 Parcel data, reply;
93 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
Andreas Huber1b86fe02014-01-29 11:13:26 -080094 data.writeInt32(httpService != NULL);
95 if (httpService != NULL) {
96 data.writeStrongBinder(httpService->asBinder());
97 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080098 data.writeCString(srcUrl);
Andreas Huberaf8791e2011-03-21 10:25:44 -070099
100 if (headers == NULL) {
101 data.writeInt32(0);
102 } else {
103 // serialize the headers
104 data.writeInt32(headers->size());
105 for (size_t i = 0; i < headers->size(); ++i) {
106 data.writeString8(headers->keyAt(i));
107 data.writeString8(headers->valueAt(i));
108 }
109 }
110
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800111 remote()->transact(SET_DATA_SOURCE_URL, data, &reply);
112 return reply.readInt32();
113 }
114
115 status_t setDataSource(int fd, int64_t offset, int64_t length)
116 {
117 Parcel data, reply;
118 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
119 data.writeFileDescriptor(fd);
120 data.writeInt64(offset);
121 data.writeInt64(length);
122 remote()->transact(SET_DATA_SOURCE_FD, data, &reply);
123 return reply.readInt32();
124 }
125
James Dong16afe2f2010-12-02 17:42:08 -0800126 sp<IMemory> getFrameAtTime(int64_t timeUs, int option)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800127 {
Steve Block3856b092011-10-20 11:56:00 +0100128 ALOGV("getTimeAtTime: time(%lld us) and option(%d)", timeUs, option);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800129 Parcel data, reply;
130 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
James Dong16afe2f2010-12-02 17:42:08 -0800131 data.writeInt64(timeUs);
132 data.writeInt32(option);
Dave Sparksec4dde72009-11-23 16:51:15 -0800133#ifndef DISABLE_GROUP_SCHEDULE_HACK
134 sendSchedPolicy(data);
135#endif
James Dong16afe2f2010-12-02 17:42:08 -0800136 remote()->transact(GET_FRAME_AT_TIME, data, &reply);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800137 status_t ret = reply.readInt32();
138 if (ret != NO_ERROR) {
139 return NULL;
140 }
141 return interface_cast<IMemory>(reply.readStrongBinder());
142 }
143
144 sp<IMemory> extractAlbumArt()
145 {
146 Parcel data, reply;
147 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
Dave Sparksec4dde72009-11-23 16:51:15 -0800148#ifndef DISABLE_GROUP_SCHEDULE_HACK
149 sendSchedPolicy(data);
150#endif
151 remote()->transact(EXTRACT_ALBUM_ART, data, &reply);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800152 status_t ret = reply.readInt32();
153 if (ret != NO_ERROR) {
154 return NULL;
155 }
156 return interface_cast<IMemory>(reply.readStrongBinder());
157 }
158
159 const char* extractMetadata(int keyCode)
160 {
161 Parcel data, reply;
162 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
Dave Sparksec4dde72009-11-23 16:51:15 -0800163#ifndef DISABLE_GROUP_SCHEDULE_HACK
164 sendSchedPolicy(data);
165#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800166 data.writeInt32(keyCode);
167 remote()->transact(EXTRACT_METADATA, data, &reply);
168 status_t ret = reply.readInt32();
169 if (ret != NO_ERROR) {
170 return NULL;
171 }
Sangkyu Leed01c1482013-02-08 16:26:39 +0900172 const char* str = reply.readCString();
173 if (str != NULL) {
174 String8 value(str);
175 if (mMetadata.indexOfKey(keyCode) < 0) {
176 mMetadata.add(keyCode, value);
177 } else {
178 mMetadata.replaceValueFor(keyCode, value);
179 }
180 return mMetadata.valueFor(keyCode).string();
181 } else {
182 return NULL;
183 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800184 }
Sangkyu Leed01c1482013-02-08 16:26:39 +0900185
186private:
187 KeyedVector<int, String8> mMetadata;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800188};
189
niko56f0cc52009-06-22 08:49:52 -0700190IMPLEMENT_META_INTERFACE(MediaMetadataRetriever, "android.media.IMediaMetadataRetriever");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800191
192// ----------------------------------------------------------------------
193
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800194status_t BnMediaMetadataRetriever::onTransact(
195 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
196{
197 switch (code) {
198 case DISCONNECT: {
199 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
200 disconnect();
201 return NO_ERROR;
202 } break;
203 case SET_DATA_SOURCE_URL: {
204 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
Andreas Huber1b86fe02014-01-29 11:13:26 -0800205
206 sp<IMediaHTTPService> httpService;
207 if (data.readInt32()) {
208 httpService =
209 interface_cast<IMediaHTTPService>(data.readStrongBinder());
210 }
211
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800212 const char* srcUrl = data.readCString();
Andreas Huberaf8791e2011-03-21 10:25:44 -0700213
214 KeyedVector<String8, String8> headers;
215 int32_t numHeaders = data.readInt32();
216 for (int i = 0; i < numHeaders; ++i) {
217 String8 key = data.readString8();
218 String8 value = data.readString8();
219 headers.add(key, value);
220 }
221
222 reply->writeInt32(
Andreas Huber1b86fe02014-01-29 11:13:26 -0800223 setDataSource(
224 httpService, srcUrl, numHeaders > 0 ? &headers : NULL));
Andreas Huberaf8791e2011-03-21 10:25:44 -0700225
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800226 return NO_ERROR;
227 } break;
228 case SET_DATA_SOURCE_FD: {
229 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
230 int fd = dup(data.readFileDescriptor());
231 int64_t offset = data.readInt64();
232 int64_t length = data.readInt64();
233 reply->writeInt32(setDataSource(fd, offset, length));
234 return NO_ERROR;
235 } break;
James Dong16afe2f2010-12-02 17:42:08 -0800236 case GET_FRAME_AT_TIME: {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800237 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
James Dong16afe2f2010-12-02 17:42:08 -0800238 int64_t timeUs = data.readInt64();
239 int option = data.readInt32();
Steve Block3856b092011-10-20 11:56:00 +0100240 ALOGV("getTimeAtTime: time(%lld us) and option(%d)", timeUs, option);
Dave Sparksec4dde72009-11-23 16:51:15 -0800241#ifndef DISABLE_GROUP_SCHEDULE_HACK
242 setSchedPolicy(data);
243#endif
James Dong16afe2f2010-12-02 17:42:08 -0800244 sp<IMemory> bitmap = getFrameAtTime(timeUs, option);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800245 if (bitmap != 0) { // Don't send NULL across the binder interface
246 reply->writeInt32(NO_ERROR);
247 reply->writeStrongBinder(bitmap->asBinder());
248 } else {
249 reply->writeInt32(UNKNOWN_ERROR);
250 }
Dave Sparksec4dde72009-11-23 16:51:15 -0800251#ifndef DISABLE_GROUP_SCHEDULE_HACK
252 restoreSchedPolicy();
253#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800254 return NO_ERROR;
255 } break;
Dave Sparksec4dde72009-11-23 16:51:15 -0800256 case EXTRACT_ALBUM_ART: {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800257 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
Dave Sparksec4dde72009-11-23 16:51:15 -0800258#ifndef DISABLE_GROUP_SCHEDULE_HACK
259 setSchedPolicy(data);
260#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800261 sp<IMemory> albumArt = extractAlbumArt();
262 if (albumArt != 0) { // Don't send NULL across the binder interface
263 reply->writeInt32(NO_ERROR);
264 reply->writeStrongBinder(albumArt->asBinder());
265 } else {
266 reply->writeInt32(UNKNOWN_ERROR);
267 }
Dave Sparksec4dde72009-11-23 16:51:15 -0800268#ifndef DISABLE_GROUP_SCHEDULE_HACK
269 restoreSchedPolicy();
270#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800271 return NO_ERROR;
272 } break;
273 case EXTRACT_METADATA: {
274 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
Dave Sparksec4dde72009-11-23 16:51:15 -0800275#ifndef DISABLE_GROUP_SCHEDULE_HACK
276 setSchedPolicy(data);
277#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800278 int keyCode = data.readInt32();
279 const char* value = extractMetadata(keyCode);
280 if (value != NULL) { // Don't send NULL across the binder interface
281 reply->writeInt32(NO_ERROR);
282 reply->writeCString(value);
283 } else {
284 reply->writeInt32(UNKNOWN_ERROR);
285 }
Dave Sparksec4dde72009-11-23 16:51:15 -0800286#ifndef DISABLE_GROUP_SCHEDULE_HACK
287 restoreSchedPolicy();
288#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800289 return NO_ERROR;
290 } break;
291 default:
292 return BBinder::onTransact(code, data, reply, flags);
293 }
294}
295
296// ----------------------------------------------------------------------------
297
298}; // namespace android