/*
* 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() : mVideoRefCount(0), mAudioRefCount(0) {}
BatteryNotifier::~BatteryNotifier() {
Mutex::Autolock _l(mLock);
if (mDeathNotifier != nullptr) {
IInterface::asBinder(mBatteryStatService)->unlinkToDeath(mDeathNotifier);
}
}
void BatteryNotifier::noteStartVideo() {
Mutex::Autolock _l(mLock);
sp<IBatteryStats> batteryService = getBatteryService_l();
if (mVideoRefCount == 0 && batteryService != nullptr) {
batteryService->noteStartVideo(AID_MEDIA);
}
mVideoRefCount++;
}
void BatteryNotifier::noteStopVideo() {
Mutex::Autolock _l(mLock);
if (mVideoRefCount == 0) {
ALOGW("%s: video refcount is broken.", __FUNCTION__);
return;
}
sp<IBatteryStats> batteryService = getBatteryService_l();
mVideoRefCount--;
if (mVideoRefCount == 0 && batteryService != nullptr) {
batteryService->noteStopVideo(AID_MEDIA);
}
}
void BatteryNotifier::noteResetVideo() {
Mutex::Autolock _l(mLock);
sp<IBatteryStats> batteryService = getBatteryService_l();
mVideoRefCount = 0;
if (batteryService != nullptr) {
batteryService->noteResetVideo();
}
}
void BatteryNotifier::noteStartAudio() {
Mutex::Autolock _l(mLock);
sp<IBatteryStats> batteryService = getBatteryService_l();
if (mAudioRefCount == 0 && batteryService != nullptr) {
batteryService->noteStartAudio(AID_AUDIOSERVER);
}
mAudioRefCount++;
}
void BatteryNotifier::noteStopAudio() {
Mutex::Autolock _l(mLock);
if (mAudioRefCount == 0) {
ALOGW("%s: audio refcount is broken.", __FUNCTION__);
return;
}
sp<IBatteryStats> batteryService = getBatteryService_l();
mAudioRefCount--;
if (mAudioRefCount == 0 && batteryService != nullptr) {
batteryService->noteStopAudio(AID_AUDIOSERVER);
}
}
void BatteryNotifier::noteResetAudio() {
Mutex::Autolock _l(mLock);
sp<IBatteryStats> batteryService = getBatteryService_l();
mAudioRefCount = 0;
if (batteryService != nullptr) {
batteryService->noteResetAudio();
}
}
void BatteryNotifier::noteFlashlightOn(const String8& id, int uid) {
Mutex::Autolock _l(mLock);
sp<IBatteryStats> batteryService = getBatteryService_l();
std::pair<String8, int> k = std::make_pair(id, uid);
if (!mFlashlightState[k]) {
mFlashlightState[k] = true;
if (batteryService != nullptr) {
batteryService->noteFlashlightOn(uid);
}
}
}
void BatteryNotifier::noteFlashlightOff(const String8& id, int uid) {
Mutex::Autolock _l(mLock);
sp<IBatteryStats> batteryService = getBatteryService_l();
std::pair<String8, int> 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, int uid) {
Mutex::Autolock _l(mLock);
sp<IBatteryStats> batteryService = getBatteryService_l();
std::pair<String8, int> k = std::make_pair(id, uid);
if (!mCameraState[k]) {
mCameraState[k] = true;
if (batteryService != nullptr) {
batteryService->noteStartCamera(uid);
}
}
}
void BatteryNotifier::noteStopCamera(const String8& id, int uid) {
Mutex::Autolock _l(mLock);
sp<IBatteryStats> batteryService = getBatteryService_l();
std::pair<String8, int> 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 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.
}
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.
if (mVideoRefCount > 0) {
mBatteryStatService->noteStartVideo(AID_MEDIA);
}
if (mAudioRefCount > 0) {
mBatteryStatService->noteStartAudio(AID_AUDIOSERVER);
}
// TODO: Notify for camera and flashlight state as well?
}
return mBatteryStatService;
}
ANDROID_SINGLETON_STATIC_INSTANCE(BatteryNotifier);
} // namespace android