1*e7c364b6SAndroid Build Coastguard Worker /*
2*e7c364b6SAndroid Build Coastguard Worker * Copyright (C) 2019 The Android Open Source Project
3*e7c364b6SAndroid Build Coastguard Worker *
4*e7c364b6SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*e7c364b6SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*e7c364b6SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*e7c364b6SAndroid Build Coastguard Worker *
8*e7c364b6SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*e7c364b6SAndroid Build Coastguard Worker *
10*e7c364b6SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*e7c364b6SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*e7c364b6SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*e7c364b6SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*e7c364b6SAndroid Build Coastguard Worker * limitations under the License.
15*e7c364b6SAndroid Build Coastguard Worker */
16*e7c364b6SAndroid Build Coastguard Worker
17*e7c364b6SAndroid Build Coastguard Worker #include "recovery_utils/battery_utils.h"
18*e7c364b6SAndroid Build Coastguard Worker
19*e7c364b6SAndroid Build Coastguard Worker #include <stdint.h>
20*e7c364b6SAndroid Build Coastguard Worker #include <unistd.h>
21*e7c364b6SAndroid Build Coastguard Worker
22*e7c364b6SAndroid Build Coastguard Worker #include <android-base/logging.h>
23*e7c364b6SAndroid Build Coastguard Worker #include <android/binder_manager.h>
24*e7c364b6SAndroid Build Coastguard Worker #include <health-shim/shim.h>
25*e7c364b6SAndroid Build Coastguard Worker #include <healthhalutils/HealthHalUtils.h>
26*e7c364b6SAndroid Build Coastguard Worker
GetBatteryInfo()27*e7c364b6SAndroid Build Coastguard Worker BatteryInfo GetBatteryInfo() {
28*e7c364b6SAndroid Build Coastguard Worker using android::hardware::health::V2_0::get_health_service;
29*e7c364b6SAndroid Build Coastguard Worker using HidlHealth = android::hardware::health::V2_0::IHealth;
30*e7c364b6SAndroid Build Coastguard Worker using aidl::android::hardware::health::BatteryStatus;
31*e7c364b6SAndroid Build Coastguard Worker using aidl::android::hardware::health::HealthShim;
32*e7c364b6SAndroid Build Coastguard Worker using aidl::android::hardware::health::IHealth;
33*e7c364b6SAndroid Build Coastguard Worker using aidl::android::hardware::health::toString;
34*e7c364b6SAndroid Build Coastguard Worker using std::string_literals::operator""s;
35*e7c364b6SAndroid Build Coastguard Worker
36*e7c364b6SAndroid Build Coastguard Worker auto service_name = IHealth::descriptor + "/default"s;
37*e7c364b6SAndroid Build Coastguard Worker std::shared_ptr<IHealth> health;
38*e7c364b6SAndroid Build Coastguard Worker if (AServiceManager_isDeclared(service_name.c_str())) {
39*e7c364b6SAndroid Build Coastguard Worker ndk::SpAIBinder binder(AServiceManager_waitForService(service_name.c_str()));
40*e7c364b6SAndroid Build Coastguard Worker health = IHealth::fromBinder(binder);
41*e7c364b6SAndroid Build Coastguard Worker }
42*e7c364b6SAndroid Build Coastguard Worker if (health == nullptr) {
43*e7c364b6SAndroid Build Coastguard Worker LOG(INFO) << "Unable to get AIDL health service, trying HIDL...";
44*e7c364b6SAndroid Build Coastguard Worker android::sp<HidlHealth> hidl_health = get_health_service();
45*e7c364b6SAndroid Build Coastguard Worker if (hidl_health != nullptr) {
46*e7c364b6SAndroid Build Coastguard Worker health = ndk::SharedRefBase::make<HealthShim>(hidl_health);
47*e7c364b6SAndroid Build Coastguard Worker }
48*e7c364b6SAndroid Build Coastguard Worker }
49*e7c364b6SAndroid Build Coastguard Worker if (health == nullptr) {
50*e7c364b6SAndroid Build Coastguard Worker LOG(WARNING) << "No health implementation is found; assuming defaults";
51*e7c364b6SAndroid Build Coastguard Worker }
52*e7c364b6SAndroid Build Coastguard Worker
53*e7c364b6SAndroid Build Coastguard Worker int wait_second = 0;
54*e7c364b6SAndroid Build Coastguard Worker while (true) {
55*e7c364b6SAndroid Build Coastguard Worker auto charge_status = BatteryStatus::UNKNOWN;
56*e7c364b6SAndroid Build Coastguard Worker if (health != nullptr) {
57*e7c364b6SAndroid Build Coastguard Worker auto res = health->getChargeStatus(&charge_status);
58*e7c364b6SAndroid Build Coastguard Worker if (!res.isOk()) {
59*e7c364b6SAndroid Build Coastguard Worker LOG(WARNING) << "Unable to call getChargeStatus: " << res.getDescription();
60*e7c364b6SAndroid Build Coastguard Worker charge_status = BatteryStatus::UNKNOWN;
61*e7c364b6SAndroid Build Coastguard Worker }
62*e7c364b6SAndroid Build Coastguard Worker }
63*e7c364b6SAndroid Build Coastguard Worker
64*e7c364b6SAndroid Build Coastguard Worker // Treat unknown status as on charger. See hardware/interfaces/health/aidl/BatteryStatus.aidl
65*e7c364b6SAndroid Build Coastguard Worker // for the meaning of the return values.
66*e7c364b6SAndroid Build Coastguard Worker bool charging = (charge_status != BatteryStatus::DISCHARGING &&
67*e7c364b6SAndroid Build Coastguard Worker charge_status != BatteryStatus::NOT_CHARGING);
68*e7c364b6SAndroid Build Coastguard Worker
69*e7c364b6SAndroid Build Coastguard Worker int32_t capacity = INT32_MIN;
70*e7c364b6SAndroid Build Coastguard Worker if (health != nullptr) {
71*e7c364b6SAndroid Build Coastguard Worker auto res = health->getCapacity(&capacity);
72*e7c364b6SAndroid Build Coastguard Worker if (!res.isOk()) {
73*e7c364b6SAndroid Build Coastguard Worker LOG(WARNING) << "Unable to call getCapacity: " << res.getDescription();
74*e7c364b6SAndroid Build Coastguard Worker capacity = INT32_MIN;
75*e7c364b6SAndroid Build Coastguard Worker }
76*e7c364b6SAndroid Build Coastguard Worker }
77*e7c364b6SAndroid Build Coastguard Worker
78*e7c364b6SAndroid Build Coastguard Worker LOG(INFO) << "charge_status " << toString(charge_status) << ", charging " << charging
79*e7c364b6SAndroid Build Coastguard Worker << ", capacity " << capacity;
80*e7c364b6SAndroid Build Coastguard Worker
81*e7c364b6SAndroid Build Coastguard Worker constexpr int BATTERY_READ_TIMEOUT_IN_SEC = 10;
82*e7c364b6SAndroid Build Coastguard Worker // At startup, the battery drivers in devices like N5X/N6P take some time to load
83*e7c364b6SAndroid Build Coastguard Worker // the battery profile. Before the load finishes, it reports value 50 as a fake
84*e7c364b6SAndroid Build Coastguard Worker // capacity. BATTERY_READ_TIMEOUT_IN_SEC is set that the battery drivers are expected
85*e7c364b6SAndroid Build Coastguard Worker // to finish loading the battery profile earlier than 10 seconds after kernel startup.
86*e7c364b6SAndroid Build Coastguard Worker if (capacity == 50) {
87*e7c364b6SAndroid Build Coastguard Worker if (wait_second < BATTERY_READ_TIMEOUT_IN_SEC) {
88*e7c364b6SAndroid Build Coastguard Worker LOG(INFO) << "Battery capacity == 50, waiting "
89*e7c364b6SAndroid Build Coastguard Worker << (BATTERY_READ_TIMEOUT_IN_SEC - wait_second)
90*e7c364b6SAndroid Build Coastguard Worker << " seconds to ensure this is not a fake value...";
91*e7c364b6SAndroid Build Coastguard Worker sleep(1);
92*e7c364b6SAndroid Build Coastguard Worker wait_second++;
93*e7c364b6SAndroid Build Coastguard Worker continue;
94*e7c364b6SAndroid Build Coastguard Worker }
95*e7c364b6SAndroid Build Coastguard Worker }
96*e7c364b6SAndroid Build Coastguard Worker // If we can't read battery percentage, it may be a device without battery. In this
97*e7c364b6SAndroid Build Coastguard Worker // situation, use 100 as a fake battery percentage.
98*e7c364b6SAndroid Build Coastguard Worker if (capacity == INT32_MIN) {
99*e7c364b6SAndroid Build Coastguard Worker LOG(WARNING) << "Using fake battery capacity 100.";
100*e7c364b6SAndroid Build Coastguard Worker capacity = 100;
101*e7c364b6SAndroid Build Coastguard Worker }
102*e7c364b6SAndroid Build Coastguard Worker
103*e7c364b6SAndroid Build Coastguard Worker LOG(INFO) << "GetBatteryInfo() reporting charging " << charging << ", capacity " << capacity;
104*e7c364b6SAndroid Build Coastguard Worker return BatteryInfo{ charging, capacity };
105*e7c364b6SAndroid Build Coastguard Worker }
106*e7c364b6SAndroid Build Coastguard Worker }
107