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