1 /* 2 ** 3 ** Copyright 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 <arpa/inet.h> 19 #include <stdint.h> 20 #include <sys/types.h> 21 22 #include <binder/Parcel.h> 23 24 #include <media/IMediaPlayer.h> 25 #include <media/IStreamSource.h> 26 27 #include <gui/ISurfaceTexture.h> 28 #include <utils/String8.h> 29 30 namespace android { 31 32 enum { 33 DISCONNECT = IBinder::FIRST_CALL_TRANSACTION, 34 SET_DATA_SOURCE_URL, 35 SET_DATA_SOURCE_FD, 36 SET_DATA_SOURCE_STREAM, 37 PREPARE_ASYNC, 38 START, 39 STOP, 40 IS_PLAYING, 41 PAUSE, 42 SEEK_TO, 43 GET_CURRENT_POSITION, 44 GET_DURATION, 45 RESET, 46 SET_AUDIO_STREAM_TYPE, 47 SET_LOOPING, 48 SET_VOLUME, 49 INVOKE, 50 SET_METADATA_FILTER, 51 GET_METADATA, 52 SET_AUX_EFFECT_SEND_LEVEL, 53 ATTACH_AUX_EFFECT, 54 SET_VIDEO_SURFACETEXTURE, 55 SET_PARAMETER, 56 GET_PARAMETER, 57 SET_RETRANSMIT_ENDPOINT, 58 SET_NEXT_PLAYER, 59 }; 60 61 class BpMediaPlayer: public BpInterface<IMediaPlayer> 62 { 63 public: 64 BpMediaPlayer(const sp<IBinder>& impl) 65 : BpInterface<IMediaPlayer>(impl) 66 { 67 } 68 69 // disconnect from media player service 70 void disconnect() 71 { 72 Parcel data, reply; 73 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 74 remote()->transact(DISCONNECT, data, &reply); 75 } 76 77 status_t setDataSource(const char* url, 78 const KeyedVector<String8, String8>* headers) 79 { 80 Parcel data, reply; 81 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 82 data.writeCString(url); 83 if (headers == NULL) { 84 data.writeInt32(0); 85 } else { 86 // serialize the headers 87 data.writeInt32(headers->size()); 88 for (size_t i = 0; i < headers->size(); ++i) { 89 data.writeString8(headers->keyAt(i)); 90 data.writeString8(headers->valueAt(i)); 91 } 92 } 93 remote()->transact(SET_DATA_SOURCE_URL, data, &reply); 94 return reply.readInt32(); 95 } 96 97 status_t setDataSource(int fd, int64_t offset, int64_t length) { 98 Parcel data, reply; 99 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 100 data.writeFileDescriptor(fd); 101 data.writeInt64(offset); 102 data.writeInt64(length); 103 remote()->transact(SET_DATA_SOURCE_FD, data, &reply); 104 return reply.readInt32(); 105 } 106 107 status_t setDataSource(const sp<IStreamSource> &source) { 108 Parcel data, reply; 109 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 110 data.writeStrongBinder(source->asBinder()); 111 remote()->transact(SET_DATA_SOURCE_STREAM, data, &reply); 112 return reply.readInt32(); 113 } 114 115 // pass the buffered ISurfaceTexture to the media player service 116 status_t setVideoSurfaceTexture(const sp<ISurfaceTexture>& surfaceTexture) 117 { 118 Parcel data, reply; 119 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 120 sp<IBinder> b(surfaceTexture->asBinder()); 121 data.writeStrongBinder(b); 122 remote()->transact(SET_VIDEO_SURFACETEXTURE, data, &reply); 123 return reply.readInt32(); 124 } 125 126 status_t prepareAsync() 127 { 128 Parcel data, reply; 129 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 130 remote()->transact(PREPARE_ASYNC, data, &reply); 131 return reply.readInt32(); 132 } 133 134 status_t start() 135 { 136 Parcel data, reply; 137 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 138 remote()->transact(START, data, &reply); 139 return reply.readInt32(); 140 } 141 142 status_t stop() 143 { 144 Parcel data, reply; 145 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 146 remote()->transact(STOP, data, &reply); 147 return reply.readInt32(); 148 } 149 150 status_t isPlaying(bool* state) 151 { 152 Parcel data, reply; 153 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 154 remote()->transact(IS_PLAYING, data, &reply); 155 *state = reply.readInt32(); 156 return reply.readInt32(); 157 } 158 159 status_t pause() 160 { 161 Parcel data, reply; 162 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 163 remote()->transact(PAUSE, data, &reply); 164 return reply.readInt32(); 165 } 166 167 status_t seekTo(int msec) 168 { 169 Parcel data, reply; 170 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 171 data.writeInt32(msec); 172 remote()->transact(SEEK_TO, data, &reply); 173 return reply.readInt32(); 174 } 175 176 status_t getCurrentPosition(int* msec) 177 { 178 Parcel data, reply; 179 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 180 remote()->transact(GET_CURRENT_POSITION, data, &reply); 181 *msec = reply.readInt32(); 182 return reply.readInt32(); 183 } 184 185 status_t getDuration(int* msec) 186 { 187 Parcel data, reply; 188 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 189 remote()->transact(GET_DURATION, data, &reply); 190 *msec = reply.readInt32(); 191 return reply.readInt32(); 192 } 193 194 status_t reset() 195 { 196 Parcel data, reply; 197 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 198 remote()->transact(RESET, data, &reply); 199 return reply.readInt32(); 200 } 201 202 status_t setAudioStreamType(audio_stream_type_t stream) 203 { 204 Parcel data, reply; 205 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 206 data.writeInt32((int32_t) stream); 207 remote()->transact(SET_AUDIO_STREAM_TYPE, data, &reply); 208 return reply.readInt32(); 209 } 210 211 status_t setLooping(int loop) 212 { 213 Parcel data, reply; 214 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 215 data.writeInt32(loop); 216 remote()->transact(SET_LOOPING, data, &reply); 217 return reply.readInt32(); 218 } 219 220 status_t setVolume(float leftVolume, float rightVolume) 221 { 222 Parcel data, reply; 223 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 224 data.writeFloat(leftVolume); 225 data.writeFloat(rightVolume); 226 remote()->transact(SET_VOLUME, data, &reply); 227 return reply.readInt32(); 228 } 229 230 status_t invoke(const Parcel& request, Parcel *reply) 231 { 232 // Avoid doing any extra copy. The interface descriptor should 233 // have been set by MediaPlayer.java. 234 return remote()->transact(INVOKE, request, reply); 235 } 236 237 status_t setMetadataFilter(const Parcel& request) 238 { 239 Parcel reply; 240 // Avoid doing any extra copy of the request. The interface 241 // descriptor should have been set by MediaPlayer.java. 242 remote()->transact(SET_METADATA_FILTER, request, &reply); 243 return reply.readInt32(); 244 } 245 246 status_t getMetadata(bool update_only, bool apply_filter, Parcel *reply) 247 { 248 Parcel request; 249 request.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 250 // TODO: Burning 2 ints for 2 boolean. Should probably use flags in an int here. 251 request.writeInt32(update_only); 252 request.writeInt32(apply_filter); 253 remote()->transact(GET_METADATA, request, reply); 254 return reply->readInt32(); 255 } 256 257 status_t setAuxEffectSendLevel(float level) 258 { 259 Parcel data, reply; 260 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 261 data.writeFloat(level); 262 remote()->transact(SET_AUX_EFFECT_SEND_LEVEL, data, &reply); 263 return reply.readInt32(); 264 } 265 266 status_t attachAuxEffect(int effectId) 267 { 268 Parcel data, reply; 269 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 270 data.writeInt32(effectId); 271 remote()->transact(ATTACH_AUX_EFFECT, data, &reply); 272 return reply.readInt32(); 273 } 274 275 status_t setParameter(int key, const Parcel& request) 276 { 277 Parcel data, reply; 278 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 279 data.writeInt32(key); 280 if (request.dataSize() > 0) { 281 data.appendFrom(const_cast<Parcel *>(&request), 0, request.dataSize()); 282 } 283 remote()->transact(SET_PARAMETER, data, &reply); 284 return reply.readInt32(); 285 } 286 287 status_t getParameter(int key, Parcel *reply) 288 { 289 Parcel data; 290 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 291 data.writeInt32(key); 292 return remote()->transact(GET_PARAMETER, data, reply); 293 } 294 295 status_t setRetransmitEndpoint(const struct sockaddr_in* endpoint) { 296 Parcel data, reply; 297 status_t err; 298 299 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 300 if (NULL != endpoint) { 301 data.writeInt32(sizeof(*endpoint)); 302 data.write(endpoint, sizeof(*endpoint)); 303 } else { 304 data.writeInt32(0); 305 } 306 307 err = remote()->transact(SET_RETRANSMIT_ENDPOINT, data, &reply); 308 if (OK != err) { 309 return err; 310 } 311 return reply.readInt32(); 312 } 313 314 status_t setNextPlayer(const sp<IMediaPlayer>& player) { 315 Parcel data, reply; 316 data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); 317 sp<IBinder> b(player->asBinder()); 318 data.writeStrongBinder(b); 319 remote()->transact(SET_NEXT_PLAYER, data, &reply); 320 return reply.readInt32(); 321 } 322 }; 323 324 IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer"); 325 326 // ---------------------------------------------------------------------- 327 328 status_t BnMediaPlayer::onTransact( 329 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 330 { 331 switch (code) { 332 case DISCONNECT: { 333 CHECK_INTERFACE(IMediaPlayer, data, reply); 334 disconnect(); 335 return NO_ERROR; 336 } break; 337 case SET_DATA_SOURCE_URL: { 338 CHECK_INTERFACE(IMediaPlayer, data, reply); 339 const char* url = data.readCString(); 340 KeyedVector<String8, String8> headers; 341 int32_t numHeaders = data.readInt32(); 342 for (int i = 0; i < numHeaders; ++i) { 343 String8 key = data.readString8(); 344 String8 value = data.readString8(); 345 headers.add(key, value); 346 } 347 reply->writeInt32(setDataSource(url, numHeaders > 0 ? &headers : NULL)); 348 return NO_ERROR; 349 } break; 350 case SET_DATA_SOURCE_FD: { 351 CHECK_INTERFACE(IMediaPlayer, data, reply); 352 int fd = data.readFileDescriptor(); 353 int64_t offset = data.readInt64(); 354 int64_t length = data.readInt64(); 355 reply->writeInt32(setDataSource(fd, offset, length)); 356 return NO_ERROR; 357 } 358 case SET_DATA_SOURCE_STREAM: { 359 CHECK_INTERFACE(IMediaPlayer, data, reply); 360 sp<IStreamSource> source = 361 interface_cast<IStreamSource>(data.readStrongBinder()); 362 reply->writeInt32(setDataSource(source)); 363 return NO_ERROR; 364 } 365 case SET_VIDEO_SURFACETEXTURE: { 366 CHECK_INTERFACE(IMediaPlayer, data, reply); 367 sp<ISurfaceTexture> surfaceTexture = 368 interface_cast<ISurfaceTexture>(data.readStrongBinder()); 369 reply->writeInt32(setVideoSurfaceTexture(surfaceTexture)); 370 return NO_ERROR; 371 } break; 372 case PREPARE_ASYNC: { 373 CHECK_INTERFACE(IMediaPlayer, data, reply); 374 reply->writeInt32(prepareAsync()); 375 return NO_ERROR; 376 } break; 377 case START: { 378 CHECK_INTERFACE(IMediaPlayer, data, reply); 379 reply->writeInt32(start()); 380 return NO_ERROR; 381 } break; 382 case STOP: { 383 CHECK_INTERFACE(IMediaPlayer, data, reply); 384 reply->writeInt32(stop()); 385 return NO_ERROR; 386 } break; 387 case IS_PLAYING: { 388 CHECK_INTERFACE(IMediaPlayer, data, reply); 389 bool state; 390 status_t ret = isPlaying(&state); 391 reply->writeInt32(state); 392 reply->writeInt32(ret); 393 return NO_ERROR; 394 } break; 395 case PAUSE: { 396 CHECK_INTERFACE(IMediaPlayer, data, reply); 397 reply->writeInt32(pause()); 398 return NO_ERROR; 399 } break; 400 case SEEK_TO: { 401 CHECK_INTERFACE(IMediaPlayer, data, reply); 402 reply->writeInt32(seekTo(data.readInt32())); 403 return NO_ERROR; 404 } break; 405 case GET_CURRENT_POSITION: { 406 CHECK_INTERFACE(IMediaPlayer, data, reply); 407 int msec; 408 status_t ret = getCurrentPosition(&msec); 409 reply->writeInt32(msec); 410 reply->writeInt32(ret); 411 return NO_ERROR; 412 } break; 413 case GET_DURATION: { 414 CHECK_INTERFACE(IMediaPlayer, data, reply); 415 int msec; 416 status_t ret = getDuration(&msec); 417 reply->writeInt32(msec); 418 reply->writeInt32(ret); 419 return NO_ERROR; 420 } break; 421 case RESET: { 422 CHECK_INTERFACE(IMediaPlayer, data, reply); 423 reply->writeInt32(reset()); 424 return NO_ERROR; 425 } break; 426 case SET_AUDIO_STREAM_TYPE: { 427 CHECK_INTERFACE(IMediaPlayer, data, reply); 428 reply->writeInt32(setAudioStreamType((audio_stream_type_t) data.readInt32())); 429 return NO_ERROR; 430 } break; 431 case SET_LOOPING: { 432 CHECK_INTERFACE(IMediaPlayer, data, reply); 433 reply->writeInt32(setLooping(data.readInt32())); 434 return NO_ERROR; 435 } break; 436 case SET_VOLUME: { 437 CHECK_INTERFACE(IMediaPlayer, data, reply); 438 float leftVolume = data.readFloat(); 439 float rightVolume = data.readFloat(); 440 reply->writeInt32(setVolume(leftVolume, rightVolume)); 441 return NO_ERROR; 442 } break; 443 case INVOKE: { 444 CHECK_INTERFACE(IMediaPlayer, data, reply); 445 status_t result = invoke(data, reply); 446 return result; 447 } break; 448 case SET_METADATA_FILTER: { 449 CHECK_INTERFACE(IMediaPlayer, data, reply); 450 reply->writeInt32(setMetadataFilter(data)); 451 return NO_ERROR; 452 } break; 453 case GET_METADATA: { 454 CHECK_INTERFACE(IMediaPlayer, data, reply); 455 bool update_only = static_cast<bool>(data.readInt32()); 456 bool apply_filter = static_cast<bool>(data.readInt32()); 457 const status_t retcode = getMetadata(update_only, apply_filter, reply); 458 reply->setDataPosition(0); 459 reply->writeInt32(retcode); 460 reply->setDataPosition(0); 461 return NO_ERROR; 462 } break; 463 case SET_AUX_EFFECT_SEND_LEVEL: { 464 CHECK_INTERFACE(IMediaPlayer, data, reply); 465 reply->writeInt32(setAuxEffectSendLevel(data.readFloat())); 466 return NO_ERROR; 467 } break; 468 case ATTACH_AUX_EFFECT: { 469 CHECK_INTERFACE(IMediaPlayer, data, reply); 470 reply->writeInt32(attachAuxEffect(data.readInt32())); 471 return NO_ERROR; 472 } break; 473 case SET_PARAMETER: { 474 CHECK_INTERFACE(IMediaPlayer, data, reply); 475 int key = data.readInt32(); 476 477 Parcel request; 478 if (data.dataAvail() > 0) { 479 request.appendFrom( 480 const_cast<Parcel *>(&data), data.dataPosition(), data.dataAvail()); 481 } 482 request.setDataPosition(0); 483 reply->writeInt32(setParameter(key, request)); 484 return NO_ERROR; 485 } break; 486 case GET_PARAMETER: { 487 CHECK_INTERFACE(IMediaPlayer, data, reply); 488 return getParameter(data.readInt32(), reply); 489 } break; 490 case SET_RETRANSMIT_ENDPOINT: { 491 CHECK_INTERFACE(IMediaPlayer, data, reply); 492 493 struct sockaddr_in endpoint; 494 int amt = data.readInt32(); 495 if (amt == sizeof(endpoint)) { 496 data.read(&endpoint, sizeof(struct sockaddr_in)); 497 reply->writeInt32(setRetransmitEndpoint(&endpoint)); 498 } else { 499 reply->writeInt32(setRetransmitEndpoint(NULL)); 500 } 501 return NO_ERROR; 502 } break; 503 case SET_NEXT_PLAYER: { 504 CHECK_INTERFACE(IMediaPlayer, data, reply); 505 reply->writeInt32(setNextPlayer(interface_cast<IMediaPlayer>(data.readStrongBinder()))); 506 return NO_ERROR; 507 } break; 508 default: 509 return BBinder::onTransact(code, data, reply, flags); 510 } 511 } 512 513 // ---------------------------------------------------------------------------- 514 515 }; // namespace android 516