Merge "Implement getHardwareInfo() in Trusty KM TA"
diff --git a/code_coverage/Android.bp b/code_coverage/Android.bp
index 2cb1617..f2c5341 100644
--- a/code_coverage/Android.bp
+++ b/code_coverage/Android.bp
@@ -24,6 +24,14 @@
                 },
             },
         },
+        riscv64: {
+            src: "empty_policy/code_coverage.riscv64.policy",
+            product_variables: {
+                native_coverage: {
+                    src: "seccomp_policy/code_coverage.riscv64.policy",
+                },
+            },
+        },
         x86: {
             src: "empty_policy/code_coverage.x86.policy",
             product_variables: {
@@ -67,6 +75,14 @@
                 },
             },
         },
+        riscv64: {
+            src: "empty_policy/code_coverage.riscv64.policy",
+            product_variables: {
+                native_coverage: {
+                    src: "seccomp_policy/code_coverage.riscv64.policy",
+                },
+            },
+        },
         x86: {
             src: "empty_policy/code_coverage.x86_64.policy",
             product_variables: {
diff --git a/code_coverage/empty_policy/code_coverage.riscv64.policy b/code_coverage/empty_policy/code_coverage.riscv64.policy
new file mode 100644
index 0000000..9456932
--- /dev/null
+++ b/code_coverage/empty_policy/code_coverage.riscv64.policy
@@ -0,0 +1,2 @@
+# empty unless code_coverage is enabled.
+# code_coverage.riscv64.policy
diff --git a/code_coverage/seccomp_policy/code_coverage.riscv64.policy b/code_coverage/seccomp_policy/code_coverage.riscv64.policy
new file mode 100644
index 0000000..fdb4d1e
--- /dev/null
+++ b/code_coverage/seccomp_policy/code_coverage.riscv64.policy
@@ -0,0 +1,15 @@
+close: 1
+fchmod: 1
+mkdirat: 1
+msync: 1
+munmap: 1
+openat: 1
+write: 1
+fcntl: 1
+fstat: 1
+ftruncate: 1
+geteuid: 1
+lseek: 1
+mmap: 1
+rt_sigreturn: 1
+prctl: 1
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index cc09d09..6213aeb 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -120,13 +120,9 @@
     return !stat(path.c_str(), &st) && S_ISDIR(st.st_mode);
 }
 
-// Similar test as overlayfs workdir= validation in the kernel for read-write
-// validation, except we use fs_mgr_work.  Covers space and storage issues.
-bool fs_mgr_dir_is_writable(const std::string& path) {
-    auto test_directory = path + "/fs_mgr_work";
-    rmdir(test_directory.c_str());
-    auto ret = !mkdir(test_directory.c_str(), 0700);
-    return ret | !rmdir(test_directory.c_str());
+bool fs_mgr_rw_access(const std::string& path) {
+    if (path.empty()) return false;
+    return access(path.c_str(), R_OK | W_OK) == 0;
 }
 
 // At less than 1% or 8MB of free space return value of false,
@@ -280,7 +276,7 @@
         if (!fs_mgr_is_dir(upper)) continue;
         auto work = dir + kWorkName;
         if (!fs_mgr_is_dir(work)) continue;
-        if (!fs_mgr_dir_is_writable(work)) continue;
+        if (!fs_mgr_rw_access(work)) continue;
         return dir;
     }
     return "";
@@ -317,11 +313,6 @@
     return "/system";
 }
 
-bool fs_mgr_rw_access(const std::string& path) {
-    if (path.empty()) return false;
-    return access(path.c_str(), R_OK | W_OK) == 0;
-}
-
 constexpr char kOverlayfsFileContext[] = "u:object_r:overlayfs_file:s0";
 
 class AutoSetFsCreateCon final {
@@ -1089,7 +1080,7 @@
     return true;
 }
 
-static bool CanUseSuperPartition(const Fstab& fstab) {
+static bool CanUseSuperPartition(const Fstab& fstab, bool* is_virtual_ab) {
     auto slot_number = fs_mgr_overlayfs_slot_number();
     auto super_device = fs_mgr_overlayfs_super_device(slot_number);
     if (!fs_mgr_rw_access(super_device) || !fs_mgr_overlayfs_has_logical(fstab)) {
@@ -1099,6 +1090,7 @@
     if (!metadata) {
         return false;
     }
+    *is_virtual_ab = !!(metadata->header.flags & LP_HEADER_FLAG_VIRTUAL_AB_DEVICE);
     return true;
 }
 
@@ -1111,13 +1103,12 @@
         return *partition_exists;
     }
 
-    // Try ImageManager on /data first.
-    bool can_use_data = false;
-    if (FilesystemHasReliablePinning("/data", &can_use_data) && can_use_data) {
-        return CreateScratchOnData(scratch_device, partition_exists);
-    }
-    // If that fails, see if we can land on super.
-    if (CanUseSuperPartition(fstab)) {
+    bool is_virtual_ab = false;
+    if (CanUseSuperPartition(fstab, &is_virtual_ab)) {
+        bool can_use_data = false;
+        if (is_virtual_ab && FilesystemHasReliablePinning("/data", &can_use_data) && can_use_data) {
+            return CreateScratchOnData(scratch_device, partition_exists);
+        }
         return CreateDynamicScratch(scratch_device, partition_exists);
     }
     return false;
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index 34c7baf..cdff06e 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -332,10 +332,13 @@
     // Helper function for second stage init to restorecon on the rollback indicator.
     static std::string GetGlobalRollbackIndicatorPath();
 
-    // Detach dm-user devices from the current snapuserd, and populate
-    // |snapuserd_argv| with the necessary arguments to restart snapuserd
-    // and reattach them.
-    bool DetachSnapuserdForSelinux(std::vector<std::string>* snapuserd_argv);
+    // Populate |snapuserd_argv| with the necessary arguments to restart snapuserd
+    // after loading selinux policy.
+    bool PrepareSnapuserdArgsForSelinux(std::vector<std::string>* snapuserd_argv);
+
+    // Detach dm-user devices from the first stage snapuserd. Load
+    // new dm-user tables after loading selinux policy.
+    bool DetachFirstStageSnapuserdForSelinux();
 
     // Perform the transition from the selinux stage of snapuserd into the
     // second-stage of snapuserd. This process involves re-creating the dm-user
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 59abd6f..6fed09c 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -1746,13 +1746,6 @@
 
         auto misc_name = user_cow_name;
 
-        DmTable table;
-        table.Emplace<DmTargetUser>(0, target.spec.length, misc_name);
-        if (!dm_.LoadTableAndActivate(user_cow_name, table)) {
-            LOG(ERROR) << "Unable to swap tables for " << misc_name;
-            continue;
-        }
-
         std::string source_device_name;
         if (snapshot_status.old_partition_size() > 0) {
             source_device_name = GetSourceDeviceName(snapshot);
@@ -1780,13 +1773,6 @@
             continue;
         }
 
-        // Wait for ueventd to acknowledge and create the control device node.
-        std::string control_device = "/dev/dm-user/" + misc_name;
-        if (!WaitForDevice(control_device, 10s)) {
-            LOG(ERROR) << "dm-user control device no found:  " << misc_name;
-            continue;
-        }
-
         if (transition == InitTransition::SELINUX_DETACH) {
             if (!UpdateUsesUserSnapshots(lock.get())) {
                 auto message = misc_name + "," + cow_image_device + "," + source_device;
@@ -1804,6 +1790,20 @@
             continue;
         }
 
+        DmTable table;
+        table.Emplace<DmTargetUser>(0, target.spec.length, misc_name);
+        if (!dm_.LoadTableAndActivate(user_cow_name, table)) {
+            LOG(ERROR) << "Unable to swap tables for " << misc_name;
+            continue;
+        }
+
+        // Wait for ueventd to acknowledge and create the control device node.
+        std::string control_device = "/dev/dm-user/" + misc_name;
+        if (!WaitForDevice(control_device, 10s)) {
+            LOG(ERROR) << "dm-user control device no found:  " << misc_name;
+            continue;
+        }
+
         uint64_t base_sectors;
         if (!UpdateUsesUserSnapshots(lock.get())) {
             base_sectors =
@@ -4136,10 +4136,71 @@
     return status.state() != UpdateState::None && status.using_snapuserd();
 }
 
-bool SnapshotManager::DetachSnapuserdForSelinux(std::vector<std::string>* snapuserd_argv) {
+bool SnapshotManager::PrepareSnapuserdArgsForSelinux(std::vector<std::string>* snapuserd_argv) {
     return PerformInitTransition(InitTransition::SELINUX_DETACH, snapuserd_argv);
 }
 
+bool SnapshotManager::DetachFirstStageSnapuserdForSelinux() {
+    LOG(INFO) << "Detaching first stage snapuserd";
+
+    auto lock = LockExclusive();
+    if (!lock) return false;
+
+    std::vector<std::string> snapshots;
+    if (!ListSnapshots(lock.get(), &snapshots)) {
+        LOG(ERROR) << "Failed to list snapshots.";
+        return false;
+    }
+
+    size_t num_cows = 0;
+    size_t ok_cows = 0;
+    for (const auto& snapshot : snapshots) {
+        std::string user_cow_name = GetDmUserCowName(snapshot, GetSnapshotDriver(lock.get()));
+
+        if (dm_.GetState(user_cow_name) == DmDeviceState::INVALID) {
+            continue;
+        }
+
+        DeviceMapper::TargetInfo target;
+        if (!GetSingleTarget(user_cow_name, TableQuery::Table, &target)) {
+            continue;
+        }
+
+        auto target_type = DeviceMapper::GetTargetType(target.spec);
+        if (target_type != "user") {
+            LOG(ERROR) << "Unexpected target type for " << user_cow_name << ": " << target_type;
+            continue;
+        }
+
+        num_cows++;
+        auto misc_name = user_cow_name;
+
+        DmTable table;
+        table.Emplace<DmTargetUser>(0, target.spec.length, misc_name);
+        if (!dm_.LoadTableAndActivate(user_cow_name, table)) {
+            LOG(ERROR) << "Unable to swap tables for " << misc_name;
+            continue;
+        }
+
+        // Wait for ueventd to acknowledge and create the control device node.
+        std::string control_device = "/dev/dm-user/" + misc_name;
+        if (!WaitForDevice(control_device, 10s)) {
+            LOG(ERROR) << "dm-user control device no found:  " << misc_name;
+            continue;
+        }
+
+        ok_cows++;
+        LOG(INFO) << "control device is ready: " << control_device;
+    }
+
+    if (ok_cows != num_cows) {
+        LOG(ERROR) << "Could not transition all snapuserd consumers.";
+        return false;
+    }
+
+    return true;
+}
+
 bool SnapshotManager::PerformSecondStageInitTransition() {
     return PerformInitTransition(InitTransition::SECOND_STAGE);
 }
diff --git a/init/Android.bp b/init/Android.bp
index f0e362c..f6f1e8c 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -308,7 +308,7 @@
     name: "init_first_stage_cc_defaults",
     module_type: "cc_defaults",
     config_namespace: "ANDROID",
-    bool_variables: ["BOARD_BUILD_SYSTEM_ROOT_IMAGE", "BOARD_USES_RECOVERY_AS_BOOT"],
+    bool_variables: ["BOARD_USES_RECOVERY_AS_BOOT"],
     properties: ["installable"],
 }
 
@@ -317,9 +317,6 @@
 init_first_stage_cc_defaults {
     name: "init_first_stage_defaults",
     soong_config_variables: {
-        BOARD_BUILD_SYSTEM_ROOT_IMAGE: {
-            installable: false,
-        },
         BOARD_USES_RECOVERY_AS_BOOT: {
             installable: false,
         },
diff --git a/init/Android.mk b/init/Android.mk
index c08fe03..4b85c15 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -8,11 +8,9 @@
 LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
 LOCAL_LICENSE_CONDITIONS := notice
 LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
-ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
 ifneq ($(BOARD_USES_RECOVERY_AS_BOOT),true)
 LOCAL_REQUIRED_MODULES := \
    init_first_stage \
 
 endif  # BOARD_USES_RECOVERY_AS_BOOT
-endif  # BOARD_BUILD_SYSTEM_ROOT_IMAGE
 include $(BUILD_PHONY_PACKAGE)
diff --git a/init/snapuserd_transition.cpp b/init/snapuserd_transition.cpp
index 5c821b0..6972f30 100644
--- a/init/snapuserd_transition.cpp
+++ b/init/snapuserd_transition.cpp
@@ -226,12 +226,9 @@
 
     argv_.emplace_back("snapuserd");
     argv_.emplace_back("-no_socket");
-    if (!sm_->DetachSnapuserdForSelinux(&argv_)) {
+    if (!sm_->PrepareSnapuserdArgsForSelinux(&argv_)) {
         LOG(FATAL) << "Could not perform selinux transition";
     }
-
-    // Make sure the process is gone so we don't have any selinux audits.
-    KillFirstStageSnapuserd(old_pid_);
 }
 
 void SnapuserdSelinuxHelper::FinishTransition() {
@@ -301,6 +298,12 @@
 }
 
 void SnapuserdSelinuxHelper::RelaunchFirstStageSnapuserd() {
+    if (!sm_->DetachFirstStageSnapuserdForSelinux()) {
+        LOG(FATAL) << "Could not perform selinux transition";
+    }
+
+    KillFirstStageSnapuserd(old_pid_);
+
     auto fd = GetRamdiskSnapuserdFd();
     if (!fd) {
         LOG(FATAL) << "Environment variable " << kSnapuserdFirstStageFdVar << " was not set!";
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index fde30ad..753edf7 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -219,6 +219,11 @@
                 misc_undefined: ["integer"],
             },
         },
+        android_riscv64: {
+            sanitize: {
+                misc_undefined: ["integer"],
+            },
+        },
 
         android_x86: {
             // TODO: This is to work around b/29412086.
diff --git a/libutils/Android.bp b/libutils/Android.bp
index c744b53..26e1597 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -58,10 +58,6 @@
     vendor_available: true,
     product_available: true,
     recovery_available: true,
-    vndk: {
-        enabled: true,
-        support_system_process: true,
-    },
     host_supported: true,
 
     cflags: [
@@ -126,8 +122,8 @@
     },
 }
 
-cc_library {
-    name: "libutils",
+cc_defaults {
+    name: "libutils_impl_defaults",
     defaults: ["libutils_defaults"],
     native_bridge_supported: true,
 
@@ -181,11 +177,39 @@
 }
 
 cc_library {
+    name: "libutils",
+    defaults: ["libutils_impl_defaults"],
+
+    vndk: {
+        enabled: true,
+        support_system_process: true,
+    },
+}
+
+cc_library {
+    name: "libutils_test_compile",
+    defaults: ["libutils_impl_defaults"],
+
+    cflags: [
+        "-DCALLSTACKS=1",
+        "-DDEBUG_POLL_AND_WAKE=1",
+        "-DDEBUG_REFS=1",
+        "-DDEBUG_TOKENIZER=1",
+    ],
+
+    visibility: [":__subpackages__"],
+}
+
+cc_library {
     name: "libutilscallstack",
     defaults: ["libutils_defaults"],
     // TODO(b/153609531): remove when no longer needed.
     native_bridge_supported: true,
     min_sdk_version: "29",
+    vndk: {
+        enabled: true,
+        support_system_process: true,
+    },
 
     srcs: [
         "CallStack.cpp",
diff --git a/libutils/Looper.cpp b/libutils/Looper.cpp
index 1a3f34b..402e43c 100644
--- a/libutils/Looper.cpp
+++ b/libutils/Looper.cpp
@@ -8,10 +8,14 @@
 //#define LOG_NDEBUG 0
 
 // Debugs poll and wake interactions.
+#ifndef DEBUG_POLL_AND_WAKE
 #define DEBUG_POLL_AND_WAKE 0
+#endif
 
 // Debugs callback registration and invocation.
+#ifndef DEBUG_CALLBACKS
 #define DEBUG_CALLBACKS 0
+#endif
 
 #include <utils/Looper.h>
 
diff --git a/libutils/RefBase.cpp b/libutils/RefBase.cpp
index ed5b2a9..ab122c7 100644
--- a/libutils/RefBase.cpp
+++ b/libutils/RefBase.cpp
@@ -21,9 +21,11 @@
 
 #include <android-base/macros.h>
 
+#include <fcntl.h>
 #include <log/log.h>
 
 #include <utils/RefBase.h>
+#include <utils/String8.h>
 
 #include <utils/Mutex.h>
 
@@ -32,7 +34,9 @@
 #endif
 
 // Compile with refcounting debugging enabled.
+#ifndef DEBUG_REFS
 #define DEBUG_REFS 0
+#endif
 
 // The following three are ignored unless DEBUG_REFS is set.
 
@@ -45,7 +49,11 @@
 
 // folder where stack traces are saved when DEBUG_REFS is enabled
 // this folder needs to exist and be writable
+#ifdef __ANDROID__
 #define DEBUG_REFS_CALLSTACK_PATH "/data/debug"
+#else
+#define DEBUG_REFS_CALLSTACK_PATH "."
+#endif
 
 // log all reference counting operations
 #define PRINT_REFS 0
@@ -320,11 +328,11 @@
             char name[100];
             snprintf(name, sizeof(name), DEBUG_REFS_CALLSTACK_PATH "/%p.stack",
                      this);
-            int rc = open(name, O_RDWR | O_CREAT | O_APPEND, 644);
+            int rc = open(name, O_RDWR | O_CREAT | O_APPEND, 0644);
             if (rc >= 0) {
                 (void)write(rc, text.string(), text.length());
                 close(rc);
-                ALOGD("STACK TRACE for %p saved in %s", this, name);
+                ALOGI("STACK TRACE for %p saved in %s", this, name);
             }
             else ALOGE("FAILED TO PRINT STACK TRACE for %p in %s: %s", this,
                       name, strerror(errno));
diff --git a/libutils/Tokenizer.cpp b/libutils/Tokenizer.cpp
index 98dd2fd..c3ec165 100644
--- a/libutils/Tokenizer.cpp
+++ b/libutils/Tokenizer.cpp
@@ -21,9 +21,10 @@
 #include <sys/stat.h>
 #include <utils/Log.h>
 
+#ifndef DEBUG_TOKENIZER
 // Enables debug output for the tokenizer.
 #define DEBUG_TOKENIZER 0
-
+#endif
 
 namespace android {
 
diff --git a/rootdir/etc/public.libraries.wear.txt b/rootdir/etc/public.libraries.wear.txt
index 82196e4..ea1e234 100644
--- a/rootdir/etc/public.libraries.wear.txt
+++ b/rootdir/etc/public.libraries.wear.txt
@@ -10,6 +10,7 @@
 libGLESv1_CM.so
 libGLESv2.so
 libGLESv3.so
+libicu.so
 libicui18n.so
 libicuuc.so
 libjnigraphics.so
diff --git a/trusty/storage/interface/include/trusty/interface/storage.h b/trusty/storage/interface/include/trusty/interface/storage.h
index 255ade1..3291607 100644
--- a/trusty/storage/interface/include/trusty/interface/storage.h
+++ b/trusty/storage/interface/include/trusty/interface/storage.h
@@ -53,6 +53,8 @@
 
 	/* transaction support */
 	STORAGE_END_TRANSACTION = 9 << STORAGE_REQ_SHIFT,
+
+	STORAGE_FILE_GET_MAX_SIZE = 12 << STORAGE_REQ_SHIFT,
 };
 
 /**
@@ -184,6 +186,24 @@
 };
 
 /**
+ * struct storage_file_get_max_size_req - request format for
+ *                                        STORAGE_FILE_GET_MAX_SIZE
+ * @handle: the handle for the file whose max size is requested
+ */
+struct storage_file_get_max_size_req {
+	uint32_t handle;
+};
+
+/**
+ * struct storage_file_get_max_size_resp - response format for
+ *                                         STORAGE_FILE_GET_MAX_SIZE
+ * @max_size:   the maximum size of the file
+ */
+struct storage_file_get_max_size_resp {
+	uint64_t max_size;
+};
+
+/**
  * struct storage_file_read_req - request format for STORAGE_FILE_READ
  * @handle: the handle for the file from which to read
  * @size:   the quantity of bytes to read from the file