1 /*
2 * Copyright (C) 2021 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 <android-base/logging.h>
18 #include <android/hardware/health/translate-ndk.h>
19 #include <health-shim/shim.h>
20
21 using ::android::sp;
22 using ::android::h2a::translate;
23 using ::android::hardware::Return;
24 using ::android::hardware::Void;
25 using ::android::hardware::health::V2_0::Result;
26 using ::android::hardware::health::V2_0::toString;
27 using ::ndk::ScopedAStatus;
28 using HidlHealth = ::android::hardware::health::V2_0::IHealth;
29 using HidlHealthInfoCallback = ::android::hardware::health::V2_0::IHealthInfoCallback;
30 using HidlHealthInfo = ::android::hardware::health::V2_0::HealthInfo;
31
32 namespace aidl::android::hardware::health {
33
34 namespace {
35
36 class HealthInfoCallbackShim : public HidlHealthInfoCallback {
37 using AidlHealthInfoCallback = ::aidl::android::hardware::health::IHealthInfoCallback;
38 using AidlHealthInfo = ::aidl::android::hardware::health::HealthInfo;
39
40 public:
HealthInfoCallbackShim(const std::shared_ptr<AidlHealthInfoCallback> & impl)41 explicit HealthInfoCallbackShim(const std::shared_ptr<AidlHealthInfoCallback>& impl)
42 : impl_(impl) {}
healthInfoChanged(const HidlHealthInfo & info)43 Return<void> healthInfoChanged(const HidlHealthInfo& info) override {
44 AidlHealthInfo aidl_info;
45 // translate() should always return true.
46 CHECK(translate(info, &aidl_info));
47 // This is a oneway function, so we can't (and shouldn't) check for errors.
48 (void)impl_->healthInfoChanged(aidl_info);
49 return Void();
50 }
51
52 private:
53 std::shared_ptr<AidlHealthInfoCallback> impl_;
54 };
55
ResultToStatus(Result result)56 ScopedAStatus ResultToStatus(Result result) {
57 switch (result) {
58 case Result::SUCCESS:
59 return ScopedAStatus::ok();
60 case Result::NOT_SUPPORTED:
61 return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
62 case Result::UNKNOWN:
63 return ScopedAStatus::fromServiceSpecificError(IHealth::STATUS_UNKNOWN);
64 case Result::NOT_FOUND:
65 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
66 case Result::CALLBACK_DIED:
67 return ScopedAStatus::fromServiceSpecificError(IHealth::STATUS_CALLBACK_DIED);
68 }
69 return ScopedAStatus::fromServiceSpecificErrorWithMessage(
70 IHealth::STATUS_UNKNOWN, ("Unrecognized result value " + toString(result)).c_str());
71 }
72
73 template <typename T>
ReturnAndResultToStatus(const Return<T> & ret,Result result)74 ScopedAStatus ReturnAndResultToStatus(const Return<T>& ret, Result result) {
75 if (ret.isOk()) {
76 return ResultToStatus(result);
77 }
78 if (ret.isDeadObject()) {
79 return ScopedAStatus::fromStatus(STATUS_DEAD_OBJECT);
80 }
81 return ScopedAStatus::fromServiceSpecificErrorWithMessage(IHealth::STATUS_UNKNOWN,
82 ret.description().c_str());
83 }
84
ReturnResultToStatus(const Return<Result> & return_result)85 ScopedAStatus ReturnResultToStatus(const Return<Result>& return_result) {
86 return ReturnAndResultToStatus(return_result, return_result.isOk()
87 ? static_cast<Result>(return_result)
88 : Result::UNKNOWN);
89 }
90
91 } // namespace
92
HealthShim(const sp<HidlHealth> & service)93 HealthShim::HealthShim(const sp<HidlHealth>& service) : service_(service) {}
94
registerCallback(const std::shared_ptr<IHealthInfoCallback> & in_callback)95 ScopedAStatus HealthShim::registerCallback(
96 const std::shared_ptr<IHealthInfoCallback>& in_callback) {
97 sp<HidlHealthInfoCallback> shim(new HealthInfoCallbackShim(in_callback));
98 callback_map_.emplace(in_callback, shim);
99 return ReturnResultToStatus(service_->registerCallback(shim));
100 }
101
unregisterCallback(const std::shared_ptr<IHealthInfoCallback> & in_callback)102 ScopedAStatus HealthShim::unregisterCallback(
103 const std::shared_ptr<IHealthInfoCallback>& in_callback) {
104 auto it = callback_map_.find(in_callback);
105 if (it == callback_map_.end()) {
106 return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
107 }
108 sp<HidlHealthInfoCallback> shim = it->second;
109 callback_map_.erase(it);
110 return ReturnResultToStatus(service_->unregisterCallback(shim));
111 }
112
update()113 ScopedAStatus HealthShim::update() {
114 return ReturnResultToStatus(service_->update());
115 }
116
getChargeCounterUah(int32_t * out)117 ScopedAStatus HealthShim::getChargeCounterUah(int32_t* out) {
118 Result out_result = Result::UNKNOWN;
119 auto ret = service_->getChargeCounter([out, &out_result](auto result, auto value) {
120 out_result = result;
121 if (out_result != Result::SUCCESS) return;
122 *out = value;
123 });
124 return ReturnAndResultToStatus(ret, out_result);
125 }
126
getCurrentNowMicroamps(int32_t * out)127 ScopedAStatus HealthShim::getCurrentNowMicroamps(int32_t* out) {
128 Result out_result = Result::UNKNOWN;
129 auto ret = service_->getCurrentNow([out, &out_result](auto result, auto value) {
130 out_result = result;
131 if (out_result != Result::SUCCESS) return;
132 *out = value;
133 });
134 return ReturnAndResultToStatus(ret, out_result);
135 }
136
getCurrentAverageMicroamps(int32_t * out)137 ScopedAStatus HealthShim::getCurrentAverageMicroamps(int32_t* out) {
138 Result out_result = Result::UNKNOWN;
139 auto ret = service_->getCurrentAverage([out, &out_result](auto result, auto value) {
140 out_result = result;
141 if (out_result != Result::SUCCESS) return;
142 *out = value;
143 });
144 return ReturnAndResultToStatus(ret, out_result);
145 }
146
getCapacity(int32_t * out)147 ScopedAStatus HealthShim::getCapacity(int32_t* out) {
148 Result out_result = Result::UNKNOWN;
149 auto ret = service_->getCapacity([out, &out_result](auto result, auto value) {
150 out_result = result;
151 if (out_result != Result::SUCCESS) return;
152 *out = value;
153 });
154 return ReturnAndResultToStatus(ret, out_result);
155 }
156
getEnergyCounterNwh(int64_t * out)157 ScopedAStatus HealthShim::getEnergyCounterNwh(int64_t* out) {
158 Result out_result = Result::UNKNOWN;
159 auto ret = service_->getEnergyCounter([out, &out_result](auto result, auto value) {
160 out_result = result;
161 if (out_result != Result::SUCCESS) return;
162 *out = value;
163 });
164 return ReturnAndResultToStatus(ret, out_result);
165 }
166
getChargeStatus(BatteryStatus * out)167 ScopedAStatus HealthShim::getChargeStatus(BatteryStatus* out) {
168 Result out_result = Result::UNKNOWN;
169 auto ret = service_->getChargeStatus([out, &out_result](auto result, auto value) {
170 out_result = result;
171 if (out_result != Result::SUCCESS) return;
172 *out = static_cast<BatteryStatus>(value);
173 });
174 return ReturnAndResultToStatus(ret, out_result);
175 }
176
getStorageInfo(std::vector<StorageInfo> * out)177 ScopedAStatus HealthShim::getStorageInfo(std::vector<StorageInfo>* out) {
178 Result out_result = Result::UNKNOWN;
179 auto ret = service_->getStorageInfo([out, &out_result](auto result, const auto& value) {
180 out_result = result;
181 if (out_result != Result::SUCCESS) return;
182 out->clear();
183 out->reserve(value.size());
184 for (const auto& hidl_info : value) {
185 auto& aidl_info = out->emplace_back();
186 // translate() should always return true.
187 CHECK(translate(hidl_info, &aidl_info));
188 }
189 });
190 return ReturnAndResultToStatus(ret, out_result);
191 }
192
getDiskStats(std::vector<DiskStats> * out)193 ScopedAStatus HealthShim::getDiskStats(std::vector<DiskStats>* out) {
194 Result out_result = Result::UNKNOWN;
195 auto ret = service_->getDiskStats([out, &out_result](auto result, const auto& value) {
196 out_result = result;
197 if (out_result != Result::SUCCESS) return;
198 out->clear();
199 out->reserve(value.size());
200 for (const auto& hidl_info : value) {
201 auto& aidl_info = out->emplace_back();
202 // translate() should always return true.
203 CHECK(translate(hidl_info, &aidl_info));
204 }
205 });
206 return ReturnAndResultToStatus(ret, out_result);
207 }
208
getHealthInfo(HealthInfo * out)209 ScopedAStatus HealthShim::getHealthInfo(HealthInfo* out) {
210 Result out_result = Result::UNKNOWN;
211 auto ret = service_->getHealthInfo([out, &out_result](auto result, const auto& value) {
212 out_result = result;
213 if (out_result != Result::SUCCESS) return;
214 // translate() should always return true.
215 CHECK(translate(value, out));
216 });
217 return ReturnAndResultToStatus(ret, out_result);
218 }
219
setChargingPolicy(BatteryChargingPolicy in_value)220 ScopedAStatus HealthShim::setChargingPolicy(BatteryChargingPolicy in_value) {
221 in_value = static_cast<BatteryChargingPolicy>(0);
222 return ResultToStatus(Result::NOT_SUPPORTED);
223 }
224
getChargingPolicy(BatteryChargingPolicy * out)225 ScopedAStatus HealthShim::getChargingPolicy(BatteryChargingPolicy* out) {
226 *out = static_cast<BatteryChargingPolicy>(0);
227 return ResultToStatus(Result::NOT_SUPPORTED);
228 }
229
getBatteryHealthData(BatteryHealthData * out)230 ScopedAStatus HealthShim::getBatteryHealthData(BatteryHealthData* out) {
231 out->batteryManufacturingDateSeconds = 0;
232 out->batteryFirstUsageSeconds = 0;
233 out->batteryPartStatus = BatteryPartStatus::UNSUPPORTED;
234 return ResultToStatus(Result::NOT_SUPPORTED);
235 }
236
237 } // namespace aidl::android::hardware::health
238