Merge "libutils: sharedbuffer test - expect greatness!"
diff --git a/fs_mgr/libsnapshot/android/snapshot/snapshot.proto b/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
index 012f2ae..92aa55c 100644
--- a/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
+++ b/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
@@ -186,7 +186,7 @@
     MergeFailureCode merge_failure_code = 7;
 }
 
-// Next: 9
+// Next: 10
 message SnapshotMergeReport {
     // Status of the update after the merge attempts.
     UpdateState state = 1;
@@ -212,4 +212,7 @@
 
     // Time from sys.boot_completed to merge start, in milliseconds.
     uint32 boot_complete_to_merge_start_time_ms = 8;
+
+    // Merge failure code, filled if state == MergeFailed.
+    MergeFailureCode merge_failure_code = 9;
 }
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot.h
index 1cb966b..94d5055 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot.h
@@ -27,6 +27,7 @@
     MOCK_METHOD(bool, CancelUpdate, (), (override));
     MOCK_METHOD(bool, FinishedSnapshotWrites, (bool wipe), (override));
     MOCK_METHOD(void, UpdateCowStats, (ISnapshotMergeStats * stats), (override));
+    MOCK_METHOD(MergeFailureCode, ReadMergeFailureCode, (), (override));
     MOCK_METHOD(bool, InitiateMerge, (), (override));
 
     MOCK_METHOD(UpdateState, ProcessUpdateState,
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_merge_stats.h b/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_merge_stats.h
index ac2c787..067f99c 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_merge_stats.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot_merge_stats.h
@@ -34,11 +34,13 @@
     MOCK_METHOD(void, set_estimated_cow_size_bytes, (uint64_t), (override));
     MOCK_METHOD(void, set_boot_complete_time_ms, (uint32_t), (override));
     MOCK_METHOD(void, set_boot_complete_to_merge_start_time_ms, (uint32_t), (override));
+    MOCK_METHOD(void, set_merge_failure_code, (MergeFailureCode), (override));
     MOCK_METHOD(uint64_t, cow_file_size, (), (override));
     MOCK_METHOD(uint64_t, total_cow_size_bytes, (), (override));
     MOCK_METHOD(uint64_t, estimated_cow_size_bytes, (), (override));
     MOCK_METHOD(uint32_t, boot_complete_time_ms, (), (override));
     MOCK_METHOD(uint32_t, boot_complete_to_merge_start_time_ms, (), (override));
+    MOCK_METHOD(MergeFailureCode, merge_failure_code, (), (override));
     MOCK_METHOD(std::unique_ptr<Result>, Finish, (), (override));
 
     using ISnapshotMergeStats::Result;
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index 81cb640..195b6f2 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -167,6 +167,10 @@
     virtual UpdateState ProcessUpdateState(const std::function<bool()>& callback = {},
                                            const std::function<bool()>& before_cancel = {}) = 0;
 
+    // If ProcessUpdateState() returned MergeFailed, this returns the appropriate
+    // code. Otherwise, MergeFailureCode::Ok is returned.
+    virtual MergeFailureCode ReadMergeFailureCode() = 0;
+
     // Find the status of the current update, if any.
     //
     // |progress| depends on the returned status:
@@ -332,6 +336,7 @@
     bool CancelUpdate() override;
     bool FinishedSnapshotWrites(bool wipe) override;
     void UpdateCowStats(ISnapshotMergeStats* stats) override;
+    MergeFailureCode ReadMergeFailureCode() override;
     bool InitiateMerge() override;
     UpdateState ProcessUpdateState(const std::function<bool()>& callback = {},
                                    const std::function<bool()>& before_cancel = {}) override;
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stats.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stats.h
index e617d7a..4ce5077 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stats.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stats.h
@@ -34,11 +34,13 @@
     virtual void set_estimated_cow_size_bytes(uint64_t bytes) = 0;
     virtual void set_boot_complete_time_ms(uint32_t ms) = 0;
     virtual void set_boot_complete_to_merge_start_time_ms(uint32_t ms) = 0;
+    virtual void set_merge_failure_code(MergeFailureCode code) = 0;
     virtual uint64_t cow_file_size() = 0;
     virtual uint64_t total_cow_size_bytes() = 0;
     virtual uint64_t estimated_cow_size_bytes() = 0;
     virtual uint32_t boot_complete_time_ms() = 0;
     virtual uint32_t boot_complete_to_merge_start_time_ms() = 0;
+    virtual MergeFailureCode merge_failure_code() = 0;
 
     // Called when merge ends. Properly clean up permanent storage.
     class Result {
@@ -70,6 +72,8 @@
     uint32_t boot_complete_time_ms() override;
     void set_boot_complete_to_merge_start_time_ms(uint32_t ms) override;
     uint32_t boot_complete_to_merge_start_time_ms() override;
+    void set_merge_failure_code(MergeFailureCode code) override;
+    MergeFailureCode merge_failure_code() override;
     std::unique_ptr<Result> Finish() override;
 
   private:
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h
index cc75db8..a7cd939 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h
@@ -29,6 +29,7 @@
     bool CancelUpdate() override;
     bool FinishedSnapshotWrites(bool wipe) override;
     void UpdateCowStats(ISnapshotMergeStats* stats) override;
+    MergeFailureCode ReadMergeFailureCode() override;
     bool InitiateMerge() override;
     UpdateState ProcessUpdateState(const std::function<bool()>& callback = {},
                                    const std::function<bool()>& before_cancel = {}) override;
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 64a434c..567eb26 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -3690,5 +3690,16 @@
     return false;
 }
 
+MergeFailureCode SnapshotManager::ReadMergeFailureCode() {
+    auto lock = LockExclusive();
+    if (!lock) return MergeFailureCode::AcquireLock;
+
+    SnapshotUpdateStatus status = ReadSnapshotUpdateStatus(lock.get());
+    if (status.state() != UpdateState::MergeFailed) {
+        return MergeFailureCode::Ok;
+    }
+    return status.merge_failure_code();
+}
+
 }  // namespace snapshot
 }  // namespace android
diff --git a/fs_mgr/libsnapshot/snapshot_stats.cpp b/fs_mgr/libsnapshot/snapshot_stats.cpp
index 7fcfcea..4a93d65 100644
--- a/fs_mgr/libsnapshot/snapshot_stats.cpp
+++ b/fs_mgr/libsnapshot/snapshot_stats.cpp
@@ -130,6 +130,14 @@
     return report_.boot_complete_to_merge_start_time_ms();
 }
 
+void SnapshotMergeStats::set_merge_failure_code(MergeFailureCode code) {
+    report_.set_merge_failure_code(code);
+}
+
+MergeFailureCode SnapshotMergeStats::merge_failure_code() {
+    return report_.merge_failure_code();
+}
+
 class SnapshotMergeStatsResultImpl : public SnapshotMergeStats::Result {
   public:
     SnapshotMergeStatsResultImpl(const SnapshotMergeReport& report,
diff --git a/fs_mgr/libsnapshot/snapshot_stub.cpp b/fs_mgr/libsnapshot/snapshot_stub.cpp
index 43825cc..1a9eda5 100644
--- a/fs_mgr/libsnapshot/snapshot_stub.cpp
+++ b/fs_mgr/libsnapshot/snapshot_stub.cpp
@@ -135,6 +135,8 @@
     uint32_t boot_complete_time_ms() override { return 0; }
     void set_boot_complete_to_merge_start_time_ms(uint32_t) override {}
     uint32_t boot_complete_to_merge_start_time_ms() override { return 0; }
+    void set_merge_failure_code(MergeFailureCode) override {}
+    MergeFailureCode merge_failure_code() { return MergeFailureCode::Ok; }
 };
 
 ISnapshotMergeStats* SnapshotManagerStub::GetSnapshotMergeStatsInstance() {
@@ -163,4 +165,9 @@
     LOG(ERROR) << __FUNCTION__ << " should never be called.";
 }
 
+auto SnapshotManagerStub::ReadMergeFailureCode() -> MergeFailureCode {
+    LOG(ERROR) << __FUNCTION__ << " should never be called.";
+    return MergeFailureCode::Ok;
+}
+
 }  // namespace android::snapshot
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index 5cde167..84cda98 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -327,28 +327,22 @@
         LOG(INFO) << "Copied ramdisk prop to " << dest;
     }
 
-    if (ForceNormalBoot(cmdline, bootconfig)) {
-        mkdir("/first_stage_ramdisk", 0755);
-        // SwitchRoot() must be called with a mount point as the target, so we bind mount the
-        // target directory to itself here.
-        if (mount("/first_stage_ramdisk", "/first_stage_ramdisk", nullptr, MS_BIND, nullptr) != 0) {
-            LOG(FATAL) << "Could not bind mount /first_stage_ramdisk to itself";
-        }
-        SwitchRoot("/first_stage_ramdisk");
-    }
-
-    std::string force_debuggable("/force_debuggable");
+    // If "/force_debuggable" is present, the second-stage init will use a userdebug
+    // sepolicy and load adb_debug.prop to allow adb root, if the device is unlocked.
+    bool found_debuggable = false;
     std::string adb_debug_prop("/adb_debug.prop");
     std::string userdebug_sepolicy("/userdebug_plat_sepolicy.cil");
-    if (IsRecoveryMode()) {
-        // Update these file paths since we didn't switch root
-        force_debuggable.insert(0, "/first_stage_ramdisk");
+    if (access("/force_debuggable", F_OK) == 0) {
+        found_debuggable = true;
+    } else if (access("/first_stage_ramdisk/force_debuggable", F_OK) == 0) {
+        // Fallback to legacy debug resource paths.
+        // TODO(b/186485355): removes the fallback path once it is not needed.
+        found_debuggable = true;
         adb_debug_prop.insert(0, "/first_stage_ramdisk");
         userdebug_sepolicy.insert(0, "/first_stage_ramdisk");
     }
-    // If this file is present, the second-stage init will use a userdebug sepolicy
-    // and load adb_debug.prop to allow adb root, if the device is unlocked.
-    if (access(force_debuggable.c_str(), F_OK) == 0) {
+
+    if (found_debuggable) {
         std::error_code ec;  // to invoke the overloaded copy_file() that won't throw.
         if (!fs::copy_file(adb_debug_prop, kDebugRamdiskProp, ec) ||
             !fs::copy_file(userdebug_sepolicy, kDebugRamdiskSEPolicy, ec)) {
@@ -359,6 +353,16 @@
         }
     }
 
+    if (ForceNormalBoot(cmdline, bootconfig)) {
+        mkdir("/first_stage_ramdisk", 0755);
+        // SwitchRoot() must be called with a mount point as the target, so we bind mount the
+        // target directory to itself here.
+        if (mount("/first_stage_ramdisk", "/first_stage_ramdisk", nullptr, MS_BIND, nullptr) != 0) {
+            LOG(FATAL) << "Could not bind mount /first_stage_ramdisk to itself";
+        }
+        SwitchRoot("/first_stage_ramdisk");
+    }
+
     if (!DoFirstStageMount(!created_devices)) {
         LOG(FATAL) << "Failed to mount required partitions early ...";
     }
diff --git a/libcutils/include/private/android_filesystem_config.h b/libcutils/include/private/android_filesystem_config.h
index 7489281..43f4d35 100644
--- a/libcutils/include/private/android_filesystem_config.h
+++ b/libcutils/include/private/android_filesystem_config.h
@@ -128,6 +128,7 @@
 #define AID_EXT_OBB_RW 1079       /* GID for OBB directories on external storage */
 #define AID_CONTEXT_HUB 1080      /* GID for access to the Context Hub */
 #define AID_VIRTMANAGER 1081      /* VirtManager daemon */
+#define AID_ARTD 1082             /* ART Service daemon */
 /* Changes to this file must be made in AOSP, *not* in internal branches. */
 
 #define AID_SHELL 2000 /* adb and debug shell user */