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
Change-Id: I219465b8b81decb960e2c5f46bab6e0768b31317
This commit is contained in:
Jiyong Park 2019-05-10 21:12:15 +09:00
parent 0e68ab18fb
commit f93088ba2b
2 changed files with 43 additions and 1 deletions

View file

@ -79,6 +79,38 @@ static bool IsApexUpdatable() {
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 @@ bool SetupMountNamespaces() {
default_ns_id = GetMountNamespaceId();
}
success &= ActivateFlattenedApexesIfPossible();
LOG(INFO) << "SetupMountNamespaces done";
return success;
}

View file

@ -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 @@ void Service::Reap(const siginfo_t& siginfo) {
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) {