Merge changes from topic "revert_move_bionic_to_apex"
* changes: Revert "Identify post-apexd crashing processes" Revert "Bionic libs and the dynamic linker are bind mounted" Revert "Don't create separate mount namespaces for pre-apexd processes"
This commit is contained in:
commit
e0c7a8bbdd
4 changed files with 6 additions and 212 deletions
|
|
@ -1098,86 +1098,6 @@ static Result<Success> do_parse_apex_configs(const BuiltinArguments& args) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Result<Success> bind_mount_file(const char* source, const char* mount_point,
|
|
||||||
bool remount_private) {
|
|
||||||
if (remount_private && mount(nullptr, mount_point, nullptr, MS_PRIVATE, nullptr) == -1) {
|
|
||||||
return ErrnoError() << "Could not change " << mount_point << " to a private mount point";
|
|
||||||
}
|
|
||||||
if (mount(source, mount_point, nullptr, MS_BIND, nullptr) == -1) {
|
|
||||||
return ErrnoError() << "Could not bind-mount " << source << " to " << mount_point;
|
|
||||||
}
|
|
||||||
return Success();
|
|
||||||
}
|
|
||||||
|
|
||||||
static Result<Success> bind_mount_bionic(const char* linker_source, const char* lib_dir_source,
|
|
||||||
const char* linker_mount_point, const char* lib_mount_dir,
|
|
||||||
bool remount_private) {
|
|
||||||
if (access(linker_source, F_OK) != 0) {
|
|
||||||
return Success();
|
|
||||||
}
|
|
||||||
if (auto result = bind_mount_file(linker_source, linker_mount_point, remount_private);
|
|
||||||
!result) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
for (auto libname : kBionicLibFileNames) {
|
|
||||||
std::string mount_point = lib_mount_dir + libname;
|
|
||||||
std::string source = lib_dir_source + libname;
|
|
||||||
if (auto result = bind_mount_file(source.c_str(), mount_point.c_str(), remount_private);
|
|
||||||
!result) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Success();
|
|
||||||
}
|
|
||||||
|
|
||||||
// The bootstrap bionic libs and the bootstrap linker are bind-mounted to
|
|
||||||
// the mount points for pre-apexd processes.
|
|
||||||
static Result<Success> do_prepare_bootstrap_bionic(const BuiltinArguments& args) {
|
|
||||||
static bool prepare_bootstrap_bionic_done = false;
|
|
||||||
if (prepare_bootstrap_bionic_done) {
|
|
||||||
return Error() << "prepare_bootstrap_bionic was already executed. Cannot be executed again";
|
|
||||||
}
|
|
||||||
if (auto result = bind_mount_bionic(kBootstrapLinkerPath, kBootstrapBionicLibsDir,
|
|
||||||
kLinkerMountPoint, kBionicLibsMountPointDir, false);
|
|
||||||
!result) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
if (auto result = bind_mount_bionic(kBootstrapLinkerPath64, kBootstrapBionicLibsDir64,
|
|
||||||
kLinkerMountPoint64, kBionicLibsMountPointDir64, false);
|
|
||||||
!result) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(INFO) << "prepare_bootstrap_bionic done";
|
|
||||||
prepare_bootstrap_bionic_done = true;
|
|
||||||
return Success();
|
|
||||||
}
|
|
||||||
|
|
||||||
// The bionic libs and the dynamic linker from the runtime APEX are bind-mounted
|
|
||||||
// to the mount points. As a result, the previous mounts done by
|
|
||||||
// prepare_bootstrap_bionic become hidden.
|
|
||||||
static Result<Success> do_setup_runtime_bionic(const BuiltinArguments& args) {
|
|
||||||
static bool setup_runtime_bionic_done = false;
|
|
||||||
if (setup_runtime_bionic_done) {
|
|
||||||
return Error() << "setup_runtime_bionic was already executed. Cannot be executed again";
|
|
||||||
}
|
|
||||||
if (auto result = bind_mount_bionic(kRuntimeLinkerPath, kRuntimeBionicLibsDir,
|
|
||||||
kLinkerMountPoint, kBionicLibsMountPointDir, true);
|
|
||||||
!result) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
if (auto result = bind_mount_bionic(kRuntimeLinkerPath64, kRuntimeBionicLibsDir64,
|
|
||||||
kLinkerMountPoint64, kBionicLibsMountPointDir64, true);
|
|
||||||
!result) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ServiceList::GetInstance().MarkRuntimeAvailable();
|
|
||||||
LOG(INFO) << "setup_runtime_bionic done";
|
|
||||||
setup_runtime_bionic_done = true;
|
|
||||||
return Success();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Builtin-function-map start
|
// Builtin-function-map start
|
||||||
const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
|
const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
|
||||||
constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
|
constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
|
||||||
|
|
@ -1216,7 +1136,6 @@ const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
|
||||||
{"mount_all", {1, kMax, {false, do_mount_all}}},
|
{"mount_all", {1, kMax, {false, do_mount_all}}},
|
||||||
{"mount", {3, kMax, {false, do_mount}}},
|
{"mount", {3, kMax, {false, do_mount}}},
|
||||||
{"parse_apex_configs", {0, 0, {false, do_parse_apex_configs}}},
|
{"parse_apex_configs", {0, 0, {false, do_parse_apex_configs}}},
|
||||||
{"prepare_bootstrap_bionic",{0, 0, {false, do_prepare_bootstrap_bionic}}},
|
|
||||||
{"umount", {1, 1, {false, do_umount}}},
|
{"umount", {1, 1, {false, do_umount}}},
|
||||||
{"readahead", {1, 2, {true, do_readahead}}},
|
{"readahead", {1, 2, {true, do_readahead}}},
|
||||||
{"restart", {1, 1, {false, do_restart}}},
|
{"restart", {1, 1, {false, do_restart}}},
|
||||||
|
|
@ -1225,7 +1144,6 @@ const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
|
||||||
{"rm", {1, 1, {true, do_rm}}},
|
{"rm", {1, 1, {true, do_rm}}},
|
||||||
{"rmdir", {1, 1, {true, do_rmdir}}},
|
{"rmdir", {1, 1, {true, do_rmdir}}},
|
||||||
{"setprop", {2, 2, {true, do_setprop}}},
|
{"setprop", {2, 2, {true, do_setprop}}},
|
||||||
{"setup_runtime_bionic", {0, 0, {false, do_setup_runtime_bionic}}},
|
|
||||||
{"setrlimit", {3, 3, {false, do_setrlimit}}},
|
{"setrlimit", {3, 3, {false, do_setrlimit}}},
|
||||||
{"start", {1, 1, {false, do_start}}},
|
{"start", {1, 1, {false, do_start}}},
|
||||||
{"stop", {1, 1, {false, do_stop}}},
|
{"stop", {1, 1, {false, do_stop}}},
|
||||||
|
|
|
||||||
|
|
@ -140,43 +140,6 @@ Result<Success> Service::SetUpMountNamespace() const {
|
||||||
return Success();
|
return Success();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<Success> Service::SetUpPreApexdMounts() const {
|
|
||||||
// If a pre-apexd service is 're' launched after the runtime APEX is
|
|
||||||
// available, unmount the linker and bionic libs which are currently
|
|
||||||
// bind mounted to the files in the runtime APEX. This will reveal
|
|
||||||
// the hidden mount points (targetting the bootstrap ones in the
|
|
||||||
// system partition) which were setup before the runtime APEX was
|
|
||||||
// started. Note that these unmounts are done in a separate mount namespace
|
|
||||||
// for the process. It does not affect other processes including the init.
|
|
||||||
if (pre_apexd_ && ServiceList::GetInstance().IsRuntimeAvailable()) {
|
|
||||||
if (access(kLinkerMountPoint, F_OK) == 0) {
|
|
||||||
if (umount(kLinkerMountPoint) == -1) {
|
|
||||||
return ErrnoError() << "Could not umount " << kLinkerMountPoint;
|
|
||||||
}
|
|
||||||
for (const auto& libname : kBionicLibFileNames) {
|
|
||||||
std::string mount_point = kBionicLibsMountPointDir + libname;
|
|
||||||
if (umount(mount_point.c_str()) == -1) {
|
|
||||||
return ErrnoError() << "Could not umount " << mount_point;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (access(kLinkerMountPoint64, F_OK) == 0) {
|
|
||||||
if (umount(kLinkerMountPoint64) == -1) {
|
|
||||||
return ErrnoError() << "Could not umount " << kLinkerMountPoint64;
|
|
||||||
}
|
|
||||||
for (const auto& libname : kBionicLibFileNames) {
|
|
||||||
std::string mount_point = kBionicLibsMountPointDir64 + libname;
|
|
||||||
std::string source = kBootstrapBionicLibsDir64 + libname;
|
|
||||||
if (umount(mount_point.c_str()) == -1) {
|
|
||||||
return ErrnoError() << "Could not umount " << mount_point;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Success();
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<Success> Service::SetUpPidNamespace() const {
|
Result<Success> Service::SetUpPidNamespace() const {
|
||||||
if (prctl(PR_SET_NAME, name_.c_str()) == -1) {
|
if (prctl(PR_SET_NAME, name_.c_str()) == -1) {
|
||||||
return ErrnoError() << "Could not set name";
|
return ErrnoError() << "Could not set name";
|
||||||
|
|
@ -406,7 +369,7 @@ void Service::Reap(const siginfo_t& siginfo) {
|
||||||
|
|
||||||
// If we crash > 4 times in 4 minutes, reboot into bootloader or set crashing property
|
// If we crash > 4 times in 4 minutes, reboot into bootloader or set crashing property
|
||||||
boot_clock::time_point now = boot_clock::now();
|
boot_clock::time_point now = boot_clock::now();
|
||||||
if (((flags_ & SVC_CRITICAL) || !pre_apexd_) && !(flags_ & SVC_RESTART)) {
|
if (((flags_ & SVC_CRITICAL) || classnames_.count("updatable")) && !(flags_ & SVC_RESTART)) {
|
||||||
if (now < time_crashed_ + 4min) {
|
if (now < time_crashed_ + 4min) {
|
||||||
if (++crash_count_ > 4) {
|
if (++crash_count_ > 4) {
|
||||||
if (flags_ & SVC_CRITICAL) {
|
if (flags_ & SVC_CRITICAL) {
|
||||||
|
|
@ -966,14 +929,6 @@ Result<Success> Service::Start() {
|
||||||
scon = *result;
|
scon = *result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ServiceList::GetInstance().IsRuntimeAvailable() && !pre_apexd_) {
|
|
||||||
// If this service is started before the runtime APEX gets available,
|
|
||||||
// mark it as pre-apexd one. Note that this marking is permanent. So
|
|
||||||
// for example, if the service is re-launched (e.g., due to crash),
|
|
||||||
// it is still recognized as pre-apexd... for consistency.
|
|
||||||
pre_apexd_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(INFO) << "starting service '" << name_ << "'...";
|
LOG(INFO) << "starting service '" << name_ << "'...";
|
||||||
|
|
||||||
pid_t pid = -1;
|
pid_t pid = -1;
|
||||||
|
|
@ -990,37 +945,6 @@ Result<Success> Service::Start() {
|
||||||
LOG(FATAL) << "Service '" << name_ << "' could not enter namespaces: " << result.error();
|
LOG(FATAL) << "Service '" << name_ << "' could not enter namespaces: " << result.error();
|
||||||
}
|
}
|
||||||
|
|
||||||
// b/122559956: mount namespace is not cloned for the devices that don't support
|
|
||||||
// the update of bionic libraries via APEX. In that case, because the bionic
|
|
||||||
// libraries in the runtime APEX and the bootstrap bionic libraries are
|
|
||||||
// identical, it doesn't matter which libs are used. This is also to avoid the
|
|
||||||
// bug in sdcardfs which is triggered when we have multiple mount namespaces
|
|
||||||
// across vold and the others. BIONIC_UPDATABLE shall be true only for the
|
|
||||||
// devices where kernel has the fix for the sdcardfs bug (see the commit message
|
|
||||||
// for the fix).
|
|
||||||
static bool bionic_updatable =
|
|
||||||
android::base::GetBoolProperty("ro.apex.bionic_updatable", false);
|
|
||||||
|
|
||||||
if (bionic_updatable && pre_apexd_) {
|
|
||||||
// pre-apexd process gets a private copy of the mount namespace.
|
|
||||||
// However, this does not mean that mount/unmount events are not
|
|
||||||
// shared across pre-apexd processes and post-apexd processes.
|
|
||||||
// *Most* of the events are still shared because the propagation
|
|
||||||
// type of / is set to 'shared'. (see `mount rootfs rootfs /shared
|
|
||||||
// rec` in init.rc)
|
|
||||||
//
|
|
||||||
// This unsharing is required to not propagate the mount events
|
|
||||||
// under /system/lib/{libc|libdl|libm}.so and /system/bin/linker(64)
|
|
||||||
// whose propagation type is set to private. With this,
|
|
||||||
// bind-mounting the bionic libs and the dynamic linker from the
|
|
||||||
// runtime APEX to the mount points does not affect pre-apexd
|
|
||||||
// processes which should use the bootstrap ones.
|
|
||||||
if (unshare(CLONE_NEWNS) != 0) {
|
|
||||||
LOG(FATAL) << "Creating a new mount namespace for service"
|
|
||||||
<< " '" << name_ << "' failed: " << strerror(errno);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (namespace_flags_ & CLONE_NEWNS) {
|
if (namespace_flags_ & CLONE_NEWNS) {
|
||||||
if (auto result = SetUpMountNamespace(); !result) {
|
if (auto result = SetUpMountNamespace(); !result) {
|
||||||
LOG(FATAL) << "Service '" << name_
|
LOG(FATAL) << "Service '" << name_
|
||||||
|
|
@ -1028,14 +952,6 @@ Result<Success> Service::Start() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// b/122559956: same as above
|
|
||||||
if (bionic_updatable && pre_apexd_ && ServiceList::GetInstance().IsRuntimeAvailable()) {
|
|
||||||
if (auto result = SetUpPreApexdMounts(); !result) {
|
|
||||||
LOG(FATAL) << "Pre-apexd service '" << name_
|
|
||||||
<< "' could not setup the mount points: " << result.error();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (namespace_flags_ & CLONE_NEWPID) {
|
if (namespace_flags_ & CLONE_NEWPID) {
|
||||||
// This will fork again to run an init process inside the PID
|
// This will fork again to run an init process inside the PID
|
||||||
// namespace.
|
// namespace.
|
||||||
|
|
@ -1408,10 +1324,6 @@ void ServiceList::MarkServicesUpdate() {
|
||||||
delayed_service_names_.clear();
|
delayed_service_names_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServiceList::MarkRuntimeAvailable() {
|
|
||||||
runtime_available_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ServiceList::DelayService(const Service& service) {
|
void ServiceList::DelayService(const Service& service) {
|
||||||
if (services_update_finished_) {
|
if (services_update_finished_) {
|
||||||
LOG(ERROR) << "Cannot delay the start of service '" << service.name()
|
LOG(ERROR) << "Cannot delay the start of service '" << service.name()
|
||||||
|
|
|
||||||
|
|
@ -62,24 +62,6 @@
|
||||||
namespace android {
|
namespace android {
|
||||||
namespace init {
|
namespace init {
|
||||||
|
|
||||||
static constexpr const char* kLinkerMountPoint = "/system/bin/linker";
|
|
||||||
static constexpr const char* kBootstrapLinkerPath = "/system/bin/linker";
|
|
||||||
static constexpr const char* kRuntimeLinkerPath = "/apex/com.android.runtime/bin/linker";
|
|
||||||
|
|
||||||
static constexpr const char* kBionicLibsMountPointDir = "/system/lib/";
|
|
||||||
static constexpr const char* kBootstrapBionicLibsDir = "/system/lib/";
|
|
||||||
static constexpr const char* kRuntimeBionicLibsDir = "/apex/com.android.runtime/lib/bionic/";
|
|
||||||
|
|
||||||
static constexpr const char* kLinkerMountPoint64 = "/system/bin/linker64";
|
|
||||||
static constexpr const char* kBootstrapLinkerPath64 = "/system/bin/linker64";
|
|
||||||
static constexpr const char* kRuntimeLinkerPath64 = "/apex/com.android.runtime/bin/linker64";
|
|
||||||
|
|
||||||
static constexpr const char* kBionicLibsMountPointDir64 = "/system/lib64/";
|
|
||||||
static constexpr const char* kBootstrapBionicLibsDir64 = "/system/lib64/";
|
|
||||||
static constexpr const char* kRuntimeBionicLibsDir64 = "/apex/com.android.runtime/lib64/bionic/";
|
|
||||||
|
|
||||||
static const std::vector<std::string> kBionicLibFileNames = {"libc.so", "libm.so", "libdl.so"};
|
|
||||||
|
|
||||||
class Service {
|
class Service {
|
||||||
public:
|
public:
|
||||||
Service(const std::string& name, Subcontext* subcontext_for_restart_commands,
|
Service(const std::string& name, Subcontext* subcontext_for_restart_commands,
|
||||||
|
|
@ -142,7 +124,6 @@ class Service {
|
||||||
std::optional<std::chrono::seconds> timeout_period() const { return timeout_period_; }
|
std::optional<std::chrono::seconds> timeout_period() const { return timeout_period_; }
|
||||||
const std::vector<std::string>& args() const { return args_; }
|
const std::vector<std::string>& args() const { return args_; }
|
||||||
bool is_updatable() const { return updatable_; }
|
bool is_updatable() const { return updatable_; }
|
||||||
bool is_pre_apexd() const { return pre_apexd_; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using OptionParser = Result<Success> (Service::*)(std::vector<std::string>&& args);
|
using OptionParser = Result<Success> (Service::*)(std::vector<std::string>&& args);
|
||||||
|
|
@ -151,7 +132,6 @@ class Service {
|
||||||
Result<Success> SetUpMountNamespace() const;
|
Result<Success> SetUpMountNamespace() const;
|
||||||
Result<Success> SetUpPidNamespace() const;
|
Result<Success> SetUpPidNamespace() const;
|
||||||
Result<Success> EnterNamespaces() const;
|
Result<Success> EnterNamespaces() const;
|
||||||
Result<Success> SetUpPreApexdMounts() const;
|
|
||||||
void NotifyStateChange(const std::string& new_state) const;
|
void NotifyStateChange(const std::string& new_state) const;
|
||||||
void StopOrReset(int how);
|
void StopOrReset(int how);
|
||||||
void ZapStdio() const;
|
void ZapStdio() const;
|
||||||
|
|
@ -262,8 +242,6 @@ class Service {
|
||||||
std::vector<std::string> args_;
|
std::vector<std::string> args_;
|
||||||
|
|
||||||
std::vector<std::function<void(const siginfo_t& siginfo)>> reap_callbacks_;
|
std::vector<std::function<void(const siginfo_t& siginfo)>> reap_callbacks_;
|
||||||
|
|
||||||
bool pre_apexd_ = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class ServiceList {
|
class ServiceList {
|
||||||
|
|
@ -306,16 +284,13 @@ class ServiceList {
|
||||||
const std::vector<Service*> services_in_shutdown_order() const;
|
const std::vector<Service*> services_in_shutdown_order() const;
|
||||||
|
|
||||||
void MarkServicesUpdate();
|
void MarkServicesUpdate();
|
||||||
void MarkRuntimeAvailable();
|
|
||||||
bool IsServicesUpdated() const { return services_update_finished_; }
|
bool IsServicesUpdated() const { return services_update_finished_; }
|
||||||
bool IsRuntimeAvailable() const { return runtime_available_; }
|
|
||||||
void DelayService(const Service& service);
|
void DelayService(const Service& service);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::unique_ptr<Service>> services_;
|
std::vector<std::unique_ptr<Service>> services_;
|
||||||
|
|
||||||
bool services_update_finished_ = false;
|
bool services_update_finished_ = false;
|
||||||
bool runtime_available_ = false;
|
|
||||||
std::vector<std::string> delayed_service_names_;
|
std::vector<std::string> delayed_service_names_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,6 @@ import /init.usb.configfs.rc
|
||||||
import /init.${ro.zygote}.rc
|
import /init.${ro.zygote}.rc
|
||||||
|
|
||||||
on early-init
|
on early-init
|
||||||
# Mount shared so changes propagate into child namespaces
|
|
||||||
# Do this before other processes are started from init. Otherwise,
|
|
||||||
# processes launched while the propagation type of / is 'private'
|
|
||||||
# won't get mount events from others.
|
|
||||||
mount rootfs rootfs / shared rec
|
|
||||||
|
|
||||||
# Set init and its forked children's oom_adj.
|
# Set init and its forked children's oom_adj.
|
||||||
write /proc/1/oom_score_adj -1000
|
write /proc/1/oom_score_adj -1000
|
||||||
|
|
||||||
|
|
@ -46,8 +40,6 @@ on early-init
|
||||||
# cgroup for system_server and surfaceflinger
|
# cgroup for system_server and surfaceflinger
|
||||||
mkdir /dev/memcg/system 0550 system system
|
mkdir /dev/memcg/system 0550 system system
|
||||||
|
|
||||||
prepare_bootstrap_bionic
|
|
||||||
|
|
||||||
start ueventd
|
start ueventd
|
||||||
|
|
||||||
on init
|
on init
|
||||||
|
|
@ -352,6 +344,8 @@ on post-fs
|
||||||
# Once everything is setup, no need to modify /.
|
# Once everything is setup, no need to modify /.
|
||||||
# The bind+remount combination allows this to work in containers.
|
# The bind+remount combination allows this to work in containers.
|
||||||
mount rootfs rootfs / remount bind ro nodev
|
mount rootfs rootfs / remount bind ro nodev
|
||||||
|
# Mount shared so changes propagate into child namespaces
|
||||||
|
mount rootfs rootfs / shared rec
|
||||||
# Mount default storage into root namespace
|
# Mount default storage into root namespace
|
||||||
mount none /mnt/runtime/default /storage bind rec
|
mount none /mnt/runtime/default /storage bind rec
|
||||||
mount none none /storage slave rec
|
mount none none /storage slave rec
|
||||||
|
|
@ -587,14 +581,6 @@ on post-fs-data
|
||||||
# Check any timezone data in /data is newer than the copy in the runtime module, delete if not.
|
# Check any timezone data in /data is newer than the copy in the runtime module, delete if not.
|
||||||
exec - system system -- /system/bin/tzdatacheck /apex/com.android.runtime/etc/tz /data/misc/zoneinfo
|
exec - system system -- /system/bin/tzdatacheck /apex/com.android.runtime/etc/tz /data/misc/zoneinfo
|
||||||
|
|
||||||
# Wait for apexd to finish activating APEXes before starting more processes.
|
|
||||||
# This certainly reduces the parallelism but is required to make as many processes
|
|
||||||
# as possible to use the bionic libs from the runtime APEX. This takes less than 50ms
|
|
||||||
# so the impact on the booting time is not significant.
|
|
||||||
wait_for_prop apexd.status ready
|
|
||||||
setup_runtime_bionic
|
|
||||||
parse_apex_configs
|
|
||||||
|
|
||||||
# If there is no post-fs-data action in the init.<device>.rc file, you
|
# If there is no post-fs-data action in the init.<device>.rc file, you
|
||||||
# must uncomment this line, otherwise encrypted filesystems
|
# must uncomment this line, otherwise encrypted filesystems
|
||||||
# won't work.
|
# won't work.
|
||||||
|
|
@ -816,3 +802,6 @@ on property:ro.debuggable=1
|
||||||
service flash_recovery /system/bin/install-recovery.sh
|
service flash_recovery /system/bin/install-recovery.sh
|
||||||
class main
|
class main
|
||||||
oneshot
|
oneshot
|
||||||
|
|
||||||
|
on property:apexd.status=ready
|
||||||
|
parse_apex_configs
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue