1 /*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "entities/bluetooth_entity.h"
17
18 #include <cinttypes>
19 #include <ipc_skeleton.h>
20 #include "bundle_constants.h"
21 #include "bundle_mgr_interface.h"
22 #include "system_ability_definition.h"
23 #include "sys_mgr_client.h"
24
25 #include "battery_stats_service.h"
26 #include "stats_log.h"
27
28 namespace OHOS {
29 namespace PowerMgr {
30 namespace {
31 auto g_statsService = DelayedStatsSpSingleton<BatteryStatsService>::GetInstance();
32 }
33
BluetoothEntity()34 BluetoothEntity::BluetoothEntity()
35 {
36 consumptionType_ = BatteryStatsInfo::CONSUMPTION_TYPE_BLUETOOTH;
37 }
38
Calculate(int32_t uid)39 void BluetoothEntity::Calculate(int32_t uid)
40 {
41 if (uid > StatsUtils::INVALID_VALUE) {
42 // Calculate Bluetooth scan caused by app
43 CalculateBtPowerForApp(uid);
44 } else {
45 // Calculate Bluetooth on and Bluetooth app power consumption caused by Bluetooth hardware
46 CalculateBtPower();
47 }
48 }
49
CalculateBtPower()50 void BluetoothEntity::CalculateBtPower()
51 {
52 // Calculate Bluetooth BR on power
53 auto bluetoothBrOnAverageMa =
54 g_statsService->GetBatteryStatsParser()->GetAveragePowerMa(StatsUtils::CURRENT_BLUETOOTH_BR_ON);
55 auto bluetoothBrOnTimeMs = GetActiveTimeMs(StatsUtils::STATS_TYPE_BLUETOOTH_BR_ON);
56 auto bluetoothBrOnPowerMah = bluetoothBrOnAverageMa * bluetoothBrOnTimeMs / StatsUtils::MS_IN_HOUR;
57 bluetoothBrPowerMah_ += bluetoothBrOnPowerMah;
58
59 // Calculate Bluetooth BLE on power
60 auto bluetoothBleOnAverageMa =
61 g_statsService->GetBatteryStatsParser()->GetAveragePowerMa(StatsUtils::CURRENT_BLUETOOTH_BLE_ON);
62 auto bluetoothBleOnTimeMs = GetActiveTimeMs(StatsUtils::STATS_TYPE_BLUETOOTH_BLE_ON);
63 auto bluetoothBleOnPowerMah = bluetoothBleOnAverageMa * bluetoothBleOnTimeMs / StatsUtils::MS_IN_HOUR;
64 bluetoothBlePowerMah_ += bluetoothBleOnPowerMah;
65
66 auto bluetoothUidPowerMah = GetBluetoothUidPower();
67
68 bluetoothPowerMah_ = bluetoothBrOnPowerMah + bluetoothBleOnPowerMah + bluetoothUidPowerMah;
69 totalPowerMah_ += bluetoothPowerMah_;
70
71 std::shared_ptr<BatteryStatsInfo> statsInfo = std::make_shared<BatteryStatsInfo>();
72 statsInfo->SetConsumptioType(BatteryStatsInfo::CONSUMPTION_TYPE_BLUETOOTH);
73 statsInfo->SetPower(bluetoothPowerMah_);
74 statsInfoList_.push_back(statsInfo);
75
76 STATS_HILOGD(COMP_SVC, "Calculate bluetooth Br time: %{public}" PRId64 "ms, Br power average: %{public}lfma," \
77 "Br power consumption: %{public}lfmAh, bluetooth Ble time: %{public}" PRId64 "ms, " \
78 "Ble power average: %{public}lfma, Ble power consumption: %{public}lfmAh, " \
79 "uid power consumption: %{public}lfmAh, total power consumption: %{public}lfmAh",
80 bluetoothBrOnTimeMs,
81 bluetoothBrOnAverageMa,
82 bluetoothBrOnPowerMah,
83 bluetoothBleOnTimeMs,
84 bluetoothBleOnAverageMa,
85 bluetoothBleOnPowerMah,
86 bluetoothUidPowerMah,
87 bluetoothPowerMah_);
88 }
89
CalculateBtPowerForApp(int32_t uid)90 void BluetoothEntity::CalculateBtPowerForApp(int32_t uid)
91 {
92 // Calculate Bluetooth Br scan power consumption
93 auto bluetoothBrScanAverageMa =
94 g_statsService->GetBatteryStatsParser()->GetAveragePowerMa(StatsUtils::CURRENT_BLUETOOTH_BR_SCAN);
95 auto bluetoothBrScanTimeMs = GetActiveTimeMs(uid, StatsUtils::STATS_TYPE_BLUETOOTH_BR_SCAN);
96 auto bluetoothBrScanPowerMah = bluetoothBrScanTimeMs * bluetoothBrScanAverageMa / StatsUtils::MS_IN_HOUR;
97 UpdateAppBluetoothBlePower(POWER_TYPE_BR, uid, bluetoothBrScanPowerMah);
98
99 // Calculate Bluetooth Ble scan power consumption
100 auto bluetoothBleScanAverageMa =
101 g_statsService->GetBatteryStatsParser()->GetAveragePowerMa(StatsUtils::CURRENT_BLUETOOTH_BLE_SCAN);
102 auto bluetoothBleScanTimeMs = GetActiveTimeMs(uid, StatsUtils::STATS_TYPE_BLUETOOTH_BLE_SCAN);
103 auto bluetoothBleScanPowerMah = bluetoothBleScanTimeMs * bluetoothBleScanAverageMa / StatsUtils::MS_IN_HOUR;
104 UpdateAppBluetoothBlePower(POWER_TYPE_BLE, uid, bluetoothBleScanPowerMah);
105
106 auto bluetoothUidPowerMah = bluetoothBrScanPowerMah + bluetoothBleScanPowerMah;
107 UpdateAppBluetoothBlePower(POWER_TYPE_ALL, uid, bluetoothUidPowerMah);
108
109 STATS_HILOGD(COMP_SVC, "Calculate bluetooth Br scan time: %{public}" PRId64 "ms, " \
110 "Br scan power average: %{public}lfma, Br scan power consumption: %{public}lfmAh " \
111 "bluetooth Ble scan time: %{public}" PRId64 "ms, Ble scan power average: %{public}lfma, " \
112 "Ble scan power consumption: %{public}lfmAh, total power consumption: %{public}lfmAh, uid:%{public}d",
113 bluetoothBrScanTimeMs,
114 bluetoothBrScanAverageMa,
115 bluetoothBrScanPowerMah,
116 bluetoothBleScanTimeMs,
117 bluetoothBleScanAverageMa,
118 bluetoothBleScanPowerMah,
119 bluetoothUidPowerMah,
120 uid);
121 }
122
UpdateAppBluetoothBlePower(PowerType type,int32_t uid,double powerMah)123 void BluetoothEntity::UpdateAppBluetoothBlePower(PowerType type, int32_t uid, double powerMah)
124 {
125 switch (type) {
126 case POWER_TYPE_BR: {
127 auto iter = appBluetoothBrPowerMap_.find(uid);
128 if (iter != appBluetoothBrPowerMap_.end()) {
129 iter->second = powerMah;
130 STATS_HILOGD(COMP_SVC, "Update app bluetooth Br power consumption: %{public}lfmAh for uid: %{public}d",
131 powerMah, uid);
132 break;
133 }
134 appBluetoothBrPowerMap_.insert(std::pair<int32_t, double>(uid, powerMah));
135 STATS_HILOGD(COMP_SVC, "Create app bluetooth Br power consumption: %{public}lfmAh for uid: %{public}d",
136 powerMah, uid);
137 break;
138 }
139 case POWER_TYPE_BLE: {
140 auto iter = appBluetoothBlePowerMap_.find(uid);
141 if (iter != appBluetoothBlePowerMap_.end()) {
142 iter->second = powerMah;
143 STATS_HILOGD(COMP_SVC, "Update app bluetooth Ble power consumption: %{public}lfmAh for uid: %{public}d",
144 powerMah, uid);
145 break;
146 }
147 appBluetoothBlePowerMap_.insert(std::pair<int32_t, double>(uid, powerMah));
148 STATS_HILOGD(COMP_SVC, "Create app bluetooth Ble power consumption: %{public}lfmAh for uid: %{public}d",
149 powerMah, uid);
150 break;
151 }
152 case POWER_TYPE_ALL: {
153 auto iter = appBluetoothPowerMap_.find(uid);
154 if (iter != appBluetoothPowerMap_.end()) {
155 iter->second = powerMah;
156 STATS_HILOGD(COMP_SVC, "Update app bluetooth power consumption: %{public}lfmAh for uid: %{public}d",
157 powerMah, uid);
158 break;
159 }
160 appBluetoothPowerMap_.insert(std::pair<int32_t, double>(uid, powerMah));
161 STATS_HILOGD(COMP_SVC, "Create app bluetooth power consumption: %{public}lfmAh for uid: %{public}d",
162 powerMah, uid);
163 break;
164 }
165 default:
166 break;
167 }
168 }
169
GetActiveTimeMs(int32_t uid,StatsUtils::StatsType statsType,int16_t level)170 int64_t BluetoothEntity::GetActiveTimeMs(int32_t uid, StatsUtils::StatsType statsType, int16_t level)
171 {
172 int64_t time = StatsUtils::DEFAULT_VALUE;
173 switch (statsType) {
174 case StatsUtils::STATS_TYPE_BLUETOOTH_BR_SCAN: {
175 auto brScanIter = appBluetoothBrScanTimerMap_.find(uid);
176 if (brScanIter != appBluetoothBrScanTimerMap_.end()) {
177 time = brScanIter->second->GetRunningTimeMs();
178 STATS_HILOGD(COMP_SVC, "Get blueooth Br scan time: %{public}" PRId64 "ms for uid: %{public}d",
179 time, uid);
180 break;
181 }
182 STATS_HILOGD(COMP_SVC, "No bluetooth Br scan timer related to uid: %{public}d was found, return 0", uid);
183 break;
184 }
185 case StatsUtils::STATS_TYPE_BLUETOOTH_BLE_SCAN: {
186 auto bleScanIter = appBluetoothBleScanTimerMap_.find(uid);
187 if (bleScanIter != appBluetoothBleScanTimerMap_.end()) {
188 time = bleScanIter->second->GetRunningTimeMs();
189 STATS_HILOGD(COMP_SVC, "Get blueooth Ble scan time: %{public}" PRId64 "ms for uid: %{public}d",
190 time, uid);
191 break;
192 }
193 STATS_HILOGD(COMP_SVC, "No bluetooth Ble scan timer related to uid: %{public}d was found, return 0", uid);
194 break;
195 }
196 default:
197 break;
198 }
199 return time;
200 }
201
GetActiveTimeMs(StatsUtils::StatsType statsType,int16_t level)202 int64_t BluetoothEntity::GetActiveTimeMs(StatsUtils::StatsType statsType, int16_t level)
203 {
204 int64_t time = StatsUtils::DEFAULT_VALUE;
205 switch (statsType) {
206 case StatsUtils::STATS_TYPE_BLUETOOTH_BR_ON: {
207 if (bluetoothBrOnTimer_) {
208 time = bluetoothBrOnTimer_->GetRunningTimeMs();
209 STATS_HILOGD(COMP_SVC, "Get blueooth Br on time: %{public}" PRId64 "ms", time);
210 break;
211 }
212 STATS_HILOGD(COMP_SVC, "Bluetooth Br has not been turned on yet, return 0");
213 break;
214 }
215 case StatsUtils::STATS_TYPE_BLUETOOTH_BLE_ON: {
216 if (bluetoothBleOnTimer_) {
217 time = bluetoothBleOnTimer_->GetRunningTimeMs();
218 STATS_HILOGD(COMP_SVC, "Get blueooth Ble on time: %{public}" PRId64 "ms", time);
219 break;
220 }
221 STATS_HILOGD(COMP_SVC, "Bluetooth Ble has not been turned on yet, return 0");
222 break;
223 }
224 default:
225 break;
226 }
227 return time;
228 }
229
GetEntityPowerMah(int32_t uidOrUserId)230 double BluetoothEntity::GetEntityPowerMah(int32_t uidOrUserId)
231 {
232 double power = StatsUtils::DEFAULT_VALUE;
233 if (uidOrUserId > StatsUtils::INVALID_VALUE) {
234 auto iter = appBluetoothPowerMap_.find(uidOrUserId);
235 if (iter != appBluetoothPowerMap_.end()) {
236 power = iter->second;
237 STATS_HILOGD(COMP_SVC, "Get app blueooth power consumption: %{public}lfmAh for uid: %{public}d",
238 power, uidOrUserId);
239 } else {
240 STATS_HILOGD(COMP_SVC,
241 "No app blueooth power consumption related to uid: %{public}d was found, return 0", uidOrUserId);
242 }
243 } else {
244 power = bluetoothPowerMah_;
245 STATS_HILOGD(COMP_SVC, "Get blueooth power consumption: %{public}lfmAh", power);
246 }
247 return power;
248 }
249
GetStatsPowerMah(StatsUtils::StatsType statsType,int32_t uid)250 double BluetoothEntity::GetStatsPowerMah(StatsUtils::StatsType statsType, int32_t uid)
251 {
252 double power = StatsUtils::DEFAULT_VALUE;
253 switch (statsType) {
254 case StatsUtils::STATS_TYPE_BLUETOOTH_BR_ON: {
255 power = bluetoothBrPowerMah_;
256 STATS_HILOGD(COMP_SVC, "Get blueooth Br on power consumption: %{public}lfmAh", power);
257 break;
258 }
259 case StatsUtils::STATS_TYPE_BLUETOOTH_BLE_ON: {
260 power = bluetoothBlePowerMah_;
261 STATS_HILOGD(COMP_SVC, "Get blueooth Ble on power consumption: %{public}lfmAh", power);
262 break;
263 }
264 case StatsUtils::STATS_TYPE_BLUETOOTH_BR_SCAN: {
265 auto brIter = appBluetoothBrPowerMap_.find(uid);
266 if (brIter != appBluetoothBrPowerMap_.end()) {
267 power = brIter->second;
268 STATS_HILOGD(COMP_SVC, "Get blueooth Br scan power consumption: %{public}lfmAh for uid: %{public}d",
269 power, uid);
270 break;
271 }
272 STATS_HILOGD(COMP_SVC,
273 "No bluetooth Br scan power consumption related to uid: %{public}d was found, return 0", uid);
274 break;
275 }
276 case StatsUtils::STATS_TYPE_BLUETOOTH_BLE_SCAN: {
277 auto bleIter = appBluetoothBlePowerMap_.find(uid);
278 if (bleIter != appBluetoothBlePowerMap_.end()) {
279 power = bleIter->second;
280 STATS_HILOGD(COMP_SVC, "Get blueooth Ble scan power consumption: %{public}lfmAh for uid: %{public}d",
281 power, uid);
282 break;
283 }
284 STATS_HILOGD(COMP_SVC,
285 "No bluetooth Ble scan power consumption related to uid: %{public}d was found, return 0", uid);
286 break;
287 }
288 default:
289 break;
290 }
291 return power;
292 }
293
Reset()294 void BluetoothEntity::Reset()
295 {
296 // Reset Bluetooth on timer and power consumption
297 bluetoothBrPowerMah_ = StatsUtils::DEFAULT_VALUE;
298 bluetoothBlePowerMah_ = StatsUtils::DEFAULT_VALUE;
299 bluetoothPowerMah_ = StatsUtils::DEFAULT_VALUE;
300 if (bluetoothBrOnTimer_) {
301 bluetoothBrOnTimer_->Reset();
302 }
303
304 if (bluetoothBleOnTimer_) {
305 bluetoothBleOnTimer_->Reset();
306 }
307
308 // Reset app Bluetooth scan power consumption
309 for (auto& iter : appBluetoothBrPowerMap_) {
310 iter.second = StatsUtils::DEFAULT_VALUE;
311 }
312
313 for (auto& iter : appBluetoothBlePowerMap_) {
314 iter.second = StatsUtils::DEFAULT_VALUE;
315 }
316
317 for (auto& iter : appBluetoothPowerMap_) {
318 iter.second = StatsUtils::DEFAULT_VALUE;
319 }
320
321 // Reset Bluetooth scan timer
322 for (auto& iter : appBluetoothBrScanTimerMap_) {
323 if (iter.second) {
324 iter.second->Reset();
325 }
326 }
327
328 for (auto& iter : appBluetoothBleScanTimerMap_) {
329 if (iter.second) {
330 iter.second->Reset();
331 }
332 }
333 }
334
GetOrCreateTimer(int32_t uid,StatsUtils::StatsType statsType,int16_t level)335 std::shared_ptr<StatsHelper::ActiveTimer> BluetoothEntity::GetOrCreateTimer(int32_t uid,
336 StatsUtils::StatsType statsType, int16_t level)
337 {
338 std::shared_ptr<StatsHelper::ActiveTimer> timer = nullptr;
339 switch (statsType) {
340 case StatsUtils::STATS_TYPE_BLUETOOTH_BR_SCAN: {
341 auto brScanIter = appBluetoothBrScanTimerMap_.find(uid);
342 if (brScanIter != appBluetoothBrScanTimerMap_.end()) {
343 STATS_HILOGD(COMP_SVC, "Get blueooth Br scan timer for uid: %{public}d", uid);
344 timer = brScanIter->second;
345 break;
346 }
347 STATS_HILOGD(COMP_SVC, "Create bluetooth Br scan timer for uid: %{public}d", uid);
348 std::shared_ptr<StatsHelper::ActiveTimer> brScanTimer = std::make_shared<StatsHelper::ActiveTimer>();
349 appBluetoothBrScanTimerMap_.insert(
350 std::pair<int32_t, std::shared_ptr<StatsHelper::ActiveTimer>>(uid, brScanTimer));
351 timer = brScanTimer;
352 break;
353 }
354 case StatsUtils::STATS_TYPE_BLUETOOTH_BLE_SCAN: {
355 auto bleScanIter = appBluetoothBleScanTimerMap_.find(uid);
356 if (bleScanIter != appBluetoothBleScanTimerMap_.end()) {
357 STATS_HILOGD(COMP_SVC, "Get blueooth Ble scan timer for uid: %{public}d", uid);
358 timer = bleScanIter->second;
359 break;
360 }
361 STATS_HILOGD(COMP_SVC, "Create bluetooth Ble scan timer for uid: %{public}d", uid);
362 std::shared_ptr<StatsHelper::ActiveTimer> bleScanTimer = std::make_shared<StatsHelper::ActiveTimer>();
363 appBluetoothBleScanTimerMap_.insert(
364 std::pair<int32_t, std::shared_ptr<StatsHelper::ActiveTimer>>(uid, bleScanTimer));
365 timer = bleScanTimer;
366 break;
367 }
368 default:
369 STATS_HILOGW(COMP_SVC, "Create active timer failed");
370 break;
371 }
372 return timer;
373 }
374
GetOrCreateTimer(StatsUtils::StatsType statsType,int16_t level)375 std::shared_ptr<StatsHelper::ActiveTimer> BluetoothEntity::GetOrCreateTimer(StatsUtils::StatsType statsType,
376 int16_t level)
377 {
378 std::shared_ptr<StatsHelper::ActiveTimer> timer = nullptr;
379 switch (statsType) {
380 case StatsUtils::STATS_TYPE_BLUETOOTH_BR_ON: {
381 if (bluetoothBrOnTimer_ != nullptr) {
382 STATS_HILOGD(COMP_SVC, "Get blueooth Br on timer");
383 timer = bluetoothBrOnTimer_;
384 break;
385 }
386 STATS_HILOGD(COMP_SVC, "Create blueooth Br on timer");
387 bluetoothBrOnTimer_ = std::make_shared<StatsHelper::ActiveTimer>();
388 timer = bluetoothBrOnTimer_;
389 break;
390 }
391 case StatsUtils::STATS_TYPE_BLUETOOTH_BLE_ON: {
392 if (bluetoothBleOnTimer_ != nullptr) {
393 STATS_HILOGD(COMP_SVC, "Get blueooth Ble on timer");
394 timer = bluetoothBleOnTimer_;
395 break;
396 }
397 STATS_HILOGD(COMP_SVC, "Create blueooth Ble on timer");
398 bluetoothBleOnTimer_ = std::make_shared<StatsHelper::ActiveTimer>();
399 timer = bluetoothBleOnTimer_;
400 break;
401 }
402 default:
403 STATS_HILOGW(COMP_SVC, "Create active timer failed");
404 break;
405 }
406 return timer;
407 }
408
GetBluetoothUidPower()409 double BluetoothEntity::GetBluetoothUidPower()
410 {
411 double bluetoothUidPower = StatsUtils::DEFAULT_VALUE;
412 auto bundleObj =
413 DelayedSingleton<AppExecFwk::SysMrgClient>::GetInstance()->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
414 if (bundleObj == nullptr) {
415 STATS_HILOGW(COMP_SVC, "Failed to get bundle manager service, return 0");
416 return bluetoothUidPower;
417 }
418
419 sptr<AppExecFwk::IBundleMgr> bmgr = iface_cast<AppExecFwk::IBundleMgr>(bundleObj);
420 if (bmgr == nullptr) {
421 STATS_HILOGW(COMP_SVC, "Failed to get bundle manager proxy, return 0");
422 return bluetoothUidPower;
423 }
424
425 std::string bundleName = "com.ohos.bluetooth";
426 std::string identity = IPCSkeleton::ResetCallingIdentity();
427 int32_t bluetoothUid = bmgr->GetUidByBundleName(bundleName, AppExecFwk::Constants::DEFAULT_USERID);
428 IPCSkeleton::SetCallingIdentity(identity);
429
430 auto core = g_statsService->GetBatteryStatsCore();
431 auto uidEntity = core->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_APP);
432 if (uidEntity != nullptr) {
433 bluetoothUidPower = uidEntity->GetEntityPowerMah(bluetoothUid);
434 }
435 STATS_HILOGD(COMP_SVC, "Get bluetooth uid power consumption: %{public}lfmAh", bluetoothUidPower);
436 return bluetoothUidPower;
437 }
438
DumpInfo(std::string & result,int32_t uid)439 void BluetoothEntity::DumpInfo(std::string& result, int32_t uid)
440 {
441 int64_t brOntime = GetActiveTimeMs(StatsUtils::STATS_TYPE_BLUETOOTH_BR_ON);
442 int64_t bleOntime = GetActiveTimeMs(StatsUtils::STATS_TYPE_BLUETOOTH_BR_ON);
443 result.append("Bluetooth dump:\n")
444 .append("Bluetooth Br on time: ")
445 .append(ToString(brOntime))
446 .append("ms")
447 .append("\n")
448 .append("Bluetooth Ble on time: ")
449 .append(ToString(bleOntime))
450 .append("ms")
451 .append("\n");
452 }
453 } // namespace PowerMgr
454 } // namespace OHOS
455