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