init: Replace property_set() with android::base::SetProperty()
Init is no longer a special case and talks to property service just like every other client, therefore move it away from property_set() and to android::base::SetProperty(). In doing so, this change moves the initial property set up from the kernel command line and property files directly into PropertyInit(). This makes the responsibilities between init and property services more clear. Test: boot, unit test cases Change-Id: I36b8c83e845d887f1b203355c2391ec123c3d05f
This commit is contained in:
parent
f7a6c4587f
commit
c88d8f93cf
12 changed files with 189 additions and 217 deletions
|
@ -84,6 +84,7 @@
|
|||
using namespace std::literals::string_literals;
|
||||
|
||||
using android::base::Basename;
|
||||
using android::base::SetProperty;
|
||||
using android::base::StartsWith;
|
||||
using android::base::StringPrintf;
|
||||
using android::base::unique_fd;
|
||||
|
@ -561,16 +562,16 @@ static Result<void> queue_fs_event(int code, bool userdata_remount) {
|
|||
LOG(ERROR) << "Userdata remount is not supported on FDE devices. How did you get here?";
|
||||
trigger_shutdown("reboot,requested-userdata-remount-on-fde-device");
|
||||
}
|
||||
property_set("ro.crypto.state", "encrypted");
|
||||
property_set("ro.crypto.type", "block");
|
||||
SetProperty("ro.crypto.state", "encrypted");
|
||||
SetProperty("ro.crypto.type", "block");
|
||||
ActionManager::GetInstance().QueueEventTrigger("defaultcrypto");
|
||||
return {};
|
||||
} else if (code == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) {
|
||||
property_set("ro.crypto.state", "unencrypted");
|
||||
SetProperty("ro.crypto.state", "unencrypted");
|
||||
ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
|
||||
return {};
|
||||
} else if (code == FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) {
|
||||
property_set("ro.crypto.state", "unsupported");
|
||||
SetProperty("ro.crypto.state", "unsupported");
|
||||
ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
|
||||
return {};
|
||||
} else if (code == FS_MGR_MNTALL_DEV_NEEDS_RECOVERY) {
|
||||
|
@ -586,8 +587,8 @@ static Result<void> queue_fs_event(int code, bool userdata_remount) {
|
|||
if (!FscryptInstallKeyring()) {
|
||||
return Error() << "FscryptInstallKeyring() failed";
|
||||
}
|
||||
property_set("ro.crypto.state", "encrypted");
|
||||
property_set("ro.crypto.type", "file");
|
||||
SetProperty("ro.crypto.state", "encrypted");
|
||||
SetProperty("ro.crypto.type", "file");
|
||||
|
||||
// Although encrypted, we have device key, so we do not need to
|
||||
// do anything different from the nonencrypted case.
|
||||
|
@ -597,8 +598,8 @@ static Result<void> queue_fs_event(int code, bool userdata_remount) {
|
|||
if (!FscryptInstallKeyring()) {
|
||||
return Error() << "FscryptInstallKeyring() failed";
|
||||
}
|
||||
property_set("ro.crypto.state", "encrypted");
|
||||
property_set("ro.crypto.type", "file");
|
||||
SetProperty("ro.crypto.state", "encrypted");
|
||||
SetProperty("ro.crypto.type", "file");
|
||||
|
||||
// Although encrypted, vold has already set the device up, so we do not need to
|
||||
// do anything different from the nonencrypted case.
|
||||
|
@ -608,8 +609,8 @@ static Result<void> queue_fs_event(int code, bool userdata_remount) {
|
|||
if (!FscryptInstallKeyring()) {
|
||||
return Error() << "FscryptInstallKeyring() failed";
|
||||
}
|
||||
property_set("ro.crypto.state", "encrypted");
|
||||
property_set("ro.crypto.type", "file");
|
||||
SetProperty("ro.crypto.state", "encrypted");
|
||||
SetProperty("ro.crypto.type", "file");
|
||||
|
||||
// Although encrypted, vold has already set the device up, so we do not need to
|
||||
// do anything different from the nonencrypted case.
|
||||
|
@ -662,7 +663,7 @@ static Result<void> do_mount_all(const BuiltinArguments& args) {
|
|||
}
|
||||
|
||||
auto mount_fstab_return_code = fs_mgr_mount_all(&fstab, mount_mode);
|
||||
property_set(prop_name, std::to_string(t.duration().count()));
|
||||
SetProperty(prop_name, std::to_string(t.duration().count()));
|
||||
|
||||
if (import_rc && SelinuxGetVendorAndroidVersion() <= __ANDROID_API_Q__) {
|
||||
/* Paths of .rc files are specified at the 2nd argument and beyond */
|
||||
|
@ -718,7 +719,7 @@ static Result<void> do_setprop(const BuiltinArguments& args) {
|
|||
<< "' from init; use the restorecon builtin directly";
|
||||
}
|
||||
|
||||
property_set(args[1], args[2]);
|
||||
SetProperty(args[1], args[2]);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -832,7 +833,7 @@ static Result<void> do_verity_update_state(const BuiltinArguments& args) {
|
|||
// To be consistent in vboot 1.0 and vboot 2.0 (AVB), use "system" for the partition even
|
||||
// for system as root, so it has property [partition.system.verified].
|
||||
std::string partition = entry.mount_point == "/" ? "system" : Basename(entry.mount_point);
|
||||
property_set("partition." + partition + ".verified", std::to_string(mode));
|
||||
SetProperty("partition." + partition + ".verified", std::to_string(mode));
|
||||
}
|
||||
|
||||
return {};
|
||||
|
@ -1221,8 +1222,8 @@ static Result<void> do_enter_default_mount_ns(const BuiltinArguments& args) {
|
|||
static Result<void> do_finish_userspace_reboot(const BuiltinArguments&) {
|
||||
LOG(INFO) << "Userspace reboot successfully finished";
|
||||
boot_clock::time_point now = boot_clock::now();
|
||||
property_set("sys.init.userspace_reboot.last_finished",
|
||||
std::to_string(now.time_since_epoch().count()));
|
||||
SetProperty("sys.init.userspace_reboot.last_finished",
|
||||
std::to_string(now.time_since_epoch().count()));
|
||||
if (!android::sysprop::InitProperties::userspace_reboot_in_progress(false)) {
|
||||
return Error() << "Failed to set sys.init.userspace_reboot.in_progress property";
|
||||
}
|
||||
|
|
|
@ -39,15 +39,6 @@ namespace init {
|
|||
inline bool CanReadProperty(const std::string&, const std::string&) {
|
||||
return true;
|
||||
}
|
||||
inline uint32_t SetProperty(const std::string& key, const std::string& value) {
|
||||
android::base::SetProperty(key, value);
|
||||
return 0;
|
||||
}
|
||||
inline uint32_t (*property_set)(const std::string& name, const std::string& value) = SetProperty;
|
||||
inline uint32_t HandlePropertySet(const std::string&, const std::string&, const std::string&,
|
||||
const ucred&, std::string*) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// reboot_utils.h
|
||||
inline void SetFatalRebootTarget() {}
|
||||
|
|
153
init/init.cpp
153
init/init.cpp
|
@ -81,6 +81,7 @@ using namespace std::string_literals;
|
|||
using android::base::boot_clock;
|
||||
using android::base::GetProperty;
|
||||
using android::base::ReadFileToString;
|
||||
using android::base::SetProperty;
|
||||
using android::base::StringPrintf;
|
||||
using android::base::Timer;
|
||||
using android::base::Trim;
|
||||
|
@ -91,8 +92,6 @@ namespace init {
|
|||
|
||||
static int property_triggers_enabled = 0;
|
||||
|
||||
static char qemu[32];
|
||||
|
||||
static int signal_fd = -1;
|
||||
static int property_fd = -1;
|
||||
|
||||
|
@ -101,7 +100,6 @@ static std::string wait_prop_name;
|
|||
static std::string wait_prop_value;
|
||||
static std::string shutdown_command;
|
||||
static bool do_shutdown = false;
|
||||
static bool load_debug_prop = false;
|
||||
|
||||
static std::unique_ptr<Subcontext> subcontext;
|
||||
|
||||
|
@ -208,7 +206,7 @@ void property_changed(const std::string& name, const std::string& value) {
|
|||
// to wait.
|
||||
if (name == kColdBootDoneProp) {
|
||||
auto time_waited = waiting_for_prop ? waiting_for_prop->duration().count() : 0;
|
||||
property_set("ro.boottime.init.cold_boot_wait", std::to_string(time_waited));
|
||||
SetProperty("ro.boottime.init.cold_boot_wait", std::to_string(time_waited));
|
||||
}
|
||||
|
||||
if (waiting_for_prop) {
|
||||
|
@ -364,85 +362,15 @@ static Result<void> SetupCgroupsAction(const BuiltinArguments&) {
|
|||
return {};
|
||||
}
|
||||
|
||||
static void import_kernel_nv(const std::string& key, const std::string& value, bool for_emulator) {
|
||||
if (key.empty()) return;
|
||||
|
||||
if (for_emulator) {
|
||||
// In the emulator, export any kernel option with the "ro.kernel." prefix.
|
||||
property_set("ro.kernel." + key, value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (key == "qemu") {
|
||||
strlcpy(qemu, value.c_str(), sizeof(qemu));
|
||||
} else if (android::base::StartsWith(key, "androidboot.")) {
|
||||
property_set("ro.boot." + key.substr(12), value);
|
||||
}
|
||||
}
|
||||
|
||||
static void export_oem_lock_status() {
|
||||
if (!android::base::GetBoolProperty("ro.oem_unlock_supported", false)) {
|
||||
return;
|
||||
}
|
||||
import_kernel_cmdline(
|
||||
false, [](const std::string& key, const std::string& value, bool in_qemu) {
|
||||
if (key == "androidboot.verifiedbootstate") {
|
||||
property_set("ro.boot.flash.locked", value == "orange" ? "0" : "1");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void export_kernel_boot_props() {
|
||||
constexpr const char* UNSET = "";
|
||||
struct {
|
||||
const char *src_prop;
|
||||
const char *dst_prop;
|
||||
const char *default_value;
|
||||
} prop_map[] = {
|
||||
{ "ro.boot.serialno", "ro.serialno", UNSET, },
|
||||
{ "ro.boot.mode", "ro.bootmode", "unknown", },
|
||||
{ "ro.boot.baseband", "ro.baseband", "unknown", },
|
||||
{ "ro.boot.bootloader", "ro.bootloader", "unknown", },
|
||||
{ "ro.boot.hardware", "ro.hardware", "unknown", },
|
||||
{ "ro.boot.revision", "ro.revision", "0", },
|
||||
};
|
||||
for (const auto& prop : prop_map) {
|
||||
std::string value = GetProperty(prop.src_prop, prop.default_value);
|
||||
if (value != UNSET)
|
||||
property_set(prop.dst_prop, value);
|
||||
}
|
||||
}
|
||||
|
||||
static void process_kernel_dt() {
|
||||
if (!is_android_dt_value_expected("compatible", "android,firmware")) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(get_android_dt_dir().c_str()), closedir);
|
||||
if (!dir) return;
|
||||
|
||||
std::string dt_file;
|
||||
struct dirent *dp;
|
||||
while ((dp = readdir(dir.get())) != NULL) {
|
||||
if (dp->d_type != DT_REG || !strcmp(dp->d_name, "compatible") || !strcmp(dp->d_name, "name")) {
|
||||
continue;
|
||||
ImportKernelCmdline([](const std::string& key, const std::string& value) {
|
||||
if (key == "androidboot.verifiedbootstate") {
|
||||
SetProperty("ro.boot.flash.locked", value == "orange" ? "0" : "1");
|
||||
}
|
||||
|
||||
std::string file_name = get_android_dt_dir() + dp->d_name;
|
||||
|
||||
android::base::ReadFileToString(file_name, &dt_file);
|
||||
std::replace(dt_file.begin(), dt_file.end(), ',', '.');
|
||||
|
||||
property_set("ro.boot."s + dp->d_name, dt_file);
|
||||
}
|
||||
}
|
||||
|
||||
static void process_kernel_cmdline() {
|
||||
// The first pass does the common stuff, and finds if we are in qemu.
|
||||
// The second pass is only necessary for qemu to export all kernel params
|
||||
// as properties.
|
||||
import_kernel_cmdline(false, import_kernel_nv);
|
||||
if (qemu[0]) import_kernel_cmdline(true, import_kernel_nv);
|
||||
});
|
||||
}
|
||||
|
||||
static Result<void> property_enable_triggers_action(const BuiltinArguments& args) {
|
||||
|
@ -468,7 +396,7 @@ static void set_usb_controller() {
|
|||
while ((dp = readdir(dir.get())) != nullptr) {
|
||||
if (dp->d_name[0] == '.') continue;
|
||||
|
||||
property_set("sys.usb.controller", dp->d_name);
|
||||
SetProperty("sys.usb.controller", dp->d_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -591,7 +519,7 @@ static void RecordStageBoottimes(const boot_clock::time_point& second_stage_star
|
|||
int64_t first_stage_start_time_ns = -1;
|
||||
if (auto first_stage_start_time_str = getenv(kEnvFirstStageStartedAt);
|
||||
first_stage_start_time_str) {
|
||||
property_set("ro.boottime.init", first_stage_start_time_str);
|
||||
SetProperty("ro.boottime.init", first_stage_start_time_str);
|
||||
android::base::ParseInt(first_stage_start_time_str, &first_stage_start_time_ns);
|
||||
}
|
||||
unsetenv(kEnvFirstStageStartedAt);
|
||||
|
@ -605,11 +533,11 @@ static void RecordStageBoottimes(const boot_clock::time_point& second_stage_star
|
|||
if (selinux_start_time_ns == -1) return;
|
||||
if (first_stage_start_time_ns == -1) return;
|
||||
|
||||
property_set("ro.boottime.init.first_stage",
|
||||
std::to_string(selinux_start_time_ns - first_stage_start_time_ns));
|
||||
property_set("ro.boottime.init.selinux",
|
||||
std::to_string(second_stage_start_time.time_since_epoch().count() -
|
||||
selinux_start_time_ns));
|
||||
SetProperty("ro.boottime.init.first_stage",
|
||||
std::to_string(selinux_start_time_ns - first_stage_start_time_ns));
|
||||
SetProperty("ro.boottime.init.selinux",
|
||||
std::to_string(second_stage_start_time.time_since_epoch().count() -
|
||||
selinux_start_time_ns));
|
||||
}
|
||||
|
||||
void SendLoadPersistentPropertiesMessage() {
|
||||
|
@ -706,34 +634,27 @@ int SecondStageMain(int argc, char** argv) {
|
|||
// Indicate that booting is in progress to background fw loaders, etc.
|
||||
close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));
|
||||
|
||||
property_init();
|
||||
|
||||
// If arguments are passed both on the command line and in DT,
|
||||
// properties set in DT always have priority over the command-line ones.
|
||||
process_kernel_dt();
|
||||
process_kernel_cmdline();
|
||||
|
||||
// Propagate the kernel variables to internal variables
|
||||
// used by init as well as the current required properties.
|
||||
export_kernel_boot_props();
|
||||
|
||||
// Make the time that init stages started available for bootstat to log.
|
||||
RecordStageBoottimes(start_time);
|
||||
|
||||
// Set libavb version for Framework-only OTA match in Treble build.
|
||||
const char* avb_version = getenv("INIT_AVB_VERSION");
|
||||
if (avb_version) property_set("ro.boot.avb_version", avb_version);
|
||||
|
||||
// See if need to load debug props to allow adb root, when the device is unlocked.
|
||||
const char* force_debuggable_env = getenv("INIT_FORCE_DEBUGGABLE");
|
||||
bool load_debug_prop = false;
|
||||
if (force_debuggable_env && AvbHandle::IsDeviceUnlocked()) {
|
||||
load_debug_prop = "true"s == force_debuggable_env;
|
||||
}
|
||||
|
||||
// Clean up our environment.
|
||||
unsetenv("INIT_AVB_VERSION");
|
||||
unsetenv("INIT_FORCE_DEBUGGABLE");
|
||||
|
||||
// Umount the debug ramdisk so property service doesn't read .prop files from there, when it
|
||||
// is not meant to.
|
||||
if (!load_debug_prop) {
|
||||
UmountDebugRamdisk();
|
||||
}
|
||||
|
||||
PropertyInit();
|
||||
|
||||
// Umount the debug ramdisk after property service has read the .prop files when it means to.
|
||||
if (load_debug_prop) {
|
||||
UmountDebugRamdisk();
|
||||
}
|
||||
|
||||
// Now set up SELinux for second stage.
|
||||
SelinuxSetupKernelLogging();
|
||||
SelabelInitialize();
|
||||
|
@ -746,16 +667,22 @@ int SecondStageMain(int argc, char** argv) {
|
|||
|
||||
InstallSignalFdHandler(&epoll);
|
||||
|
||||
property_load_boot_defaults(load_debug_prop);
|
||||
UmountDebugRamdisk();
|
||||
fs_mgr_vendor_overlay_mount_all();
|
||||
export_oem_lock_status();
|
||||
|
||||
StartPropertyService(&property_fd);
|
||||
if (auto result = epoll.RegisterHandler(property_fd, HandlePropertyFd); !result) {
|
||||
LOG(FATAL) << "Could not register epoll handler for property fd: " << result.error();
|
||||
}
|
||||
|
||||
// Make the time that init stages started available for bootstat to log.
|
||||
RecordStageBoottimes(start_time);
|
||||
|
||||
// Set libavb version for Framework-only OTA match in Treble build.
|
||||
if (const char* avb_version = getenv("INIT_AVB_VERSION"); avb_version != nullptr) {
|
||||
SetProperty("ro.boot.avb_version", avb_version);
|
||||
}
|
||||
unsetenv("INIT_AVB_VERSION");
|
||||
|
||||
fs_mgr_vendor_overlay_mount_all();
|
||||
export_oem_lock_status();
|
||||
MountHandler mount_handler(&epoll);
|
||||
set_usb_controller();
|
||||
|
||||
|
@ -779,9 +706,9 @@ int SecondStageMain(int argc, char** argv) {
|
|||
|
||||
// Make the GSI status available before scripts start running.
|
||||
if (android::gsi::IsGsiRunning()) {
|
||||
property_set("ro.gsid.image_running", "1");
|
||||
SetProperty("ro.gsid.image_running", "1");
|
||||
} else {
|
||||
property_set("ro.gsid.image_running", "0");
|
||||
SetProperty("ro.gsid.image_running", "0");
|
||||
}
|
||||
|
||||
am.QueueBuiltinAction(SetupCgroupsAction, "SetupCgroups");
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
#include <libdm/dm.h>
|
||||
|
||||
#include "epoll.h"
|
||||
#include "property_service.h"
|
||||
|
||||
namespace android {
|
||||
namespace init {
|
||||
|
@ -96,7 +95,7 @@ void SetMountProperty(const MountHandlerEntry& entry, bool add) {
|
|||
// handling, except for clearing non-existent or already clear property.
|
||||
// Goal is reduction of empty properties and associated triggers.
|
||||
if (value.empty() && android::base::GetProperty(mount_prop, "").empty()) return;
|
||||
property_set(mount_prop, value);
|
||||
android::base::SetProperty(mount_prop, value);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -97,8 +97,6 @@ static bool accept_messages = false;
|
|||
|
||||
static PropertyInfoAreaFile property_info_area;
|
||||
|
||||
void CreateSerializedPropertyInfo();
|
||||
|
||||
struct PropertyAuditData {
|
||||
const ucred* cr;
|
||||
const char* name;
|
||||
|
@ -117,21 +115,6 @@ static int PropertyAuditCallback(void* data, security_class_t /*cls*/, char* buf
|
|||
return 0;
|
||||
}
|
||||
|
||||
void property_init() {
|
||||
selinux_callback cb;
|
||||
cb.func_audit = PropertyAuditCallback;
|
||||
selinux_set_callback(SELINUX_CB_AUDIT, cb);
|
||||
|
||||
mkdir("/dev/__properties__", S_IRWXU | S_IXGRP | S_IXOTH);
|
||||
CreateSerializedPropertyInfo();
|
||||
if (__system_property_area_init()) {
|
||||
LOG(FATAL) << "Failed to initialize property area";
|
||||
}
|
||||
if (!property_info_area.LoadDefaultPath()) {
|
||||
LOG(FATAL) << "Failed to load serialized property info file";
|
||||
}
|
||||
}
|
||||
|
||||
bool CanReadProperty(const std::string& source_context, const std::string& name) {
|
||||
const char* target_context = nullptr;
|
||||
property_info_area->GetPropertyInfo(name.c_str(), &target_context, nullptr);
|
||||
|
@ -527,20 +510,6 @@ uint32_t HandlePropertySet(const std::string& name, const std::string& value,
|
|||
return PropertySet(name, value, error);
|
||||
}
|
||||
|
||||
uint32_t InitPropertySet(const std::string& name, const std::string& value) {
|
||||
uint32_t result = 0;
|
||||
ucred cr = {.pid = 1, .uid = 0, .gid = 0};
|
||||
std::string error;
|
||||
result = HandlePropertySet(name, value, kInitContext, cr, nullptr, &error);
|
||||
if (result != PROP_SUCCESS) {
|
||||
LOG(ERROR) << "Init cannot set '" << name << "' to '" << value << "': " << error;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t (*property_set)(const std::string& name, const std::string& value) = InitPropertySet;
|
||||
|
||||
static void handle_property_set_fd() {
|
||||
static constexpr uint32_t kDefaultSocketTimeout = 2000; /* ms */
|
||||
|
||||
|
@ -634,6 +603,18 @@ static void handle_property_set_fd() {
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t InitPropertySet(const std::string& name, const std::string& value) {
|
||||
uint32_t result = 0;
|
||||
ucred cr = {.pid = 1, .uid = 0, .gid = 0};
|
||||
std::string error;
|
||||
result = HandlePropertySet(name, value, kInitContext, cr, nullptr, &error);
|
||||
if (result != PROP_SUCCESS) {
|
||||
LOG(ERROR) << "Init cannot set '" << name << "' to '" << value << "': " << error;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool load_properties_from_file(const char*, const char*,
|
||||
std::map<std::string, std::string>*);
|
||||
|
||||
|
@ -765,11 +746,11 @@ static void update_sys_usb_config() {
|
|||
bool is_debuggable = android::base::GetBoolProperty("ro.debuggable", false);
|
||||
std::string config = android::base::GetProperty("persist.sys.usb.config", "");
|
||||
if (config.empty()) {
|
||||
property_set("persist.sys.usb.config", is_debuggable ? "adb" : "none");
|
||||
InitPropertySet("persist.sys.usb.config", is_debuggable ? "adb" : "none");
|
||||
} else if (is_debuggable && config.find("adb") == std::string::npos &&
|
||||
config.length() + 4 < PROP_VALUE_MAX) {
|
||||
config.append(",adb");
|
||||
property_set("persist.sys.usb.config", config);
|
||||
InitPropertySet("persist.sys.usb.config", config);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -890,7 +871,7 @@ static void property_derive_build_fingerprint() {
|
|||
}
|
||||
}
|
||||
|
||||
void property_load_boot_defaults(bool load_debug_prop) {
|
||||
void PropertyLoadBootDefaults() {
|
||||
// TODO(b/117892318): merge prop.default and build.prop files into one
|
||||
// We read the properties and their values into a map, in order to always allow properties
|
||||
// loaded in the later property files to override the properties in loaded in the earlier
|
||||
|
@ -916,7 +897,7 @@ void property_load_boot_defaults(bool load_debug_prop) {
|
|||
load_properties_from_file("/product/build.prop", nullptr, &properties);
|
||||
load_properties_from_file("/factory/factory.prop", "ro.*", &properties);
|
||||
|
||||
if (load_debug_prop) {
|
||||
if (access(kDebugRamdiskProp, R_OK) == 0) {
|
||||
LOG(INFO) << "Loading " << kDebugRamdiskProp;
|
||||
load_properties_from_file(kDebugRamdiskProp, nullptr, &properties);
|
||||
}
|
||||
|
@ -1009,6 +990,97 @@ void CreateSerializedPropertyInfo() {
|
|||
selinux_android_restorecon(kPropertyInfosPath, 0);
|
||||
}
|
||||
|
||||
static void ExportKernelBootProps() {
|
||||
constexpr const char* UNSET = "";
|
||||
struct {
|
||||
const char* src_prop;
|
||||
const char* dst_prop;
|
||||
const char* default_value;
|
||||
} prop_map[] = {
|
||||
// clang-format off
|
||||
{ "ro.boot.serialno", "ro.serialno", UNSET, },
|
||||
{ "ro.boot.mode", "ro.bootmode", "unknown", },
|
||||
{ "ro.boot.baseband", "ro.baseband", "unknown", },
|
||||
{ "ro.boot.bootloader", "ro.bootloader", "unknown", },
|
||||
{ "ro.boot.hardware", "ro.hardware", "unknown", },
|
||||
{ "ro.boot.revision", "ro.revision", "0", },
|
||||
// clang-format on
|
||||
};
|
||||
for (const auto& prop : prop_map) {
|
||||
std::string value = GetProperty(prop.src_prop, prop.default_value);
|
||||
if (value != UNSET) InitPropertySet(prop.dst_prop, value);
|
||||
}
|
||||
}
|
||||
|
||||
static void ProcessKernelDt() {
|
||||
if (!is_android_dt_value_expected("compatible", "android,firmware")) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(get_android_dt_dir().c_str()), closedir);
|
||||
if (!dir) return;
|
||||
|
||||
std::string dt_file;
|
||||
struct dirent* dp;
|
||||
while ((dp = readdir(dir.get())) != NULL) {
|
||||
if (dp->d_type != DT_REG || !strcmp(dp->d_name, "compatible") ||
|
||||
!strcmp(dp->d_name, "name")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string file_name = get_android_dt_dir() + dp->d_name;
|
||||
|
||||
android::base::ReadFileToString(file_name, &dt_file);
|
||||
std::replace(dt_file.begin(), dt_file.end(), ',', '.');
|
||||
|
||||
InitPropertySet("ro.boot."s + dp->d_name, dt_file);
|
||||
}
|
||||
}
|
||||
|
||||
static void ProcessKernelCmdline() {
|
||||
bool for_emulator = false;
|
||||
ImportKernelCmdline([&](const std::string& key, const std::string& value) {
|
||||
if (key == "qemu") {
|
||||
for_emulator = true;
|
||||
} else if (StartsWith(key, "androidboot.")) {
|
||||
InitPropertySet("ro.boot." + key.substr(12), value);
|
||||
}
|
||||
});
|
||||
|
||||
if (for_emulator) {
|
||||
ImportKernelCmdline([&](const std::string& key, const std::string& value) {
|
||||
// In the emulator, export any kernel option with the "ro.kernel." prefix.
|
||||
InitPropertySet("ro.kernel." + key, value);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void PropertyInit() {
|
||||
selinux_callback cb;
|
||||
cb.func_audit = PropertyAuditCallback;
|
||||
selinux_set_callback(SELINUX_CB_AUDIT, cb);
|
||||
|
||||
mkdir("/dev/__properties__", S_IRWXU | S_IXGRP | S_IXOTH);
|
||||
CreateSerializedPropertyInfo();
|
||||
if (__system_property_area_init()) {
|
||||
LOG(FATAL) << "Failed to initialize property area";
|
||||
}
|
||||
if (!property_info_area.LoadDefaultPath()) {
|
||||
LOG(FATAL) << "Failed to load serialized property info file";
|
||||
}
|
||||
|
||||
// If arguments are passed both on the command line and in DT,
|
||||
// properties set in DT always have priority over the command-line ones.
|
||||
ProcessKernelDt();
|
||||
ProcessKernelCmdline();
|
||||
|
||||
// Propagate the kernel variables to internal variables
|
||||
// used by init as well as the current required properties.
|
||||
ExportKernelBootProps();
|
||||
|
||||
PropertyLoadBootDefaults();
|
||||
}
|
||||
|
||||
static void HandleInitSocket() {
|
||||
auto message = ReadMessage(init_socket);
|
||||
if (!message) {
|
||||
|
@ -1075,7 +1147,7 @@ static void PropertyServiceThread() {
|
|||
}
|
||||
|
||||
void StartPropertyService(int* epoll_socket) {
|
||||
property_set("ro.property_service.version", "2");
|
||||
InitPropertySet("ro.property_service.version", "2");
|
||||
|
||||
int sockets[2];
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, sockets) != 0) {
|
||||
|
@ -1095,11 +1167,6 @@ void StartPropertyService(int* epoll_socket) {
|
|||
listen(property_set_fd, 8);
|
||||
|
||||
std::thread{PropertyServiceThread}.detach();
|
||||
|
||||
property_set = [](const std::string& key, const std::string& value) -> uint32_t {
|
||||
android::base::SetProperty(key, value);
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace init
|
||||
|
|
|
@ -29,10 +29,7 @@ static constexpr const char kRestoreconProperty[] = "selinux.restorecon_recursiv
|
|||
|
||||
bool CanReadProperty(const std::string& source_context, const std::string& name);
|
||||
|
||||
extern uint32_t (*property_set)(const std::string& name, const std::string& value);
|
||||
|
||||
void property_init();
|
||||
void property_load_boot_defaults(bool load_debug_prop);
|
||||
void PropertyInit();
|
||||
void StartPropertyService(int* epoll_socket);
|
||||
|
||||
} // namespace init
|
||||
|
|
|
@ -59,7 +59,6 @@
|
|||
#include "builtin_arguments.h"
|
||||
#include "init.h"
|
||||
#include "mount_namespace.h"
|
||||
#include "property_service.h"
|
||||
#include "reboot_utils.h"
|
||||
#include "service.h"
|
||||
#include "service_list.h"
|
||||
|
@ -548,7 +547,7 @@ static void DoReboot(unsigned int cmd, const std::string& reason, const std::str
|
|||
reasons[1] == "hard" || reasons[1] == "warm")) {
|
||||
skip = strlen("reboot,");
|
||||
}
|
||||
property_set(LAST_REBOOT_REASON_PROPERTY, reason.c_str() + skip);
|
||||
SetProperty(LAST_REBOOT_REASON_PROPERTY, reason.c_str() + skip);
|
||||
sync();
|
||||
|
||||
bool is_thermal_shutdown = cmd == ANDROID_RB_THERMOFF;
|
||||
|
@ -619,7 +618,7 @@ static void DoReboot(unsigned int cmd, const std::string& reason, const std::str
|
|||
bool do_shutdown_animation = GetBoolProperty("ro.init.shutdown_animation", false);
|
||||
|
||||
if (do_shutdown_animation) {
|
||||
property_set("service.bootanim.exit", "0");
|
||||
SetProperty("service.bootanim.exit", "0");
|
||||
// Could be in the middle of animation. Stop and start so that it can pick
|
||||
// up the right mode.
|
||||
boot_anim->Stop();
|
||||
|
@ -733,8 +732,8 @@ static Result<void> UnmountAllApexes() {
|
|||
static Result<void> DoUserspaceReboot() {
|
||||
LOG(INFO) << "Userspace reboot initiated";
|
||||
boot_clock::time_point now = boot_clock::now();
|
||||
property_set("sys.init.userspace_reboot.last_started",
|
||||
std::to_string(now.time_since_epoch().count()));
|
||||
SetProperty("sys.init.userspace_reboot.last_started",
|
||||
std::to_string(now.time_since_epoch().count()));
|
||||
auto guard = android::base::make_scope_guard([] {
|
||||
// Leave shutdown so that we can handle a full reboot.
|
||||
LeaveShutdown();
|
||||
|
|
|
@ -88,12 +88,11 @@ enum EnforcingStatus { SELINUX_PERMISSIVE, SELINUX_ENFORCING };
|
|||
EnforcingStatus StatusFromCmdline() {
|
||||
EnforcingStatus status = SELINUX_ENFORCING;
|
||||
|
||||
import_kernel_cmdline(false,
|
||||
[&](const std::string& key, const std::string& value, bool in_qemu) {
|
||||
if (key == "androidboot.selinux" && value == "permissive") {
|
||||
status = SELINUX_PERMISSIVE;
|
||||
}
|
||||
});
|
||||
ImportKernelCmdline([&](const std::string& key, const std::string& value) {
|
||||
if (key == "androidboot.selinux" && value == "permissive") {
|
||||
status = SELINUX_PERMISSIVE;
|
||||
}
|
||||
});
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
#include <android/api-level.h>
|
||||
|
||||
#include "mount_namespace.h"
|
||||
#include "property_service.h"
|
||||
#include "selinux.h"
|
||||
#else
|
||||
#include "host_init_stubs.h"
|
||||
|
@ -55,6 +54,7 @@ using android::base::boot_clock;
|
|||
using android::base::GetProperty;
|
||||
using android::base::Join;
|
||||
using android::base::make_scope_guard;
|
||||
using android::base::SetProperty;
|
||||
using android::base::StartsWith;
|
||||
using android::base::StringPrintf;
|
||||
using android::base::WriteStringToFile;
|
||||
|
@ -164,13 +164,13 @@ void Service::NotifyStateChange(const std::string& new_state) const {
|
|||
}
|
||||
|
||||
std::string prop_name = "init.svc." + name_;
|
||||
property_set(prop_name, new_state);
|
||||
SetProperty(prop_name, new_state);
|
||||
|
||||
if (new_state == "running") {
|
||||
uint64_t start_ns = time_started_.time_since_epoch().count();
|
||||
std::string boottime_property = "ro.boottime." + name_;
|
||||
if (GetProperty(boottime_property, "").empty()) {
|
||||
property_set(boottime_property, std::to_string(start_ns));
|
||||
SetProperty(boottime_property, std::to_string(start_ns));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,9 +178,9 @@ void Service::NotifyStateChange(const std::string& new_state) const {
|
|||
// on device for security checks.
|
||||
std::string pid_property = "init.svc_debug_pid." + name_;
|
||||
if (new_state == "running") {
|
||||
property_set(pid_property, std::to_string(pid_));
|
||||
SetProperty(pid_property, std::to_string(pid_));
|
||||
} else if (new_state == "stopped") {
|
||||
property_set(pid_property, "");
|
||||
SetProperty(pid_property, "");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -324,7 +324,7 @@ void Service::Reap(const siginfo_t& siginfo) {
|
|||
LOG(ERROR) << "updatable process '" << name_ << "' exited 4 times "
|
||||
<< (boot_completed ? "in 4 minutes" : "before boot completed");
|
||||
// Notifies update_verifier and apexd
|
||||
property_set("sys.init.updatable_crashing", "1");
|
||||
SetProperty("sys.init.updatable_crashing", "1");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -176,11 +176,6 @@ int SubcontextMain(int argc, char** argv, const BuiltinFunctionMap* function_map
|
|||
|
||||
SelabelInitialize();
|
||||
|
||||
property_set = [](const std::string& key, const std::string& value) -> uint32_t {
|
||||
android::base::SetProperty(key, value);
|
||||
return 0;
|
||||
};
|
||||
|
||||
trigger_shutdown = [](const std::string& command) { shutdown_command = command; };
|
||||
|
||||
auto subcontext_process = SubcontextProcess(function_map, context, init_fd);
|
||||
|
|
|
@ -234,15 +234,14 @@ int wait_for_file(const char* filename, std::chrono::nanoseconds timeout) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
void import_kernel_cmdline(bool in_qemu,
|
||||
const std::function<void(const std::string&, const std::string&, bool)>& fn) {
|
||||
void ImportKernelCmdline(const std::function<void(const std::string&, const std::string&)>& fn) {
|
||||
std::string cmdline;
|
||||
android::base::ReadFileToString("/proc/cmdline", &cmdline);
|
||||
|
||||
for (const auto& entry : android::base::Split(android::base::Trim(cmdline), " ")) {
|
||||
std::vector<std::string> pieces = android::base::Split(entry, "=");
|
||||
if (pieces.size() == 2) {
|
||||
fn(pieces[0], pieces[1], in_qemu);
|
||||
fn(pieces[0], pieces[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -359,12 +358,11 @@ static std::string init_android_dt_dir() {
|
|||
// Use the standard procfs-based path by default
|
||||
std::string android_dt_dir = kDefaultAndroidDtDir;
|
||||
// The platform may specify a custom Android DT path in kernel cmdline
|
||||
import_kernel_cmdline(false,
|
||||
[&](const std::string& key, const std::string& value, bool in_qemu) {
|
||||
if (key == "androidboot.android_dt_dir") {
|
||||
android_dt_dir = value;
|
||||
}
|
||||
});
|
||||
ImportKernelCmdline([&](const std::string& key, const std::string& value) {
|
||||
if (key == "androidboot.android_dt_dir") {
|
||||
android_dt_dir = value;
|
||||
}
|
||||
});
|
||||
LOG(INFO) << "Using Android DT directory " << android_dt_dir;
|
||||
return android_dt_dir;
|
||||
}
|
||||
|
|
|
@ -47,8 +47,7 @@ Result<uid_t> DecodeUid(const std::string& name);
|
|||
|
||||
bool mkdir_recursive(const std::string& pathname, mode_t mode);
|
||||
int wait_for_file(const char *filename, std::chrono::nanoseconds timeout);
|
||||
void import_kernel_cmdline(bool in_qemu,
|
||||
const std::function<void(const std::string&, const std::string&, bool)>&);
|
||||
void ImportKernelCmdline(const std::function<void(const std::string&, const std::string&)>&);
|
||||
bool make_dir(const std::string& path, mode_t mode);
|
||||
bool is_dir(const char* pathname);
|
||||
Result<std::string> ExpandProps(const std::string& src);
|
||||
|
|
Loading…
Reference in a new issue