1 /*
2  * Copyright 2015, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "BatteryNotifier"
18 //#define LOG_NDEBUG 0
19 
20 #include "include/mediautils/BatteryNotifier.h"
21 
22 #include <binder/IServiceManager.h>
23 #include <utils/Log.h>
24 #include <private/android_filesystem_config.h>
25 
26 namespace android {
27 
binderDied(const wp<IBinder> &)28 void BatteryNotifier::DeathNotifier::binderDied(const wp<IBinder>& /*who*/) {
29     BatteryNotifier::getInstance().onBatteryStatServiceDied();
30 }
31 
BatteryNotifier()32 BatteryNotifier::BatteryNotifier() {}
33 
~BatteryNotifier()34 BatteryNotifier::~BatteryNotifier() {
35     Mutex::Autolock _l(mLock);
36     if (mDeathNotifier != nullptr) {
37         IInterface::asBinder(mBatteryStatService)->unlinkToDeath(mDeathNotifier);
38     }
39 }
40 
noteStartVideo(uid_t uid)41 void BatteryNotifier::noteStartVideo(uid_t uid) {
42     Mutex::Autolock _l(mLock);
43     sp<IBatteryStats> batteryService = getBatteryService_l();
44     if (mVideoRefCounts[uid] == 0 && batteryService != nullptr) {
45         batteryService->noteStartVideo(uid);
46     }
47     mVideoRefCounts[uid]++;
48 }
49 
noteStopVideo(uid_t uid)50 void BatteryNotifier::noteStopVideo(uid_t uid) {
51     Mutex::Autolock _l(mLock);
52     if (mVideoRefCounts.find(uid) == mVideoRefCounts.end()) {
53         ALOGW("%s: video refcount is broken for uid(%d).", __FUNCTION__, (int)uid);
54         return;
55     }
56 
57     sp<IBatteryStats> batteryService = getBatteryService_l();
58 
59     mVideoRefCounts[uid]--;
60     if (mVideoRefCounts[uid] == 0) {
61         if (batteryService != nullptr) {
62             batteryService->noteStopVideo(uid);
63         }
64         mVideoRefCounts.erase(uid);
65     }
66 }
67 
noteResetVideo()68 void BatteryNotifier::noteResetVideo() {
69     Mutex::Autolock _l(mLock);
70     sp<IBatteryStats> batteryService = getBatteryService_l();
71     mVideoRefCounts.clear();
72     if (batteryService != nullptr) {
73         batteryService->noteResetVideo();
74     }
75 }
76 
noteStartAudio(uid_t uid)77 void BatteryNotifier::noteStartAudio(uid_t uid) {
78     Mutex::Autolock _l(mLock);
79     sp<IBatteryStats> batteryService = getBatteryService_l();
80     if (mAudioRefCounts[uid] == 0 && batteryService != nullptr) {
81         batteryService->noteStartAudio(uid);
82     }
83     mAudioRefCounts[uid]++;
84 }
85 
noteStopAudio(uid_t uid)86 void BatteryNotifier::noteStopAudio(uid_t uid) {
87     Mutex::Autolock _l(mLock);
88     if (mAudioRefCounts.find(uid) == mAudioRefCounts.end()) {
89         ALOGW("%s: audio refcount is broken for uid(%d).", __FUNCTION__, (int)uid);
90         return;
91     }
92 
93     sp<IBatteryStats> batteryService = getBatteryService_l();
94 
95     mAudioRefCounts[uid]--;
96     if (mAudioRefCounts[uid] == 0) {
97         if (batteryService != nullptr) {
98             batteryService->noteStopAudio(uid);
99         }
100         mAudioRefCounts.erase(uid);
101     }
102 }
103 
noteResetAudio()104 void BatteryNotifier::noteResetAudio() {
105     Mutex::Autolock _l(mLock);
106     sp<IBatteryStats> batteryService = getBatteryService_l();
107     mAudioRefCounts.clear();
108     if (batteryService != nullptr) {
109         batteryService->noteResetAudio();
110     }
111 }
112 
noteFlashlightOn(const String8 & id,uid_t uid)113 void BatteryNotifier::noteFlashlightOn(const String8& id, uid_t uid) {
114     Mutex::Autolock _l(mLock);
115     sp<IBatteryStats> batteryService = getBatteryService_l();
116 
117     std::pair<String8, uid_t> k = std::make_pair(id, uid);
118     if (!mFlashlightState[k]) {
119         mFlashlightState[k] = true;
120         if (batteryService != nullptr) {
121             batteryService->noteFlashlightOn(uid);
122         }
123     }
124 }
125 
noteFlashlightOff(const String8 & id,uid_t uid)126 void BatteryNotifier::noteFlashlightOff(const String8& id, uid_t uid) {
127     Mutex::Autolock _l(mLock);
128     sp<IBatteryStats> batteryService = getBatteryService_l();
129 
130     std::pair<String8, uid_t> k = std::make_pair(id, uid);
131     if (mFlashlightState[k]) {
132         mFlashlightState[k] = false;
133         if (batteryService != nullptr) {
134             batteryService->noteFlashlightOff(uid);
135         }
136     }
137 }
138 
noteResetFlashlight()139 void BatteryNotifier::noteResetFlashlight() {
140     Mutex::Autolock _l(mLock);
141     sp<IBatteryStats> batteryService = getBatteryService_l();
142     mFlashlightState.clear();
143     if (batteryService != nullptr) {
144         batteryService->noteResetFlashlight();
145     }
146 }
147 
noteStartCamera(const String8 & id,uid_t uid)148 void BatteryNotifier::noteStartCamera(const String8& id, uid_t uid) {
149     Mutex::Autolock _l(mLock);
150     sp<IBatteryStats> batteryService = getBatteryService_l();
151     std::pair<String8, uid_t> k = std::make_pair(id, uid);
152     if (!mCameraState[k]) {
153         mCameraState[k] = true;
154         if (batteryService != nullptr) {
155             batteryService->noteStartCamera(uid);
156         }
157     }
158 }
159 
noteStopCamera(const String8 & id,uid_t uid)160 void BatteryNotifier::noteStopCamera(const String8& id, uid_t uid) {
161     Mutex::Autolock _l(mLock);
162     sp<IBatteryStats> batteryService = getBatteryService_l();
163     std::pair<String8, uid_t> k = std::make_pair(id, uid);
164     if (mCameraState[k]) {
165         mCameraState[k] = false;
166         if (batteryService != nullptr) {
167             batteryService->noteStopCamera(uid);
168         }
169     }
170 }
171 
noteResetCamera()172 void BatteryNotifier::noteResetCamera() {
173     Mutex::Autolock _l(mLock);
174     sp<IBatteryStats> batteryService = getBatteryService_l();
175     mCameraState.clear();
176     if (batteryService != nullptr) {
177         batteryService->noteResetCamera();
178     }
179 }
180 
onBatteryStatServiceDied()181 void BatteryNotifier::onBatteryStatServiceDied() {
182     Mutex::Autolock _l(mLock);
183     mBatteryStatService.clear();
184     mDeathNotifier.clear();
185     // Do not reset mVideoRefCounts and mAudioRefCounts here. The ref
186     // counting is independent of the battery service availability.
187     // We need this if battery service becomes available after media
188     // started.
189 
190 }
191 
getBatteryService_l()192 sp<IBatteryStats> BatteryNotifier::getBatteryService_l() {
193     if (mBatteryStatService != nullptr) {
194         return mBatteryStatService;
195     }
196     // Get battery service from service manager
197     const sp<IServiceManager> sm(defaultServiceManager());
198     if (sm != nullptr) {
199         const String16 name("batterystats");
200         mBatteryStatService = interface_cast<IBatteryStats>(sm->checkService(name));
201         if (mBatteryStatService == nullptr) {
202             // this may occur normally during the init sequence as mediaserver
203             // and audioserver start before the batterystats service is available.
204             ALOGW("batterystats service unavailable!");
205             return nullptr;
206         }
207 
208         mDeathNotifier = new DeathNotifier();
209         IInterface::asBinder(mBatteryStatService)->linkToDeath(mDeathNotifier);
210 
211         // Notify start now if mediaserver or audioserver is already started.
212         // 1) mediaserver and audioserver is started before batterystats service
213         // 2) batterystats server may have crashed.
214         std::map<uid_t, int>::iterator it = mVideoRefCounts.begin();
215         for (; it != mVideoRefCounts.end(); ++it) {
216             mBatteryStatService->noteStartVideo(it->first);
217         }
218         it = mAudioRefCounts.begin();
219         for (; it != mAudioRefCounts.end(); ++it) {
220             mBatteryStatService->noteStartAudio(it->first);
221         }
222         // TODO: Notify for camera and flashlight state as well?
223     }
224     return mBatteryStatService;
225 }
226 
227 ANDROID_SINGLETON_STATIC_INSTANCE(BatteryNotifier);
228 
229 }  // namespace android
230