| /* |
| * Copyright 2015, The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #define LOG_TAG "BatteryNotifier" |
| //#define LOG_NDEBUG 0 |
| |
| #include "include/mediautils/BatteryNotifier.h" |
| |
| #include <binder/IServiceManager.h> |
| #include <utils/Log.h> |
| #include <private/android_filesystem_config.h> |
| |
| namespace android { |
| |
| void BatteryNotifier::DeathNotifier::binderDied(const wp<IBinder>& /*who*/) { |
| BatteryNotifier::getInstance().onBatteryStatServiceDied(); |
| } |
| |
| BatteryNotifier::BatteryNotifier() {} |
| |
| BatteryNotifier::~BatteryNotifier() { |
| Mutex::Autolock _l(mLock); |
| if (mDeathNotifier != nullptr) { |
| IInterface::asBinder(mBatteryStatService)->unlinkToDeath(mDeathNotifier); |
| } |
| } |
| |
| void BatteryNotifier::noteStartVideo(uid_t uid) { |
| Mutex::Autolock _l(mLock); |
| sp<IBatteryStats> batteryService = getBatteryService_l(); |
| if (mVideoRefCounts[uid] == 0 && batteryService != nullptr) { |
| batteryService->noteStartVideo(uid); |
| } |
| mVideoRefCounts[uid]++; |
| } |
| |
| void BatteryNotifier::noteStopVideo(uid_t uid) { |
| Mutex::Autolock _l(mLock); |
| if (mVideoRefCounts.find(uid) == mVideoRefCounts.end()) { |
| ALOGW("%s: video refcount is broken for uid(%d).", __FUNCTION__, (int)uid); |
| return; |
| } |
| |
| sp<IBatteryStats> batteryService = getBatteryService_l(); |
| |
| mVideoRefCounts[uid]--; |
| if (mVideoRefCounts[uid] == 0) { |
| if (batteryService != nullptr) { |
| batteryService->noteStopVideo(uid); |
| } |
| mVideoRefCounts.erase(uid); |
| } |
| } |
| |
| void BatteryNotifier::noteResetVideo() { |
| Mutex::Autolock _l(mLock); |
| sp<IBatteryStats> batteryService = getBatteryService_l(); |
| mVideoRefCounts.clear(); |
| if (batteryService != nullptr) { |
| batteryService->noteResetVideo(); |
| } |
| } |
| |
| void BatteryNotifier::noteStartAudio(uid_t uid) { |
| Mutex::Autolock _l(mLock); |
| sp<IBatteryStats> batteryService = getBatteryService_l(); |
| if (mAudioRefCounts[uid] == 0 && batteryService != nullptr) { |
| batteryService->noteStartAudio(uid); |
| } |
| mAudioRefCounts[uid]++; |
| } |
| |
| void BatteryNotifier::noteStopAudio(uid_t uid) { |
| Mutex::Autolock _l(mLock); |
| if (mAudioRefCounts.find(uid) == mAudioRefCounts.end()) { |
| ALOGW("%s: audio refcount is broken for uid(%d).", __FUNCTION__, (int)uid); |
| return; |
| } |
| |
| sp<IBatteryStats> batteryService = getBatteryService_l(); |
| |
| mAudioRefCounts[uid]--; |
| if (mAudioRefCounts[uid] == 0) { |
| if (batteryService != nullptr) { |
| batteryService->noteStopAudio(uid); |
| } |
| mAudioRefCounts.erase(uid); |
| } |
| } |
| |
| void BatteryNotifier::noteResetAudio() { |
| Mutex::Autolock _l(mLock); |
| sp<IBatteryStats> batteryService = getBatteryService_l(); |
| mAudioRefCounts.clear(); |
| if (batteryService != nullptr) { |
| batteryService->noteResetAudio(); |
| } |
| } |
| |
| void BatteryNotifier::noteFlashlightOn(const String8& id, uid_t uid) { |
| Mutex::Autolock _l(mLock); |
| sp<IBatteryStats> batteryService = getBatteryService_l(); |
| |
| std::pair<String8, uid_t> k = std::make_pair(id, uid); |
| if (!mFlashlightState[k]) { |
| mFlashlightState[k] = true; |
| if (batteryService != nullptr) { |
| batteryService->noteFlashlightOn(uid); |
| } |
| } |
| } |
| |
| void BatteryNotifier::noteFlashlightOff(const String8& id, uid_t uid) { |
| Mutex::Autolock _l(mLock); |
| sp<IBatteryStats> batteryService = getBatteryService_l(); |
| |
| std::pair<String8, uid_t> k = std::make_pair(id, uid); |
| if (mFlashlightState[k]) { |
| mFlashlightState[k] = false; |
| if (batteryService != nullptr) { |
| batteryService->noteFlashlightOff(uid); |
| } |
| } |
| } |
| |
| void BatteryNotifier::noteResetFlashlight() { |
| Mutex::Autolock _l(mLock); |
| sp<IBatteryStats> batteryService = getBatteryService_l(); |
| mFlashlightState.clear(); |
| if (batteryService != nullptr) { |
| batteryService->noteResetFlashlight(); |
| } |
| } |
| |
| void BatteryNotifier::noteStartCamera(const String8& id, uid_t uid) { |
| Mutex::Autolock _l(mLock); |
| sp<IBatteryStats> batteryService = getBatteryService_l(); |
| std::pair<String8, uid_t> k = std::make_pair(id, uid); |
| if (!mCameraState[k]) { |
| mCameraState[k] = true; |
| if (batteryService != nullptr) { |
| batteryService->noteStartCamera(uid); |
| } |
| } |
| } |
| |
| void BatteryNotifier::noteStopCamera(const String8& id, uid_t uid) { |
| Mutex::Autolock _l(mLock); |
| sp<IBatteryStats> batteryService = getBatteryService_l(); |
| std::pair<String8, uid_t> k = std::make_pair(id, uid); |
| if (mCameraState[k]) { |
| mCameraState[k] = false; |
| if (batteryService != nullptr) { |
| batteryService->noteStopCamera(uid); |
| } |
| } |
| } |
| |
| void BatteryNotifier::noteResetCamera() { |
| Mutex::Autolock _l(mLock); |
| sp<IBatteryStats> batteryService = getBatteryService_l(); |
| mCameraState.clear(); |
| if (batteryService != nullptr) { |
| batteryService->noteResetCamera(); |
| } |
| } |
| |
| void BatteryNotifier::onBatteryStatServiceDied() { |
| Mutex::Autolock _l(mLock); |
| mBatteryStatService.clear(); |
| mDeathNotifier.clear(); |
| // Do not reset mVideoRefCounts and mAudioRefCounts here. The ref |
| // counting is independent of the battery service availability. |
| // We need this if battery service becomes available after media |
| // started. |
| |
| } |
| |
| sp<IBatteryStats> BatteryNotifier::getBatteryService_l() { |
| if (mBatteryStatService != nullptr) { |
| return mBatteryStatService; |
| } |
| // Get battery service from service manager |
| const sp<IServiceManager> sm(defaultServiceManager()); |
| if (sm != nullptr) { |
| const String16 name("batterystats"); |
| mBatteryStatService = interface_cast<IBatteryStats>(sm->checkService(name)); |
| if (mBatteryStatService == nullptr) { |
| // this may occur normally during the init sequence as mediaserver |
| // and audioserver start before the batterystats service is available. |
| ALOGW("batterystats service unavailable!"); |
| return nullptr; |
| } |
| |
| mDeathNotifier = new DeathNotifier(); |
| IInterface::asBinder(mBatteryStatService)->linkToDeath(mDeathNotifier); |
| |
| // Notify start now if mediaserver or audioserver is already started. |
| // 1) mediaserver and audioserver is started before batterystats service |
| // 2) batterystats server may have crashed. |
| std::map<uid_t, int>::iterator it = mVideoRefCounts.begin(); |
| for (; it != mVideoRefCounts.end(); ++it) { |
| mBatteryStatService->noteStartVideo(it->first); |
| } |
| it = mAudioRefCounts.begin(); |
| for (; it != mAudioRefCounts.end(); ++it) { |
| mBatteryStatService->noteStartAudio(it->first); |
| } |
| // TODO: Notify for camera and flashlight state as well? |
| } |
| return mBatteryStatService; |
| } |
| |
| ANDROID_SINGLETON_STATIC_INSTANCE(BatteryNotifier); |
| |
| } // namespace android |