/* * 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