Merge "add shutdown animation" into oc-dev
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 64a2d82..75b3c61 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -919,8 +919,14 @@
     if (!is_file_crypto()) {
         return 0;
     }
-    return e4crypt_create_device_key(args[1].c_str(),
-                                     do_installkeys_ensure_dir_exists);
+    auto unencrypted_dir = args[1] + e4crypt_unencrypted_folder;
+    if (do_installkeys_ensure_dir_exists(unencrypted_dir.c_str())) {
+        PLOG(ERROR) << "Failed to create " << unencrypted_dir;
+        return -1;
+    }
+    std::vector<std::string> exec_args = {"exec", "/system/bin/vdc", "--wait", "cryptfs",
+                                          "enablefilecrypto"};
+    return do_exec(exec_args);
 }
 
 static int do_init_user0(const std::vector<std::string>& args) {
diff --git a/libgrallocusage/GrallocUsageConversion.cpp b/libgrallocusage/GrallocUsageConversion.cpp
index 8164beb..10e728d 100644
--- a/libgrallocusage/GrallocUsageConversion.cpp
+++ b/libgrallocusage/GrallocUsageConversion.cpp
@@ -30,13 +30,17 @@
                                        /* ProducerUsage::CPU_WRITE_OFTEN | */
                                        ProducerUsage::GPU_RENDER_TARGET | ProducerUsage::PROTECTED |
                                        ProducerUsage::CAMERA | ProducerUsage::VIDEO_DECODER |
-                                       ProducerUsage::SENSOR_DIRECT_DATA;
+                                       ProducerUsage::SENSOR_DIRECT_DATA |
+                                       /* Private flags may be consumer or producer */
+                                       GRALLOC_USAGE_PRIVATE_MASK;
     constexpr uint64_t CONSUMER_MASK = ConsumerUsage::CPU_READ |
                                        /* ConsumerUsage::CPU_READ_OFTEN | */
                                        ConsumerUsage::GPU_TEXTURE | ConsumerUsage::HWCOMPOSER |
                                        ConsumerUsage::CLIENT_TARGET | ConsumerUsage::CURSOR |
                                        ConsumerUsage::VIDEO_ENCODER | ConsumerUsage::CAMERA |
-                                       ConsumerUsage::RENDERSCRIPT | ConsumerUsage::GPU_DATA_BUFFER;
+                                       ConsumerUsage::RENDERSCRIPT | ConsumerUsage::GPU_DATA_BUFFER |
+                                       /* Private flags may be consumer or producer */
+                                       GRALLOC_USAGE_PRIVATE_MASK;
     *producerUsage = static_cast<uint64_t>(usage) & PRODUCER_MASK;
     *consumerUsage = static_cast<uint64_t>(usage) & CONSUMER_MASK;
     if ((static_cast<uint32_t>(usage) & GRALLOC_USAGE_SW_READ_OFTEN) == GRALLOC_USAGE_SW_READ_OFTEN) {
diff --git a/storaged/README.properties b/storaged/README.properties
index 70e6026..2d8397f 100644
--- a/storaged/README.properties
+++ b/storaged/README.properties
@@ -1,6 +1,5 @@
 ro.storaged.event.interval    # interval storaged scans for IO stats, in seconds
 ro.storaged.event.perf_check  # check for time spent in event loop, in microseconds
 ro.storaged.disk_stats_pub    # interval storaged publish disk stats, in seconds
-ro.storaged.emmc_info_pub     # interval storaged publish emmc info, in seconds
 ro.storaged.uid_io.interval   # interval storaged checks Per UID IO usage, in seconds
 ro.storaged.uid_io.threshold  # Per UID IO usage limit, in bytes
diff --git a/storaged/include/storaged.h b/storaged/include/storaged.h
index bd1391c..b6a0850 100644
--- a/storaged/include/storaged.h
+++ b/storaged/include/storaged.h
@@ -230,7 +230,6 @@
 // Periodic chores intervals in seconds
 #define DEFAULT_PERIODIC_CHORES_INTERVAL_UNIT ( 60 )
 #define DEFAULT_PERIODIC_CHORES_INTERVAL_DISK_STATS_PUBLISH ( 3600 )
-#define DEFAULT_PERIODIC_CHORES_INTERVAL_EMMC_INFO_PUBLISH ( 86400 )
 #define DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO ( 3600 )
 #define DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO_LIMIT (300)
 
@@ -240,7 +239,6 @@
 struct storaged_config {
     int periodic_chores_interval_unit;
     int periodic_chores_interval_disk_stats_publish;
-    int periodic_chores_interval_emmc_info_publish;
     int periodic_chores_interval_uid_io;
     bool proc_uid_io_available;      // whether uid_io is accessible
     bool diskstats_available;   // whether diskstats is accessible
@@ -253,7 +251,6 @@
     storaged_config mConfig;
     disk_stats_publisher mDiskStats;
     disk_stats_monitor mDsm;
-    storage_info_t *info = nullptr;
     uid_monitor mUidm;
     time_t mStarttime;
 public:
@@ -264,9 +261,6 @@
     void pause(void) {
         sleep(mConfig.periodic_chores_interval_unit);
     }
-    void set_storage_info(storage_info_t *storage_info) {
-        info = storage_info;
-    }
 
     time_t get_starttime(void) {
         return mStarttime;
diff --git a/storaged/include/storaged_info.h b/storaged/include/storaged_info.h
index cb5b8a8..913c814 100644
--- a/storaged/include/storaged_info.h
+++ b/storaged/include/storaged_info.h
@@ -24,43 +24,42 @@
 
 using namespace std;
 
-// two characters in string for each byte
-struct str_hex {
-    char str[2];
-};
-
 class storage_info_t {
 protected:
     FRIEND_TEST(storaged_test, storage_info_t);
-    uint8_t eol;                    // pre-eol (end of life) information
-    uint8_t lifetime_a;             // device life time estimation (type A)
-    uint8_t lifetime_b;             // device life time estimation (type B)
+    uint16_t eol;                   // pre-eol (end of life) information
+    uint16_t lifetime_a;            // device life time estimation (type A)
+    uint16_t lifetime_b;            // device life time estimation (type B)
     string version;                 // version string
-public:
     void publish();
+public:
+    storage_info_t() : eol(0), lifetime_a(0), lifetime_b(0) {}
     virtual ~storage_info_t() {}
-    virtual bool init() = 0;
-    virtual bool update() = 0;
+    virtual bool report() = 0;
 };
 
 class emmc_info_t : public storage_info_t {
 private:
-    // minimum size of a ext_csd file
-    const int EXT_CSD_FILE_MIN_SIZE = 1024;
-    // List of interesting offsets
-    const size_t EXT_CSD_REV_IDX = 192 * sizeof(str_hex);
-    const size_t EXT_PRE_EOL_INFO_IDX = 267 * sizeof(str_hex);
-    const size_t EXT_DEVICE_LIFE_TIME_EST_A_IDX = 268 * sizeof(str_hex);
-    const size_t EXT_DEVICE_LIFE_TIME_EST_B_IDX = 269 * sizeof(str_hex);
-
-    const char* ext_csd_file = "/d/mmc0/mmc0:0001/ext_csd";
-    const char* emmc_ver_str[8] = {
-        "4.0", "4.1", "4.2", "4.3", "Obsolete", "4.41", "4.5", "5.0"
+    const string emmc_sysfs = "/sys/bus/mmc/devices/mmc0:0001/";
+    const string emmc_debugfs = "/d/mmc0/mmc0:0001/ext_csd";
+    const char* emmc_ver_str[9] = {
+        "4.0", "4.1", "4.2", "4.3", "Obsolete", "4.41", "4.5", "5.0", "5.1"
     };
 public:
     virtual ~emmc_info_t() {}
-    bool init();
-    bool update();
+    bool report();
+    bool report_sysfs();
+    bool report_debugfs();
 };
 
+class ufs_info_t : public storage_info_t {
+private:
+    const string health_file = "/sys/devices/soc/624000.ufshc/health";
+public:
+    virtual ~ufs_info_t() {}
+    bool report();
+};
+
+void report_storage_health();
+
 #endif /* _STORAGED_INFO_H_ */
diff --git a/storaged/main.cpp b/storaged/main.cpp
index e25298b..2f2273d 100644
--- a/storaged/main.cpp
+++ b/storaged/main.cpp
@@ -43,7 +43,6 @@
 #include <storaged_utils.h>
 
 storaged_t storaged;
-emmc_info_t emmc_info;
 
 // Function of storaged's main thread
 void* storaged_main(void* s) {
@@ -114,10 +113,7 @@
     }
 
     if (flag_main_service) { // start main thread
-        if (emmc_info.init()) {
-            storaged.set_storage_info(&emmc_info);
-        }
-
+        report_storage_health();
         // Start the main thread of storaged
         pthread_t storaged_main_thread;
         errno = pthread_create(&storaged_main_thread, NULL, storaged_main, &storaged);
diff --git a/storaged/storaged.cpp b/storaged/storaged.cpp
index 88fbb7a..1770922 100644
--- a/storaged/storaged.cpp
+++ b/storaged/storaged.cpp
@@ -170,6 +170,9 @@
 }
 
 void storaged_t::init_battery_service() {
+    if (!mConfig.proc_uid_io_available)
+        return;
+
     sp<IBatteryPropertiesRegistrar> battery_properties = get_battery_properties_service();
     if (battery_properties == NULL) {
         LOG_TO(SYSTEM, WARNING) << "failed to find batteryproperties service";
@@ -203,9 +206,6 @@
     mConfig.periodic_chores_interval_disk_stats_publish =
         property_get_int32("ro.storaged.disk_stats_pub", DEFAULT_PERIODIC_CHORES_INTERVAL_DISK_STATS_PUBLISH);
 
-    mConfig.periodic_chores_interval_emmc_info_publish =
-        property_get_int32("ro.storaged.emmc_info_pub", DEFAULT_PERIODIC_CHORES_INTERVAL_EMMC_INFO_PUBLISH);
-
     mConfig.periodic_chores_interval_uid_io =
         property_get_int32("ro.storaged.uid_io.interval", DEFAULT_PERIODIC_CHORES_INTERVAL_UID_IO);
 
@@ -221,12 +221,6 @@
         }
     }
 
-    if (info && mTimer &&
-        (mTimer % mConfig.periodic_chores_interval_emmc_info_publish) == 0) {
-        info->update();
-        info->publish();
-    }
-
     if (mConfig.proc_uid_io_available && mTimer &&
             (mTimer % mConfig.periodic_chores_interval_uid_io) == 0) {
          mUidm.report();
diff --git a/storaged/storaged_info.cpp b/storaged/storaged_info.cpp
index 73d611c..434bd74 100644
--- a/storaged/storaged_info.cpp
+++ b/storaged/storaged_info.cpp
@@ -16,83 +16,169 @@
 
 #define LOG_TAG "storaged"
 
+#include <stdio.h>
 #include <string.h>
 
 #include <android-base/file.h>
-#include <android-base/logging.h>
 #include <android-base/parseint.h>
+#include <android-base/logging.h>
+#include <android-base/strings.h>
 #include <log/log_event_list.h>
 
 #include "storaged.h"
 
 using namespace std;
-using namespace android;
 using namespace android::base;
 
+void report_storage_health()
+{
+    emmc_info_t mmc;
+    ufs_info_t ufs;
+
+    mmc.report();
+    ufs.report();
+}
+
 void storage_info_t::publish()
 {
-    if (eol == 0 && lifetime_a == 0 && lifetime_b == 0) {
-        return;
-    }
-
     android_log_event_list(EVENTLOGTAG_EMMCINFO)
         << version << eol << lifetime_a << lifetime_b
         << LOG_ID_EVENTS;
 }
 
-bool emmc_info_t::init()
+bool emmc_info_t::report()
+{
+    if (!report_sysfs() && !report_debugfs())
+        return false;
+
+    publish();
+    return true;
+}
+
+bool emmc_info_t::report_sysfs()
 {
     string buffer;
-    if (!ReadFileToString(ext_csd_file, &buffer) ||
-        buffer.length() < (size_t)EXT_CSD_FILE_MIN_SIZE) {
+    uint16_t rev = 0;
+
+    if (!ReadFileToString(emmc_sysfs + "rev", &buffer)) {
         return false;
     }
 
-    string ver_str = buffer.substr(EXT_CSD_REV_IDX, sizeof(str_hex));
-    uint8_t ext_csd_rev;
-    if (!ParseUint(ver_str, &ext_csd_rev)) {
-        LOG_TO(SYSTEM, ERROR) << "Failure on parsing EXT_CSD_REV.";
+    if (sscanf(buffer.c_str(), "0x%hx", &rev) < 1 ||
+        rev < 7 || rev > ARRAY_SIZE(emmc_ver_str)) {
         return false;
     }
 
     version = "emmc ";
-    version += (ext_csd_rev < ARRAY_SIZE(emmc_ver_str)) ?
-                emmc_ver_str[ext_csd_rev] : "Unknown";
+    version += emmc_ver_str[rev];
 
-    if (ext_csd_rev < 7) {
+    if (!ReadFileToString(emmc_sysfs + "pre_eol_info", &buffer)) {
         return false;
     }
 
-    return update();
-}
-
-bool emmc_info_t::update()
-{
-    string buffer;
-    if (!ReadFileToString(ext_csd_file, &buffer) ||
-        buffer.length() < (size_t)EXT_CSD_FILE_MIN_SIZE) {
+    if (sscanf(buffer.c_str(), "%hx", &eol) < 1 || eol == 0) {
         return false;
     }
 
-    string str = buffer.substr(EXT_PRE_EOL_INFO_IDX, sizeof(str_hex));
-    if (!ParseUint(str, &eol)) {
-        LOG_TO(SYSTEM, ERROR) << "Failure on parsing EXT_PRE_EOL_INFO.";
+    if (!ReadFileToString(emmc_sysfs + "life_time", &buffer)) {
         return false;
     }
 
-    str = buffer.substr(EXT_DEVICE_LIFE_TIME_EST_A_IDX, sizeof(str_hex));
-    if (!ParseUint(str, &lifetime_a)) {
-        LOG_TO(SYSTEM, ERROR)
-            << "Failure on parsing EXT_DEVICE_LIFE_TIME_EST_TYP_A.";
-        return false;
-    }
-
-    str = buffer.substr(EXT_DEVICE_LIFE_TIME_EST_B_IDX, sizeof(str_hex));
-    if (!ParseUint(str, &lifetime_b)) {
-        LOG_TO(SYSTEM, ERROR)
-            << "Failure on parsing EXT_DEVICE_LIFE_TIME_EST_TYP_B.";
+    if (sscanf(buffer.c_str(), "0x%hx 0x%hx", &lifetime_a, &lifetime_b) < 2 ||
+        (lifetime_a == 0 && lifetime_b == 0)) {
         return false;
     }
 
     return true;
 }
+
+const size_t EXT_CSD_FILE_MIN_SIZE = 1024;
+/* 2 characters in string for each byte */
+const size_t EXT_CSD_REV_IDX = 192 * 2;
+const size_t EXT_PRE_EOL_INFO_IDX = 267 * 2;
+const size_t EXT_DEVICE_LIFE_TIME_EST_A_IDX = 268 * 2;
+const size_t EXT_DEVICE_LIFE_TIME_EST_B_IDX = 269 * 2;
+
+bool emmc_info_t::report_debugfs()
+{
+    string buffer;
+    uint16_t rev = 0;
+
+    if (!ReadFileToString(emmc_debugfs, &buffer) ||
+        buffer.length() < (size_t)EXT_CSD_FILE_MIN_SIZE) {
+        return false;
+    }
+
+    string str = buffer.substr(EXT_CSD_REV_IDX, 2);
+    if (!ParseUint(str, &rev) ||
+        rev < 7 || rev > ARRAY_SIZE(emmc_ver_str)) {
+        return false;
+    }
+
+    version = "emmc ";
+    version += emmc_ver_str[rev];
+
+    str = buffer.substr(EXT_PRE_EOL_INFO_IDX, 2);
+    if (!ParseUint(str, &eol)) {
+        return false;
+    }
+
+    str = buffer.substr(EXT_DEVICE_LIFE_TIME_EST_A_IDX, 2);
+    if (!ParseUint(str, &lifetime_a)) {
+        return false;
+    }
+
+    str = buffer.substr(EXT_DEVICE_LIFE_TIME_EST_B_IDX, 2);
+    if (!ParseUint(str, &lifetime_b)) {
+        return false;
+    }
+
+    return true;
+}
+
+bool ufs_info_t::report()
+{
+    string buffer;
+    if (!ReadFileToString(health_file, &buffer)) {
+        return false;
+    }
+
+    vector<string> lines = Split(buffer, "\n");
+    if (lines.empty()) {
+        return false;
+    }
+
+    char rev[8];
+    if (sscanf(lines[0].c_str(), "ufs version: 0x%7s\n", rev) < 1) {
+        return false;
+    }
+
+    version = "ufs " + string(rev);
+
+    for (size_t i = 1; i < lines.size(); i++) {
+        char token[32];
+        uint16_t val;
+        int ret;
+        if ((ret = sscanf(lines[i].c_str(),
+                   "Health Descriptor[Byte offset 0x%*d]: %31s = 0x%hx",
+                   token, &val)) < 2) {
+            continue;
+        }
+
+        if (string(token) == "bPreEOLInfo") {
+            eol = val;
+        } else if (string(token) == "bDeviceLifeTimeEstA") {
+            lifetime_a = val;
+        } else if (string(token) == "bDeviceLifeTimeEstB") {
+            lifetime_b = val;
+        }
+    }
+
+    if (eol == 0 || (lifetime_a == 0 && lifetime_b == 0)) {
+        return false;
+    }
+
+    publish();
+    return true;
+}
+
diff --git a/storaged/tests/storaged_test.cpp b/storaged/tests/storaged_test.cpp
index e335cad..b103ac1 100644
--- a/storaged/tests/storaged_test.cpp
+++ b/storaged/tests/storaged_test.cpp
@@ -29,7 +29,6 @@
 
 #define MMC_DISK_STATS_PATH "/sys/block/mmcblk0/stat"
 #define SDA_DISK_STATS_PATH "/sys/block/sda/stat"
-#define EMMC_EXT_CSD_PATH "/d/mmc0/mmc0:0001/ext_csd"
 
 static void pause(uint32_t sec) {
     const char* path = "/cache/test";
@@ -58,13 +57,8 @@
 const char* DISK_STATS_PATH;
 TEST(storaged_test, retvals) {
     struct disk_stats stats;
-    emmc_info_t info;
     memset(&stats, 0, sizeof(struct disk_stats));
 
-    if (info.init()) {
-        EXPECT_TRUE(info.update());
-    }
-
     if (access(MMC_DISK_STATS_PATH, R_OK) >= 0) {
         DISK_STATS_PATH = MMC_DISK_STATS_PATH;
     } else if (access(SDA_DISK_STATS_PATH, R_OK) >= 0) {
@@ -127,20 +121,6 @@
     }
 }
 
-TEST(storaged_test, storage_info_t) {
-    emmc_info_t info;
-
-    if (access(EMMC_EXT_CSD_PATH, R_OK) >= 0) {
-        int ret = info.init();
-        if (ret) {
-            EXPECT_TRUE(info.version.empty());
-            ASSERT_TRUE(info.update());
-            // update should put something in info.
-            EXPECT_TRUE(info.eol || info.lifetime_a || info.lifetime_b);
-        }
-    }
-}
-
 static double mean(std::deque<uint32_t> nums) {
     double sum = 0.0;
     for (uint32_t i : nums) {