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 *value = hal_health_info.legacy.batteryVoltage;
102 });
103 break;
104 } // switch(counter)
105
106 if (ret.isDeadObject())
107 g_svc.hidl.clear();
108
109 return ret.isOk() && res == Result::SUCCESS;
110 }
111
GetBatteryCounterAidl(BatteryCounter counter,int64_t * value)112 bool GetBatteryCounterAidl(BatteryCounter counter, int64_t* value) {
113 ndk::ScopedAStatus status;
114 int32_t value32;
115
116 switch (counter) {
117 case BatteryCounter::kUnspecified:
118 return false;
119
120 case BatteryCounter::kCharge:
121 status = g_svc.aidl->getChargeCounterUah(&value32);
122 break;
123
124 case BatteryCounter::kCapacityPercent:
125 status = g_svc.aidl->getCapacity(&value32);
126 break;
127
128 case BatteryCounter::kCurrent:
129 status = g_svc.aidl->getCurrentNowMicroamps(&value32);
130 break;
131
132 case BatteryCounter::kCurrentAvg:
133 status = g_svc.aidl->getCurrentAverageMicroamps(&value32);
134 break;
135
136 case BatteryCounter::kVoltage:
137 ::aidl::android::hardware::health::HealthInfo health_info;
138 status = g_svc.aidl->getHealthInfo(&health_info);
139 value32 = health_info.batteryVoltageMillivolts;
140 break;
141 } // switch(counter)
142
143 if (status.isOk()) {
144 *value = value32;
145 return true;
146 }
147
148 if (status.getStatus() == STATUS_DEAD_OBJECT)
149 g_svc.aidl.reset();
150
151 return false;
152 }
153
154 } // namespace
155
GetBatteryCounter(BatteryCounter counter,int64_t * value)156 bool GetBatteryCounter(BatteryCounter counter, int64_t* value) {
157 *value = 0;
158 if (!g_svc.aidl && !g_svc.hidl)
159 ResetService();
160
161 if (!g_svc.aidl && !g_svc.hidl)
162 return false;
163
164 if (g_svc.aidl)
165 return GetBatteryCounterAidl(counter, value);
166
167 return GetBatteryCounterHidl(counter, value);
168 }
169
170 } // namespace android_internal
171 } // namespace perfetto
172