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