Merge "sf: Update PowerAdvisor to talk to AIDL Power HAL"
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index e1a7bb8..02e5d9b 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -1103,7 +1103,7 @@
binder::Status InstalldNativeService::moveCompleteApp(const std::unique_ptr<std::string>& fromUuid,
const std::unique_ptr<std::string>& toUuid, const std::string& packageName,
- const std::string& dataAppName, int32_t appId, const std::string& seInfo,
+ int32_t appId, const std::string& seInfo,
int32_t targetSdkVersion, const std::string& fromCodePath) {
ENFORCE_UID(AID_SYSTEM);
CHECK_ARGUMENT_UUID(fromUuid);
@@ -1114,24 +1114,24 @@
const char* from_uuid = fromUuid ? fromUuid->c_str() : nullptr;
const char* to_uuid = toUuid ? toUuid->c_str() : nullptr;
const char* package_name = packageName.c_str();
- const char* data_app_name = dataAppName.c_str();
binder::Status res = ok();
std::vector<userid_t> users = get_known_users(from_uuid);
+ auto to_app_package_path_parent = create_data_app_path(to_uuid);
+ auto to_app_package_path = StringPrintf("%s/%s", to_app_package_path_parent.c_str(),
+ android::base::Basename(fromCodePath).c_str());
+
// Copy app
{
- auto to = create_data_app_package_path(to_uuid, data_app_name);
- auto to_parent = create_data_app_path(to_uuid);
-
- int rc = copy_directory_recursive(fromCodePath.c_str(), to_parent.c_str());
+ int rc = copy_directory_recursive(fromCodePath.c_str(), to_app_package_path_parent.c_str());
if (rc != 0) {
- res = error(rc, "Failed copying " + fromCodePath + " to " + to);
+ res = error(rc, "Failed copying " + fromCodePath + " to " + to_app_package_path);
goto fail;
}
- if (selinux_android_restorecon(to.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE) != 0) {
- res = error("Failed to restorecon " + to);
+ if (selinux_android_restorecon(to_app_package_path.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE) != 0) {
+ res = error("Failed to restorecon " + to_app_package_path);
goto fail;
}
}
@@ -1188,9 +1188,8 @@
fail:
// Nuke everything we might have already copied
{
- auto to = create_data_app_package_path(to_uuid, data_app_name);
- if (delete_dir_contents(to.c_str(), 1, nullptr) != 0) {
- LOG(WARNING) << "Failed to rollback " << to;
+ if (delete_dir_contents(to_app_package_path.c_str(), 1, nullptr) != 0) {
+ LOG(WARNING) << "Failed to rollback " << to_app_package_path;
}
}
for (auto user : users) {
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index 27c59b0..df01c3c 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -96,7 +96,7 @@
binder::Status moveCompleteApp(const std::unique_ptr<std::string>& fromUuid,
const std::unique_ptr<std::string>& toUuid, const std::string& packageName,
- const std::string& dataAppName, int32_t appId, const std::string& seInfo,
+ int32_t appId, const std::string& seInfo,
int32_t targetSdkVersion, const std::string& fromCodePath);
binder::Status dexopt(const std::string& apkPath, int32_t uid,
diff --git a/cmds/installd/binder/android/os/IInstalld.aidl b/cmds/installd/binder/android/os/IInstalld.aidl
index f2e86ba..ca95cb3 100644
--- a/cmds/installd/binder/android/os/IInstalld.aidl
+++ b/cmds/installd/binder/android/os/IInstalld.aidl
@@ -51,7 +51,7 @@
void setAppQuota(@nullable @utf8InCpp String uuid, int userId, int appId, long cacheQuota);
void moveCompleteApp(@nullable @utf8InCpp String fromUuid, @nullable @utf8InCpp String toUuid,
- @utf8InCpp String packageName, @utf8InCpp String dataAppName, int appId,
+ @utf8InCpp String packageName, int appId,
@utf8InCpp String seInfo, int targetSdkVersion, @utf8InCpp String fromCodePath);
void dexopt(@utf8InCpp String apkPath, int uid, @nullable @utf8InCpp String packageName,
diff --git a/cmds/installd/tests/installd_utils_test.cpp b/cmds/installd/tests/installd_utils_test.cpp
index d236f76..ed87b67 100644
--- a/cmds/installd/tests/installd_utils_test.cpp
+++ b/cmds/installd/tests/installd_utils_test.cpp
@@ -331,13 +331,6 @@
create_data_media_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", 10));
}
-TEST_F(UtilsTest, CreateDataAppPackagePath) {
- EXPECT_EQ("/data/app/com.example", create_data_app_package_path(nullptr, "com.example"));
-
- EXPECT_EQ("/mnt/expand/57f8f4bc-abf4-655f-bf67-946fc0f9f25b/app/com.example",
- create_data_app_package_path("57f8f4bc-abf4-655f-bf67-946fc0f9f25b", "com.example"));
-}
-
TEST_F(UtilsTest, CreateDataUserPackagePath) {
EXPECT_EQ("/data/data/com.example", create_data_user_ce_package_path(nullptr, 0, "com.example"));
EXPECT_EQ("/data/user/10/com.example", create_data_user_ce_package_path(nullptr, 10, "com.example"));
diff --git a/cmds/installd/utils.cpp b/cmds/installd/utils.cpp
index 939cf90..042d69e 100644
--- a/cmds/installd/utils.cpp
+++ b/cmds/installd/utils.cpp
@@ -100,18 +100,6 @@
}
/**
- * Create the path name where package app contents should be stored for
- * the given volume UUID and package name. An empty UUID is assumed to
- * be internal storage.
- */
-std::string create_data_app_package_path(const char* volume_uuid,
- const char* package_name) {
- check_package_name(package_name);
- return StringPrintf("%s/%s",
- create_data_app_path(volume_uuid).c_str(), package_name);
-}
-
-/**
* Create the path name where package data should be stored for the given
* volume UUID, package name, and user ID. An empty UUID is assumed to be
* internal storage.
diff --git a/cmds/installd/utils.h b/cmds/installd/utils.h
index 6a39adc..01126c0 100644
--- a/cmds/installd/utils.h
+++ b/cmds/installd/utils.h
@@ -47,7 +47,6 @@
std::string create_data_path(const char* volume_uuid);
std::string create_data_app_path(const char* volume_uuid);
-std::string create_data_app_package_path(const char* volume_uuid, const char* package_name);
std::string create_data_user_ce_path(const char* volume_uuid, userid_t userid);
std::string create_data_user_de_path(const char* volume_uuid, userid_t userid);
diff --git a/data/etc/android.hardware.tv.tuner.xml b/data/etc/android.hardware.tv.tuner.xml
new file mode 100644
index 0000000..bbf084f
--- /dev/null
+++ b/data/etc/android.hardware.tv.tuner.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- This feature indicates that the device has tuner hardware and tuner HAL
+ implementation to support tuner operations. -->
+<permissions>
+ <feature name="android.hardware.tv.tuner" />
+</permissions>
diff --git a/headers/media_plugin/media/openmax/OMX_AudioExt.h b/headers/media_plugin/media/openmax/OMX_AudioExt.h
index 477faed..b66efce 100644
--- a/headers/media_plugin/media/openmax/OMX_AudioExt.h
+++ b/headers/media_plugin/media/openmax/OMX_AudioExt.h
@@ -116,6 +116,8 @@
OMX_S32 nEncodedTargetLevel; /**< Target reference level assumed at the encoder, between 0 and 127, -1 if unspecified */
OMX_S32 nPCMLimiterEnable; /**< Signal level limiting, 0 for disable, 1 for enable, -1 if unspecified */
OMX_S32 nDrcEffectType; /**< MPEG-D DRC effect type, between -1 and 6, -2 if unspecified */
+ OMX_S32 nDrcOutputLoudness; /**< MPEG-D DRC Output Loudness, between -1 and 231, -2 if unspecified */
+ OMX_S32 nDrcAlbumMode; /**< MPEG-D DRC Album Mode, between 0 and 1, -1 if unspecified */
} OMX_AUDIO_PARAM_ANDROID_AACDRCPRESENTATIONTYPE;
typedef struct OMX_AUDIO_PARAM_ANDROID_PROFILETYPE {
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/InputDevice.h b/include/input/InputDevice.h
index b6efc82..20a17e3 100644
--- a/include/input/InputDevice.h
+++ b/include/input/InputDevice.h
@@ -180,6 +180,8 @@
VIRTUAL_KEYBOARD_ID = -1,
// Device id of the "built-in" keyboard if there is one.
BUILT_IN_KEYBOARD_ID = 0,
+ // First device id available for dynamic devices
+ END_RESERVED_ID = 1,
};
} // namespace android
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/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/ProcessState.cpp b/libs/binder/ProcessState.cpp
index bdc2e40..4b773e8 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -112,6 +112,10 @@
{
sp<IBinder> context = getStrongProxyForHandle(0);
+ if (context == nullptr) {
+ ALOGW("Not able to get context object on %s.", mDriverName.c_str());
+ }
+
// The root object is special since we get it directly from the driver, it is never
// written by Parcell::writeStrongBinder.
internal::Stability::tryMarkCompilationUnit(context.get());
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/binder/ndk/parcel.cpp b/libs/binder/ndk/parcel.cpp
index 703ceae..c33c44f 100644
--- a/libs/binder/ndk/parcel.cpp
+++ b/libs/binder/ndk/parcel.cpp
@@ -247,15 +247,12 @@
if (fd != -1) {
return STATUS_UNKNOWN_ERROR;
}
- return parcel->get()->writeInt32(0); // null
+ return PruneStatusT(parcel->get()->writeInt32(0)); // null
}
+ status_t status = parcel->get()->writeInt32(1); // not-null
+ if (status != STATUS_OK) return PruneStatusT(status);
- ParcelFileDescriptor parcelFd = ParcelFileDescriptor(unique_fd(fd));
- status_t status = parcel->get()->writeParcelable(parcelFd);
-
- // ownership is retained by caller
- (void)parcelFd.release().release();
-
+ status = parcel->get()->writeDupParcelFileDescriptor(fd);
return PruneStatusT(status);
}
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 94ab9f0..e343df7 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -30,6 +30,7 @@
#include <private/binder/binder_module.h>
#include <sys/epoll.h>
+#include <sys/prctl.h>
#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
@@ -107,6 +108,7 @@
if (pid == -1)
return pid;
if (pid == 0) {
+ prctl(PR_SET_PDEATHSIG, SIGHUP);
close(pipefd[0]);
execv(binderservername, childargv);
status = -errno;
diff --git a/libs/cputimeinstate/cputimeinstate.cpp b/libs/cputimeinstate/cputimeinstate.cpp
index fbc485c..0b77ab3 100644
--- a/libs/cputimeinstate/cputimeinstate.cpp
+++ b/libs/cputimeinstate/cputimeinstate.cpp
@@ -161,6 +161,17 @@
return bpf_attach_tracepoint(prog_fd, eventType.c_str(), eventName.c_str()) >= 0;
}
+static std::optional<uint32_t> getPolicyFreqIdx(uint32_t policy) {
+ auto path = StringPrintf("/sys/devices/system/cpu/cpufreq/policy%u/scaling_cur_freq",
+ gPolicyCpus[policy][0]);
+ auto freqVec = readNumbersFromFile(path);
+ if (!freqVec.has_value() || freqVec->size() != 1) return {};
+ for (uint32_t idx = 0; idx < gPolicyFreqs[policy].size(); ++idx) {
+ if ((*freqVec)[0] == gPolicyFreqs[policy][idx]) return idx + 1;
+ }
+ return {};
+}
+
// Start tracking and aggregating data to be reported by getUidCpuFreqTimes and getUidsCpuFreqTimes.
// Returns true on success, false otherwise.
// Tracking is active only once a live process has successfully called this function; if the calling
@@ -215,7 +226,9 @@
unique_fd policyFreqIdxFd(bpf_obj_get_wronly(BPF_FS_PATH "map_time_in_state_policy_freq_idx_map"));
if (policyFreqIdxFd < 0) return false;
for (uint32_t i = 0; i < gNPolicies; ++i) {
- if (writeToMapEntry(policyFreqIdxFd, &i, &zero, BPF_ANY)) return false;
+ auto freqIdx = getPolicyFreqIdx(i);
+ if (!freqIdx.has_value()) return false;
+ if (writeToMapEntry(policyFreqIdxFd, &i, &(*freqIdx), BPF_ANY)) return false;
}
gTracking = attachTracepointProgram("sched", "sched_switch") &&
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index 90fded0..1b42b69 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -35,7 +35,7 @@
"/system/bin/mediaserver",
"/system/bin/netd",
"/system/bin/sdcard",
- "/system/bin/statsd",
+ "/apex/com.android.os.statsd/bin/statsd",
"/system/bin/surfaceflinger",
"/system/bin/vehicle_network_service",
"/vendor/bin/hw/android.hardware.media.omx@1.0-service", // media.codec
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index acd833f..30e1351 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -101,6 +101,9 @@
mHeight(height),
mNextTransaction(nullptr) {
BufferQueue::createBufferQueue(&mProducer, &mConsumer);
+ // since the adapter is in the client process, set dequeue timeout
+ // explicitly so that dequeueBuffer will block
+ mProducer->setDequeueTimeout(std::numeric_limits<int64_t>::max());
int8_t disableTripleBuffer = property_get_bool("ro.sf.disable_triple_buffer", 0);
if (!disableTripleBuffer) {
diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp
index f09decf..fd1793b 100644
--- a/libs/nativewindow/ANativeWindow.cpp
+++ b/libs/nativewindow/ANativeWindow.cpp
@@ -335,7 +335,3 @@
void* data) {
return window->perform(window, NATIVE_WINDOW_SET_QUEUE_INTERCEPTOR, interceptor, data);
}
-
-int64_t ANativeWindow_getNextFrameId(ANativeWindow* window) {
- return query64(window, NATIVE_WINDOW_GET_NEXT_FRAME_ID);
-}
diff --git a/libs/nativewindow/include/apex/window.h b/libs/nativewindow/include/apex/window.h
index 02b886c..2d1354c 100644
--- a/libs/nativewindow/include/apex/window.h
+++ b/libs/nativewindow/include/apex/window.h
@@ -173,25 +173,22 @@
/**
* Retrieves how long it took for the last time a buffer was dequeued.
*
- * \return a negative value on error, otherwise returns the duration in
- * nanoseconds
+ * \return the dequeue duration in nanoseconds
*/
int64_t ANativeWindow_getLastDequeueDuration(ANativeWindow* window);
/**
* Retrieves how long it took for the last time a buffer was queued.
*
- * \return a negative value on error, otherwise returns the duration in
- * nanoseconds.
+ * \return the queue duration in nanoseconds
*/
int64_t ANativeWindow_getLastQueueDuration(ANativeWindow* window);
/**
* Retrieves the system time in nanoseconds when the last time a buffer
- * was dequeued.
+ * started to be dequeued.
*
- * \return a negative value on error, otherwise returns the duration in
- * nanoseconds.
+ * \return the start time in nanoseconds
*/
int64_t ANativeWindow_getLastDequeueStartTime(ANativeWindow* window);
@@ -200,23 +197,14 @@
* made by the window will return -ETIMEDOUT after the timeout if the dequeue
* takes too long.
*
- * \return NO_ERROR on success, -errno on error.
+ * If the provided timeout is negative, hen this removes the previously configured
+ * timeout. The window then behaves as if ANativeWindow_setDequeueTimeout was
+ * never called.
+ *
+ * \return NO_ERROR on success
+ * \return BAD_VALUE if the dequeue timeout was unabled to be updated, as
+ * updating the dequeue timeout may change internals of the underlying window.
*/
int ANativeWindow_setDequeueTimeout(ANativeWindow* window, int64_t timeout);
-/**
- * Provides a hint to the window that buffers should be preallocated ahead of
- * time. Note that the window implementation is not guaranteed to preallocate
- * any buffers, for instance if a private API disallows allocation of new
- * buffers. As such no success/error status is returned.
- */
-void ANativeWindow_allocateBuffers(ANativeWindow* window);
-
-/**
- * Retrieves an identifier for the next frame to be queued by this window.
- *
- * \return -errno on error, otherwise returns the next frame id.
- */
-int64_t ANativeWindow_getNextFrameId(ANativeWindow* window);
-
__END_DECLS
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 0e28fb8..869ca9e 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -1051,4 +1051,15 @@
outTransformMatrix);
}
+/**
+ * Retrieves an identifier for the next frame to be queued by this window.
+ *
+ * \return the next frame id.
+ */
+static inline int64_t ANativeWindow_getNextFrameId(ANativeWindow* window) {
+ int64_t value;
+ window->perform(window, NATIVE_WINDOW_GET_NEXT_FRAME_ID, &value);
+ return value;
+}
+
__END_DECLS
diff --git a/libs/nativewindow/libnativewindow.map.txt b/libs/nativewindow/libnativewindow.map.txt
index e072e11..1b5d20d 100644
--- a/libs/nativewindow/libnativewindow.map.txt
+++ b/libs/nativewindow/libnativewindow.map.txt
@@ -25,7 +25,6 @@
ANativeWindow_getLastDequeueDuration; # apex # introduced=30
ANativeWindow_getLastDequeueStartTime; # apex # introduced=30
ANativeWindow_getLastQueueDuration; # apex # introduced=30
- ANativeWindow_getNextFrameId; # apex # introduced=30
ANativeWindow_getWidth;
ANativeWindow_lock;
ANativeWindow_query; # llndk
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 5c80d55..439d9bf 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// Default flags to be used throughout all libraries in inputflinger.
cc_defaults {
name: "inputflinger_defaults",
cflags: [
@@ -23,22 +24,25 @@
],
}
-cc_library_shared {
- name: "libinputflinger",
- defaults: ["inputflinger_defaults"],
+/////////////////////////////////////////////////
+// libinputflinger
+/////////////////////////////////////////////////
+filegroup {
+ name: "libinputflinger_sources",
srcs: [
"InputClassifier.cpp",
"InputClassifierConverter.cpp",
"InputManager.cpp",
],
+}
+cc_defaults {
+ name: "libinputflinger_defaults",
+ srcs: [":libinputflinger_sources"],
shared_libs: [
"android.hardware.input.classifier@1.0",
"libbase",
- "libinputflinger_base",
- "libinputreporter",
- "libinputreader",
"libbinder",
"libcrypto",
"libcutils",
@@ -50,60 +54,76 @@
"libui",
"server_configurable_flags",
],
+}
- static_libs: [
- "libinputdispatcher",
+cc_library_shared {
+ name: "libinputflinger",
+ defaults: [
+ "inputflinger_defaults",
+ "libinputflinger_defaults",
],
-
cflags: [
// TODO(b/23084678): Move inputflinger to its own process and mark it hidden
//-fvisibility=hidden
],
-
+ shared_libs: [
+ // This should consist only of dependencies from inputflinger. Other dependencies should be
+ // in cc_defaults so that they are included in the tests.
+ "libinputflinger_base",
+ "libinputreporter",
+ "libinputreader",
+ ],
+ static_libs: [
+ "libinputdispatcher",
+ ],
+ export_static_lib_headers: [
+ "libinputdispatcher",
+ ],
export_include_dirs: [
".",
"include",
],
-
- export_static_lib_headers: [
- "libinputdispatcher",
- ],
}
+/////////////////////////////////////////////////
+// libinputflinger_base
+/////////////////////////////////////////////////
+
cc_library_headers {
name: "libinputflinger_headers",
- header_libs: ["libinputreporter_headers"],
export_include_dirs: ["include"],
- export_header_lib_headers: ["libinputreporter_headers"],
}
-cc_library_shared {
- name: "libinputflinger_base",
- defaults: ["inputflinger_defaults"],
-
+filegroup {
+ name: "libinputflinger_base_sources",
srcs: [
"InputListener.cpp",
"InputReaderBase.cpp",
"InputThread.cpp",
],
+}
+cc_defaults {
+ name: "libinputflinger_base_defaults",
+ srcs: [":libinputflinger_base_sources"],
shared_libs: [
"libbase",
"libinput",
"liblog",
"libutils",
],
-
header_libs: [
"libinputflinger_headers",
],
-
- export_header_lib_headers: [
- "libinputflinger_headers",
- ],
}
-subdirs = [
- "host",
- "tests",
-]
+cc_library_shared {
+ name: "libinputflinger_base",
+ defaults: [
+ "inputflinger_defaults",
+ "libinputflinger_base_defaults",
+ ],
+ export_header_lib_headers: [
+ "libinputflinger_headers",
+ ],
+}
diff --git a/services/inputflinger/benchmarks/Android.bp b/services/inputflinger/benchmarks/Android.bp
index 385b981..066a816 100644
--- a/services/inputflinger/benchmarks/Android.bp
+++ b/services/inputflinger/benchmarks/Android.bp
@@ -7,6 +7,7 @@
shared_libs: [
"libbase",
"libbinder",
+ "libcrypto",
"libcutils",
"libinput",
"libinputflinger_base",
diff --git a/services/inputflinger/dispatcher/Android.bp b/services/inputflinger/dispatcher/Android.bp
index 3f956a8..a98f4b4 100644
--- a/services/inputflinger/dispatcher/Android.bp
+++ b/services/inputflinger/dispatcher/Android.bp
@@ -12,9 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-cc_library_static {
- name: "libinputdispatcher",
- defaults: ["inputflinger_defaults"],
+cc_library_headers {
+ name: "libinputdispatcher_headers",
+ export_include_dirs: [
+ "include",
+ ],
+}
+
+filegroup {
+ name: "libinputdispatcher_sources",
srcs: [
"Connection.cpp",
"Entry.cpp",
@@ -24,20 +30,41 @@
"InputState.cpp",
"InputTarget.cpp",
"Monitor.cpp",
- "TouchState.cpp"
+ "TouchState.cpp",
],
+}
+
+cc_defaults {
+ name: "libinputdispatcher_defaults",
+ srcs: [":libinputdispatcher_sources"],
shared_libs: [
"libbase",
"libcrypto",
"libcutils",
"libinput",
- "libinputreporter",
- "libinputflinger_base",
"liblog",
"libstatslog",
"libui",
"libutils",
],
+ header_libs: [
+ "libinputdispatcher_headers",
+ ],
+}
- export_include_dirs: ["include"],
+cc_library_static {
+ name: "libinputdispatcher",
+ defaults: [
+ "inputflinger_defaults",
+ "libinputdispatcher_defaults",
+ ],
+ shared_libs: [
+ // This should consist only of dependencies from inputflinger. Other dependencies should be
+ // in cc_defaults so that they are included in the tests.
+ "libinputreporter",
+ "libinputflinger_base",
+ ],
+ export_header_lib_headers: [
+ "libinputdispatcher_headers",
+ ],
}
diff --git a/services/inputflinger/dispatcher/Entry.cpp b/services/inputflinger/dispatcher/Entry.cpp
index b723654..c4b3789 100644
--- a/services/inputflinger/dispatcher/Entry.cpp
+++ b/services/inputflinger/dispatcher/Entry.cpp
@@ -57,6 +57,32 @@
}
return StringPrintf("%" PRId32, action);
}
+VerifiedKeyEvent verifiedKeyEventFromKeyEntry(const KeyEntry& entry) {
+ return {{VerifiedInputEvent::Type::KEY, entry.deviceId, entry.eventTime, entry.source,
+ entry.displayId},
+ entry.action,
+ entry.downTime,
+ entry.flags & VERIFIED_KEY_EVENT_FLAGS,
+ entry.keyCode,
+ entry.scanCode,
+ entry.metaState,
+ entry.repeatCount};
+}
+
+VerifiedMotionEvent verifiedMotionEventFromMotionEntry(const MotionEntry& entry) {
+ const float rawX = entry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X);
+ const float rawY = entry.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y);
+ const int actionMasked = entry.action & AMOTION_EVENT_ACTION_MASK;
+ return {{VerifiedInputEvent::Type::MOTION, entry.deviceId, entry.eventTime, entry.source,
+ entry.displayId},
+ rawX,
+ rawY,
+ actionMasked,
+ entry.downTime,
+ entry.flags & VERIFIED_MOTION_EVENT_FLAGS,
+ entry.metaState,
+ entry.buttonState};
+}
// --- EventEntry ---
diff --git a/services/inputflinger/dispatcher/Entry.h b/services/inputflinger/dispatcher/Entry.h
index e8c37f0..b5b61cc 100644
--- a/services/inputflinger/dispatcher/Entry.h
+++ b/services/inputflinger/dispatcher/Entry.h
@@ -220,6 +220,9 @@
static uint32_t nextSeq();
};
+VerifiedKeyEvent verifiedKeyEventFromKeyEntry(const KeyEntry& entry);
+VerifiedMotionEvent verifiedMotionEventFromMotionEntry(const MotionEntry& entry);
+
class InputDispatcher;
// A command entry captures state and behavior for an action to be performed in the
// dispatch loop after the initial processing has taken place. It is essentially
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 75bc0aa..f9a86dd 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -2433,12 +2433,16 @@
switch (eventEntry->type) {
case EventEntry::Type::KEY: {
KeyEntry* keyEntry = static_cast<KeyEntry*>(eventEntry);
+ VerifiedKeyEvent verifiedEvent = verifiedKeyEventFromKeyEntry(*keyEntry);
+ verifiedEvent.flags = dispatchEntry->resolvedFlags & VERIFIED_KEY_EVENT_FLAGS;
+ verifiedEvent.action = dispatchEntry->resolvedAction;
+ 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,
- INVALID_HMAC, dispatchEntry->resolvedAction,
+ std::move(hmac), dispatchEntry->resolvedAction,
dispatchEntry->resolvedFlags, keyEntry->keyCode,
keyEntry->scanCode, keyEntry->metaState,
keyEntry->repeatCount, keyEntry->downTime,
@@ -2482,12 +2486,18 @@
usingCoords = scaledCoords;
}
}
+ VerifiedMotionEvent verifiedEvent =
+ verifiedMotionEventFromMotionEntry(*motionEntry);
+ verifiedEvent.actionMasked =
+ dispatchEntry->resolvedAction & AMOTION_EVENT_ACTION_MASK;
+ verifiedEvent.flags = dispatchEntry->resolvedFlags & VERIFIED_MOTION_EVENT_FLAGS;
+ std::array<uint8_t, 32> hmac = mHmacKeyManager.sign(verifiedEvent);
// Publish the motion event.
status = connection->inputPublisher
.publishMotionEvent(dispatchEntry->seq, motionEntry->deviceId,
motionEntry->source, motionEntry->displayId,
- INVALID_HMAC, dispatchEntry->resolvedAction,
+ std::move(hmac), dispatchEntry->resolvedAction,
motionEntry->actionButton,
dispatchEntry->resolvedFlags,
motionEntry->edgeFlags, motionEntry->metaState,
@@ -3392,7 +3402,36 @@
}
std::unique_ptr<VerifiedInputEvent> InputDispatcher::verifyInputEvent(const InputEvent& event) {
- return nullptr;
+ std::array<uint8_t, 32> calculatedHmac;
+ std::unique_ptr<VerifiedInputEvent> result;
+ switch (event.getType()) {
+ case AINPUT_EVENT_TYPE_KEY: {
+ const KeyEvent& keyEvent = static_cast<const KeyEvent&>(event);
+ VerifiedKeyEvent verifiedKeyEvent = verifiedKeyEventFromKeyEvent(keyEvent);
+ result = std::make_unique<VerifiedKeyEvent>(verifiedKeyEvent);
+ calculatedHmac = mHmacKeyManager.sign(verifiedKeyEvent);
+ break;
+ }
+ case AINPUT_EVENT_TYPE_MOTION: {
+ const MotionEvent& motionEvent = static_cast<const MotionEvent&>(event);
+ VerifiedMotionEvent verifiedMotionEvent =
+ verifiedMotionEventFromMotionEvent(motionEvent);
+ result = std::make_unique<VerifiedMotionEvent>(verifiedMotionEvent);
+ calculatedHmac = mHmacKeyManager.sign(verifiedMotionEvent);
+ break;
+ }
+ default: {
+ ALOGE("Cannot verify events of type %" PRId32, event.getType());
+ return nullptr;
+ }
+ }
+ if (calculatedHmac == INVALID_HMAC) {
+ return nullptr;
+ }
+ if (calculatedHmac != event.getHmac()) {
+ return nullptr;
+ }
+ return result;
}
bool InputDispatcher::hasInjectionPermission(int32_t injectorPid, int32_t injectorUid) {
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index ded59a5..482133e 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -217,6 +217,8 @@
// the pointer stream in order to claim it for a system gesture.
std::unordered_map<int32_t, std::vector<Monitor>> mGestureMonitorsByDisplay GUARDED_BY(mLock);
+ HmacKeyManager mHmacKeyManager;
+
// Event injection and synchronization.
std::condition_variable mInjectionResultAvailable;
bool hasInjectionPermission(int32_t injectorPid, int32_t injectorUid);
diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp
index 23c08b2..83a610f 100644
--- a/services/inputflinger/reader/Android.bp
+++ b/services/inputflinger/reader/Android.bp
@@ -21,10 +21,8 @@
],
}
-cc_library_shared {
- name: "libinputreader",
- defaults: ["inputflinger_defaults"],
-
+filegroup {
+ name: "libinputreader_sources",
srcs: [
"EventHub.cpp",
"InputDevice.cpp",
@@ -44,14 +42,16 @@
"mapper/TouchInputMapper.cpp",
"mapper/VibratorInputMapper.cpp",
"InputReader.cpp",
- "InputReaderFactory.cpp",
"TouchVideoDevice.cpp",
],
+}
+cc_defaults {
+ name: "libinputreader_defaults",
+ srcs: [":libinputreader_sources"],
shared_libs: [
"libbase",
"libcap",
- "libinputflinger_base",
"libcrypto",
"libcutils",
"libinput",
@@ -59,13 +59,26 @@
"libui",
"libutils",
],
-
header_libs: [
- "libinputflinger_headers",
"libinputreader_headers",
],
+}
+cc_library_shared {
+ name: "libinputreader",
+ defaults: [
+ "inputflinger_defaults",
+ "libinputreader_defaults"
+ ],
+ srcs: [
+ "InputReaderFactory.cpp",
+ ],
+ shared_libs: [
+ // This should consist only of dependencies from inputflinger. Other dependencies should be
+ // in cc_defaults so that they are included in the tests.
+ "libinputflinger_base",
+ ],
export_header_lib_headers: [
- "libinputflinger_headers",
+ "libinputreader_headers",
],
}
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index ae82cd4..f2afc81 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -18,6 +18,8 @@
#include "InputDevice.h"
+#include <algorithm>
+
#include "CursorInputMapper.h"
#include "ExternalStylusInputMapper.h"
#include "InputReaderContext.h"
@@ -32,25 +34,28 @@
namespace android {
InputDevice::InputDevice(InputReaderContext* context, int32_t id, int32_t generation,
- int32_t controllerNumber, const InputDeviceIdentifier& identifier,
- uint32_t classes)
+ const InputDeviceIdentifier& identifier)
: mContext(context),
mId(id),
mGeneration(generation),
- mControllerNumber(controllerNumber),
+ mControllerNumber(0),
mIdentifier(identifier),
- mClasses(classes),
+ mClasses(0),
mSources(0),
mIsExternal(false),
mHasMic(false),
- mDropUntilNextSync(false) {
- mDeviceContext = std::make_unique<InputDeviceContext>(*this);
-}
+ mDropUntilNextSync(false) {}
InputDevice::~InputDevice() {}
bool InputDevice::isEnabled() {
- return mDeviceContext->isDeviceEnabled();
+ if (!hasEventHubDevices()) {
+ return false;
+ }
+ // devices are either all enabled or all disabled, so we only need to check the first
+ auto& devicePair = mDevices.begin()->second;
+ auto& contextPtr = devicePair.first;
+ return contextPtr->isDeviceEnabled();
}
void InputDevice::setEnabled(bool enabled, nsecs_t when) {
@@ -65,12 +70,15 @@
return;
}
+ // When resetting some devices, the driver needs to be queried to ensure that a proper reset is
+ // performed. The querying must happen when the device is enabled, so we reset after enabling
+ // but before disabling the device. See MultiTouchMotionAccumulator::reset for more information.
if (enabled) {
- mDeviceContext->enableDevice();
+ for_each_subdevice([](auto& context) { context.enableDevice(); });
reset(when);
} else {
reset(when);
- mDeviceContext->disableDevice();
+ for_each_subdevice([](auto& context) { context.disableDevice(); });
}
// Must change generation to flag this device as changed
bumpGeneration();
@@ -118,19 +126,18 @@
for_each_mapper([&dump](InputMapper& mapper) { mapper.dump(dump); });
}
-void InputDevice::populateMappers() {
- uint32_t classes = mClasses;
- std::vector<std::unique_ptr<InputMapper>>& mappers = mMappers;
- std::unique_ptr<InputDeviceContext>& contextPtr = mDeviceContext;
-
- // External devices.
- if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
- setExternal(true);
+void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) {
+ if (mDevices.find(eventHubId) != mDevices.end()) {
+ return;
}
+ std::unique_ptr<InputDeviceContext> contextPtr(new InputDeviceContext(*this, eventHubId));
+ uint32_t classes = contextPtr->getDeviceClasses();
+ std::vector<std::unique_ptr<InputMapper>> mappers;
- // Devices with mics.
- if (classes & INPUT_DEVICE_CLASS_MIC) {
- setMic(true);
+ // Check if we should skip population
+ if (!populateMappers) {
+ mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});
+ return;
}
// Switch-like devices.
@@ -190,22 +197,58 @@
if (classes & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
mappers.push_back(std::make_unique<ExternalStylusInputMapper>(*contextPtr));
}
+
+ // insert the context into the devices set
+ mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});
+}
+
+void InputDevice::removeEventHubDevice(int32_t eventHubId) {
+ mDevices.erase(eventHubId);
}
void InputDevice::configure(nsecs_t when, const InputReaderConfiguration* config,
uint32_t changes) {
mSources = 0;
+ mClasses = 0;
+ mControllerNumber = 0;
+
+ for_each_subdevice([this](InputDeviceContext& context) {
+ mClasses |= context.getDeviceClasses();
+ int32_t controllerNumber = context.getDeviceControllerNumber();
+ if (controllerNumber > 0) {
+ if (mControllerNumber && mControllerNumber != controllerNumber) {
+ ALOGW("InputDevice::configure(): composite device contains multiple unique "
+ "controller numbers");
+ }
+ mControllerNumber = controllerNumber;
+ }
+ });
+
+ mIsExternal = !!(mClasses & INPUT_DEVICE_CLASS_EXTERNAL);
+ mHasMic = !!(mClasses & INPUT_DEVICE_CLASS_MIC);
if (!isIgnored()) {
if (!changes) { // first time only
- mDeviceContext->getConfiguration(&mConfiguration);
+ mConfiguration.clear();
+ for_each_subdevice([this](InputDeviceContext& context) {
+ PropertyMap configuration;
+ context.getConfiguration(&configuration);
+ mConfiguration.addAll(&configuration);
+ });
}
if (!changes || (changes & InputReaderConfiguration::CHANGE_KEYBOARD_LAYOUTS)) {
if (!(mClasses & INPUT_DEVICE_CLASS_VIRTUAL)) {
sp<KeyCharacterMap> keyboardLayout =
mContext->getPolicy()->getKeyboardLayoutOverlay(mIdentifier);
- if (mDeviceContext->setKeyboardLayoutOverlay(keyboardLayout)) {
+ bool shouldBumpGeneration = false;
+ for_each_subdevice(
+ [&keyboardLayout, &shouldBumpGeneration](InputDeviceContext& context) {
+ if (context.setKeyboardLayoutOverlay(keyboardLayout)) {
+ shouldBumpGeneration = true;
+ }
+ });
+ if (shouldBumpGeneration) {
bumpGeneration();
}
}
@@ -313,7 +356,9 @@
mDropUntilNextSync = true;
reset(rawEvent->when);
} else {
- for_each_mapper([rawEvent](InputMapper& mapper) { mapper.process(rawEvent); });
+ for_each_mapper_in_subdevice(rawEvent->deviceId, [rawEvent](InputMapper& mapper) {
+ mapper.process(rawEvent);
+ });
}
--count;
}
@@ -348,16 +393,20 @@
int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
int32_t result = AKEY_STATE_UNKNOWN;
- for (auto& mapperPtr : mMappers) {
- InputMapper& mapper = *mapperPtr;
- if (sourcesMatchMask(mapper.getSources(), sourceMask)) {
- // If any mapper reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
- // value. Otherwise, return AKEY_STATE_UP as long as one mapper reports it.
- int32_t currentResult = (mapper.*getStateFunc)(sourceMask, code);
- if (currentResult >= AKEY_STATE_DOWN) {
- return currentResult;
- } else if (currentResult == AKEY_STATE_UP) {
- result = currentResult;
+ for (auto& deviceEntry : mDevices) {
+ auto& devicePair = deviceEntry.second;
+ auto& mappers = devicePair.second;
+ for (auto& mapperPtr : mappers) {
+ InputMapper& mapper = *mapperPtr;
+ if (sourcesMatchMask(mapper.getSources(), sourceMask)) {
+ // If any mapper reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
+ // value. Otherwise, return AKEY_STATE_UP as long as one mapper reports it.
+ int32_t currentResult = (mapper.*getStateFunc)(sourceMask, code);
+ if (currentResult >= AKEY_STATE_DOWN) {
+ return currentResult;
+ } else if (currentResult == AKEY_STATE_UP) {
+ result = currentResult;
+ }
}
}
}
@@ -400,10 +449,6 @@
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();
}
@@ -424,11 +469,23 @@
[](InputMapper& mapper) { return mapper.getAssociatedDisplayId(); });
}
-InputDeviceContext::InputDeviceContext(InputDevice& device)
+// returns the number of mappers associated with the device
+size_t InputDevice::getMapperCount() {
+ size_t count = 0;
+ for (auto& deviceEntry : mDevices) {
+ auto& devicePair = deviceEntry.second;
+ auto& mappers = devicePair.second;
+ count += mappers.size();
+ }
+ return count;
+}
+
+InputDeviceContext::InputDeviceContext(InputDevice& device, int32_t eventHubId)
: mDevice(device),
mContext(device.getContext()),
mEventHub(device.getContext()->getEventHub()),
- mId(device.getId()) {}
+ mId(eventHubId),
+ mDeviceId(device.getId()) {}
InputDeviceContext::~InputDeviceContext() {}
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 3e23fa6..6ab5902 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -49,6 +49,7 @@
mNextSequenceNum(1),
mGlobalMetaState(0),
mGeneration(1),
+ mNextInputDeviceId(END_RESERVED_ID),
mDisableVirtualKeysTimeout(LLONG_MIN),
mNextTimeout(LLONG_MAX),
mConfigurationChangesToRefresh(0) {
@@ -62,11 +63,7 @@
} // release lock
}
-InputReader::~InputReader() {
- for (auto& devicePair : mDevices) {
- delete devicePair.second;
- }
-}
+InputReader::~InputReader() {}
status_t InputReader::start() {
if (mThread) {
@@ -188,29 +185,28 @@
}
}
-void InputReader::addDeviceLocked(nsecs_t when, int32_t deviceId) {
- if (mDevices.find(deviceId) != mDevices.end()) {
- ALOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
+void InputReader::addDeviceLocked(nsecs_t when, int32_t eventHubId) {
+ if (mDevices.find(eventHubId) != mDevices.end()) {
+ ALOGW("Ignoring spurious device added event for eventHubId %d.", eventHubId);
return;
}
- InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(deviceId);
- uint32_t classes = mEventHub->getDeviceClasses(deviceId);
- int32_t controllerNumber = mEventHub->getDeviceControllerNumber(deviceId);
-
- InputDevice* device = createDeviceLocked(deviceId, controllerNumber, identifier, classes);
+ InputDeviceIdentifier identifier = mEventHub->getDeviceIdentifier(eventHubId);
+ std::shared_ptr<InputDevice> device = createDeviceLocked(eventHubId, identifier);
device->configure(when, &mConfig, 0);
device->reset(when);
if (device->isIgnored()) {
- ALOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId,
- identifier.name.c_str());
+ ALOGI("Device added: id=%d, eventHubId=%d, name='%s', descriptor='%s' "
+ "(ignored non-input device)",
+ device->getId(), eventHubId, identifier.name.c_str(), identifier.descriptor.c_str());
} else {
- ALOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId, identifier.name.c_str(),
+ ALOGI("Device added: id=%d, eventHubId=%d, name='%s', descriptor='%s',sources=0x%08x",
+ device->getId(), eventHubId, identifier.name.c_str(), identifier.descriptor.c_str(),
device->getSources());
}
- mDevices.insert({deviceId, device});
+ mDevices.emplace(eventHubId, device);
bumpGenerationLocked();
if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
@@ -218,51 +214,68 @@
}
}
-void InputReader::removeDeviceLocked(nsecs_t when, int32_t deviceId) {
- auto deviceIt = mDevices.find(deviceId);
+void InputReader::removeDeviceLocked(nsecs_t when, int32_t eventHubId) {
+ auto deviceIt = mDevices.find(eventHubId);
if (deviceIt == mDevices.end()) {
- ALOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
+ ALOGW("Ignoring spurious device removed event for eventHubId %d.", eventHubId);
return;
}
- InputDevice* device = deviceIt->second;
+ std::shared_ptr<InputDevice> device = std::move(deviceIt->second);
mDevices.erase(deviceIt);
bumpGenerationLocked();
if (device->isIgnored()) {
- ALOGI("Device removed: id=%d, name='%s' (ignored non-input device)", device->getId(),
- device->getName().c_str());
+ ALOGI("Device removed: id=%d, eventHubId=%d, name='%s', descriptor='%s' "
+ "(ignored non-input device)",
+ device->getId(), eventHubId, device->getName().c_str(),
+ device->getDescriptor().c_str());
} else {
- ALOGI("Device removed: id=%d, name='%s', sources=0x%08x", device->getId(),
- device->getName().c_str(), device->getSources());
+ ALOGI("Device removed: id=%d, eventHubId=%d, name='%s', descriptor='%s', sources=0x%08x",
+ device->getId(), eventHubId, device->getName().c_str(),
+ device->getDescriptor().c_str(), device->getSources());
}
+ device->removeEventHubDevice(eventHubId);
+
if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
notifyExternalStylusPresenceChanged();
}
+ if (device->hasEventHubDevices()) {
+ device->configure(when, &mConfig, 0);
+ }
device->reset(when);
- delete device;
}
-InputDevice* InputReader::createDeviceLocked(int32_t deviceId, int32_t controllerNumber,
- const InputDeviceIdentifier& identifier,
- uint32_t classes) {
- InputDevice* device = new InputDevice(&mContext, deviceId, bumpGenerationLocked(),
- controllerNumber, identifier, classes);
- device->populateMappers();
+std::shared_ptr<InputDevice> InputReader::createDeviceLocked(
+ int32_t eventHubId, const InputDeviceIdentifier& identifier) {
+ auto deviceIt = std::find_if(mDevices.begin(), mDevices.end(), [identifier](auto& devicePair) {
+ return devicePair.second->getDescriptor().size() && identifier.descriptor.size() &&
+ devicePair.second->getDescriptor() == identifier.descriptor;
+ });
+
+ std::shared_ptr<InputDevice> device;
+ if (deviceIt != mDevices.end()) {
+ device = deviceIt->second;
+ } else {
+ int32_t deviceId = (eventHubId < END_RESERVED_ID) ? eventHubId : nextInputDeviceIdLocked();
+ device = std::make_shared<InputDevice>(&mContext, deviceId, bumpGenerationLocked(),
+ identifier);
+ }
+ device->addEventHubDevice(eventHubId);
return device;
}
-void InputReader::processEventsForDeviceLocked(int32_t deviceId, const RawEvent* rawEvents,
+void InputReader::processEventsForDeviceLocked(int32_t eventHubId, const RawEvent* rawEvents,
size_t count) {
- auto deviceIt = mDevices.find(deviceId);
+ auto deviceIt = mDevices.find(eventHubId);
if (deviceIt == mDevices.end()) {
- ALOGW("Discarding event for unknown deviceId %d.", deviceId);
+ ALOGW("Discarding event for unknown eventHubId %d.", eventHubId);
return;
}
- InputDevice* device = deviceIt->second;
+ std::shared_ptr<InputDevice>& device = deviceIt->second;
if (device->isIgnored()) {
// ALOGD("Discarding event for ignored deviceId %d.", deviceId);
return;
@@ -271,15 +284,30 @@
device->process(rawEvents, count);
}
+InputDevice* InputReader::findInputDevice(int32_t deviceId) {
+ auto deviceIt =
+ std::find_if(mDevices.begin(), mDevices.end(), [deviceId](const auto& devicePair) {
+ return devicePair.second->getId() == deviceId;
+ });
+ if (deviceIt != mDevices.end()) {
+ return deviceIt->second.get();
+ }
+ return nullptr;
+}
+
void InputReader::timeoutExpiredLocked(nsecs_t when) {
for (auto& devicePair : mDevices) {
- InputDevice* device = devicePair.second;
+ std::shared_ptr<InputDevice>& device = devicePair.second;
if (!device->isIgnored()) {
device->timeoutExpired(when);
}
}
}
+int32_t InputReader::nextInputDeviceIdLocked() {
+ return ++mNextInputDeviceId;
+}
+
void InputReader::handleConfigurationChangedLocked(nsecs_t when) {
// Reset global meta state because it depends on the list of all configured devices.
updateGlobalMetaStateLocked();
@@ -298,11 +326,15 @@
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 {
for (auto& devicePair : mDevices) {
- InputDevice* device = devicePair.second;
+ std::shared_ptr<InputDevice>& device = devicePair.second;
device->configure(now, &mConfig, changes);
}
}
@@ -313,7 +345,7 @@
mGlobalMetaState = 0;
for (auto& devicePair : mDevices) {
- InputDevice* device = devicePair.second;
+ std::shared_ptr<InputDevice>& device = devicePair.second;
mGlobalMetaState |= device->getMetaState();
}
}
@@ -328,7 +360,7 @@
void InputReader::getExternalStylusDevicesLocked(std::vector<InputDeviceInfo>& outDevices) {
for (auto& devicePair : mDevices) {
- InputDevice* device = devicePair.second;
+ std::shared_ptr<InputDevice>& device = devicePair.second;
if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS && !device->isIgnored()) {
InputDeviceInfo info;
device->getDeviceInfo(&info);
@@ -339,7 +371,7 @@
void InputReader::dispatchExternalStylusState(const StylusState& state) {
for (auto& devicePair : mDevices) {
- InputDevice* device = devicePair.second;
+ std::shared_ptr<InputDevice>& device = devicePair.second;
device->updateExternalStylusState(state);
}
}
@@ -359,10 +391,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) {
- InputDevice* device = devicePair.second;
- device->fadePointer();
+ sp<PointerControllerInterface> controller = mPointerController.promote();
+ if (controller != nullptr) {
+ controller->fade(PointerControllerInterface::TRANSITION_GRADUAL);
}
}
@@ -386,7 +451,7 @@
outInputDevices.clear();
for (auto& devicePair : mDevices) {
- InputDevice* device = devicePair.second;
+ std::shared_ptr<InputDevice>& device = devicePair.second;
if (!device->isIgnored()) {
InputDeviceInfo info;
device->getDeviceInfo(&info);
@@ -417,20 +482,17 @@
GetStateFunc getStateFunc) {
int32_t result = AKEY_STATE_UNKNOWN;
if (deviceId >= 0) {
- auto deviceIt = mDevices.find(deviceId);
- if (deviceIt != mDevices.end()) {
- InputDevice* device = deviceIt->second;
- if (!device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
- result = (device->*getStateFunc)(sourceMask, code);
- }
+ InputDevice* device = findInputDevice(deviceId);
+ if (device && !device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
+ result = (device->*getStateFunc)(sourceMask, code);
}
} else {
for (auto& devicePair : mDevices) {
- InputDevice* device = devicePair.second;
+ std::shared_ptr<InputDevice>& device = devicePair.second;
if (!device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
// If any device reports AKEY_STATE_DOWN or AKEY_STATE_VIRTUAL, return that
// value. Otherwise, return AKEY_STATE_UP as long as one device reports it.
- int32_t currentResult = (device->*getStateFunc)(sourceMask, code);
+ int32_t currentResult = (device.get()->*getStateFunc)(sourceMask, code);
if (currentResult >= AKEY_STATE_DOWN) {
return currentResult;
} else if (currentResult == AKEY_STATE_UP) {
@@ -443,13 +505,12 @@
}
void InputReader::toggleCapsLockState(int32_t deviceId) {
- auto deviceIt = mDevices.find(deviceId);
- if (deviceIt == mDevices.end()) {
+ InputDevice* device = findInputDevice(deviceId);
+ if (!device) {
ALOGW("Ignoring toggleCapsLock for unknown deviceId %" PRId32 ".", deviceId);
return;
}
- InputDevice* device = deviceIt->second;
if (device->isIgnored()) {
return;
}
@@ -470,16 +531,13 @@
uint8_t* outFlags) {
bool result = false;
if (deviceId >= 0) {
- auto deviceIt = mDevices.find(deviceId);
- if (deviceIt != mDevices.end()) {
- InputDevice* device = deviceIt->second;
- if (!device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
- result = device->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
- }
+ InputDevice* device = findInputDevice(deviceId);
+ if (device && !device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
+ result = device->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
}
} else {
for (auto& devicePair : mDevices) {
- InputDevice* device = devicePair.second;
+ std::shared_ptr<InputDevice>& device = devicePair.second;
if (!device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
result |= device->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
}
@@ -504,9 +562,8 @@
void InputReader::vibrate(int32_t deviceId, const nsecs_t* pattern, size_t patternSize,
ssize_t repeat, int32_t token) {
AutoMutex _l(mLock);
- auto deviceIt = mDevices.find(deviceId);
- if (deviceIt != mDevices.end()) {
- InputDevice* device = deviceIt->second;
+ InputDevice* device = findInputDevice(deviceId);
+ if (device) {
device->vibrate(pattern, patternSize, repeat, token);
}
}
@@ -514,9 +571,8 @@
void InputReader::cancelVibrate(int32_t deviceId, int32_t token) {
AutoMutex _l(mLock);
- auto deviceIt = mDevices.find(deviceId);
- if (deviceIt != mDevices.end()) {
- InputDevice* device = deviceIt->second;
+ InputDevice* device = findInputDevice(deviceId);
+ if (device) {
device->cancelVibrate(token);
}
}
@@ -524,9 +580,8 @@
bool InputReader::isInputDeviceEnabled(int32_t deviceId) {
AutoMutex _l(mLock);
- auto deviceIt = mDevices.find(deviceId);
- if (deviceIt != mDevices.end()) {
- InputDevice* device = deviceIt->second;
+ InputDevice* device = findInputDevice(deviceId);
+ if (device) {
return device->isEnabled();
}
ALOGW("Ignoring invalid device id %" PRId32 ".", deviceId);
@@ -536,13 +591,12 @@
bool InputReader::canDispatchToDisplay(int32_t deviceId, int32_t displayId) {
AutoMutex _l(mLock);
- auto deviceIt = mDevices.find(deviceId);
- if (deviceIt == mDevices.end()) {
+ InputDevice* device = findInputDevice(deviceId);
+ if (!device) {
ALOGW("Ignoring invalid device id %" PRId32 ".", deviceId);
return false;
}
- InputDevice* device = deviceIt->second;
if (!device->isEnabled()) {
ALOGW("Ignoring disabled device %s", device->getName().c_str());
return false;
@@ -571,7 +625,7 @@
dump += "Input Reader State:\n";
for (const auto& devicePair : mDevices) {
- InputDevice* const device = devicePair.second;
+ const std::shared_ptr<InputDevice>& device = devicePair.second;
device->dump(dump);
}
@@ -671,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);
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index 0814d1f..71313fc 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -17,18 +17,19 @@
#ifndef _UI_INPUTREADER_INPUT_DEVICE_H
#define _UI_INPUTREADER_INPUT_DEVICE_H
+#include <input/DisplayViewport.h>
+#include <input/InputDevice.h>
+#include <stdint.h>
+#include <utils/PropertyMap.h>
+
+#include <optional>
+#include <unordered_map>
+#include <vector>
+
#include "EventHub.h"
#include "InputReaderBase.h"
#include "InputReaderContext.h"
-#include <input/DisplayViewport.h>
-#include <input/InputDevice.h>
-#include <utils/PropertyMap.h>
-
-#include <stdint.h>
-#include <optional>
-#include <vector>
-
namespace android {
class InputDeviceContext;
@@ -38,8 +39,7 @@
class InputDevice {
public:
InputDevice(InputReaderContext* context, int32_t id, int32_t generation,
- int32_t controllerNumber, const InputDeviceIdentifier& identifier,
- uint32_t classes);
+ const InputDeviceIdentifier& identifier);
~InputDevice();
inline InputReaderContext* getContext() { return mContext; }
@@ -50,25 +50,25 @@
inline const std::string getDescriptor() { return mIdentifier.descriptor; }
inline uint32_t getClasses() const { return mClasses; }
inline uint32_t getSources() const { return mSources; }
+ inline bool hasEventHubDevices() const { return !mDevices.empty(); }
inline bool isExternal() { return mIsExternal; }
- inline void setExternal(bool external) { mIsExternal = external; }
inline std::optional<uint8_t> getAssociatedDisplayPort() const {
return mAssociatedDisplayPort;
}
inline std::optional<DisplayViewport> getAssociatedViewport() const {
return mAssociatedViewport;
}
- inline void setMic(bool hasMic) { mHasMic = hasMic; }
inline bool hasMic() const { return mHasMic; }
- inline bool isIgnored() { return mMappers.empty(); }
+ inline bool isIgnored() { return !getMapperCount(); }
bool isEnabled();
void setEnabled(bool enabled, nsecs_t when);
void dump(std::string& dump);
- void populateMappers();
+ void addEventHubDevice(int32_t eventHubId, bool populateMappers = true);
+ void removeEventHubDevice(int32_t eventHubId);
void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
void reset(nsecs_t when);
void process(const RawEvent* rawEvents, size_t count);
@@ -88,8 +88,6 @@
int32_t getMetaState();
void updateMetaState(int32_t keyCode);
- void fadePointer();
-
void bumpGeneration();
void notifyReset(nsecs_t when);
@@ -99,11 +97,20 @@
std::optional<int32_t> getAssociatedDisplayId();
+ size_t getMapperCount();
+
// construct and add a mapper to the input device
template <class T, typename... Args>
- T& addMapper(Args... args) {
- T* mapper = new T(*mDeviceContext, args...);
- mMappers.emplace_back(mapper);
+ T& addMapper(int32_t eventHubId, Args... args) {
+ // ensure a device entry exists for this eventHubId
+ addEventHubDevice(eventHubId, false);
+
+ // create mapper
+ auto& devicePair = mDevices[eventHubId];
+ auto& deviceContext = devicePair.first;
+ auto& mappers = devicePair.second;
+ T* mapper = new T(*deviceContext, args...);
+ mappers.emplace_back(mapper);
return *mapper;
}
@@ -116,8 +123,10 @@
std::string mAlias;
uint32_t mClasses;
- std::unique_ptr<InputDeviceContext> mDeviceContext;
- std::vector<std::unique_ptr<InputMapper>> mMappers;
+ // map from eventHubId to device context and mappers
+ using MapperVector = std::vector<std::unique_ptr<InputMapper>>;
+ using DevicePair = std::pair<std::unique_ptr<InputDeviceContext>, MapperVector>;
+ std::unordered_map<int32_t, DevicePair> mDevices;
uint32_t mSources;
bool mIsExternal;
@@ -131,10 +140,37 @@
PropertyMap mConfiguration;
- // run a function against every mapper
+ // helpers to interate over the devices collection
+ // run a function against every mapper on every subdevice
inline void for_each_mapper(std::function<void(InputMapper&)> f) {
- for (auto& mapperPtr : mMappers) {
- f(*mapperPtr);
+ for (auto& deviceEntry : mDevices) {
+ auto& devicePair = deviceEntry.second;
+ auto& mappers = devicePair.second;
+ for (auto& mapperPtr : mappers) {
+ f(*mapperPtr);
+ }
+ }
+ }
+
+ // run a function against every mapper on a specific subdevice
+ inline void for_each_mapper_in_subdevice(int32_t eventHubDevice,
+ std::function<void(InputMapper&)> f) {
+ auto deviceIt = mDevices.find(eventHubDevice);
+ if (deviceIt != mDevices.end()) {
+ auto& devicePair = deviceIt->second;
+ auto& mappers = devicePair.second;
+ for (auto& mapperPtr : mappers) {
+ f(*mapperPtr);
+ }
+ }
+ }
+
+ // run a function against every subdevice
+ inline void for_each_subdevice(std::function<void(InputDeviceContext&)> f) {
+ for (auto& deviceEntry : mDevices) {
+ auto& devicePair = deviceEntry.second;
+ auto& contextPtr = devicePair.first;
+ f(*contextPtr);
}
}
@@ -142,10 +178,14 @@
// if all mappers return nullopt, return nullopt.
template <typename T>
inline std::optional<T> first_in_mappers(std::function<std::optional<T>(InputMapper&)> f) {
- for (auto& mapperPtr : mMappers) {
- std::optional<T> ret = f(*mapperPtr);
- if (ret) {
- return ret;
+ for (auto& deviceEntry : mDevices) {
+ auto& devicePair = deviceEntry.second;
+ auto& mappers = devicePair.second;
+ for (auto& mapperPtr : mappers) {
+ std::optional<T> ret = f(*mapperPtr);
+ if (ret) {
+ return ret;
+ }
}
}
return std::nullopt;
@@ -159,11 +199,12 @@
*/
class InputDeviceContext {
public:
- InputDeviceContext(InputDevice& device);
+ InputDeviceContext(InputDevice& device, int32_t eventHubId);
~InputDeviceContext();
inline InputReaderContext* getContext() { return mContext; }
- inline int32_t getId() { return mId; }
+ inline int32_t getId() { return mDeviceId; }
+ inline int32_t getEventHubId() { return mId; }
inline uint32_t getDeviceClasses() const { return mEventHub->getDeviceClasses(mId); }
inline InputDeviceIdentifier getDeviceIdentifier() const {
@@ -259,6 +300,7 @@
InputReaderContext* mContext;
EventHubInterface* mEventHub;
int32_t mId;
+ int32_t mDeviceId;
};
} // namespace android
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index cf1af04..ca1a081 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>
@@ -84,9 +85,8 @@
protected:
// These members are protected so they can be instrumented by test cases.
- virtual InputDevice* createDeviceLocked(int32_t deviceId, int32_t controllerNumber,
- const InputDeviceIdentifier& identifier,
- uint32_t classes);
+ virtual std::shared_ptr<InputDevice> createDeviceLocked(
+ int32_t deviceId, const InputDeviceIdentifier& identifier);
// With each iteration of the loop, InputReader reads and processes one incoming message from
// the EventHub.
@@ -103,6 +103,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;
@@ -138,14 +139,16 @@
static const int EVENT_BUFFER_SIZE = 256;
RawEvent mEventBuffer[EVENT_BUFFER_SIZE];
- std::unordered_map<int32_t /*deviceId*/, InputDevice*> mDevices;
+ // An input device can represent a collection of EventHub devices. This map provides a way
+ // to lookup the input device instance from the EventHub device id.
+ std::unordered_map<int32_t /*eventHubId*/, std::shared_ptr<InputDevice>> mDevices;
// low-level input event decoding and device management
void processEventsLocked(const RawEvent* rawEvents, size_t count);
- void addDeviceLocked(nsecs_t when, int32_t deviceId);
- void removeDeviceLocked(nsecs_t when, int32_t deviceId);
- void processEventsForDeviceLocked(int32_t deviceId, const RawEvent* rawEvents, size_t count);
+ void addDeviceLocked(nsecs_t when, int32_t eventHubId);
+ void removeDeviceLocked(nsecs_t when, int32_t eventHubId);
+ void processEventsForDeviceLocked(int32_t eventHubId, const RawEvent* rawEvents, size_t count);
void timeoutExpiredLocked(nsecs_t when);
void handleConfigurationChangedLocked(nsecs_t when);
@@ -158,11 +161,18 @@
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;
int32_t bumpGenerationLocked();
+ int32_t mNextInputDeviceId;
+ int32_t nextInputDeviceIdLocked();
+
void getInputDevicesLocked(std::vector<InputDeviceInfo>& outInputDevices);
nsecs_t mDisableVirtualKeysTimeout;
@@ -181,6 +191,9 @@
GetStateFunc getStateFunc);
bool markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
const int32_t* keyCodes, uint8_t* outFlags);
+
+ // find an InputDevice from an InputDevice id
+ InputDevice* findInputDevice(int32_t deviceId);
};
} // namespace android
diff --git a/services/inputflinger/reader/include/InputReaderContext.h b/services/inputflinger/reader/include/InputReaderContext.h
index e14fbbe..d5527cf 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;
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
index 78f3382..c4162bc 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "Macros.h"
+#include "../Macros.h"
#include "CursorInputMapper.h"
@@ -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;
@@ -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;
@@ -481,12 +457,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/ExternalStylusInputMapper.cpp b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp
index 37e4047..37d1d74 100644
--- a/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/ExternalStylusInputMapper.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "Macros.h"
+#include "../Macros.h"
#include "ExternalStylusInputMapper.h"
diff --git a/services/inputflinger/reader/mapper/InputMapper.cpp b/services/inputflinger/reader/mapper/InputMapper.cpp
index 92af612..a8fe39a 100644
--- a/services/inputflinger/reader/mapper/InputMapper.cpp
+++ b/services/inputflinger/reader/mapper/InputMapper.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "Macros.h"
+#include "../Macros.h"
#include "InputMapper.h"
@@ -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 57c85b6..7c3b1d9 100644
--- a/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/JoystickInputMapper.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "Macros.h"
+#include "../Macros.h"
#include "JoystickInputMapper.h"
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
index 9ab707f..ab354a2 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "Macros.h"
+#include "../Macros.h"
#include "KeyboardInputMapper.h"
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
index d195a07..d77c8c8 100644
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "Macros.h"
+#include "../Macros.h"
#include "MultiTouchInputMapper.h"
diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
index a1cce56..ed93f14 100644
--- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "Macros.h"
+#include "../Macros.h"
#include "RotaryEncoderInputMapper.h"
diff --git a/services/inputflinger/reader/mapper/SwitchInputMapper.cpp b/services/inputflinger/reader/mapper/SwitchInputMapper.cpp
index 52b2449..e79aeb2 100644
--- a/services/inputflinger/reader/mapper/SwitchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/SwitchInputMapper.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "Macros.h"
+#include "../Macros.h"
#include "SwitchInputMapper.h"
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index e832804..7543374 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "Macros.h"
+#include "../Macros.h"
#include "TouchInputMapper.h"
@@ -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();
@@ -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/reader/mapper/VibratorInputMapper.cpp b/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
index 1b584ea..7665680 100644
--- a/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "Macros.h"
+#include "../Macros.h"
#include "VibratorInputMapper.h"
diff --git a/services/inputflinger/reporter/Android.bp b/services/inputflinger/reporter/Android.bp
index 5956fb0..fbc51da 100644
--- a/services/inputflinger/reporter/Android.bp
+++ b/services/inputflinger/reporter/Android.bp
@@ -17,25 +17,33 @@
export_include_dirs: ["."],
}
-cc_library_shared {
- name: "libinputreporter",
- defaults: ["inputflinger_defaults"],
-
+filegroup {
+ name: "libinputreporter_sources",
srcs: [
- "InputReporter.cpp",
+ "InputReporter.cpp",
],
+}
+cc_defaults {
+ name: "libinputreporter_defaults",
+ srcs: [":libinputreporter_sources"],
shared_libs: [
"liblog",
"libutils",
],
-
header_libs: [
- "libinputflinger_headers",
+ "libinputreporter_headers",
],
+}
+cc_library_shared {
+ name: "libinputreporter",
+ defaults: [
+ "inputflinger_defaults",
+ "libinputreporter_defaults",
+ ],
export_header_lib_headers: [
- "libinputflinger_headers",
+ "libinputreporter_headers",
],
}
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index f913d82..73d2272 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -1,7 +1,31 @@
-// Build the unit tests.
+// 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.
cc_test {
name: "inputflinger_tests",
+ defaults: [
+ "inputflinger_defaults",
+ // For all targets inside inputflinger, these tests build all of their sources using their
+ // defaults rather than including them as shared or static libraries. By doing so, the tests
+ // will always run against the compiled version of the inputflinger code rather than the
+ // version on the device.
+ "libinputflinger_base_defaults",
+ "libinputreader_defaults",
+ "libinputreporter_defaults",
+ "libinputdispatcher_defaults",
+ "libinputflinger_defaults",
+ ],
srcs: [
"BlockingQueue_test.cpp",
"EventHub_test.cpp",
@@ -12,31 +36,5 @@
"InputReader_test.cpp",
"UinputDevice.cpp",
],
- cflags: [
- "-Wall",
- "-Werror",
- "-Wextra",
- "-Wno-unused-parameter",
- "-Wthread-safety",
- ],
- shared_libs: [
- "android.hardware.input.classifier@1.0",
- "libbase",
- "libbinder",
- "libcutils",
- "liblog",
- "libutils",
- "libhardware",
- "libhardware_legacy",
- "libui",
- "libinput",
- "libinputflinger",
- "libinputreader",
- "libinputflinger_base",
- "libinputservice",
- ],
- header_libs: [
- "libinputreader_headers",
- ],
require_root: true,
}
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index c4092cd..2fb1b65 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -1398,6 +1398,44 @@
window->assertNoEvents();
}
+TEST_F(InputDispatcherTest, VerifyInputEvent_KeyEvent) {
+ sp<FakeApplicationHandle> application = new FakeApplicationHandle();
+ sp<FakeWindowHandle> window =
+ new FakeWindowHandle(application, mDispatcher, "Test window", ADISPLAY_ID_DEFAULT);
+
+ mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
+ window->setFocus(true);
+
+ mDispatcher->setInputWindows({window}, ADISPLAY_ID_DEFAULT);
+ window->consumeFocusEvent(true /*hasFocus*/, true /*inTouchMode*/);
+
+ NotifyKeyArgs keyArgs = generateKeyArgs(AKEY_EVENT_ACTION_DOWN);
+ mDispatcher->notifyKey(&keyArgs);
+
+ InputEvent* event = window->consume();
+ ASSERT_NE(event, nullptr);
+
+ std::unique_ptr<VerifiedInputEvent> verified = mDispatcher->verifyInputEvent(*event);
+ ASSERT_NE(verified, nullptr);
+ ASSERT_EQ(verified->type, VerifiedInputEvent::Type::KEY);
+
+ ASSERT_EQ(keyArgs.eventTime, verified->eventTimeNanos);
+ ASSERT_EQ(keyArgs.deviceId, verified->deviceId);
+ ASSERT_EQ(keyArgs.source, verified->source);
+ ASSERT_EQ(keyArgs.displayId, verified->displayId);
+
+ const VerifiedKeyEvent& verifiedKey = static_cast<const VerifiedKeyEvent&>(*verified);
+
+ ASSERT_EQ(keyArgs.action, verifiedKey.action);
+ ASSERT_EQ(keyArgs.downTime, verifiedKey.downTimeNanos);
+ ASSERT_EQ(keyArgs.eventTime, verifiedKey.eventTimeNanos);
+ ASSERT_EQ(keyArgs.flags & VERIFIED_KEY_EVENT_FLAGS, verifiedKey.flags);
+ ASSERT_EQ(keyArgs.keyCode, verifiedKey.keyCode);
+ ASSERT_EQ(keyArgs.scanCode, verifiedKey.scanCode);
+ ASSERT_EQ(keyArgs.metaState, verifiedKey.metaState);
+ ASSERT_EQ(0, verifiedKey.repeatCount);
+}
+
/* 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 01bd9db..4da9d93 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -18,12 +18,15 @@
#include <InputDevice.h>
#include <InputMapper.h>
#include <InputReader.h>
+#include <InputReaderBase.h>
+#include <InputReaderFactory.h>
#include <KeyboardInputMapper.h>
#include <MultiTouchInputMapper.h>
#include <SingleTouchInputMapper.h>
#include <SwitchInputMapper.h>
#include <TestInputListener.h>
#include <TouchInputMapper.h>
+#include <UinputDevice.h>
#include <android-base/thread_annotations.h>
#include <gtest/gtest.h>
@@ -187,17 +190,19 @@
}
void assertInputDevicesChanged() {
- std::unique_lock<std::mutex> lock(mLock);
- base::ScopedLockAssertion assumeLocked(mLock);
+ waitForInputDevices([](bool devicesChanged) {
+ if (!devicesChanged) {
+ FAIL() << "Timed out waiting for notifyInputDevicesChanged() to be called.";
+ }
+ });
+ }
- const bool devicesChanged =
- mDevicesChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
- return mInputDevicesChanged;
- });
- if (!devicesChanged) {
- FAIL() << "Timed out waiting for notifyInputDevicesChanged() to be called.";
- }
- mInputDevicesChanged = false;
+ void assertInputDevicesNotChanged() {
+ waitForInputDevices([](bool devicesChanged) {
+ if (devicesChanged) {
+ FAIL() << "Expected notifyInputDevicesChanged() to not be called.";
+ }
+ });
}
virtual void clearViewports() {
@@ -331,6 +336,18 @@
virtual std::string getDeviceAlias(const InputDeviceIdentifier&) {
return "";
}
+
+ void waitForInputDevices(std::function<void(bool)> processDevicesChanged) {
+ std::unique_lock<std::mutex> lock(mLock);
+ base::ScopedLockAssertion assumeLocked(mLock);
+
+ const bool devicesChanged =
+ mDevicesChangedCondition.wait_for(lock, WAIT_TIMEOUT, [this]() REQUIRES(mLock) {
+ return mInputDevicesChanged;
+ });
+ ASSERT_NO_FATAL_FAILURE(processDevicesChanged(devicesChanged));
+ mInputDevicesChanged = false;
+ }
};
// --- FakeEventHub ---
@@ -830,6 +847,7 @@
bool mUpdateGlobalMetaStateWasCalled;
int32_t mGeneration;
uint32_t mNextSequenceNum;
+ wp<PointerControllerInterface> mPointerController;
public:
FakeInputReaderContext(std::shared_ptr<EventHubInterface> eventHub,
@@ -857,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;
@@ -883,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() {
}
@@ -1091,7 +1131,7 @@
// --- InstrumentedInputReader ---
class InstrumentedInputReader : public InputReader {
- InputDevice* mNextDevice;
+ std::shared_ptr<InputDevice> mNextDevice;
public:
InstrumentedInputReader(std::shared_ptr<EventHubInterface> eventHub,
@@ -1099,37 +1139,31 @@
const sp<InputListenerInterface>& listener)
: InputReader(eventHub, policy, listener), mNextDevice(nullptr) {}
- virtual ~InstrumentedInputReader() {
- if (mNextDevice) {
- delete mNextDevice;
- }
- }
+ virtual ~InstrumentedInputReader() {}
- void setNextDevice(InputDevice* device) { mNextDevice = device; }
+ void setNextDevice(std::shared_ptr<InputDevice> device) { mNextDevice = device; }
- InputDevice* newDevice(int32_t deviceId, int32_t controllerNumber, const std::string& name,
- uint32_t classes, const std::string& location = "") {
+ std::shared_ptr<InputDevice> newDevice(int32_t deviceId, const std::string& name,
+ const std::string& location = "") {
InputDeviceIdentifier identifier;
identifier.name = name;
identifier.location = location;
int32_t generation = deviceId + 1;
- return new InputDevice(&mContext, deviceId, generation, controllerNumber, identifier,
- classes);
+ return std::make_shared<InputDevice>(&mContext, deviceId, generation, identifier);
}
// Make the protected loopOnce method accessible to tests.
using InputReader::loopOnce;
protected:
- virtual InputDevice* createDeviceLocked(int32_t deviceId, int32_t controllerNumber,
- const InputDeviceIdentifier& identifier,
- uint32_t classes) {
+ virtual std::shared_ptr<InputDevice> createDeviceLocked(
+ int32_t eventHubId, const InputDeviceIdentifier& identifier) {
if (mNextDevice) {
- InputDevice* device = mNextDevice;
+ std::shared_ptr<InputDevice> device(mNextDevice);
mNextDevice = nullptr;
return device;
}
- return InputReader::createDeviceLocked(deviceId, controllerNumber, identifier, classes);
+ return InputReader::createDeviceLocked(eventHubId, identifier);
}
friend class InputReaderTest;
@@ -1340,12 +1374,12 @@
mFakePolicy.clear();
}
- void addDevice(int32_t deviceId, const std::string& name, uint32_t classes,
- const PropertyMap* configuration) {
- mFakeEventHub->addDevice(deviceId, name, classes);
+ void addDevice(int32_t eventHubId, const std::string& name, uint32_t classes,
+ const PropertyMap* configuration) {
+ mFakeEventHub->addDevice(eventHubId, name, classes);
if (configuration) {
- mFakeEventHub->addConfigurationMap(deviceId, configuration);
+ mFakeEventHub->addConfigurationMap(eventHubId, configuration);
}
mFakeEventHub->finishDeviceScan();
mReader->loopOnce();
@@ -1364,14 +1398,14 @@
mReader->requestRefreshConfiguration(InputReaderConfiguration::CHANGE_ENABLED_STATE);
}
- FakeInputMapper& addDeviceWithFakeInputMapper(int32_t deviceId, int32_t controllerNumber,
+ FakeInputMapper& addDeviceWithFakeInputMapper(int32_t deviceId, int32_t eventHubId,
const std::string& name, uint32_t classes,
uint32_t sources,
const PropertyMap* configuration) {
- InputDevice* device = mReader->newDevice(deviceId, controllerNumber, name, classes);
- FakeInputMapper& mapper = device->addMapper<FakeInputMapper>(sources);
+ std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, name);
+ FakeInputMapper& mapper = device->addMapper<FakeInputMapper>(eventHubId, sources);
mReader->setNextDevice(device);
- addDevice(deviceId, name, classes, configuration);
+ addDevice(eventHubId, name, classes, configuration);
return mapper;
}
};
@@ -1385,7 +1419,7 @@
std::vector<InputDeviceInfo> inputDevices;
mReader->getInputDevices(inputDevices);
ASSERT_EQ(1U, inputDevices.size());
- ASSERT_EQ(1, inputDevices[0].getId());
+ ASSERT_EQ(END_RESERVED_ID + 1, inputDevices[0].getId());
ASSERT_STREQ("keyboard", inputDevices[0].getIdentifier().name.c_str());
ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, inputDevices[0].getKeyboardType());
ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, inputDevices[0].getSources());
@@ -1394,7 +1428,7 @@
// Should also have received a notification describing the new input devices.
inputDevices = mFakePolicy->getInputDevices();
ASSERT_EQ(1U, inputDevices.size());
- ASSERT_EQ(1, inputDevices[0].getId());
+ ASSERT_EQ(END_RESERVED_ID + 1, inputDevices[0].getId());
ASSERT_STREQ("keyboard", inputDevices[0].getIdentifier().name.c_str());
ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, inputDevices[0].getKeyboardType());
ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, inputDevices[0].getSources());
@@ -1402,13 +1436,14 @@
}
TEST_F(InputReaderTest, WhenEnabledChanges_SendsDeviceResetNotification) {
- constexpr int32_t deviceId = 1;
+ constexpr int32_t deviceId = END_RESERVED_ID + 1000;
constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD;
- InputDevice* device = mReader->newDevice(deviceId, 0 /*controllerNumber*/, "fake", deviceClass);
+ 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>(AINPUT_SOURCE_KEYBOARD);
+ device->addMapper<FakeInputMapper>(eventHubId, AINPUT_SOURCE_KEYBOARD);
mReader->setNextDevice(device);
- ASSERT_NO_FATAL_FAILURE(addDevice(deviceId, "fake", deviceClass, nullptr));
+ ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled(nullptr));
@@ -1438,8 +1473,11 @@
}
TEST_F(InputReaderTest, GetKeyCodeState_ForwardsRequestsToMappers) {
+ constexpr int32_t deviceId = END_RESERVED_ID + 1000;
+ constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD;
+ constexpr int32_t eventHubId = 1;
FakeInputMapper& mapper =
- addDeviceWithFakeInputMapper(1, 0, "fake", INPUT_DEVICE_CLASS_KEYBOARD,
+ addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
AINPUT_SOURCE_KEYBOARD, nullptr);
mapper.setKeyCodeState(AKEYCODE_A, AKEY_STATE_DOWN);
@@ -1447,13 +1485,16 @@
AINPUT_SOURCE_ANY, AKEYCODE_A))
<< "Should return unknown when the device id is >= 0 but unknown.";
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(1,
- AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
- << "Should return unknown when the device id is valid but the sources are not supported by the device.";
+ ASSERT_EQ(AKEY_STATE_UNKNOWN,
+ mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
+ << "Should return unknown when the device id is valid but the sources are not "
+ "supported by the device.";
- ASSERT_EQ(AKEY_STATE_DOWN, mReader->getKeyCodeState(1,
- AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
- << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
+ ASSERT_EQ(AKEY_STATE_DOWN,
+ mReader->getKeyCodeState(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
+ AKEYCODE_A))
+ << "Should return value provided by mapper when device id is valid and the device "
+ "supports some of the sources.";
ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getKeyCodeState(-1,
AINPUT_SOURCE_TRACKBALL, AKEYCODE_A))
@@ -1465,8 +1506,11 @@
}
TEST_F(InputReaderTest, GetScanCodeState_ForwardsRequestsToMappers) {
+ constexpr int32_t deviceId = END_RESERVED_ID + 1000;
+ constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD;
+ constexpr int32_t eventHubId = 1;
FakeInputMapper& mapper =
- addDeviceWithFakeInputMapper(1, 0, "fake", INPUT_DEVICE_CLASS_KEYBOARD,
+ addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
AINPUT_SOURCE_KEYBOARD, nullptr);
mapper.setScanCodeState(KEY_A, AKEY_STATE_DOWN);
@@ -1474,13 +1518,16 @@
AINPUT_SOURCE_ANY, KEY_A))
<< "Should return unknown when the device id is >= 0 but unknown.";
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(1,
- AINPUT_SOURCE_TRACKBALL, KEY_A))
- << "Should return unknown when the device id is valid but the sources are not supported by the device.";
+ ASSERT_EQ(AKEY_STATE_UNKNOWN,
+ mReader->getScanCodeState(deviceId, AINPUT_SOURCE_TRACKBALL, KEY_A))
+ << "Should return unknown when the device id is valid but the sources are not "
+ "supported by the device.";
- ASSERT_EQ(AKEY_STATE_DOWN, mReader->getScanCodeState(1,
- AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, KEY_A))
- << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
+ ASSERT_EQ(AKEY_STATE_DOWN,
+ mReader->getScanCodeState(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
+ KEY_A))
+ << "Should return value provided by mapper when device id is valid and the device "
+ "supports some of the sources.";
ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getScanCodeState(-1,
AINPUT_SOURCE_TRACKBALL, KEY_A))
@@ -1492,8 +1539,11 @@
}
TEST_F(InputReaderTest, GetSwitchState_ForwardsRequestsToMappers) {
+ constexpr int32_t deviceId = END_RESERVED_ID + 1000;
+ constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD;
+ constexpr int32_t eventHubId = 1;
FakeInputMapper& mapper =
- addDeviceWithFakeInputMapper(1, 0, "fake", INPUT_DEVICE_CLASS_KEYBOARD,
+ addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
AINPUT_SOURCE_KEYBOARD, nullptr);
mapper.setSwitchState(SW_LID, AKEY_STATE_DOWN);
@@ -1501,13 +1551,16 @@
AINPUT_SOURCE_ANY, SW_LID))
<< "Should return unknown when the device id is >= 0 but unknown.";
- ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(1,
- AINPUT_SOURCE_TRACKBALL, SW_LID))
- << "Should return unknown when the device id is valid but the sources are not supported by the device.";
+ ASSERT_EQ(AKEY_STATE_UNKNOWN,
+ mReader->getSwitchState(deviceId, AINPUT_SOURCE_TRACKBALL, SW_LID))
+ << "Should return unknown when the device id is valid but the sources are not "
+ "supported by the device.";
- ASSERT_EQ(AKEY_STATE_DOWN, mReader->getSwitchState(1,
- AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, SW_LID))
- << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
+ ASSERT_EQ(AKEY_STATE_DOWN,
+ mReader->getSwitchState(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
+ SW_LID))
+ << "Should return value provided by mapper when device id is valid and the device "
+ "supports some of the sources.";
ASSERT_EQ(AKEY_STATE_UNKNOWN, mReader->getSwitchState(-1,
AINPUT_SOURCE_TRACKBALL, SW_LID))
@@ -1519,8 +1572,11 @@
}
TEST_F(InputReaderTest, MarkSupportedKeyCodes_ForwardsRequestsToMappers) {
+ constexpr int32_t deviceId = END_RESERVED_ID + 1000;
+ constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD;
+ constexpr int32_t eventHubId = 1;
FakeInputMapper& mapper =
- addDeviceWithFakeInputMapper(1, 0, "fake", INPUT_DEVICE_CLASS_KEYBOARD,
+ addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
AINPUT_SOURCE_KEYBOARD, nullptr);
mapper.addSupportedKeyCode(AKEYCODE_A);
@@ -1534,13 +1590,16 @@
ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
flags[3] = 1;
- ASSERT_FALSE(mReader->hasKeys(1, AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
- << "Should return false when device id is valid but the sources are not supported by the device.";
+ ASSERT_FALSE(mReader->hasKeys(deviceId, AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
+ << "Should return false when device id is valid but the sources are not supported by "
+ "the device.";
ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
flags[3] = 1;
- ASSERT_TRUE(mReader->hasKeys(1, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
- << "Should return value provided by mapper when device id is valid and the device supports some of the sources.";
+ ASSERT_TRUE(mReader->hasKeys(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, 4,
+ keyCodes, flags))
+ << "Should return value provided by mapper when device id is valid and the device "
+ "supports some of the sources.";
ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
flags[3] = 1;
@@ -1555,7 +1614,8 @@
}
TEST_F(InputReaderTest, LoopOnce_WhenDeviceScanFinished_SendsConfigurationChanged) {
- addDevice(1, "ignored", INPUT_DEVICE_CLASS_KEYBOARD, nullptr);
+ constexpr int32_t eventHubId = 1;
+ addDevice(eventHubId, "ignored", INPUT_DEVICE_CLASS_KEYBOARD, nullptr);
NotifyConfigurationChangedArgs args;
@@ -1564,31 +1624,35 @@
}
TEST_F(InputReaderTest, LoopOnce_ForwardsRawEventsToMappers) {
+ constexpr int32_t deviceId = END_RESERVED_ID + 1000;
+ constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD;
+ constexpr int32_t eventHubId = 1;
FakeInputMapper& mapper =
- addDeviceWithFakeInputMapper(1, 0, "fake", INPUT_DEVICE_CLASS_KEYBOARD,
+ addDeviceWithFakeInputMapper(deviceId, eventHubId, "fake", deviceClass,
AINPUT_SOURCE_KEYBOARD, nullptr);
- mFakeEventHub->enqueueEvent(0, 1, EV_KEY, KEY_A, 1);
+ mFakeEventHub->enqueueEvent(0, eventHubId, EV_KEY, KEY_A, 1);
mReader->loopOnce();
ASSERT_NO_FATAL_FAILURE(mFakeEventHub->assertQueueIsEmpty());
RawEvent event;
ASSERT_NO_FATAL_FAILURE(mapper.assertProcessWasCalled(&event));
ASSERT_EQ(0, event.when);
- ASSERT_EQ(1, event.deviceId);
+ ASSERT_EQ(eventHubId, event.deviceId);
ASSERT_EQ(EV_KEY, event.type);
ASSERT_EQ(KEY_A, event.code);
ASSERT_EQ(1, event.value);
}
TEST_F(InputReaderTest, DeviceReset_IncrementsSequenceNumber) {
- constexpr int32_t deviceId = 1;
+ constexpr int32_t deviceId = END_RESERVED_ID + 1000;
constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD;
- InputDevice* device = mReader->newDevice(deviceId, 0 /*controllerNumber*/, "fake", deviceClass);
+ 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>(AINPUT_SOURCE_KEYBOARD);
+ device->addMapper<FakeInputMapper>(eventHubId, AINPUT_SOURCE_KEYBOARD);
mReader->setNextDevice(device);
- ASSERT_NO_FATAL_FAILURE(addDevice(deviceId, "fake", deviceClass, nullptr));
+ ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
NotifyDeviceResetArgs resetArgs;
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled(&resetArgs));
@@ -1614,12 +1678,13 @@
}
TEST_F(InputReaderTest, Device_CanDispatchToDisplay) {
- constexpr int32_t deviceId = 1;
+ constexpr int32_t deviceId = END_RESERVED_ID + 1000;
constexpr uint32_t deviceClass = INPUT_DEVICE_CLASS_KEYBOARD;
+ constexpr int32_t eventHubId = 1;
const char* DEVICE_LOCATION = "USB1";
- InputDevice* device = mReader->newDevice(deviceId, 0 /*controllerNumber*/, "fake", deviceClass,
- DEVICE_LOCATION);
- FakeInputMapper& mapper = device->addMapper<FakeInputMapper>(AINPUT_SOURCE_TOUCHSCREEN);
+ std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
+ FakeInputMapper& mapper =
+ device->addMapper<FakeInputMapper>(eventHubId, AINPUT_SOURCE_TOUCHSCREEN);
mReader->setNextDevice(device);
const uint8_t hdmi1 = 1;
@@ -1639,7 +1704,7 @@
// Add the device, and make sure all of the callbacks are triggered.
// The device is added after the input port associations are processed since
// we do not yet support dynamic device-to-display associations.
- ASSERT_NO_FATAL_FAILURE(addDevice(deviceId, "fake", deviceClass, nullptr));
+ ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyConfigurationChangedWasCalled());
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());
ASSERT_NO_FATAL_FAILURE(mapper.assertConfigureWasCalled());
@@ -1655,6 +1720,119 @@
ASSERT_FALSE(mReader->canDispatchToDisplay(deviceId, SECONDARY_DISPLAY_ID));
}
+// --- InputReaderIntegrationTest ---
+
+// These tests create and interact with the InputReader only through its interface.
+// The InputReader is started during SetUp(), which starts its processing in its own
+// thread. The tests use linux uinput to emulate input devices.
+// NOTE: Interacting with the physical device while these tests are running may cause
+// the tests to fail.
+class InputReaderIntegrationTest : public testing::Test {
+protected:
+ sp<TestInputListener> mTestListener;
+ sp<FakeInputReaderPolicy> mFakePolicy;
+ sp<InputReaderInterface> mReader;
+
+ virtual void SetUp() override {
+ mFakePolicy = new FakeInputReaderPolicy();
+ mTestListener = new TestInputListener();
+
+ mReader = new InputReader(std::make_shared<EventHub>(), mFakePolicy, mTestListener);
+ ASSERT_EQ(mReader->start(), OK);
+
+ // Since this test is run on a real device, all the input devices connected
+ // to the test device will show up in mReader. We wait for those input devices to
+ // show up before beginning the tests.
+ ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
+ ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
+ }
+
+ virtual void TearDown() override {
+ ASSERT_EQ(mReader->stop(), OK);
+ mTestListener.clear();
+ mFakePolicy.clear();
+ }
+};
+
+TEST_F(InputReaderIntegrationTest, TestInvalidDevice) {
+ // An invalid input device that is only used for this test.
+ class InvalidUinputDevice : public UinputDevice {
+ public:
+ InvalidUinputDevice() : UinputDevice("Invalid Device") {}
+
+ private:
+ void configureDevice(int fd, uinput_user_dev* device) override {}
+ };
+
+ const size_t numDevices = mFakePolicy->getInputDevices().size();
+
+ // UinputDevice does not set any event or key bits, so InputReader should not
+ // consider it as a valid device.
+ std::unique_ptr<UinputDevice> invalidDevice = createUinputDevice<InvalidUinputDevice>();
+ ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesNotChanged());
+ ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasNotCalled());
+ ASSERT_EQ(numDevices, mFakePolicy->getInputDevices().size());
+
+ invalidDevice.reset();
+ ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesNotChanged());
+ ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasNotCalled());
+ ASSERT_EQ(numDevices, mFakePolicy->getInputDevices().size());
+}
+
+TEST_F(InputReaderIntegrationTest, AddNewDevice) {
+ const size_t initialNumDevices = mFakePolicy->getInputDevices().size();
+
+ std::unique_ptr<UinputHomeKey> keyboard = createUinputDevice<UinputHomeKey>();
+ ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
+ ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
+ ASSERT_EQ(initialNumDevices + 1, mFakePolicy->getInputDevices().size());
+
+ // Find the test device by its name.
+ std::vector<InputDeviceInfo> inputDevices;
+ mReader->getInputDevices(inputDevices);
+ InputDeviceInfo* keyboardInfo = nullptr;
+ const char* keyboardName = keyboard->getName();
+ for (unsigned int i = 0; i < initialNumDevices + 1; i++) {
+ if (!strcmp(inputDevices[i].getIdentifier().name.c_str(), keyboardName)) {
+ keyboardInfo = &inputDevices[i];
+ break;
+ }
+ }
+ ASSERT_NE(keyboardInfo, nullptr);
+ ASSERT_EQ(AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC, keyboardInfo->getKeyboardType());
+ ASSERT_EQ(AINPUT_SOURCE_KEYBOARD, keyboardInfo->getSources());
+ ASSERT_EQ(0U, keyboardInfo->getMotionRanges().size());
+
+ keyboard.reset();
+ ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
+ ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
+ ASSERT_EQ(initialNumDevices, mFakePolicy->getInputDevices().size());
+}
+
+TEST_F(InputReaderIntegrationTest, SendsEventsToInputListener) {
+ std::unique_ptr<UinputHomeKey> keyboard = createUinputDevice<UinputHomeKey>();
+ ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
+
+ NotifyConfigurationChangedArgs configChangedArgs;
+ ASSERT_NO_FATAL_FAILURE(
+ mTestListener->assertNotifyConfigurationChangedWasCalled(&configChangedArgs));
+ uint32_t prevSequenceNum = configChangedArgs.sequenceNum;
+ 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_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_LE(prevTimestamp, keyArgs.eventTime);
+}
// --- InputDeviceTest ---
class InputDeviceTest : public testing::Test {
@@ -1665,13 +1843,14 @@
static const int32_t DEVICE_GENERATION;
static const int32_t DEVICE_CONTROLLER_NUMBER;
static const uint32_t DEVICE_CLASSES;
+ static const int32_t EVENTHUB_ID;
std::shared_ptr<FakeEventHub> mFakeEventHub;
sp<FakeInputReaderPolicy> mFakePolicy;
sp<TestInputListener> mFakeListener;
FakeInputReaderContext* mFakeContext;
- InputDevice* mDevice;
+ std::shared_ptr<InputDevice> mDevice;
virtual void SetUp() override {
mFakeEventHub = std::make_unique<FakeEventHub>();
@@ -1679,17 +1858,16 @@
mFakeListener = new TestInputListener();
mFakeContext = new FakeInputReaderContext(mFakeEventHub, mFakePolicy, mFakeListener);
- mFakeEventHub->addDevice(DEVICE_ID, DEVICE_NAME, 0);
+ mFakeEventHub->addDevice(EVENTHUB_ID, DEVICE_NAME, 0);
InputDeviceIdentifier identifier;
identifier.name = DEVICE_NAME;
identifier.location = DEVICE_LOCATION;
- mDevice = new InputDevice(mFakeContext, DEVICE_ID, DEVICE_GENERATION,
- DEVICE_CONTROLLER_NUMBER, identifier, DEVICE_CLASSES);
+ mDevice = std::make_shared<InputDevice>(mFakeContext, DEVICE_ID, DEVICE_GENERATION,
+ identifier);
}
virtual void TearDown() override {
- delete mDevice;
-
+ mDevice = nullptr;
delete mFakeContext;
mFakeListener.clear();
mFakePolicy.clear();
@@ -1698,20 +1876,21 @@
const char* InputDeviceTest::DEVICE_NAME = "device";
const char* InputDeviceTest::DEVICE_LOCATION = "USB1";
-const int32_t InputDeviceTest::DEVICE_ID = 1;
+const int32_t InputDeviceTest::DEVICE_ID = END_RESERVED_ID + 1000;
const int32_t InputDeviceTest::DEVICE_GENERATION = 2;
const int32_t InputDeviceTest::DEVICE_CONTROLLER_NUMBER = 0;
const uint32_t InputDeviceTest::DEVICE_CLASSES = INPUT_DEVICE_CLASS_KEYBOARD
| INPUT_DEVICE_CLASS_TOUCH | INPUT_DEVICE_CLASS_JOYSTICK;
+const int32_t InputDeviceTest::EVENTHUB_ID = 1;
TEST_F(InputDeviceTest, ImmutableProperties) {
ASSERT_EQ(DEVICE_ID, mDevice->getId());
ASSERT_STREQ(DEVICE_NAME, mDevice->getName().c_str());
- ASSERT_EQ(DEVICE_CLASSES, mDevice->getClasses());
+ ASSERT_EQ(0U, mDevice->getClasses());
}
-TEST_F(InputDeviceTest, WhenDeviceCreated_EnabledIsTrue) {
- ASSERT_EQ(mDevice->isEnabled(), true);
+TEST_F(InputDeviceTest, WhenDeviceCreated_EnabledIsFalse) {
+ ASSERT_EQ(mDevice->isEnabled(), false);
}
TEST_F(InputDeviceTest, WhenNoMappersAreRegistered_DeviceIsIgnored) {
@@ -1758,9 +1937,10 @@
TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRequestsToMappers) {
// Configuration.
- mFakeEventHub->addConfigurationProperty(DEVICE_ID, String8("key"), String8("value"));
+ mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, String8("key"), String8("value"));
- FakeInputMapper& mapper1 = mDevice->addMapper<FakeInputMapper>(AINPUT_SOURCE_KEYBOARD);
+ FakeInputMapper& mapper1 =
+ mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, AINPUT_SOURCE_KEYBOARD);
mapper1.setKeyboardType(AINPUT_KEYBOARD_TYPE_ALPHABETIC);
mapper1.setMetaState(AMETA_ALT_ON);
mapper1.addSupportedKeyCode(AKEYCODE_A);
@@ -1771,7 +1951,8 @@
mapper1.setScanCodeState(3, AKEY_STATE_UP);
mapper1.setSwitchState(4, AKEY_STATE_DOWN);
- FakeInputMapper& mapper2 = mDevice->addMapper<FakeInputMapper>(AINPUT_SOURCE_TOUCHSCREEN);
+ FakeInputMapper& mapper2 =
+ mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, AINPUT_SOURCE_TOUCHSCREEN);
mapper2.setMetaState(AMETA_SHIFT_ON);
InputReaderConfiguration config;
@@ -1842,6 +2023,7 @@
// Event handling.
RawEvent event;
+ event.deviceId = EVENTHUB_ID;
mDevice->process(&event, 1);
ASSERT_NO_FATAL_FAILURE(mapper1.assertProcessWasCalled());
@@ -1852,7 +2034,7 @@
// 1. Device is disabled if the viewport corresponding to the associated display is not found
// 2. Device is disabled when setEnabled API is called
TEST_F(InputDeviceTest, Configure_AssignsDisplayPort) {
- mDevice->addMapper<FakeInputMapper>(AINPUT_SOURCE_TOUCHSCREEN);
+ mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, AINPUT_SOURCE_TOUCHSCREEN);
// First Configuration.
mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), 0);
@@ -1901,6 +2083,7 @@
static const int32_t DEVICE_GENERATION;
static const int32_t DEVICE_CONTROLLER_NUMBER;
static const uint32_t DEVICE_CLASSES;
+ static const int32_t EVENTHUB_ID;
std::shared_ptr<FakeEventHub> mFakeEventHub;
sp<FakeInputReaderPolicy> mFakePolicy;
@@ -1908,7 +2091,7 @@
FakeInputReaderContext* mFakeContext;
InputDevice* mDevice;
- virtual void SetUp() override {
+ virtual void SetUp(uint32_t classes) {
mFakeEventHub = std::make_unique<FakeEventHub>();
mFakePolicy = new FakeInputReaderPolicy();
mFakeListener = new TestInputListener();
@@ -1916,12 +2099,13 @@
InputDeviceIdentifier identifier;
identifier.name = DEVICE_NAME;
identifier.location = DEVICE_LOCATION;
- mDevice = new InputDevice(mFakeContext, DEVICE_ID, DEVICE_GENERATION,
- DEVICE_CONTROLLER_NUMBER, identifier, DEVICE_CLASSES);
+ mDevice = new InputDevice(mFakeContext, DEVICE_ID, DEVICE_GENERATION, identifier);
- mFakeEventHub->addDevice(mDevice->getId(), DEVICE_NAME, 0);
+ mFakeEventHub->addDevice(EVENTHUB_ID, DEVICE_NAME, classes);
}
+ virtual void SetUp() override { SetUp(DEVICE_CLASSES); }
+
virtual void TearDown() override {
delete mDevice;
delete mFakeContext;
@@ -1930,16 +2114,19 @@
}
void addConfigurationProperty(const char* key, const char* value) {
- mFakeEventHub->addConfigurationProperty(mDevice->getId(), String8(key), String8(value));
+ mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, String8(key), String8(value));
}
void configureDevice(uint32_t changes) {
+ if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
+ mFakeContext->updatePointerDisplay();
+ }
mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), changes);
}
template <class T, typename... Args>
T& addMapperAndConfigure(Args... args) {
- T& mapper = mDevice->addMapper<T>(args...);
+ T& mapper = mDevice->addMapper<T>(EVENTHUB_ID, args...);
configureDevice(0);
mDevice->reset(ARBITRARY_TIME);
return mapper;
@@ -1961,7 +2148,7 @@
int32_t value) {
RawEvent event;
event.when = when;
- event.deviceId = mapper.getDeviceId();
+ event.deviceId = mapper.getDeviceContext().getEventHubId();
event.type = type;
event.code = code;
event.value = value;
@@ -2006,11 +2193,11 @@
const char* InputMapperTest::DEVICE_NAME = "device";
const char* InputMapperTest::DEVICE_LOCATION = "USB1";
-const int32_t InputMapperTest::DEVICE_ID = 1;
+const int32_t InputMapperTest::DEVICE_ID = END_RESERVED_ID + 1000;
const int32_t InputMapperTest::DEVICE_GENERATION = 2;
const int32_t InputMapperTest::DEVICE_CONTROLLER_NUMBER = 0;
const uint32_t InputMapperTest::DEVICE_CLASSES = 0; // not needed for current tests
-
+const int32_t InputMapperTest::EVENTHUB_ID = 1;
// --- SwitchInputMapperTest ---
@@ -2027,10 +2214,10 @@
TEST_F(SwitchInputMapperTest, GetSwitchState) {
SwitchInputMapper& mapper = addMapperAndConfigure<SwitchInputMapper>();
- mFakeEventHub->setSwitchState(DEVICE_ID, SW_LID, 1);
+ mFakeEventHub->setSwitchState(EVENTHUB_ID, SW_LID, 1);
ASSERT_EQ(1, mapper.getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
- mFakeEventHub->setSwitchState(DEVICE_ID, SW_LID, 0);
+ mFakeEventHub->setSwitchState(EVENTHUB_ID, SW_LID, 0);
ASSERT_EQ(0, mapper.getSwitchState(AINPUT_SOURCE_ANY, SW_LID));
}
@@ -2104,8 +2291,8 @@
TEST_F(KeyboardInputMapperTest, Process_SimpleKeyPress) {
const int32_t USAGE_A = 0x070004;
const int32_t USAGE_UNKNOWN = 0x07ffff;
- mFakeEventHub->addKey(DEVICE_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
- mFakeEventHub->addKey(DEVICE_ID, 0, USAGE_A, AKEYCODE_A, POLICY_FLAG_WAKE);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
+ mFakeEventHub->addKey(EVENTHUB_ID, 0, USAGE_A, AKEYCODE_A, POLICY_FLAG_WAKE);
KeyboardInputMapper& mapper =
addMapperAndConfigure<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
@@ -2202,8 +2389,8 @@
}
TEST_F(KeyboardInputMapperTest, Process_ShouldUpdateMetaState) {
- mFakeEventHub->addKey(DEVICE_ID, KEY_LEFTSHIFT, 0, AKEYCODE_SHIFT_LEFT, 0);
- mFakeEventHub->addKey(DEVICE_ID, KEY_A, 0, AKEYCODE_A, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFTSHIFT, 0, AKEYCODE_SHIFT_LEFT, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
KeyboardInputMapper& mapper =
addMapperAndConfigure<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
@@ -2241,10 +2428,10 @@
}
TEST_F(KeyboardInputMapperTest, Process_WhenNotOrientationAware_ShouldNotRotateDPad) {
- mFakeEventHub->addKey(DEVICE_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
- mFakeEventHub->addKey(DEVICE_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
- mFakeEventHub->addKey(DEVICE_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
- mFakeEventHub->addKey(DEVICE_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
KeyboardInputMapper& mapper =
addMapperAndConfigure<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
@@ -2262,10 +2449,10 @@
}
TEST_F(KeyboardInputMapperTest, Process_WhenOrientationAware_ShouldRotateDPad) {
- mFakeEventHub->addKey(DEVICE_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
- mFakeEventHub->addKey(DEVICE_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
- mFakeEventHub->addKey(DEVICE_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
- mFakeEventHub->addKey(DEVICE_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
addConfigurationProperty("keyboard.orientationAware", "1");
KeyboardInputMapper& mapper =
@@ -2338,7 +2525,7 @@
TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_NotOrientationAware) {
// If the keyboard is not orientation aware,
// key events should not be associated with a specific display id
- mFakeEventHub->addKey(DEVICE_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
KeyboardInputMapper& mapper =
addMapperAndConfigure<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
@@ -2363,7 +2550,7 @@
TEST_F(KeyboardInputMapperTest, DisplayIdConfigurationChange_OrientationAware) {
// If the keyboard is orientation aware,
// key events should be associated with the internal viewport
- mFakeEventHub->addKey(DEVICE_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
addConfigurationProperty("keyboard.orientationAware", "1");
KeyboardInputMapper& mapper =
@@ -2398,10 +2585,10 @@
addMapperAndConfigure<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- mFakeEventHub->setKeyCodeState(DEVICE_ID, AKEYCODE_A, 1);
+ mFakeEventHub->setKeyCodeState(EVENTHUB_ID, AKEYCODE_A, 1);
ASSERT_EQ(1, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
- mFakeEventHub->setKeyCodeState(DEVICE_ID, AKEYCODE_A, 0);
+ mFakeEventHub->setKeyCodeState(EVENTHUB_ID, AKEYCODE_A, 0);
ASSERT_EQ(0, mapper.getKeyCodeState(AINPUT_SOURCE_ANY, AKEYCODE_A));
}
@@ -2410,10 +2597,10 @@
addMapperAndConfigure<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- mFakeEventHub->setScanCodeState(DEVICE_ID, KEY_A, 1);
+ mFakeEventHub->setScanCodeState(EVENTHUB_ID, KEY_A, 1);
ASSERT_EQ(1, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
- mFakeEventHub->setScanCodeState(DEVICE_ID, KEY_A, 0);
+ mFakeEventHub->setScanCodeState(EVENTHUB_ID, KEY_A, 0);
ASSERT_EQ(0, mapper.getScanCodeState(AINPUT_SOURCE_ANY, KEY_A));
}
@@ -2422,7 +2609,7 @@
addMapperAndConfigure<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
AINPUT_KEYBOARD_TYPE_ALPHABETIC);
- mFakeEventHub->addKey(DEVICE_ID, KEY_A, 0, AKEYCODE_A, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
const int32_t keyCodes[2] = { AKEYCODE_A, AKEYCODE_B };
uint8_t flags[2] = { 0, 0 };
@@ -2432,99 +2619,100 @@
}
TEST_F(KeyboardInputMapperTest, Process_LockedKeysShouldToggleMetaStateAndLeds) {
- mFakeEventHub->addLed(DEVICE_ID, LED_CAPSL, true /*initially on*/);
- mFakeEventHub->addLed(DEVICE_ID, LED_NUML, false /*initially off*/);
- mFakeEventHub->addLed(DEVICE_ID, LED_SCROLLL, false /*initially off*/);
- mFakeEventHub->addKey(DEVICE_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
- mFakeEventHub->addKey(DEVICE_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
- mFakeEventHub->addKey(DEVICE_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
+ mFakeEventHub->addLed(EVENTHUB_ID, LED_CAPSL, true /*initially on*/);
+ mFakeEventHub->addLed(EVENTHUB_ID, LED_NUML, false /*initially off*/);
+ mFakeEventHub->addLed(EVENTHUB_ID, LED_SCROLLL, false /*initially off*/);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_CAPSLOCK, 0, AKEYCODE_CAPS_LOCK, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_NUMLOCK, 0, AKEYCODE_NUM_LOCK, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_SCROLLLOCK, 0, AKEYCODE_SCROLL_LOCK, 0);
KeyboardInputMapper& mapper =
addMapperAndConfigure<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
AINPUT_KEYBOARD_TYPE_ALPHABETIC);
// Initialization should have turned all of the lights off.
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
+ ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
+ ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
+ ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
// Toggle caps lock on.
process(mapper, ARBITRARY_TIME, EV_KEY, KEY_CAPSLOCK, 1);
process(mapper, ARBITRARY_TIME, EV_KEY, KEY_CAPSLOCK, 0);
- ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
+ ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
+ ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
+ ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
ASSERT_EQ(AMETA_CAPS_LOCK_ON, mapper.getMetaState());
// Toggle num lock on.
process(mapper, ARBITRARY_TIME, EV_KEY, KEY_NUMLOCK, 1);
process(mapper, ARBITRARY_TIME, EV_KEY, KEY_NUMLOCK, 0);
- ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
- ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
+ ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
+ ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
+ ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
ASSERT_EQ(AMETA_CAPS_LOCK_ON | AMETA_NUM_LOCK_ON, mapper.getMetaState());
// Toggle caps lock off.
process(mapper, ARBITRARY_TIME, EV_KEY, KEY_CAPSLOCK, 1);
process(mapper, ARBITRARY_TIME, EV_KEY, KEY_CAPSLOCK, 0);
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
- ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
+ ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
+ ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
+ ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
ASSERT_EQ(AMETA_NUM_LOCK_ON, mapper.getMetaState());
// Toggle scroll lock on.
process(mapper, ARBITRARY_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
process(mapper, ARBITRARY_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
- ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
- ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
+ ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
+ ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
+ ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
ASSERT_EQ(AMETA_NUM_LOCK_ON | AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
// Toggle num lock off.
process(mapper, ARBITRARY_TIME, EV_KEY, KEY_NUMLOCK, 1);
process(mapper, ARBITRARY_TIME, EV_KEY, KEY_NUMLOCK, 0);
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
- ASSERT_TRUE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
+ ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
+ ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
+ ASSERT_TRUE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
ASSERT_EQ(AMETA_SCROLL_LOCK_ON, mapper.getMetaState());
// Toggle scroll lock off.
process(mapper, ARBITRARY_TIME, EV_KEY, KEY_SCROLLLOCK, 1);
process(mapper, ARBITRARY_TIME, EV_KEY, KEY_SCROLLLOCK, 0);
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_CAPSL));
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_NUML));
- ASSERT_FALSE(mFakeEventHub->getLedState(DEVICE_ID, LED_SCROLLL));
+ ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_CAPSL));
+ ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_NUML));
+ ASSERT_FALSE(mFakeEventHub->getLedState(EVENTHUB_ID, LED_SCROLLL));
ASSERT_EQ(AMETA_NONE, mapper.getMetaState());
}
TEST_F(KeyboardInputMapperTest, Configure_AssignsDisplayPort) {
// keyboard 1.
- mFakeEventHub->addKey(DEVICE_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
- mFakeEventHub->addKey(DEVICE_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
- mFakeEventHub->addKey(DEVICE_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
- mFakeEventHub->addKey(DEVICE_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
// keyboard 2.
const std::string USB2 = "USB2";
constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
+ constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
InputDeviceIdentifier identifier;
identifier.name = "KEYBOARD2";
identifier.location = USB2;
std::unique_ptr<InputDevice> device2 =
std::make_unique<InputDevice>(mFakeContext, SECOND_DEVICE_ID, DEVICE_GENERATION,
- DEVICE_CONTROLLER_NUMBER, identifier, DEVICE_CLASSES);
- mFakeEventHub->addDevice(SECOND_DEVICE_ID, DEVICE_NAME, 0 /*classes*/);
- mFakeEventHub->addKey(SECOND_DEVICE_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
- mFakeEventHub->addKey(SECOND_DEVICE_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
- mFakeEventHub->addKey(SECOND_DEVICE_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
- mFakeEventHub->addKey(SECOND_DEVICE_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
+ identifier);
+ mFakeEventHub->addDevice(SECOND_EVENTHUB_ID, DEVICE_NAME, 0 /*classes*/);
+ mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_UP, 0, AKEYCODE_DPAD_UP, 0);
+ mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_RIGHT, 0, AKEYCODE_DPAD_RIGHT, 0);
+ mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
+ mFakeEventHub->addKey(SECOND_EVENTHUB_ID, KEY_LEFT, 0, AKEYCODE_DPAD_LEFT, 0);
KeyboardInputMapper& mapper =
addMapperAndConfigure<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
AINPUT_KEYBOARD_TYPE_ALPHABETIC);
KeyboardInputMapper& mapper2 =
- device2->addMapper<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
+ device2->addMapper<KeyboardInputMapper>(SECOND_EVENTHUB_ID, AINPUT_SOURCE_KEYBOARD,
AINPUT_KEYBOARD_TYPE_ALPHABETIC);
device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), 0 /*changes*/);
device2->reset(ARBITRARY_TIME);
@@ -2576,14 +2764,23 @@
AKEYCODE_DPAD_LEFT, newDisplayId));
}
-TEST_F(KeyboardInputMapperTest, ExternalDevice_WakeBehavior) {
+// --- KeyboardInputMapperTest_ExternalDevice ---
+
+class KeyboardInputMapperTest_ExternalDevice : public InputMapperTest {
+protected:
+ virtual void SetUp() override {
+ InputMapperTest::SetUp(DEVICE_CLASSES | INPUT_DEVICE_CLASS_EXTERNAL);
+ }
+};
+
+TEST_F(KeyboardInputMapperTest_ExternalDevice, WakeBehavior) {
// For external devices, non-media keys will trigger wake on key down. Media keys need to be
// marked as WAKE in the keylayout file to trigger wake.
- mDevice->setExternal(true);
- mFakeEventHub->addKey(DEVICE_ID, KEY_HOME, 0, AKEYCODE_HOME, 0);
- mFakeEventHub->addKey(DEVICE_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, 0);
- mFakeEventHub->addKey(DEVICE_ID, KEY_PLAYPAUSE, 0, AKEYCODE_MEDIA_PLAY_PAUSE, POLICY_FLAG_WAKE);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAYPAUSE, 0, AKEYCODE_MEDIA_PLAY_PAUSE,
+ POLICY_FLAG_WAKE);
KeyboardInputMapper& mapper =
addMapperAndConfigure<KeyboardInputMapper>(AINPUT_SOURCE_KEYBOARD,
@@ -2615,13 +2812,12 @@
ASSERT_EQ(POLICY_FLAG_WAKE, args.policyFlags);
}
-TEST_F(KeyboardInputMapperTest, ExternalDevice_DoNotWakeByDefaultBehavior) {
+TEST_F(KeyboardInputMapperTest_ExternalDevice, DoNotWakeByDefaultBehavior) {
// Tv Remote key's wake behavior is prescribed by the keylayout file.
- mDevice->setExternal(true);
- mFakeEventHub->addKey(DEVICE_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
- mFakeEventHub->addKey(DEVICE_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
- mFakeEventHub->addKey(DEVICE_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, POLICY_FLAG_WAKE);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_DOWN, 0, AKEYCODE_DPAD_DOWN, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_PLAY, 0, AKEYCODE_MEDIA_PLAY, POLICY_FLAG_WAKE);
addConfigurationProperty("keyboard.doNotWakeByDefault", "1");
KeyboardInputMapper& mapper =
@@ -3563,10 +3759,10 @@
}
void TouchInputMapperTest::prepareVirtualKeys() {
- mFakeEventHub->addVirtualKeyDefinition(DEVICE_ID, VIRTUAL_KEYS[0]);
- mFakeEventHub->addVirtualKeyDefinition(DEVICE_ID, VIRTUAL_KEYS[1]);
- mFakeEventHub->addKey(DEVICE_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
- mFakeEventHub->addKey(DEVICE_ID, KEY_MENU, 0, AKEYCODE_MENU, POLICY_FLAG_WAKE);
+ mFakeEventHub->addVirtualKeyDefinition(EVENTHUB_ID, VIRTUAL_KEYS[0]);
+ mFakeEventHub->addVirtualKeyDefinition(EVENTHUB_ID, VIRTUAL_KEYS[1]);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_HOME, 0, AKEYCODE_HOME, POLICY_FLAG_WAKE);
+ mFakeEventHub->addKey(EVENTHUB_ID, KEY_MENU, 0, AKEYCODE_MENU, POLICY_FLAG_WAKE);
}
void TouchInputMapperTest::prepareLocationCalibration() {
@@ -3627,33 +3823,29 @@
};
void SingleTouchInputMapperTest::prepareButtons() {
- mFakeEventHub->addKey(DEVICE_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
}
void SingleTouchInputMapperTest::prepareAxes(int axes) {
if (axes & POSITION) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_X,
- RAW_X_MIN, RAW_X_MAX, 0, 0);
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_Y,
- RAW_Y_MIN, RAW_Y_MAX, 0, 0);
+ mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
+ mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
}
if (axes & PRESSURE) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_PRESSURE,
- RAW_PRESSURE_MIN, RAW_PRESSURE_MAX, 0, 0);
+ mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_PRESSURE, RAW_PRESSURE_MIN,
+ RAW_PRESSURE_MAX, 0, 0);
}
if (axes & TOOL) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_TOOL_WIDTH,
- RAW_TOOL_MIN, RAW_TOOL_MAX, 0, 0);
+ mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TOOL_WIDTH, RAW_TOOL_MIN, RAW_TOOL_MAX, 0,
+ 0);
}
if (axes & DISTANCE) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_DISTANCE,
- RAW_DISTANCE_MIN, RAW_DISTANCE_MAX, 0, 0);
+ mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_DISTANCE, RAW_DISTANCE_MIN,
+ RAW_DISTANCE_MAX, 0, 0);
}
if (axes & TILT) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_TILT_X,
- RAW_TILT_MIN, RAW_TILT_MAX, 0, 0);
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_TILT_Y,
- RAW_TILT_MIN, RAW_TILT_MAX, 0, 0);
+ mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TILT_X, RAW_TILT_MIN, RAW_TILT_MAX, 0, 0);
+ mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_TILT_Y, RAW_TILT_MIN, RAW_TILT_MAX, 0, 0);
}
}
@@ -3709,8 +3901,8 @@
}
TEST_F(SingleTouchInputMapperTest, GetSources_WhenDeviceTypeIsNotSpecifiedAndIsACursor_ReturnsTouchPad) {
- mFakeEventHub->addRelativeAxis(DEVICE_ID, REL_X);
- mFakeEventHub->addRelativeAxis(DEVICE_ID, REL_Y);
+ mFakeEventHub->addRelativeAxis(EVENTHUB_ID, REL_X);
+ mFakeEventHub->addRelativeAxis(EVENTHUB_ID, REL_Y);
prepareButtons();
prepareAxes(POSITION);
SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
@@ -4777,7 +4969,7 @@
prepareDisplay(DISPLAY_ORIENTATION_0);
prepareButtons();
prepareAxes(POSITION);
- mFakeEventHub->addKey(DEVICE_ID, BTN_TOOL_FINGER, 0, AKEYCODE_UNKNOWN, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_FINGER, 0, AKEYCODE_UNKNOWN, 0);
SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -4939,51 +5131,47 @@
void MultiTouchInputMapperTest::prepareAxes(int axes) {
if (axes & POSITION) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_POSITION_X,
- RAW_X_MIN, RAW_X_MAX, 0, 0);
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_POSITION_Y,
- RAW_Y_MIN, RAW_Y_MAX, 0, 0);
+ mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX, 0, 0);
+ mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX, 0, 0);
}
if (axes & TOUCH) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_TOUCH_MAJOR,
- RAW_TOUCH_MIN, RAW_TOUCH_MAX, 0, 0);
+ mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MAJOR, RAW_TOUCH_MIN,
+ RAW_TOUCH_MAX, 0, 0);
if (axes & MINOR) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_TOUCH_MINOR,
- RAW_TOUCH_MIN, RAW_TOUCH_MAX, 0, 0);
+ mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOUCH_MINOR, RAW_TOUCH_MIN,
+ RAW_TOUCH_MAX, 0, 0);
}
}
if (axes & TOOL) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_WIDTH_MAJOR,
- RAW_TOOL_MIN, RAW_TOOL_MAX, 0, 0);
+ mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MAJOR, RAW_TOOL_MIN, RAW_TOOL_MAX,
+ 0, 0);
if (axes & MINOR) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_WIDTH_MINOR,
- RAW_TOOL_MAX, RAW_TOOL_MAX, 0, 0);
+ mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_WIDTH_MINOR, RAW_TOOL_MAX,
+ RAW_TOOL_MAX, 0, 0);
}
}
if (axes & ORIENTATION) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_ORIENTATION,
- RAW_ORIENTATION_MIN, RAW_ORIENTATION_MAX, 0, 0);
+ mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_ORIENTATION, RAW_ORIENTATION_MIN,
+ RAW_ORIENTATION_MAX, 0, 0);
}
if (axes & PRESSURE) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_PRESSURE,
- RAW_PRESSURE_MIN, RAW_PRESSURE_MAX, 0, 0);
+ mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_PRESSURE, RAW_PRESSURE_MIN,
+ RAW_PRESSURE_MAX, 0, 0);
}
if (axes & DISTANCE) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_DISTANCE,
- RAW_DISTANCE_MIN, RAW_DISTANCE_MAX, 0, 0);
+ mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_DISTANCE, RAW_DISTANCE_MIN,
+ RAW_DISTANCE_MAX, 0, 0);
}
if (axes & ID) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_TRACKING_ID,
- RAW_ID_MIN, RAW_ID_MAX, 0, 0);
+ mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TRACKING_ID, RAW_ID_MIN, RAW_ID_MAX, 0,
+ 0);
}
if (axes & SLOT) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_SLOT,
- RAW_SLOT_MIN, RAW_SLOT_MAX, 0, 0);
- mFakeEventHub->setAbsoluteAxisValue(DEVICE_ID, ABS_MT_SLOT, 0);
+ mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_SLOT, RAW_SLOT_MIN, RAW_SLOT_MAX, 0, 0);
+ mFakeEventHub->setAbsoluteAxisValue(EVENTHUB_ID, ABS_MT_SLOT, 0);
}
if (axes & TOOL_TYPE) {
- mFakeEventHub->addAbsoluteAxis(DEVICE_ID, ABS_MT_TOOL_TYPE,
- 0, MT_TOOL_MAX, 0, 0);
+ mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_TOOL_TYPE, 0, MT_TOOL_MAX, 0, 0);
}
}
@@ -6272,7 +6460,7 @@
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(DISPLAY_ORIENTATION_0);
prepareAxes(POSITION | ID | SLOT);
- mFakeEventHub->addKey(DEVICE_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
+ mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOUCH, 0, AKEYCODE_UNKNOWN, 0);
MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
NotifyMotionArgs motionArgs;
@@ -6451,35 +6639,6 @@
ASSERT_EQ(DISPLAY_ID, args.displayId);
}
-/**
- * Expect fallback to internal viewport if device is external and external viewport is not present.
- */
-TEST_F(MultiTouchInputMapperTest, Viewports_Fallback) {
- prepareAxes(POSITION);
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- mDevice->setExternal(true);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
-
- ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
-
- NotifyMotionArgs motionArgs;
-
- // Expect the event to be sent to the internal viewport,
- // because an external viewport is not present.
- processPosition(mapper, 100, 100);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(ADISPLAY_ID_DEFAULT, motionArgs.displayId);
-
- // Expect the event to be sent to the external viewport if it is present.
- prepareSecondaryDisplay(ViewportType::VIEWPORT_EXTERNAL);
- processPosition(mapper, 100, 100);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
- ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId);
-}
-
TEST_F(MultiTouchInputMapperTest, Process_Pointer_ShouldHandleDisplayId) {
// Setup for second display.
sp<FakePointerController> fakePointerController = new FakePointerController();
@@ -6516,27 +6675,28 @@
// Create the second touch screen device, and enable multi fingers.
const std::string USB2 = "USB2";
constexpr int32_t SECOND_DEVICE_ID = DEVICE_ID + 1;
+ constexpr int32_t SECOND_EVENTHUB_ID = EVENTHUB_ID + 1;
InputDeviceIdentifier identifier;
identifier.name = "TOUCHSCREEN2";
identifier.location = USB2;
std::unique_ptr<InputDevice> device2 =
std::make_unique<InputDevice>(mFakeContext, SECOND_DEVICE_ID, DEVICE_GENERATION,
- DEVICE_CONTROLLER_NUMBER, identifier, DEVICE_CLASSES);
- mFakeEventHub->addDevice(SECOND_DEVICE_ID, DEVICE_NAME, 0 /*classes*/);
- mFakeEventHub->addAbsoluteAxis(SECOND_DEVICE_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX,
- 0 /*flat*/, 0 /*fuzz*/);
- mFakeEventHub->addAbsoluteAxis(SECOND_DEVICE_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX,
- 0 /*flat*/, 0 /*fuzz*/);
- mFakeEventHub->addAbsoluteAxis(SECOND_DEVICE_ID, ABS_MT_TRACKING_ID, RAW_ID_MIN, RAW_ID_MAX,
- 0 /*flat*/, 0 /*fuzz*/);
- mFakeEventHub->addAbsoluteAxis(SECOND_DEVICE_ID, ABS_MT_SLOT, RAW_SLOT_MIN, RAW_SLOT_MAX,
- 0 /*flat*/, 0 /*fuzz*/);
- mFakeEventHub->setAbsoluteAxisValue(SECOND_DEVICE_ID, ABS_MT_SLOT, 0 /*value*/);
- mFakeEventHub->addConfigurationProperty(SECOND_DEVICE_ID, String8("touch.deviceType"),
- String8("touchScreen"));
+ identifier);
+ mFakeEventHub->addDevice(SECOND_EVENTHUB_ID, DEVICE_NAME, 0 /*classes*/);
+ mFakeEventHub->addAbsoluteAxis(SECOND_EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX,
+ 0 /*flat*/, 0 /*fuzz*/);
+ mFakeEventHub->addAbsoluteAxis(SECOND_EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX,
+ 0 /*flat*/, 0 /*fuzz*/);
+ mFakeEventHub->addAbsoluteAxis(SECOND_EVENTHUB_ID, ABS_MT_TRACKING_ID, RAW_ID_MIN, RAW_ID_MAX,
+ 0 /*flat*/, 0 /*fuzz*/);
+ mFakeEventHub->addAbsoluteAxis(SECOND_EVENTHUB_ID, ABS_MT_SLOT, RAW_SLOT_MIN, RAW_SLOT_MAX,
+ 0 /*flat*/, 0 /*fuzz*/);
+ mFakeEventHub->setAbsoluteAxisValue(SECOND_EVENTHUB_ID, ABS_MT_SLOT, 0 /*value*/);
+ mFakeEventHub->addConfigurationProperty(SECOND_EVENTHUB_ID, String8("touch.deviceType"),
+ String8("touchScreen"));
// Setup the second touch screen device.
- MultiTouchInputMapper& mapper2 = device2->addMapper<MultiTouchInputMapper>();
+ MultiTouchInputMapper& mapper2 = device2->addMapper<MultiTouchInputMapper>(SECOND_EVENTHUB_ID);
device2->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), 0 /*changes*/);
device2->reset(ARBITRARY_TIME);
@@ -6597,7 +6757,7 @@
// Unrotated video frame
TouchVideoFrame frame(3, 2, {1, 2, 3, 4, 5, 6}, {1, 2});
std::vector<TouchVideoFrame> frames{frame};
- mFakeEventHub->setVideoFrames({{mDevice->getId(), frames}});
+ mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
processPosition(mapper, 100, 200);
processSync(mapper);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
@@ -6627,7 +6787,7 @@
clearViewports();
prepareDisplay(orientation);
std::vector<TouchVideoFrame> frames{frame};
- mFakeEventHub->setVideoFrames({{mDevice->getId(), frames}});
+ mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
processPosition(mapper, 100, 200);
processSync(mapper);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
@@ -6649,7 +6809,7 @@
NotifyMotionArgs motionArgs;
prepareDisplay(DISPLAY_ORIENTATION_90);
- mFakeEventHub->setVideoFrames({{mDevice->getId(), frames}});
+ mFakeEventHub->setVideoFrames({{EVENTHUB_ID, frames}});
processPosition(mapper, 100, 200);
processSync(mapper);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
@@ -6823,4 +6983,41 @@
ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
}
+// --- MultiTouchInputMapperTest_ExternalDevice ---
+
+class MultiTouchInputMapperTest_ExternalDevice : public MultiTouchInputMapperTest {
+protected:
+ virtual void SetUp() override {
+ InputMapperTest::SetUp(DEVICE_CLASSES | INPUT_DEVICE_CLASS_EXTERNAL);
+ }
+};
+
+/**
+ * Expect fallback to internal viewport if device is external and external viewport is not present.
+ */
+TEST_F(MultiTouchInputMapperTest_ExternalDevice, Viewports_Fallback) {
+ prepareAxes(POSITION);
+ addConfigurationProperty("touch.deviceType", "touchScreen");
+ prepareDisplay(DISPLAY_ORIENTATION_0);
+ MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
+
+ NotifyMotionArgs motionArgs;
+
+ // Expect the event to be sent to the internal viewport,
+ // because an external viewport is not present.
+ processPosition(mapper, 100, 100);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(ADISPLAY_ID_DEFAULT, motionArgs.displayId);
+
+ // Expect the event to be sent to the external viewport if it is present.
+ prepareSecondaryDisplay(ViewportType::VIEWPORT_EXTERNAL);
+ processPosition(mapper, 100, 100);
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId);
+}
+
} // namespace android
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/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
index 4a0d6ee..d3712d9 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
@@ -57,6 +57,9 @@
// Forces a color mode on the outputs being refreshed
ui::ColorMode forceOutputColorMode{ui::ColorMode::NATIVE};
+ // If true, GPU clocks will be increased when rendering blurs
+ bool blursAreExpensive{false};
+
// If true, the complete output geometry needs to be recomputed this frame
bool updatingOutputGeometryThisFrame{false};
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
index 9622e78..a5711a3 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
@@ -265,7 +265,8 @@
virtual void prepareFrame() = 0;
virtual void devOptRepaintFlash(const CompositionRefreshArgs&) = 0;
virtual void finishFrame(const CompositionRefreshArgs&) = 0;
- virtual std::optional<base::unique_fd> composeSurfaces(const Region&) = 0;
+ virtual std::optional<base::unique_fd> composeSurfaces(
+ const Region&, const compositionengine::CompositionRefreshArgs& refreshArgs) = 0;
virtual void postFramebuffer() = 0;
virtual void chooseCompositionStrategy() = 0;
virtual bool getSkipColorTransform() const = 0;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
index d41337c..6f25e63 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -83,7 +83,8 @@
void prepareFrame() override;
void devOptRepaintFlash(const CompositionRefreshArgs&) override;
void finishFrame(const CompositionRefreshArgs&) override;
- std::optional<base::unique_fd> composeSurfaces(const Region&) override;
+ std::optional<base::unique_fd> composeSurfaces(
+ const Region&, const compositionengine::CompositionRefreshArgs& refreshArgs) override;
void postFramebuffer() override;
void cacheClientCompositionRequests(uint32_t) override;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
index 346c2d1..4661c5d 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h
@@ -98,7 +98,10 @@
MOCK_METHOD1(finishFrame, void(const compositionengine::CompositionRefreshArgs&));
- MOCK_METHOD1(composeSurfaces, std::optional<base::unique_fd>(const Region&));
+ MOCK_METHOD2(composeSurfaces,
+ std::optional<base::unique_fd>(
+ const Region&,
+ const compositionengine::CompositionRefreshArgs& refreshArgs));
MOCK_CONST_METHOD0(getSkipColorTransform, bool());
MOCK_METHOD0(postFramebuffer, void());
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index e792f45..248933e 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -774,7 +774,7 @@
if (!dirtyRegion.isEmpty()) {
base::unique_fd readyFence;
// redraw the whole screen
- static_cast<void>(composeSurfaces(dirtyRegion));
+ static_cast<void>(composeSurfaces(dirtyRegion, refreshArgs));
mRenderSurface->queueBuffer(std::move(readyFence));
}
@@ -787,7 +787,7 @@
prepareFrame();
}
-void Output::finishFrame(const compositionengine::CompositionRefreshArgs&) {
+void Output::finishFrame(const compositionengine::CompositionRefreshArgs& refreshArgs) {
ATRACE_CALL();
ALOGV(__FUNCTION__);
@@ -797,7 +797,7 @@
// Repaint the framebuffer (if needed), getting the optional fence for when
// the composition completes.
- auto optReadyFence = composeSurfaces(Region::INVALID_REGION);
+ auto optReadyFence = composeSurfaces(Region::INVALID_REGION, refreshArgs);
if (!optReadyFence) {
return;
}
@@ -806,7 +806,8 @@
mRenderSurface->queueBuffer(std::move(*optReadyFence));
}
-std::optional<base::unique_fd> Output::composeSurfaces(const Region& debugRegion) {
+std::optional<base::unique_fd> Output::composeSurfaces(
+ const Region& debugRegion, const compositionengine::CompositionRefreshArgs& refreshArgs) {
ATRACE_CALL();
ALOGV(__FUNCTION__);
@@ -894,8 +895,10 @@
// or complex GPU shaders and it's expensive. We boost the GPU frequency so that
// GPU composition can finish in time. We must reset GPU frequency afterwards,
// because high frequency consumes extra battery.
+ const bool expensiveBlurs =
+ refreshArgs.blursAreExpensive && mLayerRequestingBackgroundBlur != nullptr;
const bool expensiveRenderingExpected =
- clientCompositionDisplay.outputDataspace == ui::Dataspace::DISPLAY_P3;
+ clientCompositionDisplay.outputDataspace == ui::Dataspace::DISPLAY_P3 || expensiveBlurs;
if (expensiveRenderingExpected) {
setExpensiveRenderingExpected(true);
}
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index be0e9e4..63bb459 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -2463,7 +2463,9 @@
// Sets up the helper functions called by the function under test to use
// mock implementations.
MOCK_CONST_METHOD1(getDirtyRegion, Region(bool));
- MOCK_METHOD1(composeSurfaces, std::optional<base::unique_fd>(const Region&));
+ MOCK_METHOD2(composeSurfaces,
+ std::optional<base::unique_fd>(
+ const Region&, const compositionengine::CompositionRefreshArgs&));
MOCK_METHOD0(postFramebuffer, void());
MOCK_METHOD0(prepareFrame, void());
};
@@ -2526,7 +2528,7 @@
InSequence seq;
EXPECT_CALL(mOutput, getDirtyRegion(false)).WillOnce(Return(kNotEmptyRegion));
- EXPECT_CALL(mOutput, composeSurfaces(RegionEq(kNotEmptyRegion)));
+ EXPECT_CALL(mOutput, composeSurfaces(RegionEq(kNotEmptyRegion), Ref(mRefreshArgs)));
EXPECT_CALL(*mRenderSurface, queueBuffer(_));
EXPECT_CALL(mOutput, postFramebuffer());
EXPECT_CALL(mOutput, prepareFrame());
@@ -2542,7 +2544,9 @@
struct OutputPartialMock : public OutputPartialMockBase {
// Sets up the helper functions called by the function under test to use
// mock implementations.
- MOCK_METHOD1(composeSurfaces, std::optional<base::unique_fd>(const Region&));
+ MOCK_METHOD2(composeSurfaces,
+ std::optional<base::unique_fd>(
+ const Region&, const compositionengine::CompositionRefreshArgs&));
MOCK_METHOD0(postFramebuffer, void());
};
@@ -2568,7 +2572,7 @@
mOutput.mState.isEnabled = true;
InSequence seq;
- EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION)));
+ EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION), _));
mOutput.finishFrame(mRefreshArgs);
}
@@ -2577,7 +2581,7 @@
mOutput.mState.isEnabled = true;
InSequence seq;
- EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION)))
+ EXPECT_CALL(mOutput, composeSurfaces(RegionEq(Region::INVALID_REGION), _))
.WillOnce(Return(ByMove(base::unique_fd())));
EXPECT_CALL(*mRenderSurface, queueBuffer(_));
@@ -2804,7 +2808,8 @@
struct ExecuteState : public CallOrderStateMachineHelper<TestType, ExecuteState> {
auto execute() {
- getInstance()->mReadyFence = getInstance()->mOutput.composeSurfaces(kDebugRegion);
+ getInstance()->mReadyFence =
+ getInstance()->mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
return nextState<FenceCheckState>();
}
};
@@ -2832,6 +2837,7 @@
static const mat4 kDefaultColorTransformMat;
static const Region kDebugRegion;
+ static const compositionengine::CompositionRefreshArgs kDefaultRefreshArgs;
static const HdrCapabilities kHdrCapabilities;
StrictMock<mock::CompositionEngine> mCompositionEngine;
@@ -2851,6 +2857,7 @@
const Rect OutputComposeSurfacesTest::kDefaultOutputSourceClip{1009, 1010, 1011, 1012};
const Rect OutputComposeSurfacesTest::kDefaultOutputDestinationClip{1013, 1014, 1015, 1016};
const mat4 OutputComposeSurfacesTest::kDefaultColorTransformMat{mat4() * 0.5f};
+const compositionengine::CompositionRefreshArgs OutputComposeSurfacesTest::kDefaultRefreshArgs;
const Region OutputComposeSurfacesTest::kDebugRegion{Rect{100, 101, 102, 103}};
const HdrCapabilities OutputComposeSurfacesTest::
kHdrCapabilities{{},
@@ -3193,7 +3200,7 @@
mLayer2.mLayerFEState.hasProtectedContent = true;
EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
- mOutput.composeSurfaces(kDebugRegion);
+ mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
}
TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifRenderEngineDoesNotSupportIt) {
@@ -3201,7 +3208,7 @@
mLayer2.mLayerFEState.hasProtectedContent = true;
EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
- mOutput.composeSurfaces(kDebugRegion);
+ mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
}
TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNoProtectedContentLayers) {
@@ -3213,7 +3220,7 @@
EXPECT_CALL(mRenderEngine, useProtectedContext(false));
EXPECT_CALL(*mRenderSurface, setProtected(false));
- mOutput.composeSurfaces(kDebugRegion);
+ mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
}
TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifNotEnabled) {
@@ -3233,7 +3240,7 @@
EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _)).WillOnce(Return(NO_ERROR));
- mOutput.composeSurfaces(kDebugRegion);
+ mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
}
TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledEverywhere) {
@@ -3243,7 +3250,7 @@
EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true));
EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(true));
- mOutput.composeSurfaces(kDebugRegion);
+ mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
}
TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifFailsToEnableInRenderEngine) {
@@ -3254,7 +3261,7 @@
EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(false));
EXPECT_CALL(mRenderEngine, useProtectedContext(true));
- mOutput.composeSurfaces(kDebugRegion);
+ mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
}
TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledInRenderEngine) {
@@ -3265,7 +3272,7 @@
EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(false));
EXPECT_CALL(*mRenderSurface, setProtected(true));
- mOutput.composeSurfaces(kDebugRegion);
+ mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
}
TEST_F(OutputComposeSurfacesTest_HandlesProtectedContent, ifAlreadyEnabledInRenderSurface) {
@@ -3276,7 +3283,7 @@
EXPECT_CALL(*mRenderSurface, isProtected).WillOnce(Return(true));
EXPECT_CALL(mRenderEngine, useProtectedContext(true));
- mOutput.composeSurfaces(kDebugRegion);
+ mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
}
struct OutputComposeSurfacesTest_SetsExpensiveRendering : public OutputComposeSurfacesTest {
@@ -3302,7 +3309,43 @@
EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true));
EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _)).WillOnce(Return(NO_ERROR));
- mOutput.composeSurfaces(kDebugRegion);
+ mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
+}
+
+struct OutputComposeSurfacesTest_SetsExpensiveRendering_ForBlur
+ : public OutputComposeSurfacesTest_SetsExpensiveRendering {
+ OutputComposeSurfacesTest_SetsExpensiveRendering_ForBlur() {
+ mLayer.layerFEState.backgroundBlurRadius = 10;
+ mOutput.editState().isEnabled = true;
+
+ EXPECT_CALL(mLayer.outputLayer, updateCompositionState(false, true));
+ EXPECT_CALL(mLayer.outputLayer, writeStateToHWC(false));
+ EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
+ .WillOnce(Return(std::vector<LayerFE::LayerSettings>{}));
+ EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _)).WillOnce(Return(NO_ERROR));
+ EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1u));
+ EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
+ .WillRepeatedly(Return(&mLayer.outputLayer));
+ }
+
+ NonInjectedLayer mLayer;
+ compositionengine::CompositionRefreshArgs mRefreshArgs;
+};
+
+TEST_F(OutputComposeSurfacesTest_SetsExpensiveRendering_ForBlur, IfBlursAreExpensive) {
+ mRefreshArgs.blursAreExpensive = true;
+ mOutput.updateAndWriteCompositionState(mRefreshArgs);
+
+ EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true));
+ mOutput.composeSurfaces(kDebugRegion, mRefreshArgs);
+}
+
+TEST_F(OutputComposeSurfacesTest_SetsExpensiveRendering_ForBlur, IfBlursAreNotExpensive) {
+ mRefreshArgs.blursAreExpensive = false;
+ mOutput.updateAndWriteCompositionState(mRefreshArgs);
+
+ EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true)).Times(0);
+ mOutput.composeSurfaces(kDebugRegion, mRefreshArgs);
}
/*
diff --git a/services/surfaceflinger/EffectLayer.cpp b/services/surfaceflinger/EffectLayer.cpp
index 9d45e33..44d4d75 100644
--- a/services/surfaceflinger/EffectLayer.cpp
+++ b/services/surfaceflinger/EffectLayer.cpp
@@ -69,6 +69,8 @@
// Set color for color fill settings.
layerSettings->source.solidColor = getColor().rgb;
results.push_back(*layerSettings);
+ } else if (hasBlur()) {
+ results.push_back(*layerSettings);
}
return results;
@@ -148,6 +150,10 @@
mDrawingState.color.b >= 0.0_hf;
}
+bool EffectLayer::hasBlur() const {
+ return getBackgroundBlurRadius() > 0;
+}
+
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/EffectLayer.h b/services/surfaceflinger/EffectLayer.h
index 33758b6..1dcb633 100644
--- a/services/surfaceflinger/EffectLayer.h
+++ b/services/surfaceflinger/EffectLayer.h
@@ -62,7 +62,9 @@
private:
// Returns true if there is a valid color to fill.
bool fillsColor() const;
- bool hasSomethingToDraw() const { return fillsColor() || drawShadows(); }
+ // Returns true if this layer has a blur value.
+ bool hasBlur() const;
+ bool hasSomethingToDraw() const { return fillsColor() || drawShadows() || hasBlur(); }
};
} // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 2acf084..ce0a8a1 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -363,11 +363,13 @@
property_get("ro.surface_flinger.supports_background_blur", value, "0");
bool supportsBlurs = atoi(value);
- property_get("debug.sf.disableBlurs", value, "0");
+ property_get("debug.sf.disable_blurs", value, "0");
bool disableBlurs = atoi(value);
mEnableBlurs = supportsBlurs && !disableBlurs;
ALOGI_IF(!mEnableBlurs, "Disabling blur effects. supported: %d, disabled: %d", supportsBlurs,
disableBlurs);
+ property_get("ro.sf.blurs_are_expensive", value, "0");
+ mBlursAreExpensive = atoi(value);
const size_t defaultListSize = MAX_LAYERS;
auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize));
@@ -1926,6 +1928,7 @@
refreshArgs.updatingOutputGeometryThisFrame = mVisibleRegionsDirty;
refreshArgs.updatingGeometryThisFrame = mGeometryInvalid || mVisibleRegionsDirty;
+ refreshArgs.blursAreExpensive = mBlursAreExpensive;
if (CC_UNLIKELY(mDrawingState.colorMatrixChanged)) {
refreshArgs.colorTransformMatrix = mDrawingState.colorMatrix;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index dcbb150..c79621b 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -1043,7 +1043,10 @@
const std::shared_ptr<TimeStats> mTimeStats;
const std::unique_ptr<FrameTracer> mFrameTracer;
bool mUseHwcVirtualDisplays = false;
+ // Disable blurs, for debugging
bool mEnableBlurs = false;
+ // If blurs are considered expensive and should require high GPU frequency.
+ bool mBlursAreExpensive = false;
std::atomic<uint32_t> mFrameMissedCount = 0;
std::atomic<uint32_t> mHwcFrameMissedCount = 0;
std::atomic<uint32_t> mGpuFrameMissedCount = 0;