xref: /aosp_15_r20/external/perfetto/src/android_internal/health_hal.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2018 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/health_hal.h"
18 
19 #include <aidl/android/hardware/health/IHealth.h>
20 #include <android/binder_manager.h>
21 #include <android/hardware/health/2.0/IHealth.h>
22 #include <healthhalutils/HealthHalUtils.h>
23 
24 namespace perfetto {
25 namespace android_internal {
26 
27 using HidlHealth = ::android::hardware::health::V2_0::IHealth;
28 using ::aidl::android::hardware::health::IHealth;
29 using ::android::hardware::Return;
30 using ::android::hardware::health::V2_0::Result;
31 
32 namespace {
33 
34 struct HealthService {
35   android::sp<HidlHealth> hidl;
36   std::shared_ptr<IHealth> aidl;
37 };
38 
39 HealthService g_svc;
40 
ResetService()41 void ResetService() {
42   auto aidl_name = std::string(IHealth::descriptor) + "/default";
43   if (AServiceManager_isDeclared(aidl_name.c_str())) {
44     ndk::SpAIBinder binder(AServiceManager_waitForService(aidl_name.c_str()));
45     g_svc.aidl = IHealth::fromBinder(binder);
46     if (g_svc.aidl != nullptr) {
47       return;
48     }
49   }
50   g_svc.hidl = ::android::hardware::health::V2_0::get_health_service();
51 }
52 
GetBatteryCounterHidl(BatteryCounter counter,int64_t * value)53 bool GetBatteryCounterHidl(BatteryCounter counter, int64_t* value) {
54   // The Android HIDL documentation states that for blocking services, the
55   // caller blocks until the reply is received and the callback is called inline
56   // in the same thread.
57   // See https://source.android.com/devices/architecture/hidl/threading .
58 
59   Return<void> ret;
60   Result res = Result::UNKNOWN;
61   switch (counter) {
62     case BatteryCounter::kUnspecified:
63       break;
64 
65     case BatteryCounter::kCharge:
66       ret = g_svc.hidl->getChargeCounter(
67           [&res, value](Result hal_res, int32_t hal_value) {
68             res = hal_res;
69             *value = hal_value;
70           });
71       break;
72 
73     case BatteryCounter::kCapacityPercent:
74       ret = g_svc.hidl->getCapacity(
75           [&res, value](Result hal_res, int32_t hal_value) {
76             res = hal_res;
77             *value = hal_value;
78           });
79       break;
80 
81     case BatteryCounter::kCurrent:
82       ret = g_svc.hidl->getCurrentNow(
83           [&res, value](Result hal_res, int32_t hal_value) {
84             res = hal_res;
85             *value = hal_value;
86           });
87       break;
88 
89     case BatteryCounter::kCurrentAvg:
90       ret = g_svc.hidl->getCurrentAverage(
91           [&res, value](Result hal_res, int32_t hal_value) {
92             res = hal_res;
93             *value = hal_value;
94           });
95       break;
96 
97     case BatteryCounter::kVoltage:
98       g_svc.hidl->getHealthInfo(
99           [&res, value](Result hal_res, const auto& hal_health_info) {
100             res = hal_res;
101             // batteryVoltage is in mV, convert to uV.
102             *value = hal_health_info.legacy.batteryVoltage * 1000;
103           });
104       break;
105   }  // switch(counter)
106 
107   if (ret.isDeadObject())
108     g_svc.hidl.clear();
109 
110   return ret.isOk() && res == Result::SUCCESS;
111 }
112 
GetBatteryCounterAidl(BatteryCounter counter,int64_t * value)113 bool GetBatteryCounterAidl(BatteryCounter counter, int64_t* value) {
114   ndk::ScopedAStatus status;
115   int32_t value32;
116 
117   switch (counter) {
118     case BatteryCounter::kUnspecified:
119       return false;
120 
121     case BatteryCounter::kCharge:
122       status = g_svc.aidl->getChargeCounterUah(&value32);
123       break;
124 
125     case BatteryCounter::kCapacityPercent:
126       status = g_svc.aidl->getCapacity(&value32);
127       break;
128 
129     case BatteryCounter::kCurrent:
130       status = g_svc.aidl->getCurrentNowMicroamps(&value32);
131       break;
132 
133     case BatteryCounter::kCurrentAvg:
134       status = g_svc.aidl->getCurrentAverageMicroamps(&value32);
135       break;
136 
137     case BatteryCounter::kVoltage:
138       ::aidl::android::hardware::health::HealthInfo health_info;
139       status = g_svc.aidl->getHealthInfo(&health_info);
140       // Convert from mV to uV.
141       value32 = health_info.batteryVoltageMillivolts * 1000;
142       break;
143   }  // switch(counter)
144 
145   if (status.isOk()) {
146     *value = value32;
147     return true;
148   }
149 
150   if (status.getStatus() == STATUS_DEAD_OBJECT)
151     g_svc.aidl.reset();
152 
153   return false;
154 }
155 
156 }  // namespace
157 
GetBatteryCounter(BatteryCounter counter,int64_t * value)158 bool GetBatteryCounter(BatteryCounter counter, int64_t* value) {
159   *value = 0;
160   if (!g_svc.aidl && !g_svc.hidl)
161     ResetService();
162 
163   if (!g_svc.aidl && !g_svc.hidl)
164     return false;
165 
166   if (g_svc.aidl)
167     return GetBatteryCounterAidl(counter, value);
168 
169   return GetBatteryCounterHidl(counter, value);
170 }
171 
172 }  // namespace android_internal
173 }  // namespace perfetto
174