• 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   }  // 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