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