Merge "[SurfaceFlinger] Push atoms on janky events"
diff --git a/cmds/installd/CacheTracker.cpp b/cmds/installd/CacheTracker.cpp
index 8b868fb..a61f6bf 100644
--- a/cmds/installd/CacheTracker.cpp
+++ b/cmds/installd/CacheTracker.cpp
@@ -75,8 +75,7 @@
bool CacheTracker::loadQuotaStats() {
int cacheGid = multiuser_get_cache_gid(mUserId, mAppId);
- int extCacheGid = multiuser_get_ext_cache_gid(mUserId, mAppId);
- if (IsQuotaSupported(mUuid) && cacheGid != -1 && extCacheGid != -1) {
+ if (IsQuotaSupported(mUuid) && cacheGid != -1) {
int64_t space;
if ((space = GetOccupiedSpaceForGid(mUuid, cacheGid)) != -1) {
cacheUsed += space;
@@ -84,7 +83,7 @@
return false;
}
- if ((space = GetOccupiedSpaceForGid(mUuid, extCacheGid)) != -1) {
+ if ((space = get_occupied_app_cache_space_external(mUuid, mUserId, mAppId)) != -1) {
cacheUsed += space;
} else {
return false;
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 02e5d9b..c9b51b5 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -54,6 +54,7 @@
#include <log/log.h> // TODO: Move everything to base/logging.
#include <logwrap/logwrap.h>
#include <private/android_filesystem_config.h>
+#include <private/android_projectid_config.h>
#include <selinux/android.h>
#include <system/thread_defs.h>
#include <utils/Trace.h>
@@ -1487,8 +1488,8 @@
static void collectQuotaStats(const std::string& uuid, int32_t userId,
int32_t appId, struct stats* stats, struct stats* extStats) {
int64_t space;
+ uid_t uid = multiuser_get_uid(userId, appId);
if (stats != nullptr) {
- uid_t uid = multiuser_get_uid(userId, appId);
if ((space = GetOccupiedSpaceForUid(uuid, uid)) != -1) {
stats->dataSize += space;
}
@@ -1509,20 +1510,44 @@
}
if (extStats != nullptr) {
- int extGid = multiuser_get_ext_gid(userId, appId);
- if (extGid != -1) {
- if ((space = GetOccupiedSpaceForGid(uuid, extGid)) != -1) {
- extStats->dataSize += space;
+ static const bool supportsSdCardFs = supports_sdcardfs();
+ space = get_occupied_app_space_external(uuid, userId, appId);
+
+ if (space != -1) {
+ extStats->dataSize += space;
+ if (!supportsSdCardFs && stats != nullptr) {
+ // On devices without sdcardfs, if internal and external are on
+ // the same volume, a uid such as u0_a123 is used for
+ // application dirs on both internal and external storage;
+ // therefore, substract that amount from internal to make sure
+ // we don't count it double.
+ stats->dataSize -= space;
}
}
- int extCacheGid = multiuser_get_ext_cache_gid(userId, appId);
- if (extCacheGid != -1) {
- if ((space = GetOccupiedSpaceForGid(uuid, extCacheGid)) != -1) {
- extStats->dataSize += space;
- extStats->cacheSize += space;
+ space = get_occupied_app_cache_space_external(uuid, userId, appId);
+ if (space != -1) {
+ extStats->dataSize += space; // cache counts for "data"
+ extStats->cacheSize += space;
+ if (!supportsSdCardFs && stats != nullptr) {
+ // On devices without sdcardfs, if internal and external are on
+ // the same volume, a uid such as u0_a123 is used for both
+ // internal and external storage; therefore, substract that
+ // amount from internal to make sure we don't count it double.
+ stats->dataSize -= space;
}
}
+
+ if (!supportsSdCardFs && stats != nullptr) {
+ // On devices without sdcardfs, the UID of OBBs on external storage
+ // matches the regular app UID (eg u0_a123); therefore, to avoid
+ // OBBs being include in stats->dataSize, compute the OBB size for
+ // this app, and substract it from the size reported on internal
+ // storage
+ long obbProjectId = uid - AID_APP_START + PROJECT_ID_EXT_OBB_START;
+ int64_t appObbSize = GetOccupiedSpaceForProjectId(uuid, obbProjectId);
+ stats->dataSize -= appObbSize;
+ }
}
}
@@ -1771,6 +1796,106 @@
return ok();
}
+struct external_sizes {
+ int64_t audioSize;
+ int64_t videoSize;
+ int64_t imageSize;
+ int64_t totalSize; // excludes OBBs (Android/obb), but includes app data + cache
+ int64_t obbSize;
+};
+
+#define PER_USER_RANGE 100000
+
+static long getProjectIdForUser(int userId, long projectId) {
+ return userId * PER_USER_RANGE + projectId;
+}
+
+static external_sizes getExternalSizesForUserWithQuota(const std::string& uuid, int32_t userId, const std::vector<int32_t>& appIds) {
+ struct external_sizes sizes = {};
+ int64_t space;
+
+ if (supports_sdcardfs()) {
+ uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW);
+ if ((space = GetOccupiedSpaceForUid(uuid, uid)) != -1) {
+ sizes.totalSize = space;
+ }
+
+ gid_t audioGid = multiuser_get_uid(userId, AID_MEDIA_AUDIO);
+ if ((space = GetOccupiedSpaceForGid(uuid, audioGid)) != -1) {
+ sizes.audioSize = space;
+ }
+
+ gid_t videoGid = multiuser_get_uid(userId, AID_MEDIA_VIDEO);
+ if ((space = GetOccupiedSpaceForGid(uuid, videoGid)) != -1) {
+ sizes.videoSize = space;
+ }
+
+ gid_t imageGid = multiuser_get_uid(userId, AID_MEDIA_IMAGE);
+ if ((space = GetOccupiedSpaceForGid(uuid, imageGid)) != -1) {
+ sizes.imageSize = space;
+ }
+
+ if ((space = GetOccupiedSpaceForGid(uuid, AID_MEDIA_OBB)) != -1) {
+ sizes.obbSize = space;
+ }
+ } else {
+ int64_t totalSize = 0;
+ long defaultProjectId = getProjectIdForUser(userId, PROJECT_ID_EXT_DEFAULT);
+ if ((space = GetOccupiedSpaceForProjectId(uuid, defaultProjectId)) != -1) {
+ // This is all files that are not audio/video/images, excluding
+ // OBBs and app-private data
+ totalSize += space;
+ }
+
+ long audioProjectId = getProjectIdForUser(userId, PROJECT_ID_EXT_MEDIA_AUDIO);
+ if ((space = GetOccupiedSpaceForProjectId(uuid, audioProjectId)) != -1) {
+ sizes.audioSize = space;
+ totalSize += space;
+ }
+
+ long videoProjectId = getProjectIdForUser(userId, PROJECT_ID_EXT_MEDIA_VIDEO);
+ if ((space = GetOccupiedSpaceForProjectId(uuid, videoProjectId)) != -1) {
+ sizes.videoSize = space;
+ totalSize += space;
+ }
+
+ long imageProjectId = getProjectIdForUser(userId, PROJECT_ID_EXT_MEDIA_IMAGE);
+ if ((space = GetOccupiedSpaceForProjectId(uuid, imageProjectId)) != -1) {
+ sizes.imageSize = space;
+ totalSize += space;
+ }
+
+ int64_t totalAppDataSize = 0;
+ int64_t totalAppCacheSize = 0;
+ int64_t totalAppObbSize = 0;
+ for (auto appId : appIds) {
+ if (appId >= AID_APP_START) {
+ // App data
+ uid_t uid = multiuser_get_uid(userId, appId);
+ long projectId = uid - AID_APP_START + PROJECT_ID_EXT_DATA_START;
+ totalAppDataSize += GetOccupiedSpaceForProjectId(uuid, projectId);
+
+ // App cache
+ long cacheProjectId = uid - AID_APP_START + PROJECT_ID_EXT_CACHE_START;
+ totalAppCacheSize += GetOccupiedSpaceForProjectId(uuid, cacheProjectId);
+
+ // App OBBs
+ long obbProjectId = uid - AID_APP_START + PROJECT_ID_EXT_OBB_START;
+ totalAppObbSize += GetOccupiedSpaceForProjectId(uuid, obbProjectId);
+ }
+ }
+ // Total size should include app data + cache
+ totalSize += totalAppDataSize;
+ totalSize += totalAppCacheSize;
+ sizes.totalSize = totalSize;
+
+ // Only OBB is separate
+ sizes.obbSize = totalAppObbSize;
+ }
+
+ return sizes;
+}
+
binder::Status InstalldNativeService::getUserSize(const std::unique_ptr<std::string>& uuid,
int32_t userId, int32_t flags, const std::vector<int32_t>& appIds,
std::vector<int64_t>* _aidl_return) {
@@ -1799,14 +1924,6 @@
}
if (flags & FLAG_USE_QUOTA) {
- int64_t space;
-
- ATRACE_BEGIN("obb");
- if ((space = GetOccupiedSpaceForGid(uuidString, AID_MEDIA_OBB)) != -1) {
- extStats.codeSize += space;
- }
- ATRACE_END();
-
ATRACE_BEGIN("code");
calculate_tree_size(create_data_app_path(uuid_), &stats.codeSize, -1, -1, true);
ATRACE_END();
@@ -1828,10 +1945,9 @@
}
ATRACE_BEGIN("external");
- uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW);
- if ((space = GetOccupiedSpaceForUid(uuidString, uid)) != -1) {
- extStats.dataSize += space;
- }
+ auto sizes = getExternalSizesForUserWithQuota(uuidString, userId, appIds);
+ extStats.dataSize += sizes.totalSize;
+ extStats.codeSize += sizes.obbSize;
ATRACE_END();
if (!uuid) {
@@ -1842,13 +1958,11 @@
-1, -1, true);
ATRACE_END();
}
-
ATRACE_BEGIN("quota");
int64_t dataSize = extStats.dataSize;
for (auto appId : appIds) {
if (appId >= AID_APP_START) {
collectQuotaStats(uuidString, userId, appId, &stats, &extStats);
-
#if MEASURE_DEBUG
// Sleep to make sure we don't lose logs
usleep(1);
@@ -1944,29 +2058,13 @@
}
if (flags & FLAG_USE_QUOTA) {
- int64_t space;
-
ATRACE_BEGIN("quota");
- uid_t uid = multiuser_get_uid(userId, AID_MEDIA_RW);
- if ((space = GetOccupiedSpaceForUid(uuidString, uid)) != -1) {
- totalSize = space;
- }
-
- gid_t audioGid = multiuser_get_uid(userId, AID_MEDIA_AUDIO);
- if ((space = GetOccupiedSpaceForGid(uuidString, audioGid)) != -1) {
- audioSize = space;
- }
- gid_t videoGid = multiuser_get_uid(userId, AID_MEDIA_VIDEO);
- if ((space = GetOccupiedSpaceForGid(uuidString, videoGid)) != -1) {
- videoSize = space;
- }
- gid_t imageGid = multiuser_get_uid(userId, AID_MEDIA_IMAGE);
- if ((space = GetOccupiedSpaceForGid(uuidString, imageGid)) != -1) {
- imageSize = space;
- }
- if ((space = GetOccupiedSpaceForGid(uuidString, AID_MEDIA_OBB)) != -1) {
- obbSize = space;
- }
+ auto sizes = getExternalSizesForUserWithQuota(uuidString, userId, appIds);
+ totalSize = sizes.totalSize;
+ audioSize = sizes.audioSize;
+ videoSize = sizes.videoSize;
+ imageSize = sizes.imageSize;
+ obbSize = sizes.obbSize;
ATRACE_END();
ATRACE_BEGIN("apps");
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 042d69e..c47df52 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -26,6 +26,7 @@
#include <sys/xattr.h>
#include <sys/statvfs.h>
+#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/strings.h>
#include <android-base/stringprintf.h>
@@ -34,9 +35,11 @@
#include <cutils/properties.h>
#include <log/log.h>
#include <private/android_filesystem_config.h>
+#include <private/android_projectid_config.h>
#include "dexopt_return_codes.h"
#include "globals.h" // extern variables.
+#include "QuotaUtils.h"
#ifndef LOG_TAG
#define LOG_TAG "installd"
@@ -1057,6 +1060,51 @@
return 0;
}
+static const char* kProcFilesystems = "/proc/filesystems";
+bool supports_sdcardfs() {
+ std::string supported;
+ if (!android::base::ReadFileToString(kProcFilesystems, &supported)) {
+ PLOG(ERROR) << "Failed to read supported filesystems";
+ return false;
+ }
+ return supported.find("sdcardfs\n") != std::string::npos;
+}
+
+int64_t get_occupied_app_space_external(const std::string& uuid, int32_t userId, int32_t appId) {
+ static const bool supportsSdcardFs = supports_sdcardfs();
+
+ if (supportsSdcardFs) {
+ int extGid = multiuser_get_ext_gid(userId, appId);
+
+ if (extGid == -1) {
+ return -1;
+ }
+
+ return GetOccupiedSpaceForGid(uuid, extGid);
+ } else {
+ uid_t uid = multiuser_get_uid(userId, appId);
+ long projectId = uid - AID_APP_START + PROJECT_ID_EXT_DATA_START;
+ return GetOccupiedSpaceForProjectId(uuid, projectId);
+ }
+}
+int64_t get_occupied_app_cache_space_external(const std::string& uuid, int32_t userId, int32_t appId) {
+ static const bool supportsSdcardFs = supports_sdcardfs();
+
+ if (supportsSdcardFs) {
+ int extCacheGid = multiuser_get_ext_cache_gid(userId, appId);
+
+ if (extCacheGid == -1) {
+ return -1;
+ }
+
+ return GetOccupiedSpaceForGid(uuid, extCacheGid);
+ } else {
+ uid_t uid = multiuser_get_uid(userId, appId);
+ long projectId = uid - AID_APP_START + PROJECT_ID_EXT_CACHE_START;
+ return GetOccupiedSpaceForProjectId(uuid, projectId);
+ }
+}
+
// Collect all non empty profiles from the given directory and puts then into profile_paths.
// The profiles are identified based on PROFILE_EXT extension.
// If a subdirectory or profile file cannot be opened the method logs a warning and moves on.
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 01126c0..549fc6c 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -153,6 +153,10 @@
int prepare_app_cache_dir(const std::string& parent, const char* name, mode_t target_mode,
uid_t uid, gid_t gid);
+bool supports_sdcardfs();
+int64_t get_occupied_app_space_external(const std::string& uuid, int32_t userId, int32_t appId);
+int64_t get_occupied_app_cache_space_external(const std::string& uuid, int32_t userId, int32_t appId);
+
// Collect all non empty profiles from the global profile directory and
// put then into profile_paths. The profiles are identified based on PROFILE_EXT extension.
// If a subdirectory or profile file cannot be opened the method logs a warning and moves on.
diff --git a/include/android/CoolingDevice.h b/include/android/CoolingDevice.h
new file mode 100644
index 0000000..2f366be
--- /dev/null
+++ b/include/android/CoolingDevice.h
@@ -0,0 +1,49 @@
+/*
+ * 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_OS_COOLINGDEVICE_H
+#define ANDROID_OS_COOLINGDEVICE_H
+
+#include <binder/Parcelable.h>
+#include <utils/RefBase.h>
+
+namespace android {
+namespace os {
+
+/**
+ * CoolingDevice is a structure to encapsulate cooling device status.
+ */
+struct CoolingDevice : public android::Parcelable {
+ /** Current throttle state of the cooling device. */
+ float mValue;
+ /** A cooling device type from ThermalHAL */
+ uint32_t mType;
+ /** Name of this cooling device */
+ String16 mName;
+
+ CoolingDevice()
+ : mValue(0.0f),
+ mType(0),
+ mName("") {
+ }
+ virtual status_t readFromParcel(const android::Parcel* parcel) override;
+ virtual status_t writeToParcel(android::Parcel* parcel) const override;
+};
+
+} // namespace os
+} // namespace android
+
+#endif /* ANDROID_OS_COOLINGDEVICE_H */
diff --git a/include/android/Temperature.h b/include/android/Temperature.h
new file mode 100644
index 0000000..2e68ec4
--- /dev/null
+++ b/include/android/Temperature.h
@@ -0,0 +1,53 @@
+/*
+ * 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_OS_TEMPERATURE_H
+#define ANDROID_OS_TEMPERATURE_H
+
+#include <binder/Parcelable.h>
+#include <utils/RefBase.h>
+
+namespace android {
+namespace os {
+
+/**
+ * Temperature is a structure to encapsulate temperature status.
+ */
+struct Temperature : public android::Parcelable {
+ /** Temperature value */
+ float mValue;
+ /** A Temperature type from ThermalHAL */
+ int32_t mType;
+ /** Name of this Temperature */
+ String16 mName;
+ /** The level of the sensor is currently in throttling */
+ int32_t mStatus;
+
+ Temperature()
+ : mValue(0.0f),
+ mType(0),
+ mName(""),
+ mStatus(0) {
+ }
+
+ virtual status_t readFromParcel(const android::Parcel* parcel) override;
+ virtual status_t writeToParcel(android::Parcel* parcel) const override;
+};
+
+} // namespace os
+} // namespace android
+
+#endif /* ANDROID_OS_TEMPERATURE_H */
diff --git a/include/android/thermal.h b/include/android/thermal.h
new file mode 100644
index 0000000..0f4b4d9
--- /dev/null
+++ b/include/android/thermal.h
@@ -0,0 +1,182 @@
+/*
+ * 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.
+ */
+
+/**
+ * @addtogroup Thermal
+ * @{
+ */
+
+/**
+ * @file thermal.h
+ */
+
+#ifndef _ANDROID_THERMAL_H
+#define _ANDROID_THERMAL_H
+
+#include <sys/cdefs.h>
+
+/******************************************************************
+ *
+ * IMPORTANT NOTICE:
+ *
+ * This file is part of Android's set of stable system headers
+ * exposed by the Android NDK (Native Development Kit).
+ *
+ * Third-party source AND binary code relies on the definitions
+ * here to be FROZEN ON ALL UPCOMING PLATFORM RELEASES.
+ *
+ * - DO NOT MODIFY ENUMS (EXCEPT IF YOU ADD NEW 32-BIT VALUES)
+ * - DO NOT MODIFY CONSTANTS OR FUNCTIONAL MACROS
+ * - DO NOT CHANGE THE SIGNATURE OF FUNCTIONS IN ANY WAY
+ * - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES
+ */
+
+/*
+ * Structures and functions to access thermal status and register/unregister
+ * thermal status listener in native code.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#if !defined(__INTRODUCED_IN)
+#define __INTRODUCED_IN(30) /* Introduced in API level 30 */
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if __ANDROID_API__ >= 30
+
+enum AThermalStatus {
+ /** Error in thermal status. */
+ ATHERMAL_STATUS_ERROR = -1,
+ /** Not under throttling. */
+ ATHERMAL_STATUS_NONE = 0,
+ /** Light throttling where UX is not impacted. */
+ ATHERMAL_STATUS_LIGHT = 1,
+ /** Moderate throttling where UX is not largely impacted. */
+ ATHERMAL_STATUS_MODERATE = 2,
+ /** Severe throttling where UX is largely impacted. */
+ ATHERMAL_STATUS_SEVERE = 3,
+ /** Platform has done everything to reduce power. */
+ ATHERMAL_STATUS_CRITICAL = 4,
+ /**
+ * Key components in platform are shutting down due to thermal condition.
+ * Device functionalities will be limited.
+ */
+ ATHERMAL_STATUS_EMERGENCY = 5,
+ /** Need shutdown immediately. */
+ ATHERMAL_STATUS_SHUTDOWN = 6,
+};
+
+/**
+ * An opaque type representing a handle to a thermal manager.
+ * An instance of thermal manager must be acquired prior to
+ * using thermal status APIs and must be released after use.
+ *
+ * <p>To use:<ul>
+ * <li>Create a new thermal manager instance by calling the
+ * {@link AThermal_acquireManager} function.</li>
+ * <li>Get current thermal status with
+ * {@link AThermal_getCurrentThermalStatus}.</li>
+ * <li>Register a thermal status listener with
+ * {@link AThermal_registerThermalStatusListener}.</li>
+ * <li>Unregister a thermal status listener with
+ * {@link AThermal_unregisterThermalStatusListener}.</li>
+ * <li>Release the thermal manager instance with
+ * {@link AThermal_releaseManager}.</li></ul></p>
+ *
+ */
+typedef struct AThermalManager AThermalManager;
+
+/**
+ * Prototype of the function that is called when thermal status changes.
+ * It's passed the updated thermal status as parameter, as well as the
+ * pointer provided by the client that registered a callback.
+ */
+typedef int (*AThermal_StatusCallback)(void *data, AThermalStatus status);
+
+/**
+ * Acquire an instance of the thermal manager. This must be freed using
+ * {@link AThermal_releaseManager}.
+ *
+ * @return manager instance on success, nullptr on failure.
+ */
+AThermalManager* AThermal_acquireManager();
+
+/**
+ * Release the thermal manager pointer acquired via
+ * {@link AThermal_acquireManager}.
+ *
+ * @param manager The manager to be released.
+ *
+ */
+void AThermal_releaseManager(AThermalManager *manager);
+
+/**
+ * Gets the current thermal status.
+ *
+ * @param manager The manager instance to use to query the thermal status.
+ * Acquired via {@link AThermal_acquireManager}.
+ *
+ * @return current thermal status, ATHERMAL_STATUS_ERROR on failure.
+*/
+AThermalStatus AThermal_getCurrentThermalStatus(AThermalManager *manager);
+
+/**
+ * Register the thermal status listener for thermal status change.
+ *
+ * @param manager The manager instance to use to register.
+ * Acquired via {@link AThermal_acquireManager}.
+ * @param callback The callback function to be called when thermal status updated.
+ * @param data The data pointer to be passed when callback is called.
+ *
+ * @return 0 on success
+ * EINVAL if the listener and data pointer were previously added and not removed.
+ * EPERM if the required permission is not held.
+ * EPIPE if communication with the system service has failed.
+ */
+int AThermal_registerThermalStatusListener(AThermalManager *manager,
+ AThermal_StatusCallback callback, void *data);
+
+/**
+ * Unregister the thermal status listener previously resgistered.
+ *
+ * @param manager The manager instance to use to unregister.
+ * Acquired via {@link AThermal_acquireManager}.
+ * @param callback The callback function to be called when thermal status updated.
+ * @param data The data pointer to be passed when callback is called.
+ *
+ * @return 0 on success
+ * EINVAL if the listener and data pointer were not previously added.
+ * EPERM if the required permission is not held.
+ * EPIPE if communication with the system service has failed.
+ */
+int AThermal_unregisterThermalStatusListener(AThermalManager *manager,
+ AThermal_StatusCallback callback, void *data);
+
+
+#endif // __ANDROID_API__ >= 30
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _ANDROID_THERMAL_H
+
+/** @} */
diff --git a/include/input/Input.h b/include/input/Input.h
index 14a7288..9e47318 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -266,6 +266,38 @@
const char* motionClassificationToString(MotionClassification classification);
/**
+ * Generator of unique numbers used to identify input events.
+ *
+ * Layout of ID:
+ * |--------------------------|---------------------------|
+ * | 2 bits for source | 30 bits for random number |
+ * |--------------------------|---------------------------|
+ */
+class IdGenerator {
+private:
+ static constexpr uint32_t SOURCE_SHIFT = 30;
+
+public:
+ // Used to divide integer space to ensure no conflict among these sources./
+ enum class Source : int32_t {
+ INPUT_READER = 0x0 << SOURCE_SHIFT,
+ INPUT_DISPATCHER = 0x1 << SOURCE_SHIFT,
+ OTHER = 0x3 << SOURCE_SHIFT, // E.g. app injected events
+ };
+ IdGenerator(Source source);
+
+ int32_t nextId() const;
+
+ // Extract source from given id.
+ static inline Source getSource(int32_t id) { return static_cast<Source>(SOURCE_MASK & id); }
+
+private:
+ const Source mSource;
+
+ static constexpr int32_t SOURCE_MASK = 0x3 << SOURCE_SHIFT;
+};
+
+/**
* Invalid value for cursor position. Used for non-mouse events, tests and injected events. Don't
* use it for direct comparison with any other value, because NaN isn't equal to itself according to
* IEEE 754. Use isnan() instead to check if a cursor position is valid.
@@ -365,6 +397,8 @@
virtual int32_t getType() const = 0;
+ inline int32_t getId() const { return mId; }
+
inline int32_t getDeviceId() const { return mDeviceId; }
inline uint32_t getSource() const { return mSource; }
@@ -377,11 +411,15 @@
inline std::array<uint8_t, 32> getHmac() const { return mHmac; }
+ static int32_t nextId();
+
protected:
- void initialize(int32_t deviceId, uint32_t source, int32_t displayId,
+ void initialize(int32_t id, int32_t deviceId, uint32_t source, int32_t displayId,
std::array<uint8_t, 32> hmac);
+
void initialize(const InputEvent& from);
+ int32_t mId;
int32_t mDeviceId;
uint32_t mSource;
int32_t mDisplayId;
@@ -418,7 +456,7 @@
static const char* getLabel(int32_t keyCode);
static int32_t getKeyCodeFromLabel(const char* label);
- void initialize(int32_t deviceId, uint32_t source, int32_t displayId,
+ void initialize(int32_t id, int32_t deviceId, uint32_t source, int32_t displayId,
std::array<uint8_t, 32> hmac, int32_t action, int32_t flags, int32_t keyCode,
int32_t scanCode, int32_t metaState, int32_t repeatCount, nsecs_t downTime,
nsecs_t eventTime);
@@ -642,7 +680,7 @@
ssize_t findPointerIndex(int32_t pointerId) const;
- void initialize(int32_t deviceId, uint32_t source, int32_t displayId,
+ void initialize(int32_t id, int32_t deviceId, uint32_t source, int32_t displayId,
std::array<uint8_t, 32> hmac, int32_t action, int32_t actionButton,
int32_t flags, int32_t edgeFlags, int32_t metaState, int32_t buttonState,
MotionClassification classification, float xScale, float yScale, float xOffset,
@@ -722,7 +760,7 @@
inline bool getInTouchMode() const { return mInTouchMode; }
- void initialize(bool hasFocus, bool inTouchMode);
+ void initialize(int32_t id, bool hasFocus, bool inTouchMode);
void initialize(const FocusEvent& from);
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 06fd3bb..8ca178c 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -82,7 +82,7 @@
union Body {
struct Key {
uint32_t seq;
- uint32_t empty1;
+ int32_t eventId;
nsecs_t eventTime __attribute__((aligned(8)));
int32_t deviceId;
int32_t source;
@@ -102,7 +102,7 @@
struct Motion {
uint32_t seq;
- uint32_t empty1;
+ int32_t eventId;
nsecs_t eventTime __attribute__((aligned(8)));
int32_t deviceId;
int32_t source;
@@ -159,6 +159,8 @@
struct Focus {
uint32_t seq;
+ int32_t eventId;
+ uint32_t empty1;
// The following two fields take up 4 bytes total
uint16_t hasFocus; // actually a bool
uint16_t inTouchMode; // actually a bool, but we must maintain 8-byte alignment
@@ -276,9 +278,9 @@
* Returns BAD_VALUE if seq is 0.
* Other errors probably indicate that the channel is broken.
*/
- status_t publishKeyEvent(uint32_t seq, int32_t deviceId, int32_t source, int32_t displayId,
- std::array<uint8_t, 32> hmac, int32_t action, int32_t flags,
- int32_t keyCode, int32_t scanCode, int32_t metaState,
+ status_t publishKeyEvent(uint32_t seq, int32_t eventId, int32_t deviceId, int32_t source,
+ int32_t displayId, std::array<uint8_t, 32> hmac, int32_t action,
+ int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
int32_t repeatCount, nsecs_t downTime, nsecs_t eventTime);
/* Publishes a motion event to the input channel.
@@ -289,14 +291,15 @@
* Returns BAD_VALUE if seq is 0 or if pointerCount is less than 1 or greater than MAX_POINTERS.
* Other errors probably indicate that the channel is broken.
*/
- status_t publishMotionEvent(uint32_t seq, int32_t deviceId, int32_t source, int32_t displayId,
- std::array<uint8_t, 32> hmac, int32_t action, int32_t actionButton,
- int32_t flags, int32_t edgeFlags, int32_t metaState,
- int32_t buttonState, MotionClassification classification,
- float xScale, float yScale, float xOffset, float yOffset,
- float xPrecision, float yPrecision, float xCursorPosition,
- float yCursorPosition, nsecs_t downTime, nsecs_t eventTime,
- uint32_t pointerCount, const PointerProperties* pointerProperties,
+ status_t publishMotionEvent(uint32_t seq, int32_t eventId, int32_t deviceId, int32_t source,
+ int32_t displayId, std::array<uint8_t, 32> hmac, int32_t action,
+ int32_t actionButton, int32_t flags, int32_t edgeFlags,
+ int32_t metaState, int32_t buttonState,
+ MotionClassification classification, float xScale, float yScale,
+ float xOffset, float yOffset, float xPrecision, float yPrecision,
+ float xCursorPosition, float yCursorPosition, nsecs_t downTime,
+ nsecs_t eventTime, uint32_t pointerCount,
+ const PointerProperties* pointerProperties,
const PointerCoords* pointerCoords);
/* Publishes a focus event to the input channel.
@@ -306,7 +309,7 @@
* Returns DEAD_OBJECT if the channel's peer has been closed.
* Other errors probably indicate that the channel is broken.
*/
- status_t publishFocusEvent(uint32_t seq, bool hasFocus, bool inTouchMode);
+ status_t publishFocusEvent(uint32_t seq, int32_t eventId, bool hasFocus, bool inTouchMode);
/* Receives the finished signal from the consumer in reply to the original dispatch signal.
* If a signal was received, returns the message sequence number,
diff --git a/include/powermanager/PowerManager.h b/include/powermanager/PowerManager.h
index 3268b45..9bac242 100644
--- a/include/powermanager/PowerManager.h
+++ b/include/powermanager/PowerManager.h
@@ -33,6 +33,17 @@
USER_ACTIVITY_EVENT_LAST = USER_ACTIVITY_EVENT_ACCESSIBILITY, // Last valid event code.
};
+/** Keep in sync with android.os.temprature and hardware/interfaces/thermal/2.0/types.hal */
+enum class ThermalStatus : uint32_t {
+ THERMAL_STATUS_NONE = 0,
+ THERMAL_STATUS_LIGHT = 1,
+ THERMAL_STATUS_MODERATE = 2,
+ THERMAL_STATUS_SEVERE = 3,
+ THERMAL_STATUS_CRITICAL = 4,
+ THERMAL_STATUS_EMERGENCY = 5,
+ THERMAL_STATUS_SHUTDOWN = 6,
+};
+
}; // namespace android
#endif // ANDROID_POWERMANAGER_H
diff --git a/libs/adbd_auth/Android.bp b/libs/adbd_auth/Android.bp
index 8ac044c..8883c04 100644
--- a/libs/adbd_auth/Android.bp
+++ b/libs/adbd_auth/Android.bp
@@ -27,7 +27,7 @@
version_script: "libadbd_auth.map.txt",
stubs: {
- versions: ["1"],
+ versions: ["30"],
symbol_file: "libadbd_auth.map.txt",
},
diff --git a/libs/adbd_auth/adbd_auth.cpp b/libs/adbd_auth/adbd_auth.cpp
index a9c2311..5a0d3f6 100644
--- a/libs/adbd_auth/adbd_auth.cpp
+++ b/libs/adbd_auth/adbd_auth.cpp
@@ -43,6 +43,8 @@
using android::base::unique_fd;
+static constexpr uint32_t kAuthVersion = 1;
+
struct AdbdAuthPacketAuthenticated {
std::string public_key;
};
@@ -55,8 +57,21 @@
std::string public_key;
};
-using AdbdAuthPacket = std::variant<AdbdAuthPacketAuthenticated, AdbdAuthPacketDisconnected,
- AdbdAuthPacketRequestAuthorization>;
+struct AdbdPacketTlsDeviceConnected {
+ uint8_t transport_type;
+ std::string public_key;
+};
+
+struct AdbdPacketTlsDeviceDisconnected {
+ uint8_t transport_type;
+ std::string public_key;
+};
+
+using AdbdAuthPacket = std::variant<AdbdAuthPacketAuthenticated,
+ AdbdAuthPacketDisconnected,
+ AdbdAuthPacketRequestAuthorization,
+ AdbdPacketTlsDeviceConnected,
+ AdbdPacketTlsDeviceDisconnected>;
struct AdbdAuthContext {
static constexpr uint64_t kEpollConstSocket = 0;
@@ -65,6 +80,7 @@
public:
explicit AdbdAuthContext(AdbdAuthCallbacksV1* callbacks) : next_id_(0), callbacks_(*callbacks) {
+ InitFrameworkHandlers();
epoll_fd_.reset(epoll_create1(EPOLL_CLOEXEC));
if (epoll_fd_ == -1) {
PLOG(FATAL) << "failed to create epoll fd";
@@ -163,34 +179,56 @@
}
}
- void HandlePacket(std::string_view packet) REQUIRES(mutex_) {
+ void HandlePacket(std::string_view packet) EXCLUDES(mutex_) {
LOG(INFO) << "received packet: " << packet;
- if (packet.length() < 2) {
- LOG(ERROR) << "received packet of invalid length";
- ReplaceFrameworkFd(unique_fd());
+ if (packet.size() < 2) {
+ LOG(ERROR) << "received packet of invalid length";
+ std::lock_guard<std::mutex> lock(mutex_);
+ ReplaceFrameworkFd(unique_fd());
}
- if (packet[0] == 'O' && packet[1] == 'K') {
- CHECK(this->dispatched_prompt_.has_value());
- auto& [id, key, arg] = *this->dispatched_prompt_;
- keys_.emplace(id, std::move(key));
-
- this->callbacks_.key_authorized(arg, id);
- this->dispatched_prompt_ = std::nullopt;
-
- // We need to dispatch pending prompts here upon success as well,
- // since we might have multiple queued prompts.
- DispatchPendingPrompt();
- } else if (packet[0] == 'N' && packet[1] == 'O') {
- CHECK_EQ(2UL, packet.length());
- // TODO: Do we want a callback if the key is denied?
- this->dispatched_prompt_ = std::nullopt;
- DispatchPendingPrompt();
- } else {
- LOG(ERROR) << "unhandled packet: " << packet;
- ReplaceFrameworkFd(unique_fd());
+ bool handled_packet = false;
+ for (size_t i = 0; i < framework_handlers_.size(); ++i) {
+ if (android::base::ConsumePrefix(&packet, framework_handlers_[i].code)) {
+ framework_handlers_[i].cb(packet);
+ handled_packet = true;
+ break;
+ }
}
+ if (!handled_packet) {
+ LOG(ERROR) << "unhandled packet: " << packet;
+ std::lock_guard<std::mutex> lock(mutex_);
+ ReplaceFrameworkFd(unique_fd());
+ }
+ }
+
+ void AllowUsbDevice(std::string_view buf) EXCLUDES(mutex_) {
+ std::lock_guard<std::mutex> lock(mutex_);
+ CHECK(buf.empty());
+ CHECK(dispatched_prompt_.has_value());
+ auto& [id, key, arg] = *dispatched_prompt_;
+ keys_.emplace(id, std::move(key));
+
+ callbacks_.key_authorized(arg, id);
+ dispatched_prompt_ = std::nullopt;
+
+ // We need to dispatch pending prompts here upon success as well,
+ // since we might have multiple queued prompts.
+ DispatchPendingPrompt();
+ }
+
+ void DenyUsbDevice(std::string_view buf) EXCLUDES(mutex_) {
+ std::lock_guard<std::mutex> lock(mutex_);
+ CHECK(buf.empty());
+ // TODO: Do we want a callback if the key is denied?
+ dispatched_prompt_ = std::nullopt;
+ DispatchPendingPrompt();
+ }
+
+ void KeyRemoved(std::string_view buf) EXCLUDES(mutex_) {
+ CHECK(!buf.empty());
+ callbacks_.key_removed(buf.data(), buf.size());
}
bool SendPacket() REQUIRES(mutex_) {
@@ -201,7 +239,8 @@
CHECK_NE(-1, framework_fd_.get());
auto& packet = output_queue_.front();
- struct iovec iovs[2];
+ struct iovec iovs[3];
+ int iovcnt = 2;
if (auto* p = std::get_if<AdbdAuthPacketAuthenticated>(&packet)) {
iovs[0].iov_base = const_cast<char*>("CK");
iovs[0].iov_len = 2;
@@ -217,13 +256,29 @@
iovs[0].iov_len = 2;
iovs[1].iov_base = p->public_key.data();
iovs[1].iov_len = p->public_key.size();
+ } else if (auto* p = std::get_if<AdbdPacketTlsDeviceConnected>(&packet)) {
+ iovcnt = 3;
+ iovs[0].iov_base = const_cast<char*>("WE");
+ iovs[0].iov_len = 2;
+ iovs[1].iov_base = &p->transport_type;
+ iovs[1].iov_len = 1;
+ iovs[2].iov_base = p->public_key.data();
+ iovs[2].iov_len = p->public_key.size();
+ } else if (auto* p = std::get_if<AdbdPacketTlsDeviceDisconnected>(&packet)) {
+ iovcnt = 3;
+ iovs[0].iov_base = const_cast<char*>("WF");
+ iovs[0].iov_len = 2;
+ iovs[1].iov_base = &p->transport_type;
+ iovs[1].iov_len = 1;
+ iovs[2].iov_base = p->public_key.data();
+ iovs[2].iov_len = p->public_key.size();
} else {
LOG(FATAL) << "unhandled packet type?";
}
output_queue_.pop_front();
- ssize_t rc = writev(framework_fd_.get(), iovs, 2);
+ ssize_t rc = writev(framework_fd_.get(), iovs, iovcnt);
if (rc == -1 && errno != EAGAIN && errno != EWOULDBLOCK) {
PLOG(ERROR) << "failed to write to framework fd";
ReplaceFrameworkFd(unique_fd());
@@ -308,7 +363,6 @@
std::lock_guard<std::mutex> lock(mutex_);
ReplaceFrameworkFd(unique_fd());
} else {
- std::lock_guard<std::mutex> lock(mutex_);
HandlePacket(std::string_view(buf, rc));
}
}
@@ -329,7 +383,7 @@
}
static constexpr const char* key_paths[] = {"/adb_keys", "/data/misc/adb/adb_keys"};
- void IteratePublicKeys(bool (*callback)(const char*, size_t, void*), void* arg) {
+ void IteratePublicKeys(bool (*callback)(void*, const char*, size_t), void* opaque) {
for (const auto& path : key_paths) {
if (access(path, R_OK) == 0) {
LOG(INFO) << "Loading keys from " << path;
@@ -339,7 +393,7 @@
continue;
}
for (const auto& line : android::base::Split(content, "\n")) {
- if (!callback(line.data(), line.size(), arg)) {
+ if (!callback(opaque, line.data(), line.size())) {
return;
}
}
@@ -361,7 +415,7 @@
std::lock_guard<std::mutex> lock(mutex_);
keys_.emplace(id, public_key);
output_queue_.emplace_back(
- AdbdAuthPacketDisconnected{.public_key = std::string(public_key)});
+ AdbdAuthPacketAuthenticated{.public_key = std::string(public_key)});
return id;
}
@@ -376,6 +430,32 @@
keys_.erase(it);
}
+ uint64_t NotifyTlsDeviceConnected(AdbTransportType type,
+ std::string_view public_key) EXCLUDES(mutex_) {
+ uint64_t id = NextId();
+ std::lock_guard<std::mutex> lock(mutex_);
+ keys_.emplace(id, public_key);
+ output_queue_.emplace_back(AdbdPacketTlsDeviceConnected{
+ .transport_type = static_cast<uint8_t>(type),
+ .public_key = std::string(public_key)});
+ Interrupt();
+ return id;
+ }
+
+ void NotifyTlsDeviceDisconnected(AdbTransportType type, uint64_t id) EXCLUDES(mutex_) {
+ std::lock_guard<std::mutex> lock(mutex_);
+ auto it = keys_.find(id);
+ if (it == keys_.end()) {
+ LOG(DEBUG) << "couldn't find public key to notify disconnection of tls device, skipping";
+ return;
+ }
+ output_queue_.emplace_back(AdbdPacketTlsDeviceDisconnected{
+ .transport_type = static_cast<uint8_t>(type),
+ .public_key = std::move(it->second)});
+ keys_.erase(it);
+ Interrupt();
+ }
+
// Interrupt the worker thread to do some work.
void Interrupt() {
uint64_t value = 1;
@@ -387,6 +467,24 @@
}
}
+ void InitFrameworkHandlers() {
+ // Framework wants to disconnect from a secured wifi device
+ framework_handlers_.emplace_back(
+ FrameworkPktHandler{
+ .code = "DD",
+ .cb = std::bind(&AdbdAuthContext::KeyRemoved, this, std::placeholders::_1)});
+ // Framework allows USB debugging for the device
+ framework_handlers_.emplace_back(
+ FrameworkPktHandler{
+ .code = "OK",
+ .cb = std::bind(&AdbdAuthContext::AllowUsbDevice, this, std::placeholders::_1)});
+ // Framework denies USB debugging for the device
+ framework_handlers_.emplace_back(
+ FrameworkPktHandler{
+ .code = "NO",
+ .cb = std::bind(&AdbdAuthContext::DenyUsbDevice, this, std::placeholders::_1)});
+ }
+
unique_fd epoll_fd_;
unique_fd event_fd_;
unique_fd sock_fd_;
@@ -400,19 +498,27 @@
// We keep two separate queues: one to handle backpressure from the socket (output_queue_)
// and one to make sure we only dispatch one authrequest at a time (pending_prompts_).
- std::deque<AdbdAuthPacket> output_queue_;
+ std::deque<AdbdAuthPacket> output_queue_ GUARDED_BY(mutex_);
std::optional<std::tuple<uint64_t, std::string, void*>> dispatched_prompt_ GUARDED_BY(mutex_);
std::deque<std::tuple<uint64_t, std::string, void*>> pending_prompts_ GUARDED_BY(mutex_);
+
+ // This is a list of commands that the framework could send to us.
+ using FrameworkHandlerCb = std::function<void(std::string_view)>;
+ struct FrameworkPktHandler {
+ const char* code;
+ FrameworkHandlerCb cb;
+ };
+ std::vector<FrameworkPktHandler> framework_handlers_;
};
AdbdAuthContext* adbd_auth_new(AdbdAuthCallbacks* callbacks) {
- if (callbacks->version != 1) {
+ if (callbacks->version == 1) {
+ return new AdbdAuthContext(reinterpret_cast<AdbdAuthCallbacksV1*>(callbacks));
+ } else {
LOG(ERROR) << "received unknown AdbdAuthCallbacks version " << callbacks->version;
return nullptr;
}
-
- return new AdbdAuthContext(&callbacks->callbacks.v1);
}
void adbd_auth_delete(AdbdAuthContext* ctx) {
@@ -424,9 +530,9 @@
}
void adbd_auth_get_public_keys(AdbdAuthContext* ctx,
- bool (*callback)(const char* public_key, size_t len, void* arg),
- void* arg) {
- ctx->IteratePublicKeys(callback, arg);
+ bool (*callback)(void* opaque, const char* public_key, size_t len),
+ void* opaque) {
+ ctx->IteratePublicKeys(callback, opaque);
}
uint64_t adbd_auth_notify_auth(AdbdAuthContext* ctx, const char* public_key, size_t len) {
@@ -438,10 +544,28 @@
}
void adbd_auth_prompt_user(AdbdAuthContext* ctx, const char* public_key, size_t len,
- void* arg) {
- ctx->PromptUser(std::string_view(public_key, len), arg);
+ void* opaque) {
+ ctx->PromptUser(std::string_view(public_key, len), opaque);
}
-bool adbd_auth_supports_feature(AdbdAuthFeature) {
+uint64_t adbd_auth_tls_device_connected(AdbdAuthContext* ctx,
+ AdbTransportType type,
+ const char* public_key,
+ size_t len) {
+ return ctx->NotifyTlsDeviceConnected(type, std::string_view(public_key, len));
+}
+
+void adbd_auth_tls_device_disconnected(AdbdAuthContext* ctx,
+ AdbTransportType type,
+ uint64_t id) {
+ ctx->NotifyTlsDeviceDisconnected(type, id);
+}
+
+uint32_t adbd_auth_get_max_version() {
+ return kAuthVersion;
+}
+
+bool adbd_auth_supports_feature(AdbdAuthFeature f) {
+ UNUSED(f);
return false;
}
diff --git a/libs/adbd_auth/include/adbd_auth.h b/libs/adbd_auth/include/adbd_auth.h
index b7c1cb8..6ee3166 100644
--- a/libs/adbd_auth/include/adbd_auth.h
+++ b/libs/adbd_auth/include/adbd_auth.h
@@ -18,48 +18,159 @@
#include <stdbool.h>
#include <stdint.h>
+#include <sys/cdefs.h>
#include <sys/types.h>
-extern "C" {
+#if !defined(__INTRODUCED_IN)
+#define __INTRODUCED_IN(__api_level) /* nothing */
+#endif
-struct AdbdAuthCallbacksV1 {
- // Callback for a successful user authorization.
- void (*key_authorized)(void* arg, uint64_t id);
+__BEGIN_DECLS
+#if !defined(__ANDROID__) || __ANDROID_API__ >= 30
+
+// The transport type of the device connection.
+enum AdbTransportType : int32_t {
+ kAdbTransportTypeUsb = 0,
+ kAdbTransportTypeWifi,
};
+static_assert(sizeof(AdbTransportType) == sizeof(int32_t), "Unexpected AdbTransportType size");
struct AdbdAuthCallbacks {
uint32_t version;
- union {
- AdbdAuthCallbacksV1 v1;
- } callbacks;
+};
+
+struct AdbdAuthCallbacksV1 : AdbdAuthCallbacks {
+ // Callback for a successful user authorization.
+ void (*key_authorized)(void* opaque, uint64_t id);
+ // The framework removed the key from the keystore. This callback notifies
+ // adbd so it can take the appropriate actions (e.g. disconnect all devices
+ // using that key).
+ void (*key_removed)(const char* public_key, size_t length);
};
struct AdbdAuthContext;
+typedef struct AdbdAuthContext AdbdAuthContext;
-AdbdAuthContext* adbd_auth_new(AdbdAuthCallbacks* callbacks);
-void adbd_auth_delete(AdbdAuthContext* ctx);
+/**
+ * Creates a new AdbdAuthContext.
+ *
+ * @param callbacks a set of user-provided callbacks used internally (see
+ * #AdbdAuthCallbacksV1
+ * @return a new AdbdAuthContext instance. Caller is responsible for destroying
+ * the context with #adbd_auth_delete.
+ */
+AdbdAuthContext* adbd_auth_new(AdbdAuthCallbacks* callbacks) __INTRODUCED_IN(30);
-void adbd_auth_run(AdbdAuthContext* ctx);
+/**
+ * Destroys the AdbdAuthContext.
+ *
+ * @param ctx the AdbdAuthContext to destroy.
+ */
+void adbd_auth_delete(AdbdAuthContext* ctx) __INTRODUCED_IN(30);
-// Iterate through the list of authorized public keys.
-// Return false from the callback to stop iteration.
+/**
+ * Starts the AdbdAuthContext.
+ *
+ * The caller may want to run this on a different thread, as this
+ * runs indefinitely.
+ *
+ * @param ctx the AdbdAuthContext
+ */
+void adbd_auth_run(AdbdAuthContext* ctx) __INTRODUCED_IN(30);
+
+/**
+ * Iterate through the list of authorized public keys.
+ *
+ * @param ctx the AdbdAuthContext
+ * @param callback a callback which will get called for every known adb public
+ * key in its keystore. To stop iteration of the keys, return false in the
+ * callback. Otherwise, return true to continue the iteration.
+ * @param opaque an opaque userdata argument
+ */
void adbd_auth_get_public_keys(AdbdAuthContext* ctx,
- bool (*callback)(const char* public_key, size_t len, void* arg),
- void* arg);
+ bool (*callback)(void* opaque, const char* public_key, size_t len),
+ void* opaque) __INTRODUCED_IN(30);
-// Let system_server know that a key has been successfully used for authentication.
-uint64_t adbd_auth_notify_auth(AdbdAuthContext* ctx, const char* public_key, size_t len);
+/**
+ * Let system_server know that a key has been successfully used for authentication.
+ *
+ * @param ctx the AdbdAuthContext
+ * @param public_key the RSA key that was authorized using the AUTH protocol
+ * @param len the length of the public_key argument
+ * @return an id corresponding to the new connection
+ */
+uint64_t adbd_auth_notify_auth(AdbdAuthContext* ctx,
+ const char* public_key,
+ size_t len) __INTRODUCED_IN(30);
-// Let system_server know that a connection has been closed.
-void adbd_auth_notify_disconnect(AdbdAuthContext* ctx, uint64_t id);
+/**
+ * Let system_server know that an AUTH connection has been closed.
+ *
+ * @param ctx the AdbdAuthContext
+ * @param id the id of the disconnected device
+ */
+void adbd_auth_notify_disconnect(AdbdAuthContext* ctx,
+ uint64_t id) __INTRODUCED_IN(30);
-// Prompt the user to authorize a public key.
-// When this happens, a callback will be run on the auth thread with the result.
-void adbd_auth_prompt_user(AdbdAuthContext* ctx, const char* public_key, size_t len, void* arg);
+/**
+ * Prompt the user to authorize a public key.
+ *
+ * When this happens, a callback will be run on the auth thread with the result.
+ *
+ * @param ctx the AdbdAuthContext
+ * @param public_key the RSA public key to prompt user with
+ * @param len the length of the public_key argument
+ * @param arg an opaque userdata argument
+ */
+void adbd_auth_prompt_user(AdbdAuthContext* ctx,
+ const char* public_key,
+ size_t len, void* opaque) __INTRODUCED_IN(30);
-enum AdbdAuthFeature {
+/**
+ * Let system_server know that a TLS device has connected.
+ *
+ * @param ctx the AdbdAuthContext
+ * @param type the transport type of the connection (see #AdbTransportType)
+ * @param public_key the RSA public key used to establish the connection
+ * @param len the length of the public_key argument
+ * @return an id corresponding to the new connection
+ */
+uint64_t adbd_auth_tls_device_connected(AdbdAuthContext* ctx,
+ AdbTransportType type,
+ const char* public_key,
+ size_t len) __INTRODUCED_IN(30);
+
+/**
+ * Let system_server know that a TLS device has disconnected.
+ *
+ * @param ctx the AdbdAuthContext
+ * @param type the transport type of the connection (see #AdbTransportType)
+ * @param the id of the disconnected device (see #adbd_tls_device_connected)
+ */
+void adbd_auth_tls_device_disconnected(AdbdAuthContext* ctx,
+ AdbTransportType type,
+ uint64_t id) __INTRODUCED_IN(30);
+
+/**
+ * Returns the max #AdbdAuthCallbacks version.
+ *
+ * The version starts at 1, with version 1 corresponding to the
+ * #AdbdAuthCallbacksV1 struct.
+ *
+ * @return the max #AdbdAuthCallbacks version.
+ */
+uint32_t adbd_auth_get_max_version(void) __INTRODUCED_IN(30);
+
+enum AdbdAuthFeature : int32_t {
};
-bool adbd_auth_supports_feature(AdbdAuthFeature f);
+/**
+ * Checks if a feature is supported by the framework. See #AdbdAuthFeature.
+ *
+ * @param feature the feature to check for support
+ * @return true if the feature is supported
+ */
+bool adbd_auth_supports_feature(AdbdAuthFeature feature);
-}
+#endif //!__ANDROID__ || __ANDROID_API__ >= 30
+__END_DECLS
diff --git a/libs/adbd_auth/libadbd_auth.map.txt b/libs/adbd_auth/libadbd_auth.map.txt
index d01233c..5857ecb 100644
--- a/libs/adbd_auth/libadbd_auth.map.txt
+++ b/libs/adbd_auth/libadbd_auth.map.txt
@@ -1,13 +1,16 @@
LIBADBD_AUTH {
global:
- adbd_auth_new; # apex
- adbd_auth_delete; # apex
- adbd_auth_run; # apex
- adbd_auth_get_public_keys; #apex
- adbd_auth_notify_auth; # apex
- adbd_auth_notify_disconnect; # apex
- adbd_auth_prompt_user; # apex
- adbd_auth_supports_feature; # apex
+ adbd_auth_new; # apex introduced=30
+ adbd_auth_delete; # apex introduced=30
+ adbd_auth_run; # apex introduced=30
+ adbd_auth_get_public_keys; #apex introduced=30
+ adbd_auth_notify_auth; # apex introduced=30
+ adbd_auth_notify_disconnect; # apex introduced=30
+ adbd_auth_prompt_user; # apex introduced=30
+ adbd_auth_tls_device_connected; # apex introduced=30
+ adbd_auth_tls_device_disconnected; # apex introduced=30
+ adbd_auth_get_max_version; # apex introduced=30
+ adbd_auth_supports_feature; # apex introduced=30
local:
*;
};
diff --git a/libs/binder/LazyServiceRegistrar.cpp b/libs/binder/LazyServiceRegistrar.cpp
index f064bd7..71d8130 100644
--- a/libs/binder/LazyServiceRegistrar.cpp
+++ b/libs/binder/LazyServiceRegistrar.cpp
@@ -64,8 +64,7 @@
bool ClientCounterCallback::registerService(const sp<IBinder>& service, const std::string& name,
bool allowIsolated, int dumpFlags) {
- auto manager = interface_cast<AidlServiceManager>(
- ProcessState::self()->getContextObject(nullptr));
+ auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
bool reRegister = mRegisteredServices.count(name) > 0;
std::string regStr = (reRegister) ? "Re-registering" : "Registering";
@@ -114,9 +113,7 @@
void ClientCounterCallback::tryShutdown() {
ALOGI("Trying to shut down the service. No clients in use for any service in process.");
- // This makes the same assumption as IServiceManager.cpp. Could dedupe if used in more places.
- auto manager = interface_cast<AidlServiceManager>(
- ProcessState::self()->getContextObject(nullptr));
+ auto manager = interface_cast<AidlServiceManager>(asBinder(defaultServiceManager()));
auto unRegisterIt = mRegisteredServices.begin();
for (; unRegisterIt != mRegisteredServices.end(); ++unRegisterIt) {
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 9f8d752..beab270 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -560,6 +560,13 @@
bool Parcel::enforceInterface(const String16& interface,
IPCThreadState* threadState) const
{
+ return enforceInterface(interface.string(), interface.size(), threadState);
+}
+
+bool Parcel::enforceInterface(const char16_t* interface,
+ size_t len,
+ IPCThreadState* threadState) const
+{
// StrictModePolicy.
int32_t strictPolicy = readInt32();
if (threadState == nullptr) {
@@ -586,12 +593,15 @@
return false;
}
// Interface descriptor.
- const String16 str(readString16());
- if (str == interface) {
+ size_t parcel_interface_len;
+ const char16_t* parcel_interface = readString16Inplace(&parcel_interface_len);
+ if (len == parcel_interface_len &&
+ (!len || !memcmp(parcel_interface, interface, len * sizeof (char16_t)))) {
return true;
} else {
ALOGW("**** enforceInterface() expected '%s' but read '%s'",
- String8(interface).string(), String8(str).string());
+ String8(interface, len).string(),
+ String8(parcel_interface, parcel_interface_len).string());
return false;
}
}
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index d4bb85b..4b1a758 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -96,6 +96,9 @@
// passed in.
bool enforceInterface(const String16& interface,
IPCThreadState* threadState = nullptr) const;
+ bool enforceInterface(const char16_t* interface,
+ size_t len,
+ IPCThreadState* threadState = nullptr) const;
bool checkInterface(IBinder*) const;
void freeData();
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 2a73dc0..c243767 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -17,7 +17,9 @@
#define LOG_TAG "Input"
//#define LOG_NDEBUG 0
+#include <cutils/compiler.h>
#include <limits.h>
+#include <string.h>
#include <input/Input.h>
#include <input/InputDevice.h>
@@ -25,6 +27,7 @@
#ifdef __ANDROID__
#include <binder/Parcel.h>
+#include <sys/random.h>
#endif
namespace android {
@@ -40,6 +43,32 @@
}
}
+// --- IdGenerator ---
+IdGenerator::IdGenerator(Source source) : mSource(source) {}
+
+int32_t IdGenerator::nextId() const {
+ constexpr uint32_t SEQUENCE_NUMBER_MASK = ~SOURCE_MASK;
+ int32_t id = 0;
+
+// Avoid building against syscall getrandom(2) on host, which will fail build on Mac. Host doesn't
+// use sequence number so just always return mSource.
+#ifdef __ANDROID__
+ constexpr size_t BUF_LEN = sizeof(id);
+ size_t totalBytes = 0;
+ while (totalBytes < BUF_LEN) {
+ ssize_t bytes = TEMP_FAILURE_RETRY(getrandom(&id, BUF_LEN, GRND_NONBLOCK));
+ if (CC_UNLIKELY(bytes < 0)) {
+ ALOGW("Failed to fill in random number for sequence number: %s.", strerror(errno));
+ id = 0;
+ break;
+ }
+ totalBytes += bytes;
+ }
+#endif // __ANDROID__
+
+ return (id & SEQUENCE_NUMBER_MASK) | static_cast<int32_t>(mSource);
+}
+
// --- InputEvent ---
const char* inputEventTypeToString(int32_t type) {
@@ -81,8 +110,9 @@
event.getButtonState()};
}
-void InputEvent::initialize(int32_t deviceId, uint32_t source, int32_t displayId,
+void InputEvent::initialize(int32_t id, int32_t deviceId, uint32_t source, int32_t displayId,
std::array<uint8_t, 32> hmac) {
+ mId = id;
mDeviceId = deviceId;
mSource = source;
mDisplayId = displayId;
@@ -90,12 +120,18 @@
}
void InputEvent::initialize(const InputEvent& from) {
+ mId = from.mId;
mDeviceId = from.mDeviceId;
mSource = from.mSource;
mDisplayId = from.mDisplayId;
mHmac = from.mHmac;
}
+int32_t InputEvent::nextId() {
+ static IdGenerator idGen(IdGenerator::Source::OTHER);
+ return idGen.nextId();
+}
+
// --- KeyEvent ---
const char* KeyEvent::getLabel(int32_t keyCode) {
@@ -106,11 +142,11 @@
return getKeyCodeByLabel(label);
}
-void KeyEvent::initialize(int32_t deviceId, uint32_t source, int32_t displayId,
+void KeyEvent::initialize(int32_t id, int32_t deviceId, uint32_t source, int32_t displayId,
std::array<uint8_t, 32> hmac, int32_t action, int32_t flags,
int32_t keyCode, int32_t scanCode, int32_t metaState, int32_t repeatCount,
nsecs_t downTime, nsecs_t eventTime) {
- InputEvent::initialize(deviceId, source, displayId, hmac);
+ InputEvent::initialize(id, deviceId, source, displayId, hmac);
mAction = action;
mFlags = flags;
mKeyCode = keyCode;
@@ -269,7 +305,7 @@
// --- MotionEvent ---
-void MotionEvent::initialize(int32_t deviceId, uint32_t source, int32_t displayId,
+void MotionEvent::initialize(int32_t id, int32_t deviceId, uint32_t source, int32_t displayId,
std::array<uint8_t, 32> hmac, int32_t action, int32_t actionButton,
int32_t flags, int32_t edgeFlags, int32_t metaState,
int32_t buttonState, MotionClassification classification, float xScale,
@@ -278,7 +314,7 @@
nsecs_t downTime, nsecs_t eventTime, size_t pointerCount,
const PointerProperties* pointerProperties,
const PointerCoords* pointerCoords) {
- InputEvent::initialize(deviceId, source, displayId, hmac);
+ InputEvent::initialize(id, deviceId, source, displayId, hmac);
mAction = action;
mActionButton = actionButton;
mFlags = flags;
@@ -303,7 +339,8 @@
}
void MotionEvent::copyFrom(const MotionEvent* other, bool keepHistory) {
- InputEvent::initialize(other->mDeviceId, other->mSource, other->mDisplayId, other->mHmac);
+ InputEvent::initialize(other->mId, other->mDeviceId, other->mSource, other->mDisplayId,
+ other->mHmac);
mAction = other->mAction;
mActionButton = other->mActionButton;
mFlags = other->mFlags;
@@ -511,6 +548,7 @@
return BAD_VALUE;
}
+ mId = parcel->readInt32();
mDeviceId = parcel->readInt32();
mSource = parcel->readUint32();
mDisplayId = parcel->readInt32();
@@ -572,6 +610,7 @@
parcel->writeInt32(pointerCount);
parcel->writeInt32(sampleCount);
+ parcel->writeInt32(mId);
parcel->writeInt32(mDeviceId);
parcel->writeUint32(mSource);
parcel->writeInt32(mDisplayId);
@@ -641,8 +680,8 @@
// --- FocusEvent ---
-void FocusEvent::initialize(bool hasFocus, bool inTouchMode) {
- InputEvent::initialize(ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID, AINPUT_SOURCE_UNKNOWN,
+void FocusEvent::initialize(int32_t id, bool hasFocus, bool inTouchMode) {
+ InputEvent::initialize(id, ReservedInputDeviceId::VIRTUAL_KEYBOARD_ID, AINPUT_SOURCE_UNKNOWN,
ADISPLAY_ID_NONE, INVALID_HMAC);
mHasFocus = hasFocus;
mInTouchMode = inTouchMode;
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index d25a5cc..7335b30 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -139,6 +139,8 @@
case InputMessage::Type::KEY: {
// uint32_t seq
msg->body.key.seq = body.key.seq;
+ // int32_t eventId
+ msg->body.key.eventId = body.key.eventId;
// nsecs_t eventTime
msg->body.key.eventTime = body.key.eventTime;
// int32_t deviceId
@@ -168,6 +170,8 @@
case InputMessage::Type::MOTION: {
// uint32_t seq
msg->body.motion.seq = body.motion.seq;
+ // int32_t eventId
+ msg->body.motion.eventId = body.motion.eventId;
// nsecs_t eventTime
msg->body.motion.eventTime = body.motion.eventTime;
// int32_t deviceId
@@ -234,6 +238,7 @@
}
case InputMessage::Type::FOCUS: {
msg->body.focus.seq = body.focus.seq;
+ msg->body.focus.eventId = body.focus.eventId;
msg->body.focus.hasFocus = body.focus.hasFocus;
msg->body.focus.inTouchMode = body.focus.inTouchMode;
break;
@@ -432,11 +437,12 @@
InputPublisher::~InputPublisher() {
}
-status_t InputPublisher::publishKeyEvent(uint32_t seq, int32_t deviceId, int32_t source,
- int32_t displayId, std::array<uint8_t, 32> hmac,
- int32_t action, int32_t flags, int32_t keyCode,
- int32_t scanCode, int32_t metaState, int32_t repeatCount,
- nsecs_t downTime, nsecs_t eventTime) {
+status_t InputPublisher::publishKeyEvent(uint32_t seq, int32_t eventId, int32_t deviceId,
+ int32_t source, int32_t displayId,
+ std::array<uint8_t, 32> hmac, int32_t action,
+ int32_t flags, int32_t keyCode, int32_t scanCode,
+ int32_t metaState, int32_t repeatCount, nsecs_t downTime,
+ nsecs_t eventTime) {
if (ATRACE_ENABLED()) {
std::string message = StringPrintf("publishKeyEvent(inputChannel=%s, keyCode=%" PRId32 ")",
mChannel->getName().c_str(), keyCode);
@@ -458,6 +464,7 @@
InputMessage msg;
msg.header.type = InputMessage::Type::KEY;
msg.body.key.seq = seq;
+ msg.body.key.eventId = eventId;
msg.body.key.deviceId = deviceId;
msg.body.key.source = source;
msg.body.key.displayId = displayId;
@@ -474,7 +481,7 @@
}
status_t InputPublisher::publishMotionEvent(
- uint32_t seq, int32_t deviceId, int32_t source, int32_t displayId,
+ uint32_t seq, int32_t eventId, int32_t deviceId, int32_t source, int32_t displayId,
std::array<uint8_t, 32> hmac, int32_t action, int32_t actionButton, int32_t flags,
int32_t edgeFlags, int32_t metaState, int32_t buttonState,
MotionClassification classification, float xScale, float yScale, float xOffset,
@@ -515,6 +522,7 @@
InputMessage msg;
msg.header.type = InputMessage::Type::MOTION;
msg.body.motion.seq = seq;
+ msg.body.motion.eventId = eventId;
msg.body.motion.deviceId = deviceId;
msg.body.motion.source = source;
msg.body.motion.displayId = displayId;
@@ -545,7 +553,8 @@
return mChannel->sendMessage(&msg);
}
-status_t InputPublisher::publishFocusEvent(uint32_t seq, bool hasFocus, bool inTouchMode) {
+status_t InputPublisher::publishFocusEvent(uint32_t seq, int32_t eventId, bool hasFocus,
+ bool inTouchMode) {
if (ATRACE_ENABLED()) {
std::string message =
StringPrintf("publishFocusEvent(inputChannel=%s, hasFocus=%s, inTouchMode=%s)",
@@ -557,6 +566,7 @@
InputMessage msg;
msg.header.type = InputMessage::Type::FOCUS;
msg.body.focus.seq = seq;
+ msg.body.focus.eventId = eventId;
msg.body.focus.hasFocus = hasFocus ? 1 : 0;
msg.body.focus.inTouchMode = inTouchMode ? 1 : 0;
return mChannel->sendMessage(&msg);
@@ -1142,14 +1152,16 @@
}
void InputConsumer::initializeKeyEvent(KeyEvent* event, const InputMessage* msg) {
- event->initialize(msg->body.key.deviceId, msg->body.key.source, msg->body.key.displayId,
- msg->body.key.hmac, msg->body.key.action, msg->body.key.flags,
- msg->body.key.keyCode, msg->body.key.scanCode, msg->body.key.metaState,
- msg->body.key.repeatCount, msg->body.key.downTime, msg->body.key.eventTime);
+ event->initialize(msg->body.key.eventId, msg->body.key.deviceId, msg->body.key.source,
+ msg->body.key.displayId, msg->body.key.hmac, msg->body.key.action,
+ msg->body.key.flags, msg->body.key.keyCode, msg->body.key.scanCode,
+ msg->body.key.metaState, msg->body.key.repeatCount, msg->body.key.downTime,
+ msg->body.key.eventTime);
}
void InputConsumer::initializeFocusEvent(FocusEvent* event, const InputMessage* msg) {
- event->initialize(msg->body.focus.hasFocus == 1, msg->body.focus.inTouchMode == 1);
+ event->initialize(msg->body.focus.eventId, msg->body.focus.hasFocus == 1,
+ msg->body.focus.inTouchMode == 1);
}
void InputConsumer::initializeMotionEvent(MotionEvent* event, const InputMessage* msg) {
@@ -1161,7 +1173,7 @@
pointerCoords[i].copyFrom(msg->body.motion.pointers[i].coords);
}
- event->initialize(msg->body.motion.deviceId, msg->body.motion.source,
+ event->initialize(msg->body.motion.eventId, msg->body.motion.deviceId, msg->body.motion.source,
msg->body.motion.displayId, msg->body.motion.hmac, msg->body.motion.action,
msg->body.motion.actionButton, msg->body.motion.flags,
msg->body.motion.edgeFlags, msg->body.motion.metaState,
diff --git a/libs/input/KeyCharacterMap.cpp b/libs/input/KeyCharacterMap.cpp
index 6f9b162..cb68165 100644
--- a/libs/input/KeyCharacterMap.cpp
+++ b/libs/input/KeyCharacterMap.cpp
@@ -487,9 +487,9 @@
int32_t deviceId, int32_t keyCode, int32_t metaState, bool down, nsecs_t time) {
outEvents.push();
KeyEvent& event = outEvents.editTop();
- event.initialize(deviceId, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE, INVALID_HMAC,
- down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, 0, keyCode, 0, metaState,
- 0, time, time);
+ event.initialize(InputEvent::nextId(), deviceId, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
+ INVALID_HMAC, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP, 0, keyCode,
+ 0, metaState, 0, time, time);
}
void KeyCharacterMap::addMetaKeys(Vector<KeyEvent>& outEvents,
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index fb21d5e..3b57146 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -2,6 +2,7 @@
cc_test {
name: "libinput_tests",
srcs: [
+ "IdGenerator_test.cpp",
"InputChannel_test.cpp",
"InputDevice_test.cpp",
"InputEvent_test.cpp",
diff --git a/libs/input/tests/IdGenerator_test.cpp b/libs/input/tests/IdGenerator_test.cpp
new file mode 100644
index 0000000..f7fc3c0
--- /dev/null
+++ b/libs/input/tests/IdGenerator_test.cpp
@@ -0,0 +1,52 @@
+/*
+ * 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 <gtest/gtest.h>
+#include <input/Input.h>
+#include <ios>
+#include <memory>
+#include <unordered_set>
+
+namespace android::test {
+
+class IdGeneratorTest : public testing::TestWithParam<IdGenerator::Source> {
+protected:
+ void SetUp() override { mGenerator.reset(new IdGenerator(GetParam())); }
+
+ std::unique_ptr<IdGenerator> mGenerator;
+};
+
+TEST_P(IdGeneratorTest, GenerateRandomNumber) {
+ for (int i = 0; i < 500; ++i) {
+ mGenerator->nextId();
+ }
+}
+
+TEST_P(IdGeneratorTest, GenerateRandomNumberWithProperFlag) {
+ for (int i = 0; i < 500; ++i) {
+ int32_t id = mGenerator->nextId();
+ IdGenerator::Source source = IdGenerator::getSource(id);
+ EXPECT_EQ(source, GetParam())
+ << std::hex << "Generator generated a value with wrong source. Value: 0x" << id
+ << " Source: 0x" << static_cast<int32_t>(source);
+ }
+}
+
+INSTANTIATE_TEST_SUITE_P(SourceInstantiation, IdGeneratorTest,
+ testing::Values(IdGenerator::Source::INPUT_READER,
+ IdGenerator::Source::INPUT_DISPATCHER,
+ IdGenerator::Source::OTHER));
+} // namespace android::test
diff --git a/libs/input/tests/InputEvent_test.cpp b/libs/input/tests/InputEvent_test.cpp
index d0f7618..553dc4c 100644
--- a/libs/input/tests/InputEvent_test.cpp
+++ b/libs/input/tests/InputEvent_test.cpp
@@ -182,10 +182,12 @@
// Initialize and get properties.
constexpr nsecs_t ARBITRARY_DOWN_TIME = 1;
constexpr nsecs_t ARBITRARY_EVENT_TIME = 2;
- event.initialize(2, AINPUT_SOURCE_GAMEPAD, DISPLAY_ID, HMAC, AKEY_EVENT_ACTION_DOWN,
+ const int32_t id = InputEvent::nextId();
+ event.initialize(id, 2, AINPUT_SOURCE_GAMEPAD, DISPLAY_ID, HMAC, AKEY_EVENT_ACTION_DOWN,
AKEY_EVENT_FLAG_FROM_SYSTEM, AKEYCODE_BUTTON_X, 121, AMETA_ALT_ON, 1,
ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME);
+ ASSERT_EQ(id, event.getId());
ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, event.getType());
ASSERT_EQ(2, event.getDeviceId());
ASSERT_EQ(AINPUT_SOURCE_GAMEPAD, event.getSource());
@@ -222,12 +224,16 @@
static constexpr float X_OFFSET = 1;
static constexpr float Y_OFFSET = 1.1;
+ int32_t mId;
+
void initializeEventWithHistory(MotionEvent* event);
void assertEqualsEventWithHistory(const MotionEvent* event);
};
void MotionEventTest::initializeEventWithHistory(MotionEvent* event) {
+ mId = InputEvent::nextId();
+
PointerProperties pointerProperties[2];
pointerProperties[0].clear();
pointerProperties[0].id = 1;
@@ -257,10 +263,10 @@
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, 26);
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, 27);
pointerCoords[1].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 28);
- event->initialize(2, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, HMAC, AMOTION_EVENT_ACTION_MOVE, 0,
- AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED, AMOTION_EVENT_EDGE_FLAG_TOP,
- AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY, MotionClassification::NONE,
- X_SCALE, Y_SCALE, X_OFFSET, Y_OFFSET, 2.0f, 2.1f,
+ event->initialize(mId, 2, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, HMAC,
+ AMOTION_EVENT_ACTION_MOVE, 0, AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED,
+ AMOTION_EVENT_EDGE_FLAG_TOP, AMETA_ALT_ON, AMOTION_EVENT_BUTTON_PRIMARY,
+ MotionClassification::NONE, X_SCALE, Y_SCALE, X_OFFSET, Y_OFFSET, 2.0f, 2.1f,
AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
ARBITRARY_DOWN_TIME, ARBITRARY_EVENT_TIME, 2, pointerProperties,
pointerCoords);
@@ -308,6 +314,7 @@
void MotionEventTest::assertEqualsEventWithHistory(const MotionEvent* event) {
// Check properties.
+ ASSERT_EQ(mId, event->getId());
ASSERT_EQ(AINPUT_EVENT_TYPE_MOTION, event->getType());
ASSERT_EQ(2, event->getDeviceId());
ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, event->getSource());
@@ -577,8 +584,8 @@
pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, angle);
}
MotionEvent event;
- event.initialize(0 /*deviceId*/, AINPUT_SOURCE_UNKNOWN, DISPLAY_ID, INVALID_HMAC,
- AMOTION_EVENT_ACTION_MOVE, 0 /*actionButton*/, 0 /*flags*/,
+ event.initialize(InputEvent::nextId(), 0 /*deviceId*/, AINPUT_SOURCE_UNKNOWN, DISPLAY_ID,
+ INVALID_HMAC, AMOTION_EVENT_ACTION_MOVE, 0 /*actionButton*/, 0 /*flags*/,
AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0 /*buttonState*/,
MotionClassification::NONE, 1 /*xScale*/, 1 /*yScale*/, 0 /*xOffset*/,
0 /*yOffset*/, 0 /*xPrecision*/, 0 /*yPrecision*/,
@@ -642,10 +649,10 @@
}
for (MotionClassification classification : classifications) {
- event.initialize(0 /*deviceId*/, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, INVALID_HMAC,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE,
- 0, classification, 1 /*xScale*/, 1 /*yScale*/, 0, 0, 0, 0,
- AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ event.initialize(InputEvent::nextId(), 0 /*deviceId*/, AINPUT_SOURCE_TOUCHSCREEN,
+ DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
+ AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0, classification, 1 /*xScale*/,
+ 1 /*yScale*/, 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
AMOTION_EVENT_INVALID_CURSOR_POSITION, 0 /*downTime*/, 0 /*eventTime*/,
pointerCount, pointerProperties, pointerCoords);
ASSERT_EQ(classification, event.getClassification());
@@ -663,10 +670,10 @@
pointerCoords[i].clear();
}
- event.initialize(0 /*deviceId*/, AINPUT_SOURCE_MOUSE, DISPLAY_ID, INVALID_HMAC,
- AMOTION_EVENT_ACTION_DOWN, 0, 0, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0,
- MotionClassification::NONE, 1 /*xScale*/, 1 /*yScale*/, 0, 0, 0, 0,
- 280 /*xCursorPosition*/, 540 /*yCursorPosition*/, 0 /*downTime*/,
+ event.initialize(InputEvent::nextId(), 0 /*deviceId*/, AINPUT_SOURCE_MOUSE, DISPLAY_ID,
+ INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0, AMOTION_EVENT_EDGE_FLAG_NONE,
+ AMETA_NONE, 0, MotionClassification::NONE, 1 /*xScale*/, 1 /*yScale*/, 0, 0, 0,
+ 0, 280 /*xCursorPosition*/, 540 /*yCursorPosition*/, 0 /*downTime*/,
0 /*eventTime*/, pointerCount, pointerProperties, pointerCoords);
event.offsetLocation(20, 60);
ASSERT_EQ(280, event.getRawXCursorPosition());
diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp
index 885196f..8e2eec8 100644
--- a/libs/input/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp
@@ -73,6 +73,7 @@
status_t status;
constexpr uint32_t seq = 15;
+ int32_t eventId = InputEvent::nextId();
constexpr int32_t deviceId = 1;
constexpr uint32_t source = AINPUT_SOURCE_KEYBOARD;
constexpr int32_t displayId = ADISPLAY_ID_DEFAULT;
@@ -88,8 +89,8 @@
constexpr nsecs_t downTime = 3;
constexpr nsecs_t eventTime = 4;
- status = mPublisher->publishKeyEvent(seq, deviceId, source, displayId, hmac, action, flags,
- keyCode, scanCode, metaState, repeatCount, downTime,
+ status = mPublisher->publishKeyEvent(seq, eventId, deviceId, source, displayId, hmac, action,
+ flags, keyCode, scanCode, metaState, repeatCount, downTime,
eventTime);
ASSERT_EQ(OK, status)
<< "publisher publishKeyEvent should return OK";
@@ -107,6 +108,7 @@
KeyEvent* keyEvent = static_cast<KeyEvent*>(event);
EXPECT_EQ(seq, consumeSeq);
+ EXPECT_EQ(eventId, keyEvent->getId());
EXPECT_EQ(deviceId, keyEvent->getDeviceId());
EXPECT_EQ(source, keyEvent->getSource());
EXPECT_EQ(displayId, keyEvent->getDisplayId());
@@ -139,6 +141,7 @@
status_t status;
constexpr uint32_t seq = 15;
+ int32_t eventId = InputEvent::nextId();
constexpr int32_t deviceId = 1;
constexpr uint32_t source = AINPUT_SOURCE_TOUCHSCREEN;
constexpr int32_t displayId = ADISPLAY_ID_DEFAULT;
@@ -182,7 +185,7 @@
pointerCoords[i].setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, 3.5 * i);
}
- status = mPublisher->publishMotionEvent(seq, deviceId, source, displayId, hmac, action,
+ status = mPublisher->publishMotionEvent(seq, eventId, deviceId, source, displayId, hmac, action,
actionButton, flags, edgeFlags, metaState, buttonState,
classification, xScale, yScale, xOffset, yOffset,
xPrecision, yPrecision, xCursorPosition,
@@ -204,6 +207,7 @@
MotionEvent* motionEvent = static_cast<MotionEvent*>(event);
EXPECT_EQ(seq, consumeSeq);
+ EXPECT_EQ(eventId, motionEvent->getId());
EXPECT_EQ(deviceId, motionEvent->getDeviceId());
EXPECT_EQ(source, motionEvent->getSource());
EXPECT_EQ(displayId, motionEvent->getDisplayId());
@@ -277,10 +281,11 @@
status_t status;
constexpr uint32_t seq = 15;
+ int32_t eventId = InputEvent::nextId();
constexpr bool hasFocus = true;
constexpr bool inTouchMode = true;
- status = mPublisher->publishFocusEvent(seq, hasFocus, inTouchMode);
+ status = mPublisher->publishFocusEvent(seq, eventId, hasFocus, inTouchMode);
ASSERT_EQ(OK, status) << "publisher publishKeyEvent should return OK";
uint32_t consumeSeq;
@@ -294,6 +299,7 @@
FocusEvent* focusEvent = static_cast<FocusEvent*>(event);
EXPECT_EQ(seq, consumeSeq);
+ EXPECT_EQ(eventId, focusEvent->getId());
EXPECT_EQ(hasFocus, focusEvent->getHasFocus());
EXPECT_EQ(inTouchMode, focusEvent->getInTouchMode());
@@ -332,8 +338,8 @@
pointerCoords[i].clear();
}
- status = mPublisher->publishMotionEvent(0, 0, 0, 0, INVALID_HMAC, 0, 0, 0, 0, 0, 0,
- MotionClassification::NONE, 1 /* xScale */,
+ status = mPublisher->publishMotionEvent(0, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0,
+ 0, 0, 0, MotionClassification::NONE, 1 /* xScale */,
1 /* yScale */, 0, 0, 0, 0,
AMOTION_EVENT_INVALID_CURSOR_POSITION,
AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, 0,
@@ -348,8 +354,8 @@
PointerProperties pointerProperties[pointerCount];
PointerCoords pointerCoords[pointerCount];
- status = mPublisher->publishMotionEvent(1, 0, 0, 0, INVALID_HMAC, 0, 0, 0, 0, 0, 0,
- MotionClassification::NONE, 1 /* xScale */,
+ status = mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0,
+ 0, 0, 0, MotionClassification::NONE, 1 /* xScale */,
1 /* yScale */, 0, 0, 0, 0,
AMOTION_EVENT_INVALID_CURSOR_POSITION,
AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, 0,
@@ -369,8 +375,8 @@
pointerCoords[i].clear();
}
- status = mPublisher->publishMotionEvent(1, 0, 0, 0, INVALID_HMAC, 0, 0, 0, 0, 0, 0,
- MotionClassification::NONE, 1 /* xScale */,
+ status = mPublisher->publishMotionEvent(1, InputEvent::nextId(), 0, 0, 0, INVALID_HMAC, 0, 0, 0,
+ 0, 0, 0, MotionClassification::NONE, 1 /* xScale */,
1 /* yScale */, 0, 0, 0, 0,
AMOTION_EVENT_INVALID_CURSOR_POSITION,
AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, 0,
diff --git a/libs/input/tests/StructLayout_test.cpp b/libs/input/tests/StructLayout_test.cpp
index dd127fc..1fe7bb9 100644
--- a/libs/input/tests/StructLayout_test.cpp
+++ b/libs/input/tests/StructLayout_test.cpp
@@ -35,6 +35,7 @@
CHECK_OFFSET(InputMessage, body, 8);
CHECK_OFFSET(InputMessage::Body::Key, seq, 0);
+ CHECK_OFFSET(InputMessage::Body::Key, eventId, 4);
CHECK_OFFSET(InputMessage::Body::Key, eventTime, 8);
CHECK_OFFSET(InputMessage::Body::Key, deviceId, 16);
CHECK_OFFSET(InputMessage::Body::Key, source, 20);
@@ -49,6 +50,7 @@
CHECK_OFFSET(InputMessage::Body::Key, downTime, 88);
CHECK_OFFSET(InputMessage::Body::Motion, seq, 0);
+ CHECK_OFFSET(InputMessage::Body::Motion, eventId, 4);
CHECK_OFFSET(InputMessage::Body::Motion, eventTime, 8);
CHECK_OFFSET(InputMessage::Body::Motion, deviceId, 16);
CHECK_OFFSET(InputMessage::Body::Motion, source, 20);
@@ -74,8 +76,9 @@
CHECK_OFFSET(InputMessage::Body::Motion, pointers, 136);
CHECK_OFFSET(InputMessage::Body::Focus, seq, 0);
- CHECK_OFFSET(InputMessage::Body::Focus, hasFocus, 4);
- CHECK_OFFSET(InputMessage::Body::Focus, inTouchMode, 6);
+ CHECK_OFFSET(InputMessage::Body::Focus, eventId, 4);
+ CHECK_OFFSET(InputMessage::Body::Focus, hasFocus, 12);
+ CHECK_OFFSET(InputMessage::Body::Focus, inTouchMode, 14);
CHECK_OFFSET(InputMessage::Body::Finished, seq, 0);
CHECK_OFFSET(InputMessage::Body::Finished, handled, 4);
@@ -95,7 +98,7 @@
offsetof(InputMessage::Body::Motion, pointers) +
sizeof(InputMessage::Body::Motion::Pointer) * MAX_POINTERS);
static_assert(sizeof(InputMessage::Body::Finished) == 8);
- static_assert(sizeof(InputMessage::Body::Focus) == 8);
+ static_assert(sizeof(InputMessage::Body::Focus) == 16);
}
// --- VerifiedInputEvent ---
diff --git a/libs/input/tests/VelocityTracker_test.cpp b/libs/input/tests/VelocityTracker_test.cpp
index 731eb6a..bf452c0 100644
--- a/libs/input/tests/VelocityTracker_test.cpp
+++ b/libs/input/tests/VelocityTracker_test.cpp
@@ -176,11 +176,12 @@
EXPECT_EQ(pointerIndex, pointerCount);
MotionEvent event;
- event.initialize(0 /*deviceId*/, AINPUT_SOURCE_TOUCHSCREEN, DISPLAY_ID, INVALID_HMAC,
- action, 0 /*actionButton*/, 0 /*flags*/, AMOTION_EVENT_EDGE_FLAG_NONE,
- AMETA_NONE, 0 /*buttonState*/, MotionClassification::NONE, 1 /*xScale*/,
- 1 /*yScale*/, 0 /*xOffset*/, 0 /*yOffset*/, 0 /*xPrecision*/,
- 0 /*yPrecision*/, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ event.initialize(InputEvent::nextId(), 0 /*deviceId*/, AINPUT_SOURCE_TOUCHSCREEN,
+ DISPLAY_ID, INVALID_HMAC, action, 0 /*actionButton*/, 0 /*flags*/,
+ AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0 /*buttonState*/,
+ MotionClassification::NONE, 1 /*xScale*/, 1 /*yScale*/, 0 /*xOffset*/,
+ 0 /*yOffset*/, 0 /*xPrecision*/, 0 /*yPrecision*/,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION,
AMOTION_EVENT_INVALID_CURSOR_POSITION, 0 /*downTime*/,
entry.eventTime.count(), pointerCount, properties, coords);
diff --git a/libs/input/tests/VerifiedInputEvent_test.cpp b/libs/input/tests/VerifiedInputEvent_test.cpp
index a59dbe5..4e8e840 100644
--- a/libs/input/tests/VerifiedInputEvent_test.cpp
+++ b/libs/input/tests/VerifiedInputEvent_test.cpp
@@ -21,9 +21,10 @@
static KeyEvent getKeyEventWithFlags(int32_t flags) {
KeyEvent event;
- event.initialize(2 /*deviceId*/, AINPUT_SOURCE_GAMEPAD, ADISPLAY_ID_DEFAULT, INVALID_HMAC,
- AKEY_EVENT_ACTION_DOWN, flags, AKEYCODE_BUTTON_X, 121 /*scanCode*/,
- AMETA_ALT_ON, 1 /*repeatCount*/, 1000 /*downTime*/, 2000 /*eventTime*/);
+ event.initialize(InputEvent::nextId(), 2 /*deviceId*/, AINPUT_SOURCE_GAMEPAD,
+ ADISPLAY_ID_DEFAULT, INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, flags,
+ AKEYCODE_BUTTON_X, 121 /*scanCode*/, AMETA_ALT_ON, 1 /*repeatCount*/,
+ 1000 /*downTime*/, 2000 /*eventTime*/);
return event;
}
@@ -38,8 +39,8 @@
pointerCoords[i].clear();
}
- event.initialize(0 /*deviceId*/, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_DEFAULT, INVALID_HMAC,
- AMOTION_EVENT_ACTION_DOWN, 0 /*actionButton*/, flags,
+ event.initialize(InputEvent::nextId(), 0 /*deviceId*/, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_DEFAULT,
+ INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0 /*actionButton*/, flags,
AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE, 0 /*buttonState*/,
MotionClassification::NONE, 2 /*xScale*/, 3 /*yScale*/, 4 /*xOffset*/,
5 /*yOffset*/, 0.1 /*xPrecision*/, 0.2 /*yPrecision*/, 280 /*xCursorPosition*/,
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 439d9bf..4ec4e25 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -108,6 +108,7 @@
srcs: [":libinputflinger_base_sources"],
shared_libs: [
"libbase",
+ "libcutils",
"libinput",
"liblog",
"libutils",
diff --git a/services/inputflinger/InputListener.cpp b/services/inputflinger/InputListener.cpp
index de63977..84838ec 100644
--- a/services/inputflinger/InputListener.cpp
+++ b/services/inputflinger/InputListener.cpp
@@ -16,29 +16,32 @@
#define LOG_TAG "InputListener"
+#define ATRACE_TAG ATRACE_TAG_INPUT
+
//#define LOG_NDEBUG 0
#include "InputListener.h"
+#include <android-base/stringprintf.h>
#include <android/log.h>
#include <math.h>
+#include <utils/Trace.h>
+
+using android::base::StringPrintf;
namespace android {
// --- NotifyConfigurationChangedArgs ---
-NotifyConfigurationChangedArgs::NotifyConfigurationChangedArgs(
- uint32_t sequenceNum, nsecs_t eventTime) :
- NotifyArgs(sequenceNum, eventTime) {
-}
+NotifyConfigurationChangedArgs::NotifyConfigurationChangedArgs(int32_t id, nsecs_t eventTime)
+ : NotifyArgs(id, eventTime) {}
NotifyConfigurationChangedArgs::NotifyConfigurationChangedArgs(
- const NotifyConfigurationChangedArgs& other) :
- NotifyArgs(other.sequenceNum, other.eventTime) {
-}
+ const NotifyConfigurationChangedArgs& other)
+ : NotifyArgs(other.id, other.eventTime) {}
bool NotifyConfigurationChangedArgs::operator==(const NotifyConfigurationChangedArgs& rhs) const {
- return sequenceNum == rhs.sequenceNum && eventTime == rhs.eventTime;
+ return id == rhs.id && eventTime == rhs.eventTime;
}
void NotifyConfigurationChangedArgs::notify(const sp<InputListenerInterface>& listener) const {
@@ -48,37 +51,39 @@
// --- NotifyKeyArgs ---
-NotifyKeyArgs::NotifyKeyArgs(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId,
- uint32_t source, int32_t displayId, uint32_t policyFlags,
- int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode,
- int32_t metaState, nsecs_t downTime) :
- NotifyArgs(sequenceNum, eventTime), deviceId(deviceId), source(source),
- displayId(displayId), policyFlags(policyFlags),
- action(action), flags(flags), keyCode(keyCode), scanCode(scanCode),
- metaState(metaState), downTime(downTime) {
-}
+NotifyKeyArgs::NotifyKeyArgs(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source,
+ int32_t displayId, uint32_t policyFlags, int32_t action, int32_t flags,
+ int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime)
+ : NotifyArgs(id, eventTime),
+ deviceId(deviceId),
+ source(source),
+ displayId(displayId),
+ policyFlags(policyFlags),
+ action(action),
+ flags(flags),
+ keyCode(keyCode),
+ scanCode(scanCode),
+ metaState(metaState),
+ downTime(downTime) {}
-NotifyKeyArgs::NotifyKeyArgs(const NotifyKeyArgs& other) :
- NotifyArgs(other.sequenceNum, other.eventTime), deviceId(other.deviceId),
- source(other.source), displayId(other.displayId), policyFlags(other.policyFlags),
- action(other.action), flags(other.flags),
- keyCode(other.keyCode), scanCode(other.scanCode),
- metaState(other.metaState), downTime(other.downTime) {
-}
+NotifyKeyArgs::NotifyKeyArgs(const NotifyKeyArgs& other)
+ : NotifyArgs(other.id, other.eventTime),
+ deviceId(other.deviceId),
+ source(other.source),
+ displayId(other.displayId),
+ policyFlags(other.policyFlags),
+ action(other.action),
+ flags(other.flags),
+ keyCode(other.keyCode),
+ scanCode(other.scanCode),
+ metaState(other.metaState),
+ downTime(other.downTime) {}
bool NotifyKeyArgs::operator==(const NotifyKeyArgs& rhs) const {
- return sequenceNum == rhs.sequenceNum
- && eventTime == rhs.eventTime
- && deviceId == rhs.deviceId
- && source == rhs.source
- && displayId == rhs.displayId
- && policyFlags == rhs.policyFlags
- && action == rhs.action
- && flags == rhs.flags
- && keyCode == rhs.keyCode
- && scanCode == rhs.scanCode
- && metaState == rhs.metaState
- && downTime == rhs.downTime;
+ return id == rhs.id && eventTime == rhs.eventTime && deviceId == rhs.deviceId &&
+ source == rhs.source && displayId == rhs.displayId && policyFlags == rhs.policyFlags &&
+ action == rhs.action && flags == rhs.flags && keyCode == rhs.keyCode &&
+ scanCode == rhs.scanCode && metaState == rhs.metaState && downTime == rhs.downTime;
}
void NotifyKeyArgs::notify(const sp<InputListenerInterface>& listener) const {
@@ -88,15 +93,17 @@
// --- NotifyMotionArgs ---
-NotifyMotionArgs::NotifyMotionArgs(
- uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
- int32_t displayId, uint32_t policyFlags, int32_t action, int32_t actionButton,
- int32_t flags, int32_t metaState, int32_t buttonState, MotionClassification classification,
- int32_t edgeFlags, uint32_t pointerCount, const PointerProperties* pointerProperties,
- const PointerCoords* pointerCoords, float xPrecision, float yPrecision,
- float xCursorPosition, float yCursorPosition, nsecs_t downTime,
- const std::vector<TouchVideoFrame>& videoFrames)
- : NotifyArgs(sequenceNum, eventTime),
+NotifyMotionArgs::NotifyMotionArgs(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source,
+ int32_t displayId, uint32_t policyFlags, int32_t action,
+ int32_t actionButton, int32_t flags, int32_t metaState,
+ int32_t buttonState, MotionClassification classification,
+ int32_t edgeFlags, uint32_t pointerCount,
+ const PointerProperties* pointerProperties,
+ const PointerCoords* pointerCoords, float xPrecision,
+ float yPrecision, float xCursorPosition, float yCursorPosition,
+ nsecs_t downTime,
+ const std::vector<TouchVideoFrame>& videoFrames)
+ : NotifyArgs(id, eventTime),
deviceId(deviceId),
source(source),
displayId(displayId),
@@ -122,7 +129,7 @@
}
NotifyMotionArgs::NotifyMotionArgs(const NotifyMotionArgs& other)
- : NotifyArgs(other.sequenceNum, other.eventTime),
+ : NotifyArgs(other.id, other.eventTime),
deviceId(other.deviceId),
source(other.source),
displayId(other.displayId),
@@ -152,12 +159,11 @@
}
bool NotifyMotionArgs::operator==(const NotifyMotionArgs& rhs) const {
- bool equal = sequenceNum == rhs.sequenceNum && eventTime == rhs.eventTime &&
- deviceId == rhs.deviceId && source == rhs.source && displayId == rhs.displayId &&
- policyFlags == rhs.policyFlags && action == rhs.action &&
- actionButton == rhs.actionButton && flags == rhs.flags && metaState == rhs.metaState &&
- buttonState == rhs.buttonState && classification == rhs.classification &&
- edgeFlags == rhs.edgeFlags &&
+ bool equal = id == rhs.id && eventTime == rhs.eventTime && deviceId == rhs.deviceId &&
+ source == rhs.source && displayId == rhs.displayId && policyFlags == rhs.policyFlags &&
+ action == rhs.action && actionButton == rhs.actionButton && flags == rhs.flags &&
+ metaState == rhs.metaState && buttonState == rhs.buttonState &&
+ classification == rhs.classification && edgeFlags == rhs.edgeFlags &&
pointerCount == rhs.pointerCount
// PointerProperties and PointerCoords are compared separately below
&& xPrecision == rhs.xPrecision && yPrecision == rhs.yPrecision &&
@@ -186,23 +192,22 @@
// --- NotifySwitchArgs ---
-NotifySwitchArgs::NotifySwitchArgs(uint32_t sequenceNum, nsecs_t eventTime, uint32_t policyFlags,
- uint32_t switchValues, uint32_t switchMask) :
- NotifyArgs(sequenceNum, eventTime), policyFlags(policyFlags),
- switchValues(switchValues), switchMask(switchMask) {
-}
+NotifySwitchArgs::NotifySwitchArgs(int32_t id, nsecs_t eventTime, uint32_t policyFlags,
+ uint32_t switchValues, uint32_t switchMask)
+ : NotifyArgs(id, eventTime),
+ policyFlags(policyFlags),
+ switchValues(switchValues),
+ switchMask(switchMask) {}
-NotifySwitchArgs::NotifySwitchArgs(const NotifySwitchArgs& other) :
- NotifyArgs(other.sequenceNum, other.eventTime), policyFlags(other.policyFlags),
- switchValues(other.switchValues), switchMask(other.switchMask) {
-}
+NotifySwitchArgs::NotifySwitchArgs(const NotifySwitchArgs& other)
+ : NotifyArgs(other.id, other.eventTime),
+ policyFlags(other.policyFlags),
+ switchValues(other.switchValues),
+ switchMask(other.switchMask) {}
bool NotifySwitchArgs::operator==(const NotifySwitchArgs rhs) const {
- return sequenceNum == rhs.sequenceNum
- && eventTime == rhs.eventTime
- && policyFlags == rhs.policyFlags
- && switchValues == rhs.switchValues
- && switchMask == rhs.switchMask;
+ return id == rhs.id && eventTime == rhs.eventTime && policyFlags == rhs.policyFlags &&
+ switchValues == rhs.switchValues && switchMask == rhs.switchMask;
}
void NotifySwitchArgs::notify(const sp<InputListenerInterface>& listener) const {
@@ -212,19 +217,14 @@
// --- NotifyDeviceResetArgs ---
-NotifyDeviceResetArgs::NotifyDeviceResetArgs(
- uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId) :
- NotifyArgs(sequenceNum, eventTime), deviceId(deviceId) {
-}
+NotifyDeviceResetArgs::NotifyDeviceResetArgs(int32_t id, nsecs_t eventTime, int32_t deviceId)
+ : NotifyArgs(id, eventTime), deviceId(deviceId) {}
-NotifyDeviceResetArgs::NotifyDeviceResetArgs(const NotifyDeviceResetArgs& other) :
- NotifyArgs(other.sequenceNum, other.eventTime), deviceId(other.deviceId) {
-}
+NotifyDeviceResetArgs::NotifyDeviceResetArgs(const NotifyDeviceResetArgs& other)
+ : NotifyArgs(other.id, other.eventTime), deviceId(other.deviceId) {}
bool NotifyDeviceResetArgs::operator==(const NotifyDeviceResetArgs& rhs) const {
- return sequenceNum == rhs.sequenceNum
- && eventTime == rhs.eventTime
- && deviceId == rhs.deviceId;
+ return id == rhs.id && eventTime == rhs.eventTime && deviceId == rhs.deviceId;
}
void NotifyDeviceResetArgs::notify(const sp<InputListenerInterface>& listener) const {
@@ -234,6 +234,13 @@
// --- QueuedInputListener ---
+static inline void traceEvent(const char* functionName, int32_t id) {
+ if (ATRACE_ENABLED()) {
+ std::string message = StringPrintf("%s(id=0x%" PRIx32 ")", functionName, id);
+ ATRACE_NAME(message.c_str());
+ }
+}
+
QueuedInputListener::QueuedInputListener(const sp<InputListenerInterface>& innerListener) :
mInnerListener(innerListener) {
}
@@ -247,22 +254,27 @@
void QueuedInputListener::notifyConfigurationChanged(
const NotifyConfigurationChangedArgs* args) {
+ traceEvent(__func__, args->id);
mArgsQueue.push_back(new NotifyConfigurationChangedArgs(*args));
}
void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) {
+ traceEvent(__func__, args->id);
mArgsQueue.push_back(new NotifyKeyArgs(*args));
}
void QueuedInputListener::notifyMotion(const NotifyMotionArgs* args) {
+ traceEvent(__func__, args->id);
mArgsQueue.push_back(new NotifyMotionArgs(*args));
}
void QueuedInputListener::notifySwitch(const NotifySwitchArgs* args) {
+ traceEvent(__func__, args->id);
mArgsQueue.push_back(new NotifySwitchArgs(*args));
}
void QueuedInputListener::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
+ traceEvent(__func__, args->id);
mArgsQueue.push_back(new NotifyDeviceResetArgs(*args));
}
diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
index 9a6ef21..3b18813 100644
--- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
+++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
@@ -203,8 +203,9 @@
const nsecs_t currentTime = now();
MotionEvent event;
- event.initialize(DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, INVALID_HMAC,
- AMOTION_EVENT_ACTION_DOWN, /* actionButton */ 0, /* flags */ 0,
+ event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN,
+ /* actionButton */ 0, /* flags */ 0,
/* edgeFlags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
1 /* xScale */, 1 /* yScale */,
/* xOffset */ 0, /* yOffset */ 0, /* xPrecision */ 0,
@@ -228,7 +229,7 @@
const nsecs_t currentTime = now();
// Define a valid motion event.
- NotifyMotionArgs args(/* sequenceNum */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
+ NotifyMotionArgs args(/* id */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_TOUCHSCREEN,
ADISPLAY_ID_DEFAULT, POLICY_FLAG_PASS_TO_USER, AMOTION_EVENT_ACTION_DOWN,
/* actionButton */ 0, /* flags */ 0, AMETA_NONE, /* buttonState */ 0,
MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
@@ -258,14 +259,14 @@
for (auto _ : state) {
// Send ACTION_DOWN
motionArgs.action = AMOTION_EVENT_ACTION_DOWN;
- motionArgs.sequenceNum = 0;
+ motionArgs.id = 0;
motionArgs.downTime = now();
motionArgs.eventTime = motionArgs.downTime;
dispatcher->notifyMotion(&motionArgs);
// Send ACTION_UP
motionArgs.action = AMOTION_EVENT_ACTION_UP;
- motionArgs.sequenceNum = 1;
+ motionArgs.id = 1;
motionArgs.eventTime = now();
dispatcher->notifyMotion(&motionArgs);
diff --git a/services/inputflinger/dispatcher/Connection.cpp b/services/inputflinger/dispatcher/Connection.cpp
index 6f82f4f..188212b 100644
--- a/services/inputflinger/dispatcher/Connection.cpp
+++ b/services/inputflinger/dispatcher/Connection.cpp
@@ -20,11 +20,13 @@
namespace android::inputdispatcher {
-Connection::Connection(const sp<InputChannel>& inputChannel, bool monitor)
+Connection::Connection(const sp<InputChannel>& inputChannel, bool monitor,
+ const IdGenerator& idGenerator)
: status(STATUS_NORMAL),
inputChannel(inputChannel),
monitor(monitor),
inputPublisher(inputChannel),
+ inputState(idGenerator),
inputPublisherBlocked(false) {}
Connection::~Connection() {}
diff --git a/services/inputflinger/dispatcher/Connection.h b/services/inputflinger/dispatcher/Connection.h
index 8423010..bb3f2fe 100644
--- a/services/inputflinger/dispatcher/Connection.h
+++ b/services/inputflinger/dispatcher/Connection.h
@@ -58,7 +58,7 @@
// yet received a "finished" response from the application.
std::deque<DispatchEntry*> waitQueue;
- explicit Connection(const sp<InputChannel>& inputChannel, bool monitor);
+ Connection(const sp<InputChannel>& inputChannel, bool monitor, const IdGenerator& idGenerator);
inline const std::string getInputChannelName() const { return inputChannel->getName(); }
diff --git a/services/inputflinger/dispatcher/Entry.cpp b/services/inputflinger/dispatcher/Entry.cpp
index c4b3789..49630ad 100644
--- a/services/inputflinger/dispatcher/Entry.cpp
+++ b/services/inputflinger/dispatcher/Entry.cpp
@@ -86,8 +86,8 @@
// --- EventEntry ---
-EventEntry::EventEntry(uint32_t sequenceNum, Type type, nsecs_t eventTime, uint32_t policyFlags)
- : sequenceNum(sequenceNum),
+EventEntry::EventEntry(int32_t id, Type type, nsecs_t eventTime, uint32_t policyFlags)
+ : id(id),
refCount(1),
type(type),
eventTime(eventTime),
@@ -117,8 +117,8 @@
// --- ConfigurationChangedEntry ---
-ConfigurationChangedEntry::ConfigurationChangedEntry(uint32_t sequenceNum, nsecs_t eventTime)
- : EventEntry(sequenceNum, Type::CONFIGURATION_CHANGED, eventTime, 0) {}
+ConfigurationChangedEntry::ConfigurationChangedEntry(int32_t id, nsecs_t eventTime)
+ : EventEntry(id, Type::CONFIGURATION_CHANGED, eventTime, 0) {}
ConfigurationChangedEntry::~ConfigurationChangedEntry() {}
@@ -128,8 +128,8 @@
// --- DeviceResetEntry ---
-DeviceResetEntry::DeviceResetEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId)
- : EventEntry(sequenceNum, Type::DEVICE_RESET, eventTime, 0), deviceId(deviceId) {}
+DeviceResetEntry::DeviceResetEntry(int32_t id, nsecs_t eventTime, int32_t deviceId)
+ : EventEntry(id, Type::DEVICE_RESET, eventTime, 0), deviceId(deviceId) {}
DeviceResetEntry::~DeviceResetEntry() {}
@@ -140,9 +140,8 @@
// --- FocusEntry ---
// Focus notifications always go to apps, so set the flag POLICY_FLAG_PASS_TO_USER for all entries
-FocusEntry::FocusEntry(uint32_t sequenceNum, nsecs_t eventTime, sp<IBinder> connectionToken,
- bool hasFocus)
- : EventEntry(sequenceNum, Type::FOCUS, eventTime, POLICY_FLAG_PASS_TO_USER),
+FocusEntry::FocusEntry(int32_t id, nsecs_t eventTime, sp<IBinder> connectionToken, bool hasFocus)
+ : EventEntry(id, Type::FOCUS, eventTime, POLICY_FLAG_PASS_TO_USER),
connectionToken(connectionToken),
hasFocus(hasFocus) {}
@@ -154,11 +153,11 @@
// --- KeyEntry ---
-KeyEntry::KeyEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
+KeyEntry::KeyEntry(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source,
int32_t displayId, uint32_t policyFlags, int32_t action, int32_t flags,
int32_t keyCode, int32_t scanCode, int32_t metaState, int32_t repeatCount,
nsecs_t downTime)
- : EventEntry(sequenceNum, Type::KEY, eventTime, policyFlags),
+ : EventEntry(id, Type::KEY, eventTime, policyFlags),
deviceId(deviceId),
source(source),
displayId(displayId),
@@ -198,7 +197,7 @@
// --- MotionEntry ---
-MotionEntry::MotionEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
+MotionEntry::MotionEntry(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source,
int32_t displayId, uint32_t policyFlags, int32_t action,
int32_t actionButton, int32_t flags, int32_t metaState,
int32_t buttonState, MotionClassification classification,
@@ -206,7 +205,7 @@
float xCursorPosition, float yCursorPosition, nsecs_t downTime,
uint32_t pointerCount, const PointerProperties* pointerProperties,
const PointerCoords* pointerCoords, float xOffset, float yOffset)
- : EventEntry(sequenceNum, Type::MOTION, eventTime, policyFlags),
+ : EventEntry(id, Type::MOTION, eventTime, policyFlags),
eventTime(eventTime),
deviceId(deviceId),
source(source),
diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h
index b5b61cc..ab481bd 100644
--- a/services/inputflinger/dispatcher/Entry.h
+++ b/services/inputflinger/dispatcher/Entry.h
@@ -29,9 +29,6 @@
namespace android::inputdispatcher {
-// Sequence number for synthesized or injected events.
-constexpr uint32_t SYNTHESIZED_EVENT_SEQUENCE_NUM = 0;
-
struct EventEntry {
enum class Type {
CONFIGURATION_CHANGED,
@@ -56,7 +53,7 @@
}
}
- uint32_t sequenceNum;
+ int32_t id;
mutable int32_t refCount;
Type type;
nsecs_t eventTime;
@@ -79,7 +76,7 @@
* (a key is currently pressed), but the repeat itself is generated by the framework.
*/
inline bool isSynthesized() const {
- return isInjected() || sequenceNum == SYNTHESIZED_EVENT_SEQUENCE_NUM;
+ return isInjected() || IdGenerator::getSource(id) != IdGenerator::Source::INPUT_READER;
}
void release();
@@ -87,13 +84,13 @@
virtual void appendDescription(std::string& msg) const = 0;
protected:
- EventEntry(uint32_t sequenceNum, Type type, nsecs_t eventTime, uint32_t policyFlags);
+ EventEntry(int32_t id, Type type, nsecs_t eventTime, uint32_t policyFlags);
virtual ~EventEntry();
void releaseInjectionState();
};
struct ConfigurationChangedEntry : EventEntry {
- explicit ConfigurationChangedEntry(uint32_t sequenceNum, nsecs_t eventTime);
+ explicit ConfigurationChangedEntry(int32_t id, nsecs_t eventTime);
virtual void appendDescription(std::string& msg) const;
protected:
@@ -103,7 +100,7 @@
struct DeviceResetEntry : EventEntry {
int32_t deviceId;
- DeviceResetEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId);
+ DeviceResetEntry(int32_t id, nsecs_t eventTime, int32_t deviceId);
virtual void appendDescription(std::string& msg) const;
protected:
@@ -114,7 +111,7 @@
sp<IBinder> connectionToken;
bool hasFocus;
- FocusEntry(uint32_t sequenceNum, nsecs_t eventTime, sp<IBinder> connectionToken, bool hasFocus);
+ FocusEntry(int32_t id, nsecs_t eventTime, sp<IBinder> connectionToken, bool hasFocus);
virtual void appendDescription(std::string& msg) const;
protected:
@@ -144,10 +141,9 @@
InterceptKeyResult interceptKeyResult; // set based on the interception result
nsecs_t interceptKeyWakeupTime; // used with INTERCEPT_KEY_RESULT_TRY_AGAIN_LATER
- KeyEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
- int32_t displayId, uint32_t policyFlags, int32_t action, int32_t flags,
- int32_t keyCode, int32_t scanCode, int32_t metaState, int32_t repeatCount,
- nsecs_t downTime);
+ KeyEntry(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source, int32_t displayId,
+ uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode,
+ int32_t metaState, int32_t repeatCount, nsecs_t downTime);
virtual void appendDescription(std::string& msg) const;
void recycle();
@@ -176,13 +172,13 @@
PointerProperties pointerProperties[MAX_POINTERS];
PointerCoords pointerCoords[MAX_POINTERS];
- MotionEntry(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
- int32_t displayId, uint32_t policyFlags, int32_t action, int32_t actionButton,
- int32_t flags, int32_t metaState, int32_t buttonState,
- MotionClassification classification, int32_t edgeFlags, float xPrecision,
- float yPrecision, float xCursorPosition, float yCursorPosition, nsecs_t downTime,
- uint32_t pointerCount, const PointerProperties* pointerProperties,
- const PointerCoords* pointerCoords, float xOffset, float yOffset);
+ MotionEntry(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source, int32_t displayId,
+ uint32_t policyFlags, int32_t action, int32_t actionButton, int32_t flags,
+ int32_t metaState, int32_t buttonState, MotionClassification classification,
+ int32_t edgeFlags, float xPrecision, float yPrecision, float xCursorPosition,
+ float yCursorPosition, nsecs_t downTime, uint32_t pointerCount,
+ const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
+ float xOffset, float yOffset);
virtual void appendDescription(std::string& msg) const;
protected:
@@ -202,7 +198,8 @@
float windowYScale = 1.0f;
nsecs_t deliveryTime; // time when the event was actually delivered
- // Set to the resolved action and flags when the event is enqueued.
+ // Set to the resolved ID, action and flags when the event is enqueued.
+ int32_t resolvedEventId;
int32_t resolvedAction;
int32_t resolvedFlags;
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index f9a86dd..308d19b 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -302,7 +302,7 @@
}
MotionEntry* combinedMotionEntry =
- new MotionEntry(motionEntry.sequenceNum, motionEntry.eventTime, motionEntry.deviceId,
+ new MotionEntry(motionEntry.id, motionEntry.eventTime, motionEntry.deviceId,
motionEntry.source, motionEntry.displayId, motionEntry.policyFlags,
motionEntry.action, motionEntry.actionButton, motionEntry.flags,
motionEntry.metaState, motionEntry.buttonState,
@@ -383,6 +383,7 @@
: mPolicy(policy),
mPendingEvent(nullptr),
mLastDropReason(DropReason::NOT_DROPPED),
+ mIdGenerator(IdGenerator::Source::INPUT_DISPATCHER),
mAppSwitchSawKeyDown(false),
mAppSwitchDueTime(LONG_LONG_MAX),
mNextUnblockedEvent(nullptr),
@@ -925,14 +926,15 @@
(POLICY_FLAG_RAW_MASK | POLICY_FLAG_PASS_TO_USER | POLICY_FLAG_TRUSTED);
if (entry->refCount == 1) {
entry->recycle();
+ entry->id = mIdGenerator.nextId();
entry->eventTime = currentTime;
entry->policyFlags = policyFlags;
entry->repeatCount += 1;
} else {
KeyEntry* newEntry =
- new KeyEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, currentTime, entry->deviceId,
- entry->source, entry->displayId, policyFlags, entry->action,
- entry->flags, entry->keyCode, entry->scanCode, entry->metaState,
+ new KeyEntry(mIdGenerator.nextId(), currentTime, entry->deviceId, entry->source,
+ entry->displayId, policyFlags, entry->action, entry->flags,
+ entry->keyCode, entry->scanCode, entry->metaState,
entry->repeatCount + 1, entry->downTime);
mKeyRepeatState.lastKeyEntry = newEntry;
@@ -981,7 +983,7 @@
void InputDispatcher::enqueueFocusEventLocked(const InputWindowHandle& window, bool hasFocus) {
FocusEntry* focusEntry =
- new FocusEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, now(), window.getToken(), hasFocus);
+ new FocusEntry(mIdGenerator.nextId(), now(), window.getToken(), hasFocus);
enqueueInboundEventLocked(focusEntry);
}
@@ -1076,7 +1078,7 @@
setInjectionResult(entry,
*dropReason == DropReason::POLICY ? INPUT_EVENT_INJECTION_SUCCEEDED
: INPUT_EVENT_INJECTION_FAILED);
- mReporter->reportDroppedKey(entry->sequenceNum);
+ mReporter->reportDroppedKey(entry->id);
return true;
}
@@ -2188,8 +2190,8 @@
const InputTarget& inputTarget) {
if (ATRACE_ENABLED()) {
std::string message =
- StringPrintf("prepareDispatchCycleLocked(inputChannel=%s, sequenceNum=%" PRIu32 ")",
- connection->getInputChannelName().c_str(), eventEntry->sequenceNum);
+ StringPrintf("prepareDispatchCycleLocked(inputChannel=%s, id=0x%" PRIx32 ")",
+ connection->getInputChannelName().c_str(), eventEntry->id);
ATRACE_NAME(message.c_str());
}
#if DEBUG_DISPATCH_CYCLE
@@ -2244,9 +2246,8 @@
const InputTarget& inputTarget) {
if (ATRACE_ENABLED()) {
std::string message =
- StringPrintf("enqueueDispatchEntriesLocked(inputChannel=%s, sequenceNum=%" PRIu32
- ")",
- connection->getInputChannelName().c_str(), eventEntry->sequenceNum);
+ StringPrintf("enqueueDispatchEntriesLocked(inputChannel=%s, id=0x%" PRIx32 ")",
+ connection->getInputChannelName().c_str(), eventEntry->id);
ATRACE_NAME(message.c_str());
}
@@ -2300,6 +2301,7 @@
switch (newEntry->type) {
case EventEntry::Type::KEY: {
const KeyEntry& keyEntry = static_cast<const KeyEntry&>(*newEntry);
+ dispatchEntry->resolvedEventId = keyEntry.id;
dispatchEntry->resolvedAction = keyEntry.action;
dispatchEntry->resolvedFlags = keyEntry.flags;
@@ -2316,6 +2318,11 @@
case EventEntry::Type::MOTION: {
const MotionEntry& motionEntry = static_cast<const MotionEntry&>(*newEntry);
+ // Assign a default value to dispatchEntry that will never be generated by InputReader,
+ // and assign a InputDispatcher value if it doesn't change in the if-else chain below.
+ constexpr int32_t DEFAULT_RESOLVED_EVENT_ID =
+ static_cast<int32_t>(IdGenerator::Source::OTHER);
+ dispatchEntry->resolvedEventId = DEFAULT_RESOLVED_EVENT_ID;
if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) {
dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_OUTSIDE;
} else if (dispatchMode & InputTarget::FLAG_DISPATCH_AS_HOVER_EXIT) {
@@ -2328,6 +2335,7 @@
dispatchEntry->resolvedAction = AMOTION_EVENT_ACTION_DOWN;
} else {
dispatchEntry->resolvedAction = motionEntry.action;
+ dispatchEntry->resolvedEventId = motionEntry.id;
}
if (dispatchEntry->resolvedAction == AMOTION_EVENT_ACTION_HOVER_MOVE &&
!connection->inputState.isHovering(motionEntry.deviceId, motionEntry.source,
@@ -2358,6 +2366,17 @@
return; // skip the inconsistent event
}
+ dispatchEntry->resolvedEventId =
+ dispatchEntry->resolvedEventId == DEFAULT_RESOLVED_EVENT_ID
+ ? mIdGenerator.nextId()
+ : motionEntry.id;
+ if (ATRACE_ENABLED() && dispatchEntry->resolvedEventId != motionEntry.id) {
+ std::string message = StringPrintf("Transmute MotionEvent(id=0x%" PRIx32
+ ") to MotionEvent(id=0x%" PRIx32 ").",
+ motionEntry.id, dispatchEntry->resolvedEventId);
+ ATRACE_NAME(message.c_str());
+ }
+
dispatchPointerDownOutsideFocus(motionEntry.source, dispatchEntry->resolvedAction,
inputTarget.inputChannel->getConnectionToken());
@@ -2439,14 +2458,16 @@
std::array<uint8_t, 32> hmac = mHmacKeyManager.sign(verifiedEvent);
// Publish the key event.
- status = connection->inputPublisher
- .publishKeyEvent(dispatchEntry->seq, keyEntry->deviceId,
- keyEntry->source, keyEntry->displayId,
- std::move(hmac), dispatchEntry->resolvedAction,
- dispatchEntry->resolvedFlags, keyEntry->keyCode,
- keyEntry->scanCode, keyEntry->metaState,
- keyEntry->repeatCount, keyEntry->downTime,
- keyEntry->eventTime);
+ status =
+ connection->inputPublisher
+ .publishKeyEvent(dispatchEntry->seq, dispatchEntry->resolvedEventId,
+ keyEntry->deviceId, keyEntry->source,
+ keyEntry->displayId, std::move(hmac),
+ dispatchEntry->resolvedAction,
+ dispatchEntry->resolvedFlags, keyEntry->keyCode,
+ keyEntry->scanCode, keyEntry->metaState,
+ keyEntry->repeatCount, keyEntry->downTime,
+ keyEntry->eventTime);
break;
}
@@ -2495,9 +2516,11 @@
// Publish the motion event.
status = connection->inputPublisher
- .publishMotionEvent(dispatchEntry->seq, motionEntry->deviceId,
- motionEntry->source, motionEntry->displayId,
- std::move(hmac), dispatchEntry->resolvedAction,
+ .publishMotionEvent(dispatchEntry->seq,
+ dispatchEntry->resolvedEventId,
+ motionEntry->deviceId, motionEntry->source,
+ motionEntry->displayId, std::move(hmac),
+ dispatchEntry->resolvedAction,
motionEntry->actionButton,
dispatchEntry->resolvedFlags,
motionEntry->edgeFlags, motionEntry->metaState,
@@ -2516,6 +2539,7 @@
case EventEntry::Type::FOCUS: {
FocusEntry* focusEntry = static_cast<FocusEntry*>(eventEntry);
status = connection->inputPublisher.publishFocusEvent(dispatchEntry->seq,
+ focusEntry->id,
focusEntry->hasFocus,
mInTouchMode);
break;
@@ -2921,10 +2945,17 @@
}
}
+ int32_t newId = mIdGenerator.nextId();
+ if (ATRACE_ENABLED()) {
+ std::string message = StringPrintf("Split MotionEvent(id=0x%" PRIx32
+ ") to MotionEvent(id=0x%" PRIx32 ").",
+ originalMotionEntry.id, newId);
+ ATRACE_NAME(message.c_str());
+ }
MotionEntry* splitMotionEntry =
- new MotionEntry(originalMotionEntry.sequenceNum, originalMotionEntry.eventTime,
- originalMotionEntry.deviceId, originalMotionEntry.source,
- originalMotionEntry.displayId, originalMotionEntry.policyFlags, action,
+ new MotionEntry(newId, originalMotionEntry.eventTime, originalMotionEntry.deviceId,
+ originalMotionEntry.source, originalMotionEntry.displayId,
+ originalMotionEntry.policyFlags, action,
originalMotionEntry.actionButton, originalMotionEntry.flags,
originalMotionEntry.metaState, originalMotionEntry.buttonState,
originalMotionEntry.classification, originalMotionEntry.edgeFlags,
@@ -2951,7 +2982,7 @@
std::scoped_lock _l(mLock);
ConfigurationChangedEntry* newEntry =
- new ConfigurationChangedEntry(args->sequenceNum, args->eventTime);
+ new ConfigurationChangedEntry(args->id, args->eventTime);
needWake = enqueueInboundEventLocked(newEntry);
} // release lock
@@ -3030,9 +3061,9 @@
accelerateMetaShortcuts(args->deviceId, args->action, keyCode, metaState);
KeyEvent event;
- event.initialize(args->deviceId, args->source, args->displayId, INVALID_HMAC, args->action,
- flags, keyCode, args->scanCode, metaState, repeatCount, args->downTime,
- args->eventTime);
+ event.initialize(args->id, args->deviceId, args->source, args->displayId, INVALID_HMAC,
+ args->action, flags, keyCode, args->scanCode, metaState, repeatCount,
+ args->downTime, args->eventTime);
android::base::Timer t;
mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
@@ -3057,7 +3088,7 @@
}
KeyEntry* newEntry =
- new KeyEntry(args->sequenceNum, args->eventTime, args->deviceId, args->source,
+ new KeyEntry(args->id, args->eventTime, args->deviceId, args->source,
args->displayId, policyFlags, args->action, flags, keyCode,
args->scanCode, metaState, repeatCount, args->downTime);
@@ -3076,15 +3107,15 @@
void InputDispatcher::notifyMotion(const NotifyMotionArgs* args) {
#if DEBUG_INBOUND_EVENT_DETAILS
- ALOGD("notifyMotion - eventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32
- ", policyFlags=0x%x, "
+ ALOGD("notifyMotion - id=%" PRIx32 " eventTime=%" PRId64 ", deviceId=%d, source=0x%x, "
+ "displayId=%" PRId32 ", policyFlags=0x%x, "
"action=0x%x, actionButton=0x%x, flags=0x%x, metaState=0x%x, buttonState=0x%x, "
"edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, xCursorPosition=%f, "
"yCursorPosition=%f, downTime=%" PRId64,
- args->eventTime, args->deviceId, args->source, args->displayId, args->policyFlags,
- args->action, args->actionButton, args->flags, args->metaState, args->buttonState,
- args->edgeFlags, args->xPrecision, args->yPrecision, args->xCursorPosition,
- args->yCursorPosition, args->downTime);
+ args->id, args->eventTime, args->deviceId, args->source, args->displayId,
+ args->policyFlags, args->action, args->actionButton, args->flags, args->metaState,
+ args->buttonState, args->edgeFlags, args->xPrecision, args->yPrecision,
+ args->xCursorPosition, args->yCursorPosition, args->downTime);
for (uint32_t i = 0; i < args->pointerCount; i++) {
ALOGD(" Pointer %d: id=%d, toolType=%d, "
"x=%f, y=%f, pressure=%f, size=%f, "
@@ -3125,7 +3156,7 @@
mLock.unlock();
MotionEvent event;
- event.initialize(args->deviceId, args->source, args->displayId, INVALID_HMAC,
+ event.initialize(args->id, args->deviceId, args->source, args->displayId, INVALID_HMAC,
args->action, args->actionButton, args->flags, args->edgeFlags,
args->metaState, args->buttonState, args->classification, 1 /*xScale*/,
1 /*yScale*/, 0 /* xOffset */, 0 /* yOffset */, args->xPrecision,
@@ -3143,7 +3174,7 @@
// Just enqueue a new motion event.
MotionEntry* newEntry =
- new MotionEntry(args->sequenceNum, args->eventTime, args->deviceId, args->source,
+ new MotionEntry(args->id, args->eventTime, args->deviceId, args->source,
args->displayId, policyFlags, args->action, args->actionButton,
args->flags, args->metaState, args->buttonState,
args->classification, args->edgeFlags, args->xPrecision,
@@ -3187,7 +3218,7 @@
std::scoped_lock _l(mLock);
DeviceResetEntry* newEntry =
- new DeviceResetEntry(args->sequenceNum, args->eventTime, args->deviceId);
+ new DeviceResetEntry(args->id, args->eventTime, args->deviceId);
needWake = enqueueInboundEventLocked(newEntry);
} // release lock
@@ -3227,7 +3258,7 @@
accelerateMetaShortcuts(VIRTUAL_KEYBOARD_ID, action,
/*byref*/ keyCode, /*byref*/ metaState);
KeyEvent keyEvent;
- keyEvent.initialize(VIRTUAL_KEYBOARD_ID, incomingKey.getSource(),
+ keyEvent.initialize(incomingKey.getId(), VIRTUAL_KEYBOARD_ID, incomingKey.getSource(),
incomingKey.getDisplayId(), INVALID_HMAC, action, flags, keyCode,
incomingKey.getScanCode(), metaState, incomingKey.getRepeatCount(),
incomingKey.getDownTime(), incomingKey.getEventTime());
@@ -3247,11 +3278,12 @@
mLock.lock();
KeyEntry* injectedEntry =
- new KeyEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, keyEvent.getEventTime(),
- VIRTUAL_KEYBOARD_ID, keyEvent.getSource(), keyEvent.getDisplayId(),
- policyFlags, action, flags, keyEvent.getKeyCode(),
- keyEvent.getScanCode(), keyEvent.getMetaState(),
- keyEvent.getRepeatCount(), keyEvent.getDownTime());
+ new KeyEntry(incomingKey.getId(), incomingKey.getEventTime(),
+ VIRTUAL_KEYBOARD_ID, incomingKey.getSource(),
+ incomingKey.getDisplayId(), policyFlags, action, flags,
+ incomingKey.getKeyCode(), incomingKey.getScanCode(),
+ incomingKey.getMetaState(), incomingKey.getRepeatCount(),
+ incomingKey.getDownTime());
injectedEntries.push(injectedEntry);
break;
}
@@ -3281,13 +3313,12 @@
const nsecs_t* sampleEventTimes = motionEvent->getSampleEventTimes();
const PointerCoords* samplePointerCoords = motionEvent->getSamplePointerCoords();
MotionEntry* injectedEntry =
- new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, *sampleEventTimes,
- VIRTUAL_KEYBOARD_ID, motionEvent->getSource(),
- motionEvent->getDisplayId(), policyFlags, action, actionButton,
- motionEvent->getFlags(), motionEvent->getMetaState(),
- motionEvent->getButtonState(), motionEvent->getClassification(),
- motionEvent->getEdgeFlags(), motionEvent->getXPrecision(),
- motionEvent->getYPrecision(),
+ new MotionEntry(motionEvent->getId(), *sampleEventTimes, VIRTUAL_KEYBOARD_ID,
+ motionEvent->getSource(), motionEvent->getDisplayId(),
+ policyFlags, action, actionButton, motionEvent->getFlags(),
+ motionEvent->getMetaState(), motionEvent->getButtonState(),
+ motionEvent->getClassification(), motionEvent->getEdgeFlags(),
+ motionEvent->getXPrecision(), motionEvent->getYPrecision(),
motionEvent->getRawXCursorPosition(),
motionEvent->getRawYCursorPosition(),
motionEvent->getDownTime(), uint32_t(pointerCount),
@@ -3298,7 +3329,7 @@
sampleEventTimes += 1;
samplePointerCoords += pointerCount;
MotionEntry* nextInjectedEntry =
- new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, *sampleEventTimes,
+ new MotionEntry(motionEvent->getId(), *sampleEventTimes,
VIRTUAL_KEYBOARD_ID, motionEvent->getSource(),
motionEvent->getDisplayId(), policyFlags, action,
actionButton, motionEvent->getFlags(),
@@ -4226,7 +4257,7 @@
return BAD_VALUE;
}
- sp<Connection> connection = new Connection(inputChannel, false /*monitor*/);
+ sp<Connection> connection = new Connection(inputChannel, false /*monitor*/, mIdGenerator);
int fd = inputChannel->getFd();
mConnectionsByFd[fd] = connection;
@@ -4255,7 +4286,7 @@
return BAD_VALUE;
}
- sp<Connection> connection = new Connection(inputChannel, true /*monitor*/);
+ sp<Connection> connection = new Connection(inputChannel, true /*monitor*/, mIdGenerator);
const int fd = inputChannel->getFd();
mConnectionsByFd[fd] = connection;
@@ -4630,7 +4661,7 @@
if (keyEntry->flags & AKEY_EVENT_FLAG_FALLBACK) {
if (!handled) {
// Report the key as unhandled, since the fallback was not handled.
- mReporter->reportUnhandledKey(keyEntry->sequenceNum);
+ mReporter->reportUnhandledKey(keyEntry->id);
}
return false;
}
@@ -4795,7 +4826,7 @@
#endif
// Report the key as unhandled, since there is no fallback key.
- mReporter->reportUnhandledKey(keyEntry->sequenceNum);
+ mReporter->reportUnhandledKey(keyEntry->id);
}
}
return false;
@@ -4817,9 +4848,9 @@
KeyEvent InputDispatcher::createKeyEvent(const KeyEntry& entry) {
KeyEvent event;
- event.initialize(entry.deviceId, entry.source, entry.displayId, INVALID_HMAC, entry.action,
- entry.flags, entry.keyCode, entry.scanCode, entry.metaState, entry.repeatCount,
- entry.downTime, entry.eventTime);
+ event.initialize(entry.id, entry.deviceId, entry.source, entry.displayId, INVALID_HMAC,
+ entry.action, entry.flags, entry.keyCode, entry.scanCode, entry.metaState,
+ entry.repeatCount, entry.downTime, entry.eventTime);
return event;
}
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 482133e..4aa47f8 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -156,6 +156,8 @@
DropReason mLastDropReason GUARDED_BY(mLock);
+ const IdGenerator mIdGenerator;
+
// With each iteration, InputDispatcher nominally processes one queued event,
// a timeout, or a response from an input consumer.
// This method should only be called on the input dispatcher's own thread.
diff --git a/services/inputflinger/dispatcher/InputState.cpp b/services/inputflinger/dispatcher/InputState.cpp
index 053598a..386056d 100644
--- a/services/inputflinger/dispatcher/InputState.cpp
+++ b/services/inputflinger/dispatcher/InputState.cpp
@@ -16,9 +16,11 @@
#include "InputState.h"
+#include "InputDispatcher.h"
+
namespace android::inputdispatcher {
-InputState::InputState() {}
+InputState::InputState(const IdGenerator& idGenerator) : mIdGenerator(idGenerator) {}
InputState::~InputState() {}
@@ -268,9 +270,9 @@
std::vector<EventEntry*> events;
for (KeyMemento& memento : mKeyMementos) {
if (shouldCancelKey(memento, options)) {
- events.push_back(new KeyEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, currentTime,
- memento.deviceId, memento.source, memento.displayId,
- memento.policyFlags, AKEY_EVENT_ACTION_UP,
+ events.push_back(new KeyEntry(mIdGenerator.nextId(), currentTime, memento.deviceId,
+ memento.source, memento.displayId, memento.policyFlags,
+ AKEY_EVENT_ACTION_UP,
memento.flags | AKEY_EVENT_FLAG_CANCELED, memento.keyCode,
memento.scanCode, memento.metaState, 0 /*repeatCount*/,
memento.downTime));
@@ -281,11 +283,10 @@
if (shouldCancelMotion(memento, options)) {
const int32_t action = memento.hovering ? AMOTION_EVENT_ACTION_HOVER_EXIT
: AMOTION_EVENT_ACTION_CANCEL;
- events.push_back(new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, currentTime,
- memento.deviceId, memento.source, memento.displayId,
- memento.policyFlags, action, 0 /*actionButton*/,
- memento.flags, AMETA_NONE, 0 /*buttonState*/,
- MotionClassification::NONE,
+ events.push_back(new MotionEntry(mIdGenerator.nextId(), currentTime, memento.deviceId,
+ memento.source, memento.displayId, memento.policyFlags,
+ action, 0 /*actionButton*/, memento.flags, AMETA_NONE,
+ 0 /*buttonState*/, MotionClassification::NONE,
AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
memento.yPrecision, memento.xCursorPosition,
memento.yCursorPosition, memento.downTime,
@@ -332,16 +333,15 @@
: AMOTION_EVENT_ACTION_POINTER_DOWN
| (i << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
- events.push_back(new MotionEntry(SYNTHESIZED_EVENT_SEQUENCE_NUM, currentTime,
- memento.deviceId, memento.source, memento.displayId,
- memento.policyFlags, action, 0 /*actionButton*/,
- memento.flags, AMETA_NONE, 0 /*buttonState*/,
- MotionClassification::NONE,
+ events.push_back(new MotionEntry(mIdGenerator.nextId(), currentTime, memento.deviceId,
+ memento.source, memento.displayId, memento.policyFlags,
+ action, 0 /*actionButton*/, memento.flags, AMETA_NONE,
+ 0 /*buttonState*/, MotionClassification::NONE,
AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
memento.yPrecision, memento.xCursorPosition,
memento.yCursorPosition, memento.downTime,
- pointerCount, pointerProperties,
- pointerCoords, 0 /*xOffset*/, 0 /*yOffset*/));
+ pointerCount, pointerProperties, pointerCoords,
+ 0 /*xOffset*/, 0 /*yOffset*/));
}
memento.firstNewPointerIdx = INVALID_POINTER_INDEX;
diff --git a/services/inputflinger/dispatcher/InputState.h b/services/inputflinger/dispatcher/InputState.h
index 08266ae..d97a664 100644
--- a/services/inputflinger/dispatcher/InputState.h
+++ b/services/inputflinger/dispatcher/InputState.h
@@ -30,7 +30,7 @@
* synthesized when events are dropped. */
class InputState {
public:
- InputState();
+ explicit InputState(const IdGenerator& idGenerator);
~InputState();
// Returns true if there is no state to be canceled.
@@ -111,6 +111,8 @@
void mergePointerStateTo(MotionMemento& other) const;
};
+ const IdGenerator& mIdGenerator; // InputDispatcher owns it so we won't have dangling reference.
+
std::vector<KeyMemento> mKeyMementos;
std::vector<MotionMemento> mMotionMementos;
KeyedVector<int32_t, int32_t> mFallbackKeys;
diff --git a/services/inputflinger/include/InputListener.h b/services/inputflinger/include/InputListener.h
index 0dcd2f9..f8d0150 100644
--- a/services/inputflinger/include/InputListener.h
+++ b/services/inputflinger/include/InputListener.h
@@ -31,13 +31,12 @@
/* Superclass of all input event argument objects */
struct NotifyArgs {
- uint32_t sequenceNum;
+ int32_t id;
nsecs_t eventTime;
- inline NotifyArgs() : sequenceNum(0), eventTime(0) { }
+ inline NotifyArgs() : id(0), eventTime(0) {}
- inline explicit NotifyArgs(uint32_t sequenceNum, nsecs_t eventTime) :
- sequenceNum(sequenceNum), eventTime(eventTime) { }
+ inline explicit NotifyArgs(int32_t id, nsecs_t eventTime) : id(id), eventTime(eventTime) {}
virtual ~NotifyArgs() { }
@@ -52,7 +51,7 @@
bool operator==(const NotifyConfigurationChangedArgs& rhs) const;
- NotifyConfigurationChangedArgs(uint32_t sequenceNum, nsecs_t eventTime);
+ NotifyConfigurationChangedArgs(int32_t id, nsecs_t eventTime);
NotifyConfigurationChangedArgs(const NotifyConfigurationChangedArgs& other);
@@ -77,9 +76,9 @@
inline NotifyKeyArgs() { }
- NotifyKeyArgs(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
- int32_t displayId, uint32_t policyFlags, int32_t action, int32_t flags, int32_t keyCode,
- int32_t scanCode, int32_t metaState, nsecs_t downTime);
+ NotifyKeyArgs(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source,
+ int32_t displayId, uint32_t policyFlags, int32_t action, int32_t flags,
+ int32_t keyCode, int32_t scanCode, int32_t metaState, nsecs_t downTime);
bool operator==(const NotifyKeyArgs& rhs) const;
@@ -125,7 +124,7 @@
inline NotifyMotionArgs() { }
- NotifyMotionArgs(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId, uint32_t source,
+ NotifyMotionArgs(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source,
int32_t displayId, uint32_t policyFlags, int32_t action, int32_t actionButton,
int32_t flags, int32_t metaState, int32_t buttonState,
MotionClassification classification, int32_t edgeFlags, uint32_t pointerCount,
@@ -152,8 +151,8 @@
inline NotifySwitchArgs() { }
- NotifySwitchArgs(uint32_t sequenceNum, nsecs_t eventTime, uint32_t policyFlags,
- uint32_t switchValues, uint32_t switchMask);
+ NotifySwitchArgs(int32_t id, nsecs_t eventTime, uint32_t policyFlags, uint32_t switchValues,
+ uint32_t switchMask);
NotifySwitchArgs(const NotifySwitchArgs& other);
@@ -172,7 +171,7 @@
inline NotifyDeviceResetArgs() { }
- NotifyDeviceResetArgs(uint32_t sequenceNum, nsecs_t eventTime, int32_t deviceId);
+ NotifyDeviceResetArgs(int32_t id, nsecs_t eventTime, int32_t deviceId);
NotifyDeviceResetArgs(const NotifyDeviceResetArgs& other);
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index d0eee64..4b19e5e 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -449,16 +449,12 @@
for_each_mapper([keyCode](InputMapper& mapper) { mapper.updateMetaState(keyCode); });
}
-void InputDevice::fadePointer() {
- for_each_mapper([](InputMapper& mapper) { mapper.fadePointer(); });
-}
-
void InputDevice::bumpGeneration() {
mGeneration = mContext->bumpGeneration();
}
void InputDevice::notifyReset(nsecs_t when) {
- NotifyDeviceResetArgs args(mContext->getNextSequenceNum(), when, mId);
+ NotifyDeviceResetArgs args(mContext->getNextId(), when, mId);
mContext->getListener()->notifyDeviceReset(&args);
}
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index cbfa702..657a134 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -46,7 +46,6 @@
: mContext(this),
mEventHub(eventHub),
mPolicy(policy),
- mNextSequenceNum(1),
mGlobalMetaState(0),
mGeneration(1),
mNextInputDeviceId(END_RESERVED_ID),
@@ -313,7 +312,7 @@
updateGlobalMetaStateLocked();
// Enqueue configuration changed.
- NotifyConfigurationChangedArgs args(mContext.getNextSequenceNum(), when);
+ NotifyConfigurationChangedArgs args(mContext.getNextId(), when);
mQueuedListener->notifyConfigurationChanged(&args);
}
@@ -326,6 +325,10 @@
InputReaderConfiguration::changesToString(changes).c_str());
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
+ if (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO) {
+ updatePointerDisplayLocked();
+ }
+
if (changes & InputReaderConfiguration::CHANGE_MUST_REOPEN) {
mEventHub->requestReopenDevices();
} else {
@@ -387,10 +390,43 @@
}
}
+sp<PointerControllerInterface> InputReader::getPointerControllerLocked(int32_t deviceId) {
+ sp<PointerControllerInterface> controller = mPointerController.promote();
+ if (controller == nullptr) {
+ controller = mPolicy->obtainPointerController(deviceId);
+ mPointerController = controller;
+ updatePointerDisplayLocked();
+ }
+ return controller;
+}
+
+void InputReader::updatePointerDisplayLocked() {
+ sp<PointerControllerInterface> controller = mPointerController.promote();
+ if (controller == nullptr) {
+ return;
+ }
+
+ std::optional<DisplayViewport> viewport =
+ mConfig.getDisplayViewportById(mConfig.defaultPointerDisplayId);
+ if (!viewport) {
+ ALOGW("Can't find the designated viewport with ID %" PRId32 " to update cursor input "
+ "mapper. Fall back to default display",
+ mConfig.defaultPointerDisplayId);
+ viewport = mConfig.getDisplayViewportById(ADISPLAY_ID_DEFAULT);
+ }
+ if (!viewport) {
+ ALOGE("Still can't find a viable viewport to update cursor input mapper. Skip setting it to"
+ " PointerController.");
+ return;
+ }
+
+ controller->setDisplayViewport(*viewport);
+}
+
void InputReader::fadePointerLocked() {
- for (auto& devicePair : mDevices) {
- std::shared_ptr<InputDevice>& device = devicePair.second;
- device->fadePointer();
+ sp<PointerControllerInterface> controller = mPointerController.promote();
+ if (controller != nullptr) {
+ controller->fade(PointerControllerInterface::TRANSITION_GRADUAL);
}
}
@@ -660,7 +696,8 @@
// --- InputReader::ContextImpl ---
-InputReader::ContextImpl::ContextImpl(InputReader* reader) : mReader(reader) {}
+InputReader::ContextImpl::ContextImpl(InputReader* reader)
+ : mReader(reader), mIdGenerator(IdGenerator::Source::INPUT_READER) {}
void InputReader::ContextImpl::updateGlobalMetaState() {
// lock is already held by the input loop
@@ -688,6 +725,11 @@
mReader->fadePointerLocked();
}
+sp<PointerControllerInterface> InputReader::ContextImpl::getPointerController(int32_t deviceId) {
+ // lock is already held by the input loop
+ return mReader->getPointerControllerLocked(deviceId);
+}
+
void InputReader::ContextImpl::requestTimeoutAtTime(nsecs_t when) {
// lock is already held by the input loop
mReader->requestTimeoutAtTimeLocked(when);
@@ -719,8 +761,8 @@
return mReader->mEventHub.get();
}
-uint32_t InputReader::ContextImpl::getNextSequenceNum() {
- return (mReader->mNextSequenceNum)++;
+int32_t InputReader::ContextImpl::getNextId() {
+ return mIdGenerator.nextId();
}
} // namespace android
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index aaa0d26..71313fc 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -88,8 +88,6 @@
int32_t getMetaState();
void updateMetaState(int32_t keyCode);
- void fadePointer();
-
void bumpGeneration();
void notifyReset(nsecs_t when);
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index 31d82f1..693ec30 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -23,6 +23,7 @@
#include "InputReaderContext.h"
#include "InputThread.h"
+#include <PointerControllerInterface.h>
#include <utils/Condition.h>
#include <utils/Mutex.h>
@@ -93,6 +94,7 @@
class ContextImpl : public InputReaderContext {
InputReader* mReader;
+ IdGenerator mIdGenerator;
public:
explicit ContextImpl(InputReader* reader);
@@ -102,6 +104,7 @@
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 sp<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;
@@ -109,7 +112,7 @@
virtual InputReaderPolicyInterface* getPolicy() override;
virtual InputListenerInterface* getListener() override;
virtual EventHubInterface* getEventHub() override;
- virtual uint32_t getNextSequenceNum() override;
+ virtual int32_t getNextId() override;
} mContext;
friend class ContextImpl;
@@ -130,9 +133,6 @@
InputReaderConfiguration mConfig;
- // used by InputReaderContext::getNextSequenceNum() as a counter for event sequence numbers
- uint32_t mNextSequenceNum;
-
// The event queue.
static const int EVENT_BUFFER_SIZE = 256;
RawEvent mEventBuffer[EVENT_BUFFER_SIZE];
@@ -159,6 +159,10 @@
void getExternalStylusDevicesLocked(std::vector<InputDeviceInfo>& outDevices);
void dispatchExternalStylusState(const StylusState& state);
+ // The PointerController that is shared among all the input devices that need it.
+ wp<PointerControllerInterface> mPointerController;
+ sp<PointerControllerInterface> getPointerControllerLocked(int32_t deviceId);
+ void updatePointerDisplayLocked();
void fadePointerLocked();
int32_t mGeneration;
diff --git a/services/inputflinger/reader/include/InputReaderContext.h b/services/inputflinger/reader/include/InputReaderContext.h
index e14fbbe..85701e4 100644
--- a/services/inputflinger/reader/include/InputReaderContext.h
+++ b/services/inputflinger/reader/include/InputReaderContext.h
@@ -28,6 +28,7 @@
class InputListenerInterface;
class InputMapper;
class InputReaderPolicyInterface;
+class PointerControllerInterface;
struct StylusState;
/* Internal interface used by individual input devices to access global input device state
@@ -45,6 +46,7 @@
virtual bool shouldDropVirtualKey(nsecs_t now, int32_t keyCode, int32_t scanCode) = 0;
virtual void fadePointer() = 0;
+ virtual sp<PointerControllerInterface> getPointerController(int32_t deviceId) = 0;
virtual void requestTimeoutAtTime(nsecs_t when) = 0;
virtual int32_t bumpGeneration() = 0;
@@ -56,7 +58,7 @@
virtual InputListenerInterface* getListener() = 0;
virtual EventHubInterface* getEventHub() = 0;
- virtual uint32_t getNextSequenceNum() = 0;
+ virtual int32_t getNextId() = 0;
};
} // namespace android
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
index 520a4a4..887ab53 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
@@ -132,7 +132,7 @@
mYPrecision = 1.0f;
mXScale = 1.0f;
mYScale = 1.0f;
- mPointerController = getPolicy()->obtainPointerController(getDeviceId());
+ mPointerController = getContext()->getPointerController(getDeviceId());
break;
case Parameters::MODE_NAVIGATION:
mSource = AINPUT_SOURCE_TRACKBALL;
@@ -168,7 +168,7 @@
}
bumpGeneration();
if (changes) {
- NotifyDeviceResetArgs args(getContext()->getNextSequenceNum(), when, getDeviceId());
+ NotifyDeviceResetArgs args(getContext()->getNextId(), when, getDeviceId());
getListener()->notifyDeviceReset(&args);
}
}
@@ -189,34 +189,10 @@
}
}
- // Update the PointerController if viewports changed.
- if (mParameters.mode == Parameters::MODE_POINTER) {
- updatePointerControllerDisplayViewport(*config);
- }
bumpGeneration();
}
}
-void CursorInputMapper::updatePointerControllerDisplayViewport(
- const InputReaderConfiguration& config) {
- std::optional<DisplayViewport> viewport =
- config.getDisplayViewportById(config.defaultPointerDisplayId);
- if (!viewport) {
- ALOGW("Can't find the designated viewport with ID %" PRId32 " to update cursor input "
- "mapper. Fall back to default display",
- config.defaultPointerDisplayId);
- viewport = config.getDisplayViewportById(ADISPLAY_ID_DEFAULT);
- }
-
- if (!viewport) {
- ALOGE("Still can't find a viable viewport to update cursor input mapper. Skip setting it to"
- " PointerController.");
- return;
- }
-
- mPointerController->setDisplayViewport(*viewport);
-}
-
void CursorInputMapper::configureParameters() {
mParameters.mode = Parameters::MODE_POINTER;
String8 cursorModeString;
@@ -398,8 +374,8 @@
while (!released.isEmpty()) {
int32_t actionButton = BitSet32::valueForBit(released.clearFirstMarkedBit());
buttonState &= ~actionButton;
- NotifyMotionArgs releaseArgs(getContext()->getNextSequenceNum(), when,
- getDeviceId(), mSource, displayId, policyFlags,
+ NotifyMotionArgs releaseArgs(getContext()->getNextId(), when, getDeviceId(),
+ mSource, displayId, policyFlags,
AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
metaState, buttonState, MotionClassification::NONE,
AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
@@ -410,11 +386,11 @@
}
}
- NotifyMotionArgs args(getContext()->getNextSequenceNum(), when, getDeviceId(), mSource,
- displayId, policyFlags, motionEventAction, 0, 0, metaState,
- currentButtonState, MotionClassification::NONE,
- AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties, &pointerCoords,
- mXPrecision, mYPrecision, xCursorPosition, yCursorPosition, downTime,
+ NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, displayId,
+ policyFlags, motionEventAction, 0, 0, metaState, currentButtonState,
+ MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
+ &pointerProperties, &pointerCoords, mXPrecision, mYPrecision,
+ xCursorPosition, yCursorPosition, downTime,
/* videoFrames */ {});
getListener()->notifyMotion(&args);
@@ -423,8 +399,8 @@
while (!pressed.isEmpty()) {
int32_t actionButton = BitSet32::valueForBit(pressed.clearFirstMarkedBit());
buttonState |= actionButton;
- NotifyMotionArgs pressArgs(getContext()->getNextSequenceNum(), when, getDeviceId(),
- mSource, displayId, policyFlags,
+ NotifyMotionArgs pressArgs(getContext()->getNextId(), when, getDeviceId(), mSource,
+ displayId, policyFlags,
AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton, 0,
metaState, buttonState, MotionClassification::NONE,
AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
@@ -439,10 +415,9 @@
// Send hover move after UP to tell the application that the mouse is hovering now.
if (motionEventAction == AMOTION_EVENT_ACTION_UP && (mSource == AINPUT_SOURCE_MOUSE)) {
- NotifyMotionArgs hoverArgs(getContext()->getNextSequenceNum(), when, getDeviceId(),
- mSource, displayId, policyFlags,
- AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
- currentButtonState, MotionClassification::NONE,
+ NotifyMotionArgs hoverArgs(getContext()->getNextId(), when, getDeviceId(), mSource,
+ displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
+ 0, metaState, currentButtonState, MotionClassification::NONE,
AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
&pointerCoords, mXPrecision, mYPrecision, xCursorPosition,
yCursorPosition, downTime, /* videoFrames */ {});
@@ -454,10 +429,9 @@
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
- NotifyMotionArgs scrollArgs(getContext()->getNextSequenceNum(), when, getDeviceId(),
- mSource, displayId, policyFlags,
- AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState,
- currentButtonState, MotionClassification::NONE,
+ NotifyMotionArgs scrollArgs(getContext()->getNextId(), when, getDeviceId(), mSource,
+ displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0,
+ metaState, currentButtonState, MotionClassification::NONE,
AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
&pointerCoords, mXPrecision, mYPrecision, xCursorPosition,
yCursorPosition, downTime, /* videoFrames */ {});
@@ -481,12 +455,6 @@
}
}
-void CursorInputMapper::fadePointer() {
- if (mPointerController != nullptr) {
- mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
- }
-}
-
std::optional<int32_t> CursorInputMapper::getAssociatedDisplayId() {
if (mParameters.hasAssociatedDisplay) {
if (mParameters.mode == Parameters::MODE_POINTER) {
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.h b/services/inputflinger/reader/mapper/CursorInputMapper.h
index 94ab306..f65ac39 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.h
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.h
@@ -66,8 +66,6 @@
virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode) override;
- virtual void fadePointer() override;
-
virtual std::optional<int32_t> getAssociatedDisplayId() override;
private:
@@ -117,7 +115,6 @@
void dumpParameters(std::string& dump);
void sync(nsecs_t when);
- void updatePointerControllerDisplayViewport(const InputReaderConfiguration& config);
};
} // namespace android
diff --git a/services/inputflinger/reader/mapper/InputMapper.cpp b/services/inputflinger/reader/mapper/InputMapper.cpp
index c5f99c9..a8fe39a 100644
--- a/services/inputflinger/reader/mapper/InputMapper.cpp
+++ b/services/inputflinger/reader/mapper/InputMapper.cpp
@@ -71,8 +71,6 @@
void InputMapper::updateExternalStylusState(const StylusState& state) {}
-void InputMapper::fadePointer() {}
-
status_t InputMapper::getAbsoluteAxisInfo(int32_t axis, RawAbsoluteAxisInfo* axisInfo) {
return getDeviceContext().getAbsoluteAxisInfo(axis, axisInfo);
}
diff --git a/services/inputflinger/reader/mapper/InputMapper.h b/services/inputflinger/reader/mapper/InputMapper.h
index 09888bf..949c7ea 100644
--- a/services/inputflinger/reader/mapper/InputMapper.h
+++ b/services/inputflinger/reader/mapper/InputMapper.h
@@ -71,7 +71,6 @@
virtual void updateExternalStylusState(const StylusState& state);
- virtual void fadePointer();
virtual std::optional<int32_t> getAssociatedDisplayId() { return std::nullopt; }
protected:
diff --git a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
index 7c3b1d9..030a846 100644
--- a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
@@ -333,10 +333,9 @@
// TODO: Use the input device configuration to control this behavior more finely.
uint32_t policyFlags = 0;
- NotifyMotionArgs args(getContext()->getNextSequenceNum(), when, getDeviceId(),
- AINPUT_SOURCE_JOYSTICK, ADISPLAY_ID_NONE, policyFlags,
- AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState, buttonState,
- MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
+ NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), AINPUT_SOURCE_JOYSTICK,
+ ADISPLAY_ID_NONE, policyFlags, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState,
+ buttonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
&pointerProperties, &pointerCoords, 0, 0,
AMOTION_EVENT_INVALID_CURSOR_POSITION,
AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, /* videoFrames */ {});
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
index ab354a2..7be4a58 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
@@ -348,9 +348,8 @@
policyFlags |= POLICY_FLAG_DISABLE_KEY_REPEAT;
}
- NotifyKeyArgs args(getContext()->getNextSequenceNum(), when, getDeviceId(), mSource,
- getDisplayId(), policyFlags,
- down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
+ NotifyKeyArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, getDisplayId(),
+ policyFlags, down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, keyMetaState, downTime);
getListener()->notifyKey(&args);
}
diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
index ed93f14..9885889 100644
--- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
@@ -119,9 +119,9 @@
int32_t metaState = getContext()->getGlobalMetaState();
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_SCROLL, scroll * mScalingFactor);
- NotifyMotionArgs scrollArgs(getContext()->getNextSequenceNum(), when, getDeviceId(),
- mSource, displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0,
- 0, metaState, /* buttonState */ 0, MotionClassification::NONE,
+ NotifyMotionArgs scrollArgs(getContext()->getNextId(), when, getDeviceId(), mSource,
+ displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0,
+ metaState, /* buttonState */ 0, MotionClassification::NONE,
AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties,
&pointerCoords, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
AMOTION_EVENT_INVALID_CURSOR_POSITION, 0, /* videoFrames */ {});
diff --git a/services/inputflinger/reader/mapper/SwitchInputMapper.cpp b/services/inputflinger/reader/mapper/SwitchInputMapper.cpp
index e79aeb2..4f73681 100644
--- a/services/inputflinger/reader/mapper/SwitchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/SwitchInputMapper.cpp
@@ -56,7 +56,7 @@
void SwitchInputMapper::sync(nsecs_t when) {
if (mUpdatedSwitchMask) {
uint32_t updatedSwitchValues = mSwitchValues & mUpdatedSwitchMask;
- NotifySwitchArgs args(getContext()->getNextSequenceNum(), when, 0 /*policyFlags*/,
+ NotifySwitchArgs args(getContext()->getNextId(), when, 0 /*policyFlags*/,
updatedSwitchValues, mUpdatedSwitchMask);
getListener()->notifySwitch(&args);
diff --git a/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h b/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h
index efa3d6d..2a3e263 100644
--- a/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h
+++ b/services/inputflinger/reader/mapper/TouchCursorInputMapperCommon.h
@@ -65,8 +65,8 @@
(currentButtonState & buttonState)) ||
(action == AKEY_EVENT_ACTION_UP && (lastButtonState & buttonState) &&
!(currentButtonState & buttonState))) {
- NotifyKeyArgs args(context->getNextSequenceNum(), when, deviceId, source, displayId,
- policyFlags, action, 0, keyCode, 0, context->getGlobalMetaState(), when);
+ NotifyKeyArgs args(context->getNextId(), when, deviceId, source, displayId, policyFlags,
+ action, 0, keyCode, 0, context->getGlobalMetaState(), when);
context->getListener()->notifyKey(&args);
}
}
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index b3a6df8..bbc8e53 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -386,7 +386,7 @@
if (changes && resetNeeded) {
// Send reset, unless this is the first time the device has been configured,
// in which case the reader will call reset itself after all mappers are ready.
- NotifyDeviceResetArgs args(getContext()->getNextSequenceNum(), when, getDeviceId());
+ NotifyDeviceResetArgs args(getContext()->getNextId(), when, getDeviceId());
getListener()->notifyDeviceReset(&args);
}
}
@@ -756,16 +756,11 @@
mOrientedRanges.clear();
}
- // Create or update pointer controller if needed.
+ // Create pointer controller if needed.
if (mDeviceMode == DEVICE_MODE_POINTER ||
(mDeviceMode == DEVICE_MODE_DIRECT && mConfig.showTouches)) {
- if (mPointerController == nullptr || viewportChanged) {
- mPointerController = getPolicy()->obtainPointerController(getDeviceId());
- // Set the DisplayViewport for the PointerController to the default pointer display
- // that is recommended by the configuration before using it.
- std::optional<DisplayViewport> defaultViewport =
- mConfig.getDisplayViewportById(mConfig.defaultPointerDisplayId);
- mPointerController->setDisplayViewport(defaultViewport.value_or(mViewport));
+ if (mPointerController == nullptr) {
+ mPointerController = getContext()->getPointerController(getDeviceId());
}
} else {
mPointerController.clear();
@@ -1829,9 +1824,9 @@
int32_t metaState = getContext()->getGlobalMetaState();
policyFlags |= POLICY_FLAG_VIRTUAL;
- NotifyKeyArgs args(getContext()->getNextSequenceNum(), when, getDeviceId(),
- AINPUT_SOURCE_KEYBOARD, mViewport.displayId, policyFlags, keyEventAction,
- keyEventFlags, keyCode, scanCode, metaState, downTime);
+ NotifyKeyArgs args(getContext()->getNextId(), when, getDeviceId(), AINPUT_SOURCE_KEYBOARD,
+ mViewport.displayId, policyFlags, keyEventAction, keyEventFlags, keyCode,
+ scanCode, metaState, downTime);
getListener()->notifyKey(&args);
}
@@ -2503,11 +2498,11 @@
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
const int32_t displayId = mPointerController->getDisplayId();
- NotifyMotionArgs args(getContext()->getNextSequenceNum(), when, getDeviceId(), mSource,
- displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
- metaState, buttonState, MotionClassification::NONE,
- AMOTION_EVENT_EDGE_FLAG_NONE, 1, &pointerProperties, &pointerCoords,
- 0, 0, x, y, mPointerGesture.downTime, /* videoFrames */ {});
+ NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, displayId,
+ policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
+ buttonState, MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE,
+ 1, &pointerProperties, &pointerCoords, 0, 0, x, y,
+ mPointerGesture.downTime, /* videoFrames */ {});
getListener()->notifyMotion(&args);
}
@@ -3423,8 +3418,8 @@
mPointerSimple.down = false;
// Send up.
- NotifyMotionArgs args(getContext()->getNextSequenceNum(), when, getDeviceId(), mSource,
- displayId, policyFlags, AMOTION_EVENT_ACTION_UP, 0, 0, metaState,
+ NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, displayId,
+ policyFlags, AMOTION_EVENT_ACTION_UP, 0, 0, metaState,
mLastRawState.buttonState, MotionClassification::NONE,
AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.lastProperties,
&mPointerSimple.lastCoords, mOrientedXPrecision, mOrientedYPrecision,
@@ -3437,9 +3432,9 @@
mPointerSimple.hovering = false;
// Send hover exit.
- NotifyMotionArgs args(getContext()->getNextSequenceNum(), when, getDeviceId(), mSource,
- displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0,
- metaState, mLastRawState.buttonState, MotionClassification::NONE,
+ NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, displayId,
+ policyFlags, AMOTION_EVENT_ACTION_HOVER_EXIT, 0, 0, metaState,
+ mLastRawState.buttonState, MotionClassification::NONE,
AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.lastProperties,
&mPointerSimple.lastCoords, mOrientedXPrecision, mOrientedYPrecision,
xCursorPosition, yCursorPosition, mPointerSimple.downTime,
@@ -3453,7 +3448,7 @@
mPointerSimple.downTime = when;
// Send down.
- NotifyMotionArgs args(getContext()->getNextSequenceNum(), when, getDeviceId(), mSource,
+ NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), mSource,
displayId, policyFlags, AMOTION_EVENT_ACTION_DOWN, 0, 0,
metaState, mCurrentRawState.buttonState,
MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
@@ -3464,8 +3459,8 @@
}
// Send move.
- NotifyMotionArgs args(getContext()->getNextSequenceNum(), when, getDeviceId(), mSource,
- displayId, policyFlags, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState,
+ NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, displayId,
+ policyFlags, AMOTION_EVENT_ACTION_MOVE, 0, 0, metaState,
mCurrentRawState.buttonState, MotionClassification::NONE,
AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.currentProperties,
&mPointerSimple.currentCoords, mOrientedXPrecision,
@@ -3479,7 +3474,7 @@
mPointerSimple.hovering = true;
// Send hover enter.
- NotifyMotionArgs args(getContext()->getNextSequenceNum(), when, getDeviceId(), mSource,
+ NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), mSource,
displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_ENTER, 0, 0,
metaState, mCurrentRawState.buttonState,
MotionClassification::NONE, AMOTION_EVENT_EDGE_FLAG_NONE, 1,
@@ -3490,9 +3485,9 @@
}
// Send hover move.
- NotifyMotionArgs args(getContext()->getNextSequenceNum(), when, getDeviceId(), mSource,
- displayId, policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0,
- metaState, mCurrentRawState.buttonState, MotionClassification::NONE,
+ NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, displayId,
+ policyFlags, AMOTION_EVENT_ACTION_HOVER_MOVE, 0, 0, metaState,
+ mCurrentRawState.buttonState, MotionClassification::NONE,
AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.currentProperties,
&mPointerSimple.currentCoords, mOrientedXPrecision,
mOrientedYPrecision, xCursorPosition, yCursorPosition,
@@ -3512,8 +3507,8 @@
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
- NotifyMotionArgs args(getContext()->getNextSequenceNum(), when, getDeviceId(), mSource,
- displayId, policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState,
+ NotifyMotionArgs args(getContext()->getNextId(), when, getDeviceId(), mSource, displayId,
+ policyFlags, AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState,
mCurrentRawState.buttonState, MotionClassification::NONE,
AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.currentProperties,
&pointerCoords, mOrientedXPrecision, mOrientedYPrecision,
@@ -3586,8 +3581,8 @@
std::vector<TouchVideoFrame> frames = getDeviceContext().getVideoFrames();
std::for_each(frames.begin(), frames.end(),
[this](TouchVideoFrame& frame) { frame.rotate(this->mSurfaceOrientation); });
- NotifyMotionArgs args(getContext()->getNextSequenceNum(), when, deviceId, source, displayId,
- policyFlags, action, actionButton, flags, metaState, buttonState,
+ NotifyMotionArgs args(getContext()->getNextId(), when, deviceId, source, displayId, policyFlags,
+ action, actionButton, flags, metaState, buttonState,
MotionClassification::NONE, edgeFlags, pointerCount, pointerProperties,
pointerCoords, xPrecision, yPrecision, xCursorPosition, yCursorPosition,
downTime, std::move(frames));
@@ -3624,12 +3619,6 @@
return changed;
}
-void TouchInputMapper::fadePointer() {
- if (mPointerController != nullptr) {
- mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
- }
-}
-
void TouchInputMapper::cancelTouch(nsecs_t when) {
abortPointerUsage(when, 0 /*policyFlags*/);
abortTouches(when, 0 /* policyFlags*/);
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h
index 3a61206..e21a33a 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -148,7 +148,6 @@
virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
const int32_t* keyCodes, uint8_t* outFlags) override;
- virtual void fadePointer() override;
virtual void cancelTouch(nsecs_t when) override;
virtual void timeoutExpired(nsecs_t when) override;
virtual void updateExternalStylusState(const StylusState& state) override;
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 2fb1b65..d30c4f1 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -16,13 +16,18 @@
#include "../dispatcher/InputDispatcher.h"
+#include <android-base/stringprintf.h>
#include <binder/Binder.h>
#include <input/Input.h>
#include <gtest/gtest.h>
#include <linux/input.h>
+#include <cinttypes>
+#include <unordered_set>
#include <vector>
+using android::base::StringPrintf;
+
namespace android::inputdispatcher {
// An arbitrary time value.
@@ -49,9 +54,9 @@
static KeyEvent getTestKeyEvent() {
KeyEvent event;
- event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE, INVALID_HMAC,
- AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
- ARBITRARY_TIME);
+ event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
+ INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
+ ARBITRARY_TIME, ARBITRARY_TIME);
return event;
}
@@ -89,7 +94,7 @@
void assertNotifySwitchWasCalled(const NotifySwitchArgs& args) {
ASSERT_TRUE(mLastNotifySwitch);
- // We do not check sequenceNum because it is not exposed to the policy
+ // We do not check id because it is not exposed to the policy
EXPECT_EQ(args.eventTime, mLastNotifySwitch->eventTime);
EXPECT_EQ(args.policyFlags, mLastNotifySwitch->policyFlags);
EXPECT_EQ(args.switchValues, mLastNotifySwitch->switchValues);
@@ -107,6 +112,11 @@
<< "Expected onPointerDownOutsideFocus to not have been called";
}
+ void setKeyRepeatConfiguration(nsecs_t timeout, nsecs_t delay) {
+ mConfig.keyRepeatTimeout = timeout;
+ mConfig.keyRepeatDelay = delay;
+ }
+
private:
std::unique_ptr<InputEvent> mFilteredEvent;
std::optional<nsecs_t> mConfigurationChangedTime;
@@ -171,8 +181,7 @@
/** We simply reconstruct NotifySwitchArgs in policy because InputDispatcher is
* essentially a passthrough for notifySwitch.
*/
- mLastNotifySwitch =
- NotifySwitchArgs(1 /*sequenceNum*/, when, policyFlags, switchValues, switchMask);
+ mLastNotifySwitch = NotifySwitchArgs(1 /*id*/, when, policyFlags, switchValues, switchMask);
}
virtual void pokeUserActivity(nsecs_t, int32_t) {
@@ -300,7 +309,8 @@
KeyEvent event;
// Rejects undefined key actions.
- event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE, INVALID_HMAC,
+ event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
+ INVALID_HMAC,
/*action*/ -1, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0, ARBITRARY_TIME,
ARBITRARY_TIME);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
@@ -309,8 +319,8 @@
<< "Should reject key events with undefined action.";
// Rejects ACTION_MULTIPLE since it is not supported despite being defined in the API.
- event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE, INVALID_HMAC,
- AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
+ event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, ADISPLAY_ID_NONE,
+ INVALID_HMAC, AKEY_EVENT_ACTION_MULTIPLE, 0, AKEYCODE_A, KEY_A, AMETA_NONE, 0,
ARBITRARY_TIME, ARBITRARY_TIME);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
&event,
@@ -335,7 +345,7 @@
constexpr MotionClassification classification = MotionClassification::NONE;
// Rejects undefined motion actions.
- event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
+ event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
/*action*/ -1, 0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */,
1 /* yScale */, 0, 0, 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
@@ -346,7 +356,7 @@
<< "Should reject motion events with undefined action.";
// Rejects pointer down with invalid index.
- event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
+ event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
AMOTION_EVENT_ACTION_POINTER_DOWN |
(1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
@@ -358,7 +368,7 @@
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with pointer down index too large.";
- event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
+ event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
AMOTION_EVENT_ACTION_POINTER_DOWN |
(~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
@@ -371,7 +381,7 @@
<< "Should reject motion events with pointer down index too small.";
// Rejects pointer up with invalid index.
- event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
+ event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
AMOTION_EVENT_ACTION_POINTER_UP |
(1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
@@ -383,7 +393,7 @@
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with pointer up index too large.";
- event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
+ event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
AMOTION_EVENT_ACTION_POINTER_UP |
(~0U << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
0, 0, edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */,
@@ -396,20 +406,22 @@
<< "Should reject motion events with pointer up index too small.";
// Rejects motion events with invalid number of pointers.
- event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
- edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */, 0, 0,
- 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
+ event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
+ 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 0, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
&event,
INJECTOR_PID, INJECTOR_UID, INPUT_EVENT_INJECTION_SYNC_NONE, 0, 0))
<< "Should reject motion events with 0 pointers.";
- event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
- edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */, 0, 0,
- 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
+ event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
+ 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ MAX_POINTERS + 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
&event,
@@ -418,10 +430,11 @@
// Rejects motion events with invalid pointer ids.
pointerProperties[0].id = -1;
- event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
- edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */, 0, 0,
- 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
+ event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
+ 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
&event,
@@ -429,10 +442,11 @@
<< "Should reject motion events with pointer ids less than 0.";
pointerProperties[0].id = MAX_POINTER_ID + 1;
- event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
- edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */, 0, 0,
- 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
+ event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
+ 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 1, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
&event,
@@ -442,10 +456,11 @@
// Rejects motion events with duplicate pointer ids.
pointerProperties[0].id = 1;
pointerProperties[1].id = 1;
- event.initialize(DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC, AMOTION_EVENT_ACTION_DOWN, 0, 0,
- edgeFlags, metaState, 0, classification, 1 /* xScale */, 1 /* yScale */, 0, 0,
- 0, 0, AMOTION_EVENT_INVALID_CURSOR_POSITION,
- AMOTION_EVENT_INVALID_CURSOR_POSITION, ARBITRARY_TIME, ARBITRARY_TIME,
+ event.initialize(InputEvent::nextId(), DEVICE_ID, source, DISPLAY_ID, INVALID_HMAC,
+ AMOTION_EVENT_ACTION_DOWN, 0, 0, edgeFlags, metaState, 0, classification,
+ 1 /* xScale */, 1 /* yScale */, 0, 0, 0, 0,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ ARBITRARY_TIME, ARBITRARY_TIME,
/*pointerCount*/ 2, pointerProperties, pointerCoords);
ASSERT_EQ(INPUT_EVENT_INJECTION_FAILED, mDispatcher->injectInputEvent(
&event,
@@ -457,7 +472,7 @@
TEST_F(InputDispatcherTest, NotifyConfigurationChanged_CallsPolicy) {
constexpr nsecs_t eventTime = 20;
- NotifyConfigurationChangedArgs args(10 /*sequenceNum*/, eventTime);
+ NotifyConfigurationChangedArgs args(10 /*id*/, eventTime);
mDispatcher->notifyConfigurationChanged(&args);
ASSERT_TRUE(mDispatcher->waitForIdle());
@@ -465,8 +480,8 @@
}
TEST_F(InputDispatcherTest, NotifySwitch_CallsPolicy) {
- NotifySwitchArgs args(10 /*sequenceNum*/, 20 /*eventTime*/, 0 /*policyFlags*/,
- 1 /*switchValues*/, 2 /*switchMask*/);
+ NotifySwitchArgs args(10 /*id*/, 20 /*eventTime*/, 0 /*policyFlags*/, 1 /*switchValues*/,
+ 2 /*switchMask*/);
mDispatcher->notifySwitch(&args);
// InputDispatcher adds POLICY_FLAG_TRUSTED because the event went through InputListener
@@ -748,8 +763,9 @@
nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
// Define a valid key down event.
- event.initialize(DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId, INVALID_HMAC,
- AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A, AMETA_NONE,
+ event.initialize(InputEvent::nextId(), DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
+ INVALID_HMAC, AKEY_EVENT_ACTION_DOWN, /* flags */ 0, AKEYCODE_A, KEY_A,
+ AMETA_NONE,
/* repeatCount */ 0, currentTime, currentTime);
// Inject event until dispatch out.
@@ -777,7 +793,8 @@
nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
// Define a valid motion down event.
- event.initialize(DEVICE_ID, source, displayId, INVALID_HMAC, action, /* actionButton */ 0,
+ event.initialize(InputEvent::nextId(), DEVICE_ID, source, displayId, INVALID_HMAC, action,
+ /* actionButton */ 0,
/* flags */ 0,
/* edgeFlags */ 0, AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
/* xScale */ 1, /* yScale */ 1, /* xOffset */ 0, /* yOffset */ 0,
@@ -805,9 +822,9 @@
static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
// Define a valid key event.
- NotifyKeyArgs args(/* sequenceNum */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD,
- displayId, POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0,
- AKEYCODE_A, KEY_A, AMETA_NONE, currentTime);
+ NotifyKeyArgs args(/* id */ 0, currentTime, DEVICE_ID, AINPUT_SOURCE_KEYBOARD, displayId,
+ POLICY_FLAG_PASS_TO_USER, action, /* flags */ 0, AKEYCODE_A, KEY_A,
+ AMETA_NONE, currentTime);
return args;
}
@@ -834,7 +851,7 @@
nsecs_t currentTime = systemTime(SYSTEM_TIME_MONOTONIC);
// Define a valid motion event.
- NotifyMotionArgs args(/* sequenceNum */ 0, currentTime, DEVICE_ID, source, displayId,
+ NotifyMotionArgs args(/* id */ 0, currentTime, DEVICE_ID, source, displayId,
POLICY_FLAG_PASS_TO_USER, action, /* actionButton */ 0, /* flags */ 0,
AMETA_NONE, /* buttonState */ 0, MotionClassification::NONE,
AMOTION_EVENT_EDGE_FLAG_NONE, pointerCount, pointerProperties,
@@ -997,7 +1014,7 @@
// When device reset happens, that key stream should be terminated with FLAG_CANCELED
// on the app side.
- NotifyDeviceResetArgs args(10 /*sequenceNum*/, 20 /*eventTime*/, DEVICE_ID);
+ NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
mDispatcher->notifyDeviceReset(&args);
window->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
AKEY_EVENT_FLAG_CANCELED);
@@ -1020,7 +1037,7 @@
// When device reset happens, that motion stream should be terminated with ACTION_CANCEL
// on the app side.
- NotifyDeviceResetArgs args(10 /*sequenceNum*/, 20 /*eventTime*/, DEVICE_ID);
+ NotifyDeviceResetArgs args(10 /*id*/, 20 /*eventTime*/, DEVICE_ID);
mDispatcher->notifyDeviceReset(&args);
window->consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_CANCEL, ADISPLAY_ID_DEFAULT,
0 /*expectedFlags*/);
@@ -1345,7 +1362,7 @@
window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
motionArgs.action = AMOTION_EVENT_ACTION_MOVE;
- motionArgs.sequenceNum += 1;
+ motionArgs.id += 1;
motionArgs.eventTime = systemTime(SYSTEM_TIME_MONOTONIC);
motionArgs.pointerCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
motionArgs.pointerCoords[0].getX() - 10);
@@ -1436,6 +1453,105 @@
ASSERT_EQ(0, verifiedKey.repeatCount);
}
+class InputDispatcherKeyRepeatTest : public InputDispatcherTest {
+protected:
+ static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms
+ static constexpr nsecs_t KEY_REPEAT_DELAY = 40 * 1000000; // 40 ms
+
+ sp<FakeApplicationHandle> mApp;
+ sp<FakeWindowHandle> mWindow;
+
+ virtual void SetUp() override {
+ mFakePolicy = new FakeInputDispatcherPolicy();
+ mFakePolicy->setKeyRepeatConfiguration(KEY_REPEAT_TIMEOUT, KEY_REPEAT_DELAY);
+ mDispatcher = new InputDispatcher(mFakePolicy);
+ mDispatcher->setInputDispatchMode(/*enabled*/ true, /*frozen*/ false);
+ ASSERT_EQ(OK, mDispatcher->start());
+
+ setUpWindow();
+ }
+
+ void setUpWindow() {
+ mApp = new FakeApplicationHandle();
+ mWindow = new FakeWindowHandle(mApp, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
+
+ mWindow->setFocus(true);
+ mDispatcher->setInputWindows({mWindow}, ADISPLAY_ID_DEFAULT);
+
+ mWindow->consumeFocusEvent(true);
+ }
+
+ void sendAndConsumeKeyDown() {
+ NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN, ADISPLAY_ID_DEFAULT);
+ keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Otherwise it won't generate repeat event
+ mDispatcher->notifyKey(&keyArgs);
+
+ // Window should receive key down event.
+ mWindow->consumeKeyDown(ADISPLAY_ID_DEFAULT);
+ }
+
+ void expectKeyRepeatOnce(int32_t repeatCount) {
+ SCOPED_TRACE(StringPrintf("Checking event with repeat count %" PRId32, repeatCount));
+ InputEvent* repeatEvent = mWindow->consume();
+ ASSERT_NE(nullptr, repeatEvent);
+
+ uint32_t eventType = repeatEvent->getType();
+ ASSERT_EQ(AINPUT_EVENT_TYPE_KEY, eventType);
+
+ KeyEvent* repeatKeyEvent = static_cast<KeyEvent*>(repeatEvent);
+ uint32_t eventAction = repeatKeyEvent->getAction();
+ EXPECT_EQ(AKEY_EVENT_ACTION_DOWN, eventAction);
+ EXPECT_EQ(repeatCount, repeatKeyEvent->getRepeatCount());
+ }
+
+ void sendAndConsumeKeyUp() {
+ NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT);
+ keyArgs.policyFlags |= POLICY_FLAG_TRUSTED; // Unless it won't generate repeat event
+ mDispatcher->notifyKey(&keyArgs);
+
+ // Window should receive key down event.
+ mWindow->consumeEvent(AINPUT_EVENT_TYPE_KEY, AKEY_EVENT_ACTION_UP, ADISPLAY_ID_DEFAULT,
+ 0 /*expectedFlags*/);
+ }
+};
+
+TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_ReceivesKeyRepeat) {
+ sendAndConsumeKeyDown();
+ for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
+ expectKeyRepeatOnce(repeatCount);
+ }
+}
+
+TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_StopsKeyRepeatAfterUp) {
+ sendAndConsumeKeyDown();
+ expectKeyRepeatOnce(1 /*repeatCount*/);
+ sendAndConsumeKeyUp();
+ mWindow->assertNoEvents();
+}
+
+TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseEventIdFromInputDispatcher) {
+ sendAndConsumeKeyDown();
+ for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
+ InputEvent* repeatEvent = mWindow->consume();
+ ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
+ EXPECT_EQ(IdGenerator::Source::INPUT_DISPATCHER,
+ IdGenerator::getSource(repeatEvent->getId()));
+ }
+}
+
+TEST_F(InputDispatcherKeyRepeatTest, FocusedWindow_RepeatKeyEventsUseUniqueEventId) {
+ sendAndConsumeKeyDown();
+
+ std::unordered_set<int32_t> idSet;
+ for (int32_t repeatCount = 1; repeatCount <= 10; ++repeatCount) {
+ InputEvent* repeatEvent = mWindow->consume();
+ ASSERT_NE(nullptr, repeatEvent) << "Didn't receive event with repeat count " << repeatCount;
+ int32_t id = repeatEvent->getId();
+ EXPECT_EQ(idSet.end(), idSet.find(id));
+ idSet.insert(id);
+ }
+}
+
/* Test InputDispatcher for MultiDisplay */
class InputDispatcherFocusOnTwoDisplaysTest : public InputDispatcherTest {
public:
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index af11256..3ae8b56 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -846,7 +846,8 @@
int32_t mGlobalMetaState;
bool mUpdateGlobalMetaStateWasCalled;
int32_t mGeneration;
- uint32_t mNextSequenceNum;
+ int32_t mNextId;
+ wp<PointerControllerInterface> mPointerController;
public:
FakeInputReaderContext(std::shared_ptr<EventHubInterface> eventHub,
@@ -856,7 +857,7 @@
mPolicy(policy),
mListener(listener),
mGlobalMetaState(0),
- mNextSequenceNum(1) {}
+ mNextId(1) {}
virtual ~FakeInputReaderContext() { }
@@ -874,6 +875,18 @@
return mGeneration;
}
+ void updatePointerDisplay() {
+ sp<PointerControllerInterface> controller = mPointerController.promote();
+ 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;
@@ -900,6 +913,16 @@
virtual bool shouldDropVirtualKey(nsecs_t, int32_t, int32_t) { return false; }
+ virtual sp<PointerControllerInterface> getPointerController(int32_t deviceId) {
+ sp<PointerControllerInterface> controller = mPointerController.promote();
+ if (controller == nullptr) {
+ controller = mPolicy->obtainPointerController(deviceId);
+ mPointerController = controller;
+ updatePointerDisplay();
+ }
+ return controller;
+ }
+
virtual void fadePointer() {
}
@@ -918,9 +941,7 @@
}
- virtual uint32_t getNextSequenceNum() {
- return mNextSequenceNum++;
- }
+ virtual int32_t getNextId() { return mNextId++; }
};
@@ -1621,7 +1642,7 @@
ASSERT_EQ(1, event.value);
}
-TEST_F(InputReaderTest, DeviceReset_IncrementsSequenceNumber) {
+TEST_F(InputReaderTest, DeviceReset_RandomId) {
constexpr int32_t deviceId = END_RESERVED_ID + 1000;
constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD;
constexpr int32_t eventHubId = 1;
@@ -1633,25 +1654,40 @@
NotifyDeviceResetArgs resetArgs;
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
- uint32_t prevSequenceNum = resetArgs.sequenceNum;
+ int32_t prevId = resetArgs.id;
disableDevice(deviceId);
mReader->loopOnce();
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
- ASSERT_TRUE(prevSequenceNum < resetArgs.sequenceNum);
- prevSequenceNum = resetArgs.sequenceNum;
+ ASSERT_NE(prevId, resetArgs.id);
+ prevId = resetArgs.id;
enableDevice(deviceId);
mReader->loopOnce();
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
- ASSERT_TRUE(prevSequenceNum < resetArgs.sequenceNum);
- prevSequenceNum = resetArgs.sequenceNum;
+ ASSERT_NE(prevId, resetArgs.id);
+ prevId = resetArgs.id;
disableDevice(deviceId);
mReader->loopOnce();
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
- ASSERT_TRUE(prevSequenceNum < resetArgs.sequenceNum);
- prevSequenceNum = resetArgs.sequenceNum;
+ ASSERT_NE(prevId, resetArgs.id);
+ prevId = resetArgs.id;
+}
+
+TEST_F(InputReaderTest, DeviceReset_GenerateIdWithInputReaderSource) {
+ constexpr int32_t deviceId = 1;
+ constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD;
+ constexpr int32_t eventHubId = 1;
+ std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake");
+ // Must add at least one mapper or the device will be ignored!
+ device->addMapper<FakeInputMapper>(eventHubId, AINPUT_SOURCE_KEYBOARD);
+ mReader->setNextDevice(device);
+ ASSERT_NO_FATAL_FAILURE(addDevice(deviceId, "fake", deviceClass, nullptr));
+
+ NotifyDeviceResetArgs resetArgs;
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
+ ASSERT_EQ(IdGenerator::Source::INPUT_READER, IdGenerator::getSource(resetArgs.id));
}
TEST_F(InputReaderTest, Device_CanDispatchToDisplay) {
@@ -1793,21 +1829,21 @@
NotifyConfigurationChangedArgs configChangedArgs;
ASSERT_NO_FATAL_FAILURE(
mTestListener->assertNotifyConfigurationChangedWasCalled(&configChangedArgs));
- uint32_t prevSequenceNum = configChangedArgs.sequenceNum;
+ int32_t prevId = configChangedArgs.id;
nsecs_t prevTimestamp = configChangedArgs.eventTime;
NotifyKeyArgs keyArgs;
keyboard->pressAndReleaseHomeKey();
ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs));
ASSERT_EQ(AKEY_EVENT_ACTION_DOWN, keyArgs.action);
- ASSERT_LT(prevSequenceNum, keyArgs.sequenceNum);
- prevSequenceNum = keyArgs.sequenceNum;
+ ASSERT_NE(prevId, keyArgs.id);
+ prevId = keyArgs.id;
ASSERT_LE(prevTimestamp, keyArgs.eventTime);
prevTimestamp = keyArgs.eventTime;
ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyKeyWasCalled(&keyArgs));
ASSERT_EQ(AKEY_EVENT_ACTION_UP, keyArgs.action);
- ASSERT_LT(prevSequenceNum, keyArgs.sequenceNum);
+ ASSERT_NE(prevId, keyArgs.id);
ASSERT_LE(prevTimestamp, keyArgs.eventTime);
}
@@ -2095,6 +2131,9 @@
}
void configureDevice(uint32_t changes) {
+ if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
+ mFakeContext->updatePointerDisplay();
+ }
mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), changes);
}
diff --git a/services/powermanager/Android.bp b/services/powermanager/Android.bp
index 7b3af70..3e0f136 100644
--- a/services/powermanager/Android.bp
+++ b/services/powermanager/Android.bp
@@ -1,11 +1,25 @@
cc_library_shared {
name: "libpowermanager",
- srcs: ["IPowerManager.cpp"],
+ srcs: [
+ "IPowerManager.cpp",
+ "Temperature.cpp",
+ "CoolingDevice.cpp",
+ ":libpowermanager_aidl",
+ ],
+
+ aidl: {
+ local_include_dirs: ["."],
+ include_dirs: [
+ "frameworks/base/core/java/android/os",
+ ],
+ export_aidl_headers: true
+ },
shared_libs: [
"libutils",
"libbinder",
+ "liblog"
],
cflags: [
@@ -15,3 +29,22 @@
"-Wunreachable-code",
],
}
+
+cc_test {
+ name: "thermalmanager-test",
+ srcs: ["IThermalManagerTest.cpp",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
+ shared_libs: [
+ "libbase",
+ "libhidlbase",
+ "liblog",
+ "libpowermanager",
+ "libbinder",
+ "libutils",
+ ],
+}
diff --git a/services/powermanager/CoolingDevice.cpp b/services/powermanager/CoolingDevice.cpp
new file mode 100644
index 0000000..ebbc1b4
--- /dev/null
+++ b/services/powermanager/CoolingDevice.cpp
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "CoolingDevice"
+
+#include <android/CoolingDevice.h>
+#include <binder/Parcel.h>
+#include <utils/Log.h>
+
+namespace android {
+namespace os {
+
+status_t CoolingDevice::readFromParcel(const android::Parcel *parcel) {
+ if (parcel == nullptr) {
+ ALOGE("%s: Null parcel", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ parcel->readFloat(&mValue);
+ parcel->readUint32(&mType);
+ parcel->readString16(&mName);
+
+ return OK;
+}
+
+status_t CoolingDevice::writeToParcel(android::Parcel *parcel) const {
+ if (parcel == nullptr) {
+ ALOGE("%s: Null parcel", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ parcel->writeFloat(mValue);
+ parcel->writeUint32(mType);
+ parcel->writeString16(mName);
+
+ return OK;
+}
+
+} // namespace os
+} // namespace android
\ No newline at end of file
diff --git a/services/powermanager/IThermalManagerTest.cpp b/services/powermanager/IThermalManagerTest.cpp
new file mode 100644
index 0000000..575b9ee
--- /dev/null
+++ b/services/powermanager/IThermalManagerTest.cpp
@@ -0,0 +1,158 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "ThermalManagerTest"
+//#define LOG_NDEBUG 0
+
+#include <thread>
+
+#include <android/os/BnThermalStatusListener.h>
+#include <android/os/IThermalService.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/Parcel.h>
+#include <condition_variable>
+#include <gtest/gtest.h>
+#include <powermanager/PowerManager.h>
+#include <utils/Log.h>
+
+using namespace android;
+using namespace android::os;
+using namespace std::chrono_literals;
+
+class IThermalServiceTest : public testing::Test,
+ public BnThermalStatusListener{
+ public:
+ IThermalServiceTest();
+ void setThermalOverride(int level);
+ virtual binder::Status onStatusChange(int status) override;
+ int getStatusFromService();
+ void SetUp() override;
+ void TearDown() override;
+ protected:
+ sp<IThermalService> mThermalSvc;
+ std::condition_variable mCondition;
+ int mListenerStatus;
+ int mServiceStatus;
+ std::mutex mMutex;
+};
+
+IThermalServiceTest::IThermalServiceTest()
+ : mListenerStatus(0),
+ mServiceStatus(0) {
+}
+
+void IThermalServiceTest::setThermalOverride(int level) {
+ std::string cmdStr = "cmd thermalservice override-status " + std::to_string(level);
+ system(cmdStr.c_str());
+}
+
+binder::Status IThermalServiceTest::onStatusChange(int status) {
+ std::unique_lock<std::mutex> lock(mMutex);
+ mListenerStatus = status;
+ ALOGI("IThermalServiceTest::notifyListener %d", mListenerStatus);
+ mCondition.notify_all();
+ return binder::Status::ok();
+}
+
+int IThermalServiceTest::getStatusFromService() {
+ int status;
+ binder::Status ret = mThermalSvc->getCurrentThermalStatus(&status);
+ if (ret.isOk()) {
+ return status;
+ } else {
+ return BAD_VALUE;
+ }
+}
+
+void IThermalServiceTest::SetUp() {
+ setThermalOverride(0);
+ // use checkService() to avoid blocking if thermal service is not up yet
+ sp<IBinder> binder =
+ defaultServiceManager()->checkService(String16("thermalservice"));
+ EXPECT_NE(binder, nullptr);
+ mThermalSvc = interface_cast<IThermalService>(binder);
+ EXPECT_NE(mThermalSvc, nullptr);
+ bool success = false;
+ binder::Status ret = mThermalSvc->registerThermalStatusListener(this, &success);
+ ASSERT_TRUE(success);
+ ASSERT_TRUE(ret.isOk());
+ // Wait for listener called after registration, shouldn't timeout
+ std::unique_lock<std::mutex> lock(mMutex);
+ EXPECT_NE(mCondition.wait_for(lock, 1s), std::cv_status::timeout);
+}
+
+void IThermalServiceTest::TearDown() {
+ bool success = false;
+ binder::Status ret = mThermalSvc->unregisterThermalStatusListener(this, &success);
+ ASSERT_TRUE(success);
+ ASSERT_TRUE(ret.isOk());
+}
+
+class IThermalListenerTest : public IThermalServiceTest, public testing::WithParamInterface<int32_t> {
+ public:
+ static auto PrintParam(const testing::TestParamInfo<ParamType> &info) {
+ return std::to_string(info.param);
+ }
+};
+
+TEST_P(IThermalListenerTest, TestListener) {
+ int level = GetParam();
+ std::unique_lock<std::mutex> lock(mMutex);
+ // Set the override thermal status
+ setThermalOverride(level);
+ // Wait for listener called, shouldn't timeout
+ EXPECT_NE(mCondition.wait_for(lock, 1s), std::cv_status::timeout);
+ // Check the result
+ EXPECT_EQ(level, mListenerStatus);
+ ALOGI("Thermal listener status %d, expecting %d", mListenerStatus, level);
+}
+
+INSTANTIATE_TEST_SUITE_P(TestListenerLevels, IThermalListenerTest, testing::Range(
+ static_cast<int>(ThermalStatus::THERMAL_STATUS_LIGHT),
+ static_cast<int>(ThermalStatus::THERMAL_STATUS_SHUTDOWN)),
+ IThermalListenerTest::PrintParam);
+
+class IThermalLevelTest : public IThermalServiceTest, public testing::WithParamInterface<int32_t> {
+ public:
+ static auto PrintParam(const testing::TestParamInfo<ParamType> &info) {
+ return std::to_string(info.param);
+ }
+};
+
+TEST_P(IThermalLevelTest, TestGetStatusLevel) {
+ int level = GetParam();
+ setThermalOverride(level);
+ mServiceStatus = getStatusFromService();
+ EXPECT_EQ(level, mServiceStatus);
+}
+
+INSTANTIATE_TEST_SUITE_P(TestStatusLevels, IThermalLevelTest, testing::Range(
+ static_cast<int>(ThermalStatus::THERMAL_STATUS_NONE),
+ static_cast<int>(ThermalStatus::THERMAL_STATUS_SHUTDOWN)),
+ IThermalLevelTest::PrintParam);
+
+int main(int argc, char **argv) {
+ std::unique_ptr<std::thread> binderLoop;
+ binderLoop = std::make_unique<std::thread>(
+ [&] { IPCThreadState::self()->joinThreadPool(true); });
+
+ ::testing::InitGoogleTest(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ ALOGV("Test result = %d\n", status);
+
+ return status;
+}
\ No newline at end of file
diff --git a/services/powermanager/Temperature.cpp b/services/powermanager/Temperature.cpp
new file mode 100644
index 0000000..8ec0a87
--- /dev/null
+++ b/services/powermanager/Temperature.cpp
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "Temperature"
+
+#include <android/Temperature.h>
+#include <binder/Parcel.h>
+#include <utils/Log.h>
+
+namespace android {
+namespace os {
+
+status_t Temperature::readFromParcel(const android::Parcel *parcel) {
+ if (parcel == nullptr) {
+ ALOGE("%s: Null parcel", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ parcel->readFloat(&mValue);
+ parcel->readInt32(&mType);
+ parcel->readString16(&mName);
+ parcel->readInt32(&mStatus);
+
+ return OK;
+}
+
+status_t Temperature::writeToParcel(android::Parcel *parcel) const {
+ if (parcel == nullptr) {
+ ALOGE("%s: Null parcel", __FUNCTION__);
+ return BAD_VALUE;
+ }
+
+ parcel->writeFloat(mValue);
+ parcel->writeInt32(mType);
+ parcel->writeString16(mName);
+ parcel->writeInt32(mStatus);
+
+ return OK;
+}
+
+} // namespace os
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 5dce281..c6f1f7e 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -33,6 +33,7 @@
"android.hardware.graphics.composer@2.4",
"android.hardware.power@1.0",
"android.hardware.power@1.3",
+ "android.hardware.power-cpp",
"libbase",
"libbinder",
"libbufferhubqueue",
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
index c5a73f2..e740b13 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
@@ -30,6 +30,7 @@
~PowerAdvisor() override;
MOCK_METHOD2(setExpensiveRenderingExpected, void(DisplayId displayId, bool expected));
+ MOCK_METHOD0(notifyDisplayUpdateImminent, void());
};
} // namespace mock
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
index 039db73..550ec61 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
@@ -14,14 +14,23 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+
#undef LOG_TAG
#define LOG_TAG "PowerAdvisor"
#include <cinttypes>
+#include <android-base/properties.h>
#include <utils/Log.h>
#include <utils/Mutex.h>
+#include <android/hardware/power/1.3/IPower.h>
+#include <android/hardware/power/IPower.h>
+#include <binder/IServiceManager.h>
+
+#include "../SurfaceFlingerProperties.h"
+
#include "PowerAdvisor.h"
namespace android {
@@ -32,11 +41,36 @@
namespace impl {
namespace V1_0 = android::hardware::power::V1_0;
+namespace V1_3 = android::hardware::power::V1_3;
using V1_3::PowerHint;
+using android::hardware::power::Boost;
+using android::hardware::power::IPower;
+using android::hardware::power::Mode;
+using base::GetIntProperty;
+using scheduler::OneShotTimer;
+
PowerAdvisor::~PowerAdvisor() = default;
-PowerAdvisor::PowerAdvisor() = default;
+namespace {
+int32_t getUpdateTimeout() {
+ // Default to a timeout of 80ms if nothing else is specified
+ static int32_t timeout = sysprop::display_update_imminent_timeout_ms(80);
+ return timeout;
+}
+
+} // namespace
+
+PowerAdvisor::PowerAdvisor()
+ : mUseUpdateImminentTimer(getUpdateTimeout() > 0),
+ mUpdateImminentTimer(
+ OneShotTimer::Interval(getUpdateTimeout()),
+ /* resetCallback */ [this] { mSendUpdateImminent.store(false); },
+ /* timeoutCallback */ [this] { mSendUpdateImminent.store(true); }) {
+ if (mUseUpdateImminentTimer) {
+ mUpdateImminentTimer.start();
+ }
+}
void PowerAdvisor::setExpensiveRenderingExpected(DisplayId displayId, bool expected) {
if (expected) {
@@ -47,51 +81,170 @@
const bool expectsExpensiveRendering = !mExpensiveDisplays.empty();
if (mNotifiedExpensiveRendering != expectsExpensiveRendering) {
- const sp<V1_3::IPower> powerHal = getPowerHal();
- if (powerHal == nullptr) {
+ HalWrapper* const halWrapper = getPowerHal();
+ if (halWrapper == nullptr) {
return;
}
- auto ret = powerHal->powerHintAsync_1_3(PowerHint::EXPENSIVE_RENDERING,
- expectsExpensiveRendering);
- // If Power HAL 1.3 was available previously but now fails,
- // it may restart, so attempt to reconnect next time
- if (!ret.isOk()) {
+
+ if (!halWrapper->setExpensiveRendering(expectsExpensiveRendering)) {
+ // The HAL has become unavailable; attempt to reconnect later
mReconnectPowerHal = true;
return;
}
+
mNotifiedExpensiveRendering = expectsExpensiveRendering;
}
}
-sp<V1_3::IPower> PowerAdvisor::getPowerHal() {
- static sp<V1_3::IPower> sPowerHal_1_3 = nullptr;
- static bool sHasPowerHal_1_3 = true;
+void PowerAdvisor::notifyDisplayUpdateImminent() {
+ if (mSendUpdateImminent.load()) {
+ HalWrapper* const halWrapper = getPowerHal();
+ if (halWrapper == nullptr) {
+ return;
+ }
+
+ if (!halWrapper->notifyDisplayUpdateImminent()) {
+ // The HAL has become unavailable; attempt to reconnect later
+ mReconnectPowerHal = true;
+ return;
+ }
+ }
+
+ if (mUseUpdateImminentTimer) {
+ mUpdateImminentTimer.reset();
+ }
+}
+
+class HidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
+public:
+ HidlPowerHalWrapper(sp<V1_3::IPower> powerHal) : mPowerHal(std::move(powerHal)) {}
+
+ ~HidlPowerHalWrapper() override = default;
+
+ static std::unique_ptr<HalWrapper> connect() {
+ // Power HAL 1.3 is not guaranteed to be available, thus we need to query
+ // Power HAL 1.0 first and try to cast it to Power HAL 1.3.
+ // Power HAL 1.0 is always available, thus if we fail to query it, it means
+ // Power HAL is not available temporarily and we should retry later. However,
+ // if Power HAL 1.0 is available and we can't cast it to Power HAL 1.3,
+ // it means Power HAL 1.3 is not available at all, so we should stop trying.
+ sp<V1_3::IPower> powerHal = nullptr;
+ if (sHasPowerHal_1_3) {
+ sp<V1_0::IPower> powerHal_1_0 = V1_0::IPower::getService();
+ if (powerHal_1_0 != nullptr) {
+ // Try to cast to Power HAL 1.3
+ powerHal = V1_3::IPower::castFrom(powerHal_1_0);
+ if (powerHal == nullptr) {
+ ALOGW("No Power HAL 1.3 service in system");
+ sHasPowerHal_1_3 = false;
+ } else {
+ ALOGI("Loaded Power HAL 1.3 service");
+ }
+ }
+ }
+ if (powerHal == nullptr) {
+ return nullptr;
+ }
+
+ return std::make_unique<HidlPowerHalWrapper>(std::move(powerHal));
+ }
+
+ bool setExpensiveRendering(bool enabled) override {
+ ALOGV("HIDL setExpensiveRendering %s", enabled ? "T" : "F");
+ auto ret = mPowerHal->powerHintAsync_1_3(PowerHint::EXPENSIVE_RENDERING, enabled);
+ return ret.isOk();
+ }
+
+ bool notifyDisplayUpdateImminent() override {
+ // Power HAL 1.x doesn't have a notification for this
+ ALOGV("HIDL notifyUpdateImminent received but can't send");
+ return true;
+ }
+
+private:
+ static bool sHasPowerHal_1_3;
+ const sp<V1_3::IPower> mPowerHal = nullptr;
+};
+
+bool HidlPowerHalWrapper::sHasPowerHal_1_3 = true;
+
+class AidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
+public:
+ AidlPowerHalWrapper(sp<IPower> powerHal) : mPowerHal(std::move(powerHal)) {
+ auto ret = mPowerHal->isModeSupported(Mode::EXPENSIVE_RENDERING, &mHasExpensiveRendering);
+ if (!ret.isOk()) {
+ mHasExpensiveRendering = false;
+ }
+
+ ret = mPowerHal->isBoostSupported(Boost::DISPLAY_UPDATE_IMMINENT,
+ &mHasDisplayUpdateImminent);
+ if (!ret.isOk()) {
+ mHasDisplayUpdateImminent = false;
+ }
+ }
+
+ ~AidlPowerHalWrapper() override = default;
+
+ static std::unique_ptr<HalWrapper> connect() {
+ // This only waits if the service is actually declared
+ sp<IPower> powerHal = waitForVintfService<IPower>();
+ if (powerHal == nullptr) {
+ return nullptr;
+ }
+ ALOGI("Loaded AIDL Power HAL service");
+
+ return std::make_unique<AidlPowerHalWrapper>(std::move(powerHal));
+ }
+
+ bool setExpensiveRendering(bool enabled) override {
+ ALOGV("AIDL setExpensiveRendering %s", enabled ? "T" : "F");
+ if (!mHasExpensiveRendering) {
+ ALOGV("Skipped sending EXPENSIVE_RENDERING because HAL doesn't support it");
+ return true;
+ }
+
+ auto ret = mPowerHal->setMode(Mode::EXPENSIVE_RENDERING, enabled);
+ return ret.isOk();
+ }
+
+ bool notifyDisplayUpdateImminent() override {
+ ALOGV("AIDL notifyDisplayUpdateImminent");
+ if (!mHasDisplayUpdateImminent) {
+ ALOGV("Skipped sending DISPLAY_UPDATE_IMMINENT because HAL doesn't support it");
+ return true;
+ }
+
+ auto ret = mPowerHal->setBoost(Boost::DISPLAY_UPDATE_IMMINENT, 0);
+ return ret.isOk();
+ }
+
+private:
+ const sp<IPower> mPowerHal = nullptr;
+ bool mHasExpensiveRendering = false;
+ bool mHasDisplayUpdateImminent = false;
+};
+
+PowerAdvisor::HalWrapper* PowerAdvisor::getPowerHal() {
+ static std::unique_ptr<HalWrapper> sHalWrapper = nullptr;
if (mReconnectPowerHal) {
- sPowerHal_1_3 = nullptr;
+ sHalWrapper = nullptr;
mReconnectPowerHal = false;
}
- // Power HAL 1.3 is not guaranteed to be available, thus we need to query
- // Power HAL 1.0 first and try to cast it to Power HAL 1.3.
- // Power HAL 1.0 is always available, thus if we fail to query it, it means
- // Power HAL is not available temporarily and we should retry later. However,
- // if Power HAL 1.0 is available and we can't cast it to Power HAL 1.3,
- // it means Power HAL 1.3 is not available at all, so we should stop trying.
- if (sHasPowerHal_1_3 && sPowerHal_1_3 == nullptr) {
- sp<V1_0::IPower> powerHal_1_0 = V1_0::IPower::getService();
- if (powerHal_1_0 != nullptr) {
- // Try to cast to Power HAL 1.3
- sPowerHal_1_3 = V1_3::IPower::castFrom(powerHal_1_0);
- if (sPowerHal_1_3 == nullptr) {
- ALOGW("No Power HAL 1.3 service in system");
- sHasPowerHal_1_3 = false;
- } else {
- ALOGI("Loaded Power HAL 1.3 service");
- }
- }
+ if (sHalWrapper != nullptr) {
+ return sHalWrapper.get();
}
- return sPowerHal_1_3;
+
+ // First attempt to connect to the AIDL Power HAL
+ sHalWrapper = AidlPowerHalWrapper::connect();
+
+ // If that didn't succeed, attempt to connect to the HIDL Power HAL
+ if (sHalWrapper == nullptr) {
+ sHalWrapper = HidlPowerHalWrapper::connect();
+ }
+
+ return sHalWrapper.get();
}
} // namespace impl
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
index 5aa1f22..957d289 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
@@ -22,11 +22,10 @@
#undef HWC2_INCLUDE_STRINGIFICATION
#undef HWC2_USE_CPP11
+#include <atomic>
#include <unordered_set>
-#include <android/hardware/power/1.3/IPower.h>
-#include <utils/StrongPointer.h>
-
+#include "../Scheduler/OneShotTimer.h"
#include "DisplayIdentification.h"
namespace android {
@@ -37,27 +36,40 @@
virtual ~PowerAdvisor();
virtual void setExpensiveRenderingExpected(DisplayId displayId, bool expected) = 0;
+ virtual void notifyDisplayUpdateImminent() = 0;
};
namespace impl {
-namespace V1_3 = android::hardware::power::V1_3;
-
// PowerAdvisor is a wrapper around IPower HAL which takes into account the
// full state of the system when sending out power hints to things like the GPU.
class PowerAdvisor final : public Hwc2::PowerAdvisor {
public:
+ class HalWrapper {
+ public:
+ virtual ~HalWrapper() = default;
+
+ virtual bool setExpensiveRendering(bool enabled) = 0;
+ virtual bool notifyDisplayUpdateImminent() = 0;
+ };
+
PowerAdvisor();
~PowerAdvisor() override;
void setExpensiveRenderingExpected(DisplayId displayId, bool expected) override;
+ void notifyDisplayUpdateImminent() override;
private:
- sp<V1_3::IPower> getPowerHal();
+ HalWrapper* getPowerHal();
+
+ bool mReconnectPowerHal = false;
std::unordered_set<DisplayId> mExpensiveDisplays;
bool mNotifiedExpensiveRendering = false;
- bool mReconnectPowerHal = false;
+
+ const bool mUseUpdateImminentTimer;
+ std::atomic_bool mSendUpdateImminent = true;
+ scheduler::OneShotTimer mUpdateImminentTimer;
};
} // namespace impl
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 1da894d..ef59b55 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -368,6 +368,10 @@
const size_t defaultListSize = MAX_LAYERS;
auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize));
mMaxGraphicBufferProducerListSize = (listSize > 0) ? size_t(listSize) : defaultListSize;
+ mGraphicBufferProducerListSizeLogThreshold =
+ std::max(static_cast<int>(0.95 *
+ static_cast<double>(mMaxGraphicBufferProducerListSize)),
+ 1);
property_get("debug.sf.luma_sampling", value, "1");
mLumaSampling = atoi(value);
@@ -1487,11 +1491,13 @@
void SurfaceFlinger::signalTransaction() {
mScheduler->resetIdleTimer();
+ mPowerAdvisor.notifyDisplayUpdateImminent();
mEventQueue->invalidate();
}
void SurfaceFlinger::signalLayerUpdate() {
mScheduler->resetIdleTimer();
+ mPowerAdvisor.notifyDisplayUpdateImminent();
mEventQueue->invalidate();
}
@@ -3062,6 +3068,11 @@
"Suspected IGBP leak: %zu IGBPs (%zu max), %zu Layers",
mGraphicBufferProducerList.size(),
mMaxGraphicBufferProducerListSize, mNumLayers.load());
+ if (mGraphicBufferProducerList.size() > mGraphicBufferProducerListSizeLogThreshold) {
+ ALOGW("Suspected IGBP leak: %zu IGBPs (%zu max), %zu Layers",
+ mGraphicBufferProducerList.size(), mMaxGraphicBufferProducerListSize,
+ mNumLayers.load());
+ }
}
mLayersAdded = true;
}
@@ -5132,6 +5143,7 @@
void SurfaceFlinger::repaintEverythingForHWC() {
mRepaintEverything = true;
+ mPowerAdvisor.notifyDisplayUpdateImminent();
mEventQueue->invalidate();
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index e4a5da1..09a3430 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -972,6 +972,10 @@
// Can't be unordered_set because wp<> isn't hashable
std::set<wp<IBinder>> mGraphicBufferProducerList;
size_t mMaxGraphicBufferProducerListSize = MAX_LAYERS;
+ // If there are more GraphicBufferProducers tracked by SurfaceFlinger than
+ // this threshold, then begin logging.
+ size_t mGraphicBufferProducerListSizeLogThreshold =
+ static_cast<size_t>(0.95 * static_cast<double>(MAX_LAYERS));
// protected by mStateLock (but we could use another lock)
bool mLayersRemoved = false;
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.cpp b/services/surfaceflinger/SurfaceFlingerProperties.cpp
index 1a611f5..f3352a5 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.cpp
+++ b/services/surfaceflinger/SurfaceFlingerProperties.cpp
@@ -305,6 +305,14 @@
return defaultValue;
}
+int32_t display_update_imminent_timeout_ms(int32_t defaultValue) {
+ auto temp = SurfaceFlingerProperties::display_update_imminent_timeout_ms();
+ if (temp.has_value()) {
+ return *temp;
+ }
+ return defaultValue;
+}
+
#define DISPLAY_PRIMARY_SIZE 3
constexpr float kSrgbRedX = 0.4123f;
diff --git a/services/surfaceflinger/SurfaceFlingerProperties.h b/services/surfaceflinger/SurfaceFlingerProperties.h
index 4c6e191..12c711a 100644
--- a/services/surfaceflinger/SurfaceFlingerProperties.h
+++ b/services/surfaceflinger/SurfaceFlingerProperties.h
@@ -89,6 +89,8 @@
bool use_frame_rate_api(bool defaultValue);
+int32_t display_update_imminent_timeout_ms(int32_t defaultValue);
+
android::ui::DisplayPrimaries getDisplayNativePrimaries();
} // namespace sysprop
} // namespace android
diff --git a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
index b19eae6..155f718 100644
--- a/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
+++ b/services/surfaceflinger/sysprop/SurfaceFlingerProperties.sysprop
@@ -403,3 +403,15 @@
access: Readonly
prop_name: "ro.surface_flinger.use_frame_rate_api"
}
+
+# Sets the timeout used to rate limit DISPLAY_UPDATE_IMMINENT Power HAL notifications.
+# SurfaceFlinger wakeups will trigger this boost whenever they are separated by more than this
+# duration (specified in milliseconds). A value of 0 disables the rate limit, and will result in
+# Power HAL notifications every time SF wakes up.
+prop {
+ api_name: "display_update_imminent_timeout_ms"
+ type: Integer
+ scope: Public
+ access: Readonly
+ prop_name: "ro.surface_flinger.display_update_imminent_timeout_ms"
+}
diff --git a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
index c66523a..e62c127 100644
--- a/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
+++ b/services/surfaceflinger/sysprop/api/SurfaceFlingerProperties-current.txt
@@ -36,6 +36,11 @@
prop_name: "ro.surface_flinger.display_primary_white"
}
prop {
+ api_name: "display_update_imminent_timeout_ms"
+ type: Integer
+ prop_name: "ro.surface_flinger.display_update_imminent_timeout_ms"
+ }
+ prop {
api_name: "enable_protected_contents"
prop_name: "ro.surface_flinger.protected_contents"
}
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
index 7c65f95..fe57c98 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
@@ -30,6 +30,7 @@
~PowerAdvisor() override;
MOCK_METHOD2(setExpensiveRenderingExpected, void(DisplayId displayId, bool expected));
+ MOCK_METHOD0(notifyDisplayUpdateImminent, void());
};
} // namespace mock