1 /*
2 * Copyright (C) 2021 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 #include "src/android_internal/power_stats.h"
18
19 #include "perfetto/ext/base/utils.h"
20
21 #include <string.h>
22
23 #include <algorithm>
24 #include <memory>
25 #include <vector>
26
27 // Legacy HAL interfacte for devices shipped before Android S.
28 #include <android/hardware/power/stats/1.0/IPowerStats.h>
29
30 // AIDL interface for Android S+.
31 #include <android/hardware/power/stats/IPowerStats.h>
32
33 #include <binder/IServiceManager.h>
34
35 namespace perfetto {
36 namespace android_internal {
37
38 namespace hal = android::hardware::power::stats::V1_0;
39 namespace aidl = android::hardware::power::stats;
40
41 namespace {
42
43 // Common interface for data from power stats service. Devices prior to
44 // Android S, uses the HAL interface while device from Android S or later
45 // uses the AIDL interfact.
46 class PowerStatsDataProvider {
47 public:
48 virtual bool GetAvailableRails(RailDescriptor*, size_t* size_of_arr) = 0;
49 virtual bool GetRailEnergyData(RailEnergyData*, size_t* size_of_arr) = 0;
50
51 // Available from Android S+.
52 virtual bool GetEnergyConsumerInfo(EnergyConsumerInfo* consumers,
53 size_t* size_of_arr) = 0;
54 virtual bool GetEnergyConsumed(EnergyEstimationBreakdown* breakdown,
55 size_t* size_of_arr) = 0;
56 virtual bool GetPowerEntityStates(PowerEntityState* state,
57 size_t* size_of_arr) = 0;
58 virtual bool GetPowerEntityStateResidency(PowerEntityStateResidency* state,
59 size_t* size_of_arr) = 0;
60 virtual ~PowerStatsDataProvider() = default;
61 };
62
63 class PowerStatsHalDataProvider : public PowerStatsDataProvider {
64 public:
65 bool GetAvailableRails(RailDescriptor*, size_t* size_of_arr) override;
66 bool GetRailEnergyData(RailEnergyData*, size_t* size_of_arr) override;
67 bool GetEnergyConsumerInfo(EnergyConsumerInfo* consumers,
68 size_t* size_of_arr) override;
69 bool GetEnergyConsumed(EnergyEstimationBreakdown* breakdown,
70 size_t* size_of_arr) override;
71 bool GetPowerEntityStates(PowerEntityState* state,
72 size_t* size_of_arr) override;
73 bool GetPowerEntityStateResidency(PowerEntityStateResidency* state,
74 size_t* size_of_arr) override;
75
76 PowerStatsHalDataProvider() = default;
77 ~PowerStatsHalDataProvider() override = default;
78
79 private:
80 android::sp<hal::IPowerStats> svc_;
81 hal::IPowerStats* MaybeGetService();
82 };
83
84 class PowerStatsAidlDataProvider : public PowerStatsDataProvider {
85 public:
86 static constexpr char INSTANCE[] =
87 "android.hardware.power.stats.IPowerStats/default";
88
89 bool GetAvailableRails(RailDescriptor*, size_t* size_of_arr) override;
90 bool GetRailEnergyData(RailEnergyData*, size_t* size_of_arr) override;
91 bool GetEnergyConsumerInfo(EnergyConsumerInfo* consumers,
92 size_t* size_of_arr) override;
93 bool GetEnergyConsumed(EnergyEstimationBreakdown* breakdown,
94 size_t* size_of_arr) override;
95 bool GetPowerEntityStates(PowerEntityState* state,
96 size_t* size_of_arr) override;
97 bool GetPowerEntityStateResidency(PowerEntityStateResidency* state,
98 size_t* size_of_arr) override;
99
100 PowerStatsAidlDataProvider() = default;
101 ~PowerStatsAidlDataProvider() override = default;
102
103 private:
104 android::sp<aidl::IPowerStats> svc_;
105
106 aidl::IPowerStats* MaybeGetService();
107 void ResetService();
108 };
109
GetDataProvider()110 PowerStatsDataProvider* GetDataProvider() {
111 static std::unique_ptr<PowerStatsDataProvider> data_provider;
112 if (data_provider == nullptr) {
113 const android::sp<android::IServiceManager> sm =
114 android::defaultServiceManager();
115 if (sm->isDeclared(
116 android::String16(PowerStatsAidlDataProvider::INSTANCE))) {
117 data_provider = std::make_unique<PowerStatsAidlDataProvider>();
118 } else {
119 data_provider = std::make_unique<PowerStatsHalDataProvider>();
120 }
121 }
122 return data_provider.get();
123 }
124
125 } // anonymous namespace
126
GetAvailableRails(RailDescriptor * descriptor,size_t * size_of_arr)127 bool GetAvailableRails(RailDescriptor* descriptor, size_t* size_of_arr) {
128 return GetDataProvider()->GetAvailableRails(descriptor, size_of_arr);
129 }
130
GetRailEnergyData(RailEnergyData * data,size_t * size_of_arr)131 bool GetRailEnergyData(RailEnergyData* data, size_t* size_of_arr) {
132 return GetDataProvider()->GetRailEnergyData(data, size_of_arr);
133 }
134
GetEnergyConsumerInfo(EnergyConsumerInfo * consumers,size_t * size_of_arr)135 bool GetEnergyConsumerInfo(EnergyConsumerInfo* consumers, size_t* size_of_arr) {
136 return GetDataProvider()->GetEnergyConsumerInfo(consumers, size_of_arr);
137 }
138
GetEnergyConsumed(EnergyEstimationBreakdown * breakdown,size_t * size_of_arr)139 bool GetEnergyConsumed(EnergyEstimationBreakdown* breakdown,
140 size_t* size_of_arr) {
141 return GetDataProvider()->GetEnergyConsumed(breakdown, size_of_arr);
142 }
143
GetPowerEntityStates(PowerEntityState * state,size_t * size_of_arr)144 bool GetPowerEntityStates(PowerEntityState* state, size_t* size_of_arr) {
145 return GetDataProvider()->GetPowerEntityStates(state, size_of_arr);
146 }
147
GetPowerEntityStateResidency(PowerEntityStateResidency * residency,size_t * size_of_arr)148 bool GetPowerEntityStateResidency(PowerEntityStateResidency* residency,
149 size_t* size_of_arr) {
150 return GetDataProvider()->GetPowerEntityStateResidency(residency,
151 size_of_arr);
152 }
153
154 /*** Power Stats HAL Implemenation *******************************************/
155
156 using android::hardware::hidl_vec;
157 using android::hardware::Return;
158
MaybeGetService()159 hal::IPowerStats* PowerStatsHalDataProvider::MaybeGetService() {
160 if (svc_ == nullptr) {
161 svc_ = hal::IPowerStats::tryGetService();
162 }
163 return svc_.get();
164 }
165
GetAvailableRails(RailDescriptor * rail_descriptors,size_t * size_of_arr)166 bool PowerStatsHalDataProvider::GetAvailableRails(
167 RailDescriptor* rail_descriptors,
168 size_t* size_of_arr) {
169 const size_t in_array_size = *size_of_arr;
170 *size_of_arr = 0;
171 hal::IPowerStats* svc = MaybeGetService();
172 if (svc == nullptr) {
173 return false;
174 }
175
176 hal::Status status;
177 auto rails_cb = [rail_descriptors, size_of_arr, &in_array_size, &status](
178 hidl_vec<hal::RailInfo> r, hal::Status s) {
179 status = s;
180 if (status == hal::Status::SUCCESS) {
181 *size_of_arr = std::min(in_array_size, r.size());
182 for (int i = 0; i < *size_of_arr; ++i) {
183 const hal::RailInfo& rail_info = r[i];
184 RailDescriptor& descriptor = rail_descriptors[i];
185
186 descriptor.index = rail_info.index;
187 descriptor.sampling_rate = rail_info.samplingRate;
188
189 strlcpy(descriptor.rail_name, rail_info.railName.c_str(),
190 sizeof(descriptor.rail_name));
191 strlcpy(descriptor.subsys_name, rail_info.subsysName.c_str(),
192 sizeof(descriptor.subsys_name));
193 }
194 }
195 };
196
197 Return<void> ret = svc->getRailInfo(rails_cb);
198 return status == hal::Status::SUCCESS;
199 }
200
GetRailEnergyData(RailEnergyData * rail_energy_array,size_t * size_of_arr)201 bool PowerStatsHalDataProvider::GetRailEnergyData(
202 RailEnergyData* rail_energy_array,
203 size_t* size_of_arr) {
204 const size_t in_array_size = *size_of_arr;
205 *size_of_arr = 0;
206
207 hal::IPowerStats* svc = MaybeGetService();
208 if (svc == nullptr) {
209 return false;
210 }
211
212 hal::Status status;
213 auto energy_cb = [rail_energy_array, size_of_arr, &in_array_size, &status](
214 hidl_vec<hal::EnergyData> m, hal::Status s) {
215 status = s;
216 if (status == hal::Status::SUCCESS) {
217 *size_of_arr = std::min(in_array_size, m.size());
218 for (int i = 0; i < *size_of_arr; ++i) {
219 const hal::EnergyData& measurement = m[i];
220 RailEnergyData& element = rail_energy_array[i];
221
222 element.index = measurement.index;
223 element.timestamp = measurement.timestamp;
224 element.energy = measurement.energy;
225 }
226 }
227 };
228
229 Return<void> ret = svc_->getEnergyData(hidl_vec<uint32_t>(), energy_cb);
230 return status == hal::Status::SUCCESS;
231 }
232
GetEnergyConsumerInfo(EnergyConsumerInfo *,size_t *)233 bool PowerStatsHalDataProvider::GetEnergyConsumerInfo(EnergyConsumerInfo*,
234 size_t*) {
235 return false;
236 }
237
GetEnergyConsumed(EnergyEstimationBreakdown *,size_t *)238 bool PowerStatsHalDataProvider::GetEnergyConsumed(EnergyEstimationBreakdown*,
239 size_t*) {
240 return false;
241 }
242
GetPowerEntityStates(PowerEntityState *,size_t *)243 bool PowerStatsHalDataProvider::GetPowerEntityStates(PowerEntityState*,
244 size_t*) {
245 return false;
246 }
247
GetPowerEntityStateResidency(PowerEntityStateResidency *,size_t *)248 bool PowerStatsHalDataProvider::GetPowerEntityStateResidency(
249 PowerEntityStateResidency*,
250 size_t*) {
251 return false;
252 }
253
254 /*** End of Power Stats HAL Implemenation *************************************/
255
256 /*** Power Stats AIDL Implemenation *******************************************/
MaybeGetService()257 aidl::IPowerStats* PowerStatsAidlDataProvider::MaybeGetService() {
258 if (svc_ == nullptr) {
259 svc_ = android::checkDeclaredService<aidl::IPowerStats>(
260 android::String16(INSTANCE));
261 }
262 return svc_.get();
263 }
264
ResetService()265 void PowerStatsAidlDataProvider::ResetService() {
266 svc_.clear();
267 }
268
GetAvailableRails(RailDescriptor * descriptor,size_t * size_of_arr)269 bool PowerStatsAidlDataProvider::GetAvailableRails(RailDescriptor* descriptor,
270 size_t* size_of_arr) {
271 const size_t in_array_size = *size_of_arr;
272 *size_of_arr = 0;
273
274 aidl::IPowerStats* svc = MaybeGetService();
275 if (svc_ == nullptr) {
276 return false;
277 }
278
279 std::vector<aidl::Channel> results;
280 android::binder::Status status = svc->getEnergyMeterInfo(&results);
281 if (!status.isOk()) {
282 if (status.transactionError() == android::DEAD_OBJECT) {
283 // Service has died. Reset it to attempt to acquire a new one next time.
284 ResetService();
285 }
286 return false;
287 }
288
289 size_t max_size = std::min(in_array_size, results.size());
290 for (const auto& result : results) {
291 if (*size_of_arr >= max_size) {
292 break;
293 }
294 auto& cur = descriptor[(*size_of_arr)++];
295 cur.index = result.id;
296 cur.sampling_rate = 0;
297 strlcpy(cur.rail_name, result.name.c_str(), sizeof(cur.rail_name));
298 strlcpy(cur.subsys_name, result.subsystem.c_str(), sizeof(cur.subsys_name));
299 }
300 return true;
301 }
302
GetRailEnergyData(RailEnergyData * data,size_t * size_of_arr)303 bool PowerStatsAidlDataProvider::GetRailEnergyData(RailEnergyData* data,
304 size_t* size_of_arr) {
305 const size_t in_array_size = *size_of_arr;
306 *size_of_arr = 0;
307
308 aidl::IPowerStats* svc = MaybeGetService();
309 if (svc == nullptr) {
310 return false;
311 }
312
313 std::vector<int> ids;
314 std::vector<aidl::EnergyMeasurement> results;
315 android::binder::Status status = svc->readEnergyMeter(ids, &results);
316 if (!status.isOk()) {
317 if (status.transactionError() == android::DEAD_OBJECT) {
318 // Service has died. Reset it to attempt to acquire a new one next time.
319 ResetService();
320 }
321 return false;
322 }
323
324 size_t max_size = std::min(in_array_size, results.size());
325 for (const auto& result : results) {
326 if (*size_of_arr >= max_size) {
327 break;
328 }
329 auto& cur = data[(*size_of_arr)++];
330 cur.index = result.id;
331 cur.timestamp = result.timestampMs;
332 cur.energy = result.energyUWs;
333 }
334 return true;
335 }
336
GetEnergyConsumerInfo(EnergyConsumerInfo * consumers,size_t * size_of_arr)337 bool PowerStatsAidlDataProvider::GetEnergyConsumerInfo(
338 EnergyConsumerInfo* consumers,
339 size_t* size_of_arr) {
340 const size_t in_array_size = *size_of_arr;
341 *size_of_arr = 0;
342
343 aidl::IPowerStats* svc = MaybeGetService();
344 if (svc == nullptr) {
345 return false;
346 }
347 std::vector<aidl::EnergyConsumer> results;
348 android::binder::Status status = svc->getEnergyConsumerInfo(&results);
349
350 if (!status.isOk()) {
351 if (status.transactionError() == android::DEAD_OBJECT) {
352 // Service has died. Reset it to attempt to acquire a new one next time.
353 ResetService();
354 }
355 return false;
356 }
357 size_t max_size = std::min(in_array_size, results.size());
358 for (const auto& result : results) {
359 if (*size_of_arr >= max_size) {
360 break;
361 }
362 auto& cur = consumers[(*size_of_arr)++];
363 cur.energy_consumer_id = result.id;
364 cur.ordinal = result.ordinal;
365 strlcpy(cur.type, aidl::toString(result.type).c_str(), sizeof(cur.type));
366 strlcpy(cur.name, result.name.c_str(), sizeof(cur.name));
367 }
368 return true;
369 }
GetEnergyConsumed(EnergyEstimationBreakdown * breakdown,size_t * size_of_arr)370 bool PowerStatsAidlDataProvider::GetEnergyConsumed(
371 EnergyEstimationBreakdown* breakdown,
372 size_t* size_of_arr) {
373 const size_t in_array_size = *size_of_arr;
374 *size_of_arr = 0;
375
376 aidl::IPowerStats* svc = MaybeGetService();
377 if (svc == nullptr) {
378 return false;
379 }
380
381 std::vector<int> ids;
382 std::vector<aidl::EnergyConsumerResult> results;
383 android::binder::Status status = svc->getEnergyConsumed(ids, &results);
384
385 if (!status.isOk()) {
386 if (status.transactionError() == android::DEAD_OBJECT) {
387 // Service has died. Reset it to attempt to acquire a new one next time.
388 ResetService();
389 }
390 return false;
391 }
392
393 size_t max_size = std::min(in_array_size, results.size());
394 // Iterate through all consumer ID.
395 for (const auto& result : results) {
396 if (*size_of_arr >= max_size) {
397 break;
398 }
399 auto& cur = breakdown[(*size_of_arr)++];
400 cur.energy_consumer_id = result.id;
401 cur.uid = ALL_UIDS_FOR_CONSUMER;
402 cur.energy_uws = result.energyUWs;
403
404 // Iterate through all UIDs for this consumer.
405 for (const auto& attribution : result.attribution) {
406 if (*size_of_arr >= max_size) {
407 break;
408 }
409 auto& cur = breakdown[(*size_of_arr)++];
410 cur.energy_consumer_id = result.id;
411 cur.uid = attribution.uid;
412 cur.energy_uws = attribution.energyUWs;
413 }
414 }
415 return true;
416 }
417
GetPowerEntityStates(PowerEntityState * entity_state,size_t * size_of_arr)418 bool PowerStatsAidlDataProvider::GetPowerEntityStates(
419 PowerEntityState* entity_state,
420 size_t* size_of_arr) {
421 const size_t in_array_size = *size_of_arr;
422 *size_of_arr = 0;
423
424 aidl::IPowerStats* svc = MaybeGetService();
425 if (svc == nullptr) {
426 return false;
427 }
428
429 std::vector<aidl::PowerEntity> entities;
430 android::binder::Status status = svc->getPowerEntityInfo(&entities);
431
432 if (!status.isOk()) {
433 if (status.transactionError() == android::DEAD_OBJECT) {
434 // Service has died. Reset it to attempt to acquire a new one next time.
435 ResetService();
436 }
437 return false;
438 }
439
440 // Iterate through all entities.
441 for (const auto& entity : entities) {
442 if (*size_of_arr >= in_array_size) {
443 break;
444 }
445
446 // Iterate through all states for this entity.
447 for (const auto& state : entity.states) {
448 if (*size_of_arr >= in_array_size) {
449 break;
450 }
451 auto& cur = entity_state[(*size_of_arr)++];
452 cur.entity_id = entity.id;
453 strlcpy(cur.entity_name, entity.name.c_str(), sizeof(cur.entity_name));
454 cur.state_id = state.id;
455 strlcpy(cur.state_name, state.name.c_str(), sizeof(cur.state_name));
456 }
457 }
458 return true;
459 }
460
GetPowerEntityStateResidency(PowerEntityStateResidency * residency,size_t * size_of_arr)461 bool PowerStatsAidlDataProvider::GetPowerEntityStateResidency(
462 PowerEntityStateResidency* residency,
463 size_t* size_of_arr) {
464 const size_t in_array_size = *size_of_arr;
465 *size_of_arr = 0;
466
467 aidl::IPowerStats* svc = MaybeGetService();
468 if (svc == nullptr) {
469 return false;
470 }
471
472 std::vector<int> ids;
473 std::vector<aidl::StateResidencyResult> entities;
474 android::binder::Status status = svc->getStateResidency(ids, &entities);
475
476 if (!status.isOk()) {
477 if (status.transactionError() == android::DEAD_OBJECT) {
478 // Service has died. Reset it to attempt to acquire a new one next time.
479 ResetService();
480 }
481 return false;
482 }
483
484 // Iterate through all entities.
485 for (const auto& entity : entities) {
486 if (*size_of_arr >= in_array_size) {
487 break;
488 }
489
490 // Iterate through all states for this entity.
491 for (const auto& stateResidencyData : entity.stateResidencyData) {
492 if (*size_of_arr >= in_array_size) {
493 break;
494 }
495 auto& cur = residency[(*size_of_arr)++];
496 cur.entity_id = entity.id;
497 cur.state_id = stateResidencyData.id;
498 cur.total_time_in_state_ms = stateResidencyData.totalTimeInStateMs;
499 cur.total_state_entry_count = stateResidencyData.totalStateEntryCount;
500 cur.last_entry_timestamp_ms = stateResidencyData.lastEntryTimestampMs;
501 }
502 }
503 return true;
504 }
505
506 /*** End of Power Stats AIDL Implemenation ************************************/
507
508 } // namespace android_internal
509 } // namespace perfetto
510