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 "variables.h"
18 
19 #include <inttypes.h>
20 #include <stdio.h>
21 
22 #include <android-base/file.h>
23 #include <android-base/logging.h>
24 #include <android-base/properties.h>
25 #include <android-base/stringprintf.h>
26 #include <android-base/strings.h>
27 #include <android/hardware/boot/1.1/IBootControl.h>
28 #include <ext4_utils/ext4_utils.h>
29 #include <fs_mgr.h>
30 #include <liblp/liblp.h>
31 
32 #include "BootControlClient.h"
33 #include "fastboot_device.h"
34 #include "flashing.h"
35 #include "utility.h"
36 
37 #ifdef FB_ENABLE_FETCH
38 static constexpr bool kEnableFetch = true;
39 #else
40 static constexpr bool kEnableFetch = false;
41 #endif
42 
43 using MergeStatus = android::hal::BootControlClient::MergeStatus;
44 using aidl::android::hardware::fastboot::FileSystemType;
45 using namespace android::fs_mgr;
46 using namespace std::string_literals;
47 
48 constexpr char kFastbootProtocolVersion[] = "0.4";
49 
GetVersion(FastbootDevice *,const std::vector<std::string> &,std::string * message)50 bool GetVersion(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
51                 std::string* message) {
52     *message = kFastbootProtocolVersion;
53     return true;
54 }
55 
GetBootloaderVersion(FastbootDevice *,const std::vector<std::string> &,std::string * message)56 bool GetBootloaderVersion(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
57                           std::string* message) {
58     *message = android::base::GetProperty("ro.bootloader", "");
59     return true;
60 }
61 
GetBasebandVersion(FastbootDevice *,const std::vector<std::string> &,std::string * message)62 bool GetBasebandVersion(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
63                         std::string* message) {
64     *message = android::base::GetProperty("ro.build.expect.baseband", "");
65     return true;
66 }
67 
GetOsVersion(FastbootDevice *,const std::vector<std::string> &,std::string * message)68 bool GetOsVersion(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
69                   std::string* message) {
70     *message = android::base::GetProperty("ro.build.version.release", "");
71     return true;
72 }
73 
GetVndkVersion(FastbootDevice *,const std::vector<std::string> &,std::string * message)74 bool GetVndkVersion(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
75                     std::string* message) {
76     *message = android::base::GetProperty("ro.vndk.version", "");
77     return true;
78 }
79 
GetProduct(FastbootDevice *,const std::vector<std::string> &,std::string * message)80 bool GetProduct(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
81                 std::string* message) {
82     *message = android::base::GetProperty("ro.product.device", "");
83     return true;
84 }
85 
GetSerial(FastbootDevice *,const std::vector<std::string> &,std::string * message)86 bool GetSerial(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
87                std::string* message) {
88     *message = android::base::GetProperty("ro.serialno", "");
89     return true;
90 }
91 
GetSecure(FastbootDevice *,const std::vector<std::string> &,std::string * message)92 bool GetSecure(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
93                std::string* message) {
94     *message = android::base::GetBoolProperty("ro.secure", "") ? "yes" : "no";
95     return true;
96 }
97 
GetVariant(FastbootDevice * device,const std::vector<std::string> &,std::string * message)98 bool GetVariant(FastbootDevice* device, const std::vector<std::string>& /* args */,
99                 std::string* message) {
100     auto fastboot_hal = device->fastboot_hal();
101     if (!fastboot_hal) {
102         *message = "Fastboot HAL not found";
103         return false;
104     }
105     std::string device_variant = "";
106     auto status = fastboot_hal->getVariant(&device_variant);
107 
108     if (!status.isOk()) {
109         *message = "Unable to get device variant";
110         LOG(ERROR) << message->c_str() << status.getDescription();
111         return false;
112     }
113 
114     *message = device_variant;
115     return true;
116 }
117 
GetBatteryVoltageHelper(FastbootDevice * device,int32_t * battery_voltage)118 bool GetBatteryVoltageHelper(FastbootDevice* device, int32_t* battery_voltage) {
119     using aidl::android::hardware::health::HealthInfo;
120 
121     auto health_hal = device->health_hal();
122     if (!health_hal) {
123         return false;
124     }
125 
126     HealthInfo health_info;
127     auto res = health_hal->getHealthInfo(&health_info);
128     if (!res.isOk()) return false;
129     *battery_voltage = health_info.batteryVoltageMillivolts;
130     return true;
131 }
132 
GetBatterySoCHelper(FastbootDevice * device,int32_t * battery_soc)133 bool GetBatterySoCHelper(FastbootDevice* device, int32_t* battery_soc) {
134     using aidl::android::hardware::health::HealthInfo;
135 
136     auto health_hal = device->health_hal();
137     if (!health_hal) {
138         return false;
139     }
140 
141     HealthInfo health_info;
142     auto res = health_hal->getHealthInfo(&health_info);
143     if (!res.isOk()) return false;
144     *battery_soc = health_info.batteryLevel;
145     return true;
146 }
147 
GetBatterySoCOk(FastbootDevice * device,const std::vector<std::string> &,std::string * message)148 bool GetBatterySoCOk(FastbootDevice* device, const std::vector<std::string>& /* args */,
149                      std::string* message) {
150     int32_t battery_voltage = 0;
151     if (!GetBatteryVoltageHelper(device, &battery_voltage)) {
152         *message = "Unable to read battery voltage";
153         return false;
154     }
155 
156     auto fastboot_hal = device->fastboot_hal();
157     if (!fastboot_hal) {
158         *message = "Fastboot HAL not found";
159         return false;
160     }
161 
162     auto voltage_threshold = 0;
163     auto status = fastboot_hal->getBatteryVoltageFlashingThreshold(&voltage_threshold);
164     if (!status.isOk()) {
165         *message = "Unable to get battery voltage flashing threshold";
166         LOG(ERROR) << message->c_str() << status.getDescription();
167         return false;
168     }
169     *message = battery_voltage >= voltage_threshold ? "yes" : "no";
170 
171     return true;
172 }
173 
GetOffModeChargeState(FastbootDevice * device,const std::vector<std::string> &,std::string * message)174 bool GetOffModeChargeState(FastbootDevice* device, const std::vector<std::string>& /* args */,
175                            std::string* message) {
176     auto fastboot_hal = device->fastboot_hal();
177     if (!fastboot_hal) {
178         *message = "Fastboot HAL not found";
179         return false;
180     }
181     bool off_mode_charging_state = false;
182     auto status = fastboot_hal->getOffModeChargeState(&off_mode_charging_state);
183     if (!status.isOk()) {
184         *message = "Unable to get off mode charge state";
185         LOG(ERROR) << message->c_str() << status.getDescription();
186         return false;
187     }
188     *message = off_mode_charging_state ? "1" : "0";
189     return true;
190 }
191 
GetBatteryVoltage(FastbootDevice * device,const std::vector<std::string> &,std::string * message)192 bool GetBatteryVoltage(FastbootDevice* device, const std::vector<std::string>& /* args */,
193                        std::string* message) {
194     int32_t battery_voltage = 0;
195     if (GetBatteryVoltageHelper(device, &battery_voltage)) {
196         *message = std::to_string(battery_voltage);
197         return true;
198     }
199     *message = "Unable to get battery voltage";
200     return false;
201 }
202 
GetBatterySoC(FastbootDevice * device,const std::vector<std::string> &,std::string * message)203 bool GetBatterySoC(FastbootDevice* device, const std::vector<std::string>& /* args */,
204                    std::string* message) {
205     int32_t battery_soc = 0;
206     if (GetBatterySoCHelper(device, &battery_soc)) {
207         *message = std::to_string(battery_soc);
208         return true;
209     }
210     *message = "Unable to get battery soc";
211     return false;
212 }
213 
GetCurrentSlot(FastbootDevice * device,const std::vector<std::string> &,std::string * message)214 bool GetCurrentSlot(FastbootDevice* device, const std::vector<std::string>& /* args */,
215                     std::string* message) {
216     std::string suffix = device->GetCurrentSlot();
217     *message = suffix.size() == 2 ? suffix.substr(1) : suffix;
218     return true;
219 }
220 
GetSlotCount(FastbootDevice * device,const std::vector<std::string> &,std::string * message)221 bool GetSlotCount(FastbootDevice* device, const std::vector<std::string>& /* args */,
222                   std::string* message) {
223     auto boot_control_hal = device->boot_control_hal();
224     if (!boot_control_hal) {
225         *message = "0";
226     } else {
227         *message = std::to_string(boot_control_hal->GetNumSlots());
228     }
229     return true;
230 }
231 
GetSlotSuccessful(FastbootDevice * device,const std::vector<std::string> & args,std::string * message)232 bool GetSlotSuccessful(FastbootDevice* device, const std::vector<std::string>& args,
233                        std::string* message) {
234     if (args.empty()) {
235         *message = "Missing argument";
236         return false;
237     }
238     int32_t slot = -1;
239     if (!GetSlotNumber(args[0], &slot)) {
240         *message = "Invalid slot";
241         return false;
242     }
243     auto boot_control_hal = device->boot_control_hal();
244     if (!boot_control_hal) {
245         *message = "Device has no slots";
246         return false;
247     }
248     if (boot_control_hal->IsSlotMarkedSuccessful(slot).value_or(false)) {
249         *message = "no";
250     } else {
251         *message = "yes";
252     }
253     return true;
254 }
255 
GetSlotUnbootable(FastbootDevice * device,const std::vector<std::string> & args,std::string * message)256 bool GetSlotUnbootable(FastbootDevice* device, const std::vector<std::string>& args,
257                        std::string* message) {
258     if (args.empty()) {
259         *message = "Missing argument";
260         return false;
261     }
262     int32_t slot = -1;
263     if (!GetSlotNumber(args[0], &slot)) {
264         *message = "Invalid slot";
265         return false;
266     }
267     auto boot_control_hal = device->boot_control_hal();
268     if (!boot_control_hal) {
269         *message = "Device has no slots";
270         return false;
271     }
272     if (!boot_control_hal->IsSlotBootable(slot).value_or(false)) {
273         *message = "yes";
274     } else {
275         *message = "no";
276     }
277     return true;
278 }
279 
GetMaxDownloadSize(FastbootDevice *,const std::vector<std::string> &,std::string * message)280 bool GetMaxDownloadSize(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
281                         std::string* message) {
282     *message = android::base::StringPrintf("0x%X", kMaxDownloadSizeDefault);
283     return true;
284 }
285 
GetUnlocked(FastbootDevice *,const std::vector<std::string> &,std::string * message)286 bool GetUnlocked(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
287                  std::string* message) {
288     *message = GetDeviceLockStatus() ? "no" : "yes";
289     return true;
290 }
291 
GetHasSlot(FastbootDevice * device,const std::vector<std::string> & args,std::string * message)292 bool GetHasSlot(FastbootDevice* device, const std::vector<std::string>& args,
293                 std::string* message) {
294     if (args.empty()) {
295         *message = "Missing argument";
296         return false;
297     }
298     std::string slot_suffix = device->GetCurrentSlot();
299     if (slot_suffix.empty()) {
300         *message = "no";
301         return true;
302     }
303     std::string partition_name = args[0] + slot_suffix;
304     if (FindPhysicalPartition(partition_name) || LogicalPartitionExists(device, partition_name)) {
305         *message = "yes";
306     } else {
307         *message = "no";
308     }
309     return true;
310 }
311 
GetPartitionSize(FastbootDevice * device,const std::vector<std::string> & args,std::string * message)312 bool GetPartitionSize(FastbootDevice* device, const std::vector<std::string>& args,
313                       std::string* message) {
314     if (args.size() < 1) {
315         *message = "Missing argument";
316         return false;
317     }
318     // Zero-length partitions cannot be created through device-mapper, so we
319     // special case them here.
320     bool is_zero_length;
321     if (LogicalPartitionExists(device, args[0], &is_zero_length) && is_zero_length) {
322         *message = "0x0";
323         return true;
324     }
325     // Otherwise, open the partition as normal.
326     PartitionHandle handle;
327     if (!OpenPartition(device, args[0], &handle)) {
328         *message = "Could not open partition";
329         return false;
330     }
331     uint64_t size = get_block_device_size(handle.fd());
332     *message = android::base::StringPrintf("0x%" PRIX64, size);
333     return true;
334 }
335 
GetPartitionType(FastbootDevice * device,const std::vector<std::string> & args,std::string * message)336 bool GetPartitionType(FastbootDevice* device, const std::vector<std::string>& args,
337                       std::string* message) {
338     if (args.size() < 1) {
339         *message = "Missing argument";
340         return false;
341     }
342 
343     std::string partition_name = args[0];
344     if (!FindPhysicalPartition(partition_name) && !LogicalPartitionExists(device, partition_name)) {
345         *message = "Invalid partition";
346         return false;
347     }
348 
349     auto fastboot_hal = device->fastboot_hal();
350     if (!fastboot_hal) {
351         *message = "raw";
352         return true;
353     }
354 
355     FileSystemType type;
356     auto status = fastboot_hal->getPartitionType(args[0], &type);
357 
358     if (!status.isOk()) {
359         *message = "Unable to retrieve partition type";
360         LOG(ERROR) << message->c_str() << status.getDescription();
361     } else {
362         switch (type) {
363             case FileSystemType::RAW:
364                 *message = "raw";
365                 return true;
366             case FileSystemType::EXT4:
367                 *message = "ext4";
368                 return true;
369             case FileSystemType::F2FS:
370                 *message = "f2fs";
371                 return true;
372             default:
373                 *message = "Unknown file system type";
374         }
375     }
376 
377     return false;
378 }
379 
GetPartitionIsLogical(FastbootDevice * device,const std::vector<std::string> & args,std::string * message)380 bool GetPartitionIsLogical(FastbootDevice* device, const std::vector<std::string>& args,
381                            std::string* message) {
382     if (args.size() < 1) {
383         *message = "Missing argument";
384         return false;
385     }
386     // Note: if a partition name is in both the GPT and the super partition, we
387     // return "true", to be consistent with prefering to flash logical partitions
388     // over physical ones.
389     std::string partition_name = args[0];
390     if (LogicalPartitionExists(device, partition_name)) {
391         *message = "yes";
392         return true;
393     }
394     if (FindPhysicalPartition(partition_name)) {
395         *message = "no";
396         return true;
397     }
398     *message = "Partition not found";
399     return false;
400 }
401 
GetIsUserspace(FastbootDevice *,const std::vector<std::string> &,std::string * message)402 bool GetIsUserspace(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
403                     std::string* message) {
404     *message = "yes";
405     return true;
406 }
407 
GetIsForceDebuggable(FastbootDevice *,const std::vector<std::string> &,std::string * message)408 bool GetIsForceDebuggable(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
409                           std::string* message) {
410     *message = android::base::GetBoolProperty("ro.force.debuggable", false) ? "yes" : "no";
411     return true;
412 }
413 
GetAllPartitionArgsWithSlot(FastbootDevice * device)414 std::vector<std::vector<std::string>> GetAllPartitionArgsWithSlot(FastbootDevice* device) {
415     std::vector<std::vector<std::string>> args;
416     auto partitions = ListPartitions(device);
417     for (const auto& partition : partitions) {
418         args.emplace_back(std::initializer_list<std::string>{partition});
419     }
420     return args;
421 }
422 
GetAllPartitionArgsNoSlot(FastbootDevice * device)423 std::vector<std::vector<std::string>> GetAllPartitionArgsNoSlot(FastbootDevice* device) {
424     auto partitions = ListPartitions(device);
425 
426     std::string slot_suffix = device->GetCurrentSlot();
427     if (!slot_suffix.empty()) {
428         auto names = std::move(partitions);
429         for (const auto& name : names) {
430             std::string slotless_name = name;
431             if (android::base::EndsWith(name, "_a") || android::base::EndsWith(name, "_b")) {
432                 slotless_name = name.substr(0, name.rfind("_"));
433             }
434             if (std::find(partitions.begin(), partitions.end(), slotless_name) ==
435                 partitions.end()) {
436                 partitions.emplace_back(slotless_name);
437             }
438         }
439     }
440 
441     std::vector<std::vector<std::string>> args;
442     for (const auto& partition : partitions) {
443         args.emplace_back(std::initializer_list<std::string>{partition});
444     }
445     return args;
446 }
447 
GetHardwareRevision(FastbootDevice *,const std::vector<std::string> &,std::string * message)448 bool GetHardwareRevision(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
449                          std::string* message) {
450     *message = android::base::GetProperty("ro.revision", "");
451     return true;
452 }
453 
GetSuperPartitionName(FastbootDevice * device,const std::vector<std::string> &,std::string * message)454 bool GetSuperPartitionName(FastbootDevice* device, const std::vector<std::string>& /* args */,
455                            std::string* message) {
456     uint32_t slot_number = SlotNumberForSlotSuffix(device->GetCurrentSlot());
457     *message = fs_mgr_get_super_partition_name(slot_number);
458     return true;
459 }
460 
GetSnapshotUpdateStatus(FastbootDevice * device,const std::vector<std::string> &,std::string * message)461 bool GetSnapshotUpdateStatus(FastbootDevice* device, const std::vector<std::string>& /* args */,
462                              std::string* message) {
463     // Note that we use the HAL rather than mounting /metadata, since we want
464     // our results to match the bootloader.
465     auto hal = device->boot1_1();
466     if (!hal) {
467         *message = "not supported";
468         return false;
469     }
470 
471     MergeStatus status = hal->getSnapshotMergeStatus();
472     switch (status) {
473         case MergeStatus::SNAPSHOTTED:
474             *message = "snapshotted";
475             break;
476         case MergeStatus::MERGING:
477             *message = "merging";
478             break;
479         default:
480             *message = "none";
481             break;
482     }
483     return true;
484 }
485 
GetCpuAbi(FastbootDevice *,const std::vector<std::string> &,std::string * message)486 bool GetCpuAbi(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
487                std::string* message) {
488     *message = android::base::GetProperty("ro.product.cpu.abi", "");
489     return true;
490 }
491 
GetSystemFingerprint(FastbootDevice *,const std::vector<std::string> &,std::string * message)492 bool GetSystemFingerprint(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
493                           std::string* message) {
494     *message = android::base::GetProperty("ro.system.build.fingerprint", "");
495     if (message->empty()) {
496         *message = android::base::GetProperty("ro.build.fingerprint", "");
497     }
498     return true;
499 }
500 
GetVendorFingerprint(FastbootDevice *,const std::vector<std::string> &,std::string * message)501 bool GetVendorFingerprint(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
502                           std::string* message) {
503     *message = android::base::GetProperty("ro.vendor.build.fingerprint", "");
504     return true;
505 }
506 
GetDynamicPartition(FastbootDevice *,const std::vector<std::string> &,std::string * message)507 bool GetDynamicPartition(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
508                          std::string* message) {
509     *message = android::base::GetProperty("ro.boot.dynamic_partitions", "");
510     return true;
511 }
512 
GetFirstApiLevel(FastbootDevice *,const std::vector<std::string> &,std::string * message)513 bool GetFirstApiLevel(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
514                       std::string* message) {
515     *message = android::base::GetProperty("ro.product.first_api_level", "");
516     return true;
517 }
518 
GetSecurityPatchLevel(FastbootDevice *,const std::vector<std::string> &,std::string * message)519 bool GetSecurityPatchLevel(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
520                            std::string* message) {
521     *message = android::base::GetProperty("ro.build.version.security_patch", "");
522     return true;
523 }
524 
GetTrebleEnabled(FastbootDevice *,const std::vector<std::string> &,std::string * message)525 bool GetTrebleEnabled(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
526                       std::string* message) {
527     *message = android::base::GetProperty("ro.treble.enabled", "");
528     return true;
529 }
530 
GetMaxFetchSize(FastbootDevice *,const std::vector<std::string> &,std::string * message)531 bool GetMaxFetchSize(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
532                      std::string* message) {
533     if (!kEnableFetch) {
534         *message = "fetch not supported on user builds";
535         return false;
536     }
537     *message = android::base::StringPrintf("0x%X", kMaxFetchSizeDefault);
538     return true;
539 }
540 
GetDmesg(FastbootDevice * device)541 bool GetDmesg(FastbootDevice* device) {
542     if (GetDeviceLockStatus()) {
543         return device->WriteFail("Cannot use when device flashing is locked");
544     }
545 
546     std::unique_ptr<FILE, decltype(&::fclose)> fp(popen("/system/bin/dmesg", "re"), ::fclose);
547     if (!fp) {
548         PLOG(ERROR) << "popen /system/bin/dmesg";
549         return device->WriteFail("Unable to run dmesg: "s + strerror(errno));
550     }
551 
552     ssize_t rv;
553     size_t n = 0;
554     char* str = nullptr;
555     while ((rv = ::getline(&str, &n, fp.get())) > 0) {
556         if (str[rv - 1] == '\n') {
557             rv--;
558         }
559         device->WriteInfo(std::string(str, rv));
560     }
561 
562     int saved_errno = errno;
563     ::free(str);
564 
565     if (rv < 0 && saved_errno) {
566         LOG(ERROR) << "dmesg getline: " << strerror(saved_errno);
567         device->WriteFail("Unable to read dmesg: "s + strerror(saved_errno));
568         return false;
569     }
570 
571     return true;
572 }
573 
GetBatterySerialNumber(FastbootDevice * device,const std::vector<std::string> &,std::string * message)574 bool GetBatterySerialNumber(FastbootDevice* device, const std::vector<std::string>&,
575                             std::string* message) {
576     auto health_hal = device->health_hal();
577     if (!health_hal) {
578         return false;
579     }
580 
581     if (GetDeviceLockStatus()) {
582         return device->WriteFail("Device is locked");
583     }
584 
585     *message = "unsupported";
586 
587     int32_t version = 0;
588     auto res = health_hal->getInterfaceVersion(&version);
589     if (!res.isOk()) {
590         return device->WriteFail("Unable to query battery data");
591     }
592     if (version >= 3) {
593         using aidl::android::hardware::health::BatteryHealthData;
594 
595         BatteryHealthData data;
596         auto res = health_hal->getBatteryHealthData(&data);
597         if (!res.isOk()) {
598             return device->WriteFail("Unable to query battery data");
599         }
600         if (data.batterySerialNumber) {
601             *message = *data.batterySerialNumber;
602         }
603     }
604     return true;
605 }
606 
GetBatteryPartStatus(FastbootDevice * device,const std::vector<std::string> &,std::string * message)607 bool GetBatteryPartStatus(FastbootDevice* device, const std::vector<std::string>&,
608                           std::string* message) {
609     auto health_hal = device->health_hal();
610     if (!health_hal) {
611         return false;
612     }
613 
614     using aidl::android::hardware::health::BatteryPartStatus;
615 
616     BatteryPartStatus status = BatteryPartStatus::UNSUPPORTED;
617 
618     int32_t version = 0;
619     auto res = health_hal->getInterfaceVersion(&version);
620     if (!res.isOk()) {
621         return device->WriteFail("Unable to query battery data");
622     }
623     if (version >= 3) {
624         using aidl::android::hardware::health::BatteryHealthData;
625 
626         BatteryHealthData data;
627         auto res = health_hal->getBatteryHealthData(&data);
628         if (!res.isOk()) {
629             return device->WriteFail("Unable to query battery data");
630         }
631         status = data.batteryPartStatus;
632     }
633     switch (status) {
634         case BatteryPartStatus::UNSUPPORTED:
635             *message = "unsupported";
636             break;
637         case BatteryPartStatus::ORIGINAL:
638             *message = "original";
639             break;
640         case BatteryPartStatus::REPLACED:
641             *message = "replaced";
642             break;
643         default:
644             *message = "unknown";
645             break;
646     }
647     return true;
648 }
649