Don't use apexd when TARGET_FLATTEN_APEX == true

When TARGET_FLATTEN_APEX is true (= ro.apex.updatable is unset or set to
false), apexd is not used to activate the built-in flattened APEXes.
Init simply bind-mounts /system/apex to /apex.

However, there is a special case here. The runtime APEX is installed as
either /system/apex/com.android.runtime.debug or
/system/apex/com.android.runtime.release, whereas it should be activated
on /apex/com.android.runtime - without the .debug or .release suffix.
To handle that case, the build system creates an empty directory
/system/apex/com.android.runtime and the .debug or .release directory
is bind-mounted to the empty directory by init at runtime.

This change also fixes a minor bug that native watchdog is triggered
for all post-apexd processes regardless of whether ro.apex.updatable
is true or not. Since apexd is expected to shutdown itself when ro.apex
.updatable is false, we don't trigger the watchdog in that case.

Bug: 132413565
Bug: 133305381
Test: marlin and sdk_gphone are bootable
Merged-In: I219465b8b81decb960e2c5f46bab6e0768b31317
Change-Id: I219465b8b81decb960e2c5f46bab6e0768b31317
(cherry picked from commit f93088ba2bcc77ebbc01924721467455db7a0496)
diff --git a/init/mount_namespace.cpp b/init/mount_namespace.cpp
index 5305dc7..12144c1 100644
--- a/init/mount_namespace.cpp
+++ b/init/mount_namespace.cpp
@@ -79,6 +79,38 @@
     return updatable;
 }
 
+static bool ActivateFlattenedApexesIfPossible() {
+    if (IsRecoveryMode() || IsApexUpdatable()) {
+        return true;
+    }
+
+    constexpr const char kSystemApex[] = "/system/apex";
+    constexpr const char kApexTop[] = "/apex";
+    if (mount(kSystemApex, kApexTop, nullptr, MS_BIND, nullptr) != 0) {
+        PLOG(ERROR) << "Could not bind mount " << kSystemApex << " to " << kApexTop;
+        return false;
+    }
+
+    // Special casing for the runtime APEX
+    constexpr const char kRuntimeApexMountPath[] = "/system/apex/com.android.runtime";
+    static const std::vector<std::string> kRuntimeApexDirNames = {"com.android.runtime.release",
+                                                                  "com.android.runtime.debug"};
+    bool success = false;
+    for (const auto& name : kRuntimeApexDirNames) {
+        std::string path = std::string(kSystemApex) + "/" + name;
+        if (access(path.c_str(), F_OK) == 0) {
+            if (mount(path.c_str(), kRuntimeApexMountPath, nullptr, MS_BIND, nullptr) == 0) {
+                success = true;
+                break;
+            }
+        }
+    }
+    if (!success) {
+        PLOG(ERROR) << "Failed to bind mount the runtime APEX to " << kRuntimeApexMountPath;
+    }
+    return success;
+}
+
 static android::base::unique_fd bootstrap_ns_fd;
 static android::base::unique_fd default_ns_fd;
 
@@ -129,6 +161,8 @@
         default_ns_id = GetMountNamespaceId();
     }
 
+    success &= ActivateFlattenedApexesIfPossible();
+
     LOG(INFO) << "SetupMountNamespaces done";
     return success;
 }
diff --git a/init/service.cpp b/init/service.cpp
index 6887d7b..3e865a7 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -46,6 +46,7 @@
 #include "util.h"
 
 #if defined(__ANDROID__)
+#include <ApexProperties.sysprop.h>
 #include <android/api-level.h>
 #include <sys/system_properties.h>
 
@@ -372,10 +373,17 @@
         return;
     }
 
+#if defined(__ANDROID__)
+    static bool is_apex_updatable = android::sysprop::ApexProperties::updatable().value_or(false);
+#else
+    static bool is_apex_updatable = false;
+#endif
+    const bool is_process_updatable = !pre_apexd_ && is_apex_updatable;
+
     // If we crash > 4 times in 4 minutes or before boot_completed,
     // reboot into bootloader or set crashing property
     boot_clock::time_point now = boot_clock::now();
-    if (((flags_ & SVC_CRITICAL) || !pre_apexd_) && !(flags_ & SVC_RESTART)) {
+    if (((flags_ & SVC_CRITICAL) || is_process_updatable) && !(flags_ & SVC_RESTART)) {
         bool boot_completed = android::base::GetBoolProperty("sys.boot_completed", false);
         if (now < time_crashed_ + 4min || !boot_completed) {
             if (++crash_count_ > 4) {