• Home
  • History
  • Annotate
  • 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 #define LOG_TAG "android.hardware.health@2.1-impl-zuma"
17 #include <android-base/logging.h>
18 
19 #include <android-base/file.h>
20 #include <android-base/parseint.h>
21 #include <android-base/strings.h>
22 #include <android/hardware/health/translate-ndk.h>
23 #include <health-impl/Health.h>
24 #include <health/utils.h>
25 
26 // Recovery doesn't have libpixelhealth and charger mode
27 #ifndef __ANDROID_RECOVERY__
28 #include <health-impl/ChargerUtils.h>
29 #include <pixelhealth/BatteryDefender.h>
30 #include <pixelhealth/BatteryMetricsLogger.h>
31 #include <pixelhealth/ChargerDetect.h>
32 #include <pixelhealth/DeviceHealth.h>
33 #include <pixelhealth/LowBatteryShutdownMetrics.h>
34 #endif // !__ANDROID_RECOVERY__
35 
36 #include <chrono>
37 #include <fstream>
38 #include <iomanip>
39 #include <string>
40 #include <vector>
41 
42 namespace {
43 
44 using namespace std::literals;
45 
46 using aidl::android::hardware::health::DiskStats;
47 using aidl::android::hardware::health::HalHealthLoop;
48 using aidl::android::hardware::health::HealthInfo;
49 using aidl::android::hardware::health::StorageInfo;
50 using android::hardware::health::InitHealthdConfig;
51 
52 #ifndef __ANDROID_RECOVERY__
53 using aidl::android::hardware::health::charger::ChargerCallback;
54 using aidl::android::hardware::health::charger::ChargerModeMain;
55 using hardware::google::pixel::health::BatteryDefender;
56 using hardware::google::pixel::health::BatteryMetricsLogger;
57 using hardware::google::pixel::health::DeviceHealth;
58 using hardware::google::pixel::health::LowBatteryShutdownMetrics;
59 using hardware::google::pixel::health::ChargerDetect;
60 
61 #define FG_DIR "/sys/class/power_supply/battery"
62 constexpr char kBatteryResistance[] {FG_DIR "/resistance"};
63 constexpr char kBatteryOCV[] {FG_DIR "/voltage_ocv"};
64 constexpr char kVoltageAvg[] {FG_DIR "/voltage_now"};
65 
66 #define WLC_DIR "/sys/class/power_supply/wireless"
67 
68 static BatteryDefender battDefender(WLC_DIR "/present",
69     "/sys/devices/platform/google,charger/charge_start_level",
70     "/sys/devices/platform/google,charger/charge_stop_level");
71 static BatteryMetricsLogger battMetricsLogger(kBatteryResistance, kBatteryOCV);
72 static LowBatteryShutdownMetrics shutdownMetrics(kVoltageAvg);
73 static DeviceHealth deviceHealth;
74 #endif // !__ANDROID_RECOVERY__
75 
76 #define UFS_DIR "/dev/sys/block/bootdevice"
77 constexpr char kUfsHealthEol[]{UFS_DIR "/health_descriptor/eol_info"};
78 constexpr char kUfsHealthLifetimeA[]{UFS_DIR "/health_descriptor/life_time_estimation_a"};
79 constexpr char kUfsHealthLifetimeB[]{UFS_DIR "/health_descriptor/life_time_estimation_b"};
80 constexpr char kUfsVersion[]{UFS_DIR "/device_descriptor/specification_version"};
81 constexpr char kDiskStatsFile[]{"/sys/block/sda/stat"};
82 
83 static std::string ufs_version;
84 static uint16_t eol;
85 static uint16_t lifetimeA;
86 static uint16_t lifetimeB;
87 static std::chrono::system_clock::time_point ufs_last_query_time;
88 constexpr auto kUfsQueryIntervalHours = std::chrono::hours{24};
89 
90 #ifndef __ANDROID_RECOVERY__
91 static bool needs_wlc_updates = false;
92 constexpr char kWlcCapacity[]{WLC_DIR "/capacity"};
93 #endif // !__ANDROID_RECOVERY__
94 
assert_open(const std::string & path)95 std::ifstream assert_open(const std::string &path) {
96   std::ifstream stream(path);
97   if (!stream.is_open()) {
98     LOG(WARNING) << "Cannot read " << path;
99   }
100   return stream;
101 }
102 
103 template <typename T>
read_value_from_file(const std::string & path,T * field)104 void read_value_from_file(const std::string &path, T *field) {
105   auto stream = assert_open(path);
106   stream.unsetf(std::ios_base::basefield);
107   stream >> *field;
108 }
109 
read_ufs_version(StorageInfo * info)110 void read_ufs_version(StorageInfo *info) {
111   if (ufs_version.empty()) {
112     uint64_t value;
113     read_value_from_file(kUfsVersion, &value);
114     std::stringstream ss;
115     ss << "ufs " << std::hex << value;
116     ufs_version = ss.str();
117     LOG(INFO) << "ufs: " << ufs_version << " detected";
118   }
119   info->version = ufs_version;
120 }
121 
122 #ifdef __ANDROID_RECOVERY__
private_healthd_board_init(struct healthd_config *)123 void private_healthd_board_init(struct healthd_config *) {}
private_healthd_board_battery_update(HealthInfo *)124 int private_healthd_board_battery_update(HealthInfo *) { return 0; }
125 #else // !__ANDROID__RECOVERY__
126 
FileExists(const std::string & filename)127 static bool FileExists(const std::string &filename) {
128   struct stat buffer;
129 
130   return stat(filename.c_str(), &buffer) == 0;
131 }
132 
private_healthd_board_init(struct healthd_config * hc)133 void private_healthd_board_init(struct healthd_config *hc) {
134   std::string tcpmPsyName;
135   ChargerDetect::populateTcpmPsyName(&tcpmPsyName);
136   hc->ignorePowerSupplyNames.push_back(android::String8(tcpmPsyName.c_str()));
137   needs_wlc_updates = FileExists(kWlcCapacity);
138   if (needs_wlc_updates == false) {
139     battDefender.setWirelessNotSupported();
140   }
141 }
142 
private_healthd_board_battery_update(HealthInfo * health_info)143 int private_healthd_board_battery_update(HealthInfo *health_info) {
144   deviceHealth.update(health_info);
145   battMetricsLogger.logBatteryProperties(*health_info);
146   shutdownMetrics.logShutdownVoltage(*health_info);
147   // Allow BatteryDefender to override online properties
148   ChargerDetect::onlineUpdate(health_info);
149   battDefender.update(health_info);
150 
151   if (needs_wlc_updates &&
152       !android::base::WriteStringToFile(std::to_string(health_info->batteryLevel), kWlcCapacity))
153       LOG(INFO) << "Unable to write battery level to wireless capacity";
154 
155   return 0;
156 }
157 #endif // __ANDROID_RECOVERY__
158 
private_get_storage_info(std::vector<StorageInfo> * vec_storage_info)159 void private_get_storage_info(std::vector<StorageInfo> *vec_storage_info) {
160   vec_storage_info->resize(1);
161   StorageInfo *storage_info = &vec_storage_info->at(0);
162 
163   read_ufs_version(storage_info);
164 
165   auto time_now = std::chrono::system_clock::now();
166   auto time_delta = time_now - ufs_last_query_time;
167   auto hoursElapsed = std::chrono::duration_cast<std::chrono::hours>(time_delta);
168   if (hoursElapsed >= kUfsQueryIntervalHours) {
169     ufs_last_query_time = time_now;
170     read_value_from_file(kUfsHealthEol, &eol);
171     read_value_from_file(kUfsHealthLifetimeA, &lifetimeA);
172     read_value_from_file(kUfsHealthLifetimeB, &lifetimeB);
173     LOG(INFO) << "ufs: eol=" << eol << " lifetimeA=" << lifetimeA << " lifetimeB=" << lifetimeB;
174   }
175   storage_info->eol = eol;
176   storage_info->lifetimeA = lifetimeA;
177   storage_info->lifetimeB = lifetimeB;
178 
179   return;
180 }
181 
private_get_disk_stats(std::vector<DiskStats> * vec_stats)182 void private_get_disk_stats(std::vector<DiskStats> *vec_stats) {
183   vec_stats->resize(1);
184   DiskStats *stats = &vec_stats->at(0);
185 
186   auto stream = assert_open(kDiskStatsFile);
187   // Regular diskstats entries
188   stream >> stats->reads >> stats->readMerges >> stats->readSectors >>
189       stats->readTicks >> stats->writes >> stats->writeMerges >>
190       stats->writeSectors >> stats->writeTicks >> stats->ioInFlight >>
191       stats->ioTicks >> stats->ioInQueue;
192   return;
193 }
194 }  // anonymous namespace
195 
196 namespace aidl::android::hardware::health::implementation {
197 class HealthImpl : public Health {
198  public:
HealthImpl(std::string_view instance_name,std::unique_ptr<healthd_config> && config)199   HealthImpl(std::string_view instance_name, std::unique_ptr<healthd_config>&& config)
200     : Health(std::move(instance_name), std::move(config)) {}
201 
202     ndk::ScopedAStatus getDiskStats(std::vector<DiskStats>* out) override;
203     ndk::ScopedAStatus getStorageInfo(std::vector<StorageInfo>* out) override;
204 
205  protected:
206   void UpdateHealthInfo(HealthInfo* health_info) override;
207 
208 };
209 
UpdateHealthInfo(HealthInfo * health_info)210 void HealthImpl::UpdateHealthInfo(HealthInfo* health_info) {
211   private_healthd_board_battery_update(health_info);
212 }
213 
getStorageInfo(std::vector<StorageInfo> * out)214 ndk::ScopedAStatus HealthImpl::getStorageInfo(std::vector<StorageInfo>* out)
215 {
216   private_get_storage_info(out);
217   if (out->empty()) {
218     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
219   }
220   return ndk::ScopedAStatus::ok();
221 }
222 
getDiskStats(std::vector<DiskStats> * out)223 ndk::ScopedAStatus HealthImpl::getDiskStats(std::vector<DiskStats>* out)
224 {
225   private_get_disk_stats(out);
226   if (out->empty()) {
227     return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
228   }
229   return ndk::ScopedAStatus::ok();
230 }
231 
232 }  // namespace aidl::android::hardware::health::implementation
233 
234 #ifndef __ANDROID_RECOVERY__
235 namespace aidl::android::hardware::health {
236 class ChargerCallbackImpl : public ChargerCallback {
237   public:
ChargerCallbackImpl(const std::shared_ptr<Health> & service)238     ChargerCallbackImpl(const std::shared_ptr<Health>& service) : ChargerCallback(service) {}
ChargerEnableSuspend()239     bool ChargerEnableSuspend() override { return true; }
240 };
241 } //namespace aidl::android::hardware::health
242 #endif // !__ANDROID_RECOVERY__
243 
main(int argc,char ** argv)244 int main(int argc, char **argv) {
245   using ::aidl::android::hardware::health::implementation::HealthImpl;
246 
247   // Use kernel logging in recovery
248 #ifdef __ANDROID_RECOVERY__
249   android::base::InitLogging(argv, android::base::KernelLogger);
250 #endif
251 
252   auto config = std::make_unique<healthd_config>();
253   InitHealthdConfig(config.get());
254 
255   private_healthd_board_init(config.get());
256 
257   auto binder =
258       ndk::SharedRefBase::make<HealthImpl>("default"sv, std::move(config));
259 
260   if (argc >= 2 && argv[1] == "--charger"sv) {
261     // In regular mode, start charger UI.
262 #ifndef __ANDROID_RECOVERY__
263     LOG(INFO) << "Starting charger mode with UI.";
264     auto charger_callback = std::make_shared<aidl::android::hardware::health::ChargerCallbackImpl>(binder);
265     return ChargerModeMain(binder, charger_callback);
266 #endif
267     // In recovery, ignore --charger arg.
268     LOG(INFO) << "Starting charger mode without UI.";
269   } else {
270     LOG(INFO) << "Starting health HAL.";
271   }
272 
273   auto hal_health_loop = std::make_shared<HalHealthLoop>(binder, binder);
274   return hal_health_loop->StartLoop();
275 }
276