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