blob: d5298c91cc082cc2c45787489185cfd5adba9e9c [file] [log] [blame]
The Android Open Source Project9066cfe2009-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 Agopian07952722009-05-19 19:08:10 -070020#include <binder/Parcel.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021#include <SkBitmap.h>
22#include <media/IMediaMetadataRetriever.h>
23
Dave Sparks0f9a53d2009-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 Sparks16cc72b2009-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 Sparks0f9a53d2009-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 Sparks16cc72b2009-11-23 19:51:33 -080062 get_sched_policy(myTid(), &policy);
Dave Sparks0f9a53d2009-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 Sparks16cc72b2009-11-23 19:51:33 -080069 set_sched_policy(myTid(), policy);
Dave Sparks0f9a53d2009-11-23 16:51:15 -080070}
71static void restoreSchedPolicy()
72{
Dave Sparks16cc72b2009-11-23 19:51:33 -080073 set_sched_policy(myTid(), SP_FOREGROUND);
Dave Sparks0f9a53d2009-11-23 16:51:15 -080074}
75}; // end namespace android
76#endif
77
The Android Open Source Project9066cfe2009-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,
James Dongfaf09ba2010-12-02 17:42:08 -080084 GET_FRAME_AT_TIME,
Dave Sparks0f9a53d2009-11-23 16:51:15 -080085 EXTRACT_ALBUM_ART,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086 EXTRACT_METADATA,
87};
88
89class BpMediaMetadataRetriever: public BpInterface<IMediaMetadataRetriever>
90{
91public:
92 BpMediaMetadataRetriever(const sp<IBinder>& impl)
93 : BpInterface<IMediaMetadataRetriever>(impl)
94 {
95 }
96
97 // disconnect from media metadata retriever service
98 void disconnect()
99 {
100 Parcel data, reply;
101 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
102 remote()->transact(DISCONNECT, data, &reply);
103 }
104
105 status_t setDataSource(const char* srcUrl)
106 {
107 Parcel data, reply;
108 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
109 data.writeCString(srcUrl);
110 remote()->transact(SET_DATA_SOURCE_URL, data, &reply);
111 return reply.readInt32();
112 }
113
114 status_t setDataSource(int fd, int64_t offset, int64_t length)
115 {
116 Parcel data, reply;
117 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
118 data.writeFileDescriptor(fd);
119 data.writeInt64(offset);
120 data.writeInt64(length);
121 remote()->transact(SET_DATA_SOURCE_FD, data, &reply);
122 return reply.readInt32();
123 }
124
James Dongfaf09ba2010-12-02 17:42:08 -0800125 sp<IMemory> getFrameAtTime(int64_t timeUs, int option)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126 {
James Dongfaf09ba2010-12-02 17:42:08 -0800127 LOGV("getTimeAtTime: time(%lld us) and option(%d)", timeUs, option);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128 Parcel data, reply;
129 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
James Dongfaf09ba2010-12-02 17:42:08 -0800130 data.writeInt64(timeUs);
131 data.writeInt32(option);
Dave Sparks0f9a53d2009-11-23 16:51:15 -0800132#ifndef DISABLE_GROUP_SCHEDULE_HACK
133 sendSchedPolicy(data);
134#endif
James Dongfaf09ba2010-12-02 17:42:08 -0800135 remote()->transact(GET_FRAME_AT_TIME, data, &reply);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136 status_t ret = reply.readInt32();
137 if (ret != NO_ERROR) {
138 return NULL;
139 }
140 return interface_cast<IMemory>(reply.readStrongBinder());
141 }
142
143 sp<IMemory> extractAlbumArt()
144 {
145 Parcel data, reply;
146 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
Dave Sparks0f9a53d2009-11-23 16:51:15 -0800147#ifndef DISABLE_GROUP_SCHEDULE_HACK
148 sendSchedPolicy(data);
149#endif
150 remote()->transact(EXTRACT_ALBUM_ART, data, &reply);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151 status_t ret = reply.readInt32();
152 if (ret != NO_ERROR) {
153 return NULL;
154 }
155 return interface_cast<IMemory>(reply.readStrongBinder());
156 }
157
158 const char* extractMetadata(int keyCode)
159 {
160 Parcel data, reply;
161 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
Dave Sparks0f9a53d2009-11-23 16:51:15 -0800162#ifndef DISABLE_GROUP_SCHEDULE_HACK
163 sendSchedPolicy(data);
164#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 data.writeInt32(keyCode);
166 remote()->transact(EXTRACT_METADATA, data, &reply);
167 status_t ret = reply.readInt32();
168 if (ret != NO_ERROR) {
169 return NULL;
170 }
171 return reply.readCString();
172 }
173};
174
nikodcd810d2009-06-22 08:49:52 -0700175IMPLEMENT_META_INTERFACE(MediaMetadataRetriever, "android.media.IMediaMetadataRetriever");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800176
177// ----------------------------------------------------------------------
178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800179status_t BnMediaMetadataRetriever::onTransact(
180 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
181{
182 switch (code) {
183 case DISCONNECT: {
184 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
185 disconnect();
186 return NO_ERROR;
187 } break;
188 case SET_DATA_SOURCE_URL: {
189 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
190 const char* srcUrl = data.readCString();
191 reply->writeInt32(setDataSource(srcUrl));
192 return NO_ERROR;
193 } break;
194 case SET_DATA_SOURCE_FD: {
195 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
196 int fd = dup(data.readFileDescriptor());
197 int64_t offset = data.readInt64();
198 int64_t length = data.readInt64();
199 reply->writeInt32(setDataSource(fd, offset, length));
200 return NO_ERROR;
201 } break;
James Dongfaf09ba2010-12-02 17:42:08 -0800202 case GET_FRAME_AT_TIME: {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
James Dongfaf09ba2010-12-02 17:42:08 -0800204 int64_t timeUs = data.readInt64();
205 int option = data.readInt32();
206 LOGV("getTimeAtTime: time(%lld us) and option(%d)", timeUs, option);
Dave Sparks0f9a53d2009-11-23 16:51:15 -0800207#ifndef DISABLE_GROUP_SCHEDULE_HACK
208 setSchedPolicy(data);
209#endif
James Dongfaf09ba2010-12-02 17:42:08 -0800210 sp<IMemory> bitmap = getFrameAtTime(timeUs, option);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211 if (bitmap != 0) { // Don't send NULL across the binder interface
212 reply->writeInt32(NO_ERROR);
213 reply->writeStrongBinder(bitmap->asBinder());
214 } else {
215 reply->writeInt32(UNKNOWN_ERROR);
216 }
Dave Sparks0f9a53d2009-11-23 16:51:15 -0800217#ifndef DISABLE_GROUP_SCHEDULE_HACK
218 restoreSchedPolicy();
219#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220 return NO_ERROR;
221 } break;
Dave Sparks0f9a53d2009-11-23 16:51:15 -0800222 case EXTRACT_ALBUM_ART: {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
Dave Sparks0f9a53d2009-11-23 16:51:15 -0800224#ifndef DISABLE_GROUP_SCHEDULE_HACK
225 setSchedPolicy(data);
226#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227 sp<IMemory> albumArt = extractAlbumArt();
228 if (albumArt != 0) { // Don't send NULL across the binder interface
229 reply->writeInt32(NO_ERROR);
230 reply->writeStrongBinder(albumArt->asBinder());
231 } else {
232 reply->writeInt32(UNKNOWN_ERROR);
233 }
Dave Sparks0f9a53d2009-11-23 16:51:15 -0800234#ifndef DISABLE_GROUP_SCHEDULE_HACK
235 restoreSchedPolicy();
236#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237 return NO_ERROR;
238 } break;
239 case EXTRACT_METADATA: {
240 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
Dave Sparks0f9a53d2009-11-23 16:51:15 -0800241#ifndef DISABLE_GROUP_SCHEDULE_HACK
242 setSchedPolicy(data);
243#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800244 int keyCode = data.readInt32();
245 const char* value = extractMetadata(keyCode);
246 if (value != NULL) { // Don't send NULL across the binder interface
247 reply->writeInt32(NO_ERROR);
248 reply->writeCString(value);
249 } else {
250 reply->writeInt32(UNKNOWN_ERROR);
251 }
Dave Sparks0f9a53d2009-11-23 16:51:15 -0800252#ifndef DISABLE_GROUP_SCHEDULE_HACK
253 restoreSchedPolicy();
254#endif
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 return NO_ERROR;
256 } break;
257 default:
258 return BBinder::onTransact(code, data, reply, flags);
259 }
260}
261
262// ----------------------------------------------------------------------------
263
264}; // namespace android