199e69716215cd0665379bc90d708f2ea8689831dRuben Brunk/*
299e69716215cd0665379bc90d708f2ea8689831dRuben Brunk * Copyright 2015, The Android Open Source Project
399e69716215cd0665379bc90d708f2ea8689831dRuben Brunk *
499e69716215cd0665379bc90d708f2ea8689831dRuben Brunk * Licensed under the Apache License, Version 2.0 (the "License");
599e69716215cd0665379bc90d708f2ea8689831dRuben Brunk * you may not use this file except in compliance with the License.
699e69716215cd0665379bc90d708f2ea8689831dRuben Brunk * You may obtain a copy of the License at
799e69716215cd0665379bc90d708f2ea8689831dRuben Brunk *
899e69716215cd0665379bc90d708f2ea8689831dRuben Brunk *     http://www.apache.org/licenses/LICENSE-2.0
999e69716215cd0665379bc90d708f2ea8689831dRuben Brunk *
1099e69716215cd0665379bc90d708f2ea8689831dRuben Brunk * Unless required by applicable law or agreed to in writing, software
1199e69716215cd0665379bc90d708f2ea8689831dRuben Brunk * distributed under the License is distributed on an "AS IS" BASIS,
1299e69716215cd0665379bc90d708f2ea8689831dRuben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1399e69716215cd0665379bc90d708f2ea8689831dRuben Brunk * See the License for the specific language governing permissions and
1499e69716215cd0665379bc90d708f2ea8689831dRuben Brunk * limitations under the License.
1599e69716215cd0665379bc90d708f2ea8689831dRuben Brunk */
1699e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
17dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen#define LOG_TAG "BatteryNotifier"
18dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen//#define LOG_NDEBUG 0
19dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen
2099e69716215cd0665379bc90d708f2ea8689831dRuben Brunk#include "include/mediautils/BatteryNotifier.h"
2199e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
2299e69716215cd0665379bc90d708f2ea8689831dRuben Brunk#include <binder/IServiceManager.h>
2399e69716215cd0665379bc90d708f2ea8689831dRuben Brunk#include <utils/Log.h>
2499e69716215cd0665379bc90d708f2ea8689831dRuben Brunk#include <private/android_filesystem_config.h>
2599e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
2699e69716215cd0665379bc90d708f2ea8689831dRuben Brunknamespace android {
2799e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
2899e69716215cd0665379bc90d708f2ea8689831dRuben Brunkvoid BatteryNotifier::DeathNotifier::binderDied(const wp<IBinder>& /*who*/) {
2999e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    BatteryNotifier::getInstance().onBatteryStatServiceDied();
3099e69716215cd0665379bc90d708f2ea8689831dRuben Brunk}
3199e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
32f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei JiaBatteryNotifier::BatteryNotifier() {}
3399e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
3499e69716215cd0665379bc90d708f2ea8689831dRuben BrunkBatteryNotifier::~BatteryNotifier() {
3599e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    Mutex::Autolock _l(mLock);
3699e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    if (mDeathNotifier != nullptr) {
3799e69716215cd0665379bc90d708f2ea8689831dRuben Brunk        IInterface::asBinder(mBatteryStatService)->unlinkToDeath(mDeathNotifier);
3899e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    }
3999e69716215cd0665379bc90d708f2ea8689831dRuben Brunk}
4099e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
411afd0983fdca07cd55df8dca1fa05b55c45063f4Andy Hungvoid BatteryNotifier::noteStartVideo(uid_t uid) {
4299e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    Mutex::Autolock _l(mLock);
4399e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    sp<IBatteryStats> batteryService = getBatteryService_l();
44f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia    if (mVideoRefCounts[uid] == 0 && batteryService != nullptr) {
45f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia        batteryService->noteStartVideo(uid);
4699e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    }
47f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia    mVideoRefCounts[uid]++;
4899e69716215cd0665379bc90d708f2ea8689831dRuben Brunk}
4999e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
501afd0983fdca07cd55df8dca1fa05b55c45063f4Andy Hungvoid BatteryNotifier::noteStopVideo(uid_t uid) {
5199e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    Mutex::Autolock _l(mLock);
52f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia    if (mVideoRefCounts.find(uid) == mVideoRefCounts.end()) {
53f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia        ALOGW("%s: video refcount is broken for uid(%d).", __FUNCTION__, (int)uid);
5499e69716215cd0665379bc90d708f2ea8689831dRuben Brunk        return;
5599e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    }
5699e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
5799e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    sp<IBatteryStats> batteryService = getBatteryService_l();
5899e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
59f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia    mVideoRefCounts[uid]--;
60f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia    if (mVideoRefCounts[uid] == 0) {
61f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia        if (batteryService != nullptr) {
62f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia            batteryService->noteStopVideo(uid);
63f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia        }
64f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia        mVideoRefCounts.erase(uid);
6599e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    }
6699e69716215cd0665379bc90d708f2ea8689831dRuben Brunk}
6799e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
6899e69716215cd0665379bc90d708f2ea8689831dRuben Brunkvoid BatteryNotifier::noteResetVideo() {
6999e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    Mutex::Autolock _l(mLock);
7099e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    sp<IBatteryStats> batteryService = getBatteryService_l();
71f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia    mVideoRefCounts.clear();
7299e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    if (batteryService != nullptr) {
73dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen        batteryService->noteResetVideo();
7499e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    }
7599e69716215cd0665379bc90d708f2ea8689831dRuben Brunk}
7699e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
771afd0983fdca07cd55df8dca1fa05b55c45063f4Andy Hungvoid BatteryNotifier::noteStartAudio(uid_t uid) {
7899e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    Mutex::Autolock _l(mLock);
7999e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    sp<IBatteryStats> batteryService = getBatteryService_l();
80f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia    if (mAudioRefCounts[uid] == 0 && batteryService != nullptr) {
81f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia        batteryService->noteStartAudio(uid);
8299e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    }
83f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia    mAudioRefCounts[uid]++;
8499e69716215cd0665379bc90d708f2ea8689831dRuben Brunk}
8599e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
861afd0983fdca07cd55df8dca1fa05b55c45063f4Andy Hungvoid BatteryNotifier::noteStopAudio(uid_t uid) {
8799e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    Mutex::Autolock _l(mLock);
88f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia    if (mAudioRefCounts.find(uid) == mAudioRefCounts.end()) {
89f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia        ALOGW("%s: audio refcount is broken for uid(%d).", __FUNCTION__, (int)uid);
9099e69716215cd0665379bc90d708f2ea8689831dRuben Brunk        return;
9199e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    }
9299e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
9399e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    sp<IBatteryStats> batteryService = getBatteryService_l();
9499e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
95f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia    mAudioRefCounts[uid]--;
96f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia    if (mAudioRefCounts[uid] == 0) {
97f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia        if (batteryService != nullptr) {
98f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia            batteryService->noteStopAudio(uid);
99f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia        }
100f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia        mAudioRefCounts.erase(uid);
10199e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    }
10299e69716215cd0665379bc90d708f2ea8689831dRuben Brunk}
10399e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
10499e69716215cd0665379bc90d708f2ea8689831dRuben Brunkvoid BatteryNotifier::noteResetAudio() {
10599e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    Mutex::Autolock _l(mLock);
10699e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    sp<IBatteryStats> batteryService = getBatteryService_l();
107f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia    mAudioRefCounts.clear();
10899e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    if (batteryService != nullptr) {
10999e69716215cd0665379bc90d708f2ea8689831dRuben Brunk        batteryService->noteResetAudio();
11099e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    }
11199e69716215cd0665379bc90d708f2ea8689831dRuben Brunk}
11299e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
1131afd0983fdca07cd55df8dca1fa05b55c45063f4Andy Hungvoid BatteryNotifier::noteFlashlightOn(const String8& id, uid_t uid) {
11499e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    Mutex::Autolock _l(mLock);
11599e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    sp<IBatteryStats> batteryService = getBatteryService_l();
11699e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
1171afd0983fdca07cd55df8dca1fa05b55c45063f4Andy Hung    std::pair<String8, uid_t> k = std::make_pair(id, uid);
11899e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    if (!mFlashlightState[k]) {
11999e69716215cd0665379bc90d708f2ea8689831dRuben Brunk        mFlashlightState[k] = true;
12099e69716215cd0665379bc90d708f2ea8689831dRuben Brunk        if (batteryService != nullptr) {
12199e69716215cd0665379bc90d708f2ea8689831dRuben Brunk            batteryService->noteFlashlightOn(uid);
12299e69716215cd0665379bc90d708f2ea8689831dRuben Brunk        }
12399e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    }
12499e69716215cd0665379bc90d708f2ea8689831dRuben Brunk}
12599e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
1261afd0983fdca07cd55df8dca1fa05b55c45063f4Andy Hungvoid BatteryNotifier::noteFlashlightOff(const String8& id, uid_t uid) {
12799e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    Mutex::Autolock _l(mLock);
12899e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    sp<IBatteryStats> batteryService = getBatteryService_l();
12999e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
1301afd0983fdca07cd55df8dca1fa05b55c45063f4Andy Hung    std::pair<String8, uid_t> k = std::make_pair(id, uid);
13199e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    if (mFlashlightState[k]) {
13299e69716215cd0665379bc90d708f2ea8689831dRuben Brunk        mFlashlightState[k] = false;
13399e69716215cd0665379bc90d708f2ea8689831dRuben Brunk        if (batteryService != nullptr) {
13499e69716215cd0665379bc90d708f2ea8689831dRuben Brunk            batteryService->noteFlashlightOff(uid);
13599e69716215cd0665379bc90d708f2ea8689831dRuben Brunk        }
13699e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    }
13799e69716215cd0665379bc90d708f2ea8689831dRuben Brunk}
13899e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
13999e69716215cd0665379bc90d708f2ea8689831dRuben Brunkvoid BatteryNotifier::noteResetFlashlight() {
14099e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    Mutex::Autolock _l(mLock);
14199e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    sp<IBatteryStats> batteryService = getBatteryService_l();
14299e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    mFlashlightState.clear();
14399e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    if (batteryService != nullptr) {
14499e69716215cd0665379bc90d708f2ea8689831dRuben Brunk        batteryService->noteResetFlashlight();
14599e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    }
14699e69716215cd0665379bc90d708f2ea8689831dRuben Brunk}
14799e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
1481afd0983fdca07cd55df8dca1fa05b55c45063f4Andy Hungvoid BatteryNotifier::noteStartCamera(const String8& id, uid_t uid) {
14999e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    Mutex::Autolock _l(mLock);
15099e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    sp<IBatteryStats> batteryService = getBatteryService_l();
1511afd0983fdca07cd55df8dca1fa05b55c45063f4Andy Hung    std::pair<String8, uid_t> k = std::make_pair(id, uid);
15299e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    if (!mCameraState[k]) {
15399e69716215cd0665379bc90d708f2ea8689831dRuben Brunk        mCameraState[k] = true;
15499e69716215cd0665379bc90d708f2ea8689831dRuben Brunk        if (batteryService != nullptr) {
15599e69716215cd0665379bc90d708f2ea8689831dRuben Brunk            batteryService->noteStartCamera(uid);
15699e69716215cd0665379bc90d708f2ea8689831dRuben Brunk        }
15799e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    }
15899e69716215cd0665379bc90d708f2ea8689831dRuben Brunk}
15999e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
1601afd0983fdca07cd55df8dca1fa05b55c45063f4Andy Hungvoid BatteryNotifier::noteStopCamera(const String8& id, uid_t uid) {
16199e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    Mutex::Autolock _l(mLock);
16299e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    sp<IBatteryStats> batteryService = getBatteryService_l();
1631afd0983fdca07cd55df8dca1fa05b55c45063f4Andy Hung    std::pair<String8, uid_t> k = std::make_pair(id, uid);
16499e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    if (mCameraState[k]) {
16599e69716215cd0665379bc90d708f2ea8689831dRuben Brunk        mCameraState[k] = false;
16699e69716215cd0665379bc90d708f2ea8689831dRuben Brunk        if (batteryService != nullptr) {
16799e69716215cd0665379bc90d708f2ea8689831dRuben Brunk            batteryService->noteStopCamera(uid);
16899e69716215cd0665379bc90d708f2ea8689831dRuben Brunk        }
16999e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    }
17099e69716215cd0665379bc90d708f2ea8689831dRuben Brunk}
17199e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
17299e69716215cd0665379bc90d708f2ea8689831dRuben Brunkvoid BatteryNotifier::noteResetCamera() {
17399e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    Mutex::Autolock _l(mLock);
17499e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    sp<IBatteryStats> batteryService = getBatteryService_l();
17599e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    mCameraState.clear();
17699e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    if (batteryService != nullptr) {
17799e69716215cd0665379bc90d708f2ea8689831dRuben Brunk        batteryService->noteResetCamera();
17899e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    }
17999e69716215cd0665379bc90d708f2ea8689831dRuben Brunk}
18099e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
18199e69716215cd0665379bc90d708f2ea8689831dRuben Brunkvoid BatteryNotifier::onBatteryStatServiceDied() {
18299e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    Mutex::Autolock _l(mLock);
18399e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    mBatteryStatService.clear();
18499e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    mDeathNotifier.clear();
185f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia    // Do not reset mVideoRefCounts and mAudioRefCounts here. The ref
18699e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    // counting is independent of the battery service availability.
18799e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    // We need this if battery service becomes available after media
18899e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    // started.
18999e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
19099e69716215cd0665379bc90d708f2ea8689831dRuben Brunk}
19199e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
19299e69716215cd0665379bc90d708f2ea8689831dRuben Brunksp<IBatteryStats> BatteryNotifier::getBatteryService_l() {
19399e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    if (mBatteryStatService != nullptr) {
19499e69716215cd0665379bc90d708f2ea8689831dRuben Brunk        return mBatteryStatService;
19599e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    }
19699e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    // Get battery service from service manager
19799e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    const sp<IServiceManager> sm(defaultServiceManager());
19899e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    if (sm != nullptr) {
19999e69716215cd0665379bc90d708f2ea8689831dRuben Brunk        const String16 name("batterystats");
20099e69716215cd0665379bc90d708f2ea8689831dRuben Brunk        mBatteryStatService = interface_cast<IBatteryStats>(sm->checkService(name));
20199e69716215cd0665379bc90d708f2ea8689831dRuben Brunk        if (mBatteryStatService == nullptr) {
202dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen            // this may occur normally during the init sequence as mediaserver
203dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen            // and audioserver start before the batterystats service is available.
204dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen            ALOGW("batterystats service unavailable!");
20599e69716215cd0665379bc90d708f2ea8689831dRuben Brunk            return nullptr;
20699e69716215cd0665379bc90d708f2ea8689831dRuben Brunk        }
20799e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
20899e69716215cd0665379bc90d708f2ea8689831dRuben Brunk        mDeathNotifier = new DeathNotifier();
20999e69716215cd0665379bc90d708f2ea8689831dRuben Brunk        IInterface::asBinder(mBatteryStatService)->linkToDeath(mDeathNotifier);
21099e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
211dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen        // Notify start now if mediaserver or audioserver is already started.
212dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen        // 1) mediaserver and audioserver is started before batterystats service
213dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen        // 2) batterystats server may have crashed.
2141afd0983fdca07cd55df8dca1fa05b55c45063f4Andy Hung        std::map<uid_t, int>::iterator it = mVideoRefCounts.begin();
215f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia        for (; it != mVideoRefCounts.end(); ++it) {
216f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia            mBatteryStatService->noteStartVideo(it->first);
21799e69716215cd0665379bc90d708f2ea8689831dRuben Brunk        }
218f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia        it = mAudioRefCounts.begin();
219f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia        for (; it != mAudioRefCounts.end(); ++it) {
220f2ae3e19080938db8cbf29a963fd744a3964fcc2Wei Jia            mBatteryStatService->noteStartAudio(it->first);
22199e69716215cd0665379bc90d708f2ea8689831dRuben Brunk        }
222dcb346b7dc5b88c3e85db8a70bbd6a2fee8192b9Marco Nelissen        // TODO: Notify for camera and flashlight state as well?
22399e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    }
22499e69716215cd0665379bc90d708f2ea8689831dRuben Brunk    return mBatteryStatService;
22599e69716215cd0665379bc90d708f2ea8689831dRuben Brunk}
22699e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
22799e69716215cd0665379bc90d708f2ea8689831dRuben BrunkANDROID_SINGLETON_STATIC_INSTANCE(BatteryNotifier);
22899e69716215cd0665379bc90d708f2ea8689831dRuben Brunk
22999e69716215cd0665379bc90d708f2ea8689831dRuben Brunk}  // namespace android
230