From d7ed649cfeff62680b8edb4cb86ce239116d8c8b Mon Sep 17 00:00:00 2001 From: Chong Zhang Date: Thu, 9 Apr 2015 22:34:38 -0700 Subject: MediaCodec: add DeathNotifier to BatteryNotifier make the battery notifier more robust bug: 20071299 Change-Id: I0ecfecc787c88ace26dba5e235aa0c345bcace6d --- media/libstagefright/MediaCodec.cpp | 84 ++++++++++++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 10 deletions(-) (limited to 'media') diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index 8186f63..55548f8 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -49,16 +49,31 @@ namespace android { struct MediaCodec::BatteryNotifier : public Singleton { BatteryNotifier(); + virtual ~BatteryNotifier(); void noteStartVideo(); void noteStopVideo(); void noteStartAudio(); void noteStopAudio(); + void onBatteryStatServiceDied(); private: + struct DeathNotifier : public IBinder::DeathRecipient { + DeathNotifier() {} + virtual void binderDied(const wp& /*who*/) { + BatteryNotifier::getInstance().onBatteryStatServiceDied(); + } + }; + + Mutex mLock; int32_t mVideoRefCount; int32_t mAudioRefCount; sp mBatteryStatService; + sp mDeathNotifier; + + sp getBatteryService_l(); + + DISALLOW_EVIL_CONSTRUCTORS(BatteryNotifier); }; ANDROID_SINGLETON_STATIC_INSTANCE(MediaCodec::BatteryNotifier) @@ -66,54 +81,103 @@ ANDROID_SINGLETON_STATIC_INSTANCE(MediaCodec::BatteryNotifier) MediaCodec::BatteryNotifier::BatteryNotifier() : mVideoRefCount(0), mAudioRefCount(0) { - // get battery service +} + +sp MediaCodec::BatteryNotifier::getBatteryService_l() { + if (mBatteryStatService != NULL) { + return mBatteryStatService; + } + // get battery service from service manager const sp sm(defaultServiceManager()); if (sm != NULL) { const String16 name("batterystats"); - mBatteryStatService = interface_cast(sm->getService(name)); + mBatteryStatService = + interface_cast(sm->getService(name)); if (mBatteryStatService == NULL) { ALOGE("batterystats service unavailable!"); + return NULL; + } + mDeathNotifier = new DeathNotifier(); + if (IInterface::asBinder(mBatteryStatService)-> + linkToDeath(mDeathNotifier) != OK) { + mBatteryStatService.clear(); + mDeathNotifier.clear(); + return NULL; } + // notify start now if media already started + if (mVideoRefCount > 0) { + mBatteryStatService->noteStartVideo(AID_MEDIA); + } + if (mAudioRefCount > 0) { + mBatteryStatService->noteStartAudio(AID_MEDIA); + } + } + return mBatteryStatService; +} + +MediaCodec::BatteryNotifier::~BatteryNotifier() { + if (mDeathNotifier != NULL) { + IInterface::asBinder(mBatteryStatService)-> + unlinkToDeath(mDeathNotifier); } } void MediaCodec::BatteryNotifier::noteStartVideo() { - if (mVideoRefCount == 0 && mBatteryStatService != NULL) { - mBatteryStatService->noteStartVideo(AID_MEDIA); + Mutex::Autolock _l(mLock); + sp batteryService = getBatteryService_l(); + if (mVideoRefCount == 0 && batteryService != NULL) { + batteryService->noteStartVideo(AID_MEDIA); } mVideoRefCount++; } void MediaCodec::BatteryNotifier::noteStopVideo() { + Mutex::Autolock _l(mLock); if (mVideoRefCount == 0) { ALOGW("BatteryNotifier::noteStop(): video refcount is broken!"); return; } mVideoRefCount--; - if (mVideoRefCount == 0 && mBatteryStatService != NULL) { - mBatteryStatService->noteStopVideo(AID_MEDIA); + sp batteryService = getBatteryService_l(); + if (mVideoRefCount == 0 && batteryService != NULL) { + batteryService->noteStopVideo(AID_MEDIA); } } void MediaCodec::BatteryNotifier::noteStartAudio() { - if (mAudioRefCount == 0 && mBatteryStatService != NULL) { - mBatteryStatService->noteStartAudio(AID_MEDIA); + Mutex::Autolock _l(mLock); + sp batteryService = getBatteryService_l(); + if (mAudioRefCount == 0 && batteryService != NULL) { + batteryService->noteStartAudio(AID_MEDIA); } mAudioRefCount++; } void MediaCodec::BatteryNotifier::noteStopAudio() { + Mutex::Autolock _l(mLock); if (mAudioRefCount == 0) { ALOGW("BatteryNotifier::noteStop(): audio refcount is broken!"); return; } mAudioRefCount--; - if (mAudioRefCount == 0 && mBatteryStatService != NULL) { - mBatteryStatService->noteStopAudio(AID_MEDIA); + sp batteryService = getBatteryService_l(); + if (mAudioRefCount == 0 && batteryService != NULL) { + batteryService->noteStopAudio(AID_MEDIA); } } + +void MediaCodec::BatteryNotifier::onBatteryStatServiceDied() { + Mutex::Autolock _l(mLock); + mBatteryStatService.clear(); + mDeathNotifier.clear(); + // Do not reset mVideoRefCount and mAudioRefCount here. The ref + // counting is independent of the battery service availability. + // We need this if battery service becomes available after media + // started. +} + // static sp MediaCodec::CreateByType( const sp &looper, const char *mime, bool encoder, status_t *err) { -- cgit v1.1