blob: 7e6d54bdf07f50c2d19fd03f6d98824976367687 [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 <media/IMediaMetadataRetriever.h>
Andreas Huberaf8791e2011-03-21 10:25:44 -070022#include <utils/String8.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080023
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
Dave Sparksf311c552009-11-23 19:51:33 -080032#undef LOG_TAG
Dave Sparksec4dde72009-11-23 16:51:15 -080033#define LOG_TAG "IMediaMetadataRetriever"
34#include <utils/Log.h>
35#include <cutils/sched_policy.h>
36
37namespace android {
38
39static void sendSchedPolicy(Parcel& data)
40{
41 SchedPolicy policy;
Glenn Kasten0512ab52011-05-04 17:58:57 -070042 get_sched_policy(gettid(), &policy);
Dave Sparksec4dde72009-11-23 16:51:15 -080043 data.writeInt32(policy);
44}
45
46static void setSchedPolicy(const Parcel& data)
47{
48 SchedPolicy policy = (SchedPolicy) data.readInt32();
Glenn Kasten0512ab52011-05-04 17:58:57 -070049 set_sched_policy(gettid(), policy);
Dave Sparksec4dde72009-11-23 16:51:15 -080050}
51static void restoreSchedPolicy()
52{
Glenn Kasten0512ab52011-05-04 17:58:57 -070053 set_sched_policy(gettid(), SP_FOREGROUND);
Dave Sparksec4dde72009-11-23 16:51:15 -080054}
55}; // end namespace android
56#endif
57
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080058namespace android {
59
60enum {
61 DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
62 SET_DATA_SOURCE_URL,
63 SET_DATA_SOURCE_FD,
James Dong16afe2f2010-12-02 17:42:08 -080064 GET_FRAME_AT_TIME,
Dave Sparksec4dde72009-11-23 16:51:15 -080065 EXTRACT_ALBUM_ART,
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080066 EXTRACT_METADATA,
67};
68
69class BpMediaMetadataRetriever: public BpInterface<IMediaMetadataRetriever>
70{
71public:
72 BpMediaMetadataRetriever(const sp<IBinder>& impl)
73 : BpInterface<IMediaMetadataRetriever>(impl)
74 {
75 }
76
77 // disconnect from media metadata retriever service
78 void disconnect()
79 {
80 Parcel data, reply;
81 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
82 remote()->transact(DISCONNECT, data, &reply);
83 }
84
Andreas Huberaf8791e2011-03-21 10:25:44 -070085 status_t setDataSource(
86 const char *srcUrl, const KeyedVector<String8, String8> *headers)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080087 {
88 Parcel data, reply;
89 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
90 data.writeCString(srcUrl);
Andreas Huberaf8791e2011-03-21 10:25:44 -070091
92 if (headers == NULL) {
93 data.writeInt32(0);
94 } else {
95 // serialize the headers
96 data.writeInt32(headers->size());
97 for (size_t i = 0; i < headers->size(); ++i) {
98 data.writeString8(headers->keyAt(i));
99 data.writeString8(headers->valueAt(i));
100 }
101 }
102
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800103 remote()->transact(SET_DATA_SOURCE_URL, data, &reply);
104 return reply.readInt32();
105 }
106
107 status_t setDataSource(int fd, int64_t offset, int64_t length)
108 {
109 Parcel data, reply;
110 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
111 data.writeFileDescriptor(fd);
112 data.writeInt64(offset);
113 data.writeInt64(length);
114 remote()->transact(SET_DATA_SOURCE_FD, data, &reply);
115 return reply.readInt32();
116 }
117
James Dong16afe2f2010-12-02 17:42:08 -0800118 sp<IMemory> getFrameAtTime(int64_t timeUs, int option)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800119 {
Steve Block3856b092011-10-20 11:56:00 +0100120 ALOGV("getTimeAtTime: time(%lld us) and option(%d)", timeUs, option);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800121 Parcel data, reply;
122 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
James Dong16afe2f2010-12-02 17:42:08 -0800123 data.writeInt64(timeUs);
124 data.writeInt32(option);
Dave Sparksec4dde72009-11-23 16:51:15 -0800125#ifndef DISABLE_GROUP_SCHEDULE_HACK
126 sendSchedPolicy(data);
127#endif
James Dong16afe2f2010-12-02 17:42:08 -0800128 remote()->transact(GET_FRAME_AT_TIME, data, &reply);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800129 status_t ret = reply.readInt32();
130 if (ret != NO_ERROR) {
131 return NULL;
132 }
133 return interface_cast<IMemory>(reply.readStrongBinder());
134 }
135
136 sp<IMemory> extractAlbumArt()
137 {
138 Parcel data, reply;
139 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
Dave Sparksec4dde72009-11-23 16:51:15 -0800140#ifndef DISABLE_GROUP_SCHEDULE_HACK
141 sendSchedPolicy(data);
142#endif
143 remote()->transact(EXTRACT_ALBUM_ART, data, &reply);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800144 status_t ret = reply.readInt32();
145 if (ret != NO_ERROR) {
146 return NULL;
147 }
148 return interface_cast<IMemory>(reply.readStrongBinder());
149 }
150
151 const char* extractMetadata(int keyCode)
152 {
153 Parcel data, reply;
154 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
Dave Sparksec4dde72009-11-23 16:51:15 -0800155#ifndef DISABLE_GROUP_SCHEDULE_HACK
156 sendSchedPolicy(data);
157#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800158 data.writeInt32(keyCode);
159 remote()->transact(EXTRACT_METADATA, data, &reply);
160 status_t ret = reply.readInt32();
161 if (ret != NO_ERROR) {
162 return NULL;
163 }
164 return reply.readCString();
165 }
166};
167
niko56f0cc52009-06-22 08:49:52 -0700168IMPLEMENT_META_INTERFACE(MediaMetadataRetriever, "android.media.IMediaMetadataRetriever");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800169
170// ----------------------------------------------------------------------
171
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800172status_t BnMediaMetadataRetriever::onTransact(
173 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
174{
175 switch (code) {
176 case DISCONNECT: {
177 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
178 disconnect();
179 return NO_ERROR;
180 } break;
181 case SET_DATA_SOURCE_URL: {
182 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
183 const char* srcUrl = data.readCString();
Andreas Huberaf8791e2011-03-21 10:25:44 -0700184
185 KeyedVector<String8, String8> headers;
186 int32_t numHeaders = data.readInt32();
187 for (int i = 0; i < numHeaders; ++i) {
188 String8 key = data.readString8();
189 String8 value = data.readString8();
190 headers.add(key, value);
191 }
192
193 reply->writeInt32(
194 setDataSource(srcUrl, numHeaders > 0 ? &headers : NULL));
195
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800196 return NO_ERROR;
197 } break;
198 case SET_DATA_SOURCE_FD: {
199 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
200 int fd = dup(data.readFileDescriptor());
201 int64_t offset = data.readInt64();
202 int64_t length = data.readInt64();
203 reply->writeInt32(setDataSource(fd, offset, length));
204 return NO_ERROR;
205 } break;
James Dong16afe2f2010-12-02 17:42:08 -0800206 case GET_FRAME_AT_TIME: {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800207 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
James Dong16afe2f2010-12-02 17:42:08 -0800208 int64_t timeUs = data.readInt64();
209 int option = data.readInt32();
Steve Block3856b092011-10-20 11:56:00 +0100210 ALOGV("getTimeAtTime: time(%lld us) and option(%d)", timeUs, option);
Dave Sparksec4dde72009-11-23 16:51:15 -0800211#ifndef DISABLE_GROUP_SCHEDULE_HACK
212 setSchedPolicy(data);
213#endif
James Dong16afe2f2010-12-02 17:42:08 -0800214 sp<IMemory> bitmap = getFrameAtTime(timeUs, option);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800215 if (bitmap != 0) { // Don't send NULL across the binder interface
216 reply->writeInt32(NO_ERROR);
217 reply->writeStrongBinder(bitmap->asBinder());
218 } else {
219 reply->writeInt32(UNKNOWN_ERROR);
220 }
Dave Sparksec4dde72009-11-23 16:51:15 -0800221#ifndef DISABLE_GROUP_SCHEDULE_HACK
222 restoreSchedPolicy();
223#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800224 return NO_ERROR;
225 } break;
Dave Sparksec4dde72009-11-23 16:51:15 -0800226 case EXTRACT_ALBUM_ART: {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800227 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
Dave Sparksec4dde72009-11-23 16:51:15 -0800228#ifndef DISABLE_GROUP_SCHEDULE_HACK
229 setSchedPolicy(data);
230#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800231 sp<IMemory> albumArt = extractAlbumArt();
232 if (albumArt != 0) { // Don't send NULL across the binder interface
233 reply->writeInt32(NO_ERROR);
234 reply->writeStrongBinder(albumArt->asBinder());
235 } else {
236 reply->writeInt32(UNKNOWN_ERROR);
237 }
Dave Sparksec4dde72009-11-23 16:51:15 -0800238#ifndef DISABLE_GROUP_SCHEDULE_HACK
239 restoreSchedPolicy();
240#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800241 return NO_ERROR;
242 } break;
243 case EXTRACT_METADATA: {
244 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
Dave Sparksec4dde72009-11-23 16:51:15 -0800245#ifndef DISABLE_GROUP_SCHEDULE_HACK
246 setSchedPolicy(data);
247#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800248 int keyCode = data.readInt32();
249 const char* value = extractMetadata(keyCode);
250 if (value != NULL) { // Don't send NULL across the binder interface
251 reply->writeInt32(NO_ERROR);
252 reply->writeCString(value);
253 } else {
254 reply->writeInt32(UNKNOWN_ERROR);
255 }
Dave Sparksec4dde72009-11-23 16:51:15 -0800256#ifndef DISABLE_GROUP_SCHEDULE_HACK
257 restoreSchedPolicy();
258#endif
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800259 return NO_ERROR;
260 } break;
261 default:
262 return BBinder::onTransact(code, data, reply, flags);
263 }
264}
265
266// ----------------------------------------------------------------------------
267
268}; // namespace android