Merge "adb: add authorizing, connecting states to transport."
diff --git a/adb/Android.bp b/adb/Android.bp
index b9a1596..99de54e 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -222,7 +222,6 @@
cc_binary_host {
name: "adb",
- tags: ["debug"],
defaults: ["adb_defaults"],
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index e476e07..39983ab 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -149,8 +149,8 @@
" emu COMMAND run emulator console command\n"
"\n"
"app installation:\n"
- " install [-lrtsdg] PACKAGE\n"
- " install-multiple [-lrtsdpg] PACKAGE...\n"
+ " install [-lrtsdg] [--instant] PACKAGE\n"
+ " install-multiple [-lrtsdpg] [--instant] PACKAGE...\n"
" push package(s) to the device and install them\n"
" -l: forward lock application\n"
" -r: replace existing application\n"
@@ -159,6 +159,7 @@
" -d: allow version code downgrade (debuggable packages only)\n"
" -p: partial application install (install-multiple only)\n"
" -g: grant all runtime permissions\n"
+ " --instant: cause the app to be installed as an ephemeral install app\n"
" uninstall [-k] PACKAGE\n"
" remove this app package from the device\n"
" '-k': keep the data and cache directories\n"
diff --git a/bootstat/boot_reason_test.sh b/bootstat/boot_reason_test.sh
index b194bbe..01b8948 100755
--- a/bootstat/boot_reason_test.sh
+++ b/bootstat/boot_reason_test.sh
@@ -312,6 +312,7 @@
init : processing action (ro.boot.bootreason=*) from (/system/etc/init/bootstat.rc
init : processing action (sys.boot_completed=1 && sys.logbootcomplete=1) from (/system/etc/init/bootstat.rc
(/system/bin/bootstat --record_boot_complete --record_boot_reason --record_time_since_factory_reset -l)'
+ (/system/bin/bootstat --set_system_boot_reason --record_boot_complete --record_boot_reason --record_time_since_factory_reset -l)'
(/system/bin/bootstat -r post_decrypt_time_elapsed)'
init : Command 'exec - system log -- /system/bin/bootstat --record_boot_complete' action=sys.boot_completed=1 && sys.logbootcomplete=1 (/system/etc/init/bootstat.rc:
init : Command 'exec - system log -- /system/bin/bootstat --record_boot_reason' action=sys.boot_completed=1 && sys.logbootcomplete=1 (/system/etc/init/bootstat.rc:
@@ -582,9 +583,9 @@
duration_test
case ${TEST} in
bootloader | recovery | cold | hard | warm ) reason=${TEST} ;;
- *) reason=reboot,${TEST} ;;
+ *) reason=reboot,${TEST#optional_} ;;
esac
- adb reboot ${TEST}
+ adb reboot ${TEST#optional_}
wait_for_screen
bootloader_reason=`validate_property ro.boot.bootreason`
EXPECT_PROPERTY ro.boot.bootreason ${bootloader_reason}
@@ -948,6 +949,20 @@
report_bootstat_logs reboot,adb
}
+[ "USAGE: test_rescueparty
+
+rescueparty test
+- adb reboot rescueparty
+- (wait until screen is up, boot has completed)
+- adb shell getprop sys.boot.reason
+- adb shell getprop ro.boot.bootreason
+- NB: should report reboot,rescueparty" ]
+test_optional_rescueparty() {
+ blind_reboot_test
+ echo "WARNING: legacy devices are allowed to fail following ro.boot.bootreason result" >&2
+ EXPECT_PROPERTY ro.boot.bootreason reboot,rescueparty
+}
+
[ "USAGE: test_Its_Just_So_Hard_reboot
Its Just So Hard reboot test:
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index 9bd0628..983e195 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -101,14 +101,13 @@
#
my_dist_files := $(HOST_OUT_EXECUTABLES)/fastboot
-my_dist_files += $(HOST_OUT_EXECUTABLES)/mke2fs$(HOST_EXECUTABLE_SUFFIX)
-my_dist_files += $(HOST_OUT_EXECUTABLES)/e2fsdroid$(HOST_EXECUTABLE_SUFFIX)
-my_dist_files += $(HOST_OUT_EXECUTABLES)/make_f2fs$(HOST_EXECUTABLE_SUFFIX)
-my_dist_files += $(HOST_OUT_EXECUTABLES)/sload_f2fs$(HOST_EXECUTABLE_SUFFIX)
+my_dist_files += $(HOST_OUT_EXECUTABLES)/mke2fs
+my_dist_files += $(HOST_OUT_EXECUTABLES)/e2fsdroid
+my_dist_files += $(HOST_OUT_EXECUTABLES)/make_f2fs
+my_dist_files += $(HOST_OUT_EXECUTABLES)/sload_f2fs
$(call dist-for-goals,dist_files sdk win_sdk,$(my_dist_files))
ifdef HOST_CROSS_OS
-# Archive fastboot.exe for win_sdk build.
-$(call dist-for-goals,win_sdk,$(ALL_MODULES.host_cross_fastboot.BUILT))
+$(call dist-for-goals,dist_files sdk win_sdk,$(ALL_MODULES.host_cross_fastboot.BUILT))
endif
my_dist_files :=
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 6769fda..e9040df 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -1383,7 +1383,7 @@
mount_point = basename(fstab->recs[i].mount_point);
}
- fs_mgr_verity_ioctl_init(io, mount_point);
+ fs_mgr_dm_ioctl_init(io, DM_BUF_SIZE, mount_point);
const char* status;
if (ioctl(fd, DM_TABLE_STATUS, io)) {
diff --git a/fs_mgr/fs_mgr_avb.cpp b/fs_mgr/fs_mgr_avb.cpp
index 6ea3833..cf6b497 100644
--- a/fs_mgr/fs_mgr_avb.cpp
+++ b/fs_mgr/fs_mgr_avb.cpp
@@ -303,7 +303,7 @@
static bool load_verity_table(struct dm_ioctl* io, const std::string& dm_device_name, int fd,
uint64_t image_size, const std::string& verity_table) {
- fs_mgr_verity_ioctl_init(io, dm_device_name);
+ fs_mgr_dm_ioctl_init(io, DM_BUF_SIZE, dm_device_name);
// The buffer consists of [dm_ioctl][dm_target_spec][verity_params].
char* buffer = (char*)io;
@@ -360,14 +360,14 @@
alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
struct dm_ioctl* io = (struct dm_ioctl*)buffer;
const std::string mount_point(basename(fstab_entry->mount_point));
- if (!fs_mgr_create_verity_device(io, mount_point, fd)) {
+ if (!fs_mgr_dm_create_device(io, mount_point, fd)) {
LERROR << "Couldn't create verity device!";
return false;
}
// Gets the name of the device file.
std::string verity_blk_name;
- if (!fs_mgr_get_verity_device_name(io, mount_point, fd, &verity_blk_name)) {
+ if (!fs_mgr_dm_get_device_name(io, mount_point, fd, &verity_blk_name)) {
LERROR << "Couldn't get verity device number!";
return false;
}
@@ -386,7 +386,7 @@
}
// Activates the device.
- if (!fs_mgr_resume_verity_table(io, mount_point, fd)) {
+ if (!fs_mgr_dm_resume_table(io, mount_point, fd)) {
return false;
}
diff --git a/fs_mgr/fs_mgr_dm_ioctl.cpp b/fs_mgr/fs_mgr_dm_ioctl.cpp
index 5f9b118..3a7fae4 100644
--- a/fs_mgr/fs_mgr_dm_ioctl.cpp
+++ b/fs_mgr/fs_mgr_dm_ioctl.cpp
@@ -23,9 +23,9 @@
#include "fs_mgr_priv.h"
#include "fs_mgr_priv_dm_ioctl.h"
-void fs_mgr_verity_ioctl_init(struct dm_ioctl* io, const std::string& name) {
- memset(io, 0, DM_BUF_SIZE);
- io->data_size = DM_BUF_SIZE;
+void fs_mgr_dm_ioctl_init(struct dm_ioctl* io, size_t size, const std::string& name) {
+ memset(io, 0, size);
+ io->data_size = size;
io->data_start = sizeof(struct dm_ioctl);
io->version[0] = 4;
io->version[1] = 0;
@@ -35,8 +35,8 @@
}
}
-bool fs_mgr_create_verity_device(struct dm_ioctl* io, const std::string& name, int fd) {
- fs_mgr_verity_ioctl_init(io, name);
+bool fs_mgr_dm_create_device(struct dm_ioctl* io, const std::string& name, int fd) {
+ fs_mgr_dm_ioctl_init(io, sizeof(*io), name);
if (ioctl(fd, DM_DEV_CREATE, io)) {
PERROR << "Error creating device mapping";
return false;
@@ -44,8 +44,8 @@
return true;
}
-bool fs_mgr_destroy_verity_device(struct dm_ioctl* io, const std::string& name, int fd) {
- fs_mgr_verity_ioctl_init(io, name);
+bool fs_mgr_dm_destroy_device(struct dm_ioctl* io, const std::string& name, int fd) {
+ fs_mgr_dm_ioctl_init(io, sizeof(*io), name);
if (ioctl(fd, DM_DEV_REMOVE, io)) {
PERROR << "Error removing device mapping";
return false;
@@ -53,13 +53,13 @@
return true;
}
-bool fs_mgr_get_verity_device_name(struct dm_ioctl* io, const std::string& name, int fd,
- std::string* out_dev_name) {
+bool fs_mgr_dm_get_device_name(struct dm_ioctl* io, const std::string& name, int fd,
+ std::string* out_dev_name) {
FS_MGR_CHECK(out_dev_name != nullptr);
- fs_mgr_verity_ioctl_init(io, name);
+ fs_mgr_dm_ioctl_init(io, sizeof(*io), name);
if (ioctl(fd, DM_DEV_STATUS, io)) {
- PERROR << "Error fetching verity device number";
+ PERROR << "Error fetching device-mapper device number";
return false;
}
@@ -69,10 +69,10 @@
return true;
}
-bool fs_mgr_resume_verity_table(struct dm_ioctl* io, const std::string& name, int fd) {
- fs_mgr_verity_ioctl_init(io, name);
+bool fs_mgr_dm_resume_table(struct dm_ioctl* io, const std::string& name, int fd) {
+ fs_mgr_dm_ioctl_init(io, sizeof(*io), name);
if (ioctl(fd, DM_DEV_SUSPEND, io)) {
- PERROR << "Error activating verity device";
+ PERROR << "Error activating device table";
return false;
}
return true;
diff --git a/fs_mgr/fs_mgr_priv_dm_ioctl.h b/fs_mgr/fs_mgr_priv_dm_ioctl.h
index 792683e..792475d 100644
--- a/fs_mgr/fs_mgr_priv_dm_ioctl.h
+++ b/fs_mgr/fs_mgr_priv_dm_ioctl.h
@@ -20,15 +20,15 @@
#include <linux/dm-ioctl.h>
#include <string>
-void fs_mgr_verity_ioctl_init(struct dm_ioctl* io, const std::string& name);
+void fs_mgr_dm_ioctl_init(struct dm_ioctl* io, size_t size, const std::string& name);
-bool fs_mgr_create_verity_device(struct dm_ioctl* io, const std::string& name, int fd);
+bool fs_mgr_dm_create_device(struct dm_ioctl* io, const std::string& name, int fd);
-bool fs_mgr_destroy_verity_device(struct dm_ioctl* io, const std::string& name, int fd);
+bool fs_mgr_dm_destroy_device(struct dm_ioctl* io, const std::string& name, int fd);
-bool fs_mgr_get_verity_device_name(struct dm_ioctl* io, const std::string& name, int fd,
- std::string* out_dev_name);
+bool fs_mgr_dm_get_device_name(struct dm_ioctl* io, const std::string& name, int fd,
+ std::string* out_dev_name);
-bool fs_mgr_resume_verity_table(struct dm_ioctl* io, const std::string& name, int fd);
+bool fs_mgr_dm_resume_table(struct dm_ioctl* io, const std::string& name, int fd);
#endif /* __CORE_FS_MGR_PRIV_DM_IOCTL_H */
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index d0bb058..fe41f8a 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -258,7 +258,7 @@
char *buffer = (char*) io;
size_t bufsize;
- fs_mgr_verity_ioctl_init(io, name);
+ fs_mgr_dm_ioctl_init(io, DM_BUF_SIZE, name);
struct dm_target_spec *tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)];
@@ -805,13 +805,13 @@
}
// create the device
- if (!fs_mgr_create_verity_device(io, mount_point, fd)) {
+ if (!fs_mgr_dm_create_device(io, mount_point, fd)) {
LERROR << "Couldn't create verity device!";
goto out;
}
// get the name of the device file
- if (!fs_mgr_get_verity_device_name(io, mount_point, fd, &verity_blk_name)) {
+ if (!fs_mgr_dm_get_device_name(io, mount_point, fd, &verity_blk_name)) {
LERROR << "Couldn't get verity device number!";
goto out;
}
@@ -900,7 +900,7 @@
loaded:
// activate the device
- if (!fs_mgr_resume_verity_table(io, mount_point, fd)) {
+ if (!fs_mgr_dm_resume_table(io, mount_point, fd)) {
goto out;
}
@@ -923,7 +923,7 @@
if (!verified_at_boot) {
free(fstab->blk_device);
fstab->blk_device = strdup(verity_blk_name.c_str());
- } else if (!fs_mgr_destroy_verity_device(io, mount_point, fd)) {
+ } else if (!fs_mgr_dm_destroy_device(io, mount_point, fd)) {
LERROR << "Failed to remove verity device " << mount_point.c_str();
goto out;
}
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 8bd92cc..17d34e1 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -240,6 +240,29 @@
return Success();
}
+static Result<Success> do_interface_restart(const BuiltinArguments& args) {
+ Service* svc = ServiceList::GetInstance().FindInterface(args[1]);
+ if (!svc) return Error() << "interface " << args[1] << " not found";
+ svc->Restart();
+ return Success();
+}
+
+static Result<Success> do_interface_start(const BuiltinArguments& args) {
+ Service* svc = ServiceList::GetInstance().FindInterface(args[1]);
+ if (!svc) return Error() << "interface " << args[1] << " not found";
+ if (auto result = svc->Start(); !result) {
+ return Error() << "Could not start interface: " << result.error();
+ }
+ return Success();
+}
+
+static Result<Success> do_interface_stop(const BuiltinArguments& args) {
+ Service* svc = ServiceList::GetInstance().FindInterface(args[1]);
+ if (!svc) return Error() << "interface " << args[1] << " not found";
+ svc->Stop();
+ return Success();
+}
+
// mkdir <path> [mode] [owner] [group]
static Result<Success> do_mkdir(const BuiltinArguments& args) {
mode_t mode = 0755;
@@ -1050,6 +1073,9 @@
{"init_user0", {0, 0, {false, do_init_user0}}},
{"insmod", {1, kMax, {true, do_insmod}}},
{"installkey", {1, 1, {false, do_installkey}}},
+ {"interface_restart", {1, 1, {false, do_interface_restart}}},
+ {"interface_start", {1, 1, {false, do_interface_start}}},
+ {"interface_stop", {1, 1, {false, do_interface_stop}}},
{"load_persist_props", {0, 0, {false, do_load_persist_props}}},
{"load_system_props", {0, 0, {false, do_load_system_props}}},
{"loglevel", {1, 1, {false, do_loglevel}}},
diff --git a/init/host_init_stubs.cpp b/init/host_init_stubs.cpp
index e6cc08a..4451ac8 100644
--- a/init/host_init_stubs.cpp
+++ b/init/host_init_stubs.cpp
@@ -49,6 +49,10 @@
}
// selinux.h
+bool SelinuxHasVendorInit() {
+ return true;
+}
+
void SelabelInitialize() {}
bool SelabelLookupFileContext(const std::string& key, int type, std::string* result) {
diff --git a/init/host_init_stubs.h b/init/host_init_stubs.h
index ddfb7ae..ad48602 100644
--- a/init/host_init_stubs.h
+++ b/init/host_init_stubs.h
@@ -56,6 +56,7 @@
const std::string& source_context, const ucred& cr, std::string* error);
// selinux.h
+bool SelinuxHasVendorInit();
void SelabelInitialize();
bool SelabelLookupFileContext(const std::string& key, int type, std::string* result);
diff --git a/init/init.cpp b/init/init.cpp
index 0d5690b..645184b 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -31,6 +31,10 @@
#include <sys/types.h>
#include <unistd.h>
+#include <map>
+#include <memory>
+#include <optional>
+
#include <android-base/chrono_utils.h>
#include <android-base/file.h>
#include <android-base/logging.h>
@@ -43,9 +47,6 @@
#include <private/android_filesystem_config.h>
#include <selinux/android.h>
-#include <memory>
-#include <optional>
-
#include "action_parser.h"
#include "import_parser.h"
#include "init_first_stage.h"
@@ -130,12 +131,31 @@
}
}
-void register_epoll_handler(int fd, void (*fn)()) {
+static std::map<int, std::function<void()>> epoll_handlers;
+
+void register_epoll_handler(int fd, std::function<void()> handler) {
+ auto[it, inserted] = epoll_handlers.emplace(fd, std::move(handler));
+ if (!inserted) {
+ LOG(ERROR) << "Cannot specify two epoll handlers for a given FD";
+ return;
+ }
epoll_event ev;
ev.events = EPOLLIN;
- ev.data.ptr = reinterpret_cast<void*>(fn);
+ // std::map's iterators do not get invalidated until erased, so we use the pointer to the
+ // std::function in the map directly for epoll_ctl.
+ ev.data.ptr = reinterpret_cast<void*>(&it->second);
if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev) == -1) {
- PLOG(ERROR) << "epoll_ctl failed";
+ PLOG(ERROR) << "epoll_ctl failed to add fd";
+ epoll_handlers.erase(fd);
+ }
+}
+
+void unregister_epoll_handler(int fd) {
+ if (epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fd, nullptr) == -1) {
+ PLOG(ERROR) << "epoll_ctl failed to remove fd";
+ }
+ if (epoll_handlers.erase(fd) != 1) {
+ LOG(ERROR) << "Attempting to remove epoll handler for FD without an existing handler";
}
}
@@ -277,40 +297,29 @@
const ControlMessageFunction& function = it->second;
- if (function.target == ControlTarget::SERVICE) {
- Service* svc = ServiceList::GetInstance().FindService(name);
- if (svc == nullptr) {
- LOG(ERROR) << "No such service '" << name << "' for ctl." << msg;
- return;
- }
- if (auto result = function.action(svc); !result) {
- LOG(ERROR) << "Could not ctl." << msg << " for service " << name << ": "
- << result.error();
- }
+ Service* svc = nullptr;
+ switch (function.target) {
+ case ControlTarget::SERVICE:
+ svc = ServiceList::GetInstance().FindService(name);
+ break;
+ case ControlTarget::INTERFACE:
+ svc = ServiceList::GetInstance().FindInterface(name);
+ break;
+ default:
+ LOG(ERROR) << "Invalid function target from static map key '" << msg << "': "
+ << static_cast<std::underlying_type<ControlTarget>::type>(function.target);
+ return;
+ }
+
+ if (svc == nullptr) {
+ LOG(ERROR) << "Could not find '" << name << "' for ctl." << msg;
return;
}
- if (function.target == ControlTarget::INTERFACE) {
- for (const auto& svc : ServiceList::GetInstance()) {
- if (svc->interfaces().count(name) == 0) {
- continue;
- }
-
- if (auto result = function.action(svc.get()); !result) {
- LOG(ERROR) << "Could not handle ctl." << msg << " for service " << svc->name()
- << " with interface " << name << ": " << result.error();
- }
-
- return;
- }
-
- LOG(ERROR) << "Could not find service hosting interface " << name;
- return;
+ if (auto result = function.action(svc); !result) {
+ LOG(ERROR) << "Could not ctl." << msg << " for '" << name << "': " << result.error();
}
-
- LOG(ERROR) << "Invalid function target from static map key '" << msg
- << "': " << static_cast<std::underlying_type<ControlTarget>::type>(function.target);
}
static Result<Success> wait_for_coldboot_done_action(const BuiltinArguments& args) {
@@ -334,8 +343,8 @@
return Success();
}
-static Result<Success> keychord_init_action(const BuiltinArguments& args) {
- keychord_init();
+static Result<Success> KeychordInitAction(const BuiltinArguments& args) {
+ KeychordInit();
return Success();
}
@@ -752,7 +761,7 @@
am.QueueBuiltinAction(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng");
am.QueueBuiltinAction(SetMmapRndBitsAction, "SetMmapRndBits");
am.QueueBuiltinAction(SetKptrRestrictAction, "SetKptrRestrict");
- am.QueueBuiltinAction(keychord_init_action, "keychord_init");
+ am.QueueBuiltinAction(KeychordInitAction, "KeychordInit");
am.QueueBuiltinAction(console_init_action, "console_init");
// Trigger all the boot actions to get us started.
@@ -809,7 +818,7 @@
if (nr == -1) {
PLOG(ERROR) << "epoll_wait failed";
} else if (nr == 1) {
- ((void (*)()) ev.data.ptr)();
+ std::invoke(*reinterpret_cast<std::function<void()>*>(ev.data.ptr));
}
}
diff --git a/init/init.h b/init/init.h
index d4a0e96..e7c4d8d 100644
--- a/init/init.h
+++ b/init/init.h
@@ -19,6 +19,7 @@
#include <sys/types.h>
+#include <functional>
#include <string>
#include <vector>
@@ -42,7 +43,8 @@
void property_changed(const std::string& name, const std::string& value);
-void register_epoll_handler(int fd, void (*fn)());
+void register_epoll_handler(int fd, std::function<void()> handler);
+void unregister_epoll_handler(int fd);
bool start_waiting_for_property(const char *name, const char *value);
diff --git a/init/keychords.cpp b/init/keychords.cpp
index e686ce1..f55d2c4 100644
--- a/init/keychords.cpp
+++ b/init/keychords.cpp
@@ -16,13 +16,20 @@
#include "keychords.h"
+#include <dirent.h>
#include <fcntl.h>
-#include <stdlib.h>
-#include <sys/stat.h>
+#include <linux/input.h>
+#include <sys/cdefs.h>
+#include <sys/ioctl.h>
#include <sys/types.h>
-#include <linux/keychord.h>
#include <unistd.h>
+#include <algorithm>
+#include <functional>
+#include <memory>
+#include <string>
+#include <vector>
+
#include <android-base/logging.h>
#include <android-base/properties.h>
@@ -31,51 +38,87 @@
namespace android {
namespace init {
-static struct input_keychord *keychords = 0;
-static int keychords_count = 0;
-static int keychords_length = 0;
-static int keychord_fd = -1;
+namespace {
-void add_service_keycodes(Service* svc)
-{
- struct input_keychord *keychord;
- size_t i, size;
+int keychords_count;
- if (!svc->keycodes().empty()) {
- /* add a new keychord to the list */
- size = sizeof(*keychord) + svc->keycodes().size() * sizeof(keychord->keycodes[0]);
- keychords = (input_keychord*) realloc(keychords, keychords_length + size);
- if (!keychords) {
- PLOG(ERROR) << "could not allocate keychords";
- keychords_length = 0;
- keychords_count = 0;
- return;
+struct KeychordEntry {
+ const std::vector<int> keycodes;
+ bool notified;
+ int id;
+
+ KeychordEntry(const std::vector<int>& keycodes, int id)
+ : keycodes(keycodes), notified(false), id(id) {}
+};
+
+std::vector<KeychordEntry> keychord_entries;
+
+// Bit management
+class KeychordMask {
+ private:
+ typedef unsigned int mask_t;
+ std::vector<mask_t> bits;
+ static constexpr size_t bits_per_byte = 8;
+
+ public:
+ explicit KeychordMask(size_t bit = 0) : bits((bit + sizeof(mask_t) - 1) / sizeof(mask_t), 0) {}
+
+ void SetBit(size_t bit, bool value = true) {
+ auto idx = bit / (bits_per_byte * sizeof(mask_t));
+ if (idx >= bits.size()) return;
+ if (value) {
+ bits[idx] |= mask_t(1) << (bit % (bits_per_byte * sizeof(mask_t)));
+ } else {
+ bits[idx] &= ~(mask_t(1) << (bit % (bits_per_byte * sizeof(mask_t))));
}
-
- keychord = (struct input_keychord *)((char *)keychords + keychords_length);
- keychord->version = KEYCHORD_VERSION;
- keychord->id = keychords_count + 1;
- keychord->count = svc->keycodes().size();
- svc->set_keychord_id(keychord->id);
-
- for (i = 0; i < svc->keycodes().size(); i++) {
- keychord->keycodes[i] = svc->keycodes()[i];
- }
- keychords_count++;
- keychords_length += size;
- }
-}
-
-static void handle_keychord() {
- int ret;
- __u16 id;
-
- ret = read(keychord_fd, &id, sizeof(id));
- if (ret != sizeof(id)) {
- PLOG(ERROR) << "could not read keychord id";
- return;
}
+ bool GetBit(size_t bit) const {
+ auto idx = bit / (bits_per_byte * sizeof(mask_t));
+ return bits[idx] & (mask_t(1) << (bit % (bits_per_byte * sizeof(mask_t))));
+ }
+
+ size_t bytesize() const { return bits.size() * sizeof(mask_t); }
+ void* data() { return bits.data(); }
+ size_t size() const { return bits.size() * sizeof(mask_t) * bits_per_byte; }
+ void resize(size_t bit) {
+ auto idx = bit / (bits_per_byte * sizeof(mask_t));
+ if (idx >= bits.size()) {
+ bits.resize(idx + 1, 0);
+ }
+ }
+
+ operator bool() const {
+ for (size_t i = 0; i < bits.size(); ++i) {
+ if (bits[i]) return true;
+ }
+ return false;
+ }
+
+ KeychordMask operator&(const KeychordMask& rval) const {
+ auto len = std::min(bits.size(), rval.bits.size());
+ KeychordMask ret;
+ ret.bits.resize(len);
+ for (size_t i = 0; i < len; ++i) {
+ ret.bits[i] = bits[i] & rval.bits[i];
+ }
+ return ret;
+ }
+
+ void operator|=(const KeychordMask& rval) {
+ size_t len = rval.bits.size();
+ bits.resize(len);
+ for (size_t i = 0; i < len; ++i) {
+ bits[i] |= rval.bits[i];
+ }
+ }
+};
+
+KeychordMask keychord_current;
+
+constexpr char kDevicePath[] = "/dev/input";
+
+void HandleKeychord(int id) {
// Only handle keychords if adb is enabled.
std::string adb_enabled = android::base::GetProperty("init.svc.adbd", "");
if (adb_enabled == "running") {
@@ -94,32 +137,125 @@
}
}
-void keychord_init() {
+void KeychordLambdaCheck() {
+ for (auto& e : keychord_entries) {
+ bool found = true;
+ for (auto& code : e.keycodes) {
+ if (!keychord_current.GetBit(code)) {
+ e.notified = false;
+ found = false;
+ break;
+ }
+ }
+ if (!found) continue;
+ if (e.notified) continue;
+ e.notified = true;
+ HandleKeychord(e.id);
+ }
+}
+
+void KeychordLambdaHandler(int fd) {
+ input_event event;
+ auto res = TEMP_FAILURE_RETRY(::read(fd, &event, sizeof(event)));
+ if ((res != sizeof(event)) || (event.type != EV_KEY)) return;
+ keychord_current.SetBit(event.code, event.value);
+ KeychordLambdaCheck();
+}
+
+bool KeychordGeteventEnable(int fd) {
+ static bool EviocsmaskSupported = true;
+
+ // Make sure it is an event channel, should pass this ioctl call
+ int version;
+ if (::ioctl(fd, EVIOCGVERSION, &version)) return false;
+
+ if (EviocsmaskSupported) {
+ KeychordMask mask(EV_KEY);
+ mask.SetBit(EV_KEY);
+ input_mask msg = {};
+ msg.type = EV_SYN;
+ msg.codes_size = mask.bytesize();
+ msg.codes_ptr = reinterpret_cast<uintptr_t>(mask.data());
+ if (::ioctl(fd, EVIOCSMASK, &msg) == -1) {
+ PLOG(WARNING) << "EVIOCSMASK not supported";
+ EviocsmaskSupported = false;
+ }
+ }
+
+ KeychordMask mask;
+ for (auto& e : keychord_entries) {
+ for (auto& code : e.keycodes) {
+ mask.resize(code);
+ mask.SetBit(code);
+ }
+ }
+
+ keychord_current.resize(mask.size());
+ KeychordMask available(mask.size());
+ auto res = ::ioctl(fd, EVIOCGBIT(EV_KEY, available.bytesize()), available.data());
+ if (res == -1) return false;
+ if (!(available & mask)) return false;
+
+ if (EviocsmaskSupported) {
+ input_mask msg = {};
+ msg.type = EV_KEY;
+ msg.codes_size = mask.bytesize();
+ msg.codes_ptr = reinterpret_cast<uintptr_t>(mask.data());
+ ::ioctl(fd, EVIOCSMASK, &msg);
+ }
+
+ KeychordMask set(mask.size());
+ res = ::ioctl(fd, EVIOCGKEY(res), set.data());
+ if (res > 0) {
+ keychord_current |= mask & available & set;
+ KeychordLambdaCheck();
+ }
+ register_epoll_handler(fd, [fd]() { KeychordLambdaHandler(fd); });
+ return true;
+}
+
+void GeteventOpenDevice(const std::string& device) {
+ auto fd = TEMP_FAILURE_RETRY(::open(device.c_str(), O_RDWR | O_CLOEXEC));
+ if (fd == -1) {
+ PLOG(ERROR) << "Can not open " << device;
+ return;
+ }
+ if (!KeychordGeteventEnable(fd)) {
+ ::close(fd);
+ }
+}
+
+void GeteventOpenDevice() {
+ std::unique_ptr<DIR, decltype(&closedir)> device(opendir(kDevicePath), closedir);
+ if (!device) return;
+
+ dirent* entry;
+ while ((entry = readdir(device.get()))) {
+ if (entry->d_name[0] == '.') continue;
+ std::string devname(kDevicePath);
+ devname += '/';
+ devname += entry->d_name;
+ GeteventOpenDevice(devname);
+ }
+}
+
+void AddServiceKeycodes(Service* svc) {
+ if (svc->keycodes().empty()) return;
+ for (auto& code : svc->keycodes()) {
+ if ((code < 0) || (code >= KEY_MAX)) return;
+ }
+ ++keychords_count;
+ keychord_entries.emplace_back(KeychordEntry(svc->keycodes(), keychords_count));
+ svc->set_keychord_id(keychords_count);
+}
+
+} // namespace
+
+void KeychordInit() {
for (const auto& service : ServiceList::GetInstance()) {
- add_service_keycodes(service.get());
+ AddServiceKeycodes(service.get());
}
-
- // Nothing to do if no services require keychords.
- if (!keychords) {
- return;
- }
-
- keychord_fd = TEMP_FAILURE_RETRY(open("/dev/keychord", O_RDWR | O_CLOEXEC));
- if (keychord_fd == -1) {
- PLOG(ERROR) << "could not open /dev/keychord";
- return;
- }
-
- int ret = write(keychord_fd, keychords, keychords_length);
- if (ret != keychords_length) {
- PLOG(ERROR) << "could not configure /dev/keychord " << ret;
- close(keychord_fd);
- }
-
- free(keychords);
- keychords = nullptr;
-
- register_epoll_handler(keychord_fd, handle_keychord);
+ if (keychords_count) GeteventOpenDevice();
}
} // namespace init
diff --git a/init/keychords.h b/init/keychords.h
index 1c34098..689a3b5 100644
--- a/init/keychords.h
+++ b/init/keychords.h
@@ -22,8 +22,7 @@
namespace android {
namespace init {
-void add_service_keycodes(Service* svc);
-void keychord_init();
+void KeychordInit();
} // namespace init
} // namespace android
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 99d3c83..c3100a5 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -59,6 +59,7 @@
#include "init.h"
#include "persistent_properties.h"
#include "property_type.h"
+#include "selinux.h"
#include "subcontext.h"
#include "util.h"
@@ -542,7 +543,7 @@
size_t flen = 0;
const char* context = kInitContext.c_str();
- if (GetIntProperty("ro.vndk.version", 28) >= 28) {
+ if (SelinuxHasVendorInit()) {
for (const auto& [path_prefix, secontext] : paths_and_secontexts) {
if (StartsWith(filename, path_prefix)) {
context = secontext;
diff --git a/init/selinux.cpp b/init/selinux.cpp
index 6aba9c1..0ba5c4a 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -55,12 +55,14 @@
#include <android-base/chrono_utils.h>
#include <android-base/file.h>
#include <android-base/logging.h>
+#include <android-base/parseint.h>
#include <android-base/unique_fd.h>
#include <selinux/android.h>
#include "log.h"
#include "util.h"
+using android::base::ParseInt;
using android::base::Timer;
using android::base::unique_fd;
@@ -453,6 +455,31 @@
selinux_set_callback(SELINUX_CB_LOG, cb);
}
+// This function checks whether the sepolicy supports vendor init.
+bool SelinuxHasVendorInit() {
+ if (!IsSplitPolicyDevice()) {
+ // If this device does not split sepolicy files, vendor_init will be available in the latest
+ // monolithic sepolicy file.
+ return true;
+ }
+
+ std::string version;
+ if (!GetVendorMappingVersion(&version)) {
+ // Return true as the default if we failed to load the vendor sepolicy version.
+ return true;
+ }
+
+ int major_version;
+ std::string major_version_str(version, 0, version.find('.'));
+ if (!ParseInt(major_version_str, &major_version)) {
+ PLOG(ERROR) << "Failed to parse the vendor sepolicy major version " << major_version_str;
+ // Return true as the default if we failed to parse the major version.
+ return true;
+ }
+
+ return major_version >= 28;
+}
+
// selinux_android_file_context_handle() takes on the order of 10+ms to run, so we want to cache
// its value. selinux_android_restorecon() also needs an sehandle for file context look up. It
// will create and store its own copy, but selinux_android_set_sehandle() can be used to provide
diff --git a/init/selinux.h b/init/selinux.h
index 7b880ec..30069b5 100644
--- a/init/selinux.h
+++ b/init/selinux.h
@@ -27,6 +27,7 @@
void SelinuxRestoreContext();
void SelinuxSetupKernelLogging();
+bool SelinuxHasVendorInit();
void SelabelInitialize();
bool SelabelLookupFileContext(const std::string& key, int type, std::string* result);
diff --git a/init/service.h b/init/service.h
index cf38f69..9cb35b8 100644
--- a/init/service.h
+++ b/init/service.h
@@ -244,6 +244,16 @@
return nullptr;
}
+ Service* FindInterface(const std::string& interface_name) {
+ for (const auto& svc : services_) {
+ if (svc->interfaces().count(interface_name) > 0) {
+ return svc.get();
+ }
+ }
+
+ return nullptr;
+ }
+
void DumpState() const;
auto begin() const { return services_.begin(); }
diff --git a/init/subcontext.cpp b/init/subcontext.cpp
index 9c0c0bb..fdb4641 100644
--- a/init/subcontext.cpp
+++ b/init/subcontext.cpp
@@ -357,7 +357,7 @@
static std::vector<Subcontext> subcontexts;
std::vector<Subcontext>* InitializeSubcontexts() {
- if (GetIntProperty("ro.vndk.version", 28) >= 28) {
+ if (SelinuxHasVendorInit()) {
for (const auto& [path_prefix, secontext] : paths_and_secontexts) {
subcontexts.emplace_back(path_prefix, secontext);
}
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index dd46750..e823257 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -160,6 +160,15 @@
misc_undefined: ["integer"],
},
},
+
+ vendor: {
+ exclude_srcs: [
+ // qtaguid.cpp loads libnetd_client.so with dlopen(). Since
+ // the interface of libnetd_client.so may vary between AOSP
+ // releases, exclude qtaguid.cpp from the VNDK-SP variant.
+ "qtaguid.cpp",
+ ],
+ }
},
shared_libs: ["liblog"],
diff --git a/libcutils/ashmem-host.cpp b/libcutils/ashmem-host.cpp
index b2bec99..bb990d5 100644
--- a/libcutils/ashmem-host.cpp
+++ b/libcutils/ashmem-host.cpp
@@ -24,7 +24,6 @@
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
-#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/libcutils/canned_fs_config.cpp b/libcutils/canned_fs_config.cpp
index 6b5763b..2772ef0 100644
--- a/libcutils/canned_fs_config.cpp
+++ b/libcutils/canned_fs_config.cpp
@@ -21,7 +21,6 @@
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
-#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/libcutils/hashmap.cpp b/libcutils/hashmap.cpp
index 65b6ab1..10e3b25 100644
--- a/libcutils/hashmap.cpp
+++ b/libcutils/hashmap.cpp
@@ -21,7 +21,6 @@
#include <cutils/threads.h>
#include <stdlib.h>
#include <string.h>
-#include <stdbool.h>
#include <sys/types.h>
typedef struct Entry Entry;
diff --git a/libcutils/trace-dev.inc b/libcutils/trace-dev.inc
index f95c6c5..c9580af 100644
--- a/libcutils/trace-dev.inc
+++ b/libcutils/trace-dev.inc
@@ -24,7 +24,6 @@
#include <limits.h>
#include <pthread.h>
#include <stdatomic.h>
-#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
diff --git a/libmetricslogger/Android.bp b/libmetricslogger/Android.bp
index 6549b8d..e6e17ce 100644
--- a/libmetricslogger/Android.bp
+++ b/libmetricslogger/Android.bp
@@ -29,6 +29,13 @@
defaults: ["metricslogger_defaults"],
}
+// static version of libmetricslogger, needed by a few art static binaries
+cc_library_static {
+ name: "libmetricslogger_static",
+ srcs: metricslogger_lib_src_files,
+ defaults: ["metricslogger_defaults"],
+}
+
// metricslogger shared library, debug
// -----------------------------------------------------------------------------
cc_library_shared {
diff --git a/libmetricslogger/include/metricslogger/metrics_logger.h b/libmetricslogger/include/metricslogger/metrics_logger.h
index 189bc4b..2c76869 100644
--- a/libmetricslogger/include/metricslogger/metrics_logger.h
+++ b/libmetricslogger/include/metricslogger/metrics_logger.h
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <log/log_event_list.h>
#include <cstdint>
#include <string>
@@ -32,6 +33,34 @@
// |value| in the field |field|.
void LogMultiAction(int32_t category, int32_t field, const std::string& value);
+// Logs a Tron complex event.
+//
+// A complex event can include data in a structure not suppored by the other
+// log event types above.
+//
+// Note that instances of this class are single use. You must call Record()
+// to write the event to the event log.
+class ComplexEventLogger {
+ private:
+ android_log_event_list logger;
+
+ public:
+ // Create a complex event with category|category|.
+ explicit ComplexEventLogger(int category);
+ // Add tagged data to the event, with the given tag and integer value.
+ void AddTaggedData(int tag, int32_t value);
+ // Add tagged data to the event, with the given tag and string value.
+ void AddTaggedData(int tag, const std::string& value);
+ // Add tagged data to the event, with the given tag and integer value.
+ void AddTaggedData(int tag, int64_t value);
+ // Add tagged data to the event, with the given tag and float value.
+ void AddTaggedData(int tag, float value);
+ // Record this event. This method can only be used once per instance
+ // of ComplexEventLogger. Do not made any subsequent calls to AddTaggedData
+ // after recording an event.
+ void Record();
+};
+
// TODO: replace these with the metric_logger.proto definitions
enum {
LOGBUILDER_CATEGORY = 757,
@@ -44,11 +73,23 @@
ACTION_BOOT = 1098,
FIELD_PLATFORM_REASON = 1099,
+
+ ACTION_HIDDEN_API_ACCESSED = 1391,
+ FIELD_HIDDEN_API_ACCESS_METHOD = 1392,
+ FIELD_HIDDEN_API_ACCESS_DENIED = 1393,
+ FIELD_HIDDEN_API_SIGNATURE = 1394,
};
enum {
TYPE_ACTION = 4,
};
+enum {
+ ACCESS_METHOD_NONE = 0,
+ ACCESS_METHOD_REFLECTION = 1,
+ ACCESS_METHOD_JNI = 2,
+ ACCESS_METHOD_LINKING = 3,
+};
+
} // namespace metricslogger
} // namespace android
diff --git a/libmetricslogger/metrics_logger.cpp b/libmetricslogger/metrics_logger.cpp
index fdc4407..912fa12 100644
--- a/libmetricslogger/metrics_logger.cpp
+++ b/libmetricslogger/metrics_logger.cpp
@@ -23,9 +23,14 @@
namespace {
+#ifdef __ANDROID__
EventTagMap* kEventTagMap = android_openEventTagMap(nullptr);
const int kSysuiMultiActionTag = android_lookupEventTagNum(
kEventTagMap, "sysui_multi_action", "(content|4)", ANDROID_LOG_UNKNOWN);
+#else
+// android_openEventTagMap does not work on host builds.
+const int kSysuiMultiActionTag = 0;
+#endif
} // namespace
@@ -53,5 +58,29 @@
<< field << value << LOG_ID_EVENTS;
}
+ComplexEventLogger::ComplexEventLogger(int category) : logger(kSysuiMultiActionTag) {
+ logger << LOGBUILDER_CATEGORY << category;
+}
+
+void ComplexEventLogger::AddTaggedData(int tag, int32_t value) {
+ logger << tag << value;
+}
+
+void ComplexEventLogger::AddTaggedData(int tag, const std::string& value) {
+ logger << tag << value;
+}
+
+void ComplexEventLogger::AddTaggedData(int tag, int64_t value) {
+ logger << tag << value;
+}
+
+void ComplexEventLogger::AddTaggedData(int tag, float value) {
+ logger << tag << value;
+}
+
+void ComplexEventLogger::Record() {
+ logger << LOG_ID_EVENTS;
+}
+
} // namespace metricslogger
} // namespace android
diff --git a/logcat/event.logtags b/logcat/event.logtags
index 7c40a77..750761f 100644
--- a/logcat/event.logtags
+++ b/logcat/event.logtags
@@ -67,8 +67,9 @@
# ZygoteInit class preloading ends:
3030 boot_progress_preload_end (time|2|3)
-# Dalvik VM
+# Dalvik VM / ART
20003 dvm_lock_sample (process|3),(main|1|5),(thread|3),(time|1|3),(file|3),(line|1|5),(ownerfile|3),(ownerline|1|5),(sample_percent|1|6)
+20004 art_hidden_api_access (access_method|1),(flags|1),(class|3),(member|3),(type_signature|3)
75000 sqlite_mem_alarm_current (current|1|2)
75001 sqlite_mem_alarm_max (max|1|2)
diff --git a/logd/main.cpp b/logd/main.cpp
index 4af0d21..606aa63 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -33,7 +33,6 @@
#include <syslog.h>
#include <unistd.h>
-#include <cstdbool>
#include <memory>
#include <android-base/macros.h>