Merge "SF: Fix unit test getColorModes() expectation"
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index 352cf0a..94c3102 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -5,6 +5,10 @@
"-Wall",
"-Werror",
"-Wextra",
+
+ "-Wunreachable-code",
+ "-Wunreachable-code-break",
+ "-Wunreachable-code-return",
],
srcs: [
"CacheItem.cpp",
@@ -15,6 +19,9 @@
"utils.cpp",
":installd_aidl",
],
+ header_libs: [
+ "dex2oat_headers",
+ ],
shared_libs: [
"libbase",
"libbinder",
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 0a45ab0..e53a223 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -1971,10 +1971,11 @@
const char* profile_name = getCStr(profileName);
const char* dm_path = getCStr(dexMetadataPath);
const char* compilation_reason = getCStr(compilationReason);
+ std::string error_msg;
int res = android::installd::dexopt(apk_path, uid, pkgname, instruction_set, dexoptNeeded,
oat_dir, dexFlags, compiler_filter, volume_uuid, class_loader_context, se_info,
- downgrade, targetSdkVersion, profile_name, dm_path, compilation_reason);
- return res ? error(res, "Failed to dexopt") : ok();
+ downgrade, targetSdkVersion, profile_name, dm_path, compilation_reason, &error_msg);
+ return res ? error(res, error_msg) : ok();
}
binder::Status InstalldNativeService::markBootComplete(const std::string& instructionSet) {
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 02a6063..230853d 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -28,6 +28,8 @@
#include <sys/wait.h>
#include <unistd.h>
+#include <iomanip>
+
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
@@ -37,6 +39,7 @@
#include <cutils/fs.h>
#include <cutils/properties.h>
#include <cutils/sched_policy.h>
+#include <dex2oat_return_codes.h>
#include <log/log.h> // TODO: Move everything to base/logging.
#include <openssl/sha.h>
#include <private/android_filesystem_config.h>
@@ -44,6 +47,7 @@
#include <system/thread_defs.h>
#include "dexopt.h"
+#include "dexopt_return_codes.h"
#include "globals.h"
#include "installd_deps.h"
#include "otapreopt_utils.h"
@@ -68,6 +72,7 @@
static constexpr const char* kMinidebugDex2oatFlag = "--generate-mini-debug-info";
static constexpr const char* kDisableCompactDexFlag = "--compact-dex-level=none";
+
// Deleter using free() for use with std::unique_ptr<>. See also UniqueCPtr<> below.
struct FreeDelete {
// NOTE: Deleting a const object is valid but free() takes a non-const pointer.
@@ -219,6 +224,7 @@
}
}
+[[ noreturn ]]
static void run_dex2oat(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 swap_fd,
const char* instruction_set, const char* compiler_filter,
@@ -228,9 +234,9 @@
static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
- ALOGE("Instruction set %s longer than max length of %d",
- instruction_set, MAX_INSTRUCTION_SET_LEN);
- return;
+ LOG(ERROR) << "Instruction set '" << instruction_set << "' longer than max length of "
+ << MAX_INSTRUCTION_SET_LEN;
+ exit(DexoptReturnCodes::kInstructionSetLength);
}
// Get the relative path to the input file.
@@ -302,10 +308,11 @@
// If the runtime was requested to use libartd.so, we'll run dex2oatd, otherwise dex2oat.
const char* dex2oat_bin = "/system/bin/dex2oat";
- static const char* kDex2oatDebugPath = "/system/bin/dex2oatd";
+ constexpr const char* kDex2oatDebugPath = "/system/bin/dex2oatd";
if (is_debug_runtime() || (background_job_compile && is_debuggable_build())) {
- DCHECK(access(kDex2oatDebugPath, X_OK) == 0);
- dex2oat_bin = kDex2oatDebugPath;
+ if (access(kDex2oatDebugPath, X_OK) == 0) {
+ dex2oat_bin = kDex2oatDebugPath;
+ }
}
bool generate_minidebug_info = kEnableMinidebugInfo &&
@@ -548,7 +555,8 @@
argv[i] = NULL;
execv(dex2oat_bin, (char * const *)argv);
- ALOGE("execv(%s) failed: %s\n", dex2oat_bin, strerror(errno));
+ PLOG(ERROR) << "execv(" << dex2oat_bin << ") failed";
+ exit(DexoptReturnCodes::kDex2oatExec);
}
/*
@@ -600,12 +608,12 @@
static void SetDex2OatScheduling(bool set_to_bg) {
if (set_to_bg) {
if (set_sched_policy(0, SP_BACKGROUND) < 0) {
- ALOGE("set_sched_policy failed: %s\n", strerror(errno));
- exit(70);
+ PLOG(ERROR) << "set_sched_policy failed";
+ exit(DexoptReturnCodes::kSetSchedPolicy);
}
if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
- ALOGE("setpriority failed: %s\n", strerror(errno));
- exit(71);
+ PLOG(ERROR) << "setpriority failed";
+ exit(DexoptReturnCodes::kSetPriority);
}
}
}
@@ -705,12 +713,12 @@
static void drop_capabilities(uid_t uid) {
if (setgid(uid) != 0) {
- ALOGE("setgid(%d) failed in installd during dexopt\n", uid);
- exit(64);
+ PLOG(ERROR) << "setgid(" << uid << ") failed in installd during dexopt";
+ exit(DexoptReturnCodes::kSetGid);
}
if (setuid(uid) != 0) {
- ALOGE("setuid(%d) failed in installd during dexopt\n", uid);
- exit(65);
+ PLOG(ERROR) << "setuid(" << uid << ") failed in installd during dexopt";
+ exit(DexoptReturnCodes::kSetUid);
}
// drop capabilities
struct __user_cap_header_struct capheader;
@@ -719,8 +727,8 @@
memset(&capdata, 0, sizeof(capdata));
capheader.version = _LINUX_CAPABILITY_VERSION_3;
if (capset(&capheader, &capdata[0]) < 0) {
- ALOGE("capset failed: %s\n", strerror(errno));
- exit(66);
+ PLOG(ERROR) << "capset failed";
+ exit(DexoptReturnCodes::kCapSet);
}
}
@@ -730,6 +738,7 @@
static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_IO = 3;
static constexpr int PROFMAN_BIN_RETURN_CODE_ERROR_LOCKING = 4;
+[[ noreturn ]]
static void run_profman(const std::vector<unique_fd>& profile_fds,
const unique_fd& reference_profile_fd,
const std::vector<unique_fd>* apk_fds,
@@ -773,18 +782,18 @@
argv[i] = NULL;
execv(profman_bin, (char * const *)argv);
- ALOGE("execv(%s) failed: %s\n", profman_bin, strerror(errno));
- exit(68); /* only get here on exec failure */
+ PLOG(ERROR) << "execv(" << profman_bin << ") failed";
+ exit(DexoptReturnCodes::kProfmanExec); /* only get here on exec failure */
}
-
+[[ noreturn ]]
static void run_profman_merge(const std::vector<unique_fd>& profiles_fd,
const unique_fd& reference_profile_fd,
const std::vector<unique_fd>* apk_fds = nullptr) {
run_profman(profiles_fd, reference_profile_fd, apk_fds, /*copy_and_update*/false);
}
-
+[[ noreturn ]]
static void run_profman_copy_and_update(unique_fd&& profile_fd,
unique_fd&& reference_profile_fd,
unique_fd&& apk_fd) {
@@ -819,7 +828,6 @@
/* child -- drop privileges before continuing */
drop_capabilities(uid);
run_profman_merge(profiles_fd, reference_profile_fd);
- exit(68); /* only get here on exec failure */
}
/* parent */
int return_code = wait_child(pid);
@@ -892,6 +900,7 @@
return analyze_profiles(uid, package_name, profile_name, /*is_secondary_dex*/false);
}
+[[ noreturn ]]
static void run_profman_dump(const std::vector<unique_fd>& profile_fds,
const unique_fd& reference_profile_fd,
const std::vector<std::string>& dex_locations,
@@ -923,8 +932,8 @@
argv[i] = NULL;
execv(PROFMAN_BIN, (char * const *)argv);
- ALOGE("execv(%s) failed: %s\n", PROFMAN_BIN, strerror(errno));
- exit(68); /* only get here on exec failure */
+ PLOG(ERROR) << "execv(" << PROFMAN_BIN << ") failed";
+ exit(DexoptReturnCodes::kProfmanExec); /* only get here on exec failure */
}
bool dump_profiles(int32_t uid, const std::string& pkgname, const std::string& profile_name,
@@ -969,7 +978,6 @@
drop_capabilities(uid);
run_profman_dump(profile_fds, reference_profile_fd, dex_locations,
apk_fds, output_fd);
- exit(68); /* only get here on exec failure */
}
/* parent */
int return_code = wait_child(pid);
@@ -1640,10 +1648,17 @@
// secondary dex files. This return codes are returned by the child process created for
// analyzing secondary dex files in process_secondary_dex_dexopt.
-// The dexoptanalyzer was not invoked because of validation or IO errors.
-static int constexpr SECONDARY_DEX_DEXOPTANALYZER_SKIPPED = 200;
-// The dexoptanalyzer was not invoked because the dex file does not exist anymore.
-static int constexpr SECONDARY_DEX_DEXOPTANALYZER_SKIPPED_NO_FILE = 201;
+enum DexoptAnalyzerSkipCodes {
+ // The dexoptanalyzer was not invoked because of validation or IO errors.
+ // Specific errors are encoded in the name.
+ kSecondaryDexDexoptAnalyzerSkippedValidatePath = 200,
+ kSecondaryDexDexoptAnalyzerSkippedOpenZip = 201,
+ kSecondaryDexDexoptAnalyzerSkippedPrepareDir = 202,
+ kSecondaryDexDexoptAnalyzerSkippedOpenOutput = 203,
+ kSecondaryDexDexoptAnalyzerSkippedFailExec = 204,
+ // The dexoptanalyzer was not invoked because the dex file does not exist anymore.
+ kSecondaryDexDexoptAnalyzerSkippedNoFile = 205,
+};
// Verifies the result of analyzing secondary dex files from process_secondary_dex_dexopt.
// If the result is valid returns true and sets dexopt_needed_out to a valid value.
@@ -1651,7 +1666,7 @@
// The result is expected to be either one of SECONDARY_DEX_* codes or a valid exit code
// of dexoptanalyzer.
static bool process_secondary_dexoptanalyzer_result(const std::string& dex_path, int result,
- int* dexopt_needed_out) {
+ int* dexopt_needed_out, std::string* error_msg) {
// The result values are defined in dexoptanalyzer.
switch (result) {
case 0: // dexoptanalyzer: no_dexopt_needed
@@ -1667,21 +1682,42 @@
case 2: // dexoptanalyzer: dex2oat_for_bootimage_oat
case 3: // dexoptanalyzer: dex2oat_for_filter_oat
case 4: // dexoptanalyzer: dex2oat_for_relocation_oat
- LOG(ERROR) << "Dexoptnalyzer return the status of an oat file."
- << " Expected odex file status for secondary dex " << dex_path
- << " : dexoptanalyzer result=" << result;
+ *error_msg = StringPrintf("Dexoptanalyzer return the status of an oat file."
+ " Expected odex file status for secondary dex %s"
+ " : dexoptanalyzer result=%d",
+ dex_path.c_str(),
+ result);
return false;
- case SECONDARY_DEX_DEXOPTANALYZER_SKIPPED_NO_FILE:
+ }
+
+ // Use a second switch for enum switch-case analysis.
+ switch (static_cast<DexoptAnalyzerSkipCodes>(result)) {
+ case kSecondaryDexDexoptAnalyzerSkippedNoFile:
// If the file does not exist there's no need for dexopt.
*dexopt_needed_out = NO_DEXOPT_NEEDED;
return true;
- case SECONDARY_DEX_DEXOPTANALYZER_SKIPPED:
+
+ case kSecondaryDexDexoptAnalyzerSkippedValidatePath:
+ *error_msg = "Dexoptanalyzer path validation failed";
return false;
- default:
- LOG(ERROR) << "Unexpected result from analyzing secondary dex " << dex_path
- << " result=" << result;
+ case kSecondaryDexDexoptAnalyzerSkippedOpenZip:
+ *error_msg = "Dexoptanalyzer open zip failed";
+ return false;
+ case kSecondaryDexDexoptAnalyzerSkippedPrepareDir:
+ *error_msg = "Dexoptanalyzer dir preparation failed";
+ return false;
+ case kSecondaryDexDexoptAnalyzerSkippedOpenOutput:
+ *error_msg = "Dexoptanalyzer open output failed";
+ return false;
+ case kSecondaryDexDexoptAnalyzerSkippedFailExec:
+ *error_msg = "Dexoptanalyzer failed to execute";
return false;
}
+
+ *error_msg = StringPrintf("Unexpected result from analyzing secondary dex %s result=%d",
+ dex_path.c_str(),
+ result);
+ return false;
}
enum SecondaryDexAccess {
@@ -1719,10 +1755,10 @@
// Create the oat file structure for the secondary dex 'dex_path' and assign
// the individual path component to the 'out_' parameters.
static bool create_secondary_dex_oat_layout(const std::string& dex_path, const std::string& isa,
- char* out_oat_dir, char* out_oat_isa_dir, char* out_oat_path) {
+ char* out_oat_dir, char* out_oat_isa_dir, char* out_oat_path, std::string* error_msg) {
size_t dirIndex = dex_path.rfind('/');
if (dirIndex == std::string::npos) {
- LOG(ERROR) << "Unexpected dir structure for dex file " << dex_path;
+ *error_msg = std::string("Unexpected dir structure for dex file ").append(dex_path);
return false;
}
// TODO(calin): we have similar computations in at lest 3 other places
@@ -1734,7 +1770,7 @@
if (!create_oat_out_path(dex_path.c_str(), isa.c_str(), out_oat_dir,
/*is_secondary_dex*/true, out_oat_path)) {
- LOG(ERROR) << "Could not create oat path for secondary dex " << dex_path;
+ *error_msg = std::string("Could not create oat path for secondary dex ").append(dex_path);
return false;
}
return true;
@@ -1742,17 +1778,19 @@
// Validate that the dexopt_flags contain a valid storage flag and convert that to an installd
// recognized storage flags (FLAG_STORAGE_CE or FLAG_STORAGE_DE).
-static bool validate_dexopt_storage_flags(int dexopt_flags, int* out_storage_flag) {
+static bool validate_dexopt_storage_flags(int dexopt_flags,
+ int* out_storage_flag,
+ std::string* error_msg) {
if ((dexopt_flags & DEXOPT_STORAGE_CE) != 0) {
*out_storage_flag = FLAG_STORAGE_CE;
if ((dexopt_flags & DEXOPT_STORAGE_DE) != 0) {
- LOG(ERROR) << "Ambiguous secondary dex storage flag. Both, CE and DE, flags are set";
+ *error_msg = "Ambiguous secondary dex storage flag. Both, CE and DE, flags are set";
return false;
}
} else if ((dexopt_flags & DEXOPT_STORAGE_DE) != 0) {
*out_storage_flag = FLAG_STORAGE_DE;
} else {
- LOG(ERROR) << "Secondary dex storage flag must be set";
+ *error_msg = "Secondary dex storage flag must be set";
return false;
}
return true;
@@ -1768,10 +1806,12 @@
static bool process_secondary_dex_dexopt(const std::string& dex_path, const char* pkgname,
int dexopt_flags, const char* volume_uuid, int uid, const char* instruction_set,
const char* compiler_filter, bool* is_public_out, int* dexopt_needed_out,
- std::string* oat_dir_out, bool downgrade, const char* class_loader_context) {
+ std::string* oat_dir_out, bool downgrade, const char* class_loader_context,
+ /* out */ std::string* error_msg) {
LOG(DEBUG) << "Processing secondary dex path " << dex_path;
int storage_flag;
- if (!validate_dexopt_storage_flags(dexopt_flags, &storage_flag)) {
+ if (!validate_dexopt_storage_flags(dexopt_flags, &storage_flag, error_msg)) {
+ LOG(ERROR) << *error_msg;
return false;
}
// Compute the oat dir as it's not easy to extract it from the child computation.
@@ -1779,8 +1819,8 @@
char oat_dir[PKG_PATH_MAX];
char oat_isa_dir[PKG_PATH_MAX];
if (!create_secondary_dex_oat_layout(
- dex_path, instruction_set, oat_dir, oat_isa_dir, oat_path)) {
- LOG(ERROR) << "Could not create secondary odex layout: " << dex_path;
+ dex_path, instruction_set, oat_dir, oat_isa_dir, oat_path, error_msg)) {
+ LOG(ERROR) << "Could not create secondary odex layout: " << *error_msg;
return false;
}
oat_dir_out->assign(oat_dir);
@@ -1793,7 +1833,7 @@
// Validate the path structure.
if (!validate_secondary_dex_path(pkgname, dex_path, volume_uuid, uid, storage_flag)) {
LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
- _exit(SECONDARY_DEX_DEXOPTANALYZER_SKIPPED);
+ _exit(kSecondaryDexDexoptAnalyzerSkippedValidatePath);
}
// Open the dex file.
@@ -1801,15 +1841,15 @@
zip_fd.reset(open(dex_path.c_str(), O_RDONLY));
if (zip_fd.get() < 0) {
if (errno == ENOENT) {
- _exit(SECONDARY_DEX_DEXOPTANALYZER_SKIPPED_NO_FILE);
+ _exit(kSecondaryDexDexoptAnalyzerSkippedNoFile);
} else {
- _exit(SECONDARY_DEX_DEXOPTANALYZER_SKIPPED);
+ _exit(kSecondaryDexDexoptAnalyzerSkippedOpenZip);
}
}
// Prepare the oat directories.
if (!prepare_secondary_dex_oat_dir(dex_path, uid, instruction_set)) {
- _exit(SECONDARY_DEX_DEXOPTANALYZER_SKIPPED);
+ _exit(kSecondaryDexDexoptAnalyzerSkippedPrepareDir);
}
// Open the vdex/oat files if any.
@@ -1821,7 +1861,7 @@
true /* is_secondary_dex */,
&oat_file_fd,
&vdex_file_fd)) {
- _exit(SECONDARY_DEX_DEXOPTANALYZER_SKIPPED);
+ _exit(kSecondaryDexDexoptAnalyzerSkippedOpenOutput);
}
// Analyze profiles.
@@ -1838,18 +1878,27 @@
downgrade,
class_loader_context);
PLOG(ERROR) << "Failed to exec dexoptanalyzer";
- _exit(SECONDARY_DEX_DEXOPTANALYZER_SKIPPED);
+ _exit(kSecondaryDexDexoptAnalyzerSkippedFailExec);
}
/* parent */
int result = wait_child(pid);
if (!WIFEXITED(result)) {
- LOG(ERROR) << "dexoptanalyzer failed for path " << dex_path << ": " << result;
+ *error_msg = StringPrintf("dexoptanalyzer failed for path %s: 0x%04x",
+ dex_path.c_str(),
+ result);
+ LOG(ERROR) << *error_msg;
return false;
}
result = WEXITSTATUS(result);
// Check that we successfully executed dexoptanalyzer.
- bool success = process_secondary_dexoptanalyzer_result(dex_path, result, dexopt_needed_out);
+ bool success = process_secondary_dexoptanalyzer_result(dex_path,
+ result,
+ dexopt_needed_out,
+ error_msg);
+ if (!success) {
+ LOG(ERROR) << *error_msg;
+ }
LOG(DEBUG) << "Processed secondary dex file " << dex_path << " result=" << result;
@@ -1857,7 +1906,7 @@
// Note that dexoptanalyzer is executed even if force compilation is enabled (because it
// makes the code simpler; force compilation is only needed during tests).
if (success &&
- (result != SECONDARY_DEX_DEXOPTANALYZER_SKIPPED_NO_FILE) &&
+ (result != kSecondaryDexDexoptAnalyzerSkippedNoFile) &&
((dexopt_flags & DEXOPT_FORCE) != 0)) {
*dexopt_needed_out = DEX2OAT_FROM_SCRATCH;
}
@@ -1870,22 +1919,37 @@
return success;
}
+static std::string format_dexopt_error(int status, const char* dex_path) {
+ if (WIFEXITED(status)) {
+ int int_code = WEXITSTATUS(status);
+ const char* code_name = get_return_code_name(static_cast<DexoptReturnCodes>(int_code));
+ if (code_name != nullptr) {
+ return StringPrintf("Dex2oat invocation for %s failed: %s", dex_path, code_name);
+ }
+ }
+ return StringPrintf("Dex2oat invocation for %s failed with 0x%04x", dex_path, status);
+}
+
int dexopt(const char* dex_path, uid_t uid, const char* pkgname, const char* instruction_set,
int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
const char* volume_uuid, const char* class_loader_context, const char* se_info,
bool downgrade, int target_sdk_version, const char* profile_name,
- const char* dex_metadata_path, const char* compilation_reason) {
+ const char* dex_metadata_path, const char* compilation_reason, std::string* error_msg) {
CHECK(pkgname != nullptr);
CHECK(pkgname[0] != 0);
+ CHECK(error_msg != nullptr);
CHECK_EQ(dexopt_flags & ~DEXOPT_MASK, 0)
<< "dexopt flags contains unknown fields: " << dexopt_flags;
if (!validate_dex_path_size(dex_path)) {
+ *error_msg = StringPrintf("Failed to validate %s", dex_path);
return -1;
}
if (class_loader_context != nullptr && strlen(class_loader_context) > PKG_PATH_MAX) {
- LOG(ERROR) << "Class loader context exceeds the allowed size: " << class_loader_context;
+ *error_msg = StringPrintf("Class loader context exceeds the allowed size: %s",
+ class_loader_context);
+ LOG(ERROR) << *error_msg;
return -1;
}
@@ -1902,12 +1966,15 @@
if (is_secondary_dex) {
if (process_secondary_dex_dexopt(dex_path, pkgname, dexopt_flags, volume_uuid, uid,
instruction_set, compiler_filter, &is_public, &dexopt_needed, &oat_dir_str,
- downgrade, class_loader_context)) {
+ downgrade, class_loader_context, error_msg)) {
oat_dir = oat_dir_str.c_str();
if (dexopt_needed == NO_DEXOPT_NEEDED) {
return 0; // Nothing to do, report success.
}
} else {
+ if (error_msg->empty()) { // TODO: Make this a CHECK.
+ *error_msg = "Failed processing secondary.";
+ }
return -1; // We had an error, logged in the process method.
}
} else {
@@ -1920,7 +1987,8 @@
// Open the input file.
unique_fd input_fd(open(dex_path, O_RDONLY, 0));
if (input_fd.get() < 0) {
- ALOGE("installd cannot open '%s' for input during dexopt\n", dex_path);
+ *error_msg = StringPrintf("installd cannot open '%s' for input during dexopt", dex_path);
+ LOG(ERROR) << *error_msg;
return -1;
}
@@ -1929,6 +1997,7 @@
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) {
+ *error_msg = "Could not open out oat file.";
return -1;
}
@@ -1937,6 +2006,7 @@
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)) {
+ *error_msg = "Could not open vdex files.";
return -1;
}
@@ -1948,7 +2018,8 @@
if (is_secondary_dex) {
if (selinux_android_restorecon_pkgdir(oat_dir, se_info, uid,
SELINUX_ANDROID_RESTORECON_RECURSE)) {
- LOG(ERROR) << "Failed to restorecon " << oat_dir;
+ *error_msg = std::string("Failed to restorecon ").append(oat_dir);
+ LOG(ERROR) << *error_msg;
return -1;
}
}
@@ -1972,7 +2043,7 @@
}
}
- ALOGV("DexInv: --- BEGIN '%s' ---\n", dex_path);
+ LOG(VERBOSE) << "DexInv: --- BEGIN '" << dex_path << "' ---";
pid_t pid = fork();
if (pid == 0) {
@@ -1981,8 +2052,8 @@
SetDex2OatScheduling(boot_complete);
if (flock(out_oat_fd.get(), LOCK_EX | LOCK_NB) != 0) {
- ALOGE("flock(%s) failed: %s\n", out_oat_path, strerror(errno));
- _exit(67);
+ PLOG(ERROR) << "flock(" << out_oat_path << ") failed";
+ _exit(DexoptReturnCodes::kFlock);
}
run_dex2oat(input_fd.get(),
@@ -2004,13 +2075,14 @@
enable_hidden_api_checks,
dex_metadata_fd.get(),
compilation_reason);
- _exit(68); /* only get here on exec failure */
} else {
int res = wait_child(pid);
if (res == 0) {
- ALOGV("DexInv: --- END '%s' (success) ---\n", dex_path);
+ LOG(VERBOSE) << "DexInv: --- END '" << dex_path << "' (success) ---";
} else {
- ALOGE("DexInv: --- END '%s' --- status=0x%04x, process failed\n", dex_path, res);
+ LOG(VERBOSE) << "DexInv: --- END '" << dex_path << "' --- status=0x"
+ << std::hex << std::setw(4) << res << ", process failed";
+ *error_msg = format_dexopt_error(res, dex_path);
return res;
}
}
@@ -2118,9 +2190,10 @@
char oat_isa_dir[PKG_PATH_MAX];
bool result = true;
for (size_t i = 0; i < isas.size(); i++) {
+ std::string error_msg;
if (!create_secondary_dex_oat_layout(
- dex_path,isas[i], oat_dir, oat_isa_dir, oat_path)) {
- LOG(ERROR) << "Could not create secondary odex layout: " << dex_path;
+ dex_path,isas[i], oat_dir, oat_isa_dir, oat_path, &error_msg)) {
+ LOG(ERROR) << error_msg;
_exit(kReconcileSecondaryDexValidationError);
}
@@ -2221,7 +2294,7 @@
if (!validate_secondary_dex_path(pkgname, dex_path, volume_uuid_cstr, uid, storage_flag)) {
LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
- _exit(1);
+ _exit(DexoptReturnCodes::kHashValidatePath);
}
unique_fd fd(TEMP_FAILURE_RETRY(open(dex_path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW)));
@@ -2231,7 +2304,7 @@
_exit(0);
}
PLOG(ERROR) << "Failed to open secondary dex " << dex_path;
- _exit(1);
+ _exit(DexoptReturnCodes::kHashOpenPath);
}
SHA256_CTX ctx;
@@ -2244,7 +2317,7 @@
break;
} else if (bytes_read == -1) {
PLOG(ERROR) << "Failed to read secondary dex " << dex_path;
- _exit(1);
+ _exit(DexoptReturnCodes::kHashReadDex);
}
SHA256_Update(&ctx, buffer.data(), bytes_read);
@@ -2253,7 +2326,7 @@
std::array<uint8_t, SHA256_DIGEST_LENGTH> hash;
SHA256_Final(hash.data(), &ctx);
if (!WriteFully(pipe_write, hash.data(), hash.size())) {
- _exit(1);
+ _exit(DexoptReturnCodes::kHashWrite);
}
_exit(0);
@@ -2571,7 +2644,6 @@
/* child -- drop privileges before continuing */
drop_capabilities(app_shared_gid);
run_profman_merge(profiles_fd, snapshot_fd, &apk_fds);
- exit(42); /* only get here on exec failure */
}
/* parent */
@@ -2649,7 +2721,6 @@
drop_capabilities(AID_SYSTEM);
run_profman_merge(profiles_fd, snapshot_fd, &apk_fds);
- exit(42); /* only get here on exec failure */
}
/* parent */
@@ -2713,7 +2784,6 @@
run_profman_copy_and_update(std::move(dex_metadata_fd),
std::move(ref_profile_fd),
std::move(apk_fd));
- exit(42); /* only get here on exec failure */
}
/* parent */
diff --git a/cmds/installd/dexopt.h b/cmds/installd/dexopt.h
index 62f9467..bb6fab3 100644
--- a/cmds/installd/dexopt.h
+++ b/cmds/installd/dexopt.h
@@ -106,7 +106,7 @@
int dexopt_needed, const char* oat_dir, int dexopt_flags, const char* compiler_filter,
const char* volume_uuid, const char* class_loader_context, const char* se_info,
bool downgrade, int target_sdk_version, const char* profile_name,
- const char* dexMetadataPath, const char* compilation_reason);
+ const char* dexMetadataPath, const char* compilation_reason, std::string* error_msg);
bool calculate_oat_file_path_default(char path[PKG_PATH_MAX], const char *oat_dir,
const char *apk_path, const char *instruction_set);
diff --git a/cmds/installd/dexopt_return_codes.h b/cmds/installd/dexopt_return_codes.h
new file mode 100644
index 0000000..bbecfa4
--- /dev/null
+++ b/cmds/installd/dexopt_return_codes.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dex2oat_return_codes.h>
+
+namespace android {
+namespace installd {
+
+// Constants for exit codes that installd code emits. These are failure situations before calling
+// any tools, e.g., in validation, and must not overlap with the exit codes of tools, so they
+// can be distinguished.
+enum DexoptReturnCodes : int {
+ kSetGid = 64,
+ kSetUid = 65,
+ kCapSet = 66,
+ kFlock = 67,
+ kProfmanExec = 68,
+ kSetSchedPolicy = 70,
+ kSetPriority = 71,
+ kDex2oatExec = 72,
+ kInstructionSetLength = 73,
+ kHashValidatePath = 74,
+ kHashOpenPath = 75,
+ kHashReadDex = 76,
+ kHashWrite = 77,
+};
+
+inline const char* get_installd_return_code_name(DexoptReturnCodes code) {
+ switch (code) {
+ case kSetGid:
+ return "setgid";
+ case kSetUid:
+ return "setuid";
+ case kCapSet:
+ return "capset";
+ case kFlock:
+ return "flock";
+ case kProfmanExec:
+ return "exec(profman)";
+ case kSetSchedPolicy:
+ return "setschedpolicy";
+ case kSetPriority:
+ return "setpriority";
+ case kDex2oatExec:
+ return "exec(dex2oat)";
+ case kInstructionSetLength:
+ return "instruction-set-length";
+ case kHashValidatePath:
+ return "hash(validate-path)";
+ case kHashOpenPath:
+ return "hash(open-path)";
+ case kHashReadDex:
+ return "hash(read-dex)";
+ case kHashWrite:
+ return "hash(write)";
+ }
+ return nullptr;
+}
+
+inline const char* get_dex2oat_return_code_name(art::dex2oat::ReturnCode code) {
+ switch (code) {
+ case art::dex2oat::ReturnCode::kNoFailure:
+ return "dex2oat success";
+ case art::dex2oat::ReturnCode::kOther:
+ return "unspecified dex2oat error";
+ case art::dex2oat::ReturnCode::kCreateRuntime:
+ return "dex2oat failed to create a runtime";
+ }
+ return nullptr;
+}
+
+// Get some slightly descriptive string for the return code. Handles both DexoptReturnCodes (local
+// exit codes) as well as art::dex2oat::ReturnCode.
+inline const char* get_return_code_name(int code) {
+ // Try to enforce non-overlap (see comment on DexoptReturnCodes)
+ // TODO: How could switch-case checks be used to enforce completeness?
+ switch (code) {
+ case kSetGid:
+ case kSetUid:
+ case kCapSet:
+ case kFlock:
+ case kProfmanExec:
+ case kSetSchedPolicy:
+ case kSetPriority:
+ case kDex2oatExec:
+ case kInstructionSetLength:
+ case kHashValidatePath:
+ case kHashOpenPath:
+ case kHashReadDex:
+ case kHashWrite:
+ break;
+ case static_cast<int>(art::dex2oat::ReturnCode::kNoFailure):
+ case static_cast<int>(art::dex2oat::ReturnCode::kOther):
+ case static_cast<int>(art::dex2oat::ReturnCode::kCreateRuntime):
+ break;
+ }
+ const char* value = get_installd_return_code_name(static_cast<DexoptReturnCodes>(code));
+ if (value != nullptr) {
+ return value;
+ }
+ value = get_dex2oat_return_code_name(static_cast<art::dex2oat::ReturnCode>(code));
+ return value;
+}
+
+} // namespace installd
+} // namespace android
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 76edb4c..c1a1202 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -569,6 +569,7 @@
// Run dexopt with the parameters of parameters_.
// TODO(calin): embed the profile name in the parameters.
int Dexopt() {
+ std::string dummy;
return dexopt(parameters_.apk_path,
parameters_.uid,
parameters_.pkgName,
@@ -584,7 +585,8 @@
parameters_.target_sdk_version,
parameters_.profile_name,
parameters_.dex_metadata_path,
- parameters_.compilation_reason);
+ parameters_.compilation_reason,
+ &dummy);
}
int RunPreopt() {
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index d640558..668e604 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -249,7 +249,7 @@
void CompileSecondaryDex(const std::string& path, int32_t dex_storage_flag,
bool should_binder_call_succeed, bool should_dex_be_compiled = true,
- int32_t uid = -1) {
+ /*out */ binder::Status* binder_result = nullptr, int32_t uid = -1) {
if (uid == -1) {
uid = kTestAppUid;
}
@@ -290,6 +290,9 @@
ASSERT_EQ(expected_access, access(odex.c_str(), R_OK));
ASSERT_EQ(expected_access, access(vdex.c_str(), R_OK));
ASSERT_EQ(-1, access(art.c_str(), R_OK)); // empty profiles do not generate an image.
+ if (binder_result != nullptr) {
+ *binder_result = result;
+ }
}
void reconcile_secondary_dex(const std::string& path, int32_t storage_flag,
@@ -335,10 +338,18 @@
const char* oat_dir,
int32_t uid,
int32_t dexopt_needed,
+ binder::Status* binder_result = nullptr,
const char* dm_path = nullptr,
bool downgrade = false) {
- return CompilePrimaryDex(
- compiler_filter, dex_flags, oat_dir, uid, dexopt_needed, dm_path, downgrade, true);
+ CompilePrimaryDex(compiler_filter,
+ dex_flags,
+ oat_dir,
+ uid,
+ dexopt_needed,
+ dm_path,
+ downgrade,
+ true,
+ binder_result);
}
void CompilePrimaryDexFail(std::string compiler_filter,
@@ -346,10 +357,18 @@
const char* oat_dir,
int32_t uid,
int32_t dexopt_needed,
+ binder::Status* binder_result = nullptr,
const char* dm_path = nullptr,
bool downgrade = false) {
- return CompilePrimaryDex(
- compiler_filter, dex_flags, oat_dir, uid, dexopt_needed, dm_path, downgrade, false);
+ CompilePrimaryDex(compiler_filter,
+ dex_flags,
+ oat_dir,
+ uid,
+ dexopt_needed,
+ dm_path,
+ downgrade,
+ false,
+ binder_result);
}
void CompilePrimaryDex(std::string compiler_filter,
@@ -359,7 +378,8 @@
int32_t dexopt_needed,
const char* dm_path,
bool downgrade,
- bool should_binder_call_succeed) {
+ bool should_binder_call_succeed,
+ /*out */ binder::Status* binder_result) {
std::unique_ptr<std::string> package_name_ptr(new std::string(package_name_));
std::unique_ptr<std::string> out_path(
oat_dir == nullptr ? nullptr : new std::string(oat_dir));
@@ -400,6 +420,9 @@
ASSERT_EQ(should_binder_call_succeed, result.isOk()) << result.toString8().c_str();
if (!should_binder_call_succeed) {
+ if (binder_result != nullptr) {
+ *binder_result = result;
+ }
return;
}
// Check the access to the compiler output.
@@ -417,6 +440,9 @@
if (compiler_filter == "speed-profile") {
CheckFileAccess(art, kSystemUid, uid, mode);
}
+ if (binder_result != nullptr) {
+ *binder_result = result;
+ }
}
std::string GetPrimaryDexArtifact(const char* oat_dir,
@@ -462,26 +488,36 @@
TEST_F(DexoptTest, DexoptSecondaryDoesNotExist) {
LOG(INFO) << "DexoptSecondaryDoesNotExist";
// If the file validates but does not exist we do not treat it as an error.
+ binder::Status status;
CompileSecondaryDex(secondary_dex_ce_ + "not.there", DEXOPT_STORAGE_CE,
- /*binder_ok*/ true, /*compile_ok*/ false);
+ /*binder_ok*/ true, /*compile_ok*/ false, &status);
+ EXPECT_STREQ(status.toString8().c_str(), "No error");
}
TEST_F(DexoptTest, DexoptSecondaryStorageValidationError) {
LOG(INFO) << "DexoptSecondaryStorageValidationError";
+ binder::Status status;
CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_DE,
- /*binder_ok*/ false, /*compile_ok*/ false);
+ /*binder_ok*/ false, /*compile_ok*/ false, &status);
+ EXPECT_STREQ(status.toString8().c_str(),
+ "Status(-8): '-1: Dexoptanalyzer path validation failed'");
}
TEST_F(DexoptTest, DexoptSecondaryAppOwnershipValidationError) {
LOG(INFO) << "DexoptSecondaryAppOwnershipValidationError";
+ binder::Status status;
CompileSecondaryDex("/data/data/random.app/secondary.jar", DEXOPT_STORAGE_CE,
- /*binder_ok*/ false, /*compile_ok*/ false);
+ /*binder_ok*/ false, /*compile_ok*/ false, &status);
+ EXPECT_STREQ(status.toString8().c_str(),
+ "Status(-8): '-1: Dexoptanalyzer path validation failed'");
}
TEST_F(DexoptTest, DexoptSecondaryAcessViaDifferentUidError) {
LOG(INFO) << "DexoptSecondaryAcessViaDifferentUidError";
+ binder::Status status;
CompileSecondaryDex(secondary_dex_ce_, DEXOPT_STORAGE_CE,
- /*binder_ok*/ false, /*compile_ok*/ false, kSystemUid);
+ /*binder_ok*/ false, /*compile_ok*/ false, &status, kSystemUid);
+ EXPECT_STREQ(status.toString8().c_str(), "Status(-8): '-1: Dexoptanalyzer open zip failed'");
}
TEST_F(DexoptTest, DexoptPrimaryPublic) {
@@ -495,11 +531,16 @@
TEST_F(DexoptTest, DexoptPrimaryFailedInvalidFilter) {
LOG(INFO) << "DexoptPrimaryFailedInvalidFilter";
+ binder::Status status;
CompilePrimaryDexFail("awesome-filter",
DEXOPT_IDLE_BACKGROUND_JOB | DEXOPT_PUBLIC,
app_oat_dir_.c_str(),
kTestAppGid,
- DEX2OAT_FROM_SCRATCH);
+ DEX2OAT_FROM_SCRATCH,
+ &status);
+ EXPECT_STREQ(status.toString8().c_str(),
+ "Status(-8): \'256: Dex2oat invocation for "
+ "/data/app/com.installd.test.dexopt/base.jar failed: unspecified dex2oat error'");
}
TEST_F(DexoptTest, DexoptPrimaryProfileNonPublic) {
diff --git a/libs/input/VelocityTracker.cpp b/libs/input/VelocityTracker.cpp
index e0d2113..c07a812 100644
--- a/libs/input/VelocityTracker.cpp
+++ b/libs/input/VelocityTracker.cpp
@@ -1090,7 +1090,7 @@
static float calculateImpulseVelocity(const nsecs_t* t, const float* x, size_t count) {
// The input should be in reversed time order (most recent sample at index i=0)
// t[i] is in nanoseconds, but due to FP arithmetic, convert to seconds inside this function
- static constexpr float NANOS_PER_SECOND = 1E-9;
+ static constexpr float SECONDS_PER_NANO = 1E-9;
if (count < 2) {
return 0; // if 0 or 1 points, velocity is zero
@@ -1103,7 +1103,7 @@
ALOGE("Events have identical time stamps t=%" PRId64 ", setting velocity = 0", t[0]);
return 0;
}
- return (x[1] - x[0]) / (NANOS_PER_SECOND * (t[1] - t[0]));
+ return (x[1] - x[0]) / (SECONDS_PER_NANO * (t[1] - t[0]));
}
// Guaranteed to have at least 3 points here
float work = 0;
@@ -1113,7 +1113,7 @@
continue;
}
float vprev = kineticEnergyToVelocity(work); // v[i-1]
- float vcurr = (x[i] - x[i-1]) / (NANOS_PER_SECOND * (t[i] - t[i-1])); // v[i]
+ float vcurr = (x[i] - x[i-1]) / (SECONDS_PER_NANO * (t[i] - t[i-1])); // v[i]
work += (vcurr - vprev) * fabsf(vcurr);
if (i == count - 1) {
work *= 0.5; // initial condition, case 2) above
diff --git a/libs/ui/DebugUtils.cpp b/libs/ui/DebugUtils.cpp
index 2d72944..17ebf80 100644
--- a/libs/ui/DebugUtils.cpp
+++ b/libs/ui/DebugUtils.cpp
@@ -74,7 +74,7 @@
case HAL_DATASPACE_SRGB:
return std::string("(deprecated) sRGB");
- case HAL_DATASPACE_V0_BT709:
+ case HAL_DATASPACE_BT709:
return std::string("(deprecated) BT709");
case HAL_DATASPACE_ARBITRARY:
@@ -84,7 +84,7 @@
// Fallthrough
default:
return android::base::StringPrintf("Unknown deprecated dataspace code %d",
- dataspaceSelect);
+ dataspace);
}
}
@@ -98,7 +98,7 @@
case HAL_DATASPACE_JFIF:
case HAL_DATASPACE_BT601_625:
case HAL_DATASPACE_BT601_525:
- case HAL_DATASPACE_V0_BT709:
+ case HAL_DATASPACE_BT709:
return std::string("SMPTE_170M");
case HAL_DATASPACE_SRGB_LINEAR:
@@ -159,8 +159,8 @@
case HAL_DATASPACE_BT601_625:
case HAL_DATASPACE_BT601_525:
- case HAL_DATASPACE_V0_BT709:
- return std::string("Limited range)");
+ case HAL_DATASPACE_BT709:
+ return std::string("Limited range");
case HAL_DATASPACE_ARBITRARY:
case HAL_DATASPACE_UNKNOWN:
diff --git a/services/inputflinger/InputDispatcher.cpp b/services/inputflinger/InputDispatcher.cpp
index 86492fd..c3f4f58 100644
--- a/services/inputflinger/InputDispatcher.cpp
+++ b/services/inputflinger/InputDispatcher.cpp
@@ -52,6 +52,7 @@
#include <time.h>
#include <unistd.h>
+#include <android-base/chrono_utils.h>
#include <android-base/stringprintf.h>
#include <log/log.h>
#include <utils/Trace.h>
@@ -69,28 +70,32 @@
// Default input dispatching timeout if there is no focused application or paused window
// from which to determine an appropriate dispatching timeout.
-const nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec
+constexpr nsecs_t DEFAULT_INPUT_DISPATCHING_TIMEOUT = 5000 * 1000000LL; // 5 sec
// Amount of time to allow for all pending events to be processed when an app switch
// key is on the way. This is used to preempt input dispatch and drop input events
// when an application takes too long to respond and the user has pressed an app switch key.
-const nsecs_t APP_SWITCH_TIMEOUT = 500 * 1000000LL; // 0.5sec
+constexpr nsecs_t APP_SWITCH_TIMEOUT = 500 * 1000000LL; // 0.5sec
// Amount of time to allow for an event to be dispatched (measured since its eventTime)
// before considering it stale and dropping it.
-const nsecs_t STALE_EVENT_TIMEOUT = 10000 * 1000000LL; // 10sec
+constexpr nsecs_t STALE_EVENT_TIMEOUT = 10000 * 1000000LL; // 10sec
// Amount of time to allow touch events to be streamed out to a connection before requiring
// that the first event be finished. This value extends the ANR timeout by the specified
// amount. For example, if streaming is allowed to get ahead by one second relative to the
// queue of waiting unfinished events, then ANRs will similarly be delayed by one second.
-const nsecs_t STREAM_AHEAD_EVENT_TIMEOUT = 500 * 1000000LL; // 0.5sec
+constexpr nsecs_t STREAM_AHEAD_EVENT_TIMEOUT = 500 * 1000000LL; // 0.5sec
// Log a warning when an event takes longer than this to process, even if an ANR does not occur.
-const nsecs_t SLOW_EVENT_PROCESSING_WARNING_TIMEOUT = 2000 * 1000000LL; // 2sec
+constexpr nsecs_t SLOW_EVENT_PROCESSING_WARNING_TIMEOUT = 2000 * 1000000LL; // 2sec
+
+// Log a warning when an interception call takes longer than this to process.
+constexpr std::chrono::milliseconds SLOW_INTERCEPTION_THRESHOLD = 50ms;
// Number of recent events to keep for debugging purposes.
-const size_t RECENT_QUEUE_MAX_SIZE = 10;
+constexpr size_t RECENT_QUEUE_MAX_SIZE = 10;
+
static inline nsecs_t now() {
return systemTime(SYSTEM_TIME_MONOTONIC);
@@ -2448,7 +2453,12 @@
flags, keyCode, args->scanCode, metaState, 0,
args->downTime, args->eventTime);
+ android::base::Timer t;
mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
+ if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
+ ALOGW("Excessive delay in interceptKeyBeforeQueueing; took %s ms",
+ std::to_string(t.duration().count()).c_str());
+ }
bool needWake;
{ // acquire lock
@@ -2517,7 +2527,13 @@
uint32_t policyFlags = args->policyFlags;
policyFlags |= POLICY_FLAG_TRUSTED;
+
+ android::base::Timer t;
mPolicy->interceptMotionBeforeQueueing(args->eventTime, /*byref*/ policyFlags);
+ if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
+ ALOGW("Excessive delay in interceptMotionBeforeQueueing; took %s ms",
+ std::to_string(t.duration().count()).c_str());
+ }
bool needWake;
{ // acquire lock
@@ -2629,7 +2645,12 @@
}
if (!(policyFlags & POLICY_FLAG_FILTERED)) {
+ android::base::Timer t;
mPolicy->interceptKeyBeforeQueueing(keyEvent, /*byref*/ policyFlags);
+ if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
+ ALOGW("Excessive delay in interceptKeyBeforeQueueing; took %s ms",
+ std::to_string(t.duration().count()).c_str());
+ }
}
mLock.lock();
@@ -2654,7 +2675,12 @@
if (!(policyFlags & POLICY_FLAG_FILTERED)) {
nsecs_t eventTime = motionEvent->getEventTime();
+ android::base::Timer t;
mPolicy->interceptMotionBeforeQueueing(eventTime, /*byref*/ policyFlags);
+ if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
+ ALOGW("Excessive delay in interceptMotionBeforeQueueing; took %s ms",
+ std::to_string(t.duration().count()).c_str());
+ }
}
mLock.lock();
@@ -3540,8 +3566,13 @@
mLock.unlock();
+ android::base::Timer t;
nsecs_t delay = mPolicy->interceptKeyBeforeDispatching(commandEntry->inputWindowHandle,
&event, entry->policyFlags);
+ if (t.duration() > SLOW_INTERCEPTION_THRESHOLD) {
+ ALOGW("Excessive delay in interceptKeyBeforeDispatching; took %s ms",
+ std::to_string(t.duration().count()).c_str());
+ }
mLock.lock();