Merge "Make native metrics logger write to statsd socket"
diff --git a/TEST_MAPPING b/TEST_MAPPING
new file mode 100644
index 0000000..c47230f
--- /dev/null
+++ b/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "adbd_test"
+ }
+ ]
+}
diff --git a/adb/adb.h b/adb/adb.h
index e2911e8..8c37c4b 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -59,7 +59,7 @@
std::string adb_version();
// Increment this when we want to force users to start a new adb server.
-#define ADB_SERVER_VERSION 40
+#define ADB_SERVER_VERSION 41
using TransportId = uint64_t;
class atransport;
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index bc184c5..6960345 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -293,6 +293,9 @@
struct passwd pwent;
struct passwd* result;
int pwent_max = sysconf(_SC_GETPW_R_SIZE_MAX);
+ if (pwent_max == -1) {
+ pwent_max = 16384;
+ }
std::vector<char> buf(pwent_max);
int rc = getpwuid_r(getuid(), &pwent, buf.data(), buf.size(), &result);
if (rc == 0 && result) {
@@ -341,3 +344,33 @@
return android::base::StringPrintf("%s/adb.%u.log", tmp_dir, getuid());
#endif
}
+
+[[noreturn]] static void error_exit_va(int error, const char* fmt, va_list va) {
+ fflush(stdout);
+ fprintf(stderr, "%s: ", android::base::Basename(android::base::GetExecutablePath()).c_str());
+
+ vfprintf(stderr, fmt, va);
+
+ if (error != 0) {
+ fprintf(stderr, ": %s", strerror(error));
+ }
+
+ putc('\n', stderr);
+ fflush(stderr);
+
+ exit(EXIT_FAILURE);
+}
+
+void error_exit(const char* fmt, ...) {
+ va_list va;
+ va_start(va, fmt);
+ error_exit_va(0, fmt, va);
+ va_end(va);
+}
+
+void perror_exit(const char* fmt, ...) {
+ va_list va;
+ va_start(va, fmt);
+ error_exit_va(errno, fmt, va);
+ va_end(va);
+}
diff --git a/adb/adb_utils.h b/adb/adb_utils.h
index 442ca2b..6d12225 100644
--- a/adb/adb_utils.h
+++ b/adb/adb_utils.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef _ADB_UTILS_H_
-#define _ADB_UTILS_H_
+#pragma once
#include <condition_variable>
#include <mutex>
@@ -47,9 +46,12 @@
std::string perror_str(const char* msg);
+[[noreturn]] void error_exit(const char* fmt, ...) __attribute__((__format__(__printf__, 1, 2)));
+[[noreturn]] void perror_exit(const char* fmt, ...) __attribute__((__format__(__printf__, 1, 2)));
+
bool set_file_block_mode(int fd, bool block);
-extern int adb_close(int fd);
+int adb_close(int fd);
// Given forward/reverse targets, returns true if they look sane. If an error is found, fills
// |error| and returns false.
@@ -92,5 +94,3 @@
};
std::string GetLogFilePath();
-
-#endif
diff --git a/adb/client/adb_install.cpp b/adb/client/adb_install.cpp
index e1b75b0..cf22efa 100644
--- a/adb/client/adb_install.cpp
+++ b/adb/client/adb_install.cpp
@@ -38,14 +38,22 @@
static constexpr int kFastDeployMinApi = 24;
-static bool _use_legacy_install() {
+static bool can_use_feature(const char* feature) {
FeatureSet features;
std::string error;
if (!adb_get_feature_set(&features, &error)) {
fprintf(stderr, "error: %s\n", error.c_str());
return true;
}
- return !CanUseFeature(features, kFeatureCmd);
+ return CanUseFeature(features, feature);
+}
+
+static bool use_legacy_install() {
+ return !can_use_feature(kFeatureCmd);
+}
+
+static bool is_apex_supported() {
+ return can_use_feature(kFeatureApex);
}
static int pm_command(int argc, const char** argv) {
@@ -102,7 +110,7 @@
}
int uninstall_app(int argc, const char** argv) {
- if (_use_legacy_install()) {
+ if (use_legacy_install()) {
return uninstall_app_legacy(argc, argv);
}
return uninstall_app_streamed(argc, argv);
@@ -133,8 +141,21 @@
// The last argument must be the APK file
const char* file = argv[argc - 1];
- if (!android::base::EndsWithIgnoreCase(file, ".apk")) {
- error(1, 0, "filename doesn't end .apk: %s", file);
+ if (!android::base::EndsWithIgnoreCase(file, ".apk") &&
+ !android::base::EndsWithIgnoreCase(file, ".apex")) {
+ error_exit("filename doesn't end .apk or .apex: %s", file);
+ }
+
+ bool is_apex = false;
+ if (android::base::EndsWithIgnoreCase(file, ".apex")) {
+ is_apex = true;
+ }
+ if (is_apex && !is_apex_supported()) {
+ error_exit(".apex is not supported on the target device");
+ }
+
+ if (is_apex && use_fastdeploy) {
+ error_exit("--fastdeploy doesn't support .apex files");
}
if (use_fastdeploy == true) {
@@ -177,6 +198,10 @@
// do last to override any user specified value
cmd += " " + android::base::StringPrintf("-S %" PRIu64, static_cast<uint64_t>(sb.st_size));
+ if (is_apex) {
+ cmd += " --apex";
+ }
+
int remoteFd = adb_connect(cmd, &error);
if (remoteFd < 0) {
fprintf(stderr, "adb: connect error for write: %s\n", error.c_str());
@@ -218,13 +243,16 @@
// All other arguments passed through verbatim.
int last_apk = -1;
for (int i = argc - 1; i >= 0; i--) {
+ if (android::base::EndsWithIgnoreCase(argv[i], ".apex")) {
+ error_exit("APEX packages are only compatible with Streamed Install");
+ }
if (android::base::EndsWithIgnoreCase(argv[i], ".apk")) {
last_apk = i;
break;
}
}
- if (last_apk == -1) error(1, 0, "need APK file on command line");
+ if (last_apk == -1) error_exit("need APK file on command line");
int result = -1;
std::vector<const char*> apk_file = {argv[last_apk]};
@@ -303,15 +331,15 @@
}
if (installMode == INSTALL_DEFAULT) {
- if (_use_legacy_install()) {
+ if (use_legacy_install()) {
installMode = INSTALL_PUSH;
} else {
installMode = INSTALL_STREAM;
}
}
- if (installMode == INSTALL_STREAM && _use_legacy_install() == true) {
- error(1, 0, "Attempting to use streaming install on unsupported device");
+ if (installMode == INSTALL_STREAM && use_legacy_install() == true) {
+ error_exit("Attempting to use streaming install on unsupported device");
}
if (use_fastdeploy == true && is_reinstall == false) {
@@ -359,6 +387,9 @@
uint64_t total_size = 0;
for (int i = argc - 1; i >= 0; i--) {
const char* file = argv[i];
+ if (android::base::EndsWithIgnoreCase(argv[i], ".apex")) {
+ error_exit("APEX packages are not compatible with install-multiple");
+ }
if (android::base::EndsWithIgnoreCase(file, ".apk") ||
android::base::EndsWithIgnoreCase(file, ".dm")) {
@@ -370,10 +401,10 @@
}
}
- if (first_apk == -1) error(1, 0, "need APK file on command line");
+ if (first_apk == -1) error_exit("need APK file on command line");
std::string install_cmd;
- if (_use_legacy_install()) {
+ if (use_legacy_install()) {
install_cmd = "exec:pm";
} else {
install_cmd = "exec:cmd package";
diff --git a/adb/client/bugreport.cpp b/adb/client/bugreport.cpp
index 83eb157..8ca44e8 100644
--- a/adb/client/bugreport.cpp
+++ b/adb/client/bugreport.cpp
@@ -197,7 +197,7 @@
};
int Bugreport::DoIt(int argc, const char** argv) {
- if (argc > 2) error(1, 0, "usage: adb bugreport [PATH]");
+ if (argc > 2) error_exit("usage: adb bugreport [PATH]");
// Gets bugreportz version.
std::string bugz_stdout, bugz_stderr;
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 0e03201..b5bed28 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -71,7 +71,7 @@
static std::string product_file(const std::string& file) {
const char* ANDROID_PRODUCT_OUT = getenv("ANDROID_PRODUCT_OUT");
if (ANDROID_PRODUCT_OUT == nullptr) {
- error(1, 0, "product directory not specified; set $ANDROID_PRODUCT_OUT");
+ error_exit("product directory not specified; set $ANDROID_PRODUCT_OUT");
}
return std::string{ANDROID_PRODUCT_OUT} + OS_PATH_SEPARATOR_STR + file;
}
@@ -204,8 +204,8 @@
" sideload OTAPACKAGE sideload the given full OTA package\n"
" root restart adbd with root permissions\n"
" unroot restart adbd without root permissions\n"
- " usb restart adb server listening on USB\n"
- " tcpip PORT restart adb server listening on TCP on PORT\n"
+ " usb restart adbd listening on USB\n"
+ " tcpip PORT restart adbd listening on TCP on PORT\n"
"\n"
"internal debugging:\n"
" start-server ensure that there is a server running\n"
@@ -684,7 +684,7 @@
switch (opt) {
case 'e':
if (!(strlen(optarg) == 1 || strcmp(optarg, "none") == 0)) {
- error(1, 0, "-e requires a single-character argument or 'none'");
+ error_exit("-e requires a single-character argument or 'none'");
}
escape_char = (strcmp(optarg, "none") == 0) ? 0 : optarg[0];
break;
@@ -932,21 +932,21 @@
*/
static int ppp(int argc, const char** argv) {
#if defined(_WIN32)
- error(1, 0, "adb %s not implemented on Win32", argv[0]);
+ error_exit("adb %s not implemented on Win32", argv[0]);
__builtin_unreachable();
#else
- if (argc < 2) error(1, 0, "usage: adb %s <adb service name> [ppp opts]", argv[0]);
+ if (argc < 2) error_exit("usage: adb %s <adb service name> [ppp opts]", argv[0]);
const char* adb_service_name = argv[1];
std::string error_message;
int fd = adb_connect(adb_service_name, &error_message);
if (fd < 0) {
- error(1, 0, "could not open adb service %s: %s", adb_service_name, error_message.c_str());
+ error_exit("could not open adb service %s: %s", adb_service_name, error_message.c_str());
}
pid_t pid = fork();
if (pid == -1) {
- error(1, errno, "fork failed");
+ perror_exit("fork failed");
}
if (pid == 0) {
@@ -968,7 +968,7 @@
adb_close(fd);
execvp("pppd", (char* const*)ppp_args);
- error(1, errno, "exec pppd failed");
+ perror_exit("exec pppd failed");
}
// parent side
@@ -1151,7 +1151,7 @@
/* find, extract, and use any -f argument */
for (int i = 1; i < argc; i++) {
if (!strcmp("-f", argv[i])) {
- if (i == argc - 1) error(1, 0, "backup -f passed with no filename");
+ if (i == argc - 1) error_exit("backup -f passed with no filename");
filename = argv[i+1];
for (int j = i+2; j <= argc; ) {
argv[i++] = argv[j++];
@@ -1163,7 +1163,7 @@
// Bare "adb backup" or "adb backup -f filename" are not valid invocations ---
// a list of packages is required.
- if (argc < 2) error(1, 0, "backup either needs a list of packages or -all/-shared");
+ if (argc < 2) error_exit("backup either needs a list of packages or -all/-shared");
adb_unlink(filename);
int outFd = adb_creat(filename, 0640);
@@ -1199,7 +1199,7 @@
}
static int restore(int argc, const char** argv) {
- if (argc != 2) error(1, 0, "restore requires an argument");
+ if (argc != 2) error_exit("restore requires an argument");
const char* filename = argv[1];
int tarFd = adb_open(filename, O_RDONLY);
@@ -1253,7 +1253,7 @@
} else if (!strcmp(*arg, "--")) {
ignore_flags = true;
} else {
- error(1, 0, "unrecognized option '%s'", *arg);
+ error_exit("unrecognized option '%s'", *arg);
}
}
++arg;
@@ -1331,7 +1331,7 @@
/* this is a special flag used only when the ADB client launches the ADB Server */
is_daemon = true;
} else if (!strcmp(argv[0], "--reply-fd")) {
- if (argc < 2) error(1, 0, "--reply-fd requires an argument");
+ if (argc < 2) error_exit("--reply-fd requires an argument");
const char* reply_fd_str = argv[1];
argc--;
argv++;
@@ -1344,7 +1344,7 @@
if (isdigit(argv[0][2])) {
serial = argv[0] + 2;
} else {
- if (argc < 2 || argv[0][2] != '\0') error(1, 0, "-s requires an argument");
+ if (argc < 2 || argv[0][2] != '\0') error_exit("-s requires an argument");
serial = argv[1];
argc--;
argv++;
@@ -1360,7 +1360,7 @@
}
transport_id = strtoll(id, const_cast<char**>(&id), 10);
if (*id != '\0') {
- error(1, 0, "invalid transport id");
+ error_exit("invalid transport id");
}
} else if (!strcmp(argv[0],"-d")) {
transport_type = kTransportUsb;
@@ -1370,7 +1370,7 @@
gListenAll = 1;
} else if (!strncmp(argv[0], "-H", 2)) {
if (argv[0][2] == '\0') {
- if (argc < 2) error(1, 0, "-H requires an argument");
+ if (argc < 2) error_exit("-H requires an argument");
server_host_str = argv[1];
argc--;
argv++;
@@ -1379,7 +1379,7 @@
}
} else if (!strncmp(argv[0], "-P", 2)) {
if (argv[0][2] == '\0') {
- if (argc < 2) error(1, 0, "-P requires an argument");
+ if (argc < 2) error_exit("-P requires an argument");
server_port_str = argv[1];
argc--;
argv++;
@@ -1387,7 +1387,7 @@
server_port_str = argv[0] + 2;
}
} else if (!strcmp(argv[0], "-L")) {
- if (argc < 2) error(1, 0, "-L requires an argument");
+ if (argc < 2) error_exit("-L requires an argument");
server_socket_str = argv[1];
argc--;
argv++;
@@ -1400,7 +1400,7 @@
}
if ((server_host_str || server_port_str) && server_socket_str) {
- error(1, 0, "-L is incompatible with -H or -P");
+ error_exit("-L is incompatible with -H or -P");
}
// If -L, -H, or -P are specified, ignore environment variables.
@@ -1417,10 +1417,10 @@
server_port_str = server_port_str ? server_port_str : getenv("ANDROID_ADB_SERVER_PORT");
if (server_port_str && strlen(server_port_str) > 0) {
if (!android::base::ParseInt(server_port_str, &server_port, 1, 65535)) {
- error(1, 0,
- "$ANDROID_ADB_SERVER_PORT must be a positive number less than 65535: "
- "got \"%s\"",
- server_port_str);
+ error_exit(
+ "$ANDROID_ADB_SERVER_PORT must be a positive number less than 65535: "
+ "got \"%s\"",
+ server_port_str);
}
}
@@ -1494,7 +1494,7 @@
} else if (argc == 2 && !strcmp(argv[1], "-l")) {
listopt = argv[1];
} else {
- error(1, 0, "adb devices [-l]");
+ error_exit("adb devices [-l]");
}
std::string query = android::base::StringPrintf("host:%s%s", argv[0], listopt);
@@ -1502,13 +1502,13 @@
return adb_query_command(query);
}
else if (!strcmp(argv[0], "connect")) {
- if (argc != 2) error(1, 0, "usage: adb connect <host>[:<port>]");
+ if (argc != 2) error_exit("usage: 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) error(1, 0, "usage: adb disconnect [<host>[:<port>]]");
+ if (argc > 2) error_exit("usage: adb disconnect [<host>[:<port>]]");
std::string query = android::base::StringPrintf("host:disconnect:%s",
(argc == 2) ? argv[1] : "");
@@ -1523,7 +1523,7 @@
else if (!strcmp(argv[0], "exec-in") || !strcmp(argv[0], "exec-out")) {
int exec_in = !strcmp(argv[0], "exec-in");
- if (argc < 2) error(1, 0, "usage: adb %s command", argv[0]);
+ if (argc < 2) error_exit("usage: adb %s command", argv[0]);
std::string cmd = "exec:";
cmd += argv[1];
@@ -1553,17 +1553,17 @@
return adb_kill_server() ? 0 : 1;
}
else if (!strcmp(argv[0], "sideload")) {
- if (argc != 2) error(1, 0, "sideload requires an argument");
+ if (argc != 2) error_exit("sideload requires an argument");
if (adb_sideload_host(argv[1])) {
return 1;
} else {
return 0;
}
} else if (!strcmp(argv[0], "tcpip")) {
- if (argc != 2) error(1, 0, "tcpip requires an argument");
+ if (argc != 2) error_exit("tcpip requires an argument");
int port;
if (!android::base::ParseInt(argv[1], &port, 1, 65535)) {
- error(1, 0, "tcpip: invalid port: %s", argv[1]);
+ error_exit("tcpip: invalid port: %s", argv[1]);
}
return adb_connect_command(android::base::StringPrintf("tcpip:%d", port));
}
@@ -1595,7 +1595,7 @@
} else if (!strcmp(argv[0], "forward") || !strcmp(argv[0], "reverse")) {
bool reverse = !strcmp(argv[0], "reverse");
--argc;
- if (argc < 1) error(1, 0, "%s requires an argument", argv[0]);
+ if (argc < 1) error_exit("%s requires an argument", argv[0]);
++argv;
// Determine the <host-prefix> for this command.
@@ -1616,37 +1616,37 @@
std::string cmd, error_message;
if (strcmp(argv[0], "--list") == 0) {
- if (argc != 1) error(1, 0, "--list doesn't take any arguments");
+ if (argc != 1) error_exit("--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) error(1, 0, "--remove-all doesn't take any arguments");
+ if (argc != 1) error_exit("--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) error(1, 0, "--remove requires an argument");
+ if (argc != 2) error_exit("--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) error(1, 0, "--no-rebind takes two arguments");
+ if (argc != 3) error_exit("--no-rebind takes two arguments");
if (forward_targets_are_valid(argv[1], argv[2], &error_message)) {
cmd = host_prefix + ":forward:norebind:" + argv[1] + ";" + argv[2];
}
} else {
// forward <local> <remote>
- if (argc != 2) error(1, 0, "forward takes two arguments");
+ if (argc != 2) error_exit("forward takes two arguments");
if (forward_targets_are_valid(argv[0], argv[1], &error_message)) {
cmd = host_prefix + ":forward:" + argv[0] + ";" + argv[1];
}
}
if (!error_message.empty()) {
- error(1, 0, "error: %s", error_message.c_str());
+ error_exit("error: %s", error_message.c_str());
}
int fd = adb_connect(cmd, &error_message);
if (fd < 0 || !adb_status(fd, &error_message)) {
adb_close(fd);
- error(1, 0, "error: %s", error_message.c_str());
+ error_exit("error: %s", error_message.c_str());
}
// Server or device may optionally return a resolved TCP port number.
@@ -1660,7 +1660,7 @@
}
/* do_sync_*() commands */
else if (!strcmp(argv[0], "ls")) {
- if (argc != 2) error(1, 0, "ls requires an argument");
+ if (argc != 2) error_exit("ls requires an argument");
return do_sync_ls(argv[1]) ? 0 : 1;
}
else if (!strcmp(argv[0], "push")) {
@@ -1670,7 +1670,7 @@
const char* dst = nullptr;
parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, ©_attrs, &sync);
- if (srcs.empty() || !dst) error(1, 0, "push requires an argument");
+ if (srcs.empty() || !dst) error_exit("push requires an argument");
return do_sync_push(srcs, dst, sync) ? 0 : 1;
}
else if (!strcmp(argv[0], "pull")) {
@@ -1679,19 +1679,19 @@
const char* dst = ".";
parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, ©_attrs, nullptr);
- if (srcs.empty()) error(1, 0, "pull requires an argument");
+ if (srcs.empty()) error_exit("pull requires an argument");
return do_sync_pull(srcs, dst, copy_attrs) ? 0 : 1;
}
else if (!strcmp(argv[0], "install")) {
- if (argc < 2) error(1, 0, "install requires an argument");
+ if (argc < 2) error_exit("install requires an argument");
return install_app(argc, argv);
}
else if (!strcmp(argv[0], "install-multiple")) {
- if (argc < 2) error(1, 0, "install-multiple requires an argument");
+ if (argc < 2) error_exit("install-multiple requires an argument");
return install_multiple_app(argc, argv);
}
else if (!strcmp(argv[0], "uninstall")) {
- if (argc < 2) error(1, 0, "uninstall requires an argument");
+ if (argc < 2) error_exit("uninstall requires an argument");
return uninstall_app(argc, argv);
}
else if (!strcmp(argv[0], "sync")) {
@@ -1705,7 +1705,7 @@
} else if (argc == 2) {
src = argv[1];
} else {
- error(1, 0, "usage: adb sync [-l] [PARTITION]");
+ error_exit("usage: adb sync [-l] [PARTITION]");
}
if (src.empty()) src = "all";
@@ -1720,7 +1720,7 @@
if (!do_sync_sync(src_dir, "/" + partition, list_only)) return 1;
}
}
- if (!found) error(1, 0, "don't know how to sync %s partition", src.c_str());
+ if (!found) error_exit("don't know how to sync %s partition", src.c_str());
return 0;
}
/* passthrough commands */
@@ -1752,7 +1752,7 @@
return restore(argc, argv);
}
else if (!strcmp(argv[0], "keygen")) {
- if (argc != 2) error(1, 0, "keygen requires an argument");
+ if (argc != 2) error_exit("keygen requires an argument");
// Always print key generation information for keygen command.
adb_trace_enable(AUTH);
return adb_auth_keygen(argv[1]);
@@ -1767,7 +1767,7 @@
return adb_connect_command("host:track-devices");
} else if (!strcmp(argv[0], "raw")) {
if (argc != 2) {
- error(1, 0, "usage: adb raw SERVICE");
+ error_exit("usage: adb raw SERVICE");
}
return adb_connect_command(argv[1]);
}
@@ -1810,11 +1810,11 @@
std::string err;
return adb_query_command("host:reconnect-offline");
} else {
- error(1, 0, "usage: adb reconnect [device|offline]");
+ error_exit("usage: adb reconnect [device|offline]");
}
}
}
- error(1, 0, "unknown command %s", argv[0]);
+ error_exit("unknown command %s", argv[0]);
__builtin_unreachable();
}
diff --git a/adb/client/fastdeploy.cpp b/adb/client/fastdeploy.cpp
index 933b913..45f3cca 100644
--- a/adb/client/fastdeploy.cpp
+++ b/adb/client/fastdeploy.cpp
@@ -28,7 +28,8 @@
#include "commandline.h"
#include "fastdeploycallbacks.h"
#include "sysdeps.h"
-#include "utils/String16.h"
+
+#include "adb_utils.h"
static constexpr long kRequiredAgentVersion = 0x00000001;
@@ -73,14 +74,14 @@
static std::string get_agent_component_host_path(const char* local_path, const char* sdk_path) {
std::string adb_dir = android::base::GetExecutableDirectory();
if (adb_dir.empty()) {
- error(1, 0, "Could not determine location of adb!");
+ error_exit("Could not determine location of adb!");
}
if (g_use_localagent) {
const char* product_out = getenv("ANDROID_PRODUCT_OUT");
if (product_out == nullptr) {
- error(1, 0, "Could not locate %s because $ANDROID_PRODUCT_OUT is not defined",
- local_path);
+ error_exit("Could not locate %s because $ANDROID_PRODUCT_OUT is not defined",
+ local_path);
}
return android::base::StringPrintf("%s%s", product_out, local_path);
} else {
@@ -105,10 +106,10 @@
android::base::StringPrintf(kChmodCommandPattern, kDeviceAgentPath);
int ret = send_shell_command(chmodCommand);
if (ret != 0) {
- error(1, 0, "Error executing %s returncode: %d", chmodCommand.c_str(), ret);
+ error_exit("Error executing %s returncode: %d", chmodCommand.c_str(), ret);
}
} else {
- error(1, 0, "Error pushing agent files to device");
+ error_exit("Error pushing agent files to device");
}
return true;
@@ -138,8 +139,8 @@
agent_version = get_agent_version();
if (agent_version != kRequiredAgentVersion) {
- error(1, 0, "After update agent version remains incorrect! Expected %ld but version is %ld",
- kRequiredAgentVersion, agent_version);
+ error_exit("After update agent version remains incorrect! Expected %ld but version is %ld",
+ kRequiredAgentVersion, agent_version);
}
}
@@ -159,24 +160,24 @@
std::unique_ptr<android::ZipFileRO> zipFile(android::ZipFileRO::open(apkPath));
#define open ___xxx_unix_open
if (zipFile == nullptr) {
- error(1, errno, "Could not open %s", apkPath);
+ perror_exit("Could not open %s", apkPath);
}
android::ZipEntryRO entry = zipFile->findEntryByName("AndroidManifest.xml");
if (entry == nullptr) {
- error(1, 0, "Could not find AndroidManifest.xml inside %s", apkPath);
+ error_exit("Could not find AndroidManifest.xml inside %s", apkPath);
}
uint32_t manifest_len = 0;
if (!zipFile->getEntryInfo(entry, NULL, &manifest_len, NULL, NULL, NULL, NULL)) {
- error(1, 0, "Could not read AndroidManifest.xml inside %s", apkPath);
+ error_exit("Could not read AndroidManifest.xml inside %s", apkPath);
}
std::vector<char> manifest_data(manifest_len);
if (!zipFile->uncompressEntry(entry, manifest_data.data(), manifest_len)) {
- error(1, 0, "Could not uncompress AndroidManifest.xml inside %s", apkPath);
+ error_exit("Could not uncompress AndroidManifest.xml inside %s", apkPath);
}
android::ResXMLTree tree;
android::status_t setto_status = tree.setTo(manifest_data.data(), manifest_len, true);
if (setto_status != android::OK) {
- error(1, 0, "Could not parse AndroidManifest.xml inside %s", apkPath);
+ error_exit("Could not parse AndroidManifest.xml inside %s", apkPath);
}
android::ResXMLParser::event_code_t code;
while ((code = tree.next()) != android::ResXMLParser::BAD_DOCUMENT &&
@@ -217,8 +218,7 @@
break;
}
}
- error(1, 0, "Could not find package name tag in AndroidManifest.xml inside %s", apkPath);
- __builtin_unreachable();
+ error_exit("Could not find package name tag in AndroidManifest.xml inside %s", apkPath);
}
void extract_metadata(const char* apkPath, FILE* outputFp) {
@@ -232,7 +232,7 @@
DeployAgentFileCallback cb(outputFp, &extractErrorBuffer, &statusCode);
int returnCode = send_shell_command(extractCommand, false, &cb);
if (returnCode != 0) {
- error(1, 0, "Executing %s returned %d", extractCommand.c_str(), returnCode);
+ error_exit("Executing %s returned %d", extractCommand.c_str(), returnCode);
}
}
@@ -241,9 +241,9 @@
// This should never happen on a Windows machine
const char* host_out = getenv("ANDROID_HOST_OUT");
if (host_out == nullptr) {
- error(1, 0,
- "Could not locate deploypatchgenerator.jar because $ANDROID_HOST_OUT "
- "is not defined");
+ error_exit(
+ "Could not locate deploypatchgenerator.jar because $ANDROID_HOST_OUT "
+ "is not defined");
}
return android::base::StringPrintf("java -jar %s/framework/deploypatchgenerator.jar",
host_out);
@@ -251,7 +251,7 @@
std::string adb_dir = android::base::GetExecutableDirectory();
if (adb_dir.empty()) {
- error(1, 0, "Could not locate deploypatchgenerator.jar");
+ error_exit("Could not locate deploypatchgenerator.jar");
}
return android::base::StringPrintf(R"(java -jar "%s/deploypatchgenerator.jar")",
adb_dir.c_str());
@@ -263,7 +263,7 @@
patchPath);
int returnCode = system(generatePatchCommand.c_str());
if (returnCode != 0) {
- error(1, 0, "Executing %s returned %d", generatePatchCommand.c_str(), returnCode);
+ error_exit("Executing %s returned %d", generatePatchCommand.c_str(), returnCode);
}
}
@@ -282,7 +282,7 @@
std::vector<const char*> srcs = {patchPath};
bool push_ok = do_sync_push(srcs, patchDevicePath.c_str(), false);
if (!push_ok) {
- error(1, 0, "Error pushing %s to %s returned", patchPath, patchDevicePath.c_str());
+ error_exit("Error pushing %s to %s returned", patchPath, patchDevicePath.c_str());
}
std::string applyPatchCommand =
@@ -291,7 +291,7 @@
int returnCode = send_shell_command(applyPatchCommand);
if (returnCode != 0) {
- error(1, 0, "Executing %s returned %d", applyPatchCommand.c_str(), returnCode);
+ error_exit("Executing %s returned %d", applyPatchCommand.c_str(), returnCode);
}
}
@@ -305,7 +305,7 @@
std::vector<const char*> srcs{patchPath};
bool push_ok = do_sync_push(srcs, patchDevicePath.c_str(), false);
if (!push_ok) {
- error(1, 0, "Error pushing %s to %s returned", patchPath, patchDevicePath.c_str());
+ error_exit("Error pushing %s to %s returned", patchPath, patchDevicePath.c_str());
}
std::vector<unsigned char> applyOutputBuffer;
@@ -322,6 +322,6 @@
patchDevicePath.c_str(), argsString.c_str());
int returnCode = send_shell_command(applyPatchCommand);
if (returnCode != 0) {
- error(1, 0, "Executing %s returned %d", applyPatchCommand.c_str(), returnCode);
+ error_exit("Executing %s returned %d", applyPatchCommand.c_str(), returnCode);
}
}
diff --git a/adb/client/file_sync_client.cpp b/adb/client/file_sync_client.cpp
index 697d9ea..f0f9a80 100644
--- a/adb/client/file_sync_client.cpp
+++ b/adb/client/file_sync_client.cpp
@@ -894,7 +894,8 @@
//
// TODO(b/25457350): We don't preserve permissions on directories.
// TODO: Find all of the leaves and `mkdir -p` them instead?
- if (CanUseFeature(sc.Features(), kFeatureShell2)) {
+ if (!CanUseFeature(sc.Features(), kFeatureFixedPushMkdir) &&
+ CanUseFeature(sc.Features(), kFeatureShell2)) {
SilentStandardStreamsCallbackInterface cb;
std::string cmd = "mkdir";
for (const auto& dir : directory_list) {
diff --git a/adb/daemon/framebuffer_service.cpp b/adb/daemon/framebuffer_service.cpp
index 586393e..2a6418a 100644
--- a/adb/daemon/framebuffer_service.cpp
+++ b/adb/daemon/framebuffer_service.cpp
@@ -32,6 +32,7 @@
#include "adb.h"
#include "adb_io.h"
+#include "adb_utils.h"
#include "fdevent.h"
/* TODO:
@@ -78,7 +79,7 @@
const char* command = "screencap";
const char *args[2] = {command, nullptr};
execvp(command, (char**)args);
- error(1, errno, "exec screencap failed");
+ perror_exit("exec screencap failed");
}
adb_close(fds[1]);
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index bebf4e6..b8d7e06 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -25,7 +25,6 @@
#endif
#include <errno.h>
-#include <error.h>
#include <string>
#include <vector>
@@ -70,8 +69,6 @@
#define OS_PATH_SEPARATOR_STR "\\"
#define ENV_PATH_SEPARATOR_STR ";"
-void error(int status, int error, const char* fmt, ...) __attribute__((__format__(printf, 3, 4)));
-
static __inline__ bool adb_is_separator(char c) {
return c == '\\' || c == '/';
}
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index af15241..8a6541d 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -2756,24 +2756,3 @@
return 0;
}
-
-void error(int status, int error, const char* fmt, ...) {
- fflush(stdout);
- fprintf(stderr, "%s: ", android::base::Basename(android::base::GetExecutablePath()).c_str());
-
- va_list ap;
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
-
- if (error != 0) {
- fprintf(stderr, ": %s", strerror(error));
- }
-
- putc('\n', stderr);
- fflush(stderr);
-
- if (status != 0) {
- exit(status);
- }
-}
diff --git a/adb/test_device.py b/adb/test_device.py
index c3166ff..34f8fd9 100755
--- a/adb/test_device.py
+++ b/adb/test_device.py
@@ -750,7 +750,7 @@
if host_dir is not None:
shutil.rmtree(host_dir)
- def test_push_empty(self):
+ def disabled_test_push_empty(self):
"""Push an empty directory to the device."""
self.device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR])
self.device.shell(['mkdir', self.DEVICE_TEMP_DIR])
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 0fbeec6..03a9f30 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -66,6 +66,8 @@
const char* const kFeatureStat2 = "stat_v2";
const char* const kFeatureLibusb = "libusb";
const char* const kFeaturePushSync = "push_sync";
+const char* const kFeatureApex = "apex";
+const char* const kFeatureFixedPushMkdir = "fixed_push_mkdir";
namespace {
@@ -1007,7 +1009,10 @@
const FeatureSet& supported_features() {
// Local static allocation to avoid global non-POD variables.
static const FeatureSet* features = new FeatureSet{
- kFeatureShell2, kFeatureCmd, kFeatureStat2,
+ kFeatureShell2, kFeatureCmd, kFeatureStat2, kFeatureFixedPushMkdir,
+#if ADB_HOST
+ kFeatureApex
+#endif
// Increment ADB_SERVER_VERSION whenever the feature list changes to
// make sure that the adb client and server features stay in sync
// (http://b/24370690).
diff --git a/adb/transport.h b/adb/transport.h
index 1350e63..9894bdf 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -57,8 +57,12 @@
extern const char* const kFeatureStat2;
// The server is running with libusb enabled.
extern const char* const kFeatureLibusb;
-// The server supports `push --sync`.
+// adbd supports `push --sync`.
extern const char* const kFeaturePushSync;
+// adbd supports installing .apex packages.
+extern const char* const kFeatureApex;
+// adbd has b/110953234 fixed.
+extern const char* const kFeatureFixedPushMkdir;
TransportId NextTransportId();
diff --git a/base/Android.bp b/base/Android.bp
index daa820a..741664b 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -47,6 +47,7 @@
"chrono_utils.cpp",
"file.cpp",
"logging.cpp",
+ "mapped_file.cpp",
"parsenetaddress.cpp",
"properties.cpp",
"quick_exit.cpp",
@@ -124,6 +125,7 @@
"file_test.cpp",
"logging_test.cpp",
"macros_test.cpp",
+ "mapped_file_test.cpp",
"parsedouble_test.cpp",
"parseint_test.cpp",
"parsenetaddress_test.cpp",
diff --git a/base/file.cpp b/base/file.cpp
index d6fe753..3834ed4 100644
--- a/base/file.cpp
+++ b/base/file.cpp
@@ -38,7 +38,6 @@
#endif
#if defined(_WIN32)
#include <windows.h>
-#define O_CLOEXEC O_NOINHERIT
#define O_NOFOLLOW 0
#endif
diff --git a/base/include/android-base/file.h b/base/include/android-base/file.h
index 908690b..8f9bf80 100644
--- a/base/include/android-base/file.h
+++ b/base/include/android-base/file.h
@@ -21,11 +21,17 @@
#include <string>
#if !defined(_WIN32) && !defined(O_BINARY)
+/** Windows needs O_BINARY, but Unix never mangles line endings. */
#define O_BINARY 0
#endif
+#if defined(_WIN32) && !defined(O_CLOEXEC)
+/** Windows has O_CLOEXEC but calls it O_NOINHERIT for some reason. */
+#define O_CLOEXEC O_NOINHERIT
+#endif
+
#if defined(__APPLE__)
-/* Mac OS has always had a 64-bit off_t, so it doesn't have off64_t. */
+/** Mac OS has always had a 64-bit off_t, so it doesn't have off64_t. */
typedef off_t off64_t;
#endif
diff --git a/base/include/android-base/macros.h b/base/include/android-base/macros.h
index 1748665..5abf514 100644
--- a/base/include/android-base/macros.h
+++ b/base/include/android-base/macros.h
@@ -75,46 +75,6 @@
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
-// ARRAYSIZE_UNSAFE performs essentially the same calculation as arraysize,
-// but can be used on anonymous types or types defined inside
-// functions. It's less safe than arraysize as it accepts some
-// (although not all) pointers. Therefore, you should use arraysize
-// whenever possible.
-//
-// The expression ARRAYSIZE_UNSAFE(a) is a compile-time constant of type
-// size_t.
-//
-// ARRAYSIZE_UNSAFE catches a few type errors. If you see a compiler error
-//
-// "warning: division by zero in ..."
-//
-// when using ARRAYSIZE_UNSAFE, you are (wrongfully) giving it a pointer.
-// You should only use ARRAYSIZE_UNSAFE on statically allocated arrays.
-//
-// The following comments are on the implementation details, and can
-// be ignored by the users.
-//
-// ARRAYSIZE_UNSAFE(arr) works by inspecting sizeof(arr) (the # of bytes in
-// the array) and sizeof(*(arr)) (the # of bytes in one array
-// element). If the former is divisible by the latter, perhaps arr is
-// indeed an array, in which case the division result is the # of
-// elements in the array. Otherwise, arr cannot possibly be an array,
-// and we generate a compiler error to prevent the code from
-// compiling.
-//
-// Since the size of bool is implementation-defined, we need to cast
-// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final
-// result has type size_t.
-//
-// This macro is not perfect as it wrongfully accepts certain
-// pointers, namely where the pointer size is divisible by the pointee
-// size. Since all our code has to go through a 32-bit compiler,
-// where a pointer is 4 bytes, this means all pointers to a type whose
-// size is 3 or greater than 4 will be (righteously) rejected.
-#define ARRAYSIZE_UNSAFE(a) \
- ((sizeof(a) / sizeof(*(a))) / \
- static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
-
#define SIZEOF_MEMBER(t, f) sizeof(std::declval<t>().f)
// Changing this definition will cause you a lot of pain. A majority of
@@ -153,23 +113,23 @@
// case 42:
// ...
//
-// As shown in the example above, the FALLTHROUGH_INTENDED macro should be
-// followed by a semicolon. It is designed to mimic control-flow statements
-// like 'break;', so it can be placed in most places where 'break;' can, but
-// only if there are no statements on the execution path between it and the
-// next switch label.
+// As shown in the example above, the FALLTHROUGH_INTENDED macro should be
+// followed by a semicolon. It is designed to mimic control-flow statements
+// like 'break;', so it can be placed in most places where 'break;' can, but
+// only if there are no statements on the execution path between it and the
+// next switch label.
//
-// When compiled with clang, the FALLTHROUGH_INTENDED macro is expanded to
-// [[clang::fallthrough]] attribute, which is analysed when performing switch
-// labels fall-through diagnostic ('-Wimplicit-fallthrough'). See clang
-// documentation on language extensions for details:
-// http://clang.llvm.org/docs/LanguageExtensions.html#clang__fallthrough
+// When compiled with clang, the FALLTHROUGH_INTENDED macro is expanded to
+// [[clang::fallthrough]] attribute, which is analysed when performing switch
+// labels fall-through diagnostic ('-Wimplicit-fallthrough'). See clang
+// documentation on language extensions for details:
+// http://clang.llvm.org/docs/LanguageExtensions.html#clang__fallthrough
//
-// When used with unsupported compilers, the FALLTHROUGH_INTENDED macro has no
-// effect on diagnostics.
+// When used with unsupported compilers, the FALLTHROUGH_INTENDED macro has no
+// effect on diagnostics.
//
-// In either case this macro has no effect on runtime behavior and performance
-// of code.
+// In either case this macro has no effect on runtime behavior and performance
+// of code.
#ifndef FALLTHROUGH_INTENDED
#define FALLTHROUGH_INTENDED [[clang::fallthrough]] // NOLINT
#endif
diff --git a/base/include/android-base/mapped_file.h b/base/include/android-base/mapped_file.h
new file mode 100644
index 0000000..52d11ed
--- /dev/null
+++ b/base/include/android-base/mapped_file.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+#include "android-base/macros.h"
+
+#include <sys/types.h>
+
+#include <memory>
+
+#if defined(_WIN32)
+#include <windows.h>
+#define PROT_READ 1
+#define PROT_WRITE 2
+#else
+#include <sys/mman.h>
+#endif
+
+namespace android {
+namespace base {
+
+/**
+ * A region of a file mapped into memory.
+ */
+class MappedFile {
+ public:
+ /**
+ * Creates a new mapping of the file pointed to by `fd`. Unlike the underlying OS primitives,
+ * `offset` does not need to be page-aligned. If `PROT_WRITE` is set in `prot`, the mapping
+ * will be writable, otherwise it will be read-only. Mappings are always `MAP_SHARED`.
+ */
+ static std::unique_ptr<MappedFile> FromFd(int fd, off64_t offset, size_t length, int prot);
+
+ /**
+ * Removes the mapping.
+ */
+ ~MappedFile();
+
+ char* data() { return base_ + offset_; }
+ size_t size() { return size_; }
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(MappedFile);
+
+ char* base_;
+ size_t size_;
+
+ size_t offset_;
+
+#if defined(_WIN32)
+ MappedFile(char* base, size_t size, size_t offset, HANDLE handle)
+ : base_(base), size_(size), offset_(offset), handle_(handle) {}
+ HANDLE handle_;
+#else
+ MappedFile(char* base, size_t size, size_t offset) : base_(base), size_(size), offset_(offset) {}
+#endif
+};
+
+} // namespace base
+} // namespace android
diff --git a/base/mapped_file.cpp b/base/mapped_file.cpp
new file mode 100644
index 0000000..f7901af
--- /dev/null
+++ b/base/mapped_file.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2018 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 "android-base/mapped_file.h"
+
+namespace android {
+namespace base {
+
+static off64_t InitPageSize() {
+#if defined(_WIN32)
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ return si.dwAllocationGranularity;
+#else
+ return sysconf(_SC_PAGE_SIZE);
+#endif
+}
+
+std::unique_ptr<MappedFile> MappedFile::FromFd(int fd, off64_t offset, size_t length, int prot) {
+ static off64_t page_size = InitPageSize();
+ size_t slop = offset % page_size;
+ off64_t file_offset = offset - slop;
+ off64_t file_length = length + slop;
+
+#if defined(_WIN32)
+ HANDLE handle =
+ CreateFileMapping(reinterpret_cast<HANDLE>(_get_osfhandle(fd)), nullptr,
+ (prot & PROT_WRITE) ? PAGE_READWRITE : PAGE_READONLY, 0, 0, nullptr);
+ if (handle == nullptr) return nullptr;
+ void* base = MapViewOfFile(handle, (prot & PROT_WRITE) ? FILE_MAP_ALL_ACCESS : FILE_MAP_READ, 0,
+ file_offset, file_length);
+ if (base == nullptr) {
+ CloseHandle(handle);
+ return nullptr;
+ }
+ return std::unique_ptr<MappedFile>(
+ new MappedFile{static_cast<char*>(base), length, slop, handle});
+#else
+ void* base = mmap(nullptr, file_length, prot, MAP_SHARED, fd, file_offset);
+ if (base == MAP_FAILED) return nullptr;
+ return std::unique_ptr<MappedFile>(new MappedFile{static_cast<char*>(base), length, slop});
+#endif
+}
+
+MappedFile::~MappedFile() {
+#if defined(_WIN32)
+ if (base_ != nullptr) UnmapViewOfFile(base_);
+ if (handle_ != nullptr) CloseHandle(handle_);
+#else
+ if (base_ != nullptr) munmap(base_, size_);
+#endif
+
+ base_ = nullptr;
+ offset_ = size_ = 0;
+}
+
+} // namespace base
+} // namespace android
diff --git a/base/mapped_file_test.cpp b/base/mapped_file_test.cpp
new file mode 100644
index 0000000..57fde6f
--- /dev/null
+++ b/base/mapped_file_test.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2018 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 "android-base/mapped_file.h"
+
+#include <gtest/gtest.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <string>
+
+#include "android-base/file.h"
+#include "android-base/test_utils.h"
+#include "android-base/unique_fd.h"
+
+TEST(mapped_file, smoke) {
+ TemporaryFile tf;
+ ASSERT_TRUE(tf.fd != -1);
+ ASSERT_TRUE(android::base::WriteStringToFd("hello world", tf.fd));
+
+ auto m = android::base::MappedFile::FromFd(tf.fd, 3, 2, PROT_READ);
+ ASSERT_EQ(2u, m->size());
+ ASSERT_EQ('l', m->data()[0]);
+ ASSERT_EQ('o', m->data()[1]);
+}
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 6b6e659..5101410 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -79,10 +79,6 @@
using android::base::Trim;
using android::base::unique_fd;
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
static const char* serial = nullptr;
static bool g_long_listing = false;
diff --git a/fastboot/fastboot_driver.cpp b/fastboot/fastboot_driver.cpp
index b1f3bc9..65a5247 100644
--- a/fastboot/fastboot_driver.cpp
+++ b/fastboot/fastboot_driver.cpp
@@ -41,10 +41,10 @@
#include <vector>
#include <android-base/file.h>
+#include <android-base/mapped_file.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
-#include <utils/FileMap.h>
#include "constants.h"
#include "transport.h"
@@ -467,15 +467,14 @@
while (remaining) {
// Memory map the file
- android::FileMap filemap;
size_t len = std::min(remaining, MAX_MAP_SIZE);
-
- if (!filemap.create(NULL, fd, offset, len, true)) {
+ auto mapping{android::base::MappedFile::FromFd(fd, offset, len, PROT_READ)};
+ if (!mapping) {
error_ = "Creating filemap failed";
return IO_ERROR;
}
- if ((ret = SendBuffer(filemap.getDataPtr(), len))) {
+ if ((ret = SendBuffer(mapping->data(), mapping->size()))) {
return ret;
}
diff --git a/fs_mgr/fs_mgr_dm_linear.cpp b/fs_mgr/fs_mgr_dm_linear.cpp
index 804069a..6ddd5a8 100644
--- a/fs_mgr/fs_mgr_dm_linear.cpp
+++ b/fs_mgr/fs_mgr_dm_linear.cpp
@@ -33,6 +33,7 @@
#include <sstream>
+#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
@@ -50,8 +51,21 @@
using DmTargetZero = android::dm::DmTargetZero;
using DmTargetLinear = android::dm::DmTargetLinear;
-static bool CreateDmTable(const std::string& block_device, const LpMetadata& metadata,
- const LpMetadataPartition& partition, DmTable* table) {
+bool GetPhysicalPartitionDevicePath(const LpMetadataBlockDevice& block_device,
+ std::string* result) {
+ // Note: device-mapper will not accept symlinks, so we must use realpath
+ // here.
+ std::string name = GetBlockDevicePartitionName(block_device);
+ std::string path = "/dev/block/by-name/" + name;
+ if (!android::base::Realpath(path, result)) {
+ PERROR << "realpath: " << path;
+ return false;
+ }
+ return true;
+}
+
+static bool CreateDmTable(const LpMetadata& metadata, const LpMetadataPartition& partition,
+ DmTable* table) {
uint64_t sector = 0;
for (size_t i = 0; i < partition.num_extents; i++) {
const auto& extent = metadata.extents[partition.first_extent_index + i];
@@ -60,10 +74,22 @@
case LP_TARGET_TYPE_ZERO:
target = std::make_unique<DmTargetZero>(sector, extent.num_sectors);
break;
- case LP_TARGET_TYPE_LINEAR:
- target = std::make_unique<DmTargetLinear>(sector, extent.num_sectors, block_device,
+ case LP_TARGET_TYPE_LINEAR: {
+ auto block_device = GetMetadataSuperBlockDevice(metadata);
+ if (!block_device) {
+ LOG(ERROR) << "Could not identify the super block device";
+ return false;
+ }
+
+ std::string path;
+ if (!GetPhysicalPartitionDevicePath(*block_device, &path)) {
+ LOG(ERROR) << "Unable to complete device-mapper table, unknown block device";
+ return false;
+ }
+ target = std::make_unique<DmTargetLinear>(sector, extent.num_sectors, path,
extent.target_data);
break;
+ }
default:
LOG(ERROR) << "Unknown target type in metadata: " << extent.target_type;
return false;
@@ -79,13 +105,13 @@
return true;
}
-static bool CreateLogicalPartition(const std::string& block_device, const LpMetadata& metadata,
- const LpMetadataPartition& partition, bool force_writable,
- const std::chrono::milliseconds& timeout_ms, std::string* path) {
+static bool CreateLogicalPartition(const LpMetadata& metadata, const LpMetadataPartition& partition,
+ bool force_writable, const std::chrono::milliseconds& timeout_ms,
+ std::string* path) {
DeviceMapper& dm = DeviceMapper::Instance();
DmTable table;
- if (!CreateDmTable(block_device, metadata, partition, &table)) {
+ if (!CreateDmTable(metadata, partition, &table)) {
return false;
}
if (force_writable) {
@@ -122,7 +148,7 @@
continue;
}
std::string path;
- if (!CreateLogicalPartition(block_device, *metadata.get(), partition, false, {}, &path)) {
+ if (!CreateLogicalPartition(*metadata.get(), partition, false, {}, &path)) {
LERROR << "Could not create logical partition: " << GetPartitionName(partition);
return false;
}
@@ -140,8 +166,8 @@
}
for (const auto& partition : metadata->partitions) {
if (GetPartitionName(partition) == partition_name) {
- return CreateLogicalPartition(block_device, *metadata.get(), partition, force_writable,
- timeout_ms, path);
+ return CreateLogicalPartition(*metadata.get(), partition, force_writable, timeout_ms,
+ path);
}
}
LERROR << "Could not find any partition with name: " << partition_name;
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 64e9fb4..ad488a9 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -590,6 +590,7 @@
// Mount kScratchMountPoint
bool fs_mgr_overlayfs_mount_scratch(const std::string& device_path, const std::string mnt_type) {
+ if (!fs_mgr_rw_access(device_path)) return false;
if (setfscreatecon(kOverlayfsFileContext)) {
PERROR << "setfscreatecon " << kOverlayfsFileContext;
}
@@ -826,6 +827,19 @@
if (change) *change = false;
mount_point = fs_mgr_mount_point(mount_point);
auto ret = true;
+ // If scratch exists, but is not mounted, lets gain access to clean
+ // specific override entries.
+ if ((mount_point != nullptr) && !fs_mgr_overlayfs_already_mounted(kScratchMountPoint, false)) {
+ auto scratch_device = fs_mgr_overlayfs_scratch_device();
+ if (scratch_device.empty()) {
+ auto slot_number = fs_mgr_overlayfs_slot_number();
+ auto super_device = fs_mgr_overlayfs_super_device(slot_number);
+ const auto partition_name = android::base::Basename(kScratchMountPoint);
+ CreateLogicalPartition(super_device, slot_number, partition_name, true, 0s,
+ &scratch_device);
+ }
+ fs_mgr_overlayfs_mount_scratch(scratch_device, fs_mgr_overlayfs_scratch_mount_type());
+ }
for (const auto& overlay_mount_point : kOverlayMountPoints) {
ret &= fs_mgr_overlayfs_teardown_one(overlay_mount_point, mount_point ?: "", change);
}
diff --git a/fs_mgr/liblp/Android.bp b/fs_mgr/liblp/Android.bp
index bbdec5b..5689bdf 100644
--- a/fs_mgr/liblp/Android.bp
+++ b/fs_mgr/liblp/Android.bp
@@ -25,6 +25,7 @@
srcs: [
"builder.cpp",
"images.cpp",
+ "partition_opener.cpp",
"reader.cpp",
"utility.cpp",
"writer.cpp",
@@ -47,6 +48,9 @@
cppflags: [
"-Wno-unused-parameter",
],
+ static_libs: [
+ "libgmock",
+ ],
shared_libs: [
"liblp",
"libbase",
@@ -56,6 +60,7 @@
srcs: [
"builder_test.cpp",
"io_test.cpp",
+ "test_partition_opener.cpp",
"utility_test.cpp",
],
}
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp
index 963e1b3..1b8ed57 100644
--- a/fs_mgr/liblp/builder.cpp
+++ b/fs_mgr/liblp/builder.cpp
@@ -16,11 +16,7 @@
#include "liblp/builder.h"
-#if defined(__linux__)
-#include <linux/fs.h>
-#endif
#include <string.h>
-#include <sys/ioctl.h>
#include <algorithm>
@@ -33,43 +29,6 @@
namespace android {
namespace fs_mgr {
-bool GetBlockDeviceInfo(const std::string& block_device, BlockDeviceInfo* device_info) {
-#if defined(__linux__)
- android::base::unique_fd fd(open(block_device.c_str(), O_RDONLY));
- if (fd < 0) {
- PERROR << __PRETTY_FUNCTION__ << "open '" << block_device << "' failed";
- return false;
- }
- if (!GetDescriptorSize(fd, &device_info->size)) {
- return false;
- }
- if (ioctl(fd, BLKIOMIN, &device_info->alignment) < 0) {
- PERROR << __PRETTY_FUNCTION__ << "BLKIOMIN failed";
- return false;
- }
-
- int alignment_offset;
- if (ioctl(fd, BLKALIGNOFF, &alignment_offset) < 0) {
- PERROR << __PRETTY_FUNCTION__ << "BLKIOMIN failed";
- return false;
- }
- int logical_block_size;
- if (ioctl(fd, BLKSSZGET, &logical_block_size) < 0) {
- PERROR << __PRETTY_FUNCTION__ << "BLKSSZGET failed";
- return false;
- }
-
- device_info->alignment_offset = static_cast<uint32_t>(alignment_offset);
- device_info->logical_block_size = static_cast<uint32_t>(logical_block_size);
- return true;
-#else
- (void)block_device;
- (void)device_info;
- LERROR << __PRETTY_FUNCTION__ << ": Not supported on this operating system.";
- return false;
-#endif
-}
-
void LinearExtent::AddTo(LpMetadata* out) const {
out->extents.push_back(LpMetadataExtent{num_sectors_, LP_TARGET_TYPE_LINEAR, physical_sector_});
}
@@ -138,9 +97,10 @@
return sectors * LP_SECTOR_SIZE;
}
-std::unique_ptr<MetadataBuilder> MetadataBuilder::New(const std::string& block_device,
+std::unique_ptr<MetadataBuilder> MetadataBuilder::New(const IPartitionOpener& opener,
+ const std::string& super_partition,
uint32_t slot_number) {
- std::unique_ptr<LpMetadata> metadata = ReadMetadata(block_device.c_str(), slot_number);
+ std::unique_ptr<LpMetadata> metadata = ReadMetadata(opener, super_partition, slot_number);
if (!metadata) {
return nullptr;
}
@@ -149,12 +109,17 @@
return nullptr;
}
BlockDeviceInfo device_info;
- if (fs_mgr::GetBlockDeviceInfo(block_device, &device_info)) {
+ if (opener.GetInfo(super_partition, &device_info)) {
builder->UpdateBlockDeviceInfo(device_info);
}
return builder;
}
+std::unique_ptr<MetadataBuilder> MetadataBuilder::New(const std::string& super_partition,
+ uint32_t slot_number) {
+ return New(PartitionOpener(), super_partition, slot_number);
+}
+
std::unique_ptr<MetadataBuilder> MetadataBuilder::New(const BlockDeviceInfo& device_info,
uint32_t metadata_max_size,
uint32_t metadata_slot_count) {
@@ -186,6 +151,7 @@
header_.partitions.entry_size = sizeof(LpMetadataPartition);
header_.extents.entry_size = sizeof(LpMetadataExtent);
header_.groups.entry_size = sizeof(LpMetadataPartitionGroup);
+ header_.block_devices.entry_size = sizeof(LpMetadataBlockDevice);
}
bool MetadataBuilder::Init(const LpMetadata& metadata) {
@@ -198,6 +164,10 @@
}
}
+ for (const auto& block_device : metadata.block_devices) {
+ block_devices_.push_back(block_device);
+ }
+
for (const auto& partition : metadata.partitions) {
std::string group_name = GetPartitionGroupName(metadata.groups[partition.group_index]);
Partition* builder =
@@ -259,9 +229,7 @@
// We reserve a geometry block (4KB) plus space for each copy of the
// maximum size of a metadata blob. Then, we double that space since
// we store a backup copy of everything.
- uint64_t reserved =
- LP_METADATA_GEOMETRY_SIZE + (uint64_t(metadata_max_size) * metadata_slot_count);
- uint64_t total_reserved = LP_PARTITION_RESERVED_BYTES + reserved * 2;
+ uint64_t total_reserved = GetTotalMetadataSize(metadata_max_size, metadata_slot_count);
if (device_info.size < total_reserved) {
LERROR << "Attempting to create metadata on a block device that is too small.";
return false;
@@ -285,12 +253,16 @@
return false;
}
- geometry_.first_logical_sector = first_sector;
+ block_devices_.push_back(LpMetadataBlockDevice{
+ first_sector,
+ device_info.alignment,
+ device_info.alignment_offset,
+ device_info.size,
+ "super",
+ });
+
geometry_.metadata_max_size = metadata_max_size;
geometry_.metadata_slot_count = metadata_slot_count;
- geometry_.alignment = device_info.alignment;
- geometry_.alignment_offset = device_info.alignment_offset;
- geometry_.block_device_size = device_info.size;
geometry_.logical_block_size = device_info.logical_block_size;
if (!AddGroup("default", 0)) {
@@ -339,7 +311,7 @@
return nullptr;
}
-PartitionGroup* MetadataBuilder::FindGroup(const std::string& group_name) const {
+PartitionGroup* MetadataBuilder::FindGroup(const std::string& group_name) {
for (const auto& group : groups_) {
if (group->name() == group_name) {
return group.get();
@@ -408,9 +380,10 @@
}
// Add 0-length intervals for the first and last sectors. This will cause
- // ExtentsToFreeList() to treat the space in between as available.
- uint64_t last_sector = geometry_.block_device_size / LP_SECTOR_SIZE;
- extents.emplace_back(geometry_.first_logical_sector, geometry_.first_logical_sector);
+ // ExtentToFreeList() to treat the space in between as available.
+ uint64_t first_sector = super_device().first_logical_sector;
+ uint64_t last_sector = super_device().size / LP_SECTOR_SIZE;
+ extents.emplace_back(first_sector, first_sector);
extents.emplace_back(last_sector, last_sector);
std::sort(extents.begin(), extents.end());
@@ -547,14 +520,18 @@
metadata->partitions.push_back(part);
}
+ metadata->block_devices = block_devices_;
+
metadata->header.partitions.num_entries = static_cast<uint32_t>(metadata->partitions.size());
metadata->header.extents.num_entries = static_cast<uint32_t>(metadata->extents.size());
metadata->header.groups.num_entries = static_cast<uint32_t>(metadata->groups.size());
+ metadata->header.block_devices.num_entries =
+ static_cast<uint32_t>(metadata->block_devices.size());
return metadata;
}
uint64_t MetadataBuilder::AllocatableSpace() const {
- return geometry_.block_device_size - (geometry_.first_logical_sector * LP_SECTOR_SIZE);
+ return super_device().size - (super_device().first_logical_sector * LP_SECTOR_SIZE);
}
uint64_t MetadataBuilder::UsedSpace() const {
@@ -569,22 +546,22 @@
// Note: when reading alignment info from the Kernel, we don't assume it
// is aligned to the sector size, so we round up to the nearest sector.
uint64_t lba = sector * LP_SECTOR_SIZE;
- uint64_t aligned = AlignTo(lba, geometry_.alignment, geometry_.alignment_offset);
+ uint64_t aligned = AlignTo(lba, super_device().alignment, super_device().alignment_offset);
return AlignTo(aligned, LP_SECTOR_SIZE) / LP_SECTOR_SIZE;
}
bool MetadataBuilder::GetBlockDeviceInfo(BlockDeviceInfo* info) const {
- info->size = geometry_.block_device_size;
- info->alignment = geometry_.alignment;
- info->alignment_offset = geometry_.alignment_offset;
+ info->size = super_device().size;
+ info->alignment = super_device().alignment;
+ info->alignment_offset = super_device().alignment_offset;
info->logical_block_size = geometry_.logical_block_size;
return true;
}
bool MetadataBuilder::UpdateBlockDeviceInfo(const BlockDeviceInfo& device_info) {
- if (device_info.size != geometry_.block_device_size) {
+ if (device_info.size != super_device().size) {
LERROR << "Device size does not match (got " << device_info.size << ", expected "
- << geometry_.block_device_size << ")";
+ << super_device().size << ")";
return false;
}
if (device_info.logical_block_size != geometry_.logical_block_size) {
@@ -596,10 +573,10 @@
// The kernel does not guarantee these values are present, so we only
// replace existing values if the new values are non-zero.
if (device_info.alignment) {
- geometry_.alignment = device_info.alignment;
+ super_device().alignment = device_info.alignment;
}
if (device_info.alignment_offset) {
- geometry_.alignment_offset = device_info.alignment_offset;
+ super_device().alignment_offset = device_info.alignment_offset;
}
return true;
}
@@ -624,5 +601,36 @@
return true;
}
+std::vector<std::string> MetadataBuilder::ListGroups() const {
+ std::vector<std::string> names;
+ for (const auto& group : groups_) {
+ names.emplace_back(group->name());
+ }
+ return names;
+}
+
+void MetadataBuilder::RemoveGroupAndPartitions(const std::string& group_name) {
+ if (group_name == "default") {
+ // Cannot remove the default group.
+ return;
+ }
+ std::vector<std::string> partition_names;
+ for (const auto& partition : partitions_) {
+ if (partition->group_name() == group_name) {
+ partition_names.emplace_back(partition->name());
+ }
+ }
+
+ for (const auto& partition_name : partition_names) {
+ RemovePartition(partition_name);
+ }
+ for (auto iter = groups_.begin(); iter != groups_.end(); iter++) {
+ if ((*iter)->name() == group_name) {
+ groups_.erase(iter);
+ break;
+ }
+ }
+}
+
} // namespace fs_mgr
} // namespace android
diff --git a/fs_mgr/liblp/builder_test.cpp b/fs_mgr/liblp/builder_test.cpp
index f72b8e1..c02242a 100644
--- a/fs_mgr/liblp/builder_test.cpp
+++ b/fs_mgr/liblp/builder_test.cpp
@@ -14,13 +14,16 @@
* limitations under the License.
*/
+#include <fs_mgr.h>
+#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <liblp/builder.h>
-#include "fs_mgr.h"
+
#include "utility.h"
using namespace std;
using namespace android::fs_mgr;
+using ::testing::ElementsAre;
TEST(liblp, BuildBasic) {
unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(1024 * 1024, 1024, 2);
@@ -129,7 +132,9 @@
ASSERT_NE(builder, nullptr);
unique_ptr<LpMetadata> exported = builder->Export();
ASSERT_NE(exported, nullptr);
- EXPECT_EQ(exported->geometry.first_logical_sector, 1536);
+ auto super_device = GetMetadataSuperBlockDevice(*exported.get());
+ ASSERT_NE(super_device, nullptr);
+ EXPECT_EQ(super_device->first_logical_sector, 1536);
// Test a large alignment offset thrown in.
device_info.alignment_offset = 753664;
@@ -137,7 +142,9 @@
ASSERT_NE(builder, nullptr);
exported = builder->Export();
ASSERT_NE(exported, nullptr);
- EXPECT_EQ(exported->geometry.first_logical_sector, 1472);
+ super_device = GetMetadataSuperBlockDevice(*exported.get());
+ ASSERT_NE(super_device, nullptr);
+ EXPECT_EQ(super_device->first_logical_sector, 1472);
// Alignment offset without alignment doesn't mean anything.
device_info.alignment = 0;
@@ -151,7 +158,9 @@
ASSERT_NE(builder, nullptr);
exported = builder->Export();
ASSERT_NE(exported, nullptr);
- EXPECT_EQ(exported->geometry.first_logical_sector, 174);
+ super_device = GetMetadataSuperBlockDevice(*exported.get());
+ ASSERT_NE(super_device, nullptr);
+ EXPECT_EQ(super_device->first_logical_sector, 174);
// Test a small alignment with no alignment offset.
device_info.alignment = 11 * 1024;
@@ -159,7 +168,9 @@
ASSERT_NE(builder, nullptr);
exported = builder->Export();
ASSERT_NE(exported, nullptr);
- EXPECT_EQ(exported->geometry.first_logical_sector, 160);
+ super_device = GetMetadataSuperBlockDevice(*exported.get());
+ ASSERT_NE(super_device, nullptr);
+ EXPECT_EQ(super_device->first_logical_sector, 160);
}
TEST(liblp, InternalPartitionAlignment) {
@@ -289,6 +300,9 @@
unique_ptr<LpMetadata> exported = builder->Export();
EXPECT_NE(exported, nullptr);
+ auto super_device = GetMetadataSuperBlockDevice(*exported.get());
+ ASSERT_NE(super_device, nullptr);
+
// Verify geometry. Some details of this may change if we change the
// metadata structures. So in addition to checking the exact values, we
// also check that they are internally consistent after.
@@ -297,11 +311,11 @@
EXPECT_EQ(geometry.struct_size, sizeof(geometry));
EXPECT_EQ(geometry.metadata_max_size, 1024);
EXPECT_EQ(geometry.metadata_slot_count, 2);
- EXPECT_EQ(geometry.first_logical_sector, 32);
+ EXPECT_EQ(super_device->first_logical_sector, 32);
static const size_t kMetadataSpace =
((kMetadataSize * kMetadataSlots) + LP_METADATA_GEOMETRY_SIZE) * 2;
- EXPECT_GE(geometry.first_logical_sector * LP_SECTOR_SIZE, kMetadataSpace);
+ EXPECT_GE(super_device->first_logical_sector * LP_SECTOR_SIZE, kMetadataSpace);
// Verify header.
const LpMetadataHeader& header = exported->header;
@@ -410,13 +424,10 @@
fs_mgr_free_fstab);
ASSERT_NE(fstab, nullptr);
- // This should read from the "super" partition once we have a well-defined
- // way to access it.
- struct fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab.get(), "/data");
- ASSERT_NE(rec, nullptr);
+ PartitionOpener opener;
BlockDeviceInfo device_info;
- ASSERT_TRUE(GetBlockDeviceInfo(rec->blk_device, &device_info));
+ ASSERT_TRUE(opener.GetInfo(fs_mgr_get_super_partition_name(), &device_info));
// Sanity check that the device doesn't give us some weird inefficient
// alignment.
@@ -542,3 +553,30 @@
p = builder->AddPartition("vendor_a", "foo_a", 0);
ASSERT_TRUE(p && builder->ResizePartition(p, 1_GiB));
}
+
+TEST(liblp, ListGroups) {
+ BlockDeviceInfo device_info(1024 * 1024, 0, 0, 4096);
+ unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
+ ASSERT_NE(builder, nullptr);
+ ASSERT_TRUE(builder->AddGroup("example", 0));
+
+ std::vector<std::string> groups = builder->ListGroups();
+ ASSERT_THAT(groups, ElementsAre("default", "example"));
+}
+
+TEST(liblp, RemoveGroupAndPartitions) {
+ BlockDeviceInfo device_info(1024 * 1024, 0, 0, 4096);
+ unique_ptr<MetadataBuilder> builder = MetadataBuilder::New(device_info, 1024, 1);
+ ASSERT_NE(builder, nullptr);
+ ASSERT_TRUE(builder->AddGroup("example", 0));
+ ASSERT_NE(builder->AddPartition("system", "default", 0), nullptr);
+ ASSERT_NE(builder->AddPartition("vendor", "example", 0), nullptr);
+
+ builder->RemoveGroupAndPartitions("example");
+ ASSERT_NE(builder->FindPartition("system"), nullptr);
+ ASSERT_EQ(builder->FindPartition("vendor"), nullptr);
+ ASSERT_THAT(builder->ListGroups(), ElementsAre("default"));
+
+ builder->RemoveGroupAndPartitions("default");
+ ASSERT_NE(builder->FindPartition("system"), nullptr);
+}
diff --git a/fs_mgr/liblp/images.cpp b/fs_mgr/liblp/images.cpp
index dfa37fe..46bdfa4 100644
--- a/fs_mgr/liblp/images.cpp
+++ b/fs_mgr/liblp/images.cpp
@@ -99,11 +99,12 @@
block_size_(block_size),
file_(nullptr, sparse_file_destroy),
images_(images) {
+ uint64_t total_size = GetTotalSuperPartitionSize(metadata);
if (block_size % LP_SECTOR_SIZE != 0) {
LERROR << "Block size must be a multiple of the sector size, " << LP_SECTOR_SIZE;
return;
}
- if (metadata.geometry.block_device_size % block_size != 0) {
+ if (total_size % block_size != 0) {
LERROR << "Device size must be a multiple of the block size, " << block_size;
return;
}
@@ -120,7 +121,7 @@
return;
}
- uint64_t num_blocks = metadata.geometry.block_device_size % block_size;
+ uint64_t num_blocks = total_size % block_size;
if (num_blocks >= UINT_MAX) {
// libsparse counts blocks in unsigned 32-bit integers, so we check to
// make sure we're not going to overflow.
@@ -128,7 +129,10 @@
return;
}
- file_.reset(sparse_file_new(block_size_, geometry_.block_device_size));
+ file_.reset(sparse_file_new(block_size_, total_size));
+ if (!file_) {
+ LERROR << "Could not allocate sparse file of size " << total_size;
+ }
}
bool SparseBuilder::Export(const char* file) {
@@ -333,14 +337,7 @@
bool WriteToSparseFile(const char* file, const LpMetadata& metadata, uint32_t block_size,
const std::map<std::string, std::string>& images) {
SparseBuilder builder(metadata, block_size, images);
- if (!builder.IsValid()) {
- LERROR << "Could not allocate sparse file of size " << metadata.geometry.block_device_size;
- return false;
- }
- if (!builder.Build()) {
- return false;
- }
- return builder.Export(file);
+ return builder.IsValid() && builder.Build() && builder.Export(file);
}
} // namespace fs_mgr
diff --git a/fs_mgr/liblp/include/liblp/builder.h b/fs_mgr/liblp/include/liblp/builder.h
index 30dc300..a090889 100644
--- a/fs_mgr/liblp/include/liblp/builder.h
+++ b/fs_mgr/liblp/include/liblp/builder.h
@@ -24,6 +24,7 @@
#include <memory>
#include "liblp.h"
+#include "partition_opener.h"
namespace android {
namespace fs_mgr {
@@ -34,27 +35,6 @@
static const uint32_t kDefaultPartitionAlignment = 1024 * 1024;
static const uint32_t kDefaultBlockSize = 4096;
-struct BlockDeviceInfo {
- BlockDeviceInfo() : size(0), alignment(0), alignment_offset(0), logical_block_size(0) {}
- BlockDeviceInfo(uint64_t size, uint32_t alignment, uint32_t alignment_offset,
- uint32_t logical_block_size)
- : size(size),
- alignment(alignment),
- alignment_offset(alignment_offset),
- logical_block_size(logical_block_size) {}
- // Size of the block device, in bytes.
- uint64_t size;
- // Optimal target alignment, in bytes. Partition extents will be aligned to
- // this value by default. This value must be 0 or a multiple of 512.
- uint32_t alignment;
- // Alignment offset to parent device (if any), in bytes. The sector at
- // |alignment_offset| on the target device is correctly aligned on its
- // parent device. This value must be 0 or a multiple of 512.
- uint32_t alignment_offset;
- // Block size, for aligning extent sizes and partition sizes.
- uint32_t logical_block_size;
-};
-
// Abstraction around dm-targets that can be encoded into logical partition tables.
class Extent {
public:
@@ -157,7 +137,12 @@
// Import an existing table for modification. This reads metadata off the
// given block device and imports it. It also adjusts alignment information
// based on run-time values in the operating system.
- static std::unique_ptr<MetadataBuilder> New(const std::string& block_device,
+ static std::unique_ptr<MetadataBuilder> New(const IPartitionOpener& opener,
+ const std::string& super_partition,
+ uint32_t slot_number);
+
+ // Same as above, but use the default PartitionOpener.
+ static std::unique_ptr<MetadataBuilder> New(const std::string& super_partition,
uint32_t slot_number);
// Import an existing table for modification. If the table is not valid, for
@@ -199,6 +184,9 @@
// Find a partition by name. If no partition is found, nullptr is returned.
Partition* FindPartition(const std::string& name);
+ // Find a group by name. If no group is found, nullptr is returned.
+ PartitionGroup* FindGroup(const std::string& name);
+
// Grow or shrink a partition to the requested size. This size will be
// rounded UP to the nearest block (512 bytes).
//
@@ -215,6 +203,12 @@
uint64_t AllocatableSpace() const;
uint64_t UsedSpace() const;
+ // Return a list of all group names.
+ std::vector<std::string> ListGroups() const;
+
+ // Remove all partitions belonging to a group, then remove the group.
+ void RemoveGroupAndPartitions(const std::string& group_name);
+
bool GetBlockDeviceInfo(BlockDeviceInfo* info) const;
bool UpdateBlockDeviceInfo(const BlockDeviceInfo& info);
@@ -229,7 +223,6 @@
bool GrowPartition(Partition* partition, uint64_t aligned_size);
void ShrinkPartition(Partition* partition, uint64_t aligned_size);
uint64_t AlignSector(uint64_t sector) const;
- PartitionGroup* FindGroup(const std::string& group_name) const;
uint64_t TotalSizeOfGroup(PartitionGroup* group) const;
struct Interval {
@@ -246,10 +239,14 @@
void ExtentsToFreeList(const std::vector<Interval>& extents,
std::vector<Interval>* free_regions) const;
+ const LpMetadataBlockDevice& super_device() const { return block_devices_[0]; }
+ LpMetadataBlockDevice& super_device() { return block_devices_[0]; }
+
LpMetadataGeometry geometry_;
LpMetadataHeader header_;
std::vector<std::unique_ptr<Partition>> partitions_;
std::vector<std::unique_ptr<PartitionGroup>> groups_;
+ std::vector<LpMetadataBlockDevice> block_devices_;
};
// Read BlockDeviceInfo for a given block device. This always returns false
diff --git a/fs_mgr/liblp/include/liblp/liblp.h b/fs_mgr/liblp/include/liblp/liblp.h
index 5f95dca..4669cea 100644
--- a/fs_mgr/liblp/include/liblp/liblp.h
+++ b/fs_mgr/liblp/include/liblp/liblp.h
@@ -24,7 +24,10 @@
#include <memory>
#include <string>
+#include <android-base/unique_fd.h>
+
#include "metadata_format.h"
+#include "partition_opener.h"
namespace android {
namespace fs_mgr {
@@ -37,13 +40,15 @@
std::vector<LpMetadataPartition> partitions;
std::vector<LpMetadataExtent> extents;
std::vector<LpMetadataPartitionGroup> groups;
+ std::vector<LpMetadataBlockDevice> block_devices;
};
// Place an initial partition table on the device. This will overwrite the
// existing geometry, and should not be used for normal partition table
// updates. False can be returned if the geometry is incompatible with the
// block device or an I/O error occurs.
-bool FlashPartitionTable(const std::string& block_device, const LpMetadata& metadata);
+bool FlashPartitionTable(const IPartitionOpener& opener, const std::string& super_partition,
+ const LpMetadata& metadata);
// Update the partition table for a given metadata slot number. False is
// returned if an error occurs, which can include:
@@ -51,12 +56,19 @@
// - I/O error.
// - Corrupt or missing metadata geometry on disk.
// - Incompatible geometry.
-bool UpdatePartitionTable(const std::string& block_device, const LpMetadata& metadata,
- uint32_t slot_number);
+bool UpdatePartitionTable(const IPartitionOpener& opener, const std::string& super_partition,
+ const LpMetadata& metadata, uint32_t slot_number);
// Read logical partition metadata from its predetermined location on a block
// device. If readback fails, we also attempt to load from a backup copy.
-std::unique_ptr<LpMetadata> ReadMetadata(const char* block_device, uint32_t slot_number);
+std::unique_ptr<LpMetadata> ReadMetadata(const IPartitionOpener& opener,
+ const std::string& super_partition, uint32_t slot_number);
+
+// Helper functions that use the default PartitionOpener.
+bool FlashPartitionTable(const std::string& super_partition, const LpMetadata& metadata);
+bool UpdatePartitionTable(const std::string& super_partition, const LpMetadata& metadata,
+ uint32_t slot_number);
+std::unique_ptr<LpMetadata> ReadMetadata(const std::string& super_partition, uint32_t slot_number);
// Read/Write logical partition metadata to an image file, for diagnostics or
// flashing.
@@ -69,6 +81,14 @@
// Helper to extract safe C++ strings from partition info.
std::string GetPartitionName(const LpMetadataPartition& partition);
std::string GetPartitionGroupName(const LpMetadataPartitionGroup& group);
+std::string GetBlockDevicePartitionName(const LpMetadataBlockDevice& block_device);
+
+// Return the block device that houses the super partition metadata; returns
+// null on failure.
+const LpMetadataBlockDevice* GetMetadataSuperBlockDevice(const LpMetadata& metadata);
+
+// Return the total size of all partitions comprising the super partition.
+uint64_t GetTotalSuperPartitionSize(const LpMetadata& metadata);
// Helper to return a slot number for a slot suffix.
uint32_t SlotNumberForSlotSuffix(const std::string& suffix);
diff --git a/fs_mgr/liblp/include/liblp/metadata_format.h b/fs_mgr/liblp/include/liblp/metadata_format.h
index 89b219c..8a309be 100644
--- a/fs_mgr/liblp/include/liblp/metadata_format.h
+++ b/fs_mgr/liblp/include/liblp/metadata_format.h
@@ -38,7 +38,7 @@
#define LP_METADATA_HEADER_MAGIC 0x414C5030
/* Current metadata version. */
-#define LP_METADATA_MAJOR_VERSION 6
+#define LP_METADATA_MAJOR_VERSION 7
#define LP_METADATA_MINOR_VERSION 0
/* Attributes for the LpMetadataPartition::attributes field.
@@ -103,42 +103,10 @@
*/
uint32_t metadata_slot_count;
- /* 48: First usable sector for allocating logical partitions. this will be
- * the first sector after the initial geometry blocks, followed by the
- * space consumed by metadata_max_size*metadata_slot_count*2.
- */
- uint64_t first_logical_sector;
-
- /* 64: Alignment for defining partitions or partition extents. For example,
- * an alignment of 1MiB will require that all partitions have a size evenly
- * divisible by 1MiB, and that the smallest unit the partition can grow by
- * is 1MiB.
- *
- * Alignment is normally determined at runtime when growing or adding
- * partitions. If for some reason the alignment cannot be determined, then
- * this predefined alignment in the geometry is used instead. By default
- * it is set to 1MiB.
- */
- uint32_t alignment;
-
- /* 68: Alignment offset for "stacked" devices. For example, if the "super"
- * partition itself is not aligned within the parent block device's
- * partition table, then we adjust for this in deciding where to place
- * |first_logical_sector|.
- *
- * Similar to |alignment|, this will be derived from the operating system.
- * If it cannot be determined, it is assumed to be 0.
- */
- uint32_t alignment_offset;
-
- /* 72: Block device size, as specified when the metadata was created. This
- * can be used to verify the geometry against a target device.
- */
- uint64_t block_device_size;
-
- /* 76: Logical block size of the super partition block device. This is the
- * minimal alignment for partition and extent sizes, and it must be a
- * multiple of LP_SECTOR_SIZE.
+ /* 48: Logical block size. This is the minimal alignment for partition and
+ * extent sizes, and it must be a multiple of LP_SECTOR_SIZE. Note that
+ * this must be equal across all LUNs that comprise the super partition,
+ * and thus this field is stored in the geometry, not per-device.
*/
uint32_t logical_block_size;
} __attribute__((packed)) LpMetadataGeometry;
@@ -217,6 +185,8 @@
LpMetadataTableDescriptor extents;
/* 104: Updateable group descriptor. */
LpMetadataTableDescriptor groups;
+ /* 116: Block device table. */
+ LpMetadataTableDescriptor block_devices;
} __attribute__((packed)) LpMetadataHeader;
/* This struct defines a logical partition entry, similar to what would be
@@ -285,6 +255,47 @@
uint64_t maximum_size;
} LpMetadataPartitionGroup;
+/* This struct defines an entry in the block_devices table. There must be
+ * exactly one device, corresponding to the super partition.
+ */
+typedef struct LpMetadataBlockDevice {
+ /* 0: First usable sector for allocating logical partitions. this will be
+ * the first sector after the initial geometry blocks, followed by the
+ * space consumed by metadata_max_size*metadata_slot_count*2.
+ */
+ uint64_t first_logical_sector;
+
+ /* 8: Alignment for defining partitions or partition extents. For example,
+ * an alignment of 1MiB will require that all partitions have a size evenly
+ * divisible by 1MiB, and that the smallest unit the partition can grow by
+ * is 1MiB.
+ *
+ * Alignment is normally determined at runtime when growing or adding
+ * partitions. If for some reason the alignment cannot be determined, then
+ * this predefined alignment in the geometry is used instead. By default
+ * it is set to 1MiB.
+ */
+ uint32_t alignment;
+
+ /* 12: Alignment offset for "stacked" devices. For example, if the "super"
+ * partition itself is not aligned within the parent block device's
+ * partition table, then we adjust for this in deciding where to place
+ * |first_logical_sector|.
+ *
+ * Similar to |alignment|, this will be derived from the operating system.
+ * If it cannot be determined, it is assumed to be 0.
+ */
+ uint32_t alignment_offset;
+
+ /* 16: Block device size, as specified when the metadata was created. This
+ * can be used to verify the geometry against a target device.
+ */
+ uint64_t size;
+
+ /* 24: Partition name in the GPT. Any unused characters must be 0. */
+ char partition_name[36];
+} LpMetadataBlockDevice;
+
#ifdef __cplusplus
} /* extern "C" */
#endif
diff --git a/fs_mgr/liblp/include/liblp/partition_opener.h b/fs_mgr/liblp/include/liblp/partition_opener.h
new file mode 100644
index 0000000..fe61b9c
--- /dev/null
+++ b/fs_mgr/liblp/include/liblp/partition_opener.h
@@ -0,0 +1,73 @@
+//
+// Copyright (C) 2018 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.
+//
+
+#pragma once
+
+#include <stdint.h>
+
+#include <string>
+
+#include <android-base/unique_fd.h>
+
+namespace android {
+namespace fs_mgr {
+
+struct BlockDeviceInfo {
+ BlockDeviceInfo() : size(0), alignment(0), alignment_offset(0), logical_block_size(0) {}
+ BlockDeviceInfo(uint64_t size, uint32_t alignment, uint32_t alignment_offset,
+ uint32_t logical_block_size)
+ : size(size),
+ alignment(alignment),
+ alignment_offset(alignment_offset),
+ logical_block_size(logical_block_size) {}
+ // Size of the block device, in bytes.
+ uint64_t size;
+ // Optimal target alignment, in bytes. Partition extents will be aligned to
+ // this value by default. This value must be 0 or a multiple of 512.
+ uint32_t alignment;
+ // Alignment offset to parent device (if any), in bytes. The sector at
+ // |alignment_offset| on the target device is correctly aligned on its
+ // parent device. This value must be 0 or a multiple of 512.
+ uint32_t alignment_offset;
+ // Block size, for aligning extent sizes and partition sizes.
+ uint32_t logical_block_size;
+};
+
+// Test-friendly interface for interacting with partitions.
+class IPartitionOpener {
+ public:
+ virtual ~IPartitionOpener() = default;
+
+ // Open the given named physical partition with the provided open() flags.
+ // The name can be an absolute path if the full path is already known.
+ virtual android::base::unique_fd Open(const std::string& partition_name, int flags) const = 0;
+
+ // Return block device information about the given named physical partition.
+ // The name can be an absolute path if the full path is already known.
+ virtual bool GetInfo(const std::string& partition_name, BlockDeviceInfo* info) const = 0;
+};
+
+// Helper class to implement IPartitionOpener. If |partition_name| is not an
+// absolute path, /dev/block/by-name/ will be prepended.
+class PartitionOpener : public IPartitionOpener {
+ public:
+ virtual android::base::unique_fd Open(const std::string& partition_name,
+ int flags) const override;
+ virtual bool GetInfo(const std::string& partition_name, BlockDeviceInfo* info) const override;
+};
+
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/liblp/io_test.cpp b/fs_mgr/liblp/io_test.cpp
index 2aa41f3..9c675fe 100644
--- a/fs_mgr/liblp/io_test.cpp
+++ b/fs_mgr/liblp/io_test.cpp
@@ -26,6 +26,7 @@
#include "images.h"
#include "reader.h"
+#include "test_partition_opener.h"
#include "utility.h"
#include "writer.h"
@@ -101,7 +102,9 @@
if (!exported) {
return {};
}
- if (!FlashPartitionTable(fd, *exported.get())) {
+
+ TestPartitionOpener opener({{"super", fd}});
+ if (!FlashPartitionTable(opener, "super", *exported.get())) {
return {};
}
return fd;
@@ -116,8 +119,10 @@
ASSERT_TRUE(GetDescriptorSize(fd, &size));
ASSERT_EQ(size, kDiskSize);
+ TestPartitionOpener opener({{"super", fd}});
+
// Verify that we can't read unwritten metadata.
- ASSERT_EQ(ReadMetadata(fd, 1), nullptr);
+ ASSERT_EQ(ReadMetadata(opener, "super", 1), nullptr);
}
// Flashing metadata should not work if the metadata was created for a larger
@@ -133,7 +138,9 @@
unique_fd fd = CreateFakeDisk();
ASSERT_GE(fd, 0);
- EXPECT_FALSE(FlashPartitionTable(fd, *exported.get()));
+ TestPartitionOpener opener({{"super", fd}});
+
+ EXPECT_FALSE(FlashPartitionTable(opener, "super", *exported.get()));
}
// Test the basics of flashing a partition and reading it back.
@@ -145,22 +152,23 @@
unique_fd fd = CreateFakeDisk();
ASSERT_GE(fd, 0);
+ TestPartitionOpener opener({{"super", fd}});
+
// Export and flash.
unique_ptr<LpMetadata> exported = builder->Export();
ASSERT_NE(exported, nullptr);
- ASSERT_TRUE(FlashPartitionTable(fd, *exported.get()));
+ ASSERT_TRUE(FlashPartitionTable(opener, "super", *exported.get()));
// Read back. Note that some fields are only filled in during
// serialization, so exported and imported will not be identical. For
// example, table sizes and checksums are computed in WritePartitionTable.
// Therefore we check on a field-by-field basis.
- unique_ptr<LpMetadata> imported = ReadMetadata(fd, 0);
+ unique_ptr<LpMetadata> imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
// Check geometry and header.
EXPECT_EQ(exported->geometry.metadata_max_size, imported->geometry.metadata_max_size);
EXPECT_EQ(exported->geometry.metadata_slot_count, imported->geometry.metadata_slot_count);
- EXPECT_EQ(exported->geometry.first_logical_sector, imported->geometry.first_logical_sector);
EXPECT_EQ(exported->header.major_version, imported->header.major_version);
EXPECT_EQ(exported->header.minor_version, imported->header.minor_version);
EXPECT_EQ(exported->header.header_size, imported->header.header_size);
@@ -178,6 +186,11 @@
EXPECT_EQ(exported->extents[0].num_sectors, imported->extents[0].num_sectors);
EXPECT_EQ(exported->extents[0].target_type, imported->extents[0].target_type);
EXPECT_EQ(exported->extents[0].target_data, imported->extents[0].target_data);
+
+ // Check block devices table.
+ ASSERT_EQ(exported->block_devices.size(), imported->block_devices.size());
+ EXPECT_EQ(exported->block_devices[0].first_logical_sector,
+ imported->block_devices[0].first_logical_sector);
}
// Test that we can update metadata slots without disturbing others.
@@ -185,35 +198,40 @@
unique_fd fd = CreateFlashedDisk();
ASSERT_GE(fd, 0);
- unique_ptr<LpMetadata> imported = ReadMetadata(fd, 0);
+ TestPartitionOpener opener({{"super", fd}});
+
+ unique_ptr<LpMetadata> imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
ASSERT_EQ(imported->partitions.size(), 1);
EXPECT_EQ(GetPartitionName(imported->partitions[0]), "system");
// Change the name before writing to the next slot.
strncpy(imported->partitions[0].name, "vendor", sizeof(imported->partitions[0].name));
- ASSERT_TRUE(UpdatePartitionTable(fd, *imported.get(), 1));
+ ASSERT_TRUE(UpdatePartitionTable(opener, "super", *imported.get(), 1));
// Read back the original slot, make sure it hasn't changed.
- imported = ReadMetadata(fd, 0);
+ imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
ASSERT_EQ(imported->partitions.size(), 1);
EXPECT_EQ(GetPartitionName(imported->partitions[0]), "system");
// Now read back the new slot, and verify that it has a different name.
- imported = ReadMetadata(fd, 1);
+ imported = ReadMetadata(opener, "super", 1);
ASSERT_NE(imported, nullptr);
ASSERT_EQ(imported->partitions.size(), 1);
EXPECT_EQ(GetPartitionName(imported->partitions[0]), "vendor");
- uint64_t last_sector = imported->geometry.block_device_size / LP_SECTOR_SIZE;
+ auto super_device = GetMetadataSuperBlockDevice(*imported.get());
+ ASSERT_NE(super_device, nullptr);
+
+ uint64_t last_sector = super_device->size / LP_SECTOR_SIZE;
// Verify that we didn't overwrite anything in the logical paritition area.
// We expect the disk to be filled with 0xcc on creation so we can read
// this back and compare it.
char expected[LP_SECTOR_SIZE];
memset(expected, 0xcc, sizeof(expected));
- for (uint64_t i = imported->geometry.first_logical_sector; i < last_sector; i++) {
+ for (uint64_t i = super_device->first_logical_sector; i < last_sector; i++) {
char buffer[LP_SECTOR_SIZE];
ASSERT_GE(lseek(fd, i * LP_SECTOR_SIZE, SEEK_SET), 0);
ASSERT_TRUE(android::base::ReadFully(fd, buffer, sizeof(buffer)));
@@ -225,15 +243,17 @@
unique_fd fd = CreateFlashedDisk();
ASSERT_GE(fd, 0);
+ TestPartitionOpener opener({{"super", fd}});
+
// Make sure all slots are filled.
- unique_ptr<LpMetadata> metadata = ReadMetadata(fd, 0);
+ unique_ptr<LpMetadata> metadata = ReadMetadata(opener, "super", 0);
ASSERT_NE(metadata, nullptr);
for (uint32_t i = 1; i < kMetadataSlots; i++) {
- ASSERT_TRUE(UpdatePartitionTable(fd, *metadata.get(), i));
+ ASSERT_TRUE(UpdatePartitionTable(opener, "super", *metadata.get(), i));
}
// Verify that we can't read unavailable slots.
- EXPECT_EQ(ReadMetadata(fd, kMetadataSlots), nullptr);
+ EXPECT_EQ(ReadMetadata(opener, "super", kMetadataSlots), nullptr);
}
// Test that updating a metadata slot does not allow it to be computed based
@@ -242,24 +262,27 @@
unique_fd fd = CreateFlashedDisk();
ASSERT_GE(fd, 0);
- unique_ptr<LpMetadata> imported = ReadMetadata(fd, 0);
+ TestPartitionOpener opener({{"super", fd}});
+
+ unique_ptr<LpMetadata> imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
- ASSERT_TRUE(UpdatePartitionTable(fd, *imported.get(), 1));
+ ASSERT_TRUE(UpdatePartitionTable(opener, "super", *imported.get(), 1));
imported->geometry.metadata_max_size += LP_SECTOR_SIZE;
- ASSERT_FALSE(UpdatePartitionTable(fd, *imported.get(), 1));
+ ASSERT_FALSE(UpdatePartitionTable(opener, "super", *imported.get(), 1));
- imported = ReadMetadata(fd, 0);
+ imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
imported->geometry.metadata_slot_count++;
- ASSERT_FALSE(UpdatePartitionTable(fd, *imported.get(), 1));
+ ASSERT_FALSE(UpdatePartitionTable(opener, "super", *imported.get(), 1));
- imported = ReadMetadata(fd, 0);
+ imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
- imported->geometry.first_logical_sector++;
- ASSERT_FALSE(UpdatePartitionTable(fd, *imported.get(), 1));
+ ASSERT_EQ(imported->block_devices.size(), 1);
+ imported->block_devices[0].first_logical_sector++;
+ ASSERT_FALSE(UpdatePartitionTable(opener, "super", *imported.get(), 1));
- imported = ReadMetadata(fd, 0);
+ imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
}
@@ -268,6 +291,8 @@
unique_fd fd = CreateFlashedDisk();
ASSERT_GE(fd, 0);
+ TestPartitionOpener opener({{"super", fd}});
+
LpMetadataGeometry geometry;
ASSERT_GE(lseek(fd, 0, SEEK_SET), 0);
ASSERT_TRUE(android::base::ReadFully(fd, &geometry, sizeof(geometry)));
@@ -276,7 +301,7 @@
bad_geometry.metadata_slot_count++;
ASSERT_TRUE(android::base::WriteFully(fd, &bad_geometry, sizeof(bad_geometry)));
- unique_ptr<LpMetadata> metadata = ReadMetadata(fd, 0);
+ unique_ptr<LpMetadata> metadata = ReadMetadata(opener, "super", 0);
ASSERT_NE(metadata, nullptr);
EXPECT_EQ(metadata->geometry.metadata_slot_count, 2);
}
@@ -285,25 +310,29 @@
unique_fd fd = CreateFlashedDisk();
ASSERT_GE(fd, 0);
+ TestPartitionOpener opener({{"super", fd}});
+
char corruption[LP_METADATA_GEOMETRY_SIZE];
memset(corruption, 0xff, sizeof(corruption));
// Corrupt the primary geometry.
ASSERT_GE(lseek(fd, GetPrimaryGeometryOffset(), SEEK_SET), 0);
ASSERT_TRUE(android::base::WriteFully(fd, corruption, sizeof(corruption)));
- EXPECT_NE(ReadMetadata(fd, 0), nullptr);
+ EXPECT_NE(ReadMetadata(opener, "super", 0), nullptr);
// Corrupt the backup geometry.
ASSERT_GE(lseek(fd, GetBackupGeometryOffset(), SEEK_SET), 0);
ASSERT_TRUE(android::base::WriteFully(fd, corruption, sizeof(corruption)));
- EXPECT_EQ(ReadMetadata(fd, 0), nullptr);
+ EXPECT_EQ(ReadMetadata(opener, "super", 0), nullptr);
}
TEST(liblp, ReadBackupMetadata) {
unique_fd fd = CreateFlashedDisk();
ASSERT_GE(fd, 0);
- unique_ptr<LpMetadata> metadata = ReadMetadata(fd, 0);
+ TestPartitionOpener opener({{"super", fd}});
+
+ unique_ptr<LpMetadata> metadata = ReadMetadata(opener, "super", 0);
char corruption[kMetadataSize];
memset(corruption, 0xff, sizeof(corruption));
@@ -312,14 +341,14 @@
ASSERT_GE(lseek(fd, offset, SEEK_SET), 0);
ASSERT_TRUE(android::base::WriteFully(fd, corruption, sizeof(corruption)));
- EXPECT_NE(ReadMetadata(fd, 0), nullptr);
+ EXPECT_NE(ReadMetadata(opener, "super", 0), nullptr);
offset = GetBackupMetadataOffset(metadata->geometry, 0);
// Corrupt the backup metadata.
ASSERT_GE(lseek(fd, offset, SEEK_SET), 0);
ASSERT_TRUE(android::base::WriteFully(fd, corruption, sizeof(corruption)));
- EXPECT_EQ(ReadMetadata(fd, 0), nullptr);
+ EXPECT_EQ(ReadMetadata(opener, "super", 0), nullptr);
}
// Test that we don't attempt to write metadata if it would overflow its
@@ -329,9 +358,11 @@
ASSERT_NE(builder, nullptr);
// Compute the maximum number of partitions we can fit in 512 bytes of
- // metadata. By default there is the header, and one partition group.
- static const size_t kMaxPartitionTableSize =
- kMetadataSize - sizeof(LpMetadataHeader) - sizeof(LpMetadataPartitionGroup);
+ // metadata. By default there is the header, one partition group, and a
+ // block device entry.
+ static const size_t kMaxPartitionTableSize = kMetadataSize - sizeof(LpMetadataHeader) -
+ sizeof(LpMetadataPartitionGroup) -
+ sizeof(LpMetadataBlockDevice);
size_t max_partitions = kMaxPartitionTableSize / sizeof(LpMetadataPartition);
// Add this number of partitions.
@@ -347,8 +378,10 @@
unique_fd fd = CreateFakeDisk();
ASSERT_GE(fd, 0);
+ TestPartitionOpener opener({{"super", fd}});
+
// Check that we are able to write our table.
- ASSERT_TRUE(FlashPartitionTable(fd, *exported.get()));
+ ASSERT_TRUE(FlashPartitionTable(opener, "super", *exported.get()));
// Check that adding one more partition overflows the metadata allotment.
partition = builder->AddPartition("final", LP_PARTITION_ATTR_NONE);
@@ -358,14 +391,17 @@
ASSERT_NE(exported, nullptr);
// The new table should be too large to be written.
- ASSERT_FALSE(UpdatePartitionTable(fd, *exported.get(), 1));
+ ASSERT_FALSE(UpdatePartitionTable(opener, "super", *exported.get(), 1));
+
+ auto super_device = GetMetadataSuperBlockDevice(*exported.get());
+ ASSERT_NE(super_device, nullptr);
// Check that the first and last logical sectors weren't touched when we
// wrote this almost-full metadata.
char expected[LP_SECTOR_SIZE];
memset(expected, 0xcc, sizeof(expected));
char buffer[LP_SECTOR_SIZE];
- ASSERT_GE(lseek(fd, exported->geometry.first_logical_sector * LP_SECTOR_SIZE, SEEK_SET), 0);
+ ASSERT_GE(lseek(fd, super_device->first_logical_sector * LP_SECTOR_SIZE, SEEK_SET), 0);
ASSERT_TRUE(android::base::ReadFully(fd, buffer, sizeof(buffer)));
EXPECT_EQ(memcmp(expected, buffer, LP_SECTOR_SIZE), 0);
}
@@ -451,23 +487,25 @@
unique_fd fd = CreateFlashedDisk();
ASSERT_GE(fd, 0);
+ TestPartitionOpener opener({{"super", fd}});
+
BadWriter writer;
// Read and write it back.
writer.FailOnWrite(1);
- unique_ptr<LpMetadata> imported = ReadMetadata(fd, 0);
+ unique_ptr<LpMetadata> imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
- ASSERT_FALSE(UpdatePartitionTable(fd, *imported.get(), 0, writer));
+ ASSERT_FALSE(UpdatePartitionTable(opener, "super", *imported.get(), 0, writer));
// We should still be able to read the backup copy.
- imported = ReadMetadata(fd, 0);
+ imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
// Flash again, this time fail the backup copy. We should still be able
// to read the primary.
writer.FailOnWrite(3);
- ASSERT_FALSE(UpdatePartitionTable(fd, *imported.get(), 0, writer));
- imported = ReadMetadata(fd, 0);
+ ASSERT_FALSE(UpdatePartitionTable(opener, "super", *imported.get(), 0, writer));
+ imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
}
@@ -477,23 +515,25 @@
unique_fd fd = CreateFlashedDisk();
ASSERT_GE(fd, 0);
+ TestPartitionOpener opener({{"super", fd}});
+
BadWriter writer;
// Read and write it back.
writer.FailOnWrite(2);
- unique_ptr<LpMetadata> imported = ReadMetadata(fd, 0);
+ unique_ptr<LpMetadata> imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
- ASSERT_FALSE(UpdatePartitionTable(fd, *imported.get(), 0, writer));
+ ASSERT_FALSE(UpdatePartitionTable(opener, "super", *imported.get(), 0, writer));
// We should still be able to read the primary copy.
- imported = ReadMetadata(fd, 0);
+ imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
// Flash again, this time fail the primary copy. We should still be able
// to read the primary.
writer.FailOnWrite(2);
- ASSERT_FALSE(UpdatePartitionTable(fd, *imported.get(), 0, writer));
- imported = ReadMetadata(fd, 0);
+ ASSERT_FALSE(UpdatePartitionTable(opener, "super", *imported.get(), 0, writer));
+ imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
}
@@ -504,20 +544,22 @@
unique_fd fd = CreateFlashedDisk();
ASSERT_GE(fd, 0);
+ TestPartitionOpener opener({{"super", fd}});
+
BadWriter writer;
// Change the name of the existing partition.
- unique_ptr<LpMetadata> new_table = ReadMetadata(fd, 0);
+ unique_ptr<LpMetadata> new_table = ReadMetadata(opener, "super", 0);
ASSERT_NE(new_table, nullptr);
ASSERT_GE(new_table->partitions.size(), 1);
new_table->partitions[0].name[0]++;
// Flash it, but fail to write the backup copy.
writer.FailAfterWrite(2);
- ASSERT_FALSE(UpdatePartitionTable(fd, *new_table.get(), 0, writer));
+ ASSERT_FALSE(UpdatePartitionTable(opener, "super", *new_table.get(), 0, writer));
// When we read back, we should get the updated primary copy.
- unique_ptr<LpMetadata> imported = ReadMetadata(fd, 0);
+ unique_ptr<LpMetadata> imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
ASSERT_GE(new_table->partitions.size(), 1);
ASSERT_EQ(GetPartitionName(new_table->partitions[0]), GetPartitionName(imported->partitions[0]));
@@ -526,9 +568,9 @@
// Note that the sync step should have used the primary to sync, not
// the backup.
writer.Reset();
- ASSERT_TRUE(UpdatePartitionTable(fd, *new_table.get(), 0, writer));
+ ASSERT_TRUE(UpdatePartitionTable(opener, "super", *new_table.get(), 0, writer));
- imported = ReadMetadata(fd, 0);
+ imported = ReadMetadata(opener, "super", 0);
ASSERT_NE(imported, nullptr);
ASSERT_GE(new_table->partitions.size(), 1);
ASSERT_EQ(GetPartitionName(new_table->partitions[0]), GetPartitionName(imported->partitions[0]));
diff --git a/fs_mgr/liblp/partition_opener.cpp b/fs_mgr/liblp/partition_opener.cpp
new file mode 100644
index 0000000..7381eed
--- /dev/null
+++ b/fs_mgr/liblp/partition_opener.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2018 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 "liblp/partition_opener.h"
+
+#if defined(__linux__)
+#include <linux/fs.h>
+#endif
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "utility.h"
+
+namespace android {
+namespace fs_mgr {
+
+using android::base::unique_fd;
+
+namespace {
+
+std::string GetPartitionAbsolutePath(const std::string& path) {
+ if (path[0] == '/') {
+ return path;
+ }
+ return "/dev/block/by-name/" + path;
+}
+
+bool GetBlockDeviceInfo(const std::string& block_device, BlockDeviceInfo* device_info) {
+#if defined(__linux__)
+ unique_fd fd(open(block_device.c_str(), O_RDONLY));
+ if (fd < 0) {
+ PERROR << __PRETTY_FUNCTION__ << "open '" << block_device << "' failed";
+ return false;
+ }
+ if (!GetDescriptorSize(fd, &device_info->size)) {
+ return false;
+ }
+ if (ioctl(fd, BLKIOMIN, &device_info->alignment) < 0) {
+ PERROR << __PRETTY_FUNCTION__ << "BLKIOMIN failed";
+ return false;
+ }
+
+ int alignment_offset;
+ if (ioctl(fd, BLKALIGNOFF, &alignment_offset) < 0) {
+ PERROR << __PRETTY_FUNCTION__ << "BLKIOMIN failed";
+ return false;
+ }
+ int logical_block_size;
+ if (ioctl(fd, BLKSSZGET, &logical_block_size) < 0) {
+ PERROR << __PRETTY_FUNCTION__ << "BLKSSZGET failed";
+ return false;
+ }
+
+ device_info->alignment_offset = static_cast<uint32_t>(alignment_offset);
+ device_info->logical_block_size = static_cast<uint32_t>(logical_block_size);
+ return true;
+#else
+ (void)block_device;
+ (void)device_info;
+ LERROR << __PRETTY_FUNCTION__ << ": Not supported on this operating system.";
+ return false;
+#endif
+}
+
+} // namespace
+
+unique_fd PartitionOpener::Open(const std::string& partition_name, int flags) const {
+ std::string path = GetPartitionAbsolutePath(partition_name);
+ return unique_fd{open(path.c_str(), flags)};
+}
+
+bool PartitionOpener::GetInfo(const std::string& partition_name, BlockDeviceInfo* info) const {
+ std::string path = GetPartitionAbsolutePath(partition_name);
+ return GetBlockDeviceInfo(path, info);
+}
+
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/liblp/reader.cpp b/fs_mgr/liblp/reader.cpp
index 43d8076..070573c 100644
--- a/fs_mgr/liblp/reader.cpp
+++ b/fs_mgr/liblp/reader.cpp
@@ -108,15 +108,6 @@
LERROR << "Metadata max size is not sector-aligned.";
return false;
}
-
- // Check that the metadata area and logical partition areas don't overlap.
- int64_t end_of_metadata =
- GetPrimaryMetadataOffset(*geometry, geometry->metadata_slot_count - 1) +
- geometry->metadata_max_size;
- if (uint64_t(end_of_metadata) > geometry->first_logical_sector * LP_SECTOR_SIZE) {
- LERROR << "Logical partition metadata overlaps with logical partition contents.";
- return false;
- }
return true;
}
@@ -195,7 +186,8 @@
}
if (!ValidateTableBounds(header, header.partitions) ||
!ValidateTableBounds(header, header.extents) ||
- !ValidateTableBounds(header, header.groups)) {
+ !ValidateTableBounds(header, header.groups) ||
+ !ValidateTableBounds(header, header.block_devices)) {
LERROR << "Logical partition metadata has invalid table bounds.";
return false;
}
@@ -294,6 +286,28 @@
metadata->groups.push_back(group);
}
+ cursor = buffer.get() + header.block_devices.offset;
+ for (size_t i = 0; i < header.block_devices.num_entries; i++) {
+ LpMetadataBlockDevice device = {};
+ memcpy(&device, cursor, sizeof(device));
+ cursor += header.block_devices.entry_size;
+
+ metadata->block_devices.push_back(device);
+ }
+
+ const LpMetadataBlockDevice* super_device = GetMetadataSuperBlockDevice(*metadata.get());
+ if (!super_device) {
+ LERROR << "Metadata does not specify a super device.";
+ return nullptr;
+ }
+
+ // Check that the metadata area and logical partition areas don't overlap.
+ uint64_t metadata_region =
+ GetTotalMetadataSize(geometry.metadata_max_size, geometry.metadata_slot_count);
+ if (metadata_region > super_device->first_logical_sector * LP_SECTOR_SIZE) {
+ LERROR << "Logical partition metadata overlaps with logical partition contents.";
+ return nullptr;
+ }
return metadata;
}
@@ -328,7 +342,14 @@
return ParseMetadata(geometry, fd);
}
-std::unique_ptr<LpMetadata> ReadMetadata(int fd, uint32_t slot_number) {
+std::unique_ptr<LpMetadata> ReadMetadata(const IPartitionOpener& opener,
+ const std::string& super_partition, uint32_t slot_number) {
+ android::base::unique_fd fd = opener.Open(super_partition, O_RDONLY);
+ if (fd < 0) {
+ PERROR << __PRETTY_FUNCTION__ << " open failed: " << super_partition;
+ return nullptr;
+ }
+
LpMetadataGeometry geometry;
if (!ReadLogicalPartitionGeometry(fd, &geometry)) {
return nullptr;
@@ -347,13 +368,8 @@
return ReadBackupMetadata(fd, geometry, slot_number);
}
-std::unique_ptr<LpMetadata> ReadMetadata(const char* block_device, uint32_t slot_number) {
- android::base::unique_fd fd(open(block_device, O_RDONLY));
- if (fd < 0) {
- PERROR << __PRETTY_FUNCTION__ << " open failed: " << block_device;
- return nullptr;
- }
- return ReadMetadata(fd, slot_number);
+std::unique_ptr<LpMetadata> ReadMetadata(const std::string& super_partition, uint32_t slot_number) {
+ return ReadMetadata(PartitionOpener(), super_partition, slot_number);
}
static std::string NameFromFixedArray(const char* name, size_t buffer_size) {
@@ -374,5 +390,9 @@
return NameFromFixedArray(group.name, sizeof(group.name));
}
+std::string GetBlockDevicePartitionName(const LpMetadataBlockDevice& block_device) {
+ return NameFromFixedArray(block_device.partition_name, sizeof(block_device.partition_name));
+}
+
} // namespace fs_mgr
} // namespace android
diff --git a/fs_mgr/liblp/reader.h b/fs_mgr/liblp/reader.h
index 24b2611..d5d5188 100644
--- a/fs_mgr/liblp/reader.h
+++ b/fs_mgr/liblp/reader.h
@@ -31,7 +31,6 @@
bool ParseGeometry(const void* buffer, LpMetadataGeometry* geometry);
// Helper functions for manually reading geometry and metadata.
-std::unique_ptr<LpMetadata> ReadMetadata(int fd, uint32_t slot_number);
std::unique_ptr<LpMetadata> ParseMetadata(const LpMetadataGeometry& geometry, int fd);
std::unique_ptr<LpMetadata> ParseMetadata(const LpMetadataGeometry& geometry, const void* buffer,
size_t size);
diff --git a/fs_mgr/liblp/test_partition_opener.cpp b/fs_mgr/liblp/test_partition_opener.cpp
new file mode 100644
index 0000000..c796f6c
--- /dev/null
+++ b/fs_mgr/liblp/test_partition_opener.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2018 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 "test_partition_opener.h"
+
+#include <errno.h>
+
+namespace android {
+namespace fs_mgr {
+
+using android::base::unique_fd;
+
+TestPartitionOpener::TestPartitionOpener(
+ const std::map<std::string, int>& partition_map,
+ const std::map<std::string, BlockDeviceInfo>& partition_info)
+ : partition_map_(partition_map), partition_info_(partition_info) {}
+
+unique_fd TestPartitionOpener::Open(const std::string& partition_name, int flags) const {
+ auto iter = partition_map_.find(partition_name);
+ if (iter == partition_map_.end()) {
+ errno = ENOENT;
+ return {};
+ }
+ return unique_fd{dup(iter->second)};
+}
+
+bool TestPartitionOpener::GetInfo(const std::string& partition_name, BlockDeviceInfo* info) const {
+ auto iter = partition_info_.find(partition_name);
+ if (iter == partition_info_.end()) {
+ errno = ENOENT;
+ return false;
+ }
+ *info = iter->second;
+ return true;
+}
+
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/liblp/test_partition_opener.h b/fs_mgr/liblp/test_partition_opener.h
new file mode 100644
index 0000000..b90fee7
--- /dev/null
+++ b/fs_mgr/liblp/test_partition_opener.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#pragma once
+
+#include <map>
+#include <string>
+
+#include <android-base/unique_fd.h>
+#include <liblp/partition_opener.h>
+
+namespace android {
+namespace fs_mgr {
+
+class TestPartitionOpener : public PartitionOpener {
+ public:
+ explicit TestPartitionOpener(const std::map<std::string, int>& partition_map,
+ const std::map<std::string, BlockDeviceInfo>& partition_info = {});
+
+ android::base::unique_fd Open(const std::string& partition_name, int flags) const override;
+ bool GetInfo(const std::string& partition_name, BlockDeviceInfo* info) const override;
+
+ private:
+ std::map<std::string, int> partition_map_;
+ std::map<std::string, BlockDeviceInfo> partition_info_;
+};
+
+} // namespace fs_mgr
+} // namespace android
diff --git a/fs_mgr/liblp/utility.cpp b/fs_mgr/liblp/utility.cpp
index 0556833..742ad82 100644
--- a/fs_mgr/liblp/utility.cpp
+++ b/fs_mgr/liblp/utility.cpp
@@ -16,7 +16,6 @@
#include <fcntl.h>
#include <stdint.h>
-#include <sys/ioctl.h>
#include <sys/stat.h>
#include <unistd.h>
@@ -66,11 +65,8 @@
int64_t GetPrimaryMetadataOffset(const LpMetadataGeometry& geometry, uint32_t slot_number) {
CHECK(slot_number < geometry.metadata_slot_count);
-
int64_t offset = LP_PARTITION_RESERVED_BYTES + (LP_METADATA_GEOMETRY_SIZE * 2) +
geometry.metadata_max_size * slot_number;
- CHECK(offset + geometry.metadata_max_size <=
- int64_t(geometry.first_logical_sector * LP_SECTOR_SIZE));
return offset;
}
@@ -81,6 +77,18 @@
return start + int64_t(geometry.metadata_max_size * slot_number);
}
+uint64_t GetTotalMetadataSize(uint32_t metadata_max_size, uint32_t max_slots) {
+ return LP_PARTITION_RESERVED_BYTES +
+ (LP_METADATA_GEOMETRY_SIZE + metadata_max_size * max_slots) * 2;
+}
+
+const LpMetadataBlockDevice* GetMetadataSuperBlockDevice(const LpMetadata& metadata) {
+ if (metadata.block_devices.empty()) {
+ return nullptr;
+ }
+ return &metadata.block_devices[0];
+}
+
void SHA256(const void* data, size_t length, uint8_t out[32]) {
SHA256_CTX c;
SHA256_Init(&c);
@@ -100,5 +108,13 @@
return suffix[1] - 'a';
}
+uint64_t GetTotalSuperPartitionSize(const LpMetadata& metadata) {
+ uint64_t size = 0;
+ for (const auto& block_device : metadata.block_devices) {
+ size += block_device.size;
+ }
+ return size;
+}
+
} // namespace fs_mgr
} // namespace android
diff --git a/fs_mgr/liblp/utility.h b/fs_mgr/liblp/utility.h
index 61e7d31..65e643b 100644
--- a/fs_mgr/liblp/utility.h
+++ b/fs_mgr/liblp/utility.h
@@ -23,7 +23,7 @@
#include <android-base/logging.h>
-#include "liblp/metadata_format.h"
+#include "liblp/liblp.h"
#define LP_TAG "[liblp]"
#define LWARN LOG(WARNING) << LP_TAG
@@ -50,6 +50,10 @@
// device.
int64_t GetBackupMetadataOffset(const LpMetadataGeometry& geometry, uint32_t slot_number);
+// Return the total space at the start of the super partition that must be set
+// aside from headers/metadata and backups.
+uint64_t GetTotalMetadataSize(uint32_t metadata_max_size, uint32_t max_slots);
+
// Cross-platform helper for lseek64().
int64_t SeekFile64(int fd, int64_t offset, int whence);
diff --git a/fs_mgr/liblp/utility_test.cpp b/fs_mgr/liblp/utility_test.cpp
index 8baf9e7..bdf6dfd 100644
--- a/fs_mgr/liblp/utility_test.cpp
+++ b/fs_mgr/liblp/utility_test.cpp
@@ -36,10 +36,6 @@
{0},
16384,
4,
- 10000,
- 0,
- 0,
- 1024 * 1024,
4096};
static const uint64_t start = LP_PARTITION_RESERVED_BYTES;
EXPECT_EQ(GetPrimaryMetadataOffset(geometry, 0), start + 8192);
diff --git a/fs_mgr/liblp/writer.cpp b/fs_mgr/liblp/writer.cpp
index f857d8c..c740bd4 100644
--- a/fs_mgr/liblp/writer.cpp
+++ b/fs_mgr/liblp/writer.cpp
@@ -43,9 +43,7 @@
static bool CompareGeometry(const LpMetadataGeometry& g1, const LpMetadataGeometry& g2) {
return g1.metadata_max_size == g2.metadata_max_size &&
g1.metadata_slot_count == g2.metadata_slot_count &&
- g1.block_device_size == g2.block_device_size &&
- g1.logical_block_size == g2.logical_block_size &&
- g1.first_logical_sector == g2.first_logical_sector;
+ g1.logical_block_size == g2.logical_block_size;
}
std::string SerializeMetadata(const LpMetadata& input) {
@@ -59,15 +57,18 @@
metadata.extents.size() * sizeof(LpMetadataExtent));
std::string groups(reinterpret_cast<const char*>(metadata.groups.data()),
metadata.groups.size() * sizeof(LpMetadataPartitionGroup));
+ std::string block_devices(reinterpret_cast<const char*>(metadata.block_devices.data()),
+ metadata.block_devices.size() * sizeof(LpMetadataBlockDevice));
// Compute positions of tables.
header.partitions.offset = 0;
header.extents.offset = header.partitions.offset + partitions.size();
header.groups.offset = header.extents.offset + extents.size();
- header.tables_size = header.groups.offset + groups.size();
+ header.block_devices.offset = header.groups.offset + groups.size();
+ header.tables_size = header.block_devices.offset + block_devices.size();
// Compute payload checksum.
- std::string tables = partitions + extents + groups;
+ std::string tables = partitions + extents + groups + block_devices;
SHA256(tables.data(), tables.size(), header.tables_checksum);
// Compute header checksum.
@@ -105,14 +106,20 @@
uint64_t(geometry.metadata_max_size) * geometry.metadata_slot_count;
uint64_t total_reserved = reserved_size * 2;
+ const LpMetadataBlockDevice* super_device = GetMetadataSuperBlockDevice(metadata);
+ if (!super_device) {
+ LERROR << "Logical partition metadata does not have a super block device.";
+ return false;
+ }
+
if (total_reserved > blockdevice_size ||
- total_reserved > geometry.first_logical_sector * LP_SECTOR_SIZE) {
+ total_reserved > super_device->first_logical_sector * LP_SECTOR_SIZE) {
LERROR << "Not enough space to store all logical partition metadata slots.";
return false;
}
- if (blockdevice_size != metadata.geometry.block_device_size) {
+ if (blockdevice_size != super_device->size) {
LERROR << "Block device size " << blockdevice_size
- << " does not match metadata requested size " << metadata.geometry.block_device_size;
+ << " does not match metadata requested size " << super_device->size;
return false;
}
@@ -125,11 +132,11 @@
}
// Make sure all linear extents have a valid range.
- uint64_t last_sector = geometry.block_device_size / LP_SECTOR_SIZE;
+ uint64_t last_sector = super_device->size / LP_SECTOR_SIZE;
for (const auto& extent : metadata.extents) {
if (extent.target_type == LP_TARGET_TYPE_LINEAR) {
uint64_t physical_sector = extent.target_data;
- if (physical_sector < geometry.first_logical_sector ||
+ if (physical_sector < super_device->first_logical_sector ||
physical_sector + extent.num_sectors > last_sector) {
LERROR << "Extent table entry is out of bounds.";
return false;
@@ -139,10 +146,28 @@
return true;
}
-static bool WritePrimaryMetadata(int fd, const LpMetadataGeometry& geometry, uint32_t slot_number,
+// Check that the given region is within metadata bounds.
+static bool ValidateMetadataRegion(const LpMetadata& metadata, uint64_t start, size_t size) {
+ const LpMetadataBlockDevice* super_device = GetMetadataSuperBlockDevice(metadata);
+ if (!super_device) {
+ LERROR << __PRETTY_FUNCTION__ << " could not locate super block device in metadata";
+ return false;
+ }
+ if (start + size >= super_device->first_logical_sector * LP_SECTOR_SIZE) {
+ LERROR << __PRETTY_FUNCTION__ << " write of " << size << " bytes at " << start
+ << " overlaps with logical partition contents";
+ return false;
+ }
+ return true;
+}
+
+static bool WritePrimaryMetadata(int fd, const LpMetadata& metadata, uint32_t slot_number,
const std::string& blob,
const std::function<bool(int, const std::string&)>& writer) {
- int64_t primary_offset = GetPrimaryMetadataOffset(geometry, slot_number);
+ int64_t primary_offset = GetPrimaryMetadataOffset(metadata.geometry, slot_number);
+ if (!ValidateMetadataRegion(metadata, primary_offset, blob.size())) {
+ return false;
+ }
if (SeekFile64(fd, primary_offset, SEEK_SET) < 0) {
PERROR << __PRETTY_FUNCTION__ << " lseek failed: offset " << primary_offset;
return false;
@@ -154,18 +179,15 @@
return true;
}
-static bool WriteBackupMetadata(int fd, const LpMetadataGeometry& geometry, uint32_t slot_number,
+static bool WriteBackupMetadata(int fd, const LpMetadata& metadata, uint32_t slot_number,
const std::string& blob,
const std::function<bool(int, const std::string&)>& writer) {
- int64_t backup_offset = GetBackupMetadataOffset(geometry, slot_number);
- int64_t abs_offset = SeekFile64(fd, backup_offset, SEEK_SET);
- if (abs_offset == (int64_t)-1) {
- PERROR << __PRETTY_FUNCTION__ << " lseek failed: offset " << backup_offset;
+ int64_t backup_offset = GetBackupMetadataOffset(metadata.geometry, slot_number);
+ if (!ValidateMetadataRegion(metadata, backup_offset, blob.size())) {
return false;
}
- if (abs_offset >= int64_t(geometry.first_logical_sector) * LP_SECTOR_SIZE) {
- PERROR << __PRETTY_FUNCTION__ << " backup offset " << abs_offset
- << " is within logical partition bounds, sector " << geometry.first_logical_sector;
+ if (SeekFile64(fd, backup_offset, SEEK_SET) < 0) {
+ PERROR << __PRETTY_FUNCTION__ << " lseek failed: offset " << backup_offset;
return false;
}
if (!writer(fd, blob)) {
@@ -175,18 +197,18 @@
return true;
}
-static bool WriteMetadata(int fd, const LpMetadataGeometry& geometry, uint32_t slot_number,
+static bool WriteMetadata(int fd, const LpMetadata& metadata, uint32_t slot_number,
const std::string& blob,
const std::function<bool(int, const std::string&)>& writer) {
// Make sure we're writing to a valid metadata slot.
- if (slot_number >= geometry.metadata_slot_count) {
+ if (slot_number >= metadata.geometry.metadata_slot_count) {
LERROR << "Invalid logical partition metadata slot number.";
return false;
}
- if (!WritePrimaryMetadata(fd, geometry, slot_number, blob, writer)) {
+ if (!WritePrimaryMetadata(fd, metadata, slot_number, blob, writer)) {
return false;
}
- if (!WriteBackupMetadata(fd, geometry, slot_number, blob, writer)) {
+ if (!WriteBackupMetadata(fd, metadata, slot_number, blob, writer)) {
return false;
}
return true;
@@ -196,7 +218,14 @@
return android::base::WriteFully(fd, blob.data(), blob.size());
}
-bool FlashPartitionTable(int fd, const LpMetadata& metadata) {
+bool FlashPartitionTable(const IPartitionOpener& opener, const std::string& super_partition,
+ const LpMetadata& metadata) {
+ android::base::unique_fd fd = opener.Open(super_partition, O_RDWR | O_SYNC);
+ if (fd < 0) {
+ PERROR << __PRETTY_FUNCTION__ << " open failed: " << super_partition;
+ return false;
+ }
+
// Before writing geometry and/or logical partition tables, perform some
// basic checks that the geometry and tables are coherent, and will fit
// on the given block device.
@@ -216,6 +245,8 @@
return false;
}
+ LWARN << "Flashing new logical partition geometry to " << super_partition;
+
// Write geometry to the primary and backup locations.
std::string blob = SerializeGeometry(metadata.geometry);
if (SeekFile64(fd, GetPrimaryGeometryOffset(), SEEK_SET) < 0) {
@@ -237,18 +268,29 @@
bool ok = true;
for (size_t i = 0; i < metadata.geometry.metadata_slot_count; i++) {
- ok &= WriteMetadata(fd, metadata.geometry, i, metadata_blob, DefaultWriter);
+ ok &= WriteMetadata(fd, metadata, i, metadata_blob, DefaultWriter);
}
return ok;
}
+bool FlashPartitionTable(const std::string& super_partition, const LpMetadata& metadata) {
+ return FlashPartitionTable(PartitionOpener(), super_partition, metadata);
+}
+
static bool CompareMetadata(const LpMetadata& a, const LpMetadata& b) {
return !memcmp(a.header.header_checksum, b.header.header_checksum,
sizeof(a.header.header_checksum));
}
-bool UpdatePartitionTable(int fd, const LpMetadata& metadata, uint32_t slot_number,
+bool UpdatePartitionTable(const IPartitionOpener& opener, const std::string& super_partition,
+ const LpMetadata& metadata, uint32_t slot_number,
const std::function<bool(int, const std::string&)>& writer) {
+ android::base::unique_fd fd = opener.Open(super_partition, O_RDWR | O_SYNC);
+ if (fd < 0) {
+ PERROR << __PRETTY_FUNCTION__ << " open failed: " << super_partition;
+ return false;
+ }
+
// Before writing geometry and/or logical partition tables, perform some
// basic checks that the geometry and tables are coherent, and will fit
// on the given block device.
@@ -289,7 +331,7 @@
LERROR << "Error serializing primary metadata to repair corrupted backup";
return false;
}
- if (!WriteBackupMetadata(fd, geometry, slot_number, old_blob, writer)) {
+ if (!WriteBackupMetadata(fd, metadata, slot_number, old_blob, writer)) {
LERROR << "Error writing primary metadata to repair corrupted backup";
return false;
}
@@ -301,46 +343,31 @@
LERROR << "Error serializing primary metadata to repair corrupted backup";
return false;
}
- if (!WritePrimaryMetadata(fd, geometry, slot_number, old_blob, writer)) {
+ if (!WritePrimaryMetadata(fd, metadata, slot_number, old_blob, writer)) {
LERROR << "Error writing primary metadata to repair corrupted backup";
return false;
}
}
// Both copies should now be in sync, so we can continue the update.
- return WriteMetadata(fd, geometry, slot_number, blob, writer);
-}
+ if (!WriteMetadata(fd, metadata, slot_number, blob, writer)) {
+ return false;
+ }
-bool FlashPartitionTable(const std::string& block_device, const LpMetadata& metadata) {
- android::base::unique_fd fd(open(block_device.c_str(), O_RDWR | O_SYNC));
- if (fd < 0) {
- PERROR << __PRETTY_FUNCTION__ << " open failed: " << block_device;
- return false;
- }
- if (!FlashPartitionTable(fd, metadata)) {
- return false;
- }
- LWARN << "Flashed new logical partition geometry to " << block_device;
- return true;
-}
-
-bool UpdatePartitionTable(const std::string& block_device, const LpMetadata& metadata,
- uint32_t slot_number) {
- android::base::unique_fd fd(open(block_device.c_str(), O_RDWR | O_SYNC));
- if (fd < 0) {
- PERROR << __PRETTY_FUNCTION__ << " open failed: " << block_device;
- return false;
- }
- if (!UpdatePartitionTable(fd, metadata, slot_number)) {
- return false;
- }
LINFO << "Updated logical partition table at slot " << slot_number << " on device "
- << block_device;
+ << super_partition;
return true;
}
-bool UpdatePartitionTable(int fd, const LpMetadata& metadata, uint32_t slot_number) {
- return UpdatePartitionTable(fd, metadata, slot_number, DefaultWriter);
+bool UpdatePartitionTable(const IPartitionOpener& opener, const std::string& super_partition,
+ const LpMetadata& metadata, uint32_t slot_number) {
+ return UpdatePartitionTable(opener, super_partition, metadata, slot_number, DefaultWriter);
+}
+
+bool UpdatePartitionTable(const std::string& super_partition, const LpMetadata& metadata,
+ uint32_t slot_number) {
+ PartitionOpener opener;
+ return UpdatePartitionTable(opener, super_partition, metadata, slot_number, DefaultWriter);
}
} // namespace fs_mgr
diff --git a/fs_mgr/liblp/writer.h b/fs_mgr/liblp/writer.h
index ab18d45..6f1da0f 100644
--- a/fs_mgr/liblp/writer.h
+++ b/fs_mgr/liblp/writer.h
@@ -30,10 +30,8 @@
// These variants are for testing only. The path-based functions should be used
// for actual operation, so that open() is called with the correct flags.
-bool FlashPartitionTable(int fd, const LpMetadata& metadata);
-bool UpdatePartitionTable(int fd, const LpMetadata& metadata, uint32_t slot_number);
-
-bool UpdatePartitionTable(int fd, const LpMetadata& metadata, uint32_t slot_number,
+bool UpdatePartitionTable(const IPartitionOpener& opener, const std::string& super_partition,
+ const LpMetadata& metadata, uint32_t slot_number,
const std::function<bool(int, const std::string&)>& writer);
} // namespace fs_mgr
diff --git a/healthd/animation.h b/healthd/animation.h
index 562b689..f59fb38 100644
--- a/healthd/animation.h
+++ b/healthd/animation.h
@@ -20,7 +20,7 @@
#include <inttypes.h>
#include <string>
-struct GRSurface;
+class GRSurface;
struct GRFont;
namespace android {
diff --git a/init/action_parser.cpp b/init/action_parser.cpp
index 1481162..2d497b3 100644
--- a/init/action_parser.cpp
+++ b/init/action_parser.cpp
@@ -19,7 +19,11 @@
#include <android-base/properties.h>
#include <android-base/strings.h>
-#include "stable_properties.h"
+#if defined(__ANDROID__)
+#include "property_service.h"
+#else
+#include "host_init_stubs.h"
+#endif
using android::base::GetBoolProperty;
using android::base::StartsWith;
@@ -36,15 +40,7 @@
return true;
}
- if (kExportedActionableProperties.count(prop_name) == 1) {
- return true;
- }
- for (const auto& prefix : kPartnerPrefixes) {
- if (android::base::StartsWith(prop_name, prefix)) {
- return true;
- }
- }
- return false;
+ return CanReadProperty(subcontext->context(), prop_name);
}
Result<Success> ParsePropertyTrigger(const std::string& trigger, Subcontext* subcontext,
diff --git a/init/host_init_stubs.cpp b/init/host_init_stubs.cpp
index 8866bdc..b85e54a 100644
--- a/init/host_init_stubs.cpp
+++ b/init/host_init_stubs.cpp
@@ -30,6 +30,9 @@
std::string default_console = "/dev/console";
// property_service.h
+bool CanReadProperty(const std::string& source_context, const std::string& name) {
+ return true;
+}
uint32_t SetProperty(const std::string& key, const std::string& value) {
android::base::SetProperty(key, value);
return 0;
diff --git a/init/host_init_stubs.h b/init/host_init_stubs.h
index 0af11f6..63ceead 100644
--- a/init/host_init_stubs.h
+++ b/init/host_init_stubs.h
@@ -39,6 +39,7 @@
extern std::string default_console;
// property_service.h
+bool CanReadProperty(const std::string& source_context, const std::string& name);
extern uint32_t (*property_set)(const std::string& name, const std::string& value);
uint32_t HandlePropertySet(const std::string& name, const std::string& value,
const std::string& source_context, const ucred& cr, std::string* error);
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 6aed0a3..5328869 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -111,6 +111,22 @@
LOG(FATAL) << "Failed to load serialized property info file";
}
}
+
+bool CanReadProperty(const std::string& source_context, const std::string& name) {
+ const char* target_context = nullptr;
+ property_info_area->GetPropertyInfo(name.c_str(), &target_context, nullptr);
+
+ PropertyAuditData audit_data;
+
+ audit_data.name = name.c_str();
+
+ ucred cr = {.pid = 0, .uid = 0, .gid = 0};
+ audit_data.cr = &cr;
+
+ return selinux_check_access(source_context.c_str(), target_context, "file", "read",
+ &audit_data) == 0;
+}
+
static bool CheckMacPerms(const std::string& name, const char* target_context,
const char* source_context, const ucred& cr) {
if (!target_context || !source_context) {
diff --git a/init/property_service.h b/init/property_service.h
index cacd987..9022f5a 100644
--- a/init/property_service.h
+++ b/init/property_service.h
@@ -26,6 +26,8 @@
namespace android {
namespace init {
+bool CanReadProperty(const std::string& source_context, const std::string& name);
+
extern uint32_t (*property_set)(const std::string& name, const std::string& value);
uint32_t HandlePropertySet(const std::string& name, const std::string& value,
diff --git a/init/stable_properties.h b/init/stable_properties.h
deleted file mode 100644
index baef833..0000000
--- a/init/stable_properties.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2018 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_STABLE_PROPERTIES_H
-#define _INIT_STABLE_PROPERTIES_H
-
-#include <set>
-#include <string>
-
-namespace android {
-namespace init {
-
-static constexpr const char* kPartnerPrefixes[] = {
- "init.svc.vendor.", "ro.vendor.", "persist.vendor.", "vendor.", "init.svc.odm.", "ro.odm.",
- "persist.odm.", "odm.", "ro.boot.",
-};
-
-static const std::set<std::string> kExportedActionableProperties = {
- "dev.bootcomplete",
- "init.svc.console",
- "init.svc.dumpstatez",
- "init.svc.mediadrm",
- "init.svc.surfaceflinger",
- "init.svc.zygote",
- "persist.bluetooth.btsnoopenable",
- "persist.sys.crash_rcu",
- "persist.sys.usb.usbradio.config",
- "persist.sys.zram_enabled",
- "ro.board.platform",
- "ro.bootmode",
- "ro.build.type",
- "ro.crypto.state",
- "ro.crypto.type",
- "ro.debuggable",
- "sys.boot_completed",
- "sys.boot_from_charger_mode",
- "sys.retaildemo.enabled",
- "sys.shutdown.requested",
- "sys.usb.config",
- "sys.usb.configfs",
- "sys.usb.ffs.mtp.ready",
- "sys.usb.ffs.ready",
- "sys.user.0.ce_available",
- "sys.vdso",
- "vold.decrypt",
- "vold.post_fs_data_done",
- "vts.native_server.on",
- "wlan.driver.status",
-};
-
-} // namespace init
-} // namespace android
-
-#endif
diff --git a/libbacktrace/UnwindStackMap.cpp b/libbacktrace/UnwindStackMap.cpp
index d2d6ab8..52dd441 100644
--- a/libbacktrace/UnwindStackMap.cpp
+++ b/libbacktrace/UnwindStackMap.cpp
@@ -106,7 +106,7 @@
return "";
}
- unwindstack::Elf* elf = map_info->GetElf(process_memory(), true);
+ unwindstack::Elf* elf = map_info->GetElf(process_memory());
std::string name;
uint64_t func_offset;
diff --git a/libnativebridge/Android.bp b/libnativebridge/Android.bp
index 6e63b74..92fd2a2 100644
--- a/libnativebridge/Android.bp
+++ b/libnativebridge/Android.bp
@@ -10,9 +10,11 @@
host_supported: true,
srcs: ["native_bridge.cc"],
+ header_libs: [
+ "libbase_headers",
+ ],
shared_libs: [
"liblog",
- "libbase",
],
export_include_dirs: ["include"],
diff --git a/libnativebridge/tests/Android.mk b/libnativebridge/tests/Android.mk
index 5b9ba1c..4ed6e20 100644
--- a/libnativebridge/tests/Android.mk
+++ b/libnativebridge/tests/Android.mk
@@ -29,10 +29,12 @@
shared_libraries := \
liblog \
- libbase \
libnativebridge \
libnativebridge-dummy
+header_libraries := \
+ libbase_headers
+
libnativebridge_tests_common_cflags := \
-Wall \
-Werror \
@@ -40,6 +42,7 @@
$(foreach file,$(test_src_files), \
$(eval include $(CLEAR_VARS)) \
$(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \
+ $(eval LOCAL_HEADER_LIBRARIES := $(header_libraries)) \
$(eval LOCAL_SRC_FILES := $(file)) \
$(eval LOCAL_CFLAGS := $(libnativebridge_tests_common_cflags)) \
$(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
@@ -49,6 +52,7 @@
$(foreach file,$(test_src_files), \
$(eval include $(CLEAR_VARS)) \
$(eval LOCAL_SHARED_LIBRARIES := $(shared_libraries)) \
+ $(eval LOCAL_HEADER_LIBRARIES := $(header_libraries)) \
$(eval LOCAL_SRC_FILES := $(file)) \
$(eval LOCAL_CFLAGS := $(libnativebridge_tests_common_cflags)) \
$(eval LOCAL_MODULE := $(notdir $(file:%.cpp=%))) \
diff --git a/libunwindstack/Elf.cpp b/libunwindstack/Elf.cpp
index 56a0679..60ef796 100644
--- a/libunwindstack/Elf.cpp
+++ b/libunwindstack/Elf.cpp
@@ -40,7 +40,7 @@
std::unordered_map<std::string, std::pair<std::shared_ptr<Elf>, bool>>* Elf::cache_;
std::mutex* Elf::cache_lock_;
-bool Elf::Init(bool init_gnu_debugdata) {
+bool Elf::Init() {
load_bias_ = 0;
if (!memory_) {
return false;
@@ -54,11 +54,7 @@
valid_ = interface_->Init(&load_bias_);
if (valid_) {
interface_->InitHeaders(load_bias_);
- if (init_gnu_debugdata) {
- InitGnuDebugdata();
- } else {
- gnu_debugdata_interface_.reset(nullptr);
- }
+ InitGnuDebugdata();
} else {
interface_.reset(nullptr);
}
diff --git a/libunwindstack/Global.cpp b/libunwindstack/Global.cpp
index b449c7e..f0ad2b6 100644
--- a/libunwindstack/Global.cpp
+++ b/libunwindstack/Global.cpp
@@ -46,7 +46,7 @@
}
}
- Elf* elf = info->GetElf(memory_, true);
+ Elf* elf = info->GetElf(memory_);
uint64_t ptr;
// Find first non-empty list (libraries might be loaded multiple times).
if (elf->GetGlobalVariable(variable, &ptr) && ptr != 0) {
diff --git a/libunwindstack/JitDebug.cpp b/libunwindstack/JitDebug.cpp
index fe680d7..d6af49e 100644
--- a/libunwindstack/JitDebug.cpp
+++ b/libunwindstack/JitDebug.cpp
@@ -201,7 +201,7 @@
entry_addr_ = (this->*read_entry_func_)(&start, &size);
Elf* elf = new Elf(new MemoryRange(memory_, start, size, 0));
- elf->Init(true);
+ elf->Init();
if (!elf->valid()) {
// The data is not formatted in a way we understand, do not attempt
// to process any other entries.
diff --git a/libunwindstack/LocalUnwinder.cpp b/libunwindstack/LocalUnwinder.cpp
index 952b332..31337a9 100644
--- a/libunwindstack/LocalUnwinder.cpp
+++ b/libunwindstack/LocalUnwinder.cpp
@@ -100,7 +100,7 @@
break;
}
- Elf* elf = map_info->GetElf(process_memory_, true);
+ Elf* elf = map_info->GetElf(process_memory_);
uint64_t rel_pc = elf->GetRelPc(cur_pc, map_info);
uint64_t step_pc = rel_pc;
uint64_t pc_adjustment;
diff --git a/libunwindstack/MapInfo.cpp b/libunwindstack/MapInfo.cpp
index 52b7535..8527797 100644
--- a/libunwindstack/MapInfo.cpp
+++ b/libunwindstack/MapInfo.cpp
@@ -146,7 +146,7 @@
return nullptr;
}
-Elf* MapInfo::GetElf(const std::shared_ptr<Memory>& process_memory, bool init_gnu_debugdata) {
+Elf* MapInfo::GetElf(const std::shared_ptr<Memory>& process_memory) {
// Make sure no other thread is trying to add the elf to this map.
std::lock_guard<std::mutex> guard(mutex_);
@@ -175,7 +175,7 @@
elf.reset(new Elf(memory));
// If the init fails, keep the elf around as an invalid object so we
// don't try to reinit the object.
- elf->Init(init_gnu_debugdata);
+ elf->Init();
if (locked) {
Elf::CacheAdd(this);
diff --git a/libunwindstack/RegsInfo.h b/libunwindstack/RegsInfo.h
index e6dd33c..e445a91 100644
--- a/libunwindstack/RegsInfo.h
+++ b/libunwindstack/RegsInfo.h
@@ -41,7 +41,7 @@
}
inline AddressType* Save(uint32_t reg) {
- if (reg > MAX_REGISTERS) {
+ if (reg >= MAX_REGISTERS) {
// This should never happen since all currently supported
// architectures have < 64 total registers.
abort();
diff --git a/libunwindstack/Unwinder.cpp b/libunwindstack/Unwinder.cpp
index ee1cd1a..b8b0ac6 100644
--- a/libunwindstack/Unwinder.cpp
+++ b/libunwindstack/Unwinder.cpp
@@ -155,7 +155,7 @@
if (ShouldStop(map_suffixes_to_ignore, map_info->name)) {
break;
}
- elf = map_info->GetElf(process_memory_, true);
+ elf = map_info->GetElf(process_memory_);
step_pc = regs_->pc();
rel_pc = elf->GetRelPc(step_pc, map_info);
// Everyone except elf data in gdb jit debug maps uses the relative pc.
diff --git a/libunwindstack/include/unwindstack/Elf.h b/libunwindstack/include/unwindstack/Elf.h
index 9af859d..24cabf2 100644
--- a/libunwindstack/include/unwindstack/Elf.h
+++ b/libunwindstack/include/unwindstack/Elf.h
@@ -53,7 +53,7 @@
Elf(Memory* memory) : memory_(memory) {}
virtual ~Elf() = default;
- bool Init(bool init_gnu_debugdata);
+ bool Init();
void InitGnuDebugdata();
diff --git a/libunwindstack/include/unwindstack/MapInfo.h b/libunwindstack/include/unwindstack/MapInfo.h
index 9755c48..ff634f2 100644
--- a/libunwindstack/include/unwindstack/MapInfo.h
+++ b/libunwindstack/include/unwindstack/MapInfo.h
@@ -72,7 +72,7 @@
std::atomic_uint64_t load_bias;
// This function guarantees it will never return nullptr.
- Elf* GetElf(const std::shared_ptr<Memory>& process_memory, bool init_gnu_debugdata = false);
+ Elf* GetElf(const std::shared_ptr<Memory>& process_memory);
uint64_t GetLoadBias(const std::shared_ptr<Memory>& process_memory);
diff --git a/libunwindstack/tests/ElfCacheTest.cpp b/libunwindstack/tests/ElfCacheTest.cpp
index 1afd4ef..8ed697c 100644
--- a/libunwindstack/tests/ElfCacheTest.cpp
+++ b/libunwindstack/tests/ElfCacheTest.cpp
@@ -82,9 +82,9 @@
MapInfo info1(nullptr, start, end, 0, 0x5, tf.path);
MapInfo info2(nullptr, start, end, 0, 0x5, tf.path);
- Elf* elf1 = info1.GetElf(memory_, true);
+ Elf* elf1 = info1.GetElf(memory_);
ASSERT_TRUE(elf1->valid());
- Elf* elf2 = info2.GetElf(memory_, true);
+ Elf* elf2 = info2.GetElf(memory_);
ASSERT_TRUE(elf2->valid());
if (cache_enabled) {
@@ -132,10 +132,10 @@
MapInfo info300_1(nullptr, start, end, 0x300, 0x5, tf.path);
MapInfo info300_2(nullptr, start, end, 0x300, 0x5, tf.path);
- Elf* elf0_1 = info0_1.GetElf(memory_, true);
+ Elf* elf0_1 = info0_1.GetElf(memory_);
ASSERT_TRUE(elf0_1->valid());
EXPECT_EQ(ARCH_ARM, elf0_1->arch());
- Elf* elf0_2 = info0_2.GetElf(memory_, true);
+ Elf* elf0_2 = info0_2.GetElf(memory_);
ASSERT_TRUE(elf0_2->valid());
EXPECT_EQ(ARCH_ARM, elf0_2->arch());
EXPECT_EQ(0U, info0_1.elf_offset);
@@ -146,10 +146,10 @@
EXPECT_NE(elf0_1, elf0_2);
}
- Elf* elf100_1 = info100_1.GetElf(memory_, true);
+ Elf* elf100_1 = info100_1.GetElf(memory_);
ASSERT_TRUE(elf100_1->valid());
EXPECT_EQ(ARCH_X86, elf100_1->arch());
- Elf* elf100_2 = info100_2.GetElf(memory_, true);
+ Elf* elf100_2 = info100_2.GetElf(memory_);
ASSERT_TRUE(elf100_2->valid());
EXPECT_EQ(ARCH_X86, elf100_2->arch());
EXPECT_EQ(0U, info100_1.elf_offset);
@@ -160,10 +160,10 @@
EXPECT_NE(elf100_1, elf100_2);
}
- Elf* elf200_1 = info200_1.GetElf(memory_, true);
+ Elf* elf200_1 = info200_1.GetElf(memory_);
ASSERT_TRUE(elf200_1->valid());
EXPECT_EQ(ARCH_X86_64, elf200_1->arch());
- Elf* elf200_2 = info200_2.GetElf(memory_, true);
+ Elf* elf200_2 = info200_2.GetElf(memory_);
ASSERT_TRUE(elf200_2->valid());
EXPECT_EQ(ARCH_X86_64, elf200_2->arch());
EXPECT_EQ(0U, info200_1.elf_offset);
@@ -174,10 +174,10 @@
EXPECT_NE(elf200_1, elf200_2);
}
- Elf* elf300_1 = info300_1.GetElf(memory_, true);
+ Elf* elf300_1 = info300_1.GetElf(memory_);
ASSERT_TRUE(elf300_1->valid());
EXPECT_EQ(ARCH_ARM, elf300_1->arch());
- Elf* elf300_2 = info300_2.GetElf(memory_, true);
+ Elf* elf300_2 = info300_2.GetElf(memory_);
ASSERT_TRUE(elf300_2->valid());
EXPECT_EQ(ARCH_ARM, elf300_2->arch());
EXPECT_EQ(0x300U, info300_1.elf_offset);
@@ -222,10 +222,10 @@
MapInfo info400_1(nullptr, start, end, 0x400, 0x5, tf.path);
MapInfo info400_2(nullptr, start, end, 0x400, 0x5, tf.path);
- Elf* elf300_1 = info300_1.GetElf(memory_, true);
+ Elf* elf300_1 = info300_1.GetElf(memory_);
ASSERT_TRUE(elf300_1->valid());
EXPECT_EQ(ARCH_ARM, elf300_1->arch());
- Elf* elf300_2 = info300_2.GetElf(memory_, true);
+ Elf* elf300_2 = info300_2.GetElf(memory_);
ASSERT_TRUE(elf300_2->valid());
EXPECT_EQ(ARCH_ARM, elf300_2->arch());
EXPECT_EQ(0x300U, info300_1.elf_offset);
@@ -236,10 +236,10 @@
EXPECT_NE(elf300_1, elf300_2);
}
- Elf* elf400_1 = info400_1.GetElf(memory_, true);
+ Elf* elf400_1 = info400_1.GetElf(memory_);
ASSERT_TRUE(elf400_1->valid());
EXPECT_EQ(ARCH_ARM, elf400_1->arch());
- Elf* elf400_2 = info400_2.GetElf(memory_, true);
+ Elf* elf400_2 = info400_2.GetElf(memory_);
ASSERT_TRUE(elf400_2->valid());
EXPECT_EQ(ARCH_ARM, elf400_2->arch());
EXPECT_EQ(0x400U, info400_1.elf_offset);
diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp
index 9a117b2..ccf8927 100644
--- a/libunwindstack/tests/ElfTest.cpp
+++ b/libunwindstack/tests/ElfTest.cpp
@@ -110,7 +110,7 @@
TEST_F(ElfTest, invalid_memory) {
Elf elf(memory_);
- ASSERT_FALSE(elf.Init(false));
+ ASSERT_FALSE(elf.Init());
ASSERT_FALSE(elf.valid());
}
@@ -122,7 +122,7 @@
// Corrupt the ELF signature.
memory_->SetData32(0, 0x7f000000);
- ASSERT_FALSE(elf.Init(false));
+ ASSERT_FALSE(elf.Init());
ASSERT_FALSE(elf.valid());
ASSERT_TRUE(elf.interface() == nullptr);
@@ -142,7 +142,7 @@
InitElf32(EM_PPC);
ResetLogs();
- ASSERT_FALSE(elf.Init(false));
+ ASSERT_FALSE(elf.Init());
ASSERT_EQ("", GetFakeLogBuf());
ASSERT_EQ("4 unwind 32 bit elf that is neither arm nor x86 nor mips: e_machine = 20\n\n",
@@ -155,7 +155,7 @@
InitElf64(EM_PPC64);
ResetLogs();
- ASSERT_FALSE(elf.Init(false));
+ ASSERT_FALSE(elf.Init());
ASSERT_EQ("", GetFakeLogBuf());
ASSERT_EQ("4 unwind 64 bit elf that is neither aarch64 nor x86_64 nor mips64: e_machine = 21\n\n",
@@ -167,7 +167,7 @@
InitElf32(EM_ARM);
- ASSERT_TRUE(elf.Init(false));
+ ASSERT_TRUE(elf.Init());
ASSERT_TRUE(elf.valid());
ASSERT_EQ(static_cast<uint32_t>(EM_ARM), elf.machine_type());
ASSERT_EQ(ELFCLASS32, elf.class_type());
@@ -179,7 +179,7 @@
InitElf32(EM_MIPS);
- ASSERT_TRUE(elf.Init(false));
+ ASSERT_TRUE(elf.Init());
ASSERT_TRUE(elf.valid());
ASSERT_EQ(static_cast<uint32_t>(EM_MIPS), elf.machine_type());
ASSERT_EQ(ELFCLASS32, elf.class_type());
@@ -191,7 +191,7 @@
InitElf32(EM_386);
- ASSERT_TRUE(elf.Init(false));
+ ASSERT_TRUE(elf.Init());
ASSERT_TRUE(elf.valid());
ASSERT_EQ(static_cast<uint32_t>(EM_386), elf.machine_type());
ASSERT_EQ(ELFCLASS32, elf.class_type());
@@ -203,7 +203,7 @@
InitElf64(EM_AARCH64);
- ASSERT_TRUE(elf.Init(false));
+ ASSERT_TRUE(elf.Init());
ASSERT_TRUE(elf.valid());
ASSERT_EQ(static_cast<uint32_t>(EM_AARCH64), elf.machine_type());
ASSERT_EQ(ELFCLASS64, elf.class_type());
@@ -215,7 +215,7 @@
InitElf64(EM_X86_64);
- ASSERT_TRUE(elf.Init(false));
+ ASSERT_TRUE(elf.Init());
ASSERT_TRUE(elf.valid());
ASSERT_EQ(static_cast<uint32_t>(EM_X86_64), elf.machine_type());
ASSERT_EQ(ELFCLASS64, elf.class_type());
@@ -227,41 +227,13 @@
InitElf64(EM_MIPS);
- ASSERT_TRUE(elf.Init(false));
+ ASSERT_TRUE(elf.Init());
ASSERT_TRUE(elf.valid());
ASSERT_EQ(static_cast<uint32_t>(EM_MIPS), elf.machine_type());
ASSERT_EQ(ELFCLASS64, elf.class_type());
ASSERT_TRUE(elf.interface() != nullptr);
}
-TEST_F(ElfTest, gnu_debugdata_init_fail32) {
- TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, false,
- [&](uint64_t offset, const void* ptr, size_t size) {
- memory_->SetMemory(offset, ptr, size);
- });
-
- Elf elf(memory_);
- ASSERT_TRUE(elf.Init(false));
- ASSERT_TRUE(elf.interface() != nullptr);
- ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr);
- EXPECT_EQ(0x1acU, elf.interface()->gnu_debugdata_offset());
- EXPECT_EQ(0x100U, elf.interface()->gnu_debugdata_size());
-}
-
-TEST_F(ElfTest, gnu_debugdata_init_fail64) {
- TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, false,
- [&](uint64_t offset, const void* ptr, size_t size) {
- memory_->SetMemory(offset, ptr, size);
- });
-
- Elf elf(memory_);
- ASSERT_TRUE(elf.Init(false));
- ASSERT_TRUE(elf.interface() != nullptr);
- ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr);
- EXPECT_EQ(0x200U, elf.interface()->gnu_debugdata_offset());
- EXPECT_EQ(0x100U, elf.interface()->gnu_debugdata_size());
-}
-
TEST_F(ElfTest, gnu_debugdata_init32) {
TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, true,
[&](uint64_t offset, const void* ptr, size_t size) {
@@ -269,7 +241,7 @@
});
Elf elf(memory_);
- ASSERT_TRUE(elf.Init(true));
+ ASSERT_TRUE(elf.Init());
ASSERT_TRUE(elf.interface() != nullptr);
ASSERT_TRUE(elf.gnu_debugdata_interface() != nullptr);
EXPECT_EQ(0x1acU, elf.interface()->gnu_debugdata_offset());
@@ -283,7 +255,7 @@
});
Elf elf(memory_);
- ASSERT_TRUE(elf.Init(true));
+ ASSERT_TRUE(elf.Init());
ASSERT_TRUE(elf.interface() != nullptr);
ASSERT_TRUE(elf.gnu_debugdata_interface() != nullptr);
EXPECT_EQ(0x200U, elf.interface()->gnu_debugdata_offset());
diff --git a/libunwindstack/tests/MapInfoGetElfTest.cpp b/libunwindstack/tests/MapInfoGetElfTest.cpp
index 918c028..c6c1c34 100644
--- a/libunwindstack/tests/MapInfoGetElfTest.cpp
+++ b/libunwindstack/tests/MapInfoGetElfTest.cpp
@@ -72,7 +72,7 @@
MapInfo info(nullptr, 0x1000, 0x2000, 0, PROT_READ, "");
// The map is empty, but this should still create an invalid elf object.
- Elf* elf = info.GetElf(process_memory_, false);
+ Elf* elf = info.GetElf(process_memory_);
ASSERT_TRUE(elf != nullptr);
ASSERT_FALSE(elf->valid());
}
@@ -84,7 +84,7 @@
TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr));
- Elf* elf = info.GetElf(process_memory_, false);
+ Elf* elf = info.GetElf(process_memory_);
ASSERT_TRUE(elf != nullptr);
ASSERT_TRUE(elf->valid());
EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
@@ -98,45 +98,13 @@
TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
memory_->SetMemory(0x8000, &ehdr, sizeof(ehdr));
- Elf* elf = info.GetElf(process_memory_, false);
+ Elf* elf = info.GetElf(process_memory_);
ASSERT_TRUE(elf != nullptr);
ASSERT_TRUE(elf->valid());
EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
EXPECT_EQ(ELFCLASS64, elf->class_type());
}
-TEST_F(MapInfoGetElfTest, gnu_debugdata_do_not_init32) {
- MapInfo info(nullptr, 0x4000, 0x8000, 0, PROT_READ, "");
-
- TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, false,
- [&](uint64_t offset, const void* ptr, size_t size) {
- memory_->SetMemory(0x4000 + offset, ptr, size);
- });
-
- Elf* elf = info.GetElf(process_memory_, false);
- ASSERT_TRUE(elf != nullptr);
- ASSERT_TRUE(elf->valid());
- EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
- EXPECT_EQ(ELFCLASS32, elf->class_type());
- EXPECT_TRUE(elf->gnu_debugdata_interface() == nullptr);
-}
-
-TEST_F(MapInfoGetElfTest, gnu_debugdata_do_not_init64) {
- MapInfo info(nullptr, 0x6000, 0x8000, 0, PROT_READ, "");
-
- TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, false,
- [&](uint64_t offset, const void* ptr, size_t size) {
- memory_->SetMemory(0x6000 + offset, ptr, size);
- });
-
- Elf* elf = info.GetElf(process_memory_, false);
- ASSERT_TRUE(elf != nullptr);
- ASSERT_TRUE(elf->valid());
- EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
- EXPECT_EQ(ELFCLASS64, elf->class_type());
- EXPECT_TRUE(elf->gnu_debugdata_interface() == nullptr);
-}
-
TEST_F(MapInfoGetElfTest, gnu_debugdata_init32) {
MapInfo info(nullptr, 0x2000, 0x3000, 0, PROT_READ, "");
@@ -145,7 +113,7 @@
memory_->SetMemory(0x2000 + offset, ptr, size);
});
- Elf* elf = info.GetElf(process_memory_, true);
+ Elf* elf = info.GetElf(process_memory_);
ASSERT_TRUE(elf != nullptr);
ASSERT_TRUE(elf->valid());
EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
@@ -161,7 +129,7 @@
memory_->SetMemory(0x5000 + offset, ptr, size);
});
- Elf* elf = info.GetElf(process_memory_, true);
+ Elf* elf = info.GetElf(process_memory_);
ASSERT_TRUE(elf != nullptr);
ASSERT_TRUE(elf->valid());
EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
@@ -176,20 +144,20 @@
TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
ASSERT_TRUE(android::base::WriteFully(elf_.fd, &ehdr, sizeof(ehdr)));
- Elf* elf = info.GetElf(process_memory_, false);
+ Elf* elf = info.GetElf(process_memory_);
ASSERT_TRUE(elf != nullptr);
ASSERT_FALSE(elf->valid());
info.elf.reset();
info.end = 0xfff;
- elf = info.GetElf(process_memory_, false);
+ elf = info.GetElf(process_memory_);
ASSERT_TRUE(elf != nullptr);
ASSERT_FALSE(elf->valid());
// Make sure this test is valid.
info.elf.reset();
info.end = 0x2000;
- elf = info.GetElf(process_memory_, false);
+ elf = info.GetElf(process_memory_);
ASSERT_TRUE(elf != nullptr);
ASSERT_TRUE(elf->valid());
}
@@ -206,7 +174,7 @@
memcpy(buffer.data(), &ehdr, sizeof(ehdr));
ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
- Elf* elf = info.GetElf(process_memory_, false);
+ Elf* elf = info.GetElf(process_memory_);
ASSERT_TRUE(elf != nullptr);
ASSERT_TRUE(elf->valid());
ASSERT_TRUE(elf->memory() != nullptr);
@@ -235,7 +203,7 @@
memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr));
ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
- Elf* elf = info.GetElf(process_memory_, false);
+ Elf* elf = info.GetElf(process_memory_);
ASSERT_TRUE(elf != nullptr);
ASSERT_TRUE(elf->valid());
ASSERT_TRUE(elf->memory() != nullptr);
@@ -268,7 +236,7 @@
memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr));
ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
- Elf* elf = info.GetElf(process_memory_, false);
+ Elf* elf = info.GetElf(process_memory_);
ASSERT_TRUE(elf != nullptr);
ASSERT_TRUE(elf->valid());
ASSERT_TRUE(elf->memory() != nullptr);
@@ -296,7 +264,7 @@
memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr));
ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
- Elf* elf = info.GetElf(process_memory_, false);
+ Elf* elf = info.GetElf(process_memory_);
ASSERT_TRUE(elf != nullptr);
ASSERT_TRUE(elf->valid());
ASSERT_TRUE(elf->memory() != nullptr);
@@ -322,13 +290,13 @@
ehdr.e_shnum = 0;
memory_->SetMemory(0x9000, &ehdr, sizeof(ehdr));
- Elf* elf = info.GetElf(process_memory_, false);
+ Elf* elf = info.GetElf(process_memory_);
ASSERT_TRUE(elf != nullptr);
ASSERT_FALSE(elf->valid());
info.elf.reset();
info.flags = PROT_READ;
- elf = info.GetElf(process_memory_, false);
+ elf = info.GetElf(process_memory_);
ASSERT_TRUE(elf->valid());
}
@@ -345,20 +313,20 @@
ehdr.e_shnum = 0;
memory_->SetMemory(0x7000, &ehdr, sizeof(ehdr));
- Elf* elf = info.GetElf(process_memory_, false);
+ Elf* elf = info.GetElf(process_memory_);
ASSERT_TRUE(elf != nullptr);
ASSERT_FALSE(elf->valid());
// Set the name to nothing to verify that it still fails.
info.elf.reset();
info.name = "";
- elf = info.GetElf(process_memory_, false);
+ elf = info.GetElf(process_memory_);
ASSERT_FALSE(elf->valid());
// Change the flags and verify the elf is valid now.
info.elf.reset();
info.flags = PROT_READ;
- elf = info.GetElf(process_memory_, false);
+ elf = info.GetElf(process_memory_);
ASSERT_TRUE(elf->valid());
}
@@ -384,7 +352,7 @@
std::thread* thread = new std::thread([i, this, &wait, &info, &elf_in_threads]() {
while (wait)
;
- Elf* elf = info.GetElf(process_memory_, false);
+ Elf* elf = info.GetElf(process_memory_);
elf_in_threads[i] = elf;
});
threads.push_back(thread);
diff --git a/libunwindstack/tests/RegsInfoTest.cpp b/libunwindstack/tests/RegsInfoTest.cpp
index 052b5bf..a6bc2c5 100644
--- a/libunwindstack/tests/RegsInfoTest.cpp
+++ b/libunwindstack/tests/RegsInfoTest.cpp
@@ -82,4 +82,11 @@
}
}
+TEST(RegsInfoTest, invalid_register) {
+ RegsImplFake<uint64_t> regs(64);
+ RegsInfo<uint64_t> info(®s);
+
+ EXPECT_DEATH(info.Save(RegsInfo<uint64_t>::MAX_REGISTERS), "");
+}
+
} // namespace unwindstack
diff --git a/libunwindstack/tools/unwind_info.cpp b/libunwindstack/tools/unwind_info.cpp
index 266a6db..aebeb95 100644
--- a/libunwindstack/tools/unwind_info.cpp
+++ b/libunwindstack/tools/unwind_info.cpp
@@ -113,7 +113,7 @@
}
Elf elf(memory);
- if (!elf.Init(true) || !elf.valid()) {
+ if (!elf.Init() || !elf.valid()) {
printf("%s is not a valid elf file.\n", file);
return 1;
}
diff --git a/libunwindstack/tools/unwind_reg_info.cpp b/libunwindstack/tools/unwind_reg_info.cpp
index 0f01566..4b6f49a 100644
--- a/libunwindstack/tools/unwind_reg_info.cpp
+++ b/libunwindstack/tools/unwind_reg_info.cpp
@@ -173,7 +173,7 @@
}
Elf elf(memory);
- if (!elf.Init(true) || !elf.valid()) {
+ if (!elf.Init() || !elf.valid()) {
printf("%s is not a valid elf file.\n", file);
return 1;
}
diff --git a/libunwindstack/tools/unwind_symbols.cpp b/libunwindstack/tools/unwind_symbols.cpp
index f8e3e92..9128430 100644
--- a/libunwindstack/tools/unwind_symbols.cpp
+++ b/libunwindstack/tools/unwind_symbols.cpp
@@ -66,7 +66,7 @@
}
unwindstack::Elf elf(memory);
- if (!elf.Init(true) || !elf.valid()) {
+ if (!elf.Init() || !elf.valid()) {
printf("%s is not a valid elf file.\n", argv[1]);
return 1;
}
diff --git a/libziparchive/Android.bp b/libziparchive/Android.bp
index 3308adf..608afb7 100644
--- a/libziparchive/Android.bp
+++ b/libziparchive/Android.bp
@@ -84,14 +84,6 @@
"libz",
],
target: {
- android: {
- shared_libs: [
- "libutils",
- ],
- },
- host: {
- static_libs: ["libutils"],
- },
linux_bionic: {
enabled: true,
},
diff --git a/libziparchive/include/ziparchive/zip_archive.h b/libziparchive/include/ziparchive/zip_archive.h
index 32d7901..3952532 100644
--- a/libziparchive/include/ziparchive/zip_archive.h
+++ b/libziparchive/include/ziparchive/zip_archive.h
@@ -14,17 +14,16 @@
* limitations under the License.
*/
+#pragma once
+
/*
* Read-only access to Zip archives, with minimal heap allocation.
*/
-#ifndef LIBZIPARCHIVE_ZIPARCHIVE_H_
-#define LIBZIPARCHIVE_ZIPARCHIVE_H_
#include <stdint.h>
#include <string.h>
#include <sys/cdefs.h>
#include <sys/types.h>
-#include <utils/Compat.h>
/* Zip compression methods we support */
enum {
@@ -273,5 +272,3 @@
int32_t Inflate(const Reader& reader, const uint32_t compressed_length,
const uint32_t uncompressed_length, Writer* writer, uint64_t* crc_out);
} // namespace zip_archive
-
-#endif // LIBZIPARCHIVE_ZIPARCHIVE_H_
diff --git a/libziparchive/include/ziparchive/zip_writer.h b/libziparchive/include/ziparchive/zip_writer.h
index 0e0caf1..6e4ca62 100644
--- a/libziparchive/include/ziparchive/zip_writer.h
+++ b/libziparchive/include/ziparchive/zip_writer.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef LIBZIPARCHIVE_ZIPWRITER_H_
-#define LIBZIPARCHIVE_ZIPWRITER_H_
+#pragma once
#include <cstdio>
#include <ctime>
@@ -25,7 +24,6 @@
#include <vector>
#include "android-base/macros.h"
-#include "utils/Compat.h"
struct z_stream_s;
typedef struct z_stream_s z_stream;
@@ -183,5 +181,3 @@
std::unique_ptr<z_stream, void (*)(z_stream*)> z_stream_;
std::vector<uint8_t> buffer_;
};
-
-#endif /* LIBZIPARCHIVE_ZIPWRITER_H_ */
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index 4221ee7..9d6d919 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -20,7 +20,8 @@
#define LOG_TAG "ziparchive"
-#include <assert.h>
+#include "ziparchive/zip_archive.h"
+
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
@@ -40,12 +41,10 @@
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/macros.h> // TEMP_FAILURE_RETRY may or may not be in unistd
+#include <android-base/mapped_file.h>
#include <android-base/memory.h>
#include <android-base/utf8.h>
#include <log/log.h>
-#include <utils/Compat.h>
-#include <utils/FileMap.h>
-#include "ziparchive/zip_archive.h"
#include "zlib.h"
#include "entry_name_utils-inl.h"
@@ -58,12 +57,6 @@
// specified in the local file header and the central directory.
static const bool kCrcChecksEnabled = false;
-// This is for windows. If we don't open a file in binary mode, weird
-// things will happen.
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
// The maximum number of bytes to scan backwards for the EOCD start.
static const uint32_t kMaxEOCDSearch = kMaxCommentLen + sizeof(EocdRecord);
@@ -196,7 +189,7 @@
close_file(assume_ownership),
directory_offset(0),
central_directory(),
- directory_map(new android::FileMap()),
+ directory_map(),
num_entries(0),
hash_table_size(0),
hash_table(nullptr) {
@@ -212,7 +205,7 @@
close_file(false),
directory_offset(0),
central_directory(),
- directory_map(new android::FileMap()),
+ directory_map(),
num_entries(0),
hash_table_size(0),
hash_table(nullptr) {}
@@ -303,8 +296,7 @@
* in archive.
*/
- if (!archive->InitializeCentralDirectory(debug_file_name,
- static_cast<off64_t>(eocd->cd_start_offset),
+ if (!archive->InitializeCentralDirectory(static_cast<off64_t>(eocd->cd_start_offset),
static_cast<size_t>(eocd->cd_size))) {
ALOGE("Zip: failed to intialize central directory.\n");
return kMmapFailed;
@@ -823,7 +815,7 @@
virtual bool Append(uint8_t* buf, size_t buf_size) override {
if (bytes_written_ + buf_size > size_) {
- ALOGW("Zip: Unexpected size " ZD " (declared) vs " ZD " (actual)", size_,
+ ALOGW("Zip: Unexpected size %zu (declared) vs %zu (actual)", size_,
bytes_written_ + buf_size);
return false;
}
@@ -910,7 +902,7 @@
virtual bool Append(uint8_t* buf, size_t buf_size) override {
if (total_bytes_written_ + buf_size > declared_length_) {
- ALOGW("Zip: Unexpected size " ZD " (declared) vs " ZD " (actual)", declared_length_,
+ ALOGW("Zip: Unexpected size %zu (declared) vs %zu (actual)", declared_length_,
total_bytes_written_ + buf_size);
return false;
}
@@ -919,7 +911,7 @@
if (result) {
total_bytes_written_ += buf_size;
} else {
- ALOGW("Zip: unable to write " ZD " bytes to file; %s", buf_size, strerror(errno));
+ ALOGW("Zip: unable to write %zu bytes to file; %s", buf_size, strerror(errno));
}
return result;
@@ -1048,7 +1040,7 @@
}
} while (zerr == Z_OK);
- assert(zerr == Z_STREAM_END); /* other errors should've been caught */
+ CHECK_EQ(zerr, Z_STREAM_END); /* other errors should've been caught */
// NOTE: zstream.adler is always set to 0, because we're using the -MAX_WBITS
// "feature" of zlib to tell it there won't be a zlib file header. zlib
@@ -1255,16 +1247,14 @@
length_ = cd_size;
}
-bool ZipArchive::InitializeCentralDirectory(const char* debug_file_name, off64_t cd_start_offset,
- size_t cd_size) {
+bool ZipArchive::InitializeCentralDirectory(off64_t cd_start_offset, size_t cd_size) {
if (mapped_zip.HasFd()) {
- if (!directory_map->create(debug_file_name, mapped_zip.GetFileDescriptor(), cd_start_offset,
- cd_size, true /* read only */)) {
- return false;
- }
+ directory_map = android::base::MappedFile::FromFd(mapped_zip.GetFileDescriptor(),
+ cd_start_offset, cd_size, PROT_READ);
+ if (!directory_map) return false;
- CHECK_EQ(directory_map->getDataLength(), cd_size);
- central_directory.Initialize(directory_map->getDataPtr(), 0 /*offset*/, cd_size);
+ CHECK_EQ(directory_map->size(), cd_size);
+ central_directory.Initialize(directory_map->data(), 0 /*offset*/, cd_size);
} else {
if (mapped_zip.GetBasePtr() == nullptr) {
ALOGE("Zip: Failed to map central directory, bad mapped_zip base pointer\n");
diff --git a/libziparchive/zip_archive_private.h b/libziparchive/zip_archive_private.h
index 83cb11f..330a02a 100644
--- a/libziparchive/zip_archive_private.h
+++ b/libziparchive/zip_archive_private.h
@@ -14,8 +14,9 @@
* limitations under the License.
*/
-#ifndef LIBZIPARCHIVE_ZIPARCHIVE_PRIVATE_H_
-#define LIBZIPARCHIVE_ZIPARCHIVE_PRIVATE_H_
+#pragma once
+
+#include <ziparchive/zip_archive.h>
#include <stdint.h>
#include <stdlib.h>
@@ -24,9 +25,8 @@
#include <memory>
#include <vector>
-#include <utils/FileMap.h>
-#include <ziparchive/zip_archive.h>
#include "android-base/macros.h"
+#include "android-base/mapped_file.h"
static const char* kErrorMessages[] = {
"Success",
@@ -164,7 +164,7 @@
// mapped central directory area
off64_t directory_offset;
CentralDirectory central_directory;
- std::unique_ptr<android::FileMap> directory_map;
+ std::unique_ptr<android::base::MappedFile> directory_map;
// number of entries in the Zip archive
uint16_t num_entries;
@@ -180,8 +180,5 @@
ZipArchive(void* address, size_t length);
~ZipArchive();
- bool InitializeCentralDirectory(const char* debug_file_name, off64_t cd_start_offset,
- size_t cd_size);
+ bool InitializeCentralDirectory(off64_t cd_start_offset, size_t cd_size);
};
-
-#endif // LIBZIPARCHIVE_ZIPARCHIVE_PRIVATE_H_
diff --git a/libziparchive/zip_archive_test.cc b/libziparchive/zip_archive_test.cc
index 23dd5dc..af9f4c8 100644
--- a/libziparchive/zip_archive_test.cc
+++ b/libziparchive/zip_archive_test.cc
@@ -27,10 +27,10 @@
#include <vector>
#include <android-base/file.h>
+#include <android-base/mapped_file.h>
#include <android-base/test_utils.h>
#include <android-base/unique_fd.h>
#include <gtest/gtest.h>
-#include <utils/FileMap.h>
#include <ziparchive/zip_archive.h>
#include <ziparchive/zip_archive_stream_entry.h>
@@ -416,11 +416,10 @@
ASSERT_EQ(0, fstat(fd, &sb));
// Memory map the file first and open the archive from the memory region.
- android::FileMap file_map;
- file_map.create(zip_path.c_str(), fd, 0 /*offset*/, sb.st_size, true);
+ auto file_map{android::base::MappedFile::FromFd(fd, 0, sb.st_size, PROT_READ)};
ZipArchiveHandle handle;
- ASSERT_EQ(0, OpenArchiveFromMemory(file_map.getDataPtr(), file_map.getDataLength(),
- zip_path.c_str(), &handle));
+ ASSERT_EQ(0,
+ OpenArchiveFromMemory(file_map->data(), file_map->size(), zip_path.c_str(), &handle));
// Assert one entry can be found and extracted correctly.
std::string BINARY_PATH("META-INF/com/google/android/update-binary");
diff --git a/libziparchive/zip_writer.cc b/libziparchive/zip_writer.cc
index ed1d135..981df3a 100644
--- a/libziparchive/zip_writer.cc
+++ b/libziparchive/zip_writer.cc
@@ -26,8 +26,6 @@
#include <vector>
#include "android-base/logging.h"
-#include "utils/Compat.h"
-#include "utils/Log.h"
#include "entry_name_utils-inl.h"
#include "zip_archive_common.h"
@@ -303,10 +301,10 @@
if (zerr != Z_OK) {
if (zerr == Z_VERSION_ERROR) {
- ALOGE("Installed zlib is not compatible with linked version (%s)", ZLIB_VERSION);
+ LOG(ERROR) << "Installed zlib is not compatible with linked version (" << ZLIB_VERSION << ")";
return HandleError(kZlibError);
} else {
- ALOGE("deflateInit2 failed (zerr=%d)", zerr);
+ LOG(ERROR) << "deflateInit2 failed (zerr=" << zerr << ")";
return HandleError(kZlibError);
}
}
diff --git a/llkd/include/llkd.h b/llkd/include/llkd.h
index 4d39dd9..2c62fca 100644
--- a/llkd/include/llkd.h
+++ b/llkd/include/llkd.h
@@ -51,13 +51,13 @@
#define LLK_CHECK_STACK_DEFAULT "cma_alloc,__get_user_pages"
#define LLK_BLACKLIST_PROCESS_PROPERTY "ro.llk.blacklist.process"
#define LLK_BLACKLIST_PROCESS_DEFAULT \
- "0,1,2,init,[kthreadd],[khungtaskd],lmkd,lmkd.llkd,llkd,watchdogd,[watchdogd],[watchdogd/0]"
+ "0,1,2,init,[kthreadd],[khungtaskd],lmkd,llkd,watchdogd,[watchdogd],[watchdogd/0]"
#define LLK_BLACKLIST_PARENT_PROPERTY "ro.llk.blacklist.parent"
#define LLK_BLACKLIST_PARENT_DEFAULT "0,2,[kthreadd]"
#define LLK_BLACKLIST_UID_PROPERTY "ro.llk.blacklist.uid"
#define LLK_BLACKLIST_UID_DEFAULT ""
#define LLK_BLACKLIST_STACK_PROPERTY "ro.llk.blacklist.process.stack"
-#define LLK_BLACKLIST_STACK_DEFAULT "init,lmkd.llkd,llkd,keystore,/system/bin/keystore,ueventd,apexd"
+#define LLK_BLACKLIST_STACK_DEFAULT "init,lmkd.llkd,llkd,keystore,ueventd,apexd"
/* clang-format on */
__END_DECLS
diff --git a/llkd/libllkd.cpp b/llkd/libllkd.cpp
index 6840ed0..2727aab 100644
--- a/llkd/libllkd.cpp
+++ b/llkd/libllkd.cpp
@@ -712,6 +712,7 @@
if (llkSkipName(std::to_string(procp->pid), llkBlacklistStack)) return false;
if (llkSkipName(procp->getComm(), llkBlacklistStack)) return false;
if (llkSkipName(procp->getCmdline(), llkBlacklistStack)) return false;
+ if (llkSkipName(android::base::Basename(procp->getCmdline()), llkBlacklistStack)) return false;
auto kernel_stack = ReadFile(piddir + "/stack");
if (kernel_stack.empty()) {
@@ -995,13 +996,18 @@
if (llkSkipName(procp->getCmdline())) {
break;
}
+ if (llkSkipName(android::base::Basename(procp->getCmdline()))) {
+ break;
+ }
auto pprocp = llkTidLookup(ppid);
if (pprocp == nullptr) {
pprocp = llkTidAlloc(ppid, ppid, 0, "", 0, '?');
}
- if ((pprocp != nullptr) && (llkSkipName(pprocp->getComm(), llkBlacklistParent) ||
- llkSkipName(pprocp->getCmdline(), llkBlacklistParent))) {
+ if ((pprocp != nullptr) &&
+ (llkSkipName(pprocp->getComm(), llkBlacklistParent) ||
+ llkSkipName(pprocp->getCmdline(), llkBlacklistParent) ||
+ llkSkipName(android::base::Basename(pprocp->getCmdline()), llkBlacklistParent))) {
break;
}
diff --git a/lmkd/include/lmkd.h b/lmkd/include/lmkd.h
index e8f51da..e72d159 100644
--- a/lmkd/include/lmkd.h
+++ b/lmkd/include/lmkd.h
@@ -31,6 +31,7 @@
LMK_PROCPRIO, /* Register a process and set its oom_adj_score */
LMK_PROCREMOVE, /* Unregister a process */
LMK_PROCPURGE, /* Purge all registered processes */
+ LMK_GETKILLCNT, /* Get number of kills */
};
/*
@@ -152,6 +153,44 @@
return sizeof(int);
}
+/* LMK_GETKILLCNT packet payload */
+struct lmk_getkillcnt {
+ int min_oomadj;
+ int max_oomadj;
+};
+
+/*
+ * For LMK_GETKILLCNT packet get its payload.
+ * Warning: no checks performed, caller should ensure valid parameters.
+ */
+inline void lmkd_pack_get_getkillcnt(LMKD_CTRL_PACKET packet,
+ struct lmk_getkillcnt *params) {
+ params->min_oomadj = ntohl(packet[1]);
+ params->max_oomadj = ntohl(packet[2]);
+}
+
+/*
+ * Prepare LMK_GETKILLCNT packet and return packet size in bytes.
+ * Warning: no checks performed, caller should ensure valid parameters.
+ */
+inline size_t lmkd_pack_set_getkillcnt(LMKD_CTRL_PACKET packet,
+ struct lmk_getkillcnt *params) {
+ packet[0] = htonl(LMK_GETKILLCNT);
+ packet[1] = htonl(params->min_oomadj);
+ packet[2] = htonl(params->max_oomadj);
+ return 3 * sizeof(int);
+}
+
+/*
+ * Prepare LMK_GETKILLCNT reply packet and return packet size in bytes.
+ * Warning: no checks performed, caller should ensure valid parameters.
+ */
+inline size_t lmkd_pack_set_getkillcnt_repl(LMKD_CTRL_PACKET packet, int kill_cnt) {
+ packet[0] = htonl(LMK_GETKILLCNT);
+ packet[1] = htonl(kill_cnt);
+ return 2 * sizeof(int);
+}
+
__END_DECLS
#endif /* _LMKD_H_ */
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 0a469e8..e3c4ccc 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -313,7 +313,20 @@
#define pid_hashfn(x) ((((x) >> 8) ^ (x)) & (PIDHASH_SZ - 1))
#define ADJTOSLOT(adj) ((adj) + -OOM_SCORE_ADJ_MIN)
-static struct adjslot_list procadjslot_list[ADJTOSLOT(OOM_SCORE_ADJ_MAX) + 1];
+#define ADJTOSLOT_COUNT (ADJTOSLOT(OOM_SCORE_ADJ_MAX) + 1)
+static struct adjslot_list procadjslot_list[ADJTOSLOT_COUNT];
+
+#define MAX_DISTINCT_OOM_ADJ 32
+#define KILLCNT_INVALID_IDX 0xFF
+/*
+ * Because killcnt array is sparse a two-level indirection is used
+ * to keep the size small. killcnt_idx stores index of the element in
+ * killcnt array. Index KILLCNT_INVALID_IDX indicates an unused slot.
+ */
+static uint8_t killcnt_idx[ADJTOSLOT_COUNT];
+static uint16_t killcnt[MAX_DISTINCT_OOM_ADJ];
+static int killcnt_free_idx = 0;
+static uint32_t killcnt_total = 0;
/* PAGE_SIZE / 1024 */
static long page_k;
@@ -644,6 +657,67 @@
memset(&pidhash[0], 0, sizeof(pidhash));
}
+static void inc_killcnt(int oomadj) {
+ int slot = ADJTOSLOT(oomadj);
+ uint8_t idx = killcnt_idx[slot];
+
+ if (idx == KILLCNT_INVALID_IDX) {
+ /* index is not assigned for this oomadj */
+ if (killcnt_free_idx < MAX_DISTINCT_OOM_ADJ) {
+ killcnt_idx[slot] = killcnt_free_idx;
+ killcnt[killcnt_free_idx] = 1;
+ killcnt_free_idx++;
+ } else {
+ ALOGW("Number of distinct oomadj levels exceeds %d",
+ MAX_DISTINCT_OOM_ADJ);
+ }
+ } else {
+ /*
+ * wraparound is highly unlikely and is detectable using total
+ * counter because it has to be equal to the sum of all counters
+ */
+ killcnt[idx]++;
+ }
+ /* increment total kill counter */
+ killcnt_total++;
+}
+
+static int get_killcnt(int min_oomadj, int max_oomadj) {
+ int slot;
+ int count = 0;
+
+ if (min_oomadj > max_oomadj)
+ return 0;
+
+ /* special case to get total kill count */
+ if (min_oomadj > OOM_SCORE_ADJ_MAX)
+ return killcnt_total;
+
+ while (min_oomadj <= max_oomadj &&
+ (slot = ADJTOSLOT(min_oomadj)) < ADJTOSLOT_COUNT) {
+ uint8_t idx = killcnt_idx[slot];
+ if (idx != KILLCNT_INVALID_IDX) {
+ count += killcnt[idx];
+ }
+ min_oomadj++;
+ }
+
+ return count;
+}
+
+static int cmd_getkillcnt(LMKD_CTRL_PACKET packet) {
+ struct lmk_getkillcnt params;
+
+ if (use_inkernel_interface) {
+ /* kernel driver does not expose this information */
+ return 0;
+ }
+
+ lmkd_pack_get_getkillcnt(packet, ¶ms);
+
+ return get_killcnt(params.min_oomadj, params.max_oomadj);
+}
+
static void cmd_target(int ntargets, LMKD_CTRL_PACKET packet) {
int i;
struct lmk_target target;
@@ -748,12 +822,28 @@
return ret;
}
+static int ctrl_data_write(int dsock_idx, char *buf, size_t bufsz) {
+ int ret = 0;
+
+ ret = TEMP_FAILURE_RETRY(write(data_sock[dsock_idx].sock, buf, bufsz));
+
+ if (ret == -1) {
+ ALOGE("control data socket write failed; errno=%d", errno);
+ } else if (ret == 0) {
+ ALOGE("Got EOF on control data socket");
+ ret = -1;
+ }
+
+ return ret;
+}
+
static void ctrl_command_handler(int dsock_idx) {
LMKD_CTRL_PACKET packet;
int len;
enum lmk_cmd cmd;
int nargs;
int targets;
+ int kill_cnt;
len = ctrl_data_read(dsock_idx, (char *)packet, CTRL_PACKET_MAX_SIZE);
if (len <= 0)
@@ -791,6 +881,14 @@
goto wronglen;
cmd_procpurge();
break;
+ case LMK_GETKILLCNT:
+ if (nargs != 2)
+ goto wronglen;
+ kill_cnt = cmd_getkillcnt(packet);
+ len = lmkd_pack_set_getkillcnt_repl(packet, kill_cnt);
+ if (ctrl_data_write(dsock_idx, (char *)packet, len) != len)
+ return;
+ break;
default:
ALOGE("Received unknown command code %d", cmd);
return;
@@ -1200,6 +1298,7 @@
/* CAP_KILL required */
r = kill(pid, SIGKILL);
+ inc_killcnt(procp->oomadj);
ALOGI("Kill '%s' (%d), uid %d, oom_adj %d to free %ldkB",
taskname, pid, uid, procp->oomadj, tasksize * page_k);
@@ -1700,6 +1799,8 @@
procadjslot_list[i].prev = &procadjslot_list[i];
}
+ memset(killcnt_idx, KILLCNT_INVALID_IDX, sizeof(killcnt_idx));
+
return 0;
}
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 393e204..aad00ad 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -146,13 +146,7 @@
include $(BUILD_SYSTEM)/base_rules.mk
-# Regenerate init.environ.rc if PRODUCT_BOOTCLASSPATH has changed.
-bcp_md5 := $(word 1, $(shell echo $(PRODUCT_BOOTCLASSPATH) $(PRODUCT_SYSTEM_SERVER_CLASSPATH) | $(MD5SUM)))
-bcp_dep := $(intermediates)/$(bcp_md5).bcp.dep
-$(bcp_dep) :
- $(hide) mkdir -p $(dir $@) && rm -rf $(dir $@)*.bcp.dep && touch $@
-
-$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/init.environ.rc.in $(bcp_dep)
+$(LOCAL_BUILT_MODULE): $(LOCAL_PATH)/init.environ.rc.in
@echo "Generate: $< -> $@"
@mkdir -p $(dir $@)
$(hide) sed -e 's?%BOOTCLASSPATH%?$(PRODUCT_BOOTCLASSPATH)?g' $< >$@
@@ -161,9 +155,6 @@
$(hide) sed -i -e 's?%EXPORT_GLOBAL_GCOV_OPTIONS%?$(EXPORT_GLOBAL_GCOV_OPTIONS)?g' $@
$(hide) sed -i -e 's?%EXPORT_GLOBAL_HWASAN_OPTIONS%?$(EXPORT_GLOBAL_HWASAN_OPTIONS)?g' $@
-bcp_md5 :=
-bcp_dep :=
-
# Append PLATFORM_VNDK_VERSION to base name.
define append_vndk_version
$(strip \
diff --git a/rootdir/init.rc b/rootdir/init.rc
index ea83ef9..025e3c3 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -489,6 +489,8 @@
mkdir /data/misc/profman 0770 system shell
mkdir /data/misc/gcov 0770 root root
+ mkdir /data/preloads 0775 system system
+
mkdir /data/vendor 0771 root root
mkdir /data/vendor_ce 0771 root root
mkdir /data/vendor_de 0771 root root