Merge "Remove libstats/Android.bp"
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index d3ee659..3e9c942 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -1118,6 +1118,12 @@
             continue;
         }
 
+        // Terrible hack to make it possible to remount /data.
+        // TODO: refact fs_mgr_mount_all and get rid of this.
+        if (mount_mode == MOUNT_MODE_ONLY_USERDATA && current_entry.mount_point != "/data") {
+            continue;
+        }
+
         // Translate LABEL= file system labels into block devices.
         if (is_extfs(current_entry.fs_type)) {
             if (!TranslateExtLabels(&current_entry)) {
@@ -1351,6 +1357,7 @@
     return ret;
 }
 
+// TODO(b/143970043): return different error codes based on which step failed.
 int fs_mgr_remount_userdata_into_checkpointing(Fstab* fstab) {
     auto entry = GetMountedEntryForUserdata(fstab);
     if (entry == nullptr) {
@@ -1374,12 +1381,29 @@
         }
         if (mount(entry->blk_device.c_str(), entry->mount_point.c_str(), "none",
                   MS_REMOUNT | entry->flags, entry->fs_options.c_str()) != 0) {
-            LERROR << "Failed to remount userdata in checkpointing mode";
+            PERROR << "Failed to remount userdata in checkpointing mode";
             return -1;
         }
     } else {
-        // STOPSHIP(b/143970043): support remounting for ext4.
-        LWARNING << "Remounting into checkpointing is not supported for ex4. Proceed with caution";
+        // STOPSHIP(b/143970043): support remounting for ext4 + metadata encryption.
+        if (should_use_metadata_encryption(*entry)) {
+            LWARNING << "Remounting into checkpointing is not supported for metadata encrypted "
+                     << "ext4 userdata. Proceed with caution";
+            return 0;
+        }
+        if (umount2("/data", UMOUNT_NOFOLLOW) != 0) {
+            PERROR << "Failed to umount /data";
+            return -1;
+        }
+        DeviceMapper& dm = DeviceMapper::Instance();
+        // TODO(b/143970043): need to delete every dm-device under the one userdata is mounted on.
+        if (!dm.DeleteDeviceIfExists("bow")) {
+            LERROR << "Failed to delete dm-bow";
+            return -1;
+        }
+        // TODO(b/143970043): remove this hack after fs_mgr_mount_all is refactored.
+        int result = fs_mgr_mount_all(fstab, MOUNT_MODE_ONLY_USERDATA);
+        return result == FS_MGR_MNTALL_FAIL ? -1 : 0;
     }
     return 0;
 }
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index ca67f37..9bc38f9 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -46,7 +46,9 @@
 enum mount_mode {
     MOUNT_MODE_DEFAULT = 0,
     MOUNT_MODE_EARLY = 1,
-    MOUNT_MODE_LATE = 2
+    MOUNT_MODE_LATE = 2,
+    // TODO(b/135984674): remove this after refactoring fs_mgr_mount_all.
+    MOUNT_MODE_ONLY_USERDATA = 3
 };
 
 #define FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED 7
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 485806b..98a9805 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -583,7 +583,7 @@
         return reboot_into_recovery(options);
         /* If reboot worked, there is no return. */
     } else if (code == FS_MGR_MNTALL_DEV_FILE_ENCRYPTED) {
-        if (!userdata_remount && !FscryptInstallKeyring()) {
+        if (!FscryptInstallKeyring()) {
             return Error() << "FscryptInstallKeyring() failed";
         }
         property_set("ro.crypto.state", "encrypted");
@@ -594,7 +594,7 @@
         ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
         return {};
     } else if (code == FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED) {
-        if (!userdata_remount && !FscryptInstallKeyring()) {
+        if (!FscryptInstallKeyring()) {
             return Error() << "FscryptInstallKeyring() failed";
         }
         property_set("ro.crypto.state", "encrypted");
@@ -605,7 +605,7 @@
         ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
         return {};
     } else if (code == FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION) {
-        if (!userdata_remount && !FscryptInstallKeyring()) {
+        if (!FscryptInstallKeyring()) {
             return Error() << "FscryptInstallKeyring() failed";
         }
         property_set("ro.crypto.state", "encrypted");
diff --git a/init/fscrypt_init_extensions.cpp b/init/fscrypt_init_extensions.cpp
index 7820f3d..fbd8189 100644
--- a/init/fscrypt_init_extensions.cpp
+++ b/init/fscrypt_init_extensions.cpp
@@ -42,6 +42,10 @@
 using namespace android::fscrypt;
 
 bool FscryptInstallKeyring() {
+    if (keyctl_search(KEY_SPEC_SESSION_KEYRING, "keyring", "fscrypt", 0) != -1) {
+        LOG(INFO) << "Keyring is already created";
+        return true;
+    }
     key_serial_t device_keyring = add_key("keyring", "fscrypt", 0, 0, KEY_SPEC_SESSION_KEYRING);
 
     if (device_keyring == -1) {
diff --git a/init/reboot.cpp b/init/reboot.cpp
index c9b521a..b04db7f 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -186,17 +186,17 @@
     }
 }
 
-static Result<void> ShutdownVold() {
-    const char* vdc_argv[] = {"/system/bin/vdc", "volume", "shutdown"};
+static Result<void> CallVdc(const std::string& system, const std::string& cmd) {
+    const char* vdc_argv[] = {"/system/bin/vdc", system.c_str(), cmd.c_str()};
     int status;
     if (logwrap_fork_execvp(arraysize(vdc_argv), vdc_argv, &status, false, LOG_KLOG, true,
                             nullptr) != 0) {
-        return ErrnoError() << "Failed to call 'vdc volume shutdown'";
+        return ErrnoError() << "Failed to call '/system/bin/vdc " << system << " " << cmd << "'";
     }
     if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
         return {};
     }
-    return Error() << "'vdc volume shutdown' failed : " << status;
+    return Error() << "'/system/bin/vdc " << system << " " << cmd << "' failed : " << status;
 }
 
 static void LogShutdownTime(UmountStat stat, Timer* t) {
@@ -658,7 +658,7 @@
     // 3. send volume shutdown to vold
     Service* vold_service = ServiceList::GetInstance().FindService("vold");
     if (vold_service != nullptr && vold_service->IsRunning()) {
-        ShutdownVold();
+        CallVdc("volume", "shutdown");
         vold_service->Stop();
     } else {
         LOG(INFO) << "vold not running, skipping vold shutdown";
@@ -774,8 +774,12 @@
         // TODO(b/135984674): store information about offending services for debugging.
         return Error() << r << " post-data services are still running";
     }
-    // TODO(b/143970043): in case of ext4 we probably we will need to restart vold and kill zram
-    //  backing device.
+    if (auto result = KillZramBackingDevice(); !result) {
+        return result;
+    }
+    if (auto result = CallVdc("volume", "reset"); !result) {
+        return result;
+    }
     if (int r = StopServicesAndLogViolations(GetDebuggingServices(true /* only_post_data */), 5s,
                                              false /* SIGKILL */);
         r > 0) {
diff --git a/libstats/socket/include/stats_event.h b/libstats/socket/include/stats_event.h
index 1760e7e..6a33d54 100644
--- a/libstats/socket/include/stats_event.h
+++ b/libstats/socket/include/stats_event.h
@@ -95,14 +95,14 @@
 void stats_event_write_float(struct stats_event* event, float value);
 void stats_event_write_bool(struct stats_event* event, bool value);
 
-void stats_event_write_byte_array(struct stats_event* event, uint8_t* buf, size_t numBytes);
+void stats_event_write_byte_array(struct stats_event* event, const uint8_t* buf, size_t numBytes);
 
 // Buf must be null-terminated.
 void stats_event_write_string8(struct stats_event* event, const char* buf);
 
 // Tags must be null-terminated.
-void stats_event_write_attribution_chain(struct stats_event* event, uint32_t* uids,
-                                         const char** tags, uint8_t numNodes);
+void stats_event_write_attribution_chain(struct stats_event* event, const uint32_t* uids,
+                                         const char* const* tags, uint8_t numNodes);
 
 /* key_value_pair struct can be constructed as follows:
  *    struct key_value_pair pair = {.key = key, .valueType = STRING_TYPE,
diff --git a/libstats/socket/stats_event.c b/libstats/socket/stats_event.c
index dfd587a..ef887e3 100644
--- a/libstats/socket/stats_event.c
+++ b/libstats/socket/stats_event.c
@@ -132,7 +132,7 @@
     }
 }
 
-static void append_byte_array(struct stats_event* event, uint8_t* buf, size_t size) {
+static void append_byte_array(struct stats_event* event, const uint8_t* buf, size_t size) {
     if (!overflows(event, size)) {
         memcpy(&event->buf[event->size], buf, size);
         event->size += size;
@@ -185,7 +185,7 @@
     append_bool(event, value);
 }
 
-void stats_event_write_byte_array(struct stats_event* event, uint8_t* buf, size_t numBytes) {
+void stats_event_write_byte_array(struct stats_event* event, const uint8_t* buf, size_t numBytes) {
     if (event->errors) return;
 
     start_field(event, BYTE_ARRAY_TYPE);
@@ -202,8 +202,8 @@
 }
 
 // Tags are assumed to be encoded using UTF8
-void stats_event_write_attribution_chain(struct stats_event* event, uint32_t* uids,
-                                         const char** tags, uint8_t numNodes) {
+void stats_event_write_attribution_chain(struct stats_event* event, const uint32_t* uids,
+                                         const char* const* tags, uint8_t numNodes) {
     if (numNodes > MAX_BYTE_VALUE) event->errors |= ERROR_ATTRIBUTION_CHAIN_TOO_LONG;
     if (event->errors) return;