1 /* 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 //#define LOG_NDEBUG 0 19 #define LOG_TAG "MediaRecorder" 20 21 #include <inttypes.h> 22 23 #include <utils/Log.h> 24 #include <media/mediarecorder.h> 25 #include <binder/IServiceManager.h> 26 #include <utils/String8.h> 27 #include <media/IMediaPlayerService.h> 28 #include <media/IMediaRecorder.h> 29 #include <media/mediaplayer.h> // for MEDIA_ERROR_SERVER_DIED 30 #include <gui/IGraphicBufferProducer.h> 31 32 namespace android { 33 34 status_t MediaRecorder::setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy) 35 { 36 ALOGV("setCamera(%p,%p)", camera.get(), proxy.get()); 37 if (mMediaRecorder == NULL) { 38 ALOGE("media recorder is not initialized yet"); 39 return INVALID_OPERATION; 40 } 41 if (!(mCurrentState & MEDIA_RECORDER_IDLE)) { 42 ALOGE("setCamera called in an invalid state(%d)", mCurrentState); 43 return INVALID_OPERATION; 44 } 45 46 status_t ret = mMediaRecorder->setCamera(camera, proxy); 47 if (OK != ret) { 48 ALOGV("setCamera failed: %d", ret); 49 mCurrentState = MEDIA_RECORDER_ERROR; 50 return ret; 51 } 52 return ret; 53 } 54 55 status_t MediaRecorder::setPreviewSurface(const sp<IGraphicBufferProducer>& surface) 56 { 57 ALOGV("setPreviewSurface(%p)", surface.get()); 58 if (mMediaRecorder == NULL) { 59 ALOGE("media recorder is not initialized yet"); 60 return INVALID_OPERATION; 61 } 62 if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { 63 ALOGE("setPreviewSurface called in an invalid state(%d)", mCurrentState); 64 return INVALID_OPERATION; 65 } 66 if (!mIsVideoSourceSet) { 67 ALOGE("try to set preview surface without setting the video source first"); 68 return INVALID_OPERATION; 69 } 70 71 status_t ret = mMediaRecorder->setPreviewSurface(surface); 72 if (OK != ret) { 73 ALOGV("setPreviewSurface failed: %d", ret); 74 mCurrentState = MEDIA_RECORDER_ERROR; 75 return ret; 76 } 77 return ret; 78 } 79 80 status_t MediaRecorder::init() 81 { 82 ALOGV("init"); 83 if (mMediaRecorder == NULL) { 84 ALOGE("media recorder is not initialized yet"); 85 return INVALID_OPERATION; 86 } 87 if (!(mCurrentState & MEDIA_RECORDER_IDLE)) { 88 ALOGE("init called in an invalid state(%d)", mCurrentState); 89 return INVALID_OPERATION; 90 } 91 92 status_t ret = mMediaRecorder->init(); 93 if (OK != ret) { 94 ALOGV("init failed: %d", ret); 95 mCurrentState = MEDIA_RECORDER_ERROR; 96 return ret; 97 } 98 99 ret = mMediaRecorder->setListener(this); 100 if (OK != ret) { 101 ALOGV("setListener failed: %d", ret); 102 mCurrentState = MEDIA_RECORDER_ERROR; 103 return ret; 104 } 105 106 mCurrentState = MEDIA_RECORDER_INITIALIZED; 107 return ret; 108 } 109 110 status_t MediaRecorder::setVideoSource(int vs) 111 { 112 ALOGV("setVideoSource(%d)", vs); 113 if (mMediaRecorder == NULL) { 114 ALOGE("media recorder is not initialized yet"); 115 return INVALID_OPERATION; 116 } 117 if (mIsVideoSourceSet) { 118 ALOGE("video source has already been set"); 119 return INVALID_OPERATION; 120 } 121 if (mCurrentState & MEDIA_RECORDER_IDLE) { 122 ALOGV("Call init() since the media recorder is not initialized yet"); 123 status_t ret = init(); 124 if (OK != ret) { 125 return ret; 126 } 127 } 128 if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) { 129 ALOGE("setVideoSource called in an invalid state(%d)", mCurrentState); 130 return INVALID_OPERATION; 131 } 132 133 // following call is made over the Binder Interface 134 status_t ret = mMediaRecorder->setVideoSource(vs); 135 136 if (OK != ret) { 137 ALOGV("setVideoSource failed: %d", ret); 138 mCurrentState = MEDIA_RECORDER_ERROR; 139 return ret; 140 } 141 mIsVideoSourceSet = true; 142 return ret; 143 } 144 145 status_t MediaRecorder::setAudioSource(int as) 146 { 147 ALOGV("setAudioSource(%d)", as); 148 if (mMediaRecorder == NULL) { 149 ALOGE("media recorder is not initialized yet"); 150 return INVALID_OPERATION; 151 } 152 if (mCurrentState & MEDIA_RECORDER_IDLE) { 153 ALOGV("Call init() since the media recorder is not initialized yet"); 154 status_t ret = init(); 155 if (OK != ret) { 156 return ret; 157 } 158 } 159 if (mIsAudioSourceSet) { 160 ALOGE("audio source has already been set"); 161 return INVALID_OPERATION; 162 } 163 if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) { 164 ALOGE("setAudioSource called in an invalid state(%d)", mCurrentState); 165 return INVALID_OPERATION; 166 } 167 168 status_t ret = mMediaRecorder->setAudioSource(as); 169 if (OK != ret) { 170 ALOGV("setAudioSource failed: %d", ret); 171 mCurrentState = MEDIA_RECORDER_ERROR; 172 return ret; 173 } 174 mIsAudioSourceSet = true; 175 return ret; 176 } 177 178 status_t MediaRecorder::setOutputFormat(int of) 179 { 180 ALOGV("setOutputFormat(%d)", of); 181 if (mMediaRecorder == NULL) { 182 ALOGE("media recorder is not initialized yet"); 183 return INVALID_OPERATION; 184 } 185 if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) { 186 ALOGE("setOutputFormat called in an invalid state: %d", mCurrentState); 187 return INVALID_OPERATION; 188 } 189 if (mIsVideoSourceSet 190 && of >= OUTPUT_FORMAT_AUDIO_ONLY_START //first non-video output format 191 && of < OUTPUT_FORMAT_AUDIO_ONLY_END) { 192 ALOGE("output format (%d) is meant for audio recording only" 193 " and incompatible with video recording", of); 194 return INVALID_OPERATION; 195 } 196 197 status_t ret = mMediaRecorder->setOutputFormat(of); 198 if (OK != ret) { 199 ALOGE("setOutputFormat failed: %d", ret); 200 mCurrentState = MEDIA_RECORDER_ERROR; 201 return ret; 202 } 203 mCurrentState = MEDIA_RECORDER_DATASOURCE_CONFIGURED; 204 return ret; 205 } 206 207 status_t MediaRecorder::setVideoEncoder(int ve) 208 { 209 ALOGV("setVideoEncoder(%d)", ve); 210 if (mMediaRecorder == NULL) { 211 ALOGE("media recorder is not initialized yet"); 212 return INVALID_OPERATION; 213 } 214 if (!mIsVideoSourceSet) { 215 ALOGE("try to set the video encoder without setting the video source first"); 216 return INVALID_OPERATION; 217 } 218 if (mIsVideoEncoderSet) { 219 ALOGE("video encoder has already been set"); 220 return INVALID_OPERATION; 221 } 222 if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { 223 ALOGE("setVideoEncoder called in an invalid state(%d)", mCurrentState); 224 return INVALID_OPERATION; 225 } 226 227 status_t ret = mMediaRecorder->setVideoEncoder(ve); 228 if (OK != ret) { 229 ALOGV("setVideoEncoder failed: %d", ret); 230 mCurrentState = MEDIA_RECORDER_ERROR; 231 return ret; 232 } 233 mIsVideoEncoderSet = true; 234 return ret; 235 } 236 237 status_t MediaRecorder::setAudioEncoder(int ae) 238 { 239 ALOGV("setAudioEncoder(%d)", ae); 240 if (mMediaRecorder == NULL) { 241 ALOGE("media recorder is not initialized yet"); 242 return INVALID_OPERATION; 243 } 244 if (!mIsAudioSourceSet) { 245 ALOGE("try to set the audio encoder without setting the audio source first"); 246 return INVALID_OPERATION; 247 } 248 if (mIsAudioEncoderSet) { 249 ALOGE("audio encoder has already been set"); 250 return INVALID_OPERATION; 251 } 252 if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { 253 ALOGE("setAudioEncoder called in an invalid state(%d)", mCurrentState); 254 return INVALID_OPERATION; 255 } 256 257 status_t ret = mMediaRecorder->setAudioEncoder(ae); 258 if (OK != ret) { 259 ALOGV("setAudioEncoder failed: %d", ret); 260 mCurrentState = MEDIA_RECORDER_ERROR; 261 return ret; 262 } 263 mIsAudioEncoderSet = true; 264 return ret; 265 } 266 267 status_t MediaRecorder::setOutputFile(const char* path) 268 { 269 ALOGV("setOutputFile(%s)", path); 270 if (mMediaRecorder == NULL) { 271 ALOGE("media recorder is not initialized yet"); 272 return INVALID_OPERATION; 273 } 274 if (mIsOutputFileSet) { 275 ALOGE("output file has already been set"); 276 return INVALID_OPERATION; 277 } 278 if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { 279 ALOGE("setOutputFile called in an invalid state(%d)", mCurrentState); 280 return INVALID_OPERATION; 281 } 282 283 status_t ret = mMediaRecorder->setOutputFile(path); 284 if (OK != ret) { 285 ALOGV("setOutputFile failed: %d", ret); 286 mCurrentState = MEDIA_RECORDER_ERROR; 287 return ret; 288 } 289 mIsOutputFileSet = true; 290 return ret; 291 } 292 293 status_t MediaRecorder::setOutputFile(int fd, int64_t offset, int64_t length) 294 { 295 ALOGV("setOutputFile(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length); 296 if (mMediaRecorder == NULL) { 297 ALOGE("media recorder is not initialized yet"); 298 return INVALID_OPERATION; 299 } 300 if (mIsOutputFileSet) { 301 ALOGE("output file has already been set"); 302 return INVALID_OPERATION; 303 } 304 if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { 305 ALOGE("setOutputFile called in an invalid state(%d)", mCurrentState); 306 return INVALID_OPERATION; 307 } 308 309 // It appears that if an invalid file descriptor is passed through 310 // binder calls, the server-side of the inter-process function call 311 // is skipped. As a result, the check at the server-side to catch 312 // the invalid file descritpor never gets invoked. This is to workaround 313 // this issue by checking the file descriptor first before passing 314 // it through binder call. 315 if (fd < 0) { 316 ALOGE("Invalid file descriptor: %d", fd); 317 return BAD_VALUE; 318 } 319 320 status_t ret = mMediaRecorder->setOutputFile(fd, offset, length); 321 if (OK != ret) { 322 ALOGV("setOutputFile failed: %d", ret); 323 mCurrentState = MEDIA_RECORDER_ERROR; 324 return ret; 325 } 326 mIsOutputFileSet = true; 327 return ret; 328 } 329 330 status_t MediaRecorder::setVideoSize(int width, int height) 331 { 332 ALOGV("setVideoSize(%d, %d)", width, height); 333 if (mMediaRecorder == NULL) { 334 ALOGE("media recorder is not initialized yet"); 335 return INVALID_OPERATION; 336 } 337 if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { 338 ALOGE("setVideoSize called in an invalid state: %d", mCurrentState); 339 return INVALID_OPERATION; 340 } 341 if (!mIsVideoSourceSet) { 342 ALOGE("Cannot set video size without setting video source first"); 343 return INVALID_OPERATION; 344 } 345 346 status_t ret = mMediaRecorder->setVideoSize(width, height); 347 if (OK != ret) { 348 ALOGE("setVideoSize failed: %d", ret); 349 mCurrentState = MEDIA_RECORDER_ERROR; 350 return ret; 351 } 352 353 return ret; 354 } 355 356 // Query a SurfaceMediaSurface through the Mediaserver, over the 357 // binder interface. This is used by the Filter Framework (MediaEncoder) 358 // to get an <IGraphicBufferProducer> object to hook up to ANativeWindow. 359 sp<IGraphicBufferProducer> MediaRecorder:: 360 querySurfaceMediaSourceFromMediaServer() 361 { 362 Mutex::Autolock _l(mLock); 363 mSurfaceMediaSource = 364 mMediaRecorder->querySurfaceMediaSource(); 365 if (mSurfaceMediaSource == NULL) { 366 ALOGE("SurfaceMediaSource could not be initialized!"); 367 } 368 return mSurfaceMediaSource; 369 } 370 371 372 373 status_t MediaRecorder::setVideoFrameRate(int frames_per_second) 374 { 375 ALOGV("setVideoFrameRate(%d)", frames_per_second); 376 if (mMediaRecorder == NULL) { 377 ALOGE("media recorder is not initialized yet"); 378 return INVALID_OPERATION; 379 } 380 if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { 381 ALOGE("setVideoFrameRate called in an invalid state: %d", mCurrentState); 382 return INVALID_OPERATION; 383 } 384 if (!mIsVideoSourceSet) { 385 ALOGE("Cannot set video frame rate without setting video source first"); 386 return INVALID_OPERATION; 387 } 388 389 status_t ret = mMediaRecorder->setVideoFrameRate(frames_per_second); 390 if (OK != ret) { 391 ALOGE("setVideoFrameRate failed: %d", ret); 392 mCurrentState = MEDIA_RECORDER_ERROR; 393 return ret; 394 } 395 return ret; 396 } 397 398 status_t MediaRecorder::setParameters(const String8& params) { 399 ALOGV("setParameters(%s)", params.string()); 400 if (mMediaRecorder == NULL) { 401 ALOGE("media recorder is not initialized yet"); 402 return INVALID_OPERATION; 403 } 404 405 bool isInvalidState = (mCurrentState & 406 (MEDIA_RECORDER_PREPARED | 407 MEDIA_RECORDER_RECORDING | 408 MEDIA_RECORDER_ERROR)); 409 if (isInvalidState) { 410 ALOGE("setParameters is called in an invalid state: %d", mCurrentState); 411 return INVALID_OPERATION; 412 } 413 414 status_t ret = mMediaRecorder->setParameters(params); 415 if (OK != ret) { 416 ALOGE("setParameters(%s) failed: %d", params.string(), ret); 417 // Do not change our current state to MEDIA_RECORDER_ERROR, failures 418 // of the only currently supported parameters, "max-duration" and 419 // "max-filesize" are _not_ fatal. 420 } 421 422 return ret; 423 } 424 425 status_t MediaRecorder::prepare() 426 { 427 ALOGV("prepare"); 428 if (mMediaRecorder == NULL) { 429 ALOGE("media recorder is not initialized yet"); 430 return INVALID_OPERATION; 431 } 432 if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { 433 ALOGE("prepare called in an invalid state: %d", mCurrentState); 434 return INVALID_OPERATION; 435 } 436 if (mIsAudioSourceSet != mIsAudioEncoderSet) { 437 if (mIsAudioSourceSet) { 438 ALOGE("audio source is set, but audio encoder is not set"); 439 } else { // must not happen, since setAudioEncoder checks this already 440 ALOGE("audio encoder is set, but audio source is not set"); 441 } 442 return INVALID_OPERATION; 443 } 444 445 if (mIsVideoSourceSet != mIsVideoEncoderSet) { 446 if (mIsVideoSourceSet) { 447 ALOGE("video source is set, but video encoder is not set"); 448 } else { // must not happen, since setVideoEncoder checks this already 449 ALOGE("video encoder is set, but video source is not set"); 450 } 451 return INVALID_OPERATION; 452 } 453 454 status_t ret = mMediaRecorder->prepare(); 455 if (OK != ret) { 456 ALOGE("prepare failed: %d", ret); 457 mCurrentState = MEDIA_RECORDER_ERROR; 458 return ret; 459 } 460 mCurrentState = MEDIA_RECORDER_PREPARED; 461 return ret; 462 } 463 464 status_t MediaRecorder::getMaxAmplitude(int* max) 465 { 466 ALOGV("getMaxAmplitude"); 467 if (mMediaRecorder == NULL) { 468 ALOGE("media recorder is not initialized yet"); 469 return INVALID_OPERATION; 470 } 471 if (mCurrentState & MEDIA_RECORDER_ERROR) { 472 ALOGE("getMaxAmplitude called in an invalid state: %d", mCurrentState); 473 return INVALID_OPERATION; 474 } 475 476 status_t ret = mMediaRecorder->getMaxAmplitude(max); 477 if (OK != ret) { 478 ALOGE("getMaxAmplitude failed: %d", ret); 479 mCurrentState = MEDIA_RECORDER_ERROR; 480 return ret; 481 } 482 return ret; 483 } 484 485 status_t MediaRecorder::start() 486 { 487 ALOGV("start"); 488 if (mMediaRecorder == NULL) { 489 ALOGE("media recorder is not initialized yet"); 490 return INVALID_OPERATION; 491 } 492 if (!(mCurrentState & MEDIA_RECORDER_PREPARED)) { 493 ALOGE("start called in an invalid state: %d", mCurrentState); 494 return INVALID_OPERATION; 495 } 496 497 status_t ret = mMediaRecorder->start(); 498 if (OK != ret) { 499 ALOGE("start failed: %d", ret); 500 mCurrentState = MEDIA_RECORDER_ERROR; 501 return ret; 502 } 503 mCurrentState = MEDIA_RECORDER_RECORDING; 504 return ret; 505 } 506 507 status_t MediaRecorder::stop() 508 { 509 ALOGV("stop"); 510 if (mMediaRecorder == NULL) { 511 ALOGE("media recorder is not initialized yet"); 512 return INVALID_OPERATION; 513 } 514 if (!(mCurrentState & MEDIA_RECORDER_RECORDING)) { 515 ALOGE("stop called in an invalid state: %d", mCurrentState); 516 return INVALID_OPERATION; 517 } 518 519 status_t ret = mMediaRecorder->stop(); 520 if (OK != ret) { 521 ALOGE("stop failed: %d", ret); 522 mCurrentState = MEDIA_RECORDER_ERROR; 523 return ret; 524 } 525 526 // FIXME: 527 // stop and reset are semantically different. 528 // We treat them the same for now, and will change this in the future. 529 doCleanUp(); 530 mCurrentState = MEDIA_RECORDER_IDLE; 531 return ret; 532 } 533 534 // Reset should be OK in any state 535 status_t MediaRecorder::reset() 536 { 537 ALOGV("reset"); 538 if (mMediaRecorder == NULL) { 539 ALOGE("media recorder is not initialized yet"); 540 return INVALID_OPERATION; 541 } 542 543 doCleanUp(); 544 status_t ret = UNKNOWN_ERROR; 545 switch (mCurrentState) { 546 case MEDIA_RECORDER_IDLE: 547 ret = OK; 548 break; 549 550 case MEDIA_RECORDER_RECORDING: 551 case MEDIA_RECORDER_DATASOURCE_CONFIGURED: 552 case MEDIA_RECORDER_PREPARED: 553 case MEDIA_RECORDER_ERROR: { 554 ret = doReset(); 555 if (OK != ret) { 556 return ret; // No need to continue 557 } 558 } // Intentional fall through 559 case MEDIA_RECORDER_INITIALIZED: 560 ret = close(); 561 break; 562 563 default: { 564 ALOGE("Unexpected non-existing state: %d", mCurrentState); 565 break; 566 } 567 } 568 return ret; 569 } 570 571 status_t MediaRecorder::close() 572 { 573 ALOGV("close"); 574 if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) { 575 ALOGE("close called in an invalid state: %d", mCurrentState); 576 return INVALID_OPERATION; 577 } 578 status_t ret = mMediaRecorder->close(); 579 if (OK != ret) { 580 ALOGE("close failed: %d", ret); 581 mCurrentState = MEDIA_RECORDER_ERROR; 582 return UNKNOWN_ERROR; 583 } else { 584 mCurrentState = MEDIA_RECORDER_IDLE; 585 } 586 return ret; 587 } 588 589 status_t MediaRecorder::doReset() 590 { 591 ALOGV("doReset"); 592 status_t ret = mMediaRecorder->reset(); 593 if (OK != ret) { 594 ALOGE("doReset failed: %d", ret); 595 mCurrentState = MEDIA_RECORDER_ERROR; 596 return ret; 597 } else { 598 mCurrentState = MEDIA_RECORDER_INITIALIZED; 599 } 600 return ret; 601 } 602 603 void MediaRecorder::doCleanUp() 604 { 605 ALOGV("doCleanUp"); 606 mIsAudioSourceSet = false; 607 mIsVideoSourceSet = false; 608 mIsAudioEncoderSet = false; 609 mIsVideoEncoderSet = false; 610 mIsOutputFileSet = false; 611 } 612 613 // Release should be OK in any state 614 status_t MediaRecorder::release() 615 { 616 ALOGV("release"); 617 if (mMediaRecorder != NULL) { 618 return mMediaRecorder->release(); 619 } 620 return INVALID_OPERATION; 621 } 622 623 MediaRecorder::MediaRecorder() : mSurfaceMediaSource(NULL) 624 { 625 ALOGV("constructor"); 626 627 const sp<IMediaPlayerService>& service(getMediaPlayerService()); 628 if (service != NULL) { 629 mMediaRecorder = service->createMediaRecorder(); 630 } 631 if (mMediaRecorder != NULL) { 632 mCurrentState = MEDIA_RECORDER_IDLE; 633 } 634 635 636 doCleanUp(); 637 } 638 639 status_t MediaRecorder::initCheck() 640 { 641 return mMediaRecorder != 0 ? NO_ERROR : NO_INIT; 642 } 643 644 MediaRecorder::~MediaRecorder() 645 { 646 ALOGV("destructor"); 647 if (mMediaRecorder != NULL) { 648 mMediaRecorder.clear(); 649 } 650 651 if (mSurfaceMediaSource != NULL) { 652 mSurfaceMediaSource.clear(); 653 } 654 } 655 656 status_t MediaRecorder::setListener(const sp<MediaRecorderListener>& listener) 657 { 658 ALOGV("setListener"); 659 Mutex::Autolock _l(mLock); 660 mListener = listener; 661 662 return NO_ERROR; 663 } 664 665 status_t MediaRecorder::setClientName(const String16& clientName) 666 { 667 ALOGV("setClientName"); 668 if (mMediaRecorder == NULL) { 669 ALOGE("media recorder is not initialized yet"); 670 return INVALID_OPERATION; 671 } 672 bool isInvalidState = (mCurrentState & 673 (MEDIA_RECORDER_PREPARED | 674 MEDIA_RECORDER_RECORDING | 675 MEDIA_RECORDER_ERROR)); 676 if (isInvalidState) { 677 ALOGE("setClientName is called in an invalid state: %d", mCurrentState); 678 return INVALID_OPERATION; 679 } 680 681 mMediaRecorder->setClientName(clientName); 682 683 return NO_ERROR; 684 } 685 686 void MediaRecorder::notify(int msg, int ext1, int ext2) 687 { 688 ALOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2); 689 690 sp<MediaRecorderListener> listener; 691 mLock.lock(); 692 listener = mListener; 693 mLock.unlock(); 694 695 if (listener != NULL) { 696 Mutex::Autolock _l(mNotifyLock); 697 ALOGV("callback application"); 698 listener->notify(msg, ext1, ext2); 699 ALOGV("back from callback"); 700 } 701 } 702 703 void MediaRecorder::died() 704 { 705 ALOGV("died"); 706 notify(MEDIA_RECORDER_EVENT_ERROR, MEDIA_ERROR_SERVER_DIED, 0); 707 } 708 709 }; // namespace android 710