Merge "Remove unneeded vendor_available"
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index eb6870e..96875d5 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -20,6 +20,7 @@
"execv_helper.cpp",
"globals.cpp",
"run_dex2oat.cpp",
+ "unique_file.cpp",
"utils.cpp",
"utils_default.cpp",
"view_compiler.cpp",
@@ -112,6 +113,7 @@
srcs: [
"run_dex2oat_test.cpp",
"run_dex2oat.cpp",
+ "unique_file.cpp",
"execv_helper.cpp",
],
cflags: ["-Wall", "-Werror"],
@@ -119,9 +121,6 @@
"libbase",
"server_configurable_flags",
],
- static_libs: [
- //"libinstalld",
- ],
test_config: "run_dex2oat_test.xml",
}
@@ -232,6 +231,7 @@
"otapreopt.cpp",
"otapreopt_utils.cpp",
"run_dex2oat.cpp",
+ "unique_file.cpp",
"utils.cpp",
"utils_default.cpp",
"view_compiler.cpp",
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 82ea746..5076ae6 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -54,6 +54,7 @@
#include "installd_deps.h"
#include "otapreopt_utils.h"
#include "run_dex2oat.h"
+#include "unique_file.h"
#include "utils.h"
using android::base::Basename;
@@ -230,6 +231,12 @@
return profile_boot_class_path == "true";
}
+static void UnlinkIgnoreResult(const std::string& path) {
+ if (unlink(path.c_str()) < 0) {
+ PLOG(ERROR) << "Failed to unlink " << path;
+ }
+}
+
/*
* Whether dexopt should use a swap file when compiling an APK.
*
@@ -346,6 +353,16 @@
return open_profile(uid, profile, read_write ? (O_CREAT | O_RDWR) : O_RDONLY);
}
+static UniqueFile open_reference_profile_as_unique_file(uid_t uid, const std::string& package_name,
+ const std::string& location, bool read_write, bool is_secondary_dex) {
+ std::string profile_path = create_reference_profile_path(package_name, location,
+ is_secondary_dex);
+ unique_fd ufd = open_profile(uid, profile_path, read_write ? (O_CREAT | O_RDWR) : O_RDONLY);
+ return UniqueFile(ufd.release(), profile_path, [](const std::string& path) {
+ clear_profile(path);
+ });
+}
+
static unique_fd open_spnashot_profile(uid_t uid, const std::string& package_name,
const std::string& location) {
std::string profile = create_snapshot_profile_path(package_name, location);
@@ -836,118 +853,14 @@
return true;
}
-// Helper for fd management. This is similar to a unique_fd in that it closes the file descriptor
-// on destruction. It will also run the given cleanup (unless told not to) after closing.
-//
-// Usage example:
-//
-// Dex2oatFileWrapper file(open(...),
-// [name]() {
-// unlink(name.c_str());
-// });
-// // Note: care needs to be taken about name, as it needs to have a lifetime longer than the
-// wrapper if captured as a reference.
-//
-// if (file.get() == -1) {
-// // Error opening...
-// }
-//
-// ...
-// if (error) {
-// // At this point, when the Dex2oatFileWrapper is destructed, the cleanup function will run
-// // and delete the file (after the fd is closed).
-// return -1;
-// }
-//
-// (Success case)
-// file.SetCleanup(false);
-// // At this point, when the Dex2oatFileWrapper is destructed, the cleanup function will not run
-// // (leaving the file around; after the fd is closed).
-//
-class Dex2oatFileWrapper {
- public:
- Dex2oatFileWrapper() : value_(-1), cleanup_(), do_cleanup_(true), auto_close_(true) {
- }
-
- Dex2oatFileWrapper(int value, std::function<void ()> cleanup)
- : value_(value), cleanup_(cleanup), do_cleanup_(true), auto_close_(true) {}
-
- Dex2oatFileWrapper(Dex2oatFileWrapper&& other) {
- value_ = other.value_;
- cleanup_ = other.cleanup_;
- do_cleanup_ = other.do_cleanup_;
- auto_close_ = other.auto_close_;
- other.release();
- }
-
- Dex2oatFileWrapper& operator=(Dex2oatFileWrapper&& other) {
- value_ = other.value_;
- cleanup_ = other.cleanup_;
- do_cleanup_ = other.do_cleanup_;
- auto_close_ = other.auto_close_;
- other.release();
- return *this;
- }
-
- ~Dex2oatFileWrapper() {
- reset(-1);
- }
-
- int get() {
- return value_;
- }
-
- void SetCleanup(bool cleanup) {
- do_cleanup_ = cleanup;
- }
-
- void reset(int new_value) {
- if (auto_close_ && value_ >= 0) {
- close(value_);
- }
- if (do_cleanup_ && cleanup_ != nullptr) {
- cleanup_();
- }
-
- value_ = new_value;
- }
-
- void reset(int new_value, std::function<void ()> new_cleanup) {
- if (auto_close_ && value_ >= 0) {
- close(value_);
- }
- if (do_cleanup_ && cleanup_ != nullptr) {
- cleanup_();
- }
-
- value_ = new_value;
- cleanup_ = new_cleanup;
- }
-
- void DisableAutoClose() {
- auto_close_ = false;
- }
-
- private:
- void release() {
- value_ = -1;
- do_cleanup_ = false;
- cleanup_ = nullptr;
- }
- int value_;
- std::function<void ()> cleanup_;
- bool do_cleanup_;
- bool auto_close_;
-};
-
// (re)Creates the app image if needed.
-Dex2oatFileWrapper maybe_open_app_image(const char* out_oat_path,
+UniqueFile maybe_open_app_image(const std::string& out_oat_path,
bool generate_app_image, bool is_public, int uid, bool is_secondary_dex) {
const std::string image_path = create_image_filename(out_oat_path);
if (image_path.empty()) {
// Happens when the out_oat_path has an unknown extension.
- return Dex2oatFileWrapper();
+ return UniqueFile();
}
// In case there is a stale image, remove it now. Ignore any error.
@@ -955,18 +868,19 @@
// Not enabled, exit.
if (!generate_app_image) {
- return Dex2oatFileWrapper();
+ return UniqueFile();
}
std::string app_image_format = GetProperty("dalvik.vm.appimageformat", "");
if (app_image_format.empty()) {
- return Dex2oatFileWrapper();
+ return UniqueFile();
}
// Recreate is true since we do not want to modify a mapped image. If the app is
// already running and we modify the image file, it can cause crashes (b/27493510).
- Dex2oatFileWrapper wrapper_fd(
+ UniqueFile image_file(
open_output_file(image_path.c_str(), true /*recreate*/, 0600 /*permissions*/),
- [image_path]() { unlink(image_path.c_str()); });
- if (wrapper_fd.get() < 0) {
+ image_path,
+ UnlinkIgnoreResult);
+ if (image_file.fd() < 0) {
// Could not create application image file. Go on since we can compile without it.
LOG(ERROR) << "installd could not create '" << image_path
<< "' for image file during dexopt";
@@ -977,21 +891,21 @@
}
}
} else if (!set_permissions_and_ownership(
- wrapper_fd.get(), is_public, uid, image_path.c_str(), is_secondary_dex)) {
+ image_file.fd(), is_public, uid, image_path.c_str(), is_secondary_dex)) {
ALOGE("installd cannot set owner '%s' for image during dexopt\n", image_path.c_str());
- wrapper_fd.reset(-1);
+ image_file.reset();
}
- return wrapper_fd;
+ return image_file;
}
// Creates the dexopt swap file if necessary and return its fd.
// Returns -1 if there's no need for a swap or in case of errors.
-unique_fd maybe_open_dexopt_swap_file(const char* out_oat_path) {
+unique_fd maybe_open_dexopt_swap_file(const std::string& out_oat_path) {
if (!ShouldUseSwapFileForDexopt()) {
return invalid_unique_fd();
}
- auto swap_file_name = std::string(out_oat_path) + ".swap";
+ auto swap_file_name = out_oat_path + ".swap";
unique_fd swap_fd(open_output_file(
swap_file_name.c_str(), /*recreate*/true, /*permissions*/0600));
if (swap_fd.get() < 0) {
@@ -1009,13 +923,13 @@
// Opens the reference profiles if needed.
// Note that the reference profile might not exist so it's OK if the fd will be -1.
-Dex2oatFileWrapper maybe_open_reference_profile(const std::string& pkgname,
+UniqueFile maybe_open_reference_profile(const std::string& pkgname,
const std::string& dex_path, const char* profile_name, bool profile_guided,
bool is_public, int uid, bool is_secondary_dex) {
// If we are not profile guided compilation, or we are compiling system server
// do not bother to open the profiles; we won't be using them.
if (!profile_guided || (pkgname[0] == '*')) {
- return Dex2oatFileWrapper();
+ return UniqueFile();
}
// If this is a secondary dex path which is public do not open the profile.
@@ -1027,7 +941,7 @@
// compiling with a public profile from the .dm file the PackageManager will
// set is_public toghether with the profile guided compilation.
if (is_secondary_dex && is_public) {
- return Dex2oatFileWrapper();
+ return UniqueFile();
}
// Open reference profile in read only mode as dex2oat does not get write permissions.
@@ -1037,33 +951,28 @@
} else {
if (profile_name == nullptr) {
// This path is taken for system server re-compilation lunched from ZygoteInit.
- return Dex2oatFileWrapper();
+ return UniqueFile();
} else {
location = profile_name;
}
}
- unique_fd ufd = open_reference_profile(uid, pkgname, location, /*read_write*/false,
- is_secondary_dex);
- const auto& cleanup = [pkgname, location, is_secondary_dex]() {
- clear_reference_profile(pkgname, location, is_secondary_dex);
- };
- return Dex2oatFileWrapper(ufd.release(), cleanup);
+ return open_reference_profile_as_unique_file(uid, pkgname, location, /*read_write*/false,
+ is_secondary_dex);
}
-// Opens the vdex files and assigns the input fd to in_vdex_wrapper_fd and the output fd to
-// out_vdex_wrapper_fd. Returns true for success or false in case of errors.
+// Opens the vdex files and assigns the input fd to in_vdex_wrapper and the output fd to
+// out_vdex_wrapper. Returns true for success or false in case of errors.
bool open_vdex_files_for_dex2oat(const char* apk_path, const char* out_oat_path, int dexopt_needed,
const char* instruction_set, bool is_public, int uid, bool is_secondary_dex,
- bool profile_guided, Dex2oatFileWrapper* in_vdex_wrapper_fd,
- Dex2oatFileWrapper* out_vdex_wrapper_fd) {
- CHECK(in_vdex_wrapper_fd != nullptr);
- CHECK(out_vdex_wrapper_fd != nullptr);
+ bool profile_guided, UniqueFile* in_vdex_wrapper,
+ UniqueFile* out_vdex_wrapper) {
+ CHECK(in_vdex_wrapper != nullptr);
+ CHECK(out_vdex_wrapper != nullptr);
// Open the existing VDEX. We do this before creating the new output VDEX, which will
// unlink the old one.
char in_odex_path[PKG_PATH_MAX];
int dexopt_action = abs(dexopt_needed);
bool is_odex_location = dexopt_needed < 0;
- std::string in_vdex_path_str;
// Infer the name of the output VDEX.
const std::string out_vdex_path_str = create_vdex_filename(out_oat_path);
@@ -1085,7 +994,7 @@
} else {
path = out_oat_path;
}
- in_vdex_path_str = create_vdex_filename(path);
+ std::string in_vdex_path_str = create_vdex_filename(path);
if (in_vdex_path_str.empty()) {
ALOGE("installd cannot compute input vdex location for '%s'\n", path);
return false;
@@ -1103,13 +1012,15 @@
!profile_guided;
if (update_vdex_in_place) {
// Open the file read-write to be able to update it.
- in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDWR, 0));
- if (in_vdex_wrapper_fd->get() == -1) {
+ in_vdex_wrapper->reset(open(in_vdex_path_str.c_str(), O_RDWR, 0),
+ in_vdex_path_str);
+ if (in_vdex_wrapper->fd() == -1) {
// If we failed to open the file, we cannot update it in place.
update_vdex_in_place = false;
}
} else {
- in_vdex_wrapper_fd->reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0));
+ in_vdex_wrapper->reset(open(in_vdex_path_str.c_str(), O_RDONLY, 0),
+ in_vdex_path_str);
}
}
@@ -1118,22 +1029,24 @@
if (update_vdex_in_place) {
// We unlink the file in case the invocation of dex2oat fails, to ensure we don't
// have bogus stale vdex files.
- out_vdex_wrapper_fd->reset(
- in_vdex_wrapper_fd->get(),
- [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
+ out_vdex_wrapper->reset(
+ in_vdex_wrapper->fd(),
+ out_vdex_path_str,
+ UnlinkIgnoreResult);
// Disable auto close for the in wrapper fd (it will be done when destructing the out
// wrapper).
- in_vdex_wrapper_fd->DisableAutoClose();
+ in_vdex_wrapper->DisableAutoClose();
} else {
- out_vdex_wrapper_fd->reset(
+ out_vdex_wrapper->reset(
open_output_file(out_vdex_path_str.c_str(), /*recreate*/true, /*permissions*/0644),
- [out_vdex_path_str]() { unlink(out_vdex_path_str.c_str()); });
- if (out_vdex_wrapper_fd->get() < 0) {
+ out_vdex_path_str,
+ UnlinkIgnoreResult);
+ if (out_vdex_wrapper->fd() < 0) {
ALOGE("installd cannot open vdex'%s' during dexopt\n", out_vdex_path_str.c_str());
return false;
}
}
- if (!set_permissions_and_ownership(out_vdex_wrapper_fd->get(), is_public, uid,
+ if (!set_permissions_and_ownership(out_vdex_wrapper->fd(), is_public, uid,
out_vdex_path_str.c_str(), is_secondary_dex)) {
ALOGE("installd cannot set owner '%s' for vdex during dexopt\n", out_vdex_path_str.c_str());
return false;
@@ -1144,25 +1057,24 @@
}
// Opens the output oat file for the given apk.
-// If successful it stores the output path into out_oat_path and returns true.
-Dex2oatFileWrapper open_oat_out_file(const char* apk_path, const char* oat_dir,
- bool is_public, int uid, const char* instruction_set, bool is_secondary_dex,
- char* out_oat_path) {
+UniqueFile open_oat_out_file(const char* apk_path, const char* oat_dir,
+ bool is_public, int uid, const char* instruction_set, bool is_secondary_dex) {
+ char out_oat_path[PKG_PATH_MAX];
if (!create_oat_out_path(apk_path, instruction_set, oat_dir, is_secondary_dex, out_oat_path)) {
- return Dex2oatFileWrapper();
+ return UniqueFile();
}
- const std::string out_oat_path_str(out_oat_path);
- Dex2oatFileWrapper wrapper_fd(
+ UniqueFile oat(
open_output_file(out_oat_path, /*recreate*/true, /*permissions*/0644),
- [out_oat_path_str]() { unlink(out_oat_path_str.c_str()); });
- if (wrapper_fd.get() < 0) {
+ out_oat_path,
+ UnlinkIgnoreResult);
+ if (oat.fd() < 0) {
PLOG(ERROR) << "installd cannot open output during dexopt" << out_oat_path;
} else if (!set_permissions_and_ownership(
- wrapper_fd.get(), is_public, uid, out_oat_path, is_secondary_dex)) {
+ oat.fd(), is_public, uid, out_oat_path, is_secondary_dex)) {
ALOGE("installd cannot set owner '%s' for output during dexopt\n", out_oat_path);
- wrapper_fd.reset(-1);
+ oat.reset();
}
- return wrapper_fd;
+ return oat;
}
// Creates RDONLY fds for oat and vdex files, if exist.
@@ -1769,8 +1681,8 @@
}
// Open the input file.
- unique_fd input_fd(open(dex_path, O_RDONLY, 0));
- if (input_fd.get() < 0) {
+ UniqueFile in_dex(open(dex_path, O_RDONLY, 0), dex_path);
+ if (in_dex.fd() < 0) {
*error_msg = StringPrintf("installd cannot open '%s' for input during dexopt", dex_path);
LOG(ERROR) << *error_msg;
return -1;
@@ -1784,19 +1696,19 @@
}
// Create the output OAT file.
- char out_oat_path[PKG_PATH_MAX];
- Dex2oatFileWrapper out_oat_fd = open_oat_out_file(dex_path, oat_dir, is_public, uid,
- instruction_set, is_secondary_dex, out_oat_path);
- if (out_oat_fd.get() < 0) {
+ UniqueFile out_oat = open_oat_out_file(dex_path, oat_dir, is_public, uid,
+ instruction_set, is_secondary_dex);
+ if (out_oat.fd() < 0) {
*error_msg = "Could not open out oat file.";
return -1;
}
// Open vdex files.
- Dex2oatFileWrapper in_vdex_fd;
- Dex2oatFileWrapper out_vdex_fd;
- if (!open_vdex_files_for_dex2oat(dex_path, out_oat_path, dexopt_needed, instruction_set,
- is_public, uid, is_secondary_dex, profile_guided, &in_vdex_fd, &out_vdex_fd)) {
+ UniqueFile in_vdex;
+ UniqueFile out_vdex;
+ if (!open_vdex_files_for_dex2oat(dex_path, out_oat.path().c_str(), dexopt_needed,
+ instruction_set, is_public, uid, is_secondary_dex, profile_guided, &in_vdex,
+ &out_vdex)) {
*error_msg = "Could not open vdex files.";
return -1;
}
@@ -1816,26 +1728,27 @@
}
// Create a swap file if necessary.
- unique_fd swap_fd = maybe_open_dexopt_swap_file(out_oat_path);
+ unique_fd swap_fd = maybe_open_dexopt_swap_file(out_oat.path());
// Open the reference profile if needed.
- Dex2oatFileWrapper reference_profile_fd = maybe_open_reference_profile(
+ UniqueFile reference_profile = maybe_open_reference_profile(
pkgname, dex_path, profile_name, profile_guided, is_public, uid, is_secondary_dex);
- if (reference_profile_fd.get() == -1) {
+ if (reference_profile.fd() == -1) {
// We don't create an app image without reference profile since there is no speedup from
// loading it in that case and instead will be a small overhead.
generate_app_image = false;
}
// Create the app image file if needed.
- Dex2oatFileWrapper image_fd = maybe_open_app_image(
- out_oat_path, generate_app_image, is_public, uid, is_secondary_dex);
+ UniqueFile out_image = maybe_open_app_image(
+ out_oat.path(), generate_app_image, is_public, uid, is_secondary_dex);
- unique_fd dex_metadata_fd;
+ UniqueFile dex_metadata;
if (dex_metadata_path != nullptr) {
- dex_metadata_fd.reset(TEMP_FAILURE_RETRY(open(dex_metadata_path, O_RDONLY | O_NOFOLLOW)));
- if (dex_metadata_fd.get() < 0) {
+ dex_metadata.reset(TEMP_FAILURE_RETRY(open(dex_metadata_path, O_RDONLY | O_NOFOLLOW)),
+ dex_metadata_path);
+ if (dex_metadata.fd() < 0) {
PLOG(ERROR) << "Failed to open dex metadata file " << dex_metadata_path;
}
}
@@ -1862,26 +1775,24 @@
LOG(VERBOSE) << "DexInv: --- BEGIN '" << dex_path << "' ---";
RunDex2Oat runner(dex2oat_bin, execv_helper.get());
- runner.Initialize(input_fd.get(),
- out_oat_fd.get(),
- in_vdex_fd.get(),
- out_vdex_fd.get(),
- image_fd.get(),
- dex_path,
- out_oat_path,
+ runner.Initialize(out_oat,
+ out_vdex,
+ out_image,
+ in_dex,
+ in_vdex,
+ dex_metadata,
+ reference_profile,
+ class_loader_context,
+ join_fds(context_input_fds),
swap_fd.get(),
instruction_set,
compiler_filter,
debuggable,
boot_complete,
for_restore,
- reference_profile_fd.get(),
- class_loader_context,
- join_fds(context_input_fds),
target_sdk_version,
enable_hidden_api_checks,
generate_compact_dex,
- dex_metadata_fd.get(),
use_jitzygote_image,
compilation_reason);
@@ -1891,8 +1802,8 @@
drop_capabilities(uid);
SetDex2OatScheduling(boot_complete);
- if (flock(out_oat_fd.get(), LOCK_EX | LOCK_NB) != 0) {
- PLOG(ERROR) << "flock(" << out_oat_path << ") failed";
+ if (flock(out_oat.fd(), LOCK_EX | LOCK_NB) != 0) {
+ PLOG(ERROR) << "flock(" << out_oat.path() << ") failed";
_exit(DexoptReturnCodes::kFlock);
}
@@ -1909,13 +1820,13 @@
}
}
- update_out_oat_access_times(dex_path, out_oat_path);
+ update_out_oat_access_times(dex_path, out_oat.path().c_str());
// We've been successful, don't delete output.
- out_oat_fd.SetCleanup(false);
- out_vdex_fd.SetCleanup(false);
- image_fd.SetCleanup(false);
- reference_profile_fd.SetCleanup(false);
+ out_oat.DisableCleanup();
+ out_vdex.DisableCleanup();
+ out_image.DisableCleanup();
+ reference_profile.DisableCleanup();
return 0;
}
diff --git a/cmds/installd/run_dex2oat.cpp b/cmds/installd/run_dex2oat.cpp
index 1572e3b..17ea903 100644
--- a/cmds/installd/run_dex2oat.cpp
+++ b/cmds/installd/run_dex2oat.cpp
@@ -30,6 +30,8 @@
#include <log/log.h>
#include <server_configurable_flags/get_flags.h>
+#include "unique_file.h"
+
using android::base::Basename;
using android::base::StringPrintf;
@@ -64,35 +66,33 @@
RunDex2Oat::RunDex2Oat(const char* dex2oat_bin, ExecVHelper* execv_helper)
: dex2oat_bin_(dex2oat_bin), execv_helper_(execv_helper) {}
-void RunDex2Oat::Initialize(int zip_fd,
- int oat_fd,
- int input_vdex_fd,
- int output_vdex_fd,
- int image_fd,
- const char* input_file_name,
- const char* output_file_name,
+void RunDex2Oat::Initialize(const UniqueFile& output_oat,
+ const UniqueFile& output_vdex,
+ const UniqueFile& output_image,
+ const UniqueFile& input_dex,
+ const UniqueFile& input_vdex,
+ const UniqueFile& dex_metadata,
+ const UniqueFile& profile,
+ const char* class_loader_context,
+ const std::string& class_loader_context_fds,
int swap_fd,
const char* instruction_set,
const char* compiler_filter,
bool debuggable,
bool post_bootcomplete,
bool for_restore,
- int profile_fd,
- const char* class_loader_context,
- const std::string& class_loader_context_fds,
int target_sdk_version,
bool enable_hidden_api_checks,
bool generate_compact_dex,
- int dex_metadata_fd,
bool use_jitzygote_image,
const char* compilation_reason) {
PrepareBootImageAndBootClasspathFlags(use_jitzygote_image);
- PrepareInputFileFlags(zip_fd, oat_fd, input_vdex_fd, output_vdex_fd, image_fd, input_file_name,
- output_file_name, profile_fd, dex_metadata_fd, swap_fd,
- class_loader_context, class_loader_context_fds);
+ PrepareInputFileFlags(output_oat, output_vdex, output_image, input_dex, input_vdex,
+ dex_metadata, profile, swap_fd, class_loader_context,
+ class_loader_context_fds);
- PrepareCompilerConfigFlags(input_vdex_fd, output_vdex_fd, instruction_set, compiler_filter,
+ PrepareCompilerConfigFlags(input_vdex, output_vdex, instruction_set, compiler_filter,
debuggable, target_sdk_version, enable_hidden_api_checks,
generate_compact_dex, compilation_reason);
@@ -139,38 +139,36 @@
AddArg(updatable_bcp_packages);
}
-void RunDex2Oat::PrepareInputFileFlags(int zip_fd,
- int oat_fd,
- int input_vdex_fd,
- int output_vdex_fd,
- int image_fd,
- const char* input_file_name,
- const char* output_file_name,
- int profile_fd,
- int dex_metadata_fd,
+void RunDex2Oat::PrepareInputFileFlags(const UniqueFile& output_oat,
+ const UniqueFile& output_vdex,
+ const UniqueFile& output_image,
+ const UniqueFile& input_dex,
+ const UniqueFile& input_vdex,
+ const UniqueFile& dex_metadata,
+ const UniqueFile& profile,
int swap_fd,
const char* class_loader_context,
const std::string& class_loader_context_fds) {
- std::string input_basename = Basename(input_file_name);
- ALOGV("Running %s in=%s out=%s\n", dex2oat_bin_.c_str(), input_basename.c_str(),
- output_file_name);
+ std::string input_basename = Basename(input_dex.path());
+ LOG(VERBOSE) << "Running " << dex2oat_bin_ << " in=" << input_basename << " out="
+ << output_oat.path();
- AddArg(StringPrintf("--zip-fd=%d", zip_fd));
+ AddArg(StringPrintf("--zip-fd=%d", input_dex.fd()));
AddArg(StringPrintf("--zip-location=%s", input_basename.c_str()));
- AddArg(StringPrintf("--oat-fd=%d", oat_fd));
- AddArg(StringPrintf("--oat-location=%s", output_file_name));
- AddArg(StringPrintf("--input-vdex-fd=%d", input_vdex_fd));
- AddArg(StringPrintf("--output-vdex-fd=%d", output_vdex_fd));
+ AddArg(StringPrintf("--oat-fd=%d", output_oat.fd()));
+ AddArg(StringPrintf("--oat-location=%s", output_oat.path().c_str()));
+ AddArg(StringPrintf("--input-vdex-fd=%d", input_vdex.fd()));
+ AddArg(StringPrintf("--output-vdex-fd=%d", output_vdex.fd()));
- if (image_fd >= 0) {
- AddArg(StringPrintf("--app-image-fd=%d", image_fd));
+ if (output_image.fd() >= 0) {
+ AddArg(StringPrintf("--app-image-fd=%d", output_image.fd()));
AddArg(MapPropertyToArg("dalvik.vm.appimageformat", "--image-format=%s"));
}
- if (dex_metadata_fd > -1) {
- AddArg("--dm-fd=" + std::to_string(dex_metadata_fd));
+ if (dex_metadata.fd() > -1) {
+ AddArg("--dm-fd=" + std::to_string(dex_metadata.fd()));
}
- if (profile_fd != -1) {
- AddArg(StringPrintf("--profile-file-fd=%d", profile_fd));
+ if (profile.fd() != -1) {
+ AddArg(StringPrintf("--profile-file-fd=%d", profile.fd()));
}
if (swap_fd >= 0) {
AddArg(StringPrintf("--swap-fd=%d", swap_fd));
@@ -178,7 +176,7 @@
// Get the directory of the apk to pass as a base classpath directory.
{
- std::string apk_dir(input_file_name);
+ std::string apk_dir(input_dex.path());
size_t dir_index = apk_dir.rfind('/');
if (dir_index != std::string::npos) {
apk_dir = apk_dir.substr(0, dir_index);
@@ -195,8 +193,8 @@
}
}
-void RunDex2Oat::PrepareCompilerConfigFlags(int input_vdex_fd,
- int output_vdex_fd,
+void RunDex2Oat::PrepareCompilerConfigFlags(const UniqueFile& input_vdex,
+ const UniqueFile& output_vdex,
const char* instruction_set,
const char* compiler_filter,
bool debuggable,
@@ -206,11 +204,11 @@
const char* compilation_reason) {
// Disable cdex if update input vdex is true since this combination of options is not
// supported.
- const bool disable_cdex = !generate_compact_dex || (input_vdex_fd == output_vdex_fd);
+ const bool disable_cdex = !generate_compact_dex || (input_vdex.fd() == output_vdex.fd());
if (disable_cdex) {
AddArg(kDisableCompactDexFlag);
}
-
+
// ISA related
{
AddArg(StringPrintf("--instruction-set=%s", instruction_set));
diff --git a/cmds/installd/run_dex2oat.h b/cmds/installd/run_dex2oat.h
index 5453272..325a3a2 100644
--- a/cmds/installd/run_dex2oat.h
+++ b/cmds/installd/run_dex2oat.h
@@ -25,31 +25,31 @@
namespace android {
namespace installd {
+class UniqueFile;
+
class RunDex2Oat {
public:
explicit RunDex2Oat(const char* dex2oat_bin, ExecVHelper* execv_helper);
virtual ~RunDex2Oat();
- void Initialize(int zip_fd,
- int oat_fd,
- int input_vdex_fd,
- int output_vdex_fd,
- int image_fd,
- const char* input_file_name,
- const char* output_file_name,
+ void Initialize(const UniqueFile& output_oat,
+ const UniqueFile& output_vdex,
+ const UniqueFile& output_image,
+ const UniqueFile& input_dex,
+ const UniqueFile& input_vdex,
+ const UniqueFile& dex_metadata,
+ const UniqueFile& profile,
+ const char* class_loader_context,
+ const std::string& class_loader_context_fds,
int swap_fd,
const char* instruction_set,
const char* compiler_filter,
bool debuggable,
bool post_bootcomplete,
bool for_restore,
- int profile_fd,
- const char* class_loader_context,
- const std::string& class_loader_context_fds,
int target_sdk_version,
bool enable_hidden_api_checks,
bool generate_compact_dex,
- int dex_metadata_fd,
bool use_jitzygote_image,
const char* compilation_reason);
@@ -57,20 +57,18 @@
protected:
void PrepareBootImageAndBootClasspathFlags(bool use_jitzygote_image);
- void PrepareInputFileFlags(int zip_fd,
- int oat_fd,
- int input_vdex_fd,
- int output_vdex_fd,
- int image_fd,
- const char* input_file_name,
- const char* output_file_name,
- int profile_fd,
- int dex_metadata_fd,
+ void PrepareInputFileFlags(const UniqueFile& output_oat,
+ const UniqueFile& output_vdex,
+ const UniqueFile& output_image,
+ const UniqueFile& input_dex,
+ const UniqueFile& input_vdex,
+ const UniqueFile& dex_metadata,
+ const UniqueFile& profile,
int swap_fd,
const char* class_loader_context,
const std::string& class_loader_context_fds);
- void PrepareCompilerConfigFlags(int input_vdex_fd,
- int output_vdex_fd,
+ void PrepareCompilerConfigFlags(const UniqueFile& input_vdex,
+ const UniqueFile& output_vdex,
const char* instruction_set,
const char* compiler_filter,
bool debuggable,
diff --git a/cmds/installd/run_dex2oat_test.cpp b/cmds/installd/run_dex2oat_test.cpp
index b1f429d..3813cf7 100644
--- a/cmds/installd/run_dex2oat_test.cpp
+++ b/cmds/installd/run_dex2oat_test.cpp
@@ -24,6 +24,7 @@
#include "execv_helper.h"
#include "run_dex2oat.h"
+#include "unique_file.h"
namespace android {
namespace installd {
@@ -34,14 +35,16 @@
static constexpr const char* OUTPUT_PATH = "/dir/output/basename.oat";
static constexpr const char* FLAG_UNUSED = "{{FLAG_UNUSED}}";
- static constexpr int ZIP_FD = 1;
- static constexpr int OAT_FD = 2;
- static constexpr int INPUT_VDEX_FD = 3;
- static constexpr int OUTPUT_VDEX_FD = 4;
- static constexpr int IMAGE_FD = 5;
- static constexpr int PROFILE_FD = 6;
- static constexpr int DEX_METADATA_FD = 7;
- static constexpr int SWAP_FD = 8;
+ // UniqueFile closes FD. Avoid using standard I/O since the test is expected to print gtest
+ // results. Alternatively, mock out UniqueFile to avoid the side effect of close(2).
+ static constexpr int ZIP_FD = 3;
+ static constexpr int OAT_FD = 4;
+ static constexpr int INPUT_VDEX_FD = 5;
+ static constexpr int OUTPUT_VDEX_FD = 6;
+ static constexpr int IMAGE_FD = 7;
+ static constexpr int PROFILE_FD = 8;
+ static constexpr int DEX_METADATA_FD = 9;
+ static constexpr int SWAP_FD = 10;
using FakeSystemProperties = std::map<std::string, std::string>;
@@ -84,37 +87,33 @@
struct RunDex2OatArgs {
static std::unique_ptr<RunDex2OatArgs> MakeDefaultTestArgs() {
auto args = std::make_unique<RunDex2OatArgs>();
- args->input_file_name = INPUT_PATH;
- args->zip_fd = ZIP_FD;
- args->output_file_name = OUTPUT_PATH;
- args->oat_fd = OAT_FD;
- args->input_vdex_fd = INPUT_VDEX_FD;
- args->output_vdex_fd = OUTPUT_VDEX_FD;
+ args->input_dex.reset(ZIP_FD, INPUT_PATH);
+ args->output_oat.reset(OAT_FD, OUTPUT_PATH);
+ args->input_vdex.reset(INPUT_VDEX_FD, "UNUSED_PATH");
+ args->output_vdex.reset(OUTPUT_VDEX_FD, "UNUSED_PATH");
args->instruction_set = "arm64";
args->compilation_reason = "rundex2oattest";
return args;
}
- int zip_fd = -1;
- int oat_fd = -1;
- int input_vdex_fd = -1;
- int output_vdex_fd = -1;
- int image_fd = -1;
- const char* input_file_name = nullptr;
- const char* output_file_name = nullptr;
+ UniqueFile output_oat;
+ UniqueFile output_vdex;
+ UniqueFile output_image;
+ UniqueFile input_dex;
+ UniqueFile input_vdex;
+ UniqueFile dex_metadata;
+ UniqueFile profile;
int swap_fd = -1;
const char* instruction_set = nullptr;
const char* compiler_filter = "extract";
bool debuggable = false;
bool post_bootcomplete = false;
bool for_restore = false;
- int profile_fd = -1;
const char* class_loader_context = nullptr;
std::string class_loader_context_fds;
int target_sdk_version = 0;
bool enable_hidden_api_checks = false;
bool generate_compact_dex = true;
- int dex_metadata_fd = -1;
bool use_jitzygote_image = false;
const char* compilation_reason = nullptr;
};
@@ -143,7 +142,7 @@
cmd += arg;
cmd += " ";
}
- LOG(DEBUG) << "FakeExecVHelper exit_code: " << exit_code << " cmd: " << cmd;
+ LOG(DEBUG) << "FakeExecVHelper exit_code: " << exit_code << " cmd: " << cmd << "\n";
}
};
@@ -230,7 +229,7 @@
<< "Flag " << flag << " should be specified without value, but got " << value;
} else {
EXPECT_TRUE(execv_helper_->HasArg(flag + value))
- << "Flag " << flag << "=" << value << " is not specificed";
+ << "Flag " << flag << value << " is not specificed";
}
}
}
@@ -241,26 +240,24 @@
void CallRunDex2Oat(std::unique_ptr<RunDex2OatArgs> args) {
FakeRunDex2Oat runner(execv_helper_.get(), &system_properties_);
- runner.Initialize(args->zip_fd,
- args->oat_fd,
- args->input_vdex_fd,
- args->output_vdex_fd,
- args->image_fd,
- args->input_file_name,
- args->output_file_name,
+ runner.Initialize(args->output_oat,
+ args->output_vdex,
+ args->output_image,
+ args->input_dex,
+ args->input_vdex,
+ args->dex_metadata,
+ args->profile,
+ args->class_loader_context,
+ args->class_loader_context_fds,
args->swap_fd,
args->instruction_set,
args->compiler_filter,
args->debuggable,
args->post_bootcomplete,
args->for_restore,
- args->profile_fd,
- args->class_loader_context,
- args->class_loader_context_fds,
args->target_sdk_version,
args->enable_hidden_api_checks,
args->generate_compact_dex,
- args->dex_metadata_fd,
args->use_jitzygote_image,
args->compilation_reason);
runner.Exec(/*exit_code=*/ 0);
@@ -281,8 +278,8 @@
TEST_F(RunDex2OatTest, WithAllOtherInputFds) {
auto args = RunDex2OatArgs::MakeDefaultTestArgs();
- args->image_fd = IMAGE_FD;
- args->profile_fd = PROFILE_FD;
+ args->output_image.reset(IMAGE_FD, "UNUSED_PATH");
+ args->profile.reset(PROFILE_FD, "UNUSED_PATH");
args->swap_fd = SWAP_FD;
CallRunDex2Oat(std::move(args));
@@ -357,8 +354,8 @@
TEST_F(RunDex2OatTest, DoNotGenerateCompactDexWithVdexInPlaceUpdate) {
auto args = RunDex2OatArgs::MakeDefaultTestArgs();
args->generate_compact_dex = true;
- args->input_vdex_fd = INPUT_VDEX_FD;
- args->output_vdex_fd = INPUT_VDEX_FD;
+ args->input_vdex.reset(INPUT_VDEX_FD, "UNUSED_PATH");
+ args->output_vdex.reset(INPUT_VDEX_FD, "UNUSED_PATH");
CallRunDex2Oat(std::move(args));
SetExpectedFlagUsed("--compact-dex-level", "=none");
diff --git a/cmds/installd/unique_file.cpp b/cmds/installd/unique_file.cpp
new file mode 100644
index 0000000..e99ce1e
--- /dev/null
+++ b/cmds/installd/unique_file.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2020 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 "unique_file.h"
+
+#include <string>
+
+#include <unistd.h>
+
+#include <android-base/logging.h>
+
+namespace android {
+namespace installd {
+
+UniqueFile::UniqueFile() : UniqueFile(-1, "") {}
+
+UniqueFile::UniqueFile(int value, std::string path) : UniqueFile(value, path, nullptr) {}
+
+UniqueFile::UniqueFile(int value, std::string path, CleanUpFunction cleanup)
+ : value_(value), path_(path), cleanup_(cleanup), do_cleanup_(true), auto_close_(true) {}
+
+UniqueFile::UniqueFile(UniqueFile&& other) {
+ *this = std::move(other);
+}
+
+UniqueFile::~UniqueFile() {
+ reset();
+}
+
+UniqueFile& UniqueFile::operator=(UniqueFile&& other) {
+ value_ = other.value_;
+ path_ = other.path_;
+ cleanup_ = other.cleanup_;
+ do_cleanup_ = other.do_cleanup_;
+ auto_close_ = other.auto_close_;
+ other.release();
+ return *this;
+}
+
+void UniqueFile::reset() {
+ reset(-1, "");
+}
+
+void UniqueFile::reset(int new_value, std::string path, CleanUpFunction new_cleanup) {
+ if (auto_close_ && value_ >= 0) {
+ if (close(value_) < 0) {
+ PLOG(ERROR) << "Failed to close fd " << value_ << ", with path " << path;
+ }
+ }
+ if (do_cleanup_ && cleanup_ != nullptr) {
+ cleanup_(path_);
+ }
+
+ value_ = new_value;
+ path_ = path;
+ cleanup_ = new_cleanup;
+}
+
+void UniqueFile::release() {
+ value_ = -1;
+ path_ = "";
+ do_cleanup_ = false;
+ cleanup_ = nullptr;
+}
+
+} // namespace installd
+} // namespace android
diff --git a/cmds/installd/unique_file.h b/cmds/installd/unique_file.h
new file mode 100644
index 0000000..e85e23b
--- /dev/null
+++ b/cmds/installd/unique_file.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2020 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 ANDROID_INSTALLD_UNIQUE_FILE_H
+#define ANDROID_INSTALLD_UNIQUE_FILE_H
+
+#include <functional>
+#include <string>
+
+namespace android {
+namespace installd {
+
+// A file management helper that serves two purposes:
+//
+// 1. Closes the file description on destruction, similar unique_fd.
+// 2. Runs a cleanup function on after close, if not cancelled.
+//
+// The class does not assume the relationship between the given fd and file path.
+//
+// Example:
+//
+// UniqueFile file(open(...),
+// filepath,
+// [](const std::string& path) {
+// unlink(path.c_str());
+// });
+// if (file.fd() == -1) {
+// // Error opening...
+// }
+//
+// ...
+// if (error) {
+// // At this point, when the UniqueFile is destructed, the cleanup function will run
+// // (e.g. to delete the file) after the fd is closed.
+// return -1;
+// }
+//
+// (Success case)
+// file.DisableCleanup();
+// // At this point, when the UniqueFile is destructed, the cleanup function will not run
+// // (e.g. leaving the file around) after the fd is closed.
+//
+class UniqueFile {
+ private:
+ using CleanUpFunction = std::function<void (const std::string&)>;
+
+ public:
+ UniqueFile();
+ UniqueFile(int value, std::string path);
+ UniqueFile(int value, std::string path, CleanUpFunction cleanup);
+ UniqueFile(UniqueFile&& other);
+ ~UniqueFile();
+
+ UniqueFile& operator=(UniqueFile&& other);
+
+ int fd() const {
+ return value_;
+ }
+
+ const std::string& path() const {
+ return path_;
+ }
+
+ void DisableAutoClose() {
+ auto_close_ = false;
+ }
+
+ void DisableCleanup() {
+ do_cleanup_ = false;
+ }
+
+ void reset();
+ void reset(int new_value, std::string path, CleanUpFunction new_cleanup = nullptr);
+
+ private:
+ void release();
+
+ int value_;
+ std::string path_;
+ CleanUpFunction cleanup_;
+ bool do_cleanup_;
+ bool auto_close_;
+};
+
+} // namespace installd
+} // namespace android
+
+#endif // ANDROID_INSTALLD_UNIQUE_FILE_H
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index 7277e85..b139251 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -44,6 +44,9 @@
cflags: [
"-DVENDORSERVICEMANAGER=1",
],
+ required: [
+ "vndservice",
+ ],
srcs: ["main.cpp"],
}
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 861b589..9675a53 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -78,7 +78,7 @@
// or dessert updates. Instead, apex users should use libbinder_ndk.
apex_available: [
"//apex_available:platform",
- // TODO(b/139016109) remove these three
+ // TODO(b/166468760) remove these three
"com.android.media.swcodec",
"test_com.android.media.swcodec",
],
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index acc1e67..53cbb1a 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -404,7 +404,7 @@
, mCallRestriction(CallRestriction::NONE)
{
-// TODO(b/139016109): enforce in build system
+// TODO(b/166468760): enforce in build system
#if defined(__ANDROID_APEX__)
LOG_ALWAYS_FATAL("Cannot use libbinder in APEX (only system.img libbinder) since it is not stable.");
#endif
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index c63c179..4960779 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -481,6 +481,10 @@
return count;
}
+void InputDevice::updateLedState(bool reset) {
+ for_each_mapper([reset](InputMapper& mapper) { mapper.updateLedState(reset); });
+}
+
InputDeviceContext::InputDeviceContext(InputDevice& device, int32_t eventHubId)
: mDevice(device),
mContext(device.getContext()),
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index bb1ccbf..feaacb3 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -47,6 +47,7 @@
mEventHub(eventHub),
mPolicy(policy),
mGlobalMetaState(0),
+ mLedMetaState(AMETA_NUM_LOCK_ON),
mGeneration(1),
mNextInputDeviceId(END_RESERVED_ID),
mDisableVirtualKeysTimeout(LLONG_MIN),
@@ -353,6 +354,18 @@
return mGlobalMetaState;
}
+void InputReader::updateLedMetaStateLocked(int32_t metaState) {
+ mLedMetaState = metaState;
+ for (auto& devicePair : mDevices) {
+ std::shared_ptr<InputDevice>& device = devicePair.second;
+ device->updateLedState(false);
+ }
+}
+
+int32_t InputReader::getLedMetaStateLocked() {
+ return mLedMetaState;
+}
+
void InputReader::notifyExternalStylusPresenceChanged() {
refreshConfigurationLocked(InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE);
}
@@ -710,6 +723,16 @@
return mReader->getGlobalMetaStateLocked();
}
+void InputReader::ContextImpl::updateLedMetaState(int32_t metaState) {
+ // lock is already held by the input loop
+ mReader->updateLedMetaStateLocked(metaState);
+}
+
+int32_t InputReader::ContextImpl::getLedMetaState() {
+ // lock is already held by the input loop
+ return mReader->getLedMetaStateLocked();
+}
+
void InputReader::ContextImpl::disableVirtualKeysUntil(nsecs_t time) {
// lock is already held by the input loop
mReader->disableVirtualKeysUntilLocked(time);
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index da36a48..307eeb4 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -98,6 +98,8 @@
std::optional<int32_t> getAssociatedDisplayId();
+ void updateLedState(bool reset);
+
size_t getMapperCount();
// construct and add a mapper to the input device
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index 9cb2052..2d6ccf5 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -55,34 +55,32 @@
const sp<InputListenerInterface>& listener);
virtual ~InputReader();
- virtual void dump(std::string& dump) override;
- virtual void monitor() override;
+ void dump(std::string& dump) override;
+ void monitor() override;
- virtual status_t start() override;
- virtual status_t stop() override;
+ status_t start() override;
+ status_t stop() override;
- virtual void getInputDevices(std::vector<InputDeviceInfo>& outInputDevices) override;
+ void getInputDevices(std::vector<InputDeviceInfo>& outInputDevices) override;
- virtual bool isInputDeviceEnabled(int32_t deviceId) override;
+ bool isInputDeviceEnabled(int32_t deviceId) override;
- virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
- int32_t scanCode) override;
- virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
- int32_t keyCode) override;
- virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t sw) override;
+ int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask, int32_t scanCode) override;
+ int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask, int32_t keyCode) override;
+ int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t sw) override;
- virtual void toggleCapsLockState(int32_t deviceId) override;
+ void toggleCapsLockState(int32_t deviceId) override;
- virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) override;
+ bool hasKeys(int32_t deviceId, uint32_t sourceMask, size_t numCodes, const int32_t* keyCodes,
+ uint8_t* outFlags) override;
- virtual void requestRefreshConfiguration(uint32_t changes) override;
+ void requestRefreshConfiguration(uint32_t changes) override;
- virtual void vibrate(int32_t deviceId, const std::vector<VibrationElement>& pattern,
- ssize_t repeat, int32_t token) override;
- virtual void cancelVibrate(int32_t deviceId, int32_t token) override;
+ void vibrate(int32_t deviceId, const std::vector<VibrationElement>& pattern, ssize_t repeat,
+ int32_t token) override;
+ void cancelVibrate(int32_t deviceId, int32_t token) override;
- virtual bool canDispatchToDisplay(int32_t deviceId, int32_t displayId) override;
+ bool canDispatchToDisplay(int32_t deviceId, int32_t displayId) override;
protected:
// These members are protected so they can be instrumented by test cases.
@@ -100,21 +98,22 @@
public:
explicit ContextImpl(InputReader* reader);
- virtual void updateGlobalMetaState() override;
- virtual int32_t getGlobalMetaState() override;
- virtual void disableVirtualKeysUntil(nsecs_t time) override;
- virtual bool shouldDropVirtualKey(nsecs_t now, int32_t keyCode, int32_t scanCode) override;
- virtual void fadePointer() override;
- virtual std::shared_ptr<PointerControllerInterface> getPointerController(
- int32_t deviceId) override;
- virtual void requestTimeoutAtTime(nsecs_t when) override;
- virtual int32_t bumpGeneration() override;
- virtual void getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices) override;
- virtual void dispatchExternalStylusState(const StylusState& outState) override;
- virtual InputReaderPolicyInterface* getPolicy() override;
- virtual InputListenerInterface* getListener() override;
- virtual EventHubInterface* getEventHub() override;
- virtual int32_t getNextId() override;
+ void updateGlobalMetaState() override;
+ int32_t getGlobalMetaState() override;
+ void disableVirtualKeysUntil(nsecs_t time) override;
+ bool shouldDropVirtualKey(nsecs_t now, int32_t keyCode, int32_t scanCode) override;
+ void fadePointer() override;
+ std::shared_ptr<PointerControllerInterface> getPointerController(int32_t deviceId) override;
+ void requestTimeoutAtTime(nsecs_t when) override;
+ int32_t bumpGeneration() override;
+ void getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices) override;
+ void dispatchExternalStylusState(const StylusState& outState) override;
+ InputReaderPolicyInterface* getPolicy() override;
+ InputListenerInterface* getListener() override;
+ EventHubInterface* getEventHub() override;
+ int32_t getNextId() override;
+ void updateLedMetaState(int32_t metaState) override;
+ int32_t getLedMetaState() override;
} mContext;
friend class ContextImpl;
@@ -157,6 +156,10 @@
void updateGlobalMetaStateLocked();
int32_t getGlobalMetaStateLocked();
+ int32_t mLedMetaState;
+ void updateLedMetaStateLocked(int32_t metaState);
+ int32_t getLedMetaStateLocked();
+
void notifyExternalStylusPresenceChanged();
void getExternalStylusDevicesLocked(std::vector<InputDeviceInfo>& outDevices);
void dispatchExternalStylusState(const StylusState& state);
diff --git a/services/inputflinger/reader/include/InputReaderContext.h b/services/inputflinger/reader/include/InputReaderContext.h
index ffb8d8c..dc807f7 100644
--- a/services/inputflinger/reader/include/InputReaderContext.h
+++ b/services/inputflinger/reader/include/InputReaderContext.h
@@ -59,6 +59,9 @@
virtual EventHubInterface* getEventHub() = 0;
virtual int32_t getNextId() = 0;
+
+ virtual void updateLedMetaState(int32_t metaState) = 0;
+ virtual int32_t getLedMetaState() = 0;
};
} // namespace android
diff --git a/services/inputflinger/reader/mapper/InputMapper.h b/services/inputflinger/reader/mapper/InputMapper.h
index d9fc5cc..56ab928 100644
--- a/services/inputflinger/reader/mapper/InputMapper.h
+++ b/services/inputflinger/reader/mapper/InputMapper.h
@@ -74,6 +74,7 @@
virtual void updateExternalStylusState(const StylusState& state);
virtual std::optional<int32_t> getAssociatedDisplayId() { return std::nullopt; }
+ virtual void updateLedState(bool reset) {}
protected:
InputDeviceContext& mDeviceContext;
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
index bd4232d..65f9781 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
@@ -390,11 +390,14 @@
bool KeyboardInputMapper::updateMetaStateIfNeeded(int32_t keyCode, bool down) {
int32_t oldMetaState = mMetaState;
int32_t newMetaState = android::updateMetaState(keyCode, down, oldMetaState);
- bool metaStateChanged = oldMetaState != newMetaState;
+ int32_t metaStateChanged = oldMetaState ^ newMetaState;
if (metaStateChanged) {
mMetaState = newMetaState;
- updateLedState(false);
-
+ constexpr int32_t allLedMetaState =
+ AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON;
+ if ((metaStateChanged & allLedMetaState) != 0) {
+ getContext()->updateLedMetaState(newMetaState & allLedMetaState);
+ }
getContext()->updateGlobalMetaState();
}
@@ -415,6 +418,7 @@
}
void KeyboardInputMapper::updateLedState(bool reset) {
+ mMetaState |= getContext()->getLedMetaState();
updateLedStateForModifier(mCapsLockLedState, ALED_CAPS_LOCK, AMETA_CAPS_LOCK_ON, reset);
updateLedStateForModifier(mNumLockLedState, ALED_NUM_LOCK, AMETA_NUM_LOCK_ON, reset);
updateLedStateForModifier(mScrollLockLedState, ALED_SCROLL_LOCK, AMETA_SCROLL_LOCK_ON, reset);
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.h b/services/inputflinger/reader/mapper/KeyboardInputMapper.h
index 0bdeded..4c0b42a 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.h
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.h
@@ -42,6 +42,7 @@
virtual int32_t getMetaState() override;
virtual void updateMetaState(int32_t keyCode) override;
virtual std::optional<int32_t> getAssociatedDisplayId() override;
+ virtual void updateLedState(bool reset);
private:
// The current viewport.
@@ -93,7 +94,6 @@
void resetLedState();
void initializeLedState(LedState& ledState, int32_t led);
- void updateLedState(bool reset);
void updateLedStateForModifier(LedState& ledState, int32_t led, int32_t modifier, bool reset);
std::optional<DisplayViewport> findViewport(nsecs_t when,
const InputReaderConfiguration* config);
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 3872de5..82157b6 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -844,115 +844,6 @@
}
};
-
-// --- FakeInputReaderContext ---
-
-class FakeInputReaderContext : public InputReaderContext {
- std::shared_ptr<EventHubInterface> mEventHub;
- sp<InputReaderPolicyInterface> mPolicy;
- sp<InputListenerInterface> mListener;
- int32_t mGlobalMetaState;
- bool mUpdateGlobalMetaStateWasCalled;
- int32_t mGeneration;
- int32_t mNextId;
- std::weak_ptr<PointerControllerInterface> mPointerController;
-
-public:
- FakeInputReaderContext(std::shared_ptr<EventHubInterface> eventHub,
- const sp<InputReaderPolicyInterface>& policy,
- const sp<InputListenerInterface>& listener)
- : mEventHub(eventHub),
- mPolicy(policy),
- mListener(listener),
- mGlobalMetaState(0),
- mNextId(1) {}
-
- virtual ~FakeInputReaderContext() { }
-
- void assertUpdateGlobalMetaStateWasCalled() {
- ASSERT_TRUE(mUpdateGlobalMetaStateWasCalled)
- << "Expected updateGlobalMetaState() to have been called.";
- mUpdateGlobalMetaStateWasCalled = false;
- }
-
- void setGlobalMetaState(int32_t state) {
- mGlobalMetaState = state;
- }
-
- uint32_t getGeneration() {
- return mGeneration;
- }
-
- void updatePointerDisplay() {
- std::shared_ptr<PointerControllerInterface> controller = mPointerController.lock();
- if (controller != nullptr) {
- InputReaderConfiguration config;
- mPolicy->getReaderConfiguration(&config);
- auto viewport = config.getDisplayViewportById(config.defaultPointerDisplayId);
- if (viewport) {
- controller->setDisplayViewport(*viewport);
- }
- }
- }
-
-private:
- virtual void updateGlobalMetaState() {
- mUpdateGlobalMetaStateWasCalled = true;
- }
-
- virtual int32_t getGlobalMetaState() {
- return mGlobalMetaState;
- }
-
- virtual EventHubInterface* getEventHub() {
- return mEventHub.get();
- }
-
- virtual InputReaderPolicyInterface* getPolicy() {
- return mPolicy.get();
- }
-
- virtual InputListenerInterface* getListener() {
- return mListener.get();
- }
-
- virtual void disableVirtualKeysUntil(nsecs_t) {
- }
-
- virtual bool shouldDropVirtualKey(nsecs_t, int32_t, int32_t) { return false; }
-
- virtual std::shared_ptr<PointerControllerInterface> getPointerController(int32_t deviceId) {
- std::shared_ptr<PointerControllerInterface> controller = mPointerController.lock();
- if (controller == nullptr) {
- controller = mPolicy->obtainPointerController(deviceId);
- mPointerController = controller;
- updatePointerDisplay();
- }
- return controller;
- }
-
- virtual void fadePointer() {
- }
-
- virtual void requestTimeoutAtTime(nsecs_t) {
- }
-
- virtual int32_t bumpGeneration() {
- return ++mGeneration;
- }
-
- virtual void getExternalStylusDevices(std::vector<InputDeviceInfo>& outDevices) {
-
- }
-
- virtual void dispatchExternalStylusState(const StylusState&) {
-
- }
-
- virtual int32_t getNextId() { return mNextId++; }
-};
-
-
// --- FakeInputMapper ---
class FakeInputMapper : public InputMapper {
@@ -1143,7 +1034,7 @@
InstrumentedInputReader(std::shared_ptr<EventHubInterface> eventHub,
const sp<InputReaderPolicyInterface>& policy,
const sp<InputListenerInterface>& listener)
- : InputReader(eventHub, policy, listener) {}
+ : InputReader(eventHub, policy, listener), mFakeContext(this) {}
virtual ~InstrumentedInputReader() {}
@@ -1155,7 +1046,7 @@
identifier.name = name;
identifier.location = location;
int32_t generation = deviceId + 1;
- return std::make_shared<InputDevice>(&mContext, deviceId, generation, identifier);
+ return std::make_shared<InputDevice>(&mFakeContext, deviceId, generation, identifier);
}
// Make the protected loopOnce method accessible to tests.
@@ -1172,7 +1063,50 @@
return InputReader::createDeviceLocked(eventHubId, identifier);
}
+ // --- FakeInputReaderContext ---
+ class FakeInputReaderContext : public ContextImpl {
+ int32_t mGlobalMetaState;
+ bool mUpdateGlobalMetaStateWasCalled;
+ int32_t mGeneration;
+
+ public:
+ FakeInputReaderContext(InputReader* reader)
+ : ContextImpl(reader),
+ mGlobalMetaState(0),
+ mUpdateGlobalMetaStateWasCalled(false),
+ mGeneration(1) {}
+
+ virtual ~FakeInputReaderContext() {}
+
+ void assertUpdateGlobalMetaStateWasCalled() {
+ ASSERT_TRUE(mUpdateGlobalMetaStateWasCalled)
+ << "Expected updateGlobalMetaState() to have been called.";
+ mUpdateGlobalMetaStateWasCalled = false;
+ }
+
+ void setGlobalMetaState(int32_t state) { mGlobalMetaState = state; }
+
+ uint32_t getGeneration() { return mGeneration; }
+
+ void updateGlobalMetaState() override {
+ mUpdateGlobalMetaStateWasCalled = true;
+ ContextImpl::updateGlobalMetaState();
+ }
+
+ int32_t getGlobalMetaState() override {
+ return mGlobalMetaState | ContextImpl::getGlobalMetaState();
+ }
+
+ int32_t bumpGeneration() override {
+ mGeneration = ContextImpl::bumpGeneration();
+ return mGeneration;
+ }
+ } mFakeContext;
+
friend class InputReaderTest;
+
+public:
+ FakeInputReaderContext* getContext() { return &mFakeContext; }
};
// --- InputReaderPolicyTest ---
@@ -2097,27 +2031,26 @@
std::shared_ptr<FakeEventHub> mFakeEventHub;
sp<FakeInputReaderPolicy> mFakePolicy;
sp<TestInputListener> mFakeListener;
- FakeInputReaderContext* mFakeContext;
-
+ std::unique_ptr<InstrumentedInputReader> mReader;
std::shared_ptr<InputDevice> mDevice;
virtual void SetUp() override {
mFakeEventHub = std::make_unique<FakeEventHub>();
mFakePolicy = new FakeInputReaderPolicy();
mFakeListener = new TestInputListener();
- mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeListener);
-
- mFakeEventHub->addDevice(EVENTHUB_ID, DEVICE_NAME, Flags<InputDeviceClass>(0));
+ mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
+ mFakeListener);
InputDeviceIdentifier identifier;
identifier.name = DEVICE_NAME;
identifier.location = DEVICE_LOCATION;
- mDevice = std::make_shared<InputDevice>(mFakeContext, DEVICE_ID, DEVICE_GENERATION,
+ mDevice = std::make_shared<InputDevice>(mReader->getContext(), DEVICE_ID, DEVICE_GENERATION,
identifier);
+ mReader->pushNextDevice(mDevice);
+ mFakeEventHub->addDevice(EVENTHUB_ID, DEVICE_NAME, Flags<InputDeviceClass>(0));
+ mReader->loopOnce();
}
virtual void TearDown() override {
- mDevice = nullptr;
- delete mFakeContext;
mFakeListener.clear();
mFakePolicy.clear();
}
@@ -2336,27 +2269,21 @@
std::shared_ptr<FakeEventHub> mFakeEventHub;
sp<FakeInputReaderPolicy> mFakePolicy;
sp<TestInputListener> mFakeListener;
- FakeInputReaderContext* mFakeContext;
- InputDevice* mDevice;
+ std::unique_ptr<InstrumentedInputReader> mReader;
+ std::shared_ptr<InputDevice> mDevice;
virtual void SetUp(Flags<InputDeviceClass> classes) {
mFakeEventHub = std::make_unique<FakeEventHub>();
mFakePolicy = new FakeInputReaderPolicy();
mFakeListener = new TestInputListener();
- mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeListener);
- InputDeviceIdentifier identifier;
- identifier.name = DEVICE_NAME;
- identifier.location = DEVICE_LOCATION;
- mDevice = new InputDevice(mFakeContext, DEVICE_ID, DEVICE_GENERATION, identifier);
-
- mFakeEventHub->addDevice(EVENTHUB_ID, DEVICE_NAME, classes);
+ mReader = std::make_unique<InstrumentedInputReader>(mFakeEventHub, mFakePolicy,
+ mFakeListener);
+ mDevice = newDevice(DEVICE_ID, DEVICE_NAME, DEVICE_LOCATION, EVENTHUB_ID, classes);
}
virtual void SetUp() override { SetUp(DEVICE_CLASSES); }
virtual void TearDown() override {
- delete mDevice;
- delete mFakeContext;
mFakeListener.clear();
mFakePolicy.clear();
}
@@ -2367,11 +2294,27 @@
void configureDevice(uint32_t changes) {
if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
- mFakeContext->updatePointerDisplay();
+ mReader->requestRefreshConfiguration(changes);
+ mReader->loopOnce();
}
mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), changes);
}
+ std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name,
+ const std::string& location, int32_t eventHubId,
+ Flags<InputDeviceClass> classes) {
+ InputDeviceIdentifier identifier;
+ identifier.name = name;
+ identifier.location = location;
+ std::shared_ptr<InputDevice> device =
+ std::make_shared<InputDevice>(mReader->getContext(), deviceId, DEVICE_GENERATION,
+ identifier);
+ mReader->pushNextDevice(device);
+ mFakeEventHub->addDevice(eventHubId, name, classes);
+ mReader->loopOnce();
+ return device;
+ }
+
template <class T, typename... Args>
T& addMapperAndConfigure(Args... args) {
T& mapper = mDevice->addMapper<T>(EVENTHUB_ID, args...);
@@ -2393,8 +2336,7 @@
mFakePolicy->clearViewports();
}
- static void process(InputMapper& mapper, nsecs_t when, int32_t type, int32_t code,
- int32_t value) {
+ void process(InputMapper& mapper, nsecs_t when, int32_t type, int32_t code, int32_t value) {
RawEvent event;
event.when = when;
event.deviceId = mapper.getDeviceContext().getEventHubId();
@@ -2402,6 +2344,7 @@
event.code = code;
event.value = value;
mapper.process(&event);
+ mReader->loopOnce();
}
static void assertMotionRange(const InputDeviceInfo& info,
@@ -2547,6 +2490,9 @@
KeyboardInputMapper& mapper =
addMapperAndConfigure<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+ // Initial metastate to AMETA_NONE.
+ ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper.getMetaState());
+ mapper.updateMetaState(AKEYCODE_NUM_LOCK);
// Key down by scan code.
process(mapper, ARBITRARY_TIME, EV_KEY, KEY_HOME, 1);
@@ -2646,8 +2592,9 @@
addMapperAndConfigure<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- // Initial metastate.
- ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
+ // Initial metastate to AMETA_NONE.
+ ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper.getMetaState());
+ mapper.updateMetaState(AKEYCODE_NUM_LOCK);
// Metakey down.
process(mapper, ARBITRARY_TIME, EV_KEY, KEY_LEFTSHIFT, 1);
@@ -2655,7 +2602,7 @@
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, args.metaState);
ASSERT_EQ(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON, mapper.getMetaState());
- ASSERT_NO_FATAL_FAILURE(mFakeContext->assertUpdateGlobalMetaStateWasCalled());
+ ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertUpdateGlobalMetaStateWasCalled());
// Key down.
process(mapper, ARBITRARY_TIME + 1, EV_KEY, KEY_A, 1);
@@ -2674,7 +2621,7 @@
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyKeyWasCalled(&args));
ASSERT_EQ(AMETA_NONE, args.metaState);
ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
- ASSERT_NO_FATAL_FAILURE(mFakeContext->assertUpdateGlobalMetaStateWasCalled());
+ ASSERT_NO_FATAL_FAILURE(mReader->getContext()->assertUpdateGlobalMetaStateWasCalled());
}
TEST_F(KeyboardInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateDPad) {
@@ -2879,6 +2826,9 @@
KeyboardInputMapper& mapper =
addMapperAndConfigure<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+ // Initial metastate to AMETA_NONE.
+ ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper.getMetaState());
+ mapper.updateMetaState(AKEYCODE_NUM_LOCK);
// Initialization should have turned all of the lights off.
ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
@@ -2943,16 +2893,13 @@
// keyboard 2.
const std::string USB2 = "USB2";
+ const std::string DEVICE_NAME2 = "KEYBOARD2";
constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
- InputDeviceIdentifier identifier;
- identifier.name = "KEYBOARD2";
- identifier.location = USB2;
- std::unique_ptr<InputDevice> device2 =
- std::make_unique<InputDevice>(mFakeContext, SECOND_DEVICE_ID, DEVICE_GENERATION,
- identifier);
- mFakeEventHub->addDevice(SECOND_EVENTHUB_ID, DEVICE_NAME,
- Flags<InputDeviceClass>(0) /*classes*/);
+ std::shared_ptr<InputDevice> device2 =
+ newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
+ Flags<InputDeviceClass>(0));
+
mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
@@ -3015,6 +2962,73 @@
AKEYCODE_DPAD_LEFT, newDisplayId));
}
+TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleAfterReattach) {
+ mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
+ mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
+ mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
+
+ KeyboardInputMapper& mapper =
+ addMapperAndConfigure<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
+ AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+ // Initial metastate to AMETA_NONE.
+ ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper.getMetaState());
+ mapper.updateMetaState(AKEYCODE_NUM_LOCK);
+
+ // Initialization should have turned all of the lights off.
+ ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
+ ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
+ ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
+
+ // Toggle caps lock on.
+ process(mapper, ARBITRARY_TIME, EV_KEY, KEY_CAPSLOCK, 1);
+ process(mapper, ARBITRARY_TIME, EV_KEY, KEY_CAPSLOCK, 0);
+ ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
+ ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
+
+ // Toggle num lock on.
+ process(mapper, ARBITRARY_TIME, EV_KEY, KEY_NUMLOCK, 1);
+ process(mapper, ARBITRARY_TIME, EV_KEY, KEY_NUMLOCK, 0);
+ ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
+ ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper.getMetaState());
+
+ // Toggle scroll lock on.
+ process(mapper, ARBITRARY_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
+ process(mapper, ARBITRARY_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
+ ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
+ ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
+
+ mFakeEventHub->removeDevice(EVENTHUB_ID);
+ mReader->loopOnce();
+
+ // keyboard 2 should default toggle keys.
+ const std::string USB2 = "USB2";
+ const std::string DEVICE_NAME2 = "KEYBOARD2";
+ constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
+ constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
+ std::shared_ptr<InputDevice> device2 =
+ newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
+ Flags<InputDeviceClass>(0));
+ mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
+ mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_NUML, false /*initially off*/);
+ mFakeEventHub->addLed(SECOND_EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
+ mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
+ mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
+ mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
+
+ device2->addMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID, AINPUT_SOURCE_KEYBOARD,
+ AINPUT_KEYBOARD_TYPE_ALPHABETIC);
+ device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), 0 /*changes*/);
+ device2->reset(ARBITRARY_TIME);
+
+ ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_CAPSL));
+ ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_NUML));
+ ASSERT_TRUE(mFakeEventHub->getLedState(SECOND_EVENTHUB_ID, LED_SCROLLL));
+ ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
+}
+
// --- KeyboardInputMapperTest_ExternalDevice ---
class KeyboardInputMapperTest_ExternalDevice : public InputMapperTest {
@@ -3211,7 +3225,7 @@
addConfigurationProperty("cursor.mode", "navigation");
CursorInputMapper& mapper = addMapperAndConfigure<CursorInputMapper>();
- mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
+ mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
NotifyMotionArgs args;
@@ -3839,10 +3853,10 @@
// Disable pointer capture and check that the device generation got bumped
// and events are generated the usual way.
- const uint32_t generation = mFakeContext->getGeneration();
+ const uint32_t generation = mReader->getContext()->getGeneration();
mFakePolicy->setPointerCapture(false);
configureDevice(InputReaderConfiguration::CHANGE_POINTER_CAPTURE);
- ASSERT_TRUE(mFakeContext->getGeneration() != generation);
+ ASSERT_TRUE(mReader->getContext()->getGeneration() != generation);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
ASSERT_EQ(ARBITRARY_TIME, resetArgs.eventTime);
@@ -4257,7 +4271,7 @@
prepareVirtualKeys();
SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
- mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
+ mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
NotifyKeyArgs args;
@@ -4307,7 +4321,7 @@
prepareVirtualKeys();
SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
- mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
+ mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
NotifyKeyArgs keyArgs;
@@ -4428,7 +4442,7 @@
prepareVirtualKeys();
SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
- mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
+ mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
NotifyMotionArgs motionArgs;
@@ -4503,7 +4517,7 @@
prepareVirtualKeys();
SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
- mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
+ mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
NotifyMotionArgs motionArgs;
@@ -4599,7 +4613,7 @@
prepareVirtualKeys();
SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
- mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
+ mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
NotifyMotionArgs motionArgs;
@@ -5494,7 +5508,7 @@
prepareVirtualKeys();
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
- mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
+ mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
NotifyMotionArgs motionArgs;
@@ -5770,7 +5784,7 @@
prepareVirtualKeys();
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
- mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
+ mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
NotifyMotionArgs motionArgs;
@@ -5945,7 +5959,7 @@
prepareVirtualKeys();
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
- mFakeContext->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
+ mReader->getContext()->setGlobalMetaState(AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_ON);
NotifyMotionArgs motionArgs;
@@ -6925,16 +6939,13 @@
// Create the second touch screen device, and enable multi fingers.
const std::string USB2 = "USB2";
+ const std::string DEVICE_NAME2 = "TOUCHSCREEN2";
constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
- InputDeviceIdentifier identifier;
- identifier.name = "TOUCHSCREEN2";
- identifier.location = USB2;
- std::unique_ptr<InputDevice> device2 =
- std::make_unique<InputDevice>(mFakeContext, SECOND_DEVICE_ID, DEVICE_GENERATION,
- identifier);
- mFakeEventHub->addDevice(SECOND_EVENTHUB_ID, DEVICE_NAME,
- Flags<InputDeviceClass>(0) /*classes*/);
+ std::shared_ptr<InputDevice> device2 =
+ newDevice(SECOND_DEVICE_ID, DEVICE_NAME2, USB2, SECOND_EVENTHUB_ID,
+ Flags<InputDeviceClass>(0));
+
mFakeEventHub->addAbsoluteAxis(SECOND_EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX,
0 /*flat*/, 0 /*fuzz*/);
mFakeEventHub->addAbsoluteAxis(SECOND_EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX,
diff --git a/services/vibratorservice/VibratorCallbackScheduler.cpp b/services/vibratorservice/VibratorCallbackScheduler.cpp
index 3f8cd67..f2870b0 100644
--- a/services/vibratorservice/VibratorCallbackScheduler.cpp
+++ b/services/vibratorservice/VibratorCallbackScheduler.cpp
@@ -71,14 +71,17 @@
void CallbackScheduler::loop() {
while (true) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::unique_lock<std::mutex> lock(mMutex);
if (mFinished) {
// Destructor was called, so let the callback thread die.
break;
}
while (!mQueue.empty() && mQueue.top().isExpired()) {
- mQueue.top().run();
+ DelayedCallback callback = mQueue.top();
mQueue.pop();
+ lock.unlock();
+ callback.run();
+ lock.lock();
}
if (mQueue.empty()) {
// Wait until a new callback is scheduled.