Merge "Support for stopping/starting post-data-mount class subsets." into qt-dev
diff --git a/adb/adb.cpp b/adb/adb.cpp
index e417f05..2dd22b3 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -280,6 +280,9 @@
} else if (type == "sideload") {
D("setting connection_state to kCsSideload");
t->SetConnectionState(kCsSideload);
+ } else if (type == "rescue") {
+ D("setting connection_state to kCsRescue");
+ t->SetConnectionState(kCsRescue);
} else {
D("setting connection_state to kCsHost");
t->SetConnectionState(kCsHost);
diff --git a/adb/adb.h b/adb/adb.h
index c60dcbc..3a6f059 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -107,6 +107,7 @@
kCsHost,
kCsRecovery,
kCsSideload,
+ kCsRescue,
};
inline bool ConnectionStateIsOnline(ConnectionState state) {
@@ -116,6 +117,7 @@
case kCsHost:
case kCsRecovery:
case kCsSideload:
+ case kCsRescue:
return true;
default:
return false;
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 43a3e5e..e2a17c5 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -190,7 +190,7 @@
"scripting:\n"
" wait-for[-TRANSPORT]-STATE\n"
" wait for device to be in the given state\n"
- " STATE: device, recovery, sideload, bootloader, or disconnect\n"
+ " STATE: device, recovery, rescue, sideload, bootloader, or disconnect\n"
" TRANSPORT: usb, local, or any [default=any]\n"
" get-state print offline | bootloader | device\n"
" get-serialno print <serial-number>\n"
@@ -838,26 +838,25 @@
#define SIDELOAD_HOST_BLOCK_SIZE (CHUNK_SIZE)
-/*
- * The sideload-host protocol serves the data in a file (given on the
- * command line) to the client, using a simple protocol:
- *
- * - The connect message includes the total number of bytes in the
- * file and a block size chosen by us.
- *
- * - The other side sends the desired block number as eight decimal
- * digits (eg "00000023" for block 23). Blocks are numbered from
- * zero.
- *
- * - We send back the data of the requested block. The last block is
- * likely to be partial; when the last block is requested we only
- * send the part of the block that exists, it's not padded up to the
- * block size.
- *
- * - When the other side sends "DONEDONE" instead of a block number,
- * we hang up.
- */
-static int adb_sideload_host(const char* filename) {
+// Connects to the sideload / rescue service on the device (served by minadbd) and sends over the
+// data in an OTA package.
+//
+// It uses a simple protocol as follows.
+//
+// - The connect message includes the total number of bytes in the file and a block size chosen by
+// us.
+//
+// - The other side sends the desired block number as eight decimal digits (e.g. "00000023" for
+// block 23). Blocks are numbered from zero.
+//
+// - We send back the data of the requested block. The last block is likely to be partial; when the
+// last block is requested we only send the part of the block that exists, it's not padded up to
+// the block size.
+//
+// - When the other side sends "DONEDONE" or "FAILFAIL" instead of a block number, we have done all
+// the data transfer.
+//
+static int adb_sideload_install(const char* filename, bool rescue_mode) {
// TODO: use a LinePrinter instead...
struct stat sb;
if (stat(filename, &sb) == -1) {
@@ -870,14 +869,18 @@
return -1;
}
- std::string service =
- android::base::StringPrintf("sideload-host:%" PRId64 ":%d",
- static_cast<int64_t>(sb.st_size), SIDELOAD_HOST_BLOCK_SIZE);
+ std::string service = android::base::StringPrintf(
+ "%s:%" PRId64 ":%d", rescue_mode ? "rescue-install" : "sideload-host",
+ static_cast<int64_t>(sb.st_size), SIDELOAD_HOST_BLOCK_SIZE);
std::string error;
unique_fd device_fd(adb_connect(service, &error));
if (device_fd < 0) {
fprintf(stderr, "adb: sideload connection failed: %s\n", error.c_str());
+ if (rescue_mode) {
+ return -1;
+ }
+
// If this is a small enough package, maybe this is an older device that doesn't
// support sideload-host. Try falling back to the older (<= K) sideload method.
if (sb.st_size > INT_MAX) {
@@ -901,10 +904,14 @@
}
buf[8] = '\0';
- if (strcmp("DONEDONE", buf) == 0) {
+ if (strcmp(kMinadbdServicesExitSuccess, buf) == 0 ||
+ strcmp(kMinadbdServicesExitFailure, buf) == 0) {
printf("\rTotal xfer: %.2fx%*s\n",
static_cast<double>(xfer) / (sb.st_size ? sb.st_size : 1),
static_cast<int>(strlen(filename) + 10), "");
+ if (strcmp(kMinadbdServicesExitFailure, buf) == 0) {
+ return 1;
+ }
return 0;
}
@@ -954,6 +961,33 @@
}
}
+static int adb_wipe_devices() {
+ auto wipe_devices_message_size = strlen(kMinadbdServicesExitSuccess);
+ std::string error;
+ unique_fd fd(adb_connect(
+ android::base::StringPrintf("rescue-wipe:userdata:%zu", wipe_devices_message_size),
+ &error));
+ if (fd < 0) {
+ fprintf(stderr, "adb: wipe device connection failed: %s\n", error.c_str());
+ return 1;
+ }
+
+ std::string message(wipe_devices_message_size, '\0');
+ if (!ReadFdExactly(fd, message.data(), wipe_devices_message_size)) {
+ fprintf(stderr, "adb: failed to read wipe result: %s\n", strerror(errno));
+ return 1;
+ }
+
+ if (message == kMinadbdServicesExitSuccess) {
+ return 0;
+ }
+
+ if (message != kMinadbdServicesExitFailure) {
+ fprintf(stderr, "adb: got unexpected message from rescue wipe %s\n", message.c_str());
+ }
+ return 1;
+}
+
/**
* Run ppp in "notty" mode against a resource listed as the first parameter
* eg:
@@ -1037,11 +1071,12 @@
}
if (components[3] != "any" && components[3] != "bootloader" && components[3] != "device" &&
- components[3] != "recovery" && components[3] != "sideload" &&
+ components[3] != "recovery" && components[3] != "rescue" && components[3] != "sideload" &&
components[3] != "disconnect") {
fprintf(stderr,
"adb: unknown state %s; "
- "expected 'any', 'bootloader', 'device', 'recovery', 'sideload', or 'disconnect'\n",
+ "expected 'any', 'bootloader', 'device', 'recovery', 'rescue', 'sideload', or "
+ "'disconnect'\n",
components[3].c_str());
return false;
}
@@ -1627,11 +1662,28 @@
return adb_kill_server() ? 0 : 1;
} else if (!strcmp(argv[0], "sideload")) {
if (argc != 2) error_exit("sideload requires an argument");
- if (adb_sideload_host(argv[1])) {
+ if (adb_sideload_install(argv[1], false /* rescue_mode */)) {
return 1;
} else {
return 0;
}
+ } else if (!strcmp(argv[0], "rescue")) {
+ // adb rescue getprop <prop>
+ // adb rescue install <filename>
+ // adb rescue wipe userdata
+ if (argc != 3) error_exit("rescue requires two arguments");
+ if (!strcmp(argv[1], "getprop")) {
+ return adb_connect_command(android::base::StringPrintf("rescue-getprop:%s", argv[2]));
+ } else if (!strcmp(argv[1], "install")) {
+ if (adb_sideload_install(argv[2], true /* rescue_mode */) != 0) {
+ return 1;
+ }
+ } else if (!strcmp(argv[1], "wipe") && !strcmp(argv[2], "userdata")) {
+ return adb_wipe_devices();
+ } else {
+ error_exit("invalid rescue argument");
+ }
+ return 0;
} else if (!strcmp(argv[0], "tcpip")) {
if (argc != 2) error_exit("tcpip requires an argument");
int port;
diff --git a/adb/services.cpp b/adb/services.cpp
index cf346ba..335ffc4 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -227,6 +227,8 @@
sinfo->state = kCsDevice;
} else if (name == "-recovery") {
sinfo->state = kCsRecovery;
+ } else if (name == "-rescue") {
+ sinfo->state = kCsRescue;
} else if (name == "-sideload") {
sinfo->state = kCsSideload;
} else if (name == "-bootloader") {
diff --git a/adb/services.h b/adb/services.h
index 0ce25ba..6fc89d7 100644
--- a/adb/services.h
+++ b/adb/services.h
@@ -23,5 +23,10 @@
constexpr char kShellServiceArgPty[] = "pty";
constexpr char kShellServiceArgShellProtocol[] = "v2";
+// Special flags sent by minadbd. They indicate the end of sideload transfer and the result of
+// installation or wipe.
+constexpr char kMinadbdServicesExitSuccess[] = "DONEDONE";
+constexpr char kMinadbdServicesExitFailure[] = "FAILFAIL";
+
unique_fd create_service_thread(const char* service_name, std::function<void(unique_fd)> func);
#endif // SERVICES_H_
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 15c3a9a..841865a 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -1012,6 +1012,8 @@
return "host";
case kCsRecovery:
return "recovery";
+ case kCsRescue:
+ return "rescue";
case kCsNoPerm:
return UsbNoPermissionsShortHelpText();
case kCsSideload:
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/types.h b/debuggerd/libdebuggerd/include/libdebuggerd/types.h
index 70583af..eb4b1b8 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/types.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/types.h
@@ -23,6 +23,9 @@
struct ThreadInfo {
std::unique_ptr<unwindstack::Regs> registers;
+
+ pid_t uid;
+
pid_t tid;
std::string thread_name;
diff --git a/debuggerd/libdebuggerd/test/tombstone_test.cpp b/debuggerd/libdebuggerd/test/tombstone_test.cpp
index 3196ce8..88c206f 100644
--- a/debuggerd/libdebuggerd/test/tombstone_test.cpp
+++ b/debuggerd/libdebuggerd/test/tombstone_test.cpp
@@ -343,6 +343,16 @@
ASSERT_STREQ(expected.c_str(), amfd_data_.c_str());
}
+TEST_F(TombstoneTest, dump_thread_info_uid) {
+ dump_thread_info(&log_, ThreadInfo{.uid = 1,
+ .pid = 2,
+ .tid = 3,
+ .thread_name = "some_thread",
+ .process_name = "some_process"});
+ std::string expected = "pid: 2, tid: 3, name: some_thread >>> some_process <<<\nuid: 1\n";
+ ASSERT_STREQ(expected.c_str(), amfd_data_.c_str());
+}
+
TEST_F(TombstoneTest, dump_timestamp) {
setenv("TZ", "UTC", 1);
tzset();
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index d1726cd..d246722 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -151,6 +151,7 @@
_LOG(log, logtype::HEADER, "pid: %d, tid: %d, name: %s >>> %s <<<\n", thread_info.pid,
thread_info.tid, thread_info.thread_name.c_str(), thread_info.process_name.c_str());
+ _LOG(log, logtype::HEADER, "uid: %d\n", thread_info.uid);
}
static void dump_stack_segment(log_t* log, unwindstack::Maps* maps, unwindstack::Memory* memory,
@@ -615,6 +616,7 @@
void engrave_tombstone_ucontext(int tombstone_fd, uint64_t abort_msg_address, siginfo_t* siginfo,
ucontext_t* ucontext) {
+ pid_t uid = getuid();
pid_t pid = getpid();
pid_t tid = gettid();
@@ -636,6 +638,7 @@
std::map<pid_t, ThreadInfo> threads;
threads[gettid()] = ThreadInfo{
.registers = std::move(regs),
+ .uid = uid,
.tid = tid,
.thread_name = thread_name,
.pid = pid,
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 4043fc6..da049ef 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -38,6 +38,7 @@
using android::base::ParseByteCount;
using android::base::ParseInt;
+using android::base::ReadFileToString;
using android::base::Split;
using android::base::StartsWith;
@@ -660,6 +661,8 @@
TransformFstabForGsi(fstab);
}
+ SkipMountingPartitions(fstab);
+
return true;
}
@@ -687,6 +690,36 @@
return false;
}
+ SkipMountingPartitions(fstab);
+
+ return true;
+}
+
+// For GSI to skip mounting /product and /product_services, until there are
+// well-defined interfaces between them and /system. Otherwise, the GSI flashed
+// on /system might not be able to work with /product and /product_services.
+// When they're skipped here, /system/product and /system/product_services in
+// GSI will be used.
+bool SkipMountingPartitions(Fstab* fstab) {
+ constexpr const char kSkipMountConfig[] = "/system/etc/init/config/skip_mount.cfg";
+
+ std::string skip_config;
+ if (!ReadFileToString(kSkipMountConfig, &skip_config)) {
+ return true;
+ }
+
+ for (const auto& skip_mount_point : Split(skip_config, "\n")) {
+ if (skip_mount_point.empty()) {
+ continue;
+ }
+ auto it = std::remove_if(fstab->begin(), fstab->end(),
+ [&skip_mount_point](const auto& entry) {
+ return entry.mount_point == skip_mount_point;
+ });
+ fstab->erase(it, fstab->end());
+ LOG(INFO) << "Skip mounting partition: " << skip_mount_point;
+ }
+
return true;
}
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index 88da41d..d7afed6 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -99,6 +99,7 @@
bool ReadFstabFromFile(const std::string& path, Fstab* fstab);
bool ReadFstabFromDt(Fstab* fstab, bool log = true);
bool ReadDefaultFstab(Fstab* fstab);
+bool SkipMountingPartitions(Fstab* fstab);
FstabEntry* GetEntryForMountPoint(Fstab* fstab, const std::string& path);
diff --git a/init/README.md b/init/README.md
index f222dd4..929f0e4 100644
--- a/init/README.md
+++ b/init/README.md
@@ -191,7 +191,7 @@
`critical`
> This is a device-critical service. If it exits more than four times in
- four minutes, the device will reboot into bootloader.
+ four minutes or before boot completes, the device will reboot into bootloader.
`disabled`
> This service will not automatically start with its class.
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index 3900f72..3e76556 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -43,7 +43,6 @@
#include "uevent_listener.h"
#include "util.h"
-using android::base::ReadFileToString;
using android::base::Split;
using android::base::Timer;
using android::fs_mgr::AvbHandle;
@@ -55,6 +54,7 @@
using android::fs_mgr::FstabEntry;
using android::fs_mgr::ReadDefaultFstab;
using android::fs_mgr::ReadFstabFromDt;
+using android::fs_mgr::SkipMountingPartitions;
using namespace std::literals;
@@ -524,38 +524,10 @@
return true;
}
-// For GSI to skip mounting /product and /product_services, until there are
-// well-defined interfaces between them and /system. Otherwise, the GSI flashed
-// on /system might not be able to work with /product and /product_services.
-// When they're skipped here, /system/product and /system/product_services in
-// GSI will be used.
-bool FirstStageMount::TrySkipMountingPartitions() {
- constexpr const char kSkipMountConfig[] = "/system/etc/init/config/skip_mount.cfg";
-
- std::string skip_config;
- if (!ReadFileToString(kSkipMountConfig, &skip_config)) {
- return true;
- }
-
- for (const auto& skip_mount_point : Split(skip_config, "\n")) {
- if (skip_mount_point.empty()) {
- continue;
- }
- auto it = std::remove_if(fstab_.begin(), fstab_.end(),
- [&skip_mount_point](const auto& entry) {
- return entry.mount_point == skip_mount_point;
- });
- fstab_.erase(it, fstab_.end());
- LOG(INFO) << "Skip mounting partition: " << skip_mount_point;
- }
-
- return true;
-}
-
bool FirstStageMount::MountPartitions() {
if (!TrySwitchSystemAsRoot()) return false;
- if (!TrySkipMountingPartitions()) return false;
+ if (!SkipMountingPartitions(&fstab_)) return false;
for (auto current = fstab_.begin(); current != fstab_.end();) {
// We've already mounted /system above.
diff --git a/init/service.cpp b/init/service.cpp
index 8c3e228..2f96681 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -372,16 +372,20 @@
return;
}
- // If we crash > 4 times in 4 minutes, reboot into bootloader or set crashing property
+ // If we crash > 4 times in 4 minutes or before boot_completed,
+ // reboot into bootloader or set crashing property
boot_clock::time_point now = boot_clock::now();
if (((flags_ & SVC_CRITICAL) || !pre_apexd_) && !(flags_ & SVC_RESTART)) {
- if (now < time_crashed_ + 4min) {
+ bool boot_completed = android::base::GetBoolProperty("sys.boot_completed", false);
+ if (now < time_crashed_ + 4min || !boot_completed) {
if (++crash_count_ > 4) {
if (flags_ & SVC_CRITICAL) {
// Aborts into bootloader
- LOG(FATAL) << "critical process '" << name_ << "' exited 4 times in 4 minutes";
+ LOG(FATAL) << "critical process '" << name_ << "' exited 4 times "
+ << (boot_completed ? "in 4 minutes" : "before boot completed");
} else {
- LOG(ERROR) << "updatable process '" << name_ << "' exited 4 times in 4 minutes";
+ LOG(ERROR) << "updatable process '" << name_ << "' exited 4 times "
+ << (boot_completed ? "in 4 minutes" : "before boot completed");
// Notifies update_verifier and apexd
property_set("ro.init.updatable_crashing", "1");
}
diff --git a/libmeminfo/tools/procrank.cpp b/libmeminfo/tools/procrank.cpp
index 5e89254..cb3757d 100644
--- a/libmeminfo/tools/procrank.cpp
+++ b/libmeminfo/tools/procrank.cpp
@@ -42,7 +42,6 @@
public:
ProcessRecord(pid_t pid, bool get_wss = false, uint64_t pgflags = 0, uint64_t pgflags_mask = 0)
: pid_(-1),
- procmem_(nullptr),
oomadj_(OOM_SCORE_ADJ_MAX + 1),
cmdline_(""),
proportional_swap_(0),
@@ -79,15 +78,15 @@
// The .c_str() assignment below then takes care of trimming the cmdline at the first
// 0x00. This is how original procrank worked (luckily)
cmdline_.resize(strlen(cmdline_.c_str()));
- procmem_ = std::move(procmem);
+ usage_or_wss_ = get_wss ? procmem->Wss() : procmem->Usage();
+ swap_offsets_ = procmem->SwapOffsets();
pid_ = pid;
}
bool valid() const { return pid_ != -1; }
void CalculateSwap(const uint16_t* swap_offset_array, float zram_compression_ratio) {
- const std::vector<uint16_t>& swp_offs = procmem_->SwapOffsets();
- for (auto& off : swp_offs) {
+ for (auto& off : swap_offsets_) {
proportional_swap_ += getpagesize() / swap_offset_array[off];
unique_swap_ += swap_offset_array[off] == 1 ? getpagesize() : 0;
zswap_ = proportional_swap_ * zram_compression_ratio;
@@ -103,18 +102,19 @@
uint64_t zswap() const { return zswap_; }
// Wrappers to ProcMemInfo
- const std::vector<uint16_t>& SwapOffsets() const { return procmem_->SwapOffsets(); }
- const MemUsage& Usage() const { return procmem_->Usage(); }
- const MemUsage& Wss() const { return procmem_->Wss(); }
+ const std::vector<uint16_t>& SwapOffsets() const { return swap_offsets_; }
+ const MemUsage& Usage() const { return usage_or_wss_; }
+ const MemUsage& Wss() const { return usage_or_wss_; }
private:
pid_t pid_;
- std::unique_ptr<ProcMemInfo> procmem_;
int32_t oomadj_;
std::string cmdline_;
uint64_t proportional_swap_;
uint64_t unique_swap_;
uint64_t zswap_;
+ MemUsage usage_or_wss_;
+ std::vector<uint16_t> swap_offsets_;
};
// Show working set instead of memory consumption
@@ -171,7 +171,7 @@
while ((dir = readdir(procdir.get()))) {
if (!::android::base::ParseInt(dir->d_name, &pid)) continue;
if (!for_each_pid(pid)) return false;
- pids->push_back(pid);
+ pids->emplace_back(pid);
}
return true;
@@ -471,7 +471,7 @@
}
// Skip processes with no memory mappings
- uint64_t vss = proc.Usage().vss;
+ uint64_t vss = show_wss ? proc.Wss().vss : proc.Usage().vss;
if (vss == 0) return true;
// collect swap_offset counts from all processes in 1st pass
@@ -481,7 +481,7 @@
return false;
}
- procs.push_back(std::move(proc));
+ procs.emplace_back(std::move(proc));
return true;
};
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index 5cc0857..e460b1a 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -220,7 +220,9 @@
}
}
- if (!initialized_ && !InitPublicNamespace(library_path.c_str(), error_msg)) {
+ // Initialize the anonymous namespace with the first non-empty library path.
+ if (!library_path.empty() && !initialized_ &&
+ !InitPublicNamespace(library_path.c_str(), error_msg)) {
return nullptr;
}