marlin: add health@2.0 HAL and cycle count backup/restore

 - Implement android.hardware.health@2.0-service for marlin
 - Support battery cycle count backup/restore to persist partition
 - Cycle count bins can now be read and set as a all, fix sepolicies
   accordingly

Tests:
  - pts-tradefed run pts -a arm64-v8a -m PtsHardwareInfoHostTestCases
  - adb bugreport
  - no "avc: denied" on health vendor service
Bug: 72776338
Bug: 72769405
Change-Id: I8052eb00fbe41aebd1e691d973e9aca32b0da125
diff --git a/CleanSpec.mk b/CleanSpec.mk
index a9caff8..796cb53 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -100,3 +100,7 @@
 # Remove Widevine HAL 1.0
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.drm@1.0-service.widevine.rc)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.drm@1.0-service.widevine)
+
+# Health HAL 2.0
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/bin/hw/android.hardware.health@2.0-service)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/vendor/etc/init/android.hardware.health@2.0-service.rc)
diff --git a/device-common.mk b/device-common.mk
index c123e6d..f495afe 100644
--- a/device-common.mk
+++ b/device-common.mk
@@ -626,3 +626,7 @@
 # Enable Perfetto traced
 PRODUCT_PROPERTY_OVERRIDES += \
     persist.traced.enable=1
+
+# health HAL
+PRODUCT_PACKAGES += \
+    android.hardware.health@2.0-service.marlin
diff --git a/dumpstate/DumpstateDevice.cpp b/dumpstate/DumpstateDevice.cpp
index 4f56c2b..d32801e 100755
--- a/dumpstate/DumpstateDevice.cpp
+++ b/dumpstate/DumpstateDevice.cpp
@@ -161,7 +161,7 @@
     DumpFileToFd(fd, "FUSB302 logs", "/d/ipc_logging/fusb302/log");
 
     RunCommandToFd(fd, "Power supply properties", {"/vendor/bin/sh", "-c", "for f in /sys/class/power_supply/*/uevent ; do echo \"\n------ $f\" ; cat $f ; done"});
-    RunCommandToFd(fd, "Battery cycle count", {"/vendor/bin/sh", "-c", "for f in 1 2 3 4 5 6 7 8 ; do echo $f > /sys/class/power_supply/bms/cycle_count_id; count=`cat /sys/class/power_supply/bms/cycle_count`; echo \"$f: $count\"; done"});
+    DumpFileToFd(fd, "Battery cycle count", "/sys/class/power_supply/bms/device/cycle_counts_bins");
     RunCommandToFd(fd, "QCOM FG SRAM", {"/vendor/bin/sh", "-c", "echo 0x400 > /d/fg_memif/address ; echo 0x200 > /d/fg_memif/count ; cat /d/fg_memif/data"});
 
     /* Check if qsee_logger tool exists */
diff --git a/health/Android.bp b/health/Android.bp
new file mode 100644
index 0000000..1d2bc5a
--- /dev/null
+++ b/health/Android.bp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+cc_binary {
+    name: "android.hardware.health@2.0-service.marlin",
+    init_rc: ["android.hardware.health@2.0-service.marlin.rc"],
+    proprietary: true,
+    relative_install_path: "hw",
+    srcs: [
+        "HealthService.cpp",
+        "CycleCountBackupRestore.cpp",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+
+    static_libs: [
+        "android.hardware.health@2.0-impl",
+        "android.hardware.health@1.0-convert",
+        "libhealthservice",
+        "libbatterymonitor",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.health@2.0",
+    ],
+
+    header_libs: ["libhealthd_headers"],
+}
diff --git a/health/CycleCountBackupRestore.cpp b/health/CycleCountBackupRestore.cpp
new file mode 100644
index 0000000..581dfed
--- /dev/null
+++ b/health/CycleCountBackupRestore.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "CycleCountBackupRestore.h"
+
+namespace device {
+namespace google {
+namespace marlin {
+namespace health {
+
+static constexpr char kCycCntFile[] = "sys/class/power_supply/bms/device/cycle_counts_bins";
+static constexpr char kSysPersistFile[] = "/persist/battery/qcom_cycle_counts_bins";
+static constexpr int kBuffSize = 256;
+
+CycleCountBackupRestore::CycleCountBackupRestore() { }
+
+void CycleCountBackupRestore::Restore()
+{
+    ReadFromStorage();
+    ReadFromSRAM();
+    UpdateAndSave();
+}
+
+void CycleCountBackupRestore::Backup()
+{
+    ReadFromSRAM();
+    UpdateAndSave();
+}
+
+void CycleCountBackupRestore::ReadFromStorage()
+{
+    std::string buffer;
+
+    if (!android::base::ReadFileToString(std::string(kSysPersistFile), &buffer)) {
+        LOG(ERROR) << "Cannot read the storage file";
+        return;
+    }
+
+    if (sscanf(buffer.c_str(), "%d %d %d %d %d %d %d %d",
+               &sw_bins_[0], &sw_bins_[1], &sw_bins_[2], &sw_bins_[3],
+               &sw_bins_[4], &sw_bins_[5], &sw_bins_[6], &sw_bins_[7])
+        != kBucketCount)
+        LOG(ERROR) << "data format is wrong in the storage file: " << buffer;
+    else
+        LOG(INFO) << "Storage data: " << buffer;
+}
+
+void CycleCountBackupRestore::SaveToStorage()
+{
+    char strData[kBuffSize];
+
+    snprintf(strData, kBuffSize, "%d %d %d %d %d %d %d %d",
+             sw_bins_[0], sw_bins_[1], sw_bins_[2], sw_bins_[3],
+             sw_bins_[4], sw_bins_[5], sw_bins_[6], sw_bins_[7]);
+
+    LOG(INFO) << "Save to Storage: " << strData;
+
+    if (!android::base::WriteStringToFile(strData, std::string(kSysPersistFile)))
+        LOG(ERROR) << "Write file error: " << strerror(errno);
+}
+
+void CycleCountBackupRestore::ReadFromSRAM()
+{
+    std::string buffer;
+
+    if (!android::base::ReadFileToString(std::string(kCycCntFile), &buffer)) {
+        LOG(ERROR) << "Read cycle counter error: " << strerror(errno);
+        return;
+    }
+
+    buffer = android::base::Trim(buffer);
+
+    if (sscanf(buffer.c_str(), "%d %d %d %d %d %d %d %d",
+               &hw_bins_[0], &hw_bins_[1], &hw_bins_[2], &hw_bins_[3],
+               &hw_bins_[4], &hw_bins_[5], &hw_bins_[6], &hw_bins_[7])
+        != kBucketCount)
+        LOG(ERROR) << "Failed to parse SRAM bins: " << buffer;
+    else
+        LOG(INFO) << "SRAM data: " << buffer;
+}
+
+void CycleCountBackupRestore::SaveToSRAM()
+{
+    char strData[kBuffSize];
+
+    snprintf(strData, kBuffSize, "%d %d %d %d %d %d %d %d",
+             hw_bins_[0], hw_bins_[1], hw_bins_[2], hw_bins_[3],
+             hw_bins_[4], hw_bins_[5], hw_bins_[6], hw_bins_[7]);
+
+    LOG(INFO) << "Save to SRAM: "  << strData ;
+
+    if (!android::base::WriteStringToFile(strData, std::string(kCycCntFile)))
+        LOG(ERROR) << "Write data error: " << strerror(errno);
+}
+
+
+void CycleCountBackupRestore::UpdateAndSave()
+{
+    bool backup = false;
+    bool restore = false;
+    for (int i = 0; i < kBucketCount; i++) {
+        if (hw_bins_[i] < sw_bins_[i]) {
+            hw_bins_[i] = sw_bins_[i];
+            restore = true;
+        } else if (hw_bins_[i] > sw_bins_[i]) {
+            sw_bins_[i] = hw_bins_[i];
+            backup = true;
+        }
+    }
+    if (restore)
+        SaveToSRAM();
+    if (backup)
+        SaveToStorage();
+}
+
+} // namespace health
+} // namespace marlin
+} // namespace google
+} // namespace device
diff --git a/health/CycleCountBackupRestore.h b/health/CycleCountBackupRestore.h
new file mode 100644
index 0000000..6e3628d
--- /dev/null
+++ b/health/CycleCountBackupRestore.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef DEVICE_GOOGLE_MARLIN_HEALTH_CYCLECOUNTBACKUPRESTORE_H
+#define DEVICE_GOOGLE_MARLIN_HEALTH_CYCLECOUNTBACKUPRESTORE_H
+
+#include <string>
+#include <android-base/file.h>
+#include <android-base/strings.h>
+#include <android-base/logging.h>
+
+namespace device {
+namespace google {
+namespace marlin {
+namespace health {
+
+static constexpr int kBucketCount = 8;
+
+class CycleCountBackupRestore {
+public:
+    CycleCountBackupRestore();
+    void Restore();
+    void Backup();
+
+private:
+    int sw_bins_[kBucketCount];
+    int hw_bins_[kBucketCount];
+
+    void ReadFromStorage();
+    void SaveToStorage();
+    void ReadFromSRAM();
+    void SaveToSRAM();
+    void UpdateAndSave();
+};
+
+} // namespace health
+} // namespace marlin
+} // namespace google
+} // namespace device
+
+#endif // #ifndef DEVICE_GOOGLE_MARLIN_HEALTH_CYCLECOUNTBACKUPRESTORE_H
diff --git a/health/HealthService.cpp b/health/HealthService.cpp
new file mode 100644
index 0000000..93f159e
--- /dev/null
+++ b/health/HealthService.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "android.hardware.health@2.0-service.marlin"
+#include <android-base/logging.h>
+
+#include <healthd/healthd.h>
+#include <health2/Health.h>
+#include <health2/service.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include <android-base/file.h>
+#include <android-base/strings.h>
+
+#include <vector>
+#include <string>
+
+#include <sys/stat.h>
+
+#include "CycleCountBackupRestore.h"
+
+using android::hardware::health::V2_0::StorageInfo;
+using android::hardware::health::V2_0::DiskStats;
+using ::device::google::marlin::health::CycleCountBackupRestore;
+
+static constexpr int kBackupTrigger = 20;
+static constexpr size_t kDiskStatsSize = 11;
+static constexpr char kUFSHealthFile[] = "/sys/devices/soc/624000.ufshc/health";
+static constexpr char kUFSHealthVersionFile[] = "/sys/kernel/debug/ufshcd0/show_hba";
+static constexpr char kUFSName[] = "UFS0";
+static constexpr char kDiskStatsFile[] = "/sys/block/sda/stat";
+
+static CycleCountBackupRestore ccBackupRestore;
+
+int cycle_count_backup(int battery_level)
+{
+    static int saved_soc = 0;
+    static int soc_inc = 0;
+    static bool is_first = true;
+
+    if (is_first) {
+        is_first = false;
+        saved_soc = battery_level;
+        return 0;
+    }
+
+    if (battery_level > saved_soc) {
+        soc_inc += battery_level - saved_soc;
+    }
+
+    saved_soc = battery_level;
+
+    if (soc_inc >= kBackupTrigger) {
+        ccBackupRestore.Backup();
+        soc_inc = 0;
+    }
+    return 0;
+}
+
+// See : hardware/interfaces/health/2.0/README
+
+void healthd_board_init(struct healthd_config*)
+{
+    ccBackupRestore.Restore();
+}
+
+int healthd_board_battery_update(struct android::BatteryProperties *props)
+{
+    return cycle_count_backup(props->batteryLevel);
+}
+
+void get_storage_info(std::vector<StorageInfo>& vec_storage_info) {
+    StorageInfo storage_info = {};
+    std::string buffer, version;
+
+    storage_info.attr.isInternal = true;
+    storage_info.attr.isBootDevice = true;
+    storage_info.attr.name = std::string(kUFSName);
+
+    if (!android::base::ReadFileToString(std::string(kUFSHealthVersionFile), &version)) {
+        return;
+    }
+
+    std::vector<std::string> lines = android::base::Split(version, "\n");
+    if (lines.empty()) {
+        return;
+    }
+
+    char rev[8];
+    if (sscanf(lines[6].c_str(), "ufs version: 0x%7s\n", rev) < 1) {
+        return;
+    }
+
+    storage_info.version = "ufs " + std::string(rev);
+
+    if (!android::base::ReadFileToString(std::string(kUFSHealthFile), &buffer)) {
+        return;
+    }
+
+    lines = android::base::Split(buffer, "\n");
+    if (lines.empty()) {
+        return;
+    }
+
+    for (const auto& line : lines) {
+        char token[32];
+        uint16_t val;
+        int ret;
+        if ((ret = sscanf(line.c_str(),
+                   "Health Descriptor[Byte offset 0x%*d]: %31s = 0x%hx",
+                   token, &val)) < 2) {
+            continue;
+        }
+
+        if (std::string(token) == "bPreEOLInfo") {
+            storage_info.eol = val;
+        } else if (std::string(token) == "bDeviceLifeTimeEstA") {
+            storage_info.lifetimeA = val;
+        } else if (std::string(token) == "bDeviceLifeTimeEstB") {
+            storage_info.lifetimeB = val;
+        }
+    }
+
+    vec_storage_info.resize(1);
+    vec_storage_info[0] = storage_info;
+    return;
+}
+
+
+void get_disk_stats(std::vector<DiskStats>& vec_stats) {
+    DiskStats stats = {};
+
+    stats.attr.isInternal = true;
+    stats.attr.isBootDevice = true;
+    stats.attr.name = std::string(kUFSName);
+
+    std::string buffer;
+    if (!android::base::ReadFileToString(std::string(kDiskStatsFile), &buffer)) {
+        LOG(ERROR) << kDiskStatsFile << ": ReadFileToString failed.";
+        return;
+    }
+
+    // Regular diskstats entries
+    std::stringstream ss(buffer);
+    for (uint i = 0; i < kDiskStatsSize; i++) {
+        ss >> *(reinterpret_cast<uint64_t*>(&stats) + i);
+    }
+    vec_stats.resize(1);
+    vec_stats[0] = stats;
+
+    return;
+}
+
+int main(void) {
+    return health_service_main();
+}
diff --git a/health/android.hardware.health@2.0-service.marlin.rc b/health/android.hardware.health@2.0-service.marlin.rc
new file mode 100644
index 0000000..398a24e
--- /dev/null
+++ b/health/android.hardware.health@2.0-service.marlin.rc
@@ -0,0 +1,4 @@
+service vendor.health-hal-2-0 /vendor/bin/hw/android.hardware.health@2.0-service.marlin
+    class hal
+    user system
+    group system
diff --git a/init.common.rc b/init.common.rc
index 7285b8f..dce7d46 100644
--- a/init.common.rc
+++ b/init.common.rc
@@ -114,6 +114,9 @@
     restorecon_recursive /persist
     mkdir /persist/data 0700 system system
 
+    # for android.hardware.health@2.0-service.marlin cycle count backup
+    mkdir /persist/battery 0700 system system
+
     # Start HW service manager early
     start hwservicemanager
 
@@ -369,6 +372,11 @@
     # wait for devices
     wait_for_prop sys.qcom.devup 1
 
+    # vendor.health-hal needs to be able to RW
+    chown system system /sys/devices/soc/qpnp-fg-17/cycle_counts_bins
+    # HardwareInfo needs to be able to read CC bins
+    chmod 644 /sys/devices/soc/qpnp-fg-17/cycle_counts_bins
+
 on boot
     # from init.power.sh
     # disable thermal hotplug to switch governor
@@ -525,9 +533,6 @@
     chown system system /d/fg_memif/count
     chown system system /d/fg_memif/address
 
-    # com.google.android.hardwareinfo needs to be able to read cycle counts
-    chmod 0666 /sys/class/power_supply/bms/cycle_count_id
-
 on property:wc_transport.start_hci=true
     start vendor.start_hci_filter
 
@@ -808,7 +813,7 @@
 
     # UFS health
     chmod 755 /sys/kernel/debug/ufshcd0
-    chown 644 /sys/kernel/debug/ufshcd0/err_state
+    chmod 644 /sys/kernel/debug/ufshcd0/err_state
     chmod 644 /sys/kernel/debug/ufshcd0/power_mode
     chmod 644 /sys/kernel/debug/ufshcd0/host_regs
     chmod 644 /sys/kernel/debug/ufshcd0/show_hba
diff --git a/manifest.xml b/manifest.xml
index 3f3863e..72c5c95 100644
--- a/manifest.xml
+++ b/manifest.xml
@@ -150,6 +150,15 @@
             <name>IComposer</name>
             <instance>default</instance>
         </interface>
+      </hal>
+    <hal format="hidl">
+        <name>android.hardware.health</name>
+        <transport>hwbinder</transport>
+        <version>2.0</version>
+        <interface>
+            <name>IHealth</name>
+            <instance>default</instance>
+        </interface>
     </hal>
     <hal format="hidl">
         <name>android.hardware.keymaster</name>
diff --git a/sepolicy/file.te b/sepolicy/file.te
index ec2c14c..7945611 100644
--- a/sepolicy/file.te
+++ b/sepolicy/file.te
@@ -74,6 +74,7 @@
 type persist_file, file_type;
 type persist_data_file, file_type;
 type persist_display_file, file_type;
+type persist_battery_file, file_type;
 
 # msm_irqbalance
 type proc_irq, fs_type;
diff --git a/sepolicy/file_contexts b/sepolicy/file_contexts
index 437e07f..259d510 100644
--- a/sepolicy/file_contexts
+++ b/sepolicy/file_contexts
@@ -131,6 +131,8 @@
 /vendor/bin/init\.radio\.sh        u:object_r:init_radio_exec:s0
 /vendor/bin/init\.foreground\.sh   u:object_r:init_foreground_exec:s0
 
+/vendor/bin/hw/android\.hardware\.health@2\.0-service\.marlin          u:object_r:hal_health_default_exec:s0
+
 ###############################################
 # same-process HAL files and their dependencies
 #
@@ -202,6 +204,7 @@
 /persist(/.*)?          u:object_r:persist_file:s0
 /persist/data(/.*)?     u:object_r:persist_data_file:s0
 /persist/display(/.*)?  u:object_r:persist_display_file:s0
+/persist/battery(/.*)?  u:object_r:persist_battery_file:s0
 /persist/sensorcal\.json  u:object_r:sensors_cal_file:s0
 
 # hidraw dynamic sensor
diff --git a/sepolicy/genfs_contexts b/sepolicy/genfs_contexts
index 65f3a65..33ea628 100644
--- a/sepolicy/genfs_contexts
+++ b/sepolicy/genfs_contexts
@@ -56,7 +56,7 @@
 genfscon sysfs /devices/soc/75b5000.i2c/i2c-7/7-001d/power_supply     u:object_r:sysfs_batteryinfo:s0
 genfscon sysfs /devices/soc/msm-bcl-14/power_supply                   u:object_r:sysfs_batteryinfo:s0
 genfscon sysfs /devices/soc/soc:qcom,bcl/power_supply                 u:object_r:sysfs_batteryinfo:s0
-genfscon sysfs /devices/soc/qpnp-fg-17/power_supply                   u:object_r:sysfs_batteryinfo:s0
+genfscon sysfs /devices/soc/qpnp-fg-17                                u:object_r:sysfs_batteryinfo:s0
 genfscon sysfs /devices/soc/qpnp-smbcharger-16/power_supply           u:object_r:sysfs_batteryinfo:s0
 genfscon sysfs /devices/virtual/timed_output/vibrator/voltage_level   u:object_r:sysfs_vibrator:s0
 genfscon sysfs /module/diagchar/parameters/timestamp_switch           u:object_r:sysfs_timestamp_switch:s0
diff --git a/sepolicy/hal_dumpstate_impl.te b/sepolicy/hal_dumpstate_impl.te
index 90558fa..d7c1d35 100644
--- a/sepolicy/hal_dumpstate_impl.te
+++ b/sepolicy/hal_dumpstate_impl.te
@@ -66,7 +66,7 @@
 
 # Query and dump power supply nodes
 allow hal_dumpstate_impl sysfs_batteryinfo:dir search;
-allow hal_dumpstate_impl sysfs_batteryinfo:file rw_file_perms;
+allow hal_dumpstate_impl sysfs_batteryinfo:file r_file_perms;
 
 # Dump QCOM FG content
 allow hal_dumpstate_impl debugfs_fg_sram:dir search;
diff --git a/sepolicy/hal_health_default.te b/sepolicy/hal_health_default.te
new file mode 100644
index 0000000..a5f39de
--- /dev/null
+++ b/sepolicy/hal_health_default.te
@@ -0,0 +1,13 @@
+r_dir_file(hal_health_default, sysfs_msm_subsys)
+
+allow hal_health_default debugfs_ufs:dir search;
+allow hal_health_default sysfs_scsi_devices_0000:dir search;
+allow hal_health_default debugfs_ufs:file { getattr open read };
+allow hal_health_default sysfs_scsi_devices_0000:file { getattr open read };
+
+allow hal_health_default persist_battery_file:file create_file_perms;
+allow hal_health_default persist_battery_file:dir rw_dir_perms;
+allow hal_health_default persist_file:dir search;
+allow hal_health_default kmsg_device:chr_file { open write };
+allow hal_health_default sysfs_msm_subsys:file { write };
+allow hal_health_default sysfs_batteryinfo:file rw_file_perms;
diff --git a/sepolicy/hardware_info_app.te b/sepolicy/hardware_info_app.te
index a25be67..23d0ddd 100644
--- a/sepolicy/hardware_info_app.te
+++ b/sepolicy/hardware_info_app.te
@@ -7,7 +7,7 @@
 
 # SysFS
 allow hardware_info_app sysfs_batteryinfo:dir search;
-allow hardware_info_app sysfs_batteryinfo:file { getattr open read write };
+allow hardware_info_app sysfs_batteryinfo:file { getattr open read };
 allow hardware_info_app sysfs_camera:dir search;
 allow hardware_info_app sysfs_camera:file { getattr open read };
 allow hardware_info_app sysfs_msm_subsys:dir search;