libbase: make vendor_available
am: d10a023208
Change-Id: I34554045272dcb8c74179010ee6cde4eb899eef3
diff --git a/adb/adb.cpp b/adb/adb.cpp
index cf6b359..51d5876 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -507,8 +507,8 @@
if (!_try_make_handle_noninheritable(h)) {
// Show the handle value to give us a clue in case we have problems
// with pseudo-handle values.
- fprintf(stderr, "Cannot make handle 0x%p non-inheritable: %s\n",
- h, android::base::SystemErrorCodeToString(GetLastError()).c_str());
+ fprintf(stderr, "adb: cannot make handle 0x%p non-inheritable: %s\n", h,
+ android::base::SystemErrorCodeToString(GetLastError()).c_str());
return false;
}
@@ -523,7 +523,7 @@
HANDLE pipe_read_raw = NULL;
HANDLE pipe_write_raw = NULL;
if (!CreatePipe(&pipe_read_raw, &pipe_write_raw, sa, 0)) {
- fprintf(stderr, "Cannot create pipe: %s\n",
+ fprintf(stderr, "adb: CreatePipe failed: %s\n",
android::base::SystemErrorCodeToString(GetLastError()).c_str());
return false;
}
@@ -554,7 +554,8 @@
std::unique_ptr<FILE, decltype(&fclose)> stream(nullptr, fclose);
if (original_fd == -1) {
- fprintf(stderr, "Failed to get file descriptor for %s: %s\n", output_name, strerror(errno));
+ fprintf(stderr, "adb: failed to get file descriptor for %s: %s\n", output_name,
+ strerror(errno));
return EXIT_FAILURE;
}
@@ -566,7 +567,7 @@
// call this function if subprocesses may be started concurrently.
const int fd = dup(original_fd);
if (fd == -1) {
- fprintf(stderr, "Failed to duplicate file descriptor for %s: %s\n", output_name,
+ fprintf(stderr, "adb: failed to duplicate file descriptor for %s: %s\n", output_name,
strerror(errno));
return EXIT_FAILURE;
}
@@ -574,7 +575,7 @@
// Note that although we call fdopen() below with a binary flag, it may not adhere to that
// flag, so we have to set the mode manually.
if (_setmode(fd, _O_BINARY) == -1) {
- fprintf(stderr, "Failed to set binary mode for duplicate of %s: %s\n", output_name,
+ fprintf(stderr, "adb: failed to set binary mode for duplicate of %s: %s\n", output_name,
strerror(errno));
unix_close(fd);
return EXIT_FAILURE;
@@ -582,7 +583,7 @@
stream.reset(fdopen(fd, "wb"));
if (stream.get() == nullptr) {
- fprintf(stderr, "Failed to open duplicate stream for %s: %s\n", output_name,
+ fprintf(stderr, "adb: failed to open duplicate stream for %s: %s\n", output_name,
strerror(errno));
unix_close(fd);
return EXIT_FAILURE;
@@ -591,7 +592,7 @@
// Unbuffer the stream because it will be buffered by default and we want subprocess output
// to be shown immediately.
if (setvbuf(stream.get(), NULL, _IONBF, 0) == -1) {
- fprintf(stderr, "Failed to unbuffer %s: %s\n", output_name, strerror(errno));
+ fprintf(stderr, "adb: failed to unbuffer %s: %s\n", output_name, strerror(errno));
return EXIT_FAILURE;
}
@@ -608,7 +609,7 @@
if (err == ERROR_BROKEN_PIPE) {
return EXIT_SUCCESS;
} else {
- fprintf(stderr, "Failed to read from %s: %s\n", output_name,
+ fprintf(stderr, "adb: failed to read from %s: %s\n", output_name,
android::base::SystemErrorCodeToString(err).c_str());
return EXIT_FAILURE;
}
@@ -619,8 +620,8 @@
// fwrite() actually calls adb_fwrite() which can write UTF-8 to the console.
const size_t bytes_written = fwrite(buf, 1, bytes_read, stream.get());
if (bytes_written != bytes_read) {
- fprintf(stderr, "Only wrote %zu of %lu bytes to %s\n", bytes_written, bytes_read,
- output_name);
+ fprintf(stderr, "adb: error: only wrote %zu of %lu bytes to %s\n", bytes_written,
+ bytes_read, output_name);
return EXIT_FAILURE;
}
}
@@ -663,7 +664,7 @@
FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL));
if (nul_read.get() == INVALID_HANDLE_VALUE) {
- fprintf(stderr, "Cannot open 'nul': %s\n",
+ fprintf(stderr, "adb: CreateFileW 'nul' failed: %s\n",
android::base::SystemErrorCodeToString(GetLastError()).c_str());
return -1;
}
@@ -725,8 +726,7 @@
// If this fires, either handle values are larger than 32-bits or else
// there is a bug in our casting.
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa384203%28v=vs.85%29.aspx
- fprintf(stderr, "Cannot fit pipe handle value into 32-bits: 0x%p\n",
- ack_write.get());
+ fprintf(stderr, "adb: cannot fit pipe handle value into 32-bits: 0x%p\n", ack_write.get());
return -1;
}
@@ -736,7 +736,7 @@
arraysize(program_path));
if ((module_result >= arraysize(program_path)) || (module_result == 0)) {
// String truncation or some other error.
- fprintf(stderr, "Cannot get executable path: %s\n",
+ fprintf(stderr, "adb: cannot get executable path: %s\n",
android::base::SystemErrorCodeToString(GetLastError()).c_str());
return -1;
}
@@ -761,7 +761,7 @@
NULL, /* use parent's starting directory */
&startup, /* startup info, i.e. std handles */
&pinfo )) {
- fprintf(stderr, "Cannot create process: %s\n",
+ fprintf(stderr, "adb: CreateProcessW failed: %s\n",
android::base::SystemErrorCodeToString(GetLastError()).c_str());
return -1;
}
@@ -791,7 +791,7 @@
_beginthreadex(NULL, 0, _redirect_stdout_thread, stdout_read.get(),
0, NULL)));
if (stdout_thread.get() == nullptr) {
- fprintf(stderr, "Cannot create thread: %s\n", strerror(errno));
+ fprintf(stderr, "adb: cannot create thread: %s\n", strerror(errno));
return -1;
}
stdout_read.release(); // Transfer ownership to new thread
@@ -800,7 +800,7 @@
_beginthreadex(NULL, 0, _redirect_stderr_thread, stderr_read.get(),
0, NULL)));
if (stderr_thread.get() == nullptr) {
- fprintf(stderr, "Cannot create thread: %s\n", strerror(errno));
+ fprintf(stderr, "adb: cannot create thread: %s\n", strerror(errno));
return -1;
}
stderr_read.release(); // Transfer ownership to new thread
@@ -845,22 +845,20 @@
if (wait_result == WAIT_TIMEOUT) {
// Threads did not finish after waiting a little while. Perhaps the
// server didn't close pipes, or it is hung.
- fprintf(stderr, "Timed-out waiting for threads to finish reading from "
- "ADB Server\n");
+ fprintf(stderr, "adb: timed out waiting for threads to finish reading from ADB server\n");
// Process handles are signaled when the process exits, so if we wait
// on the handle for 0 seconds and it returns 'timeout', that means that
// the process is still running.
if (WaitForSingleObject(process_handle.get(), 0) == WAIT_TIMEOUT) {
// We could TerminateProcess(), but that seems somewhat presumptive.
- fprintf(stderr, "ADB Server is running: process id %lu\n",
- pinfo.dwProcessId);
+ fprintf(stderr, "adb: server is running with process id %lu\n", pinfo.dwProcessId);
}
return -1;
}
if (wait_result != WAIT_OBJECT_0) {
- fprintf(stderr, "Unexpected result waiting for threads: %lu: %s\n",
- wait_result, android::base::SystemErrorCodeToString(GetLastError()).c_str());
+ fprintf(stderr, "adb: unexpected result waiting for threads: %lu: %s\n", wait_result,
+ android::base::SystemErrorCodeToString(GetLastError()).c_str());
return -1;
}
@@ -894,7 +892,7 @@
int result = execl(path.c_str(), "adb", "-L", socket_spec.c_str(), "fork-server", "server",
"--reply-fd", reply_fd, NULL);
// this should not return
- fprintf(stderr, "OOPS! execl returned %d, errno: %d\n", result, errno);
+ fprintf(stderr, "adb: execl returned %d: %s\n", result, strerror(errno));
} else {
// parent side of the fork
diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp
index ef52189..b2b5c0e 100644
--- a/adb/adb_client.cpp
+++ b/adb/adb_client.cpp
@@ -164,21 +164,21 @@
D("adb_connect: service %s", service.c_str());
if (fd == -2 && !is_local_socket_spec(__adb_server_socket_spec)) {
- fprintf(stderr,"** Cannot start server on remote host\n");
+ fprintf(stderr, "* cannot start server on remote host\n");
// error is the original network connection error
return fd;
} else if (fd == -2) {
- fprintf(stdout, "* daemon not running. starting it now at %s *\n", __adb_server_socket_spec);
+ fprintf(stderr, "* daemon not running; starting now at %s\n", __adb_server_socket_spec);
start_server:
if (launch_server(__adb_server_socket_spec)) {
- fprintf(stderr,"* failed to start daemon *\n");
+ fprintf(stderr, "* failed to start daemon\n");
// launch_server() has already printed detailed error info, so just
// return a generic error string about the overall adb_connect()
// that the caller requested.
*error = "cannot connect to daemon";
return -1;
} else {
- fprintf(stdout,"* daemon started successfully *\n");
+ fprintf(stderr, "* daemon started successfully\n");
}
// Give the server some time to start properly and detect devices.
std::this_thread::sleep_for(3s);
@@ -213,8 +213,8 @@
}
if (version != ADB_SERVER_VERSION) {
- printf("adb server version (%d) doesn't match this client (%d); killing...\n",
- version, ADB_SERVER_VERSION);
+ fprintf(stderr, "adb server version (%d) doesn't match this client (%d); killing...\n",
+ version, ADB_SERVER_VERSION);
fd = _adb_connect("host:kill", error);
if (fd >= 0) {
ReadOrderlyShutdown(fd);
@@ -240,7 +240,7 @@
if (fd == -1) {
D("_adb_connect error: %s", error->c_str());
} else if(fd == -2) {
- fprintf(stderr,"** daemon still not running\n");
+ fprintf(stderr, "* daemon still not running\n");
}
D("adb_connect: return fd %d", fd);
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index 31d3dc6..6f2403d 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -267,8 +267,8 @@
adb_close(fd);
}
-int usage(const char* fmt, ...) {
- fprintf(stderr, "adb: ");
+int syntax_error(const char* fmt, ...) {
+ fprintf(stderr, "adb: usage: ");
va_list ap;
va_start(ap, fmt);
diff --git a/adb/adb_utils.h b/adb/adb_utils.h
index e0ad103..c1d5549 100644
--- a/adb/adb_utils.h
+++ b/adb/adb_utils.h
@@ -21,7 +21,7 @@
#include <android-base/macros.h>
-int usage(const char*, ...);
+int syntax_error(const char*, ...);
void close_stdin();
diff --git a/adb/bugreport.cpp b/adb/bugreport.cpp
index 9dc9811..da2cfa2 100644
--- a/adb/bugreport.cpp
+++ b/adb/bugreport.cpp
@@ -137,7 +137,7 @@
SetSrcFile(&line[strlen(BUGZ_OK_PREFIX)]);
} else if (android::base::StartsWith(line, BUGZ_FAIL_PREFIX)) {
const char* error_message = &line[strlen(BUGZ_FAIL_PREFIX)];
- fprintf(stderr, "Device failed to take a zipped bugreport: %s\n", error_message);
+ fprintf(stderr, "adb: device failed to take a zipped bugreport: %s\n", error_message);
status_ = -1;
} else if (show_progress_ && android::base::StartsWith(line, BUGZ_PROGRESS_PREFIX)) {
// progress_line should have the following format:
@@ -195,7 +195,7 @@
};
int Bugreport::DoIt(TransportType transport_type, const char* serial, int argc, const char** argv) {
- if (argc > 2) return usage("usage: adb bugreport [PATH]");
+ if (argc > 2) return syntax_error("adb bugreport [PATH]");
// Gets bugreportz version.
std::string bugz_stdout, bugz_stderr;
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index 7702b0e..d626259 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -690,8 +690,7 @@
switch (opt) {
case 'e':
if (!(strlen(optarg) == 1 || strcmp(optarg, "none") == 0)) {
- fprintf(stderr, "error: -e requires a single-character argument or 'none'\n");
- return 1;
+ return syntax_error("-e requires a single-character argument or 'none'");
}
escape_char = (strcmp(optarg, "none") == 0) ? 0 : optarg[0];
break;
@@ -843,7 +842,10 @@
* we hang up.
*/
static int adb_sideload_host(const char* filename) {
- fprintf(stderr, "opening '%s'...\n", filename);
+ // TODO: use a LinePrinter instead...
+ fprintf(stdout, "opening '%s'...\n", filename);
+ fflush(stdout);
+
struct stat sb;
if (stat(filename, &sb) == -1) {
fprintf(stderr, "failed to stat file %s: %s\n", filename, strerror(errno));
@@ -855,7 +857,8 @@
return -1;
}
- fprintf(stderr, "connecting...\n");
+ fprintf(stdout, "connecting...\n");
+ fflush(stdout);
std::string service = android::base::StringPrintf(
"sideload-host:%d:%d", static_cast<int>(sb.st_size), SIDELOAD_HOST_BLOCK_SIZE);
std::string error;
@@ -944,19 +947,13 @@
fprintf(stderr, "error: adb %s not implemented on Win32\n", argv[0]);
return -1;
#else
- if (argc < 2) {
- fprintf(stderr, "usage: adb %s <adb service name> [ppp opts]\n",
- argv[0]);
-
- return 1;
- }
+ if (argc < 2) return syntax_error("adb %s <adb service name> [ppp opts]", argv[0]);
const char* adb_service_name = argv[1];
std::string error;
int fd = adb_connect(adb_service_name, &error);
if (fd < 0) {
- fprintf(stderr,"Error: Could not open adb service: %s. Error: %s\n",
- adb_service_name, error.c_str());
+ fprintf(stderr, "adb: could not open adb service %s: %s\n", adb_service_name, error.c_str());
return 1;
}
@@ -1175,10 +1172,7 @@
/* find, extract, and use any -f argument */
for (int i = 1; i < argc; i++) {
if (!strcmp("-f", argv[i])) {
- if (i == argc-1) {
- fprintf(stderr, "adb: backup -f passed with no filename.\n");
- return EXIT_FAILURE;
- }
+ if (i == argc - 1) return syntax_error("backup -f passed with no filename");
filename = argv[i+1];
for (int j = i+2; j <= argc; ) {
argv[i++] = argv[j++];
@@ -1190,10 +1184,7 @@
// Bare "adb backup" or "adb backup -f filename" are not valid invocations ---
// a list of packages is required.
- if (argc < 2) {
- fprintf(stderr, "adb: backup either needs a list of packages or -all/-shared.\n");
- return EXIT_FAILURE;
- }
+ if (argc < 2) return syntax_error("backup either needs a list of packages or -all/-shared");
adb_unlink(filename);
int outFd = adb_creat(filename, 0640);
@@ -1218,7 +1209,7 @@
return EXIT_FAILURE;
}
- printf("Now unlock your device and confirm the backup operation...\n");
+ fprintf(stdout, "Now unlock your device and confirm the backup operation...\n");
fflush(stdout);
copy_to_file(fd, outFd);
@@ -1229,7 +1220,7 @@
}
static int restore(int argc, const char** argv) {
- if (argc != 2) return usage("restore requires an argument");
+ if (argc != 2) return syntax_error("restore requires an argument");
const char* filename = argv[1];
int tarFd = adb_open(filename, O_RDONLY);
@@ -1246,7 +1237,9 @@
return -1;
}
- printf("Now unlock your device and confirm the restore operation.\n");
+ fprintf(stdout, "Now unlock your device and confirm the restore operation.\n");
+ fflush(stdout);
+
copy_to_file(tarFd, fd);
// Provide an in-band EOD marker in case the archive file is malformed
@@ -1338,7 +1331,7 @@
} else if (!strcmp(*arg, "--")) {
ignore_flags = true;
} else {
- fprintf(stderr, "adb: unrecognized option '%s'\n", *arg);
+ syntax_error("unrecognized option '%s'", *arg);
exit(1);
}
}
@@ -1437,7 +1430,7 @@
/* this is a special flag used only when the ADB client launches the ADB Server */
is_daemon = 1;
} else if (!strcmp(argv[0], "--reply-fd")) {
- if (argc < 2) return usage("--reply-fd requires an argument");
+ if (argc < 2) return syntax_error("--reply-fd requires an argument");
const char* reply_fd_str = argv[1];
argc--;
argv++;
@@ -1449,7 +1442,7 @@
} else if (!strncmp(argv[0], "-p", 2)) {
const char* product = nullptr;
if (argv[0][2] == '\0') {
- if (argc < 2) return usage("-p requires an argument");
+ if (argc < 2) return syntax_error("-p requires an argument");
product = argv[1];
argc--;
argv++;
@@ -1465,7 +1458,7 @@
if (isdigit(argv[0][2])) {
serial = argv[0] + 2;
} else {
- if (argc < 2 || argv[0][2] != '\0') return usage("-s requires an argument");
+ if (argc < 2 || argv[0][2] != '\0') return syntax_error("-s requires an argument");
serial = argv[1];
argc--;
argv++;
@@ -1478,7 +1471,7 @@
gListenAll = 1;
} else if (!strncmp(argv[0], "-H", 2)) {
if (argv[0][2] == '\0') {
- if (argc < 2) return usage("-H requires an argument");
+ if (argc < 2) return syntax_error("-H requires an argument");
server_host_str = argv[1];
argc--;
argv++;
@@ -1487,7 +1480,7 @@
}
} else if (!strncmp(argv[0], "-P", 2)) {
if (argv[0][2] == '\0') {
- if (argc < 2) return usage("-P requires an argument");
+ if (argc < 2) return syntax_error("-P requires an argument");
server_port_str = argv[1];
argc--;
argv++;
@@ -1495,7 +1488,7 @@
server_port_str = argv[0] + 2;
}
} else if (!strcmp(argv[0], "-L")) {
- if (argc < 2) return usage("-L requires an argument");
+ if (argc < 2) return syntax_error("-L requires an argument");
server_socket_str = argv[1];
argc--;
argv++;
@@ -1508,8 +1501,7 @@
}
if ((server_host_str || server_port_str) && server_socket_str) {
- fprintf(stderr, "adb: -L is incompatible with -H or -P\n");
- exit(1);
+ return syntax_error("-L is incompatible with -H or -P");
}
// If -L, -H, or -P are specified, ignore environment variables.
@@ -1604,8 +1596,7 @@
} else if (argc == 2 && !strcmp(argv[1], "-l")) {
listopt = argv[1];
} else {
- fprintf(stderr, "Usage: adb devices [-l]\n");
- return 1;
+ return syntax_error("adb devices [-l]");
}
std::string query = android::base::StringPrintf("host:%s%s", argv[0], listopt);
@@ -1613,19 +1604,13 @@
return adb_query_command(query);
}
else if (!strcmp(argv[0], "connect")) {
- if (argc != 2) {
- fprintf(stderr, "Usage: adb connect <host>[:<port>]\n");
- return 1;
- }
+ if (argc != 2) return syntax_error("adb connect <host>[:<port>]");
std::string query = android::base::StringPrintf("host:connect:%s", argv[1]);
return adb_query_command(query);
}
else if (!strcmp(argv[0], "disconnect")) {
- if (argc > 2) {
- fprintf(stderr, "Usage: adb disconnect [<host>[:<port>]]\n");
- return 1;
- }
+ if (argc > 2) return syntax_error("adb disconnect [<host>[:<port>]]");
std::string query = android::base::StringPrintf("host:disconnect:%s",
(argc == 2) ? argv[1] : "");
@@ -1640,10 +1625,7 @@
else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
int exec_in = !strcmp(argv[0], "exec-in");
- if (argc < 2) {
- fprintf(stderr, "Usage: adb %s command\n", argv[0]);
- return 1;
- }
+ if (argc < 2) return syntax_error("adb %s command", argv[0]);
std::string cmd = "exec:";
cmd += argv[1];
@@ -1691,7 +1673,7 @@
}
}
else if (!strcmp(argv[0], "sideload")) {
- if (argc != 2) return usage("sideload requires an argument");
+ if (argc != 2) return syntax_error("sideload requires an argument");
if (adb_sideload_host(argv[1])) {
return 1;
} else {
@@ -1725,7 +1707,7 @@
bool reverse = !strcmp(argv[0], "reverse");
++argv;
--argc;
- if (argc < 1) return usage("%s requires an argument", argv[0]);
+ if (argc < 1) return syntax_error("%s requires an argument", argv[0]);
// Determine the <host-prefix> for this command.
std::string host_prefix;
@@ -1745,24 +1727,24 @@
std::string cmd, error;
if (strcmp(argv[0], "--list") == 0) {
- if (argc != 1) return usage("--list doesn't take any arguments");
+ if (argc != 1) return syntax_error("--list doesn't take any arguments");
return adb_query_command(host_prefix + ":list-forward");
} else if (strcmp(argv[0], "--remove-all") == 0) {
- if (argc != 1) return usage("--remove-all doesn't take any arguments");
+ if (argc != 1) return syntax_error("--remove-all doesn't take any arguments");
cmd = host_prefix + ":killforward-all";
} else if (strcmp(argv[0], "--remove") == 0) {
// forward --remove <local>
- if (argc != 2) return usage("--remove requires an argument");
+ if (argc != 2) return syntax_error("--remove requires an argument");
cmd = host_prefix + ":killforward:" + argv[1];
} else if (strcmp(argv[0], "--no-rebind") == 0) {
// forward --no-rebind <local> <remote>
- if (argc != 3) return usage("--no-rebind takes two arguments");
+ if (argc != 3) return syntax_error("--no-rebind takes two arguments");
if (forward_targets_are_valid(argv[1], argv[2], &error)) {
cmd = host_prefix + ":forward:norebind:" + argv[1] + ";" + argv[2];
}
} else {
// forward <local> <remote>
- if (argc != 2) return usage("forward takes two arguments");
+ if (argc != 2) return syntax_error("forward takes two arguments");
if (forward_targets_are_valid(argv[0], argv[1], &error)) {
cmd = host_prefix + ":forward:" + argv[0] + ";" + argv[1];
}
@@ -1791,7 +1773,7 @@
}
/* do_sync_*() commands */
else if (!strcmp(argv[0], "ls")) {
- if (argc != 2) return usage("ls requires an argument");
+ if (argc != 2) return syntax_error("ls requires an argument");
return do_sync_ls(argv[1]) ? 0 : 1;
}
else if (!strcmp(argv[0], "push")) {
@@ -1800,7 +1782,7 @@
const char* dst = nullptr;
parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, ©_attrs);
- if (srcs.empty() || !dst) return usage("push requires an argument");
+ if (srcs.empty() || !dst) return syntax_error("push requires an argument");
return do_sync_push(srcs, dst) ? 0 : 1;
}
else if (!strcmp(argv[0], "pull")) {
@@ -1809,22 +1791,22 @@
const char* dst = ".";
parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, ©_attrs);
- if (srcs.empty()) return usage("pull requires an argument");
+ if (srcs.empty()) return syntax_error("pull requires an argument");
return do_sync_pull(srcs, dst, copy_attrs) ? 0 : 1;
}
else if (!strcmp(argv[0], "install")) {
- if (argc < 2) return usage("install requires an argument");
+ if (argc < 2) return syntax_error("install requires an argument");
if (_use_legacy_install()) {
return install_app_legacy(transport_type, serial, argc, argv);
}
return install_app(transport_type, serial, argc, argv);
}
else if (!strcmp(argv[0], "install-multiple")) {
- if (argc < 2) return usage("install-multiple requires an argument");
+ if (argc < 2) return syntax_error("install-multiple requires an argument");
return install_multiple_app(transport_type, serial, argc, argv);
}
else if (!strcmp(argv[0], "uninstall")) {
- if (argc < 2) return usage("uninstall requires an argument");
+ if (argc < 2) return syntax_error("uninstall requires an argument");
if (_use_legacy_install()) {
return uninstall_app_legacy(transport_type, serial, argc, argv);
}
@@ -1847,12 +1829,12 @@
// A local path or "android"/"data" arg was specified.
src = argv[1];
} else {
- return usage("usage: adb sync [-l] [PARTITION]");
+ return syntax_error("adb sync [-l] [PARTITION]");
}
if (src != "" &&
src != "system" && src != "data" && src != "vendor" && src != "oem") {
- return usage("don't know how to sync %s partition", src.c_str());
+ return syntax_error("don't know how to sync %s partition", src.c_str());
}
std::string system_src_path = product_file("system");
@@ -1904,7 +1886,7 @@
return restore(argc, argv);
}
else if (!strcmp(argv[0], "keygen")) {
- if (argc != 2) return usage("keygen requires an argument");
+ if (argc != 2) return syntax_error("keygen requires an argument");
// Always print key generation information for keygen command.
adb_trace_enable(AUTH);
return adb_auth_keygen(argv[1]);
@@ -1957,12 +1939,12 @@
std::string err;
return adb_query_command("host:reconnect-offline");
} else {
- return usage("usage: adb reconnect [device|offline]");
+ return syntax_error("adb reconnect [device|offline]");
}
}
}
- usage("unknown command %s", argv[0]);
+ syntax_error("unknown command %s", argv[0]);
return 1;
}
@@ -1989,19 +1971,18 @@
// The last argument must be the APK file
const char* file = argv[argc - 1];
if (!android::base::EndsWithIgnoreCase(file, ".apk")) {
- fprintf(stderr, "Filename doesn't end .apk: %s\n", file);
- return EXIT_FAILURE;
+ return syntax_error("filename doesn't end .apk: %s", file);
}
struct stat sb;
if (stat(file, &sb) == -1) {
- fprintf(stderr, "Failed to stat %s: %s\n", file, strerror(errno));
+ fprintf(stderr, "adb: failed to stat %s: %s\n", file, strerror(errno));
return 1;
}
int localFd = adb_open(file, O_RDONLY);
if (localFd < 0) {
- fprintf(stderr, "Failed to open %s: %s\n", file, strerror(errno));
+ fprintf(stderr, "adb: failed to open %s: %s\n", file, strerror(errno));
return 1;
}
@@ -2019,7 +2000,7 @@
int remoteFd = adb_connect(cmd, &error);
if (remoteFd < 0) {
- fprintf(stderr, "Connect error for write: %s\n", error.c_str());
+ fprintf(stderr, "adb: connect error for write: %s\n", error.c_str());
adb_close(localFd);
return 1;
}
@@ -2031,12 +2012,12 @@
adb_close(localFd);
adb_close(remoteFd);
- if (strncmp("Success", buf, 7)) {
- fprintf(stderr, "Failed to install %s: %s", file, buf);
- return 1;
+ if (!strncmp("Success", buf, 7)) {
+ fputs(buf, stdout);
+ return 0;
}
- fputs(buf, stderr);
- return 0;
+ fprintf(stderr, "adb: failed to install %s: %s", file, buf);
+ return 1;
}
static int install_multiple_app(TransportType transport, const char* serial, int argc,
@@ -2058,10 +2039,7 @@
}
}
- if (first_apk == -1) {
- fprintf(stderr, "No APK file on command line\n");
- return 1;
- }
+ if (first_apk == -1) return syntax_error("need APK file on command line");
std::string install_cmd;
if (_use_legacy_install()) {
@@ -2079,7 +2057,7 @@
std::string error;
int fd = adb_connect(cmd, &error);
if (fd < 0) {
- fprintf(stderr, "Connect error for create: %s\n", error.c_str());
+ fprintf(stderr, "adb: connect error for create: %s\n", error.c_str());
return EXIT_FAILURE;
}
char buf[BUFSIZ];
@@ -2096,7 +2074,7 @@
}
}
if (session_id < 0) {
- fprintf(stderr, "Failed to create session\n");
+ fprintf(stderr, "adb: failed to create session\n");
fputs(buf, stderr);
return EXIT_FAILURE;
}
@@ -2107,7 +2085,7 @@
const char* file = argv[i];
struct stat sb;
if (stat(file, &sb) == -1) {
- fprintf(stderr, "Failed to stat %s: %s\n", file, strerror(errno));
+ fprintf(stderr, "adb: failed to stat %s: %s\n", file, strerror(errno));
success = 0;
goto finalize_session;
}
@@ -2119,7 +2097,7 @@
int localFd = adb_open(file, O_RDONLY);
if (localFd < 0) {
- fprintf(stderr, "Failed to open %s: %s\n", file, strerror(errno));
+ fprintf(stderr, "adb: failed to open %s: %s\n", file, strerror(errno));
success = 0;
goto finalize_session;
}
@@ -2127,7 +2105,7 @@
std::string error;
int remoteFd = adb_connect(cmd, &error);
if (remoteFd < 0) {
- fprintf(stderr, "Connect error for write: %s\n", error.c_str());
+ fprintf(stderr, "adb: connect error for write: %s\n", error.c_str());
adb_close(localFd);
success = 0;
goto finalize_session;
@@ -2140,7 +2118,7 @@
adb_close(remoteFd);
if (strncmp("Success", buf, 7)) {
- fprintf(stderr, "Failed to write %s\n", file);
+ fprintf(stderr, "adb: failed to write %s\n", file);
fputs(buf, stderr);
success = 0;
goto finalize_session;
@@ -2154,20 +2132,19 @@
install_cmd.c_str(), success ? "commit" : "abandon", session_id);
fd = adb_connect(service, &error);
if (fd < 0) {
- fprintf(stderr, "Connect error for finalize: %s\n", error.c_str());
+ fprintf(stderr, "adb: connect error for finalize: %s\n", error.c_str());
return EXIT_FAILURE;
}
read_status_line(fd, buf, sizeof(buf));
adb_close(fd);
if (!strncmp("Success", buf, 7)) {
- fputs(buf, stderr);
+ fputs(buf, stdout);
return 0;
- } else {
- fprintf(stderr, "Failed to finalize session\n");
- fputs(buf, stderr);
- return EXIT_FAILURE;
}
+ fprintf(stderr, "adb: failed to finalize session\n");
+ fputs(buf, stderr);
+ return EXIT_FAILURE;
}
static int pm_command(TransportType transport, const char* serial, int argc, const char** argv) {
@@ -2225,10 +2202,7 @@
}
}
- if (last_apk == -1) {
- fprintf(stderr, "No APK file on command line\n");
- return EXIT_FAILURE;
- }
+ if (last_apk == -1) return syntax_error("need APK file on command line");
int result = -1;
std::vector<const char*> apk_file = {argv[last_apk]};
diff --git a/adb/commandline.h b/adb/commandline.h
index 0cf655c..9ba69a3 100644
--- a/adb/commandline.h
+++ b/adb/commandline.h
@@ -87,7 +87,6 @@
extern DefaultStandardStreamsCallback DEFAULT_STANDARD_STREAMS_CALLBACK;
int adb_commandline(int argc, const char** argv);
-int usage();
// Connects to the device "shell" service with |command| and prints the
// resulting output.
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 4ddcc52..e3d4f87 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -128,18 +128,20 @@
}
}
+static bool should_force_check(int fs_stat) {
+ return fs_stat & (FS_STAT_E2FSCK_F_ALWAYS | FS_STAT_UNCLEAN_SHUTDOWN | FS_STAT_QUOTA_ENABLED |
+ FS_STAT_TUNE2FS_FAILED | FS_STAT_RO_MOUNT_FAILED | FS_STAT_RO_UNMOUNT_FAILED |
+ FS_STAT_FULL_MOUNT_FAILED | FS_STAT_E2FSCK_FAILED);
+}
+
static void check_fs(const char *blk_device, char *fs_type, char *target, int *fs_stat)
{
int status;
int ret;
long tmpmnt_flags = MS_NOATIME | MS_NOEXEC | MS_NOSUID;
char tmpmnt_opts[64] = "errors=remount-ro";
- const char *e2fsck_argv[] = {
- E2FSCK_BIN,
- "-f",
- "-y",
- blk_device
- };
+ const char* e2fsck_argv[] = {E2FSCK_BIN, "-y", blk_device};
+ const char* e2fsck_forced_argv[] = {E2FSCK_BIN, "-f", "-y", blk_device};
/* Check for the types of filesystems we know how to check */
if (!strcmp(fs_type, "ext2") || !strcmp(fs_type, "ext3") || !strcmp(fs_type, "ext4")) {
@@ -159,32 +161,35 @@
* filesytsem due to an error, e2fsck is still run to do a full check
* fix the filesystem.
*/
- errno = 0;
- if (!strcmp(fs_type, "ext4")) {
- // This option is only valid with ext4
- strlcat(tmpmnt_opts, ",nomblk_io_submit", sizeof(tmpmnt_opts));
- }
- ret = mount(blk_device, target, fs_type, tmpmnt_flags, tmpmnt_opts);
- PINFO << __FUNCTION__ << "(): mount(" << blk_device << "," << target
- << "," << fs_type << ")=" << ret;
- if (!ret) {
- int i;
- for (i = 0; i < 5; i++) {
- // Try to umount 5 times before continuing on.
- // Should we try rebooting if all attempts fail?
- int result = umount(target);
- if (result == 0) {
- LINFO << __FUNCTION__ << "(): unmount(" << target
- << ") succeeded";
- break;
- }
- *fs_stat |= FS_STAT_RO_UNMOUNT_FAILED;
- PERROR << __FUNCTION__ << "(): umount(" << target << ")="
- << result;
- sleep(1);
+ if (!(*fs_stat & FS_STAT_FULL_MOUNT_FAILED)) { // already tried if full mount failed
+ errno = 0;
+ if (!strcmp(fs_type, "ext4")) {
+ // This option is only valid with ext4
+ strlcat(tmpmnt_opts, ",nomblk_io_submit", sizeof(tmpmnt_opts));
}
- } else {
- *fs_stat |= FS_STAT_RO_MOUNT_FAILED;
+ ret = mount(blk_device, target, fs_type, tmpmnt_flags, tmpmnt_opts);
+ PINFO << __FUNCTION__ << "(): mount(" << blk_device << "," << target << "," << fs_type
+ << ")=" << ret;
+ if (!ret) {
+ bool umounted = false;
+ int retry_count = 5;
+ while (retry_count-- > 0) {
+ umounted = umount(target) == 0;
+ if (umounted) {
+ LINFO << __FUNCTION__ << "(): unmount(" << target << ") succeeded";
+ break;
+ }
+ PERROR << __FUNCTION__ << "(): umount(" << target << ") failed";
+ if (retry_count) sleep(1);
+ }
+ if (!umounted) {
+ // boot may fail but continue and leave it to later stage for now.
+ PERROR << __FUNCTION__ << "(): umount(" << target << ") timed out";
+ *fs_stat |= FS_STAT_RO_UNMOUNT_FAILED;
+ }
+ } else {
+ *fs_stat |= FS_STAT_RO_MOUNT_FAILED;
+ }
}
/*
@@ -196,14 +201,15 @@
<< " (executable not in system image)";
} else {
LINFO << "Running " << E2FSCK_BIN << " on " << blk_device;
-
- *fs_stat |= FS_STAT_E2FSCK_F_ALWAYS;
- ret = android_fork_execvp_ext(ARRAY_SIZE(e2fsck_argv),
- const_cast<char **>(e2fsck_argv),
- &status, true, LOG_KLOG | LOG_FILE,
- true,
- const_cast<char *>(FSCK_LOG_FILE),
- NULL, 0);
+ if (should_force_check(*fs_stat)) {
+ ret = android_fork_execvp_ext(
+ ARRAY_SIZE(e2fsck_forced_argv), const_cast<char**>(e2fsck_forced_argv), &status,
+ true, LOG_KLOG | LOG_FILE, true, const_cast<char*>(FSCK_LOG_FILE), NULL, 0);
+ } else {
+ ret = android_fork_execvp_ext(
+ ARRAY_SIZE(e2fsck_argv), const_cast<char**>(e2fsck_argv), &status, true,
+ LOG_KLOG | LOG_FILE, true, const_cast<char*>(FSCK_LOG_FILE), NULL, 0);
+ }
if (ret < 0) {
/* No need to check for error in fork, we can't really handle it now */
@@ -574,21 +580,31 @@
&fstab->recs[i], &fs_stat);
}
- if (!__mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point, &fstab->recs[i])) {
- *attempted_idx = i;
- mounted = 1;
- if (i != start_idx) {
- LERROR << __FUNCTION__ << "(): Mounted "
- << fstab->recs[i].blk_device << " on "
- << fstab->recs[i].mount_point << " with fs_type="
- << fstab->recs[i].fs_type << " instead of "
- << fstab->recs[start_idx].fs_type;
- }
- } else {
- fs_stat |= FS_STAT_FULL_MOUNT_FAILED;
- /* back up the first errno for crypto decisions */
- if (mount_errno == 0) {
- mount_errno = errno;
+ int retry_count = 2;
+ while (retry_count-- > 0) {
+ if (!__mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point,
+ &fstab->recs[i])) {
+ *attempted_idx = i;
+ mounted = 1;
+ if (i != start_idx) {
+ LERROR << __FUNCTION__ << "(): Mounted " << fstab->recs[i].blk_device
+ << " on " << fstab->recs[i].mount_point
+ << " with fs_type=" << fstab->recs[i].fs_type << " instead of "
+ << fstab->recs[start_idx].fs_type;
+ }
+ fs_stat &= ~FS_STAT_FULL_MOUNT_FAILED;
+ mount_errno = 0;
+ break;
+ } else {
+ if (retry_count <= 0) break; // run check_fs only once
+ fs_stat |= FS_STAT_FULL_MOUNT_FAILED;
+ /* back up the first errno for crypto decisions */
+ if (mount_errno == 0) {
+ mount_errno = errno;
+ }
+ // retry after fsck
+ check_fs(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
+ fstab->recs[i].mount_point, &fs_stat);
}
}
log_fs_stat(fstab->recs[i].blk_device, fs_stat);
@@ -1074,17 +1090,22 @@
} else {
m = fstab->recs[i].mount_point;
}
- if (__mount(n_blk_device, m, &fstab->recs[i])) {
- if (!first_mount_errno) first_mount_errno = errno;
- mount_errors++;
- fs_stat |= FS_STAT_FULL_MOUNT_FAILED;
- log_fs_stat(fstab->recs[i].blk_device, fs_stat);
- continue;
- } else {
- ret = 0;
- log_fs_stat(fstab->recs[i].blk_device, fs_stat);
- goto out;
+ int retry_count = 2;
+ while (retry_count-- > 0) {
+ if (!__mount(n_blk_device, m, &fstab->recs[i])) {
+ ret = 0;
+ fs_stat &= ~FS_STAT_FULL_MOUNT_FAILED;
+ goto out;
+ } else {
+ if (retry_count <= 0) break; // run check_fs only once
+ if (!first_mount_errno) first_mount_errno = errno;
+ mount_errors++;
+ fs_stat |= FS_STAT_FULL_MOUNT_FAILED;
+ // try again after fsck
+ check_fs(n_blk_device, fstab->recs[i].fs_type, fstab->recs[i].mount_point, &fs_stat);
+ }
}
+ log_fs_stat(fstab->recs[i].blk_device, fs_stat);
}
if (mount_errors) {
PERROR << "Cannot mount filesystem on " << n_blk_device
diff --git a/init/README.md b/init/README.md
index 8cb1e52..1eb42e0 100644
--- a/init/README.md
+++ b/init/README.md
@@ -16,9 +16,7 @@
or options belong to the section most recently declared. Commands
or options before the first section are ignored.
-Actions and Services have unique names. If a second Action is defined
-with the same name as an existing one, its commands are appended to
-the commands of the existing action. If a second Service is defined
+Services have unique names. If a second Service is defined
with the same name as an existing one, it is ignored and an error
message is logged.
@@ -31,13 +29,21 @@
/init.rc is the primary .rc file and is loaded by the init executable
at the beginning of its execution. It is responsible for the initial
-set up of the system. It imports /init.${ro.hardware}.rc which is the
-primary vendor supplied .rc file.
+set up of the system.
-During the mount\_all command, the init executable loads all of the
-files contained within the /{system,vendor,odm}/etc/init/ directories.
-These directories are intended for all Actions and Services used after
-file system mounting.
+Devices that mount /system, /vendor through the early mount mechanism
+load all of the files contained within the
+/{system,vendor,odm}/etc/init/ directories immediately after loading
+the primary /init.rc. This is explained in more details in the
+Imports section of this file.
+
+Legacy devices without the early mount mechanism do the following:
+1. /init.rc imports /init.${ro.hardware}.rc which is the primary
+ vendor supplied .rc file.
+2. During the mount\_all command, the init executable loads all of the
+ files contained within the /{system,vendor,odm}/etc/init/ directories.
+ These directories are intended for all Actions and Services used after
+ file system mounting.
One may specify paths in the mount\_all command line to have it import
.rc files at the specified paths instead of the default ones listed above.
@@ -89,7 +95,7 @@
Actions
-------
Actions are named sequences of commands. Actions have a trigger which
-is used to determine when the action should occur. When an event
+is used to determine when the action is executed. When an event
occurs which matches an action's trigger, that action is added to
the tail of a to-be-executed queue (unless it is already on the
queue).
@@ -106,6 +112,34 @@
<command>
<command>
+Actions are added to the queue and executed based on the order that
+the file that contains them was parsed (see the Imports section), then
+sequentially within an individual file.
+
+For example if a file contains:
+
+ on boot
+ setprop a 1
+ setprop b 2
+
+ on boot && property:true=true
+ setprop c 1
+ setprop d 2
+
+ on boot
+ setprop e 1
+ setprop f 2
+
+Then when the `boot` trigger occurs and assuming the property `true`
+equals `true`, then the order of the commands executed will be:
+
+ setprop a 1
+ setprop b 2
+ setprop c 1
+ setprop d 2
+ setprop e 1
+ setprop f 2
+
Services
--------
@@ -276,7 +310,8 @@
`class_start <serviceclass>`
> Start all services of the specified class if they are
- not already running.
+ not already running. See the start entry for more information on
+ starting services.
`class_stop <serviceclass>`
> Stop and disable all services of the specified class if they are
@@ -401,6 +436,16 @@
`start <service>`
> Start a service running if it is not already running.
+ Note that this is _not_ synchronous, and even if it were, there is
+ no guarantee that the operating system's scheduler will execute the
+ service sufficiently to guarantee anything about the service's status.
+
+> This creates an important consequence that if the service offers
+ functionality to other services, such as providing a
+ communication channel, simply starting this service before those
+ services is _not_ sufficient to guarantee that the channel has
+ been set up before those services ask for it. There must be a
+ separate mechanism to make any such guarantees.
`stop <service>`
> Stop a service from running if it is currently running.
@@ -447,21 +492,54 @@
Imports
-------
-The import keyword is not a command, but rather its own section and is
-handled immediately after the .rc file that contains it has finished
-being parsed. It takes the below form:
-
`import <path>`
> Parse an init config file, extending the current configuration.
If _path_ is a directory, each file in the directory is parsed as
a config file. It is not recursive, nested directories will
not be parsed.
-There are only two times where the init executable imports .rc files:
+The import keyword is not a command, but rather its own section,
+meaning that it does not happen as part of an Action, but rather,
+imports are handled as a file is being parsed and follow the below logic.
- 1. When it imports /init.rc during initial boot
- 2. When it imports /{system,vendor,odm}/etc/init/ or .rc files at specified
- paths during mount_all
+There are only three times where the init executable imports .rc files:
+
+ 1. When it imports /init.rc or the script indicated by the property
+ `ro.boot.init_rc` during initial boot.
+ 2. When it imports /{system,vendor,odm}/etc/init/ for early mount
+ devices immediately after importing /init.rc.
+ 3. When it imports /{system,vendor,odm}/etc/init/ or .rc files at specified
+ paths during mount_all.
+
+The order that files are imported is a bit complex for legacy reasons
+and to keep backwards compatibility. It is not strictly guaranteed.
+
+The only correct way to guarantee that a command has been run before a
+different command is to either 1) place it in an Action with an
+earlier executed trigger, or 2) place it in an Action with the same
+trigger within the same file at an earlier line.
+
+Nonetheless, the defacto order for early mount devices is:
+1. /init.rc is parsed then recursively each of its imports are
+ parsed.
+2. The contents of /system/etc/init/ are alphabetized and parsed
+ sequentially, with imports happening recursively after each file is
+ parsed.
+3. Step 2 is repeated for /vendor/etc/init then /odm/etc/init
+
+The below pseudocode may explain this more clearly:
+
+ fn Import(file)
+ Parse(file)
+ for (import : file.imports)
+ Import(import)
+
+ Import(/init.rc)
+ Directories = [/system/etc/init, /vendor/etc/init, /odm/etc/init]
+ for (directory : Directories)
+ files = <Alphabetical order of directory's contents>
+ for (file : files)
+ Import(file)
Properties
diff --git a/init/action.cpp b/init/action.cpp
index 347edb0..c128968 100644
--- a/init/action.cpp
+++ b/init/action.cpp
@@ -26,10 +26,8 @@
using android::base::Join;
using android::base::StringPrintf;
-Command::Command(BuiltinFunction f, const std::vector<std::string>& args,
- const std::string& filename, int line)
- : func_(f), args_(args), filename_(filename), line_(line) {
-}
+Command::Command(BuiltinFunction f, const std::vector<std::string>& args, int line)
+ : func_(f), args_(args), line_(line) {}
int Command::InvokeFunc() const {
std::vector<std::string> expanded_args;
@@ -49,21 +47,12 @@
return Join(args_, ' ');
}
-std::string Command::BuildSourceString() const {
- if (!filename_.empty()) {
- return StringPrintf(" (%s:%d)", filename_.c_str(), line_);
- } else {
- return std::string();
- }
-}
-
-Action::Action(bool oneshot) : oneshot_(oneshot) {
-}
+Action::Action(bool oneshot, const std::string& filename, int line)
+ : oneshot_(oneshot), filename_(filename), line_(line) {}
const KeywordMap<BuiltinFunction>* Action::function_map_ = nullptr;
-bool Action::AddCommand(const std::vector<std::string>& args,
- const std::string& filename, int line, std::string* err) {
+bool Action::AddCommand(const std::vector<std::string>& args, int line, std::string* err) {
if (!function_map_) {
*err = "no function map available";
return false;
@@ -79,20 +68,12 @@
return false;
}
- AddCommand(function, args, filename, line);
+ AddCommand(function, args, line);
return true;
}
-void Action::AddCommand(BuiltinFunction f,
- const std::vector<std::string>& args,
- const std::string& filename, int line) {
- commands_.emplace_back(f, args, filename, line);
-}
-
-void Action::CombineAction(const Action& action) {
- for (const auto& c : action.commands_) {
- commands_.emplace_back(c);
- }
+void Action::AddCommand(BuiltinFunction f, const std::vector<std::string>& args, int line) {
+ commands_.emplace_back(f, args, line);
}
std::size_t Action::NumCommands() const {
@@ -122,7 +103,7 @@
android::base::GetMinimumLogSeverity() <= android::base::DEBUG) {
std::string trigger_name = BuildTriggersString();
std::string cmd_str = command.BuildCommandString();
- std::string source = command.BuildSourceString();
+ std::string source = StringPrintf(" (%s:%d)", filename_.c_str(), command.line());
LOG(INFO) << "Command '" << cmd_str << "' action=" << trigger_name << source
<< " returned " << result << " took " << duration_ms << "ms.";
@@ -234,11 +215,6 @@
return event_trigger_.empty() && CheckPropertyTriggers(name, value);
}
-bool Action::TriggersEqual(const Action& other) const {
- return property_triggers_ == other.property_triggers_ &&
- event_trigger_ == other.event_trigger_;
-}
-
std::string Action::BuildTriggersString() const {
std::vector<std::string> triggers;
@@ -306,17 +282,7 @@
}
void ActionManager::AddAction(std::unique_ptr<Action> action) {
- auto old_action_it =
- std::find_if(actions_.begin(), actions_.end(),
- [&action] (std::unique_ptr<Action>& a) {
- return action->TriggersEqual(*a);
- });
-
- if (old_action_it != actions_.end()) {
- (*old_action_it)->CombineAction(*action);
- } else {
- actions_.emplace_back(std::move(action));
- }
+ actions_.emplace_back(std::move(action));
}
void ActionManager::QueueEventTrigger(const std::string& trigger) {
@@ -332,16 +298,15 @@
QueuePropertyTrigger("", "");
}
-void ActionManager::QueueBuiltinAction(BuiltinFunction func,
- const std::string& name) {
- auto action = std::make_unique<Action>(true);
+void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& name) {
+ auto action = std::make_unique<Action>(true, "<Builtin Action>", 0);
std::vector<std::string> name_vector{name};
if (!action->InitSingleTrigger(name)) {
return;
}
- action->AddCommand(func, name_vector);
+ action->AddCommand(func, name_vector, 0);
trigger_queue_.push(std::make_unique<BuiltinTrigger>(action.get()));
actions_.emplace_back(std::move(action));
@@ -366,7 +331,8 @@
if (current_command_ == 0) {
std::string trigger_name = action->BuildTriggersString();
- LOG(INFO) << "processing action (" << trigger_name << ")";
+ LOG(INFO) << "processing action (" << trigger_name << ") from (" << action->filename()
+ << ":" << action->line() << ")";
}
action->ExecuteOneCommand(current_command_);
@@ -397,15 +363,15 @@
}
}
-bool ActionParser::ParseSection(const std::vector<std::string>& args,
- std::string* err) {
+bool ActionParser::ParseSection(const std::vector<std::string>& args, const std::string& filename,
+ int line, std::string* err) {
std::vector<std::string> triggers(args.begin() + 1, args.end());
if (triggers.size() < 1) {
*err = "actions must have a trigger";
return false;
}
- auto action = std::make_unique<Action>(false);
+ auto action = std::make_unique<Action>(false, filename, line);
if (!action->InitTriggers(triggers, err)) {
return false;
}
@@ -414,10 +380,9 @@
return true;
}
-bool ActionParser::ParseLineSection(const std::vector<std::string>& args,
- const std::string& filename, int line,
- std::string* err) const {
- return action_ ? action_->AddCommand(args, filename, line, err) : false;
+bool ActionParser::ParseLineSection(const std::vector<std::string>& args, int line,
+ std::string* err) {
+ return action_ ? action_->AddCommand(args, line, err) : false;
}
void ActionParser::EndSection() {
diff --git a/init/action.h b/init/action.h
index 0bae9f0..25e5a3e 100644
--- a/init/action.h
+++ b/init/action.h
@@ -27,31 +27,26 @@
#include "keyword_map.h"
class Command {
-public:
- Command(BuiltinFunction f, const std::vector<std::string>& args,
- const std::string& filename, int line);
+ public:
+ Command(BuiltinFunction f, const std::vector<std::string>& args, int line);
int InvokeFunc() const;
std::string BuildCommandString() const;
- std::string BuildSourceString() const;
-private:
+ int line() const { return line_; }
+
+ private:
BuiltinFunction func_;
std::vector<std::string> args_;
- std::string filename_;
int line_;
};
class Action {
-public:
- explicit Action(bool oneshot = false);
+ public:
+ explicit Action(bool oneshot, const std::string& filename, int line);
- bool AddCommand(const std::vector<std::string>& args,
- const std::string& filename, int line, std::string* err);
- void AddCommand(BuiltinFunction f,
- const std::vector<std::string>& args,
- const std::string& filename = "", int line = 0);
- void CombineAction(const Action& action);
+ bool AddCommand(const std::vector<std::string>& args, int line, std::string* err);
+ void AddCommand(BuiltinFunction f, const std::vector<std::string>& args, int line);
bool InitTriggers(const std::vector<std::string>& args, std::string* err);
bool InitSingleTrigger(const std::string& trigger);
std::size_t NumCommands() const;
@@ -60,11 +55,12 @@
bool CheckEventTrigger(const std::string& trigger) const;
bool CheckPropertyTrigger(const std::string& name,
const std::string& value) const;
- bool TriggersEqual(const Action& other) const;
std::string BuildTriggersString() const;
void DumpState() const;
bool oneshot() const { return oneshot_; }
+ const std::string& filename() const { return filename_; }
+ int line() const { return line_; }
static void set_function_map(const KeywordMap<BuiltinFunction>* function_map) {
function_map_ = function_map;
}
@@ -80,6 +76,8 @@
std::string event_trigger_;
std::vector<Command> commands_;
bool oneshot_;
+ std::string filename_;
+ int line_;
static const KeywordMap<BuiltinFunction>* function_map_;
};
@@ -115,18 +113,17 @@
};
class ActionParser : public SectionParser {
-public:
+ public:
ActionParser() : action_(nullptr) {
}
- bool ParseSection(const std::vector<std::string>& args,
+ bool ParseSection(const std::vector<std::string>& args, const std::string& filename, int line,
std::string* err) override;
- bool ParseLineSection(const std::vector<std::string>& args,
- const std::string& filename, int line,
- std::string* err) const override;
+ bool ParseLineSection(const std::vector<std::string>& args, int line, std::string* err) override;
void EndSection() override;
void EndFile(const std::string&) override {
}
-private:
+
+ private:
std::unique_ptr<Action> action_;
};
diff --git a/init/import_parser.cpp b/init/import_parser.cpp
index 8a2bcc2..f66b2ba 100644
--- a/init/import_parser.cpp
+++ b/init/import_parser.cpp
@@ -20,8 +20,8 @@
#include "util.h"
-bool ImportParser::ParseSection(const std::vector<std::string>& args,
- std::string* err) {
+bool ImportParser::ParseSection(const std::vector<std::string>& args, const std::string& filename,
+ int line, std::string* err) {
if (args.size() != 2) {
*err = "single argument needed for import\n";
return false;
diff --git a/init/import_parser.h b/init/import_parser.h
index 0e91025..e15d555 100644
--- a/init/import_parser.h
+++ b/init/import_parser.h
@@ -23,20 +23,20 @@
#include <vector>
class ImportParser : public SectionParser {
-public:
+ public:
ImportParser() {
}
- bool ParseSection(const std::vector<std::string>& args,
+ bool ParseSection(const std::vector<std::string>& args, const std::string& filename, int line,
std::string* err) override;
- bool ParseLineSection(const std::vector<std::string>& args,
- const std::string& filename, int line,
- std::string* err) const override {
+ bool ParseLineSection(const std::vector<std::string>& args, int line,
+ std::string* err) override {
return true;
}
void EndSection() override {
}
void EndFile(const std::string& filename) override;
-private:
+
+ private:
std::vector<std::string> imports_;
};
diff --git a/init/init_parser.cpp b/init/init_parser.cpp
index 53e670b..b425497 100644
--- a/init/init_parser.cpp
+++ b/init/init_parser.cpp
@@ -71,14 +71,13 @@
}
section_parser = section_parsers_[args[0]].get();
std::string ret_err;
- if (!section_parser->ParseSection(args, &ret_err)) {
+ if (!section_parser->ParseSection(args, state.filename, state.line, &ret_err)) {
parse_error(&state, "%s\n", ret_err.c_str());
section_parser = nullptr;
}
} else if (section_parser) {
std::string ret_err;
- if (!section_parser->ParseLineSection(args, state.filename,
- state.line, &ret_err)) {
+ if (!section_parser->ParseLineSection(args, state.line, &ret_err)) {
parse_error(&state, "%s\n", ret_err.c_str());
}
}
diff --git a/init/init_parser.h b/init/init_parser.h
index 6935fdf..64f0cac 100644
--- a/init/init_parser.h
+++ b/init/init_parser.h
@@ -26,11 +26,10 @@
public:
virtual ~SectionParser() {
}
- virtual bool ParseSection(const std::vector<std::string>& args,
- std::string* err) = 0;
- virtual bool ParseLineSection(const std::vector<std::string>& args,
- const std::string& filename, int line,
- std::string* err) const = 0;
+ virtual bool ParseSection(const std::vector<std::string>& args, const std::string& filename,
+ int line, std::string* err) = 0;
+ virtual bool ParseLineSection(const std::vector<std::string>& args, int line,
+ std::string* err) = 0;
virtual void EndSection() = 0;
virtual void EndFile(const std::string& filename) = 0;
};
diff --git a/init/service.cpp b/init/service.cpp
index 4adbbf0..caf5785 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -157,6 +157,7 @@
gid_(0),
namespace_flags_(0),
seclabel_(""),
+ onrestart_(false, "<Service '" + name + "' onrestart>", 0),
ioprio_class_(IoSchedClass_NONE),
ioprio_pri_(0),
priority_(0),
@@ -180,6 +181,7 @@
capabilities_(capabilities),
namespace_flags_(namespace_flags),
seclabel_(seclabel),
+ onrestart_(false, "<Service '" + name + "' onrestart>", 0),
ioprio_class_(IoSchedClass_NONE),
ioprio_pri_(0),
priority_(0),
@@ -438,7 +440,8 @@
bool Service::ParseOnrestart(const std::vector<std::string>& args, std::string* err) {
std::vector<std::string> str_args(args.begin() + 1, args.end());
- onrestart_.AddCommand(str_args, "", 0, err);
+ int line = onrestart_.NumCommands() + 1;
+ onrestart_.AddCommand(str_args, line, err);
return true;
}
@@ -1092,8 +1095,8 @@
}
}
-bool ServiceParser::ParseSection(const std::vector<std::string>& args,
- std::string* err) {
+bool ServiceParser::ParseSection(const std::vector<std::string>& args, const std::string& filename,
+ int line, std::string* err) {
if (args.size() < 3) {
*err = "services must have a name and a program";
return false;
@@ -1110,9 +1113,8 @@
return true;
}
-bool ServiceParser::ParseLineSection(const std::vector<std::string>& args,
- const std::string& filename, int line,
- std::string* err) const {
+bool ServiceParser::ParseLineSection(const std::vector<std::string>& args, int line,
+ std::string* err) {
return service_ ? service_->ParseLine(args, err) : false;
}
diff --git a/init/service.h b/init/service.h
index 5e89b9f..6fe0258 100644
--- a/init/service.h
+++ b/init/service.h
@@ -212,18 +212,15 @@
};
class ServiceParser : public SectionParser {
-public:
- ServiceParser() : service_(nullptr) {
- }
- bool ParseSection(const std::vector<std::string>& args,
+ public:
+ ServiceParser() : service_(nullptr) {}
+ bool ParseSection(const std::vector<std::string>& args, const std::string& filename, int line,
std::string* err) override;
- bool ParseLineSection(const std::vector<std::string>& args,
- const std::string& filename, int line,
- std::string* err) const override;
+ bool ParseLineSection(const std::vector<std::string>& args, int line, std::string* err) override;
void EndSection() override;
- void EndFile(const std::string&) override {
- }
-private:
+ void EndFile(const std::string&) override {}
+
+ private:
bool IsValidName(const std::string& name) const;
std::unique_ptr<Service> service_;
diff --git a/liblog/include/log/log_time.h b/liblog/include/log/log_time.h
index 9ece0b3..3764faf 100644
--- a/liblog/include/log/log_time.h
+++ b/liblog/include/log/log_time.h
@@ -22,6 +22,8 @@
/* struct log_time is a wire-format variant of struct timespec */
#define NS_PER_SEC 1000000000ULL
+#define US_PER_SEC 1000000ULL
+#define MS_PER_SEC 1000ULL
#ifndef __struct_log_time_defined
#define __struct_log_time_defined
@@ -148,6 +150,14 @@
uint64_t nsec() const {
return static_cast<uint64_t>(tv_sec) * NS_PER_SEC + tv_nsec;
}
+ uint64_t usec() const {
+ return static_cast<uint64_t>(tv_sec) * US_PER_SEC +
+ tv_nsec / (NS_PER_SEC / US_PER_SEC);
+ }
+ uint64_t msec() const {
+ return static_cast<uint64_t>(tv_sec) * MS_PER_SEC +
+ tv_nsec / (NS_PER_SEC / MS_PER_SEC);
+ }
#ifdef _SYSTEM_CORE_INCLUDE_PRIVATE_ANDROID_LOGGER_H_
static const char default_format[];
diff --git a/libprocessgroup/Android.bp b/libprocessgroup/Android.bp
new file mode 100644
index 0000000..37e4dbf
--- /dev/null
+++ b/libprocessgroup/Android.bp
@@ -0,0 +1,10 @@
+cc_library {
+ srcs: ["processgroup.cpp"],
+ name: "libprocessgroup",
+ shared_libs: ["libbase"],
+ export_include_dirs: ["include"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+}
diff --git a/libprocessgroup/Android.mk b/libprocessgroup/Android.mk
deleted file mode 100644
index 0bfc391..0000000
--- a/libprocessgroup/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := processgroup.cpp
-LOCAL_MODULE := libprocessgroup
-LOCAL_STATIC_LIBRARIES := libbase
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_CFLAGS := -Wall -Werror
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := processgroup.cpp
-LOCAL_MODULE := libprocessgroup
-LOCAL_SHARED_LIBRARIES := libbase
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_CFLAGS := -Wall -Werror
-include $(BUILD_SHARED_LIBRARY)
diff --git a/libsparse/output_file.c b/libsparse/output_file.c
index 2115998..51e60ef 100644
--- a/libsparse/output_file.c
+++ b/libsparse/output_file.c
@@ -584,7 +584,7 @@
.file_hdr_sz = SPARSE_HEADER_LEN,
.chunk_hdr_sz = CHUNK_HEADER_LEN,
.blk_sz = out->block_size,
- .total_blks = out->len / out->block_size,
+ .total_blks = DIV_ROUND_UP(out->len, out->block_size),
.total_chunks = chunks,
.image_checksum = 0
};
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index a6bea0c..ed46181 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -208,8 +208,7 @@
if (!__android_log_is_loggable(prio, tag, ANDROID_LOG_VERBOSE)) {
// Log traffic received to total
pthread_mutex_lock(&mLogElementsLock);
- stats.add(elem);
- stats.subtract(elem);
+ stats.addTotal(elem);
pthread_mutex_unlock(&mLogElementsLock);
delete elem;
return -EACCES;
@@ -320,8 +319,7 @@
pthread_mutex_unlock(&mLogElementsLock);
return len;
}
- stats.add(currentLast);
- stats.subtract(currentLast);
+ stats.addTotal(currentLast);
delete currentLast;
swab = total;
event->payload.data = htole32(swab);
@@ -337,8 +335,7 @@
}
}
if (count) {
- stats.add(currentLast);
- stats.subtract(currentLast);
+ stats.addTotal(currentLast);
currentLast->setDropped(count);
}
droppedElements[log_id] = currentLast;
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index d3167ad..b41aca5 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -15,6 +15,7 @@
*/
#include <fcntl.h>
+#include <inttypes.h>
#include <pwd.h>
#include <stdio.h>
#include <string.h>
@@ -70,20 +71,30 @@
}
}
+void LogStatistics::addTotal(LogBufferElement* element) {
+ if (element->getDropped()) return;
+
+ log_id_t log_id = element->getLogId();
+ unsigned short size = element->getMsgLen();
+ mSizesTotal[log_id] += size;
+ SizesTotal += size;
+ ++mElementsTotal[log_id];
+}
+
void LogStatistics::add(LogBufferElement* element) {
log_id_t log_id = element->getLogId();
unsigned short size = element->getMsgLen();
mSizes[log_id] += size;
++mElements[log_id];
+ // When caller adding a chatty entry, they will have already
+ // called add() and subtract() for each entry as they are
+ // evaluated and trimmed, thus recording size and number of
+ // elements, but we must recognize the manufactured dropped
+ // entry as not contributing to the lifetime totals.
if (element->getDropped()) {
++mDroppedElements[log_id];
} else {
- // When caller adding a chatty entry, they will have already
- // called add() and subtract() for each entry as they are
- // evaluated and trimmed, thus recording size and number of
- // elements, but we must recognize the manufactured dropped
- // entry as not contributing to the lifetime totals.
mSizesTotal[log_id] += size;
SizesTotal += size;
++mElementsTotal[log_id];
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index 066b7de..e171e4a 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -576,6 +576,7 @@
enable = true;
}
+ void addTotal(LogBufferElement* entry);
void add(LogBufferElement* entry);
void subtract(LogBufferElement* entry);
// entry->setDropped(1) must follow this call
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 56e736e..a94a717 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -245,10 +245,6 @@
class_stop charger
trigger late-init
-# Load properties from /system/ + /factory after fs mount.
-on load_system_props_action
- load_system_props
-
on load_persist_props_action
load_persist_props
start logd
@@ -269,11 +265,6 @@
trigger fs
trigger post-fs
- # Load properties from /system/ + /factory after fs mount. Place
- # this in another action so that the load will be scheduled after the prior
- # issued fs triggers have completed.
- trigger load_system_props_action
-
# Mount fstab in init.{$device}.rc by mount_all with '--late' parameter
# to only mount entries with 'latemount'. This is needed if '--early' is
# specified in the previous mount_all command on the fs stage.
@@ -298,6 +289,13 @@
trigger boot
on post-fs
+ # Load properties from
+ # /system/build.prop,
+ # /odm/build.prop,
+ # /vendor/build.prop and
+ # /factory/factory.prop
+ load_system_props
+ # start essential services
start logd
start hwservicemanager