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/uid_entity.h"
17 
18 #ifdef SYS_MGR_CLIENT_ENABLE
19 #include <bundle_constants.h>
20 #include <bundle_mgr_interface.h>
21 #include <ipc_skeleton.h>
22 #include <system_ability_definition.h>
23 #include <sys_mgr_client.h>
24 #endif
25 
26 #include <ohos_account_kits_impl.h>
27 #include "battery_stats_service.h"
28 #include "stats_log.h"
29 
30 namespace OHOS {
31 namespace PowerMgr {
32 namespace {
33 }
34 
UidEntity()35 UidEntity::UidEntity()
36 {
37     consumptionType_ = BatteryStatsInfo::CONSUMPTION_TYPE_APP;
38 }
39 
UpdateUidMap(int32_t uid)40 void UidEntity::UpdateUidMap(int32_t uid)
41 {
42     std::lock_guard<std::mutex> lock(uidEntityMutex_);
43     if (uid > StatsUtils::INVALID_VALUE) {
44         auto iter = uidPowerMap_.find(uid);
45         if (iter != uidPowerMap_.end()) {
46             STATS_HILOGD(COMP_SVC, "Uid has already been added, ignore");
47         } else {
48             STATS_HILOGD(COMP_SVC, "Update %{public}d to uid power map", uid);
49             uidPowerMap_.insert(std::pair<int32_t, double>(uid, StatsUtils::DEFAULT_VALUE));
50         }
51     }
52 }
53 
GetUids()54 std::vector<int32_t> UidEntity::GetUids()
55 {
56     std::lock_guard<std::mutex> lock(uidEntityMutex_);
57     std::vector<int32_t> uids;
58     std::transform(uidPowerMap_.begin(), uidPowerMap_.end(), std::back_inserter(uids), [](const auto& item) {
59         return item.first;
60     });
61     return uids;
62 }
63 
CalculateForConnectivity(int32_t uid)64 double UidEntity::CalculateForConnectivity(int32_t uid)
65 {
66     double power = StatsUtils::DEFAULT_VALUE;
67     auto bss = BatteryStatsService::GetInstance();
68     auto core = bss->GetBatteryStatsCore();
69     auto bluetoothEntity = core->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_BLUETOOTH);
70 
71     // Calculate bluetooth power consumption
72     bluetoothEntity->Calculate(uid);
73     power += bluetoothEntity->GetEntityPowerMah(uid);
74     STATS_HILOGD(COMP_SVC, "Connectivity power consumption: %{public}lfmAh for uid: %{public}d", power, uid);
75     return power;
76 }
77 
CalculateForCommon(int32_t uid)78 double UidEntity::CalculateForCommon(int32_t uid)
79 {
80     double power = StatsUtils::DEFAULT_VALUE;
81     auto bss = BatteryStatsService::GetInstance();
82     auto core = bss->GetBatteryStatsCore();
83     auto cameraEntity = core->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_CAMERA);
84     auto flashlightEntity = core->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_FLASHLIGHT);
85     auto audioEntity = core->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_AUDIO);
86     auto sensorEntity = core->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_SENSOR);
87     auto gnssEntity = core->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_GNSS);
88     auto cpuEntity = core->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_CPU);
89     auto wakelockEntity = core->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_WAKELOCK);
90     auto alarmEntity = core->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_ALARM);
91 
92     // Calculate camera power consumption
93     cameraEntity->Calculate(uid);
94     power += cameraEntity->GetEntityPowerMah(uid);
95     // Calculate flashlight power consumption
96     flashlightEntity->Calculate(uid);
97     power += flashlightEntity->GetEntityPowerMah(uid);
98     // Calculate audio power consumption
99     audioEntity->Calculate(uid);
100     power += audioEntity->GetEntityPowerMah(uid);
101     // Calculate sensor power consumption
102     sensorEntity->Calculate(uid);
103     power += sensorEntity->GetEntityPowerMah(uid);
104     // Calculate gnss power consumption
105     gnssEntity->Calculate(uid);
106     power += gnssEntity->GetEntityPowerMah(uid);
107     // Calculate cpu power consumption
108     cpuEntity->Calculate(uid);
109     power += cpuEntity->GetEntityPowerMah(uid);
110     // Calculate cpu power consumption
111     wakelockEntity->Calculate(uid);
112     power += wakelockEntity->GetEntityPowerMah(uid);
113     // Calculate alarm power consumption
114     alarmEntity->Calculate(uid);
115     power += alarmEntity->GetEntityPowerMah(uid);
116 
117     STATS_HILOGD(COMP_SVC, "Common power consumption: %{public}lfmAh for uid: %{public}d", power, uid);
118     return power;
119 }
120 
Calculate(int32_t uid)121 void UidEntity::Calculate(int32_t uid)
122 {
123     auto bss = BatteryStatsService::GetInstance();
124     std::lock_guard<std::mutex> lock(uidEntityMutex_);
125     auto core = bss->GetBatteryStatsCore();
126     auto userEntity = core->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_USER);
127     for (auto& iter : uidPowerMap_) {
128         double power = StatsUtils::DEFAULT_VALUE;
129         power += CalculateForConnectivity(iter.first);
130         power += CalculateForCommon(iter.first);
131         iter.second = power;
132         totalPowerMah_ += power;
133         AddtoStatsList(iter.first, power);
134         int32_t uid = iter.first;
135         int32_t userId = AccountSA::OhosAccountKits::GetInstance().GetDeviceAccountIdByUID(uid);
136         if (userEntity != nullptr) {
137             userEntity->AggregateUserPowerMah(userId, power);
138         }
139     }
140 }
141 
AddtoStatsList(int32_t uid,double power)142 void UidEntity::AddtoStatsList(int32_t uid, double power)
143 {
144     std::shared_ptr<BatteryStatsInfo> statsInfo = std::make_shared<BatteryStatsInfo>();
145     statsInfo->SetConsumptioType(BatteryStatsInfo::CONSUMPTION_TYPE_APP);
146     statsInfo->SetUid(uid);
147     statsInfo->SetPower(power);
148     statsInfoList_.push_back(statsInfo);
149 }
150 
GetEntityPowerMah(int32_t uidOrUserId)151 double UidEntity::GetEntityPowerMah(int32_t uidOrUserId)
152 {
153     std::lock_guard<std::mutex> lock(uidEntityMutex_);
154     double power = StatsUtils::DEFAULT_VALUE;
155     auto iter = uidPowerMap_.find(uidOrUserId);
156     if (iter != uidPowerMap_.end()) {
157         power = iter->second;
158         STATS_HILOGD(COMP_SVC, "Get app uid power consumption: %{public}lfmAh for uid: %{public}d",
159             power, uidOrUserId);
160     } else {
161         STATS_HILOGD(COMP_SVC,
162             "No app uid power consumption related to uid: %{public}d was found, return 0", uidOrUserId);
163     }
164     return power;
165 }
166 
GetPowerForConnectivity(StatsUtils::StatsType statsType,int32_t uid)167 double UidEntity::GetPowerForConnectivity(StatsUtils::StatsType statsType, int32_t uid)
168 {
169     double power = StatsUtils::DEFAULT_VALUE;
170     auto bss = BatteryStatsService::GetInstance();
171     auto core = bss->GetBatteryStatsCore();
172     auto bluetoothEntity = core->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_BLUETOOTH);
173 
174     if (statsType == StatsUtils::STATS_TYPE_BLUETOOTH_BR_SCAN) {
175         power = bluetoothEntity->GetStatsPowerMah(StatsUtils::STATS_TYPE_BLUETOOTH_BR_SCAN, uid);
176     } else if (statsType == StatsUtils::STATS_TYPE_BLUETOOTH_BLE_SCAN) {
177         power = bluetoothEntity->GetStatsPowerMah(StatsUtils::STATS_TYPE_BLUETOOTH_BLE_SCAN, uid);
178     }
179     return power;
180 }
181 
GetPowerForCommon(StatsUtils::StatsType statsType,int32_t uid)182 double UidEntity::GetPowerForCommon(StatsUtils::StatsType statsType, int32_t uid)
183 {
184     double power = StatsUtils::DEFAULT_VALUE;
185     auto bss = BatteryStatsService::GetInstance();
186     auto core = bss->GetBatteryStatsCore();
187     auto cameraEntity = core->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_CAMERA);
188     auto flashlightEntity = core->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_FLASHLIGHT);
189     auto audioEntity = core->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_AUDIO);
190     auto sensorEntity = core->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_SENSOR);
191     auto gnssEntity = core->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_GNSS);
192     auto cpuEntity = core->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_CPU);
193     auto wakelockEntity = core->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_WAKELOCK);
194     auto alarmEntity = core->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_ALARM);
195 
196     if (statsType == StatsUtils::STATS_TYPE_CAMERA_ON) {
197         power = cameraEntity->GetStatsPowerMah(StatsUtils::STATS_TYPE_CAMERA_ON, uid);
198     } else if (statsType == StatsUtils::STATS_TYPE_FLASHLIGHT_ON) {
199         power = flashlightEntity->GetStatsPowerMah(StatsUtils::STATS_TYPE_FLASHLIGHT_ON, uid);
200     } else if (statsType == StatsUtils::STATS_TYPE_GNSS_ON) {
201         power = gnssEntity->GetStatsPowerMah(StatsUtils::STATS_TYPE_GNSS_ON, uid);
202     } else if (statsType == StatsUtils::STATS_TYPE_SENSOR_GRAVITY_ON) {
203         power = sensorEntity->GetStatsPowerMah(StatsUtils::STATS_TYPE_SENSOR_GRAVITY_ON, uid);
204     } else if (statsType == StatsUtils::STATS_TYPE_SENSOR_PROXIMITY_ON) {
205         power = sensorEntity->GetStatsPowerMah(StatsUtils::STATS_TYPE_SENSOR_PROXIMITY_ON, uid);
206     } else if (statsType == StatsUtils::STATS_TYPE_AUDIO_ON) {
207         power = audioEntity->GetStatsPowerMah(StatsUtils::STATS_TYPE_AUDIO_ON, uid);
208     } else if (statsType == StatsUtils::STATS_TYPE_WAKELOCK_HOLD) {
209         power = wakelockEntity->GetStatsPowerMah(StatsUtils::STATS_TYPE_WAKELOCK_HOLD, uid);
210     } else if (statsType == StatsUtils::STATS_TYPE_CPU_CLUSTER) {
211         power = cpuEntity->GetStatsPowerMah(StatsUtils::STATS_TYPE_CPU_CLUSTER, uid);
212     } else if (statsType == StatsUtils::STATS_TYPE_CPU_SPEED) {
213         power = cpuEntity->GetStatsPowerMah(StatsUtils::STATS_TYPE_CPU_SPEED, uid);
214     } else if (statsType == StatsUtils::STATS_TYPE_CPU_ACTIVE) {
215         power = cpuEntity->GetStatsPowerMah(StatsUtils::STATS_TYPE_CPU_ACTIVE, uid);
216     } else if (statsType == StatsUtils::STATS_TYPE_ALARM) {
217         power = alarmEntity->GetStatsPowerMah(StatsUtils::STATS_TYPE_ALARM, uid);
218     }
219     return power;
220 }
221 
GetStatsPowerMah(StatsUtils::StatsType statsType,int32_t uid)222 double UidEntity::GetStatsPowerMah(StatsUtils::StatsType statsType, int32_t uid)
223 {
224     double power = StatsUtils::DEFAULT_VALUE;
225 
226     switch (statsType) {
227         case StatsUtils::STATS_TYPE_BLUETOOTH_BR_SCAN:
228         case StatsUtils::STATS_TYPE_BLUETOOTH_BLE_SCAN:
229             power = GetPowerForConnectivity(statsType, uid);
230             break;
231         case StatsUtils::STATS_TYPE_CAMERA_ON:
232         case StatsUtils::STATS_TYPE_FLASHLIGHT_ON:
233         case StatsUtils::STATS_TYPE_GNSS_ON:
234         case StatsUtils::STATS_TYPE_SENSOR_GRAVITY_ON:
235         case StatsUtils::STATS_TYPE_SENSOR_PROXIMITY_ON:
236         case StatsUtils::STATS_TYPE_AUDIO_ON:
237         case StatsUtils::STATS_TYPE_WAKELOCK_HOLD:
238         case StatsUtils::STATS_TYPE_CPU_CLUSTER:
239         case StatsUtils::STATS_TYPE_CPU_SPEED:
240         case StatsUtils::STATS_TYPE_CPU_ACTIVE:
241         case StatsUtils::STATS_TYPE_ALARM:
242             power = GetPowerForCommon(statsType, uid);
243             break;
244         default:
245             STATS_HILOGW(COMP_SVC, "Invalid or illegal type got, return 0");
246             break;
247     }
248 
249     STATS_HILOGD(COMP_SVC, "Get %{public}s power: %{public}lfmAh for uid: %{public}d",
250         StatsUtils::ConvertStatsType(statsType).c_str(), power, uid);
251     return power;
252 }
253 
Reset()254 void UidEntity::Reset()
255 {
256     std::lock_guard<std::mutex> lock(uidEntityMutex_);
257     // Reset app Uid total power consumption
258     for (auto& iter : uidPowerMap_) {
259         iter.second = StatsUtils::DEFAULT_VALUE;
260     }
261 }
262 
DumpForBluetooth(int32_t uid,std::string & result)263 void UidEntity::DumpForBluetooth(int32_t uid, std::string& result)
264 {
265     auto bss = BatteryStatsService::GetInstance();
266     // Dump for bluetooth realted info
267     auto core = bss->GetBatteryStatsCore();
268     int64_t bluetoothBrScanTime = core->GetTotalTimeMs(uid, StatsUtils::STATS_TYPE_BLUETOOTH_BR_SCAN);
269     int64_t bluetoothBleScanTime = core->GetTotalTimeMs(uid, StatsUtils::STATS_TYPE_BLUETOOTH_BLE_SCAN);
270 
271     result.append("Bluetooth Br scan time: ")
272         .append(ToString(bluetoothBrScanTime))
273         .append("ms\n")
274         .append("Bluetooth Ble scan time: ")
275         .append(ToString(bluetoothBleScanTime))
276         .append("ms\n");
277 }
278 
DumpForCommon(int32_t uid,std::string & result)279 void UidEntity::DumpForCommon(int32_t uid, std::string& result)
280 {
281     auto bss = BatteryStatsService::GetInstance();
282     auto core = bss->GetBatteryStatsCore();
283     // Dump for camera related info
284     int64_t cameraTime = core->GetTotalTimeMs(uid, StatsUtils::STATS_TYPE_CAMERA_ON);
285 
286     // Dump for flashlight related info
287     int64_t flashlightTime = core->GetTotalTimeMs(uid, StatsUtils::STATS_TYPE_FLASHLIGHT_ON);
288 
289     // Dump for gnss related info
290     int64_t gnssTime = core->GetTotalTimeMs(uid, StatsUtils::STATS_TYPE_GNSS_ON);
291 
292     // Dump for gravity sensor related info
293     int64_t gravityTime = core->GetTotalTimeMs(uid, StatsUtils::STATS_TYPE_SENSOR_GRAVITY_ON);
294 
295     // Dump for proximity sensor related info
296     int64_t proximityTime = core->GetTotalTimeMs(uid, StatsUtils::STATS_TYPE_SENSOR_PROXIMITY_ON);
297 
298     // Dump for audio related info
299     int64_t audioTime = core->GetTotalTimeMs(uid, StatsUtils::STATS_TYPE_AUDIO_ON);
300 
301     // Dump for wakelock related info
302     int64_t wakelockTime = core->GetTotalTimeMs(uid, StatsUtils::STATS_TYPE_WAKELOCK_HOLD);
303 
304     // Dump for alarm related info
305     int64_t alarmCount = core->GetTotalConsumptionCount(StatsUtils::STATS_TYPE_ALARM, uid);
306 
307     result.append("Camera on time: ")
308         .append(ToString(cameraTime))
309         .append("ms\n")
310         .append("Flashlight scan time: ")
311         .append(ToString(flashlightTime))
312         .append("ms\n")
313         .append("GNSS scan time: ")
314         .append(ToString(gnssTime))
315         .append("ms\n")
316         .append("Gravity sensor on time: ")
317         .append(ToString(gravityTime))
318         .append("ms\n")
319         .append("Proximity sensor on time: ")
320         .append(ToString(proximityTime))
321         .append("ms\n")
322         .append("Audio on time: ")
323         .append(ToString(audioTime))
324         .append("ms\n")
325         .append("Wakelock hold time: ")
326         .append(ToString(wakelockTime))
327         .append("ms\n")
328         .append("Alarm trigger count: ")
329         .append(ToString(alarmCount))
330         .append("times\n");
331 }
332 
DumpInfo(std::string & result,int32_t uid)333 void UidEntity::DumpInfo(std::string& result, int32_t uid)
334 {
335     auto bss = BatteryStatsService::GetInstance();
336     std::lock_guard<std::mutex> lock(uidEntityMutex_);
337     auto core = bss->GetBatteryStatsCore();
338     for (auto& iter : uidPowerMap_) {
339         std::string bundleName = "NULL";
340 #ifdef SYS_MGR_CLIENT_ENABLE
341         auto bundleObj =
342             DelayedSingleton<AppExecFwk::SysMrgClient>::GetInstance()
343                 ->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID);
344         if (bundleObj == nullptr) {
345             STATS_HILOGE(COMP_SVC, "Failed to get bundle manager service");
346         } else {
347             sptr<AppExecFwk::IBundleMgr> bmgr = iface_cast<AppExecFwk::IBundleMgr>(bundleObj);
348             if (bmgr == nullptr) {
349                 STATS_HILOGE(COMP_SVC, "Failed to get bundle manager proxy");
350             } else {
351                 std::string identity = IPCSkeleton::ResetCallingIdentity();
352                 ErrCode res = bmgr->GetNameForUid(iter.first, bundleName);
353                 IPCSkeleton::SetCallingIdentity(identity);
354                 if (res != ERR_OK) {
355                     STATS_HILOGE(COMP_SVC, "Failed to get bundle name for uid=%{public}d, ErrCode=%{public}d",
356                         iter.first, static_cast<int32_t>(res));
357                 }
358             }
359         }
360 #endif
361         result.append("\n")
362             .append(ToString(iter.first))
363             .append("(Bundle name: ")
364             .append(bundleName)
365             .append(")")
366             .append(":")
367             .append("\n");
368         DumpForBluetooth(iter.first, result);
369         DumpForCommon(iter.first, result);
370         auto cpuEntity = core->GetEntity(BatteryStatsInfo::CONSUMPTION_TYPE_CPU);
371         if (cpuEntity) {
372             cpuEntity->DumpInfo(result, iter.first);
373         }
374     }
375 }
376 } // namespace PowerMgr
377 } // namespace OHOS