Merge "Do not access device maps."
diff --git a/base/file.cpp b/base/file.cpp
index 378a405..d4e5894 100644
--- a/base/file.cpp
+++ b/base/file.cpp
@@ -49,6 +49,14 @@
bool ReadFdToString(int fd, std::string* content) {
content->clear();
+ // Although original we had small files in mind, this code gets used for
+ // very large files too, where the std::string growth heuristics might not
+ // be suitable. https://code.google.com/p/android/issues/detail?id=258500.
+ struct stat sb;
+ if (fstat(fd, &sb) != -1 && sb.st_size > 0) {
+ content->reserve(sb.st_size);
+ }
+
char buf[BUFSIZ];
ssize_t n;
while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], sizeof(buf)))) > 0) {
diff --git a/base/file_test.cpp b/base/file_test.cpp
index 266131e..02b431d 100644
--- a/base/file_test.cpp
+++ b/base/file_test.cpp
@@ -214,3 +214,46 @@
EXPECT_EQ(".", android::base::Dirname("sh"));
EXPECT_EQ("/system/bin", android::base::Dirname("/system/bin/sh/"));
}
+
+TEST(file, ReadFileToString_capacity) {
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+
+ // For a huge file, the overhead should still be small.
+ std::string s;
+ size_t size = 16 * 1024 * 1024;
+ ASSERT_TRUE(android::base::WriteStringToFile(std::string(size, 'x'), tf.path));
+ ASSERT_TRUE(android::base::ReadFileToString(tf.path, &s));
+ EXPECT_EQ(size, s.size());
+ EXPECT_LT(s.capacity(), size + 16);
+
+ // Even for weird badly-aligned sizes.
+ size += 12345;
+ ASSERT_TRUE(android::base::WriteStringToFile(std::string(size, 'x'), tf.path));
+ ASSERT_TRUE(android::base::ReadFileToString(tf.path, &s));
+ EXPECT_EQ(size, s.size());
+ EXPECT_LT(s.capacity(), size + 16);
+
+ // We'll shrink an enormous string if you read a small file into it.
+ size = 64;
+ ASSERT_TRUE(android::base::WriteStringToFile(std::string(size, 'x'), tf.path));
+ ASSERT_TRUE(android::base::ReadFileToString(tf.path, &s));
+ EXPECT_EQ(size, s.size());
+ EXPECT_LT(s.capacity(), size + 16);
+}
+
+TEST(file, ReadFileToString_capacity_0) {
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+
+ // Because /proc reports its files as zero-length, we don't actually trust
+ // any file that claims to be zero-length. Rather than add increasingly
+ // complex heuristics for shrinking the passed-in string in that case, we
+ // currently leave it alone.
+ std::string s;
+ size_t initial_capacity = s.capacity();
+ ASSERT_TRUE(android::base::WriteStringToFile("", tf.path));
+ ASSERT_TRUE(android::base::ReadFileToString(tf.path, &s));
+ EXPECT_EQ(0U, s.size());
+ EXPECT_EQ(initial_capacity, s.capacity());
+}
diff --git a/healthd/BatteryPropertiesRegistrar.cpp b/healthd/BatteryPropertiesRegistrar.cpp
index d28ba41..523e1f1 100644
--- a/healthd/BatteryPropertiesRegistrar.cpp
+++ b/healthd/BatteryPropertiesRegistrar.cpp
@@ -77,6 +77,10 @@
return healthd_get_property(id, val);
}
+void BatteryPropertiesRegistrar::scheduleUpdate() {
+ healthd_battery_update();
+}
+
status_t BatteryPropertiesRegistrar::dump(int fd, const Vector<String16>& /*args*/) {
IPCThreadState* self = IPCThreadState::self();
const int pid = self->getCallingPid();
diff --git a/healthd/BatteryPropertiesRegistrar.h b/healthd/BatteryPropertiesRegistrar.h
index 095f3d3..14e9145 100644
--- a/healthd/BatteryPropertiesRegistrar.h
+++ b/healthd/BatteryPropertiesRegistrar.h
@@ -32,6 +32,7 @@
public:
void publish(const sp<BatteryPropertiesRegistrar>& service);
void notifyListeners(const struct BatteryProperties& props);
+ void scheduleUpdate();
private:
Mutex mRegistrationLock;
diff --git a/include/private/android_filesystem_capability.h b/include/private/android_filesystem_capability.h
new file mode 120000
index 0000000..f310b35
--- /dev/null
+++ b/include/private/android_filesystem_capability.h
@@ -0,0 +1 @@
+../../libcutils/include/private/android_filesystem_capability.h
\ No newline at end of file
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
deleted file mode 100644
index d200070..0000000
--- a/include/private/android_filesystem_config.h
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* This file is used to define the properties of the filesystem
-** images generated by build tools (mkbootfs and mkyaffs2image) and
-** by the device side of adb.
-*/
-
-/*
- * This file is consumed by build/tools/fs_config and is used
- * for generating various files. Anything #define AID_<name>
- * becomes the mapping for getpwnam/getpwuid, etc. The <name>
- * field is lowercased.
- * For example:
- * #define AID_FOO_BAR 6666 becomes a friendly name of "foo_bar"
- *
- * The above holds true with the exception of:
- * mediacodec
- * mediaex
- * mediadrm
- * Whose friendly names do not match the #define statements.
- *
- * Additionally, AID_OEM_RESERVED_START and AID_OEM_RESERVED_END
- * can be used to define reserved OEM ranges used for sanity checks
- * during the build process. The rules are, they must end with START/END
- * The proper convention is incrementing a number like so:
- * AID_OEM_RESERVED_START
- * AID_OEM_RESERVED_1_START
- * AID_OEM_RESERVED_2_START
- * ...
- * The same applies to the END.
- * They are not required to be in order, but must not overlap each other and
- * must define a START and END'ing range. START must be smaller than END.
- */
-
-#ifndef _ANDROID_FILESYSTEM_CONFIG_H_
-#define _ANDROID_FILESYSTEM_CONFIG_H_
-
-#include <sys/cdefs.h>
-#include <sys/types.h>
-#include <stdint.h>
-
-#if defined(__ANDROID__)
-#include <linux/capability.h>
-#else
-#include "android_filesystem_capability.h"
-#endif
-
-#define CAP_MASK_LONG(cap_name) (1ULL << (cap_name))
-
-/* This is the master Users and Groups config for the platform.
- * DO NOT EVER RENUMBER
- */
-
-#define AID_ROOT 0 /* traditional unix root user */
-
-#define AID_SYSTEM 1000 /* system server */
-
-#define AID_RADIO 1001 /* telephony subsystem, RIL */
-#define AID_BLUETOOTH 1002 /* bluetooth subsystem */
-#define AID_GRAPHICS 1003 /* graphics devices */
-#define AID_INPUT 1004 /* input devices */
-#define AID_AUDIO 1005 /* audio devices */
-#define AID_CAMERA 1006 /* camera devices */
-#define AID_LOG 1007 /* log devices */
-#define AID_COMPASS 1008 /* compass device */
-#define AID_MOUNT 1009 /* mountd socket */
-#define AID_WIFI 1010 /* wifi subsystem */
-#define AID_ADB 1011 /* android debug bridge (adbd) */
-#define AID_INSTALL 1012 /* group for installing packages */
-#define AID_MEDIA 1013 /* mediaserver process */
-#define AID_DHCP 1014 /* dhcp client */
-#define AID_SDCARD_RW 1015 /* external storage write access */
-#define AID_VPN 1016 /* vpn system */
-#define AID_KEYSTORE 1017 /* keystore subsystem */
-#define AID_USB 1018 /* USB devices */
-#define AID_DRM 1019 /* DRM server */
-#define AID_MDNSR 1020 /* MulticastDNSResponder (service discovery) */
-#define AID_GPS 1021 /* GPS daemon */
-#define AID_UNUSED1 1022 /* deprecated, DO NOT USE */
-#define AID_MEDIA_RW 1023 /* internal media storage write access */
-#define AID_MTP 1024 /* MTP USB driver access */
-#define AID_UNUSED2 1025 /* deprecated, DO NOT USE */
-#define AID_DRMRPC 1026 /* group for drm rpc */
-#define AID_NFC 1027 /* nfc subsystem */
-#define AID_SDCARD_R 1028 /* external storage read access */
-#define AID_CLAT 1029 /* clat part of nat464 */
-#define AID_LOOP_RADIO 1030 /* loop radio devices */
-#define AID_MEDIA_DRM 1031 /* MediaDrm plugins */
-#define AID_PACKAGE_INFO 1032 /* access to installed package details */
-#define AID_SDCARD_PICS 1033 /* external storage photos access */
-#define AID_SDCARD_AV 1034 /* external storage audio/video access */
-#define AID_SDCARD_ALL 1035 /* access all users external storage */
-#define AID_LOGD 1036 /* log daemon */
-#define AID_SHARED_RELRO 1037 /* creator of shared GNU RELRO files */
-#define AID_DBUS 1038 /* dbus-daemon IPC broker process */
-#define AID_TLSDATE 1039 /* tlsdate unprivileged user */
-#define AID_MEDIA_EX 1040 /* mediaextractor process */
-#define AID_AUDIOSERVER 1041 /* audioserver process */
-#define AID_METRICS_COLL 1042 /* metrics_collector process */
-#define AID_METRICSD 1043 /* metricsd process */
-#define AID_WEBSERV 1044 /* webservd process */
-#define AID_DEBUGGERD 1045 /* debuggerd unprivileged user */
-#define AID_MEDIA_CODEC 1046 /* mediacodec process */
-#define AID_CAMERASERVER 1047 /* cameraserver process */
-#define AID_FIREWALL 1048 /* firewalld process */
-#define AID_TRUNKS 1049 /* trunksd process (TPM daemon) */
-#define AID_NVRAM 1050 /* Access-controlled NVRAM */
-#define AID_DNS 1051 /* DNS resolution daemon (system: netd) */
-#define AID_DNS_TETHER 1052 /* DNS resolution daemon (tether: dnsmasq) */
-#define AID_WEBVIEW_ZYGOTE 1053 /* WebView zygote process */
-#define AID_VEHICLE_NETWORK 1054 /* Vehicle network service */
-#define AID_MEDIA_AUDIO 1055 /* GID for audio files on internal media storage */
-#define AID_MEDIA_VIDEO 1056 /* GID for video files on internal media storage */
-#define AID_MEDIA_IMAGE 1057 /* GID for image files on internal media storage */
-#define AID_TOMBSTONED 1058 /* tombstoned user */
-#define AID_MEDIA_OBB 1059 /* GID for OBB files on internal media storage */
-#define AID_ESE 1060 /* embedded secure element (eSE) subsystem */
-#define AID_OTA_UPDATE 1061 /* resource tracking UID for OTA updates */
-/* Changes to this file must be made in AOSP, *not* in internal branches. */
-
-#define AID_SHELL 2000 /* adb and debug shell user */
-#define AID_CACHE 2001 /* cache access */
-#define AID_DIAG 2002 /* access to diagnostic resources */
-
-/* The range 2900-2999 is reserved for OEM, and must never be
- * used here */
-#define AID_OEM_RESERVED_START 2900
-#define AID_OEM_RESERVED_END 2999
-
-/* The 3000 series are intended for use as supplemental group id's only.
- * They indicate special Android capabilities that the kernel is aware of. */
-#define AID_NET_BT_ADMIN 3001 /* bluetooth: create any socket */
-#define AID_NET_BT 3002 /* bluetooth: create sco, rfcomm or l2cap sockets */
-#define AID_INET 3003 /* can create AF_INET and AF_INET6 sockets */
-#define AID_NET_RAW 3004 /* can create raw INET sockets */
-#define AID_NET_ADMIN 3005 /* can configure interfaces and routing tables. */
-#define AID_NET_BW_STATS 3006 /* read bandwidth statistics */
-#define AID_NET_BW_ACCT 3007 /* change bandwidth statistics accounting */
-#define AID_READPROC 3009 /* Allow /proc read access */
-#define AID_WAKELOCK 3010 /* Allow system wakelock read/write access */
-
-/* The range 5000-5999 is also reserved for OEM, and must never be used here. */
-#define AID_OEM_RESERVED_2_START 5000
-#define AID_OEM_RESERVED_2_END 5999
-
-#define AID_EVERYBODY 9997 /* shared between all apps in the same profile */
-#define AID_MISC 9998 /* access to misc storage */
-#define AID_NOBODY 9999
-
-#define AID_APP 10000 /* TODO: switch users over to AID_APP_START */
-#define AID_APP_START 10000 /* first app user */
-#define AID_APP_END 19999 /* last app user */
-
-#define AID_CACHE_GID_START 20000 /* start of gids for apps to mark cached data */
-#define AID_CACHE_GID_END 29999 /* end of gids for apps to mark cached data */
-
-#define AID_EXT_GID_START 30000 /* start of gids for apps to mark external data */
-#define AID_EXT_GID_END 39999 /* end of gids for apps to mark external data */
-
-#define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */
-#define AID_SHARED_GID_END 59999 /* end of gids for apps in each user to share */
-
-#define AID_ISOLATED_START 99000 /* start of uids for fully isolated sandboxed processes */
-#define AID_ISOLATED_END 99999 /* end of uids for fully isolated sandboxed processes */
-
-#define AID_USER 100000 /* TODO: switch users over to AID_USER_OFFSET */
-#define AID_USER_OFFSET 100000 /* offset for uid ranges for each user */
-
-/*
- * android_ids has moved to pwd/grp functionality.
- * If you need to add one, the structure is now
- * auto-generated based on the AID_ constraints
- * documented at the top of this header file.
- * Also see build/tools/fs_config for more details.
- */
-
-#if !defined(EXCLUDE_FS_CONFIG_STRUCTURES)
-
-struct fs_path_config {
- unsigned mode;
- unsigned uid;
- unsigned gid;
- uint64_t capabilities;
- const char *prefix;
-};
-
-/* Rules for directories and files has moved to system/code/libcutils/fs_config.c */
-
-__BEGIN_DECLS
-
-/*
- * Used in:
- * build/tools/fs_config/fs_config.c
- * build/tools/fs_get_stats/fs_get_stats.c
- * system/extras/ext4_utils/make_ext4fs_main.c
- * external/squashfs-tools/squashfs-tools/android.c
- * system/core/cpio/mkbootfs.c
- * system/core/adb/file_sync_service.cpp
- * system/extras/ext4_utils/canned_fs_config.c
- */
-void fs_config(const char *path, int dir, const char *target_out_path,
- unsigned *uid, unsigned *gid, unsigned *mode, uint64_t *capabilities);
-
-ssize_t fs_config_generate(char *buffer, size_t length, const struct fs_path_config *pc);
-
-__END_DECLS
-
-#endif
-#endif
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
new file mode 120000
index 0000000..f28a564
--- /dev/null
+++ b/include/private/android_filesystem_config.h
@@ -0,0 +1 @@
+../../libcutils/include/private/android_filesystem_config.h
\ No newline at end of file
diff --git a/include/private/canned_fs_config.h b/include/private/canned_fs_config.h
new file mode 120000
index 0000000..8f92b2d
--- /dev/null
+++ b/include/private/canned_fs_config.h
@@ -0,0 +1 @@
+../../libcutils/include/private/canned_fs_config.h
\ No newline at end of file
diff --git a/init/Android.mk b/init/Android.mk
index d48f152..c82a19e 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -77,6 +77,7 @@
init.cpp \
keychords.cpp \
property_service.cpp \
+ reboot.cpp \
signal_handler.cpp \
ueventd.cpp \
ueventd_parser.cpp \
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 43eb378..24875d5 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -64,6 +64,7 @@
#include "init_parser.h"
#include "log.h"
#include "property_service.h"
+#include "reboot.h"
#include "service.h"
#include "signal_handler.h"
#include "util.h"
@@ -71,7 +72,6 @@
using namespace std::literals::string_literals;
#define chmod DO_NOT_USE_CHMOD_USE_FCHMODAT_SYMLINK_NOFOLLOW
-#define UNMOUNT_CHECK_TIMES 10
static constexpr std::chrono::nanoseconds kCommandRetryTimeout = 5s;
@@ -116,114 +116,14 @@
return ret;
}
-// Turn off backlight while we are performing power down cleanup activities.
-static void turnOffBacklight() {
- static const char off[] = "0";
-
- android::base::WriteStringToFile(off, "/sys/class/leds/lcd-backlight/brightness");
-
- static const char backlightDir[] = "/sys/class/backlight";
- std::unique_ptr<DIR, int(*)(DIR*)> dir(opendir(backlightDir), closedir);
- if (!dir) {
- return;
- }
-
- struct dirent *dp;
- while ((dp = readdir(dir.get())) != NULL) {
- if (((dp->d_type != DT_DIR) && (dp->d_type != DT_LNK)) ||
- (dp->d_name[0] == '.')) {
- continue;
- }
-
- std::string fileName = android::base::StringPrintf("%s/%s/brightness",
- backlightDir,
- dp->d_name);
- android::base::WriteStringToFile(off, fileName);
- }
-}
-
static int reboot_into_recovery(const std::vector<std::string>& options) {
std::string err;
if (!write_bootloader_message(options, &err)) {
LOG(ERROR) << "failed to set bootloader message: " << err;
return -1;
}
- reboot("recovery");
-}
-
-static void unmount_and_fsck(const struct mntent *entry) {
- if (strcmp(entry->mnt_type, "f2fs") && strcmp(entry->mnt_type, "ext4"))
- return;
-
- /* First, lazily unmount the directory. This unmount request finishes when
- * all processes that open a file or directory in |entry->mnt_dir| exit.
- */
- TEMP_FAILURE_RETRY(umount2(entry->mnt_dir, MNT_DETACH));
-
- /* Next, kill all processes except init, kthreadd, and kthreadd's
- * children to finish the lazy unmount. Killing all processes here is okay
- * because this callback function is only called right before reboot().
- * It might be cleaner to selectively kill processes that actually use
- * |entry->mnt_dir| rather than killing all, probably by reusing a function
- * like killProcessesWithOpenFiles() in vold/, but the selinux policy does
- * not allow init to scan /proc/<pid> files which the utility function
- * heavily relies on. The policy does not allow the process to execute
- * killall/pkill binaries either. Note that some processes might
- * automatically restart after kill(), but that is not really a problem
- * because |entry->mnt_dir| is no longer visible to such new processes.
- */
- ServiceManager::GetInstance().ForEachService([] (Service* s) { s->Stop(); });
- TEMP_FAILURE_RETRY(kill(-1, SIGKILL));
-
- // Restart Watchdogd to allow us to complete umounting and fsck
- Service *svc = ServiceManager::GetInstance().FindServiceByName("watchdogd");
- if (svc) {
- do {
- sched_yield(); // do not be so eager, let cleanup have priority
- ServiceManager::GetInstance().ReapAnyOutstandingChildren();
- } while (svc->flags() & SVC_RUNNING); // Paranoid Cargo
- svc->Start();
- }
-
- turnOffBacklight();
-
- int count = 0;
- while (count++ < UNMOUNT_CHECK_TIMES) {
- int fd = TEMP_FAILURE_RETRY(open(entry->mnt_fsname, O_RDONLY | O_EXCL));
- if (fd >= 0) {
- /* |entry->mnt_dir| has sucessfully been unmounted. */
- close(fd);
- break;
- } else if (errno == EBUSY) {
- // Some processes using |entry->mnt_dir| are still alive. Wait for a
- // while then retry.
- std::this_thread::sleep_for(5000ms / UNMOUNT_CHECK_TIMES);
- continue;
- } else {
- /* Cannot open the device. Give up. */
- return;
- }
- }
-
- // NB: With watchdog still running, there is no cap on the time it takes
- // to complete the fsck, from the users perspective the device graphics
- // and responses are locked-up and they may choose to hold the power
- // button in frustration if it drags out.
-
- int st;
- if (!strcmp(entry->mnt_type, "f2fs")) {
- const char *f2fs_argv[] = {
- "/system/bin/fsck.f2fs", "-f", entry->mnt_fsname,
- };
- android_fork_execvp_ext(arraysize(f2fs_argv), (char **)f2fs_argv,
- &st, true, LOG_KLOG, true, NULL, NULL, 0);
- } else if (!strcmp(entry->mnt_type, "ext4")) {
- const char *ext4_argv[] = {
- "/system/bin/e2fsck", "-f", "-y", entry->mnt_fsname,
- };
- android_fork_execvp_ext(arraysize(ext4_argv), (char **)ext4_argv,
- &st, true, LOG_KLOG, true, NULL, NULL, 0);
- }
+ DoReboot(ANDROID_RB_RESTART2, "reboot", "recovery", false);
+ return 0;
}
static int do_class_start(const std::vector<std::string>& args) {
@@ -706,86 +606,51 @@
}
static int do_powerctl(const std::vector<std::string>& args) {
- const char* command = args[1].c_str();
- int len = 0;
+ const std::string& command = args[1];
unsigned int cmd = 0;
- const char *reboot_target = "";
- void (*callback_on_ro_remount)(const struct mntent*) = NULL;
+ std::vector<std::string> cmd_params = android::base::Split(command, ",");
+ std::string reason_string = cmd_params[0];
+ std::string reboot_target = "";
+ bool runFsck = false;
+ bool commandInvalid = false;
- if (strncmp(command, "shutdown", 8) == 0) {
+ if (cmd_params.size() > 2) {
+ commandInvalid = true;
+ } else if (cmd_params[0] == "shutdown") {
cmd = ANDROID_RB_POWEROFF;
- len = 8;
- } else if (strncmp(command, "reboot", 6) == 0) {
+ if (cmd_params.size() == 2 && cmd_params[1] == "userrequested") {
+ // The shutdown reason is PowerManager.SHUTDOWN_USER_REQUESTED.
+ // Run fsck once the file system is remounted in read-only mode.
+ runFsck = true;
+ reason_string = cmd_params[1];
+ }
+ } else if (cmd_params[0] == "reboot") {
cmd = ANDROID_RB_RESTART2;
- len = 6;
- } else if (strncmp(command, "thermal-shutdown", 16) == 0) {
+ if (cmd_params.size() == 2) {
+ reboot_target = cmd_params[1];
+ // When rebooting to the bootloader notify the bootloader writing
+ // also the BCB.
+ if (reboot_target == "bootloader") {
+ std::string err;
+ if (!write_reboot_bootloader(&err)) {
+ LOG(ERROR) << "reboot-bootloader: Error writing "
+ "bootloader_message: "
+ << err;
+ }
+ }
+ }
+ } else if (command == "thermal-shutdown") { // no additional parameter allowed
cmd = ANDROID_RB_THERMOFF;
- len = 16;
} else {
+ commandInvalid = true;
+ }
+ if (commandInvalid) {
LOG(ERROR) << "powerctl: unrecognized command '" << command << "'";
return -EINVAL;
}
- if (command[len] == ',') {
- if (cmd == ANDROID_RB_POWEROFF &&
- !strcmp(&command[len + 1], "userrequested")) {
- // The shutdown reason is PowerManager.SHUTDOWN_USER_REQUESTED.
- // Run fsck once the file system is remounted in read-only mode.
- callback_on_ro_remount = unmount_and_fsck;
- } else if (cmd == ANDROID_RB_RESTART2) {
- reboot_target = &command[len + 1];
- // When rebooting to the bootloader notify the bootloader writing
- // also the BCB.
- if (strcmp(reboot_target, "bootloader") == 0) {
- std::string err;
- if (!write_reboot_bootloader(&err)) {
- LOG(ERROR) << "reboot-bootloader: Error writing "
- "bootloader_message: " << err;
- }
- }
- }
- } else if (command[len] != '\0') {
- LOG(ERROR) << "powerctl: unrecognized reboot target '" << &command[len] << "'";
- return -EINVAL;
- }
-
- std::string timeout = property_get("ro.build.shutdown_timeout");
- unsigned int delay = 0;
-
- if (android::base::ParseUint(timeout, &delay) && delay > 0) {
- Timer t;
- // Ask all services to terminate.
- ServiceManager::GetInstance().ForEachService(
- [] (Service* s) { s->Terminate(); });
-
- while (t.duration_s() < delay) {
- ServiceManager::GetInstance().ReapAnyOutstandingChildren();
-
- int service_count = 0;
- ServiceManager::GetInstance().ForEachService(
- [&service_count] (Service* s) {
- // Count the number of services running.
- // Exclude the console as it will ignore the SIGTERM signal
- // and not exit.
- // Note: SVC_CONSOLE actually means "requires console" but
- // it is only used by the shell.
- if (s->pid() != 0 && (s->flags() & SVC_CONSOLE) == 0) {
- service_count++;
- }
- });
-
- if (service_count == 0) {
- // All terminable services terminated. We can exit early.
- break;
- }
-
- // Wait a bit before recounting the number or running services.
- std::this_thread::sleep_for(50ms);
- }
- LOG(VERBOSE) << "Terminating running services took " << t;
- }
-
- return android_reboot_with_callback(cmd, 0, reboot_target, callback_on_ro_remount);
+ DoReboot(cmd, reason_string, reboot_target, runFsck);
+ return 0;
}
static int do_trigger(const std::vector<std::string>& args) {
diff --git a/init/reboot.cpp b/init/reboot.cpp
new file mode 100644
index 0000000..3e2d61e
--- /dev/null
+++ b/init/reboot.cpp
@@ -0,0 +1,413 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <dirent.h>
+#include <fcntl.h>
+#include <mntent.h>
+#include <sys/cdefs.h>
+#include <sys/mount.h>
+#include <sys/quota.h>
+#include <sys/reboot.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+#include <memory>
+#include <string>
+#include <thread>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/macros.h>
+#include <android-base/parseint.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#include <bootloader_message/bootloader_message.h>
+#include <cutils/android_reboot.h>
+#include <cutils/partition_utils.h>
+#include <fs_mgr.h>
+#include <logwrap/logwrap.h>
+
+#include "log.h"
+#include "property_service.h"
+#include "reboot.h"
+#include "service.h"
+#include "util.h"
+
+using android::base::StringPrintf;
+
+// represents umount status during reboot / shutdown.
+enum UmountStat {
+ /* umount succeeded. */
+ UMOUNT_STAT_SUCCESS = 0,
+ /* umount was not run. */
+ UMOUNT_STAT_SKIPPED = 1,
+ /* umount failed with timeout. */
+ UMOUNT_STAT_TIMEOUT = 2,
+ /* could not run due to error */
+ UMOUNT_STAT_ERROR = 3,
+ /* not used by init but reserved for other part to use this to represent the
+ the state where umount status before reboot is not found / available. */
+ UMOUNT_STAT_NOT_AVAILABLE = 4,
+};
+
+// Utility for struct mntent
+class MountEntry {
+ public:
+ explicit MountEntry(const mntent& entry, bool isMounted = true)
+ : mnt_fsname_(entry.mnt_fsname),
+ mnt_dir_(entry.mnt_dir),
+ mnt_type_(entry.mnt_type),
+ is_mounted_(isMounted) {}
+
+ bool IsF2Fs() const { return mnt_type_ == "f2fs"; }
+
+ bool IsExt4() const { return mnt_type_ == "ext4"; }
+
+ bool is_mounted() const { return is_mounted_; }
+
+ void set_is_mounted() { is_mounted_ = false; }
+
+ const std::string& mnt_fsname() const { return mnt_fsname_; }
+
+ const std::string& mnt_dir() const { return mnt_dir_; }
+
+ static bool IsBlockDevice(const struct mntent& mntent) {
+ return android::base::StartsWith(mntent.mnt_fsname, "/dev/block");
+ }
+
+ static bool IsEmulatedDevice(const struct mntent& mntent) {
+ static const std::string SDCARDFS_NAME = "sdcardfs";
+ return android::base::StartsWith(mntent.mnt_fsname, "/data/") &&
+ SDCARDFS_NAME == mntent.mnt_type;
+ }
+
+ private:
+ std::string mnt_fsname_;
+ std::string mnt_dir_;
+ std::string mnt_type_;
+ bool is_mounted_;
+};
+
+// Turn off backlight while we are performing power down cleanup activities.
+static void TurnOffBacklight() {
+ static constexpr char OFF[] = "0";
+
+ android::base::WriteStringToFile(OFF, "/sys/class/leds/lcd-backlight/brightness");
+
+ static const char backlightDir[] = "/sys/class/backlight";
+ std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(backlightDir), closedir);
+ if (!dir) {
+ return;
+ }
+
+ struct dirent* dp;
+ while ((dp = readdir(dir.get())) != nullptr) {
+ if (((dp->d_type != DT_DIR) && (dp->d_type != DT_LNK)) || (dp->d_name[0] == '.')) {
+ continue;
+ }
+
+ std::string fileName = StringPrintf("%s/%s/brightness", backlightDir, dp->d_name);
+ android::base::WriteStringToFile(OFF, fileName);
+ }
+}
+
+static void DoFsck(const MountEntry& entry) {
+ static constexpr int UNMOUNT_CHECK_TIMES = 10;
+
+ if (!entry.IsF2Fs() && !entry.IsExt4()) return;
+
+ int count = 0;
+ while (count++ < UNMOUNT_CHECK_TIMES) {
+ int fd = TEMP_FAILURE_RETRY(open(entry.mnt_fsname().c_str(), O_RDONLY | O_EXCL));
+ if (fd >= 0) {
+ /* |entry->mnt_dir| has sucessfully been unmounted. */
+ close(fd);
+ break;
+ } else if (errno == EBUSY) {
+ // Some processes using |entry->mnt_dir| are still alive. Wait for a
+ // while then retry.
+ std::this_thread::sleep_for(5000ms / UNMOUNT_CHECK_TIMES);
+ continue;
+ } else {
+ /* Cannot open the device. Give up. */
+ return;
+ }
+ }
+
+ // NB: With watchdog still running, there is no cap on the time it takes
+ // to complete the fsck, from the users perspective the device graphics
+ // and responses are locked-up and they may choose to hold the power
+ // button in frustration if it drags out.
+
+ int st;
+ if (entry.IsF2Fs()) {
+ const char* f2fs_argv[] = {
+ "/system/bin/fsck.f2fs", "-f", entry.mnt_fsname().c_str(),
+ };
+ android_fork_execvp_ext(arraysize(f2fs_argv), (char**)f2fs_argv, &st, true, LOG_KLOG, true,
+ nullptr, nullptr, 0);
+ } else if (entry.IsExt4()) {
+ const char* ext4_argv[] = {
+ "/system/bin/e2fsck", "-f", "-y", entry.mnt_fsname().c_str(),
+ };
+ android_fork_execvp_ext(arraysize(ext4_argv), (char**)ext4_argv, &st, true, LOG_KLOG, true,
+ nullptr, nullptr, 0);
+ }
+}
+
+static void ShutdownVold() {
+ const char* vdc_argv[] = {"/system/bin/vdc", "volume", "shutdown"};
+ int status;
+ android_fork_execvp_ext(arraysize(vdc_argv), (char**)vdc_argv, &status, true, LOG_KLOG, true,
+ nullptr, nullptr, 0);
+}
+
+static void LogShutdownTime(UmountStat stat, Timer* t) {
+ LOG(WARNING) << "powerctl_shutdown_time_ms:" << std::to_string(t->duration_ms()) << ":" << stat;
+}
+
+static void __attribute__((noreturn))
+RebootSystem(unsigned int cmd, const std::string& rebootTarget) {
+ switch (cmd) {
+ case ANDROID_RB_POWEROFF:
+ reboot(RB_POWER_OFF);
+ break;
+
+ case ANDROID_RB_RESTART2:
+ syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
+ LINUX_REBOOT_CMD_RESTART2, rebootTarget.c_str());
+ break;
+
+ case ANDROID_RB_THERMOFF:
+ reboot(RB_POWER_OFF);
+ break;
+ }
+ // In normal case, reboot should not return.
+ PLOG(FATAL) << "reboot call returned";
+ abort();
+}
+
+/* Find all read+write block devices and emulated devices in /proc/mounts
+ * and add them to correpsponding list.
+ */
+static bool FindPartitionsToUmount(std::vector<MountEntry>* blockDevPartitions,
+ std::vector<MountEntry>* emulatedPartitions) {
+ std::unique_ptr<std::FILE, int (*)(std::FILE*)> fp(setmntent("/proc/mounts", "r"), endmntent);
+ if (fp == nullptr) {
+ PLOG(ERROR) << "Failed to open /proc/mounts";
+ return false;
+ }
+ mntent* mentry;
+ while ((mentry = getmntent(fp.get())) != nullptr) {
+ if (MountEntry::IsBlockDevice(*mentry) && hasmntopt(mentry, "rw")) {
+ blockDevPartitions->emplace_back(*mentry);
+ } else if (MountEntry::IsEmulatedDevice(*mentry)) {
+ emulatedPartitions->emplace_back(*mentry);
+ }
+ }
+ return true;
+}
+
+static bool UmountPartitions(std::vector<MountEntry>* partitions, int maxRetry, int flags) {
+ static constexpr int SLEEP_AFTER_RETRY_US = 100000;
+
+ bool umountDone;
+ int retryCounter = 0;
+
+ while (true) {
+ umountDone = true;
+ for (auto& entry : *partitions) {
+ if (entry.is_mounted()) {
+ int r = umount2(entry.mnt_dir().c_str(), flags);
+ if (r == 0) {
+ entry.set_is_mounted();
+ LOG(INFO) << StringPrintf("umounted %s, flags:0x%x", entry.mnt_fsname().c_str(),
+ flags);
+ } else {
+ umountDone = false;
+ PLOG(WARNING) << StringPrintf("cannot umount %s, flags:0x%x",
+ entry.mnt_fsname().c_str(), flags);
+ }
+ }
+ }
+ if (umountDone) break;
+ retryCounter++;
+ if (retryCounter >= maxRetry) break;
+ usleep(SLEEP_AFTER_RETRY_US);
+ }
+ return umountDone;
+}
+
+/* Try umounting all emulated file systems R/W block device cfile systems.
+ * This will just try umount and give it up if it fails.
+ * For fs like ext4, this is ok as file system will be marked as unclean shutdown
+ * and necessary check can be done at the next reboot.
+ * For safer shutdown, caller needs to make sure that
+ * all processes / emulated partition for the target fs are all cleaned-up.
+ *
+ * return true when umount was successful. false when timed out.
+ */
+static UmountStat TryUmountAndFsck(bool runFsck) {
+ std::vector<MountEntry> emulatedPartitions;
+ std::vector<MountEntry> blockDevRwPartitions;
+
+ TurnOffBacklight(); // this part can take time. save power.
+
+ if (!FindPartitionsToUmount(&blockDevRwPartitions, &emulatedPartitions)) {
+ return UMOUNT_STAT_ERROR;
+ }
+ if (emulatedPartitions.size() > 0) {
+ LOG(WARNING) << "emulated partitions still exist, will umount";
+ /* Pending writes in emulated partitions can fail umount. After a few trials, detach
+ * it so that it can be umounted when all writes are done.
+ */
+ if (!UmountPartitions(&emulatedPartitions, 1, 0)) {
+ UmountPartitions(&emulatedPartitions, 1, MNT_DETACH);
+ }
+ }
+ UmountStat stat = UMOUNT_STAT_SUCCESS;
+ /* data partition needs all pending writes to be completed and all emulated partitions
+ * umounted. If umount failed in the above step, it DETACH is requested, so umount can
+ * still happen while waiting for /data. If the current waiting is not good enough, give
+ * up and leave it to e2fsck after reboot to fix it.
+ */
+ /* TODO update max waiting time based on usage data */
+ if (!UmountPartitions(&blockDevRwPartitions, 100, 0)) {
+ /* Last resort, detach and hope it finish before shutdown. */
+ UmountPartitions(&blockDevRwPartitions, 1, MNT_DETACH);
+ stat = UMOUNT_STAT_TIMEOUT;
+ }
+ if (stat == UMOUNT_STAT_SUCCESS && runFsck) {
+ for (auto& entry : blockDevRwPartitions) {
+ DoFsck(entry);
+ }
+ }
+
+ return stat;
+}
+
+static void DoSync() {
+ // quota sync is not done by sync cal, so should be done separately.
+ // quota sync is in VFS level, so do it before sync, which goes down to fs level.
+ int r = quotactl(QCMD(Q_SYNC, 0), nullptr, 0 /* do not care */, 0 /* do not care */);
+ if (r < 0) {
+ PLOG(ERROR) << "quotactl failed";
+ }
+ sync();
+}
+
+static void __attribute__((noreturn)) DoThermalOff() {
+ LOG(WARNING) << "Thermal system shutdown";
+ DoSync();
+ RebootSystem(ANDROID_RB_THERMOFF, "");
+ abort();
+}
+
+void DoReboot(unsigned int cmd, const std::string& reason, const std::string& rebootTarget,
+ bool runFsck) {
+ Timer t;
+ std::string timeout = property_get("ro.build.shutdown_timeout");
+ unsigned int delay = 0;
+
+ if (!android::base::ParseUint(timeout, &delay)) {
+ delay = 3; // force service termination by default
+ }
+
+ android::base::WriteStringToFile(StringPrintf("%s\n", reason.c_str()), LAST_REBOOT_REASON_FILE);
+
+ if (cmd == ANDROID_RB_THERMOFF) { // do not wait if it is thermal
+ DoThermalOff();
+ abort();
+ }
+ static const constexpr char* shutdown_critical_services[] = {"vold", "watchdogd"};
+ for (const char* name : shutdown_critical_services) {
+ Service* s = ServiceManager::GetInstance().FindServiceByName(name);
+ if (s == nullptr) {
+ LOG(WARNING) << "Shutdown critical service not found:" << name;
+ continue;
+ }
+ s->Start(); // make sure that it is running.
+ s->SetShutdownCritical();
+ }
+ // optional shutdown step
+ // 1. terminate all services except shutdown critical ones. wait for delay to finish
+ if (delay > 0) {
+ LOG(INFO) << "terminating init services";
+ // tombstoned can write to data when other services are killed. so finish it first.
+ static const constexpr char* first_to_kill[] = {"tombstoned"};
+ for (const char* name : first_to_kill) {
+ Service* s = ServiceManager::GetInstance().FindServiceByName(name);
+ if (s != nullptr) s->Stop();
+ }
+
+ // Ask all services to terminate except shutdown critical ones.
+ ServiceManager::GetInstance().ForEachService([](Service* s) {
+ if (!s->IsShutdownCritical()) s->Terminate();
+ });
+
+ int service_count = 0;
+ while (t.duration_s() < delay) {
+ ServiceManager::GetInstance().ReapAnyOutstandingChildren();
+
+ service_count = 0;
+ ServiceManager::GetInstance().ForEachService([&service_count](Service* s) {
+ // Count the number of services running except shutdown critical.
+ // Exclude the console as it will ignore the SIGTERM signal
+ // and not exit.
+ // Note: SVC_CONSOLE actually means "requires console" but
+ // it is only used by the shell.
+ if (!s->IsShutdownCritical() && s->pid() != 0 && (s->flags() & SVC_CONSOLE) == 0) {
+ service_count++;
+ }
+ });
+
+ if (service_count == 0) {
+ // All terminable services terminated. We can exit early.
+ break;
+ }
+
+ // Wait a bit before recounting the number or running services.
+ std::this_thread::sleep_for(50ms);
+ }
+ LOG(INFO) << "Terminating running services took " << t
+ << " with remaining services:" << service_count;
+ }
+
+ // minimum safety steps before restarting
+ // 2. kill all services except ones that are necessary for the shutdown sequence.
+ ServiceManager::GetInstance().ForEachService([](Service* s) {
+ if (!s->IsShutdownCritical()) s->Stop();
+ });
+ ServiceManager::GetInstance().ReapAnyOutstandingChildren();
+
+ // 3. send volume shutdown to vold
+ Service* voldService = ServiceManager::GetInstance().FindServiceByName("vold");
+ if (voldService != nullptr && voldService->IsRunning()) {
+ ShutdownVold();
+ voldService->Terminate();
+ } else {
+ LOG(INFO) << "vold not running, skipping vold shutdown";
+ }
+
+ // 4. sync, try umount, and optionally run fsck for user shutdown
+ DoSync();
+ UmountStat stat = TryUmountAndFsck(runFsck);
+ LogShutdownTime(stat, &t);
+ // Reboot regardless of umount status. If umount fails, fsck after reboot will fix it.
+ RebootSystem(cmd, rebootTarget);
+ abort();
+}
diff --git a/init/reboot.h b/init/reboot.h
new file mode 100644
index 0000000..3956249
--- /dev/null
+++ b/init/reboot.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _INIT_REBOOT_H
+#define _INIT_REBOOT_H
+
+/* Reboot / shutdown the system.
+ * cmd ANDROID_RB_* as defined in android_reboot.h
+ * reason Reason string like "reboot", "userrequested"
+ * rebootTarget Reboot target string like "bootloader". Otherwise, it should be an
+ * empty string.
+ * runFsck Whether to run fsck after umount is done.
+ */
+void DoReboot(unsigned int cmd, const std::string& reason, const std::string& rebootTarget,
+ bool runFsck) __attribute__((__noreturn__));
+
+#endif
diff --git a/init/service.h b/init/service.h
index 013e65f..08388e2 100644
--- a/init/service.h
+++ b/init/service.h
@@ -32,18 +32,21 @@
#include "keyword_map.h"
#include "util.h"
-#define SVC_DISABLED 0x001 // do not autostart with class
-#define SVC_ONESHOT 0x002 // do not restart on exit
-#define SVC_RUNNING 0x004 // currently active
-#define SVC_RESTARTING 0x008 // waiting to restart
-#define SVC_CONSOLE 0x010 // requires console
-#define SVC_CRITICAL 0x020 // will reboot into recovery if keeps crashing
-#define SVC_RESET 0x040 // Use when stopping a process,
+#define SVC_DISABLED 0x001 // do not autostart with class
+#define SVC_ONESHOT 0x002 // do not restart on exit
+#define SVC_RUNNING 0x004 // currently active
+#define SVC_RESTARTING 0x008 // waiting to restart
+#define SVC_CONSOLE 0x010 // requires console
+#define SVC_CRITICAL 0x020 // will reboot into recovery if keeps crashing
+#define SVC_RESET 0x040 // Use when stopping a process,
// but not disabling so it can be restarted with its class.
-#define SVC_RC_DISABLED 0x080 // Remember if the disabled flag was set in the rc script.
-#define SVC_RESTART 0x100 // Use to safely restart (stop, wait, start) a service.
+#define SVC_RC_DISABLED 0x080 // Remember if the disabled flag was set in the rc script.
+#define SVC_RESTART 0x100 // Use to safely restart (stop, wait, start) a service.
#define SVC_DISABLED_START 0x200 // A start was requested but it was disabled at the time.
-#define SVC_EXEC 0x400 // This synthetic service corresponds to an 'exec'.
+#define SVC_EXEC 0x400 // This synthetic service corresponds to an 'exec'.
+
+#define SVC_SHUTDOWN_CRITICAL 0x800 // This service is critical for shutdown and
+ // should not be killed during shutdown
#define NR_SVC_SUPP_GIDS 12 // twelve supplementary groups
@@ -68,6 +71,7 @@
unsigned namespace_flags, const std::string& seclabel,
const std::vector<std::string>& args);
+ bool IsRunning() { return (flags_ & SVC_RUNNING) != 0; }
bool ParseLine(const std::vector<std::string>& args, std::string* err);
bool Start();
bool StartIfNotDisabled();
@@ -79,6 +83,8 @@
void RestartIfNeeded(time_t* process_needs_restart_at);
bool Reap();
void DumpState() const;
+ void SetShutdownCritical() { flags_ |= SVC_SHUTDOWN_CRITICAL; }
+ bool IsShutdownCritical() { return (flags_ & SVC_SHUTDOWN_CRITICAL) != 0; }
const std::string& name() const { return name_; }
const std::string& classname() const { return classname_; }
diff --git a/init/util.cpp b/init/util.cpp
index c987181..b90e5b1 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -49,6 +49,7 @@
#include "init.h"
#include "log.h"
#include "property_service.h"
+#include "reboot.h"
#include "util.h"
static unsigned int do_decode_uid(const char *s)
@@ -410,18 +411,9 @@
return true;
}
-void reboot(const char* destination) {
- android_reboot(ANDROID_RB_RESTART2, 0, destination);
- // We're init, so android_reboot will actually have been a syscall so there's nothing
- // to wait for. If android_reboot returns, just abort so that the kernel will reboot
- // itself when init dies.
- PLOG(FATAL) << "reboot failed";
- abort();
-}
-
void panic() {
LOG(ERROR) << "panic: rebooting to bootloader";
- reboot("bootloader");
+ DoReboot(ANDROID_RB_RESTART2, "reboot", "bootloader", false);
}
std::ostream& operator<<(std::ostream& os, const Timer& t) {
diff --git a/init/util.h b/init/util.h
index 5c38dc3..81c64d7 100644
--- a/init/util.h
+++ b/init/util.h
@@ -78,7 +78,6 @@
bool is_dir(const char* pathname);
bool expand_props(const std::string& src, std::string* dst);
-void reboot(const char* destination) __attribute__((__noreturn__));
void panic() __attribute__((__noreturn__));
#endif
diff --git a/libcutils/android_reboot.c b/libcutils/android_reboot.c
index 06026d1..a33e45f 100644
--- a/libcutils/android_reboot.c
+++ b/libcutils/android_reboot.c
@@ -13,259 +13,39 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-#include <errno.h>
-#include <fcntl.h>
-#include <mntent.h>
-#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
-#include <sys/cdefs.h>
-#include <sys/mount.h>
-#include <sys/reboot.h>
-#include <sys/stat.h>
-#include <sys/syscall.h>
-#include <sys/types.h>
-#include <unistd.h>
#include <cutils/android_reboot.h>
-#include <cutils/klog.h>
-#include <cutils/list.h>
+#include <cutils/properties.h>
#define TAG "android_reboot"
-#define READONLY_CHECK_MS 5000
-#define READONLY_CHECK_TIMES 50
-typedef struct {
- struct listnode list;
- struct mntent entry;
-} mntent_list;
-
-static bool is_block_device(const char* fsname)
-{
- return !strncmp(fsname, "/dev/block", 10);
-}
-
-/* Find all read+write block devices in /proc/mounts and add them to
- * |rw_entries|.
- */
-static void find_rw(struct listnode* rw_entries)
-{
- FILE* fp;
- struct mntent* mentry;
-
- if ((fp = setmntent("/proc/mounts", "r")) == NULL) {
- KLOG_WARNING(TAG, "Failed to open /proc/mounts.\n");
- return;
- }
- while ((mentry = getmntent(fp)) != NULL) {
- if (is_block_device(mentry->mnt_fsname) && hasmntopt(mentry, "rw")) {
- mntent_list* item = (mntent_list*)calloc(1, sizeof(mntent_list));
- item->entry = *mentry;
- item->entry.mnt_fsname = strdup(mentry->mnt_fsname);
- item->entry.mnt_dir = strdup(mentry->mnt_dir);
- item->entry.mnt_type = strdup(mentry->mnt_type);
- item->entry.mnt_opts = strdup(mentry->mnt_opts);
- list_add_tail(rw_entries, &item->list);
- }
- }
- endmntent(fp);
-}
-
-static void free_entries(struct listnode* entries)
-{
- struct listnode* node;
- struct listnode* n;
- list_for_each_safe(node, n, entries) {
- mntent_list* item = node_to_item(node, mntent_list, list);
- free(item->entry.mnt_fsname);
- free(item->entry.mnt_dir);
- free(item->entry.mnt_type);
- free(item->entry.mnt_opts);
- free(item);
- }
-}
-
-static mntent_list* find_item(struct listnode* rw_entries, const char* fsname_to_find)
-{
- struct listnode* node;
- list_for_each(node, rw_entries) {
- mntent_list* item = node_to_item(node, mntent_list, list);
- if (!strcmp(item->entry.mnt_fsname, fsname_to_find)) {
- return item;
- }
- }
- return NULL;
-}
-
-/* Remounting filesystems read-only is difficult when there are files
- * opened for writing or pending deletes on the filesystem. There is
- * no way to force the remount with the mount(2) syscall. The magic sysrq
- * 'u' command does an emergency remount read-only on all writable filesystems
- * that have a block device (i.e. not tmpfs filesystems) by calling
- * emergency_remount(), which knows how to force the remount to read-only.
- * Unfortunately, that is asynchronous, and just schedules the work and
- * returns. The best way to determine if it is done is to read /proc/mounts
- * repeatedly until there are no more writable filesystems mounted on
- * block devices.
- */
-static void remount_ro(void (*cb_on_remount)(const struct mntent*))
-{
- int fd, cnt;
- FILE* fp;
- struct mntent* mentry;
- struct listnode* node;
-
- list_declare(rw_entries);
- list_declare(ro_entries);
-
- sync();
- find_rw(&rw_entries);
-
- /* Trigger the remount of the filesystems as read-only,
- * which also marks them clean.
- */
- fd = TEMP_FAILURE_RETRY(open("/proc/sysrq-trigger", O_WRONLY));
- if (fd < 0) {
- KLOG_WARNING(TAG, "Failed to open sysrq-trigger.\n");
- /* TODO: Try to remount each rw parition manually in readonly mode.
- * This may succeed if no process is using the partition.
- */
- goto out;
- }
- if (TEMP_FAILURE_RETRY(write(fd, "u", 1)) != 1) {
- close(fd);
- KLOG_WARNING(TAG, "Failed to write to sysrq-trigger.\n");
- /* TODO: The same. Manually remount the paritions. */
- goto out;
- }
- close(fd);
-
- /* Now poll /proc/mounts till it's done */
- cnt = 0;
- while (cnt < READONLY_CHECK_TIMES) {
- if ((fp = setmntent("/proc/mounts", "r")) == NULL) {
- /* If we can't read /proc/mounts, just give up. */
- KLOG_WARNING(TAG, "Failed to open /proc/mounts.\n");
- goto out;
- }
- while ((mentry = getmntent(fp)) != NULL) {
- if (!is_block_device(mentry->mnt_fsname) || !hasmntopt(mentry, "ro")) {
- continue;
- }
- mntent_list* item = find_item(&rw_entries, mentry->mnt_fsname);
- if (item) {
- /* |item| has now been ro remounted. */
- list_remove(&item->list);
- list_add_tail(&ro_entries, &item->list);
- }
- }
- endmntent(fp);
- if (list_empty(&rw_entries)) {
- /* All rw block devices are now readonly. */
- break;
- }
- TEMP_FAILURE_RETRY(
- usleep(READONLY_CHECK_MS * 1000 / READONLY_CHECK_TIMES));
- cnt++;
- }
-
- list_for_each(node, &rw_entries) {
- mntent_list* item = node_to_item(node, mntent_list, list);
- KLOG_WARNING(TAG, "Failed to remount %s in readonly mode.\n",
- item->entry.mnt_fsname);
- }
-
- if (cb_on_remount) {
- list_for_each(node, &ro_entries) {
- mntent_list* item = node_to_item(node, mntent_list, list);
- cb_on_remount(&item->entry);
- }
- }
-
-out:
- free_entries(&rw_entries);
- free_entries(&ro_entries);
-}
-
-static void save_reboot_reason(int cmd, const char *arg)
-{
- FILE *fp;
- const char *reason = NULL;
-
- fp = fopen(LAST_REBOOT_REASON_FILE, "w");
- if (fp == NULL) {
- KLOG_WARNING(TAG, "Error creating " LAST_REBOOT_REASON_FILE
- ": %s\n", strerror(errno));
- return;
- }
- switch (cmd) {
- case ANDROID_RB_RESTART:
- reason = "restart";
- break;
-
- case ANDROID_RB_POWEROFF:
- reason = "power-off";
- break;
-
- case ANDROID_RB_RESTART2:
- reason = arg && strlen(arg) ? arg : "restart";
- break;
-
- case ANDROID_RB_THERMOFF:
- reason = "thermal-shutdown";
- break;
-
- default:
- fprintf(fp,"0x%08X\n", cmd);
- break;
- }
-
- if (reason) {
- if (fprintf(fp, "%s\n", reason) < 0) {
- KLOG_WARNING(TAG, "Error writing " LAST_REBOOT_REASON_FILE
- ": %s\n", strerror(errno));
- }
- }
-
- fclose(fp);
-}
-
-int android_reboot_with_callback(
- int cmd, int flags __unused, const char *arg,
- void (*cb_on_remount)(const struct mntent*))
-{
+int android_reboot(int cmd, int flags __unused, const char* arg) {
int ret;
+ const char* restart_cmd = NULL;
+ char* prop_value;
- save_reboot_reason(cmd, arg);
- remount_ro(cb_on_remount);
switch (cmd) {
- case ANDROID_RB_RESTART:
- ret = reboot(RB_AUTOBOOT);
- break;
-
- case ANDROID_RB_POWEROFF:
- ret = reboot(RB_POWER_OFF);
- break;
-
+ case ANDROID_RB_RESTART: // deprecated
case ANDROID_RB_RESTART2:
- ret = syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
- LINUX_REBOOT_CMD_RESTART2, arg);
+ restart_cmd = "reboot";
break;
-
+ case ANDROID_RB_POWEROFF:
+ restart_cmd = "shutdown";
+ break;
case ANDROID_RB_THERMOFF:
- ret = reboot(RB_POWER_OFF);
+ restart_cmd = "thermal-shutdown";
break;
-
- default:
- ret = -1;
}
-
+ if (!restart_cmd) return -1;
+ if (arg) {
+ ret = asprintf(&prop_value, "%s,%s", restart_cmd, arg);
+ } else {
+ ret = asprintf(&prop_value, "%s", restart_cmd);
+ }
+ if (ret < 0) return -1;
+ ret = property_set(ANDROID_RB_PROPERTY, prop_value);
+ free(prop_value);
return ret;
}
-
-int android_reboot(int cmd, int flags, const char *arg)
-{
- return android_reboot_with_callback(cmd, flags, arg, NULL);
-}
diff --git a/libcutils/include/cutils/android_reboot.h b/libcutils/include/cutils/android_reboot.h
index 2e3b429..716567a 100644
--- a/libcutils/include/cutils/android_reboot.h
+++ b/libcutils/include/cutils/android_reboot.h
@@ -17,12 +17,11 @@
#ifndef __CUTILS_ANDROID_REBOOT_H__
#define __CUTILS_ANDROID_REBOOT_H__
-#include <mntent.h>
__BEGIN_DECLS
/* Commands */
-#define ANDROID_RB_RESTART 0xDEAD0001
+#define ANDROID_RB_RESTART 0xDEAD0001 /* deprecated. Use RESTART2. */
#define ANDROID_RB_POWEROFF 0xDEAD0002
#define ANDROID_RB_RESTART2 0xDEAD0003
#define ANDROID_RB_THERMOFF 0xDEAD0004
@@ -33,10 +32,12 @@
/* Android reboot reason stored in this file */
#define LAST_REBOOT_REASON_FILE "/data/misc/reboot/last_reboot_reason"
+/* Reboot or shutdown the system.
+ * This call uses ANDROID_RB_PROPERTY to request reboot to init process.
+ * Due to that, process calling this should have proper selinux permission
+ * to write to the property. Otherwise, the call will fail.
+ */
int android_reboot(int cmd, int flags, const char *arg);
-int android_reboot_with_callback(
- int cmd, int flags, const char *arg,
- void (*cb_on_remount)(const struct mntent*));
__END_DECLS
diff --git a/include/private/android_filesystem_capability.h b/libcutils/include/private/android_filesystem_capability.h
similarity index 86%
rename from include/private/android_filesystem_capability.h
rename to libcutils/include/private/android_filesystem_capability.h
index b92d3db..0227b1d 100644
--- a/include/private/android_filesystem_capability.h
+++ b/libcutils/include/private/android_filesystem_capability.h
@@ -35,15 +35,15 @@
#define _LINUX_CAPABILITY_U32S_3 2
typedef struct __user_cap_header_struct {
- __u32 version;
- int pid;
-} __user *cap_user_header_t;
+ __u32 version;
+ int pid;
+} __user* cap_user_header_t;
typedef struct __user_cap_data_struct {
- __u32 effective;
- __u32 permitted;
- __u32 inheritable;
-} __user *cap_user_data_t;
+ __u32 effective;
+ __u32 permitted;
+ __u32 inheritable;
+} __user* cap_user_data_t;
#define VFS_CAP_REVISION_MASK 0xFF000000
#define VFS_CAP_REVISION_SHIFT 24
@@ -51,20 +51,20 @@
#define VFS_CAP_FLAGS_EFFECTIVE 0x000001
#define VFS_CAP_REVISION_1 0x01000000
#define VFS_CAP_U32_1 1
-#define XATTR_CAPS_SZ_1 (sizeof(__le32)*(1 + 2*VFS_CAP_U32_1))
+#define XATTR_CAPS_SZ_1 (sizeof(__le32) * (1 + 2 * VFS_CAP_U32_1))
#define VFS_CAP_REVISION_2 0x02000000
#define VFS_CAP_U32_2 2
-#define XATTR_CAPS_SZ_2 (sizeof(__le32)*(1 + 2*VFS_CAP_U32_2))
+#define XATTR_CAPS_SZ_2 (sizeof(__le32) * (1 + 2 * VFS_CAP_U32_2))
#define XATTR_CAPS_SZ XATTR_CAPS_SZ_2
#define VFS_CAP_U32 VFS_CAP_U32_2
#define VFS_CAP_REVISION VFS_CAP_REVISION_2
struct vfs_cap_data {
- __le32 magic_etc;
- struct {
- __le32 permitted;
- __le32 inheritable;
- } data[VFS_CAP_U32];
+ __le32 magic_etc;
+ struct {
+ __le32 permitted;
+ __le32 inheritable;
+ } data[VFS_CAP_U32];
};
#define _LINUX_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_1
@@ -110,7 +110,7 @@
#define CAP_LAST_CAP CAP_AUDIT_READ
#define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP)
#define CAP_TO_INDEX(x) ((x) >> 5)
-#define CAP_TO_MASK(x) (1 << ((x) & 31))
+#define CAP_TO_MASK(x) (1 << ((x)&31))
#undef __user
#undef __u32
diff --git a/libcutils/include/private/android_filesystem_config.h b/libcutils/include/private/android_filesystem_config.h
new file mode 100644
index 0000000..0037f15
--- /dev/null
+++ b/libcutils/include/private/android_filesystem_config.h
@@ -0,0 +1,223 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* This file is used to define the properties of the filesystem
+** images generated by build tools (mkbootfs and mkyaffs2image) and
+** by the device side of adb.
+*/
+
+/*
+ * This file is consumed by build/tools/fs_config and is used
+ * for generating various files. Anything #define AID_<name>
+ * becomes the mapping for getpwnam/getpwuid, etc. The <name>
+ * field is lowercased.
+ * For example:
+ * #define AID_FOO_BAR 6666 becomes a friendly name of "foo_bar"
+ *
+ * The above holds true with the exception of:
+ * mediacodec
+ * mediaex
+ * mediadrm
+ * Whose friendly names do not match the #define statements.
+ *
+ * Additionally, AID_OEM_RESERVED_START and AID_OEM_RESERVED_END
+ * can be used to define reserved OEM ranges used for sanity checks
+ * during the build process. The rules are, they must end with START/END
+ * The proper convention is incrementing a number like so:
+ * AID_OEM_RESERVED_START
+ * AID_OEM_RESERVED_1_START
+ * AID_OEM_RESERVED_2_START
+ * ...
+ * The same applies to the END.
+ * They are not required to be in order, but must not overlap each other and
+ * must define a START and END'ing range. START must be smaller than END.
+ */
+
+#ifndef _ANDROID_FILESYSTEM_CONFIG_H_
+#define _ANDROID_FILESYSTEM_CONFIG_H_
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#if defined(__ANDROID__)
+#include <linux/capability.h>
+#else
+#include "android_filesystem_capability.h"
+#endif
+
+#define CAP_MASK_LONG(cap_name) (1ULL << (cap_name))
+
+/* This is the master Users and Groups config for the platform.
+ * DO NOT EVER RENUMBER
+ */
+
+#define AID_ROOT 0 /* traditional unix root user */
+
+#define AID_SYSTEM 1000 /* system server */
+
+#define AID_RADIO 1001 /* telephony subsystem, RIL */
+#define AID_BLUETOOTH 1002 /* bluetooth subsystem */
+#define AID_GRAPHICS 1003 /* graphics devices */
+#define AID_INPUT 1004 /* input devices */
+#define AID_AUDIO 1005 /* audio devices */
+#define AID_CAMERA 1006 /* camera devices */
+#define AID_LOG 1007 /* log devices */
+#define AID_COMPASS 1008 /* compass device */
+#define AID_MOUNT 1009 /* mountd socket */
+#define AID_WIFI 1010 /* wifi subsystem */
+#define AID_ADB 1011 /* android debug bridge (adbd) */
+#define AID_INSTALL 1012 /* group for installing packages */
+#define AID_MEDIA 1013 /* mediaserver process */
+#define AID_DHCP 1014 /* dhcp client */
+#define AID_SDCARD_RW 1015 /* external storage write access */
+#define AID_VPN 1016 /* vpn system */
+#define AID_KEYSTORE 1017 /* keystore subsystem */
+#define AID_USB 1018 /* USB devices */
+#define AID_DRM 1019 /* DRM server */
+#define AID_MDNSR 1020 /* MulticastDNSResponder (service discovery) */
+#define AID_GPS 1021 /* GPS daemon */
+#define AID_UNUSED1 1022 /* deprecated, DO NOT USE */
+#define AID_MEDIA_RW 1023 /* internal media storage write access */
+#define AID_MTP 1024 /* MTP USB driver access */
+#define AID_UNUSED2 1025 /* deprecated, DO NOT USE */
+#define AID_DRMRPC 1026 /* group for drm rpc */
+#define AID_NFC 1027 /* nfc subsystem */
+#define AID_SDCARD_R 1028 /* external storage read access */
+#define AID_CLAT 1029 /* clat part of nat464 */
+#define AID_LOOP_RADIO 1030 /* loop radio devices */
+#define AID_MEDIA_DRM 1031 /* MediaDrm plugins */
+#define AID_PACKAGE_INFO 1032 /* access to installed package details */
+#define AID_SDCARD_PICS 1033 /* external storage photos access */
+#define AID_SDCARD_AV 1034 /* external storage audio/video access */
+#define AID_SDCARD_ALL 1035 /* access all users external storage */
+#define AID_LOGD 1036 /* log daemon */
+#define AID_SHARED_RELRO 1037 /* creator of shared GNU RELRO files */
+#define AID_DBUS 1038 /* dbus-daemon IPC broker process */
+#define AID_TLSDATE 1039 /* tlsdate unprivileged user */
+#define AID_MEDIA_EX 1040 /* mediaextractor process */
+#define AID_AUDIOSERVER 1041 /* audioserver process */
+#define AID_METRICS_COLL 1042 /* metrics_collector process */
+#define AID_METRICSD 1043 /* metricsd process */
+#define AID_WEBSERV 1044 /* webservd process */
+#define AID_DEBUGGERD 1045 /* debuggerd unprivileged user */
+#define AID_MEDIA_CODEC 1046 /* mediacodec process */
+#define AID_CAMERASERVER 1047 /* cameraserver process */
+#define AID_FIREWALL 1048 /* firewalld process */
+#define AID_TRUNKS 1049 /* trunksd process (TPM daemon) */
+#define AID_NVRAM 1050 /* Access-controlled NVRAM */
+#define AID_DNS 1051 /* DNS resolution daemon (system: netd) */
+#define AID_DNS_TETHER 1052 /* DNS resolution daemon (tether: dnsmasq) */
+#define AID_WEBVIEW_ZYGOTE 1053 /* WebView zygote process */
+#define AID_VEHICLE_NETWORK 1054 /* Vehicle network service */
+#define AID_MEDIA_AUDIO 1055 /* GID for audio files on internal media storage */
+#define AID_MEDIA_VIDEO 1056 /* GID for video files on internal media storage */
+#define AID_MEDIA_IMAGE 1057 /* GID for image files on internal media storage */
+#define AID_TOMBSTONED 1058 /* tombstoned user */
+#define AID_MEDIA_OBB 1059 /* GID for OBB files on internal media storage */
+#define AID_ESE 1060 /* embedded secure element (eSE) subsystem */
+#define AID_OTA_UPDATE 1061 /* resource tracking UID for OTA updates */
+/* Changes to this file must be made in AOSP, *not* in internal branches. */
+
+#define AID_SHELL 2000 /* adb and debug shell user */
+#define AID_CACHE 2001 /* cache access */
+#define AID_DIAG 2002 /* access to diagnostic resources */
+
+/* The range 2900-2999 is reserved for OEM, and must never be
+ * used here */
+#define AID_OEM_RESERVED_START 2900
+#define AID_OEM_RESERVED_END 2999
+
+/* The 3000 series are intended for use as supplemental group id's only.
+ * They indicate special Android capabilities that the kernel is aware of. */
+#define AID_NET_BT_ADMIN 3001 /* bluetooth: create any socket */
+#define AID_NET_BT 3002 /* bluetooth: create sco, rfcomm or l2cap sockets */
+#define AID_INET 3003 /* can create AF_INET and AF_INET6 sockets */
+#define AID_NET_RAW 3004 /* can create raw INET sockets */
+#define AID_NET_ADMIN 3005 /* can configure interfaces and routing tables. */
+#define AID_NET_BW_STATS 3006 /* read bandwidth statistics */
+#define AID_NET_BW_ACCT 3007 /* change bandwidth statistics accounting */
+#define AID_READPROC 3009 /* Allow /proc read access */
+#define AID_WAKELOCK 3010 /* Allow system wakelock read/write access */
+
+/* The range 5000-5999 is also reserved for OEM, and must never be used here. */
+#define AID_OEM_RESERVED_2_START 5000
+#define AID_OEM_RESERVED_2_END 5999
+
+#define AID_EVERYBODY 9997 /* shared between all apps in the same profile */
+#define AID_MISC 9998 /* access to misc storage */
+#define AID_NOBODY 9999
+
+#define AID_APP 10000 /* TODO: switch users over to AID_APP_START */
+#define AID_APP_START 10000 /* first app user */
+#define AID_APP_END 19999 /* last app user */
+
+#define AID_CACHE_GID_START 20000 /* start of gids for apps to mark cached data */
+#define AID_CACHE_GID_END 29999 /* end of gids for apps to mark cached data */
+
+#define AID_EXT_GID_START 30000 /* start of gids for apps to mark external data */
+#define AID_EXT_GID_END 39999 /* end of gids for apps to mark external data */
+
+#define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */
+#define AID_SHARED_GID_END 59999 /* end of gids for apps in each user to share */
+
+#define AID_ISOLATED_START 99000 /* start of uids for fully isolated sandboxed processes */
+#define AID_ISOLATED_END 99999 /* end of uids for fully isolated sandboxed processes */
+
+#define AID_USER 100000 /* TODO: switch users over to AID_USER_OFFSET */
+#define AID_USER_OFFSET 100000 /* offset for uid ranges for each user */
+
+/*
+ * android_ids has moved to pwd/grp functionality.
+ * If you need to add one, the structure is now
+ * auto-generated based on the AID_ constraints
+ * documented at the top of this header file.
+ * Also see build/tools/fs_config for more details.
+ */
+
+#if !defined(EXCLUDE_FS_CONFIG_STRUCTURES)
+
+struct fs_path_config {
+ unsigned mode;
+ unsigned uid;
+ unsigned gid;
+ uint64_t capabilities;
+ const char* prefix;
+};
+
+/* Rules for directories and files has moved to system/code/libcutils/fs_config.c */
+
+__BEGIN_DECLS
+
+/*
+ * Used in:
+ * build/tools/fs_config/fs_config.c
+ * build/tools/fs_get_stats/fs_get_stats.c
+ * system/extras/ext4_utils/make_ext4fs_main.c
+ * external/squashfs-tools/squashfs-tools/android.c
+ * system/core/cpio/mkbootfs.c
+ * system/core/adb/file_sync_service.cpp
+ * system/extras/ext4_utils/canned_fs_config.c
+ */
+void fs_config(const char* path, int dir, const char* target_out_path, unsigned* uid, unsigned* gid,
+ unsigned* mode, uint64_t* capabilities);
+
+ssize_t fs_config_generate(char* buffer, size_t length, const struct fs_path_config* pc);
+
+__END_DECLS
+
+#endif
+#endif
diff --git a/include/private/canned_fs_config.h b/libcutils/include/private/canned_fs_config.h
similarity index 88%
rename from include/private/canned_fs_config.h
rename to libcutils/include/private/canned_fs_config.h
index d9f51ca..71e1537 100644
--- a/include/private/canned_fs_config.h
+++ b/libcutils/include/private/canned_fs_config.h
@@ -20,7 +20,7 @@
#include <inttypes.h>
int load_canned_fs_config(const char* fn);
-void canned_fs_config(const char* path, int dir, const char* target_out_path,
- unsigned* uid, unsigned* gid, unsigned* mode, uint64_t* capabilities);
+void canned_fs_config(const char* path, int dir, const char* target_out_path, unsigned* uid,
+ unsigned* gid, unsigned* mode, uint64_t* capabilities);
#endif
diff --git a/libcutils/include_vndk/private b/libcutils/include_vndk/private
new file mode 120000
index 0000000..2245a85
--- /dev/null
+++ b/libcutils/include_vndk/private
@@ -0,0 +1 @@
+../include/private
\ No newline at end of file