• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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