Merge "(touch-mode-md 2/n) Add md touch mode support in InputDispatcher"
diff --git a/cmds/bugreportz/readme.md b/cmds/bugreportz/readme.md
index eb0d898..3606827 100644
--- a/cmds/bugreportz/readme.md
+++ b/cmds/bugreportz/readme.md
@@ -1,6 +1,6 @@
# bugreportz protocol
-`bugreportz` is used to generate a zippped bugreport whose path is passed back to `adb`, using
+`bugreportz` is used to generate a zipped bugreport whose path is passed back to `adb`, using
the simple protocol defined below.
# Version 1.1
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 0b69829..235c923 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -183,6 +183,7 @@
#define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
#define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
#define CGROUPFS_DIR "/sys/fs/cgroup"
+#define SDK_EXT_INFO "/apex/com.android.sdkext/bin/derive_sdk"
// TODO(narayan): Since this information has to be kept in sync
// with tombstoned, we should just put it in a common header.
@@ -766,7 +767,7 @@
}
void Dumpstate::PrintHeader() const {
- std::string build, fingerprint, radio, bootloader, network;
+ std::string build, fingerprint, radio, bootloader, network, sdkversion;
char date[80];
build = android::base::GetProperty("ro.build.display.id", "(unknown)");
@@ -774,6 +775,7 @@
radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
+ sdkversion = android::base::GetProperty("ro.build.version.sdk", "(unknown)");
strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
printf("========================================================\n");
@@ -791,9 +793,10 @@
if (module_metadata_version != 0) {
printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
}
- printf("SDK extension versions [r=%s s=%s]\n",
- android::base::GetProperty("build.version.extensions.r", "-").c_str(),
- android::base::GetProperty("build.version.extensions.s", "-").c_str());
+ printf("Android SDK version: %s\n", sdkversion.c_str());
+ printf("SDK extensions: ");
+ RunCommandToFd(STDOUT_FILENO, "", {SDK_EXT_INFO, "--header"},
+ CommandOptions::WithTimeout(1).Always().DropRoot().Build());
printf("Kernel: ");
DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
@@ -1026,7 +1029,7 @@
MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
return;
}
- RunCommandToFd(fd, "", {"incident", "-u"}, CommandOptions::WithTimeout(120).Build());
+ RunCommandToFd(fd, "", {"incident", "-u"}, CommandOptions::WithTimeout(20).Build());
bool empty = 0 == lseek(fd, 0, SEEK_END);
if (!empty) {
// Use a different name from "incident.proto"
@@ -1084,7 +1087,7 @@
return;
}
RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
- CommandOptions::WithTimeout(120).Build());
+ CommandOptions::WithTimeout(10).Build());
bool empty = 0 == lseek(fd, 0, SEEK_END);
if (!empty) {
ds.AddZipEntry("visible_windows.zip", path);
@@ -1890,6 +1893,9 @@
DumpFile("PSI memory", "/proc/pressure/memory");
DumpFile("PSI io", "/proc/pressure/io");
+ RunCommand("SDK EXTENSIONS", {SDK_EXT_INFO, "--dump"},
+ CommandOptions::WithTimeout(10).Always().DropRoot().Build());
+
if (dump_pool_) {
RETURN_IF_USER_DENIED_CONSENT();
WaitForTask(std::move(dump_traces));
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index 3cfe529..a99ccae 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -326,16 +326,41 @@
return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "linkToDeath failure");
}
+ auto it = mNameToService.find(name);
+ if (it != mNameToService.end()) {
+ const Service& existing = it->second;
+
+ // We could do better than this because if the other service dies, it
+ // may not have an entry here. However, this case is unlikely. We are
+ // only trying to detect when two different services are accidentally installed.
+
+ if (existing.ctx.uid != ctx.uid) {
+ LOG(WARNING) << "Service '" << name << "' originally registered from UID "
+ << existing.ctx.uid << " but it is now being registered from UID "
+ << ctx.uid << ". Multiple instances installed?";
+ }
+
+ if (existing.ctx.sid != ctx.sid) {
+ LOG(WARNING) << "Service '" << name << "' originally registered from SID "
+ << existing.ctx.sid << " but it is now being registered from SID "
+ << ctx.sid << ". Multiple instances installed?";
+ }
+
+ LOG(INFO) << "Service '" << name << "' originally registered from PID "
+ << existing.ctx.debugPid << " but it is being registered again from PID "
+ << ctx.debugPid
+ << ". Bad state? Late death notification? Multiple instances installed?";
+ }
+
// Overwrite the old service if it exists
- mNameToService[name] = Service {
- .binder = binder,
- .allowIsolated = allowIsolated,
- .dumpPriority = dumpPriority,
- .debugPid = ctx.debugPid,
+ mNameToService[name] = Service{
+ .binder = binder,
+ .allowIsolated = allowIsolated,
+ .dumpPriority = dumpPriority,
+ .ctx = ctx,
};
- auto it = mNameToRegistrationCallback.find(name);
- if (it != mNameToRegistrationCallback.end()) {
+ if (auto it = mNameToRegistrationCallback.find(name); it != mNameToRegistrationCallback.end()) {
for (const sp<IServiceCallback>& cb : it->second) {
mNameToService[name].guaranteeClient = true;
// permission checked in registerForNotifications
@@ -571,7 +596,7 @@
return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
}
- if (serviceIt->second.debugPid != IPCThreadState::self()->getCallingPid()) {
+ if (serviceIt->second.ctx.debugPid != IPCThreadState::self()->getCallingPid()) {
LOG(WARNING) << "Only a server can register for client callbacks (for " << name << ")";
return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION);
}
@@ -707,7 +732,7 @@
return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
}
- if (serviceIt->second.debugPid != IPCThreadState::self()->getCallingPid()) {
+ if (serviceIt->second.ctx.debugPid != IPCThreadState::self()->getCallingPid()) {
LOG(WARNING) << "Only a server can unregister itself (for " << name << ")";
return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION);
}
@@ -754,7 +779,7 @@
for (auto const& [name, service] : mNameToService) {
ServiceDebugInfo info;
info.name = name;
- info.debugPid = service.debugPid;
+ info.debugPid = service.ctx.debugPid;
outReturn->push_back(std::move(info));
}
@@ -762,4 +787,10 @@
return Status::ok();
}
+void ServiceManager::clear() {
+ mNameToService.clear();
+ mNameToRegistrationCallback.clear();
+ mNameToClientCallback.clear();
+}
+
} // namespace android
diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h
index 5e40319..07b79f8 100644
--- a/cmds/servicemanager/ServiceManager.h
+++ b/cmds/servicemanager/ServiceManager.h
@@ -58,6 +58,12 @@
void binderDied(const wp<IBinder>& who) override;
void handleClientCallbacks();
+ /**
+ * This API is added for debug purposes. It clears members which hold service and callback
+ * information.
+ */
+ void clear();
+
protected:
virtual void tryStartService(const std::string& name);
@@ -68,7 +74,7 @@
int32_t dumpPriority;
bool hasClients = false; // notifications sent on true -> false.
bool guaranteeClient = false; // forces the client check to true
- pid_t debugPid = 0; // the process in which this service runs
+ Access::CallingContext ctx; // process that originally registers this
// the number of clients of the service, including servicemanager itself
ssize_t getNodeStrongRefCount();
diff --git a/cmds/servicemanager/ServiceManagerFuzzer.cpp b/cmds/servicemanager/ServiceManagerFuzzer.cpp
index 39f8522..b76a6bd 100644
--- a/cmds/servicemanager/ServiceManagerFuzzer.cpp
+++ b/cmds/servicemanager/ServiceManagerFuzzer.cpp
@@ -29,6 +29,7 @@
auto accessPtr = std::make_unique<Access>();
auto serviceManager = sp<ServiceManager>::make(std::move(accessPtr));
fuzzService(serviceManager, FuzzedDataProvider(data, size));
+ serviceManager->clear();
return 0;
}
diff --git a/data/etc/android.software.credentials.xml b/data/etc/android.software.credentials.xml
new file mode 100644
index 0000000..234d144
--- /dev/null
+++ b/data/etc/android.software.credentials.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 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.
+-->
+
+<permissions>
+ <feature name="android.software.credentials" />
+</permissions>
diff --git a/data/etc/handheld_core_hardware.xml b/data/etc/handheld_core_hardware.xml
index 8fdd8d0..0833012 100644
--- a/data/etc/handheld_core_hardware.xml
+++ b/data/etc/handheld_core_hardware.xml
@@ -52,6 +52,7 @@
<feature name="android.software.print" />
<feature name="android.software.companion_device_setup" />
<feature name="android.software.autofill" />
+ <feature name="android.software.credentials" />
<feature name="android.software.cant_save_state" />
<feature name="android.software.secure_lock_screen" />
<feature name="android.software.window_magnification" />
diff --git a/data/etc/tablet_core_hardware.xml b/data/etc/tablet_core_hardware.xml
index 59d5b10..6af4d91 100644
--- a/data/etc/tablet_core_hardware.xml
+++ b/data/etc/tablet_core_hardware.xml
@@ -52,6 +52,7 @@
<feature name="android.software.print" />
<feature name="android.software.companion_device_setup" />
<feature name="android.software.autofill" />
+ <feature name="android.software.credentials" />
<feature name="android.software.cant_save_state" />
<feature name="android.software.secure_lock_screen" />
<feature name="android.software.window_magnification" />
diff --git a/include/android/input.h b/include/android/input.h
index 8cd9e95..7080386 100644
--- a/include/android/input.h
+++ b/include/android/input.h
@@ -840,6 +840,12 @@
* This classification type should be used to accelerate the long press behaviour.
*/
AMOTION_EVENT_CLASSIFICATION_DEEP_PRESS = 2,
+ /**
+ * Classification constant: touchpad two-finger swipe.
+ *
+ * The current event stream represents the user swiping with two fingers on a touchpad.
+ */
+ AMOTION_EVENT_CLASSIFICATION_TWO_FINGER_SWIPE = 3,
};
/**
diff --git a/include/android/keycodes.h b/include/android/keycodes.h
index 16a13d6..e5b5db2 100644
--- a/include/android/keycodes.h
+++ b/include/android/keycodes.h
@@ -818,6 +818,17 @@
/** Keyboard backlight Toggle key.
* Toggles the keyboard backlight on/off. */
AKEYCODE_KEYBOARD_BACKLIGHT_TOGGLE = 307,
+ /** The primary button on the barrel of a stylus.
+ * This is usually the button closest to the tip of the stylus. */
+ AKEYCODE_STYLUS_BUTTON_PRIMARY = 308,
+ /** The secondary button on the barrel of a stylus.
+ * This is usually the second button from the tip of the stylus. */
+ AKEYCODE_STYLUS_BUTTON_SECONDARY = 309,
+ /** The tertiary button on the barrel of a stylus.
+ * This is usually the third button from the tip of the stylus. */
+ AKEYCODE_STYLUS_BUTTON_TERTIARY = 310,
+ /** A button on the tail end of a stylus. */
+ AKEYCODE_STYLUS_BUTTON_TAIL = 311,
// NOTE: If you add a new keycode here you must also add it to several other files.
// Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
diff --git a/include/android/surface_control_jni.h b/include/android/surface_control_jni.h
new file mode 100644
index 0000000..67e3a9f
--- /dev/null
+++ b/include/android/surface_control_jni.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2022 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 NativeActivity Native Activity
+ * @{
+ */
+
+/**
+ * @file surface_control_jni.h
+ */
+
+#ifndef ANDROID_SURFACE_CONTROL_JNI_H
+#define ANDROID_SURFACE_CONTROL_JNI_H
+
+#include <jni.h>
+#include <sys/cdefs.h>
+
+#include <android/surface_control.h>
+
+__BEGIN_DECLS
+
+/**
+ * Return the ASurfaceControl wrapped by a Java SurfaceControl object.
+ *
+ * This method does not acquire any additional reference to the ASurfaceControl
+ * that is returned. To keep the ASurfaceControl alive after the Java
+ * SurfaceControl object is closed, explicitly or by the garbage collector, be
+ * sure to use ASurfaceControl_acquire() to acquire an additional reference.
+ *
+ * Available since API level 34.
+ */
+ASurfaceControl* _Nullable ASurfaceControl_fromSurfaceControl(JNIEnv* _Nonnull env,
+ jobject _Nonnull surfaceControlObj) __INTRODUCED_IN(__ANDROID_API_U__);
+
+/**
+ * Return the ASurfaceTransaction wrapped by a Java Transaction object.
+ *
+ * The returned ASurfaceTransaction is still owned by the Java Transaction object is only
+ * valid while the Java Transaction object is alive. In particular, the returned transaction
+ * must NOT be deleted with ASurfaceTransaction_delete.
+ * May return nullptr on error.
+ *
+ * Available since API level 34.
+ */
+ASurfaceTransaction* _Nullable ASurfaceTransaction_fromTransaction(JNIEnv* _Nonnull env,
+ jobject _Nonnull transactionObj) __INTRODUCED_IN(__ANDROID_API_U__);
+
+__END_DECLS
+
+#endif // ANDROID_SURFACE_CONTROL_JNI_H
+/** @} */
diff --git a/include/input/Input.h b/include/input/Input.h
index 2dd651e..172e5b4 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -289,6 +289,10 @@
* The current gesture likely represents a user intentionally exerting force on the touchscreen.
*/
DEEP_PRESS = AMOTION_EVENT_CLASSIFICATION_DEEP_PRESS,
+ /**
+ * The current gesture represents the user swiping with two fingers on a touchpad.
+ */
+ TWO_FINGER_SWIPE = AMOTION_EVENT_CLASSIFICATION_TWO_FINGER_SWIPE,
};
/**
diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h
index 415080d..0026e82 100644
--- a/include/input/InputDevice.h
+++ b/include/input/InputDevice.h
@@ -17,6 +17,7 @@
#pragma once
#include <android/sensor.h>
+#include <ftl/flags.h>
#include <input/Input.h>
#include <input/KeyCharacterMap.h>
#include <unordered_map>
@@ -105,12 +106,18 @@
};
enum class InputDeviceLightType : int32_t {
- MONO = 0,
+ INPUT = 0,
PLAYER_ID = 1,
- RGB = 2,
- MULTI_COLOR = 3,
+ KEYBOARD_BACKLIGHT = 2,
- ftl_last = MULTI_COLOR
+ ftl_last = KEYBOARD_BACKLIGHT
+};
+
+enum class InputDeviceLightCapability : uint32_t {
+ /** Capability to change brightness of the light */
+ BRIGHTNESS = 0x00000001,
+ /** Capability to change color of the light */
+ RGB = 0x00000002,
};
struct InputDeviceSensorInfo {
@@ -171,14 +178,17 @@
struct InputDeviceLightInfo {
explicit InputDeviceLightInfo(std::string name, int32_t id, InputDeviceLightType type,
+ ftl::Flags<InputDeviceLightCapability> capabilityFlags,
int32_t ordinal)
- : name(name), id(id), type(type), ordinal(ordinal) {}
+ : name(name), id(id), type(type), capabilityFlags(capabilityFlags), ordinal(ordinal) {}
// Name string of the light.
std::string name;
// Light id
int32_t id;
// Type of the light.
InputDeviceLightType type;
+ // Light capabilities.
+ ftl::Flags<InputDeviceLightCapability> capabilityFlags;
// Ordinal of the light
int32_t ordinal;
};
diff --git a/include/input/VelocityTracker.h b/include/input/VelocityTracker.h
index 4251f04..294879e 100644
--- a/include/input/VelocityTracker.h
+++ b/include/input/VelocityTracker.h
@@ -145,16 +145,6 @@
inline int32_t getActivePointerId() const { return mActivePointerId; }
private:
- // All axes supported for velocity tracking, mapped to their default strategies.
- // Although other strategies are available for testing and comparison purposes,
- // the default strategy is the one that applications will actually use. Be very careful
- // when adjusting the default strategy because it can dramatically affect
- // (often in a bad way) the user experience.
- static const std::map<int32_t, Strategy> DEFAULT_STRATEGY_BY_AXIS;
-
- // Axes specifying location on a 2D plane (i.e. X and Y).
- static const std::set<int32_t> PLANAR_AXES;
-
nsecs_t mLastEventTime;
BitSet32 mCurrentPointerIdBits;
int32_t mActivePointerId;
@@ -170,7 +160,12 @@
void configureStrategy(int32_t axis);
- static std::unique_ptr<VelocityTrackerStrategy> createStrategy(const Strategy strategy);
+ // Generates a VelocityTrackerStrategy instance for the given Strategy type.
+ // The `deltaValues` parameter indicates whether or not the created strategy should treat motion
+ // values as deltas (and not as absolute values). This the parameter is applicable only for
+ // strategies that support differential axes.
+ static std::unique_ptr<VelocityTrackerStrategy> createStrategy(const Strategy strategy,
+ bool deltaValues);
};
@@ -316,7 +311,7 @@
class ImpulseVelocityTrackerStrategy : public VelocityTrackerStrategy {
public:
- ImpulseVelocityTrackerStrategy();
+ ImpulseVelocityTrackerStrategy(bool deltaValues);
virtual ~ImpulseVelocityTrackerStrategy();
virtual void clearPointers(BitSet32 idBits);
@@ -341,6 +336,11 @@
inline float getPosition(uint32_t id) const { return positions[idBits.getIndexOfBit(id)]; }
};
+ // Whether or not the input movement values for the strategy come in the form of delta values.
+ // If the input values are not deltas, the strategy needs to calculate deltas as part of its
+ // velocity calculation.
+ const bool mDeltaValues;
+
size_t mIndex;
Movement mMovements[HISTORY_SIZE];
};
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 5db3eef..05db774 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -380,6 +380,13 @@
if (Status status = realGetService(name, &out); !status.isOk()) {
ALOGW("Failed to getService in waitForService for %s: %s", name.c_str(),
status.toString8().c_str());
+ if (0 == ProcessState::self()->getThreadPoolMaxTotalThreadCount()) {
+ ALOGW("Got service, but may be racey because we could not wait efficiently for it. "
+ "Threadpool has 0 guaranteed threads. "
+ "Is the threadpool configured properly? "
+ "See ProcessState::startThreadPool and "
+ "ProcessState::setThreadPoolMaxThreadCount.");
+ }
return nullptr;
}
if (out != nullptr) return out;
@@ -410,7 +417,9 @@
if (waiter->mBinder != nullptr) return waiter->mBinder;
}
- ALOGW("Waited one second for %s (is service started? are binder threads started and available?)", name.c_str());
+ ALOGW("Waited one second for %s (is service started? Number of threads started in the "
+ "threadpool: %zu. Are binder threads started and available?)",
+ name.c_str(), ProcessState::self()->getThreadPoolMaxTotalThreadCount());
// Handle race condition for lazy services. Here is what can happen:
// - the service dies (not processed by init yet).
diff --git a/libs/binder/RpcTrusty.cpp b/libs/binder/RpcTrusty.cpp
index ea49eef..3b53b05 100644
--- a/libs/binder/RpcTrusty.cpp
+++ b/libs/binder/RpcTrusty.cpp
@@ -26,8 +26,12 @@
using android::base::unique_fd;
-sp<IBinder> RpcTrustyConnect(const char* device, const char* port) {
+sp<RpcSession> RpcTrustyConnectWithSessionInitializer(
+ const char* device, const char* port,
+ std::function<void(sp<RpcSession>&)> sessionInitializer) {
auto session = RpcSession::make(RpcTransportCtxFactoryTipcAndroid::make());
+ // using the callback to initialize the session
+ sessionInitializer(session);
auto request = [=] {
int tipcFd = tipc_connect(device, port);
if (tipcFd < 0) {
@@ -40,6 +44,11 @@
LOG(ERROR) << "Failed to set up Trusty client. Error: " << statusToString(status).c_str();
return nullptr;
}
+ return session;
+}
+
+sp<IBinder> RpcTrustyConnect(const char* device, const char* port) {
+ auto session = RpcTrustyConnectWithSessionInitializer(device, port, [](auto) {});
return session->getRootObject();
}
diff --git a/libs/binder/include_trusty/binder/RpcTrusty.h b/libs/binder/include_trusty/binder/RpcTrusty.h
index f124e0c..b034b9b 100644
--- a/libs/binder/include_trusty/binder/RpcTrusty.h
+++ b/libs/binder/include_trusty/binder/RpcTrusty.h
@@ -22,4 +22,8 @@
sp<IBinder> RpcTrustyConnect(const char* device, const char* port);
+sp<RpcSession> RpcTrustyConnectWithSessionInitializer(
+ const char* device, const char* port,
+ std::function<void(sp<RpcSession>&)> sessionInitializer);
+
} // namespace android
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 33d28e6..8ae7537 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -182,4 +182,8 @@
name: "libbinder_ndk",
symbol_file: "libbinder_ndk.map.txt",
first_version: "29",
+ export_header_libs: [
+ "libbinder_ndk_headers",
+ "libbinder_ndk_helper_headers",
+ ],
}
diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp
index 0ec6183..a135796 100644
--- a/libs/binder/rust/Android.bp
+++ b/libs/binder/rust/Android.bp
@@ -30,6 +30,7 @@
apex_available: [
"//apex_available:platform",
"com.android.compos",
+ "com.android.rkpd",
"com.android.uwb",
"com.android.virt",
],
@@ -80,6 +81,7 @@
apex_available: [
"//apex_available:platform",
"com.android.compos",
+ "com.android.rkpd",
"com.android.uwb",
"com.android.virt",
],
@@ -138,6 +140,7 @@
apex_available: [
"//apex_available:platform",
"com.android.compos",
+ "com.android.rkpd",
"com.android.uwb",
"com.android.virt",
],
diff --git a/libs/binder/rust/rpcbinder/Android.bp b/libs/binder/rust/rpcbinder/Android.bp
index f169390..5ebc27f 100644
--- a/libs/binder/rust/rpcbinder/Android.bp
+++ b/libs/binder/rust/rpcbinder/Android.bp
@@ -16,7 +16,7 @@
],
rustlibs: [
"libbinder_ndk_sys",
- "libbinder_rpc_unstable_bindgen",
+ "libbinder_rpc_unstable_bindgen_sys",
"libbinder_rs",
"libdowncast_rs",
"liblibc",
@@ -29,6 +29,35 @@
min_sdk_version: "Tiramisu",
}
+// Build a separate rust_library rather than depending directly on libbinder_rpc_unstable_bindgen,
+// to work around the fact that rust_bindgen targets only produce rlibs and not dylibs, which would
+// result in duplicate conflicting versions of libbinder_ndk_sys. This will hopefully be fixed in
+// the build system, at which point we can delete this target and go back to using
+// libbinder_rpc_unstable_bindgen directly.
+rust_library {
+ name: "libbinder_rpc_unstable_bindgen_sys",
+ crate_name: "binder_rpc_unstable_bindgen",
+ srcs: [
+ ":libbinder_rpc_unstable_bindgen",
+ ],
+ visibility: [":__subpackages__"],
+ rustlibs: [
+ "libbinder_ndk_sys",
+ ],
+ shared_libs: [
+ "libbinder_rpc_unstable",
+ "libutils",
+ ],
+ apex_available: [
+ "com.android.compos",
+ "com.android.uwb",
+ "com.android.virt",
+ ],
+ min_sdk_version: "Tiramisu",
+ lints: "none",
+ clippy_lints: "none",
+}
+
// TODO(b/184872979): remove once the RPC Binder API is stabilised.
rust_bindgen {
name: "libbinder_rpc_unstable_bindgen",
@@ -36,6 +65,15 @@
crate_name: "binder_rpc_unstable_bindgen",
visibility: [":__subpackages__"],
source_stem: "bindings",
+ bindgen_flags: [
+ "--blocklist-type",
+ "AIBinder",
+ "--raw-line",
+ "use binder_ndk_sys::AIBinder;",
+ ],
+ rustlibs: [
+ "libbinder_ndk_sys",
+ ],
shared_libs: [
"libbinder_rpc_unstable",
"libutils",
@@ -52,6 +90,9 @@
name: "libbinder_rpc_unstable_bindgen_test",
srcs: [":libbinder_rpc_unstable_bindgen"],
crate_name: "binder_rpc_unstable_bindgen",
+ rustlibs: [
+ "libbinder_ndk_sys",
+ ],
test_suites: ["general-tests"],
auto_gen_config: true,
clippy_lints: "none",
diff --git a/libs/binder/rust/rpcbinder/src/client.rs b/libs/binder/rust/rpcbinder/src/client.rs
index dfc6f06..743800b 100644
--- a/libs/binder/rust/rpcbinder/src/client.rs
+++ b/libs/binder/rust/rpcbinder/src/client.rs
@@ -14,10 +14,7 @@
* limitations under the License.
*/
-use binder::{
- unstable_api::{new_spibinder, AIBinder},
- FromIBinder, SpIBinder, StatusCode, Strong,
-};
+use binder::{unstable_api::new_spibinder, FromIBinder, SpIBinder, StatusCode, Strong};
use std::os::{
raw::{c_int, c_void},
unix::io::RawFd,
@@ -27,7 +24,7 @@
pub fn get_vsock_rpc_service(cid: u32, port: u32) -> Option<SpIBinder> {
// SAFETY: AIBinder returned by RpcClient has correct reference count, and the ownership can
// safely be taken by new_spibinder.
- unsafe { new_spibinder(binder_rpc_unstable_bindgen::RpcClient(cid, port) as *mut AIBinder) }
+ unsafe { new_spibinder(binder_rpc_unstable_bindgen::RpcClient(cid, port)) }
}
/// Connects to an RPC Binder server for a particular interface over vsock.
@@ -54,7 +51,7 @@
new_spibinder(binder_rpc_unstable_bindgen::RpcPreconnectedClient(
Some(request_fd_wrapper),
param,
- ) as *mut AIBinder)
+ ))
}
}
diff --git a/libs/binder/rust/rpcbinder/src/server.rs b/libs/binder/rust/rpcbinder/src/server.rs
index d98a439..aeb23c6 100644
--- a/libs/binder/rust/rpcbinder/src/server.rs
+++ b/libs/binder/rust/rpcbinder/src/server.rs
@@ -14,7 +14,10 @@
* limitations under the License.
*/
-use binder::{unstable_api::AsNative, SpIBinder};
+use binder::{
+ unstable_api::{AIBinder, AsNative},
+ SpIBinder,
+};
use std::{os::raw, ptr::null_mut};
/// Runs a binder RPC server, serving the supplied binder service implementation on the given vsock
@@ -44,7 +47,7 @@
F: FnOnce(),
{
fn run_server(&mut self, mut service: SpIBinder, port: u32) -> bool {
- let service = service.as_native_mut() as *mut binder_rpc_unstable_bindgen::AIBinder;
+ let service = service.as_native_mut();
let param = self.as_void_ptr();
// SAFETY: Service ownership is transferring to the server and won't be valid afterward.
@@ -106,10 +109,7 @@
}
}
-unsafe extern "C" fn factory_wrapper(
- cid: u32,
- context: *mut raw::c_void,
-) -> *mut binder_rpc_unstable_bindgen::AIBinder {
+unsafe extern "C" fn factory_wrapper(cid: u32, context: *mut raw::c_void) -> *mut AIBinder {
// SAFETY: `context` was created from an `&mut RpcServerFactoryRef` by
// `run_rpc_server_with_factory`, and we are still within the lifetime of the value it is
// pointing to.
@@ -117,7 +117,7 @@
let factory = factory_ptr.as_mut().unwrap();
if let Some(mut service) = factory(cid) {
- service.as_native_mut() as *mut binder_rpc_unstable_bindgen::AIBinder
+ service.as_native_mut()
} else {
null_mut()
}
diff --git a/libs/binder/rust/src/native.rs b/libs/binder/rust/src/native.rs
index 3a6dadd..dee05d0 100644
--- a/libs/binder/rust/src/native.rs
+++ b/libs/binder/rust/src/native.rs
@@ -296,7 +296,7 @@
/// Must be called with a valid pointer to a `T` object. After this call,
/// the pointer will be invalid and should not be dereferenced.
unsafe extern "C" fn on_destroy(object: *mut c_void) {
- Box::from_raw(object as *mut T);
+ drop(Box::from_raw(object as *mut T));
}
/// Called whenever a new, local `AIBinder` object is needed of a specific
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 21b0354..9a6d4df 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -85,6 +85,11 @@
return base::StringPrintf("unexpected state %d", wstatus);
}
+static void debugBacktrace(pid_t pid) {
+ std::cerr << "TAKING BACKTRACE FOR PID " << pid << std::endl;
+ system((std::string("debuggerd -b ") + std::to_string(pid)).c_str());
+}
+
class Process {
public:
Process(Process&&) = default;
@@ -125,6 +130,8 @@
// Kill the process. Avoid if possible. Shutdown gracefully via an RPC instead.
void terminate() { kill(mPid, SIGTERM); }
+ pid_t getPid() { return mPid; }
+
private:
std::function<void(int wstatus)> mCustomExitStatusCheck;
pid_t mPid = 0;
@@ -173,7 +180,9 @@
wp<RpcSession> weakSession = session;
session = nullptr;
- EXPECT_EQ(nullptr, weakSession.promote()) << "Leaked session";
+
+ EXPECT_EQ(nullptr, weakSession.promote())
+ << (debugBacktrace(host.getPid()), debugBacktrace(getpid()), "Leaked session");
}
}
};
diff --git a/libs/binderthreadstate/test.cpp b/libs/binderthreadstate/test.cpp
index 2f73137..df1f35d 100644
--- a/libs/binderthreadstate/test.cpp
+++ b/libs/binderthreadstate/test.cpp
@@ -73,6 +73,15 @@
CHECK(ret.isOk()) << ret;
}
+static std::string getStackPointerDebugInfo() {
+ const void* hwbinderSp = android::hardware::IPCThreadState::self()->getServingStackPointer();
+ const void* binderSp = android::IPCThreadState::self()->getServingStackPointer();
+
+ std::stringstream ss;
+ ss << "(hwbinder sp: " << hwbinderSp << " binder sp: " << binderSp << ")";
+ return ss.str();
+}
+
static inline std::ostream& operator<<(std::ostream& o, const BinderCallType& s) {
return o << static_cast<std::underlying_type_t<BinderCallType>>(s);
}
@@ -88,17 +97,21 @@
return android::hardware::Status::ok();
}
Return<void> call(int32_t idx) {
+ bool doCallHidl = thisId == kP1Id && idx % 4 < 2;
+
LOG(INFO) << "HidlServer CALL " << thisId << " to " << otherId << " at idx: " << idx
- << " with tid: " << gettid();
- CHECK_EQ(BinderCallType::HWBINDER, getCurrentServingCall());
+ << " with tid: " << gettid() << " calling " << (doCallHidl ? "HIDL" : "AIDL");
+ CHECK_EQ(BinderCallType::HWBINDER, getCurrentServingCall())
+ << " before call " << getStackPointerDebugInfo();
if (idx > 0) {
- if (thisId == kP1Id && idx % 4 < 2) {
+ if (doCallHidl) {
callHidl(otherId, idx - 1);
} else {
callAidl(otherId, idx - 1);
}
}
- CHECK_EQ(BinderCallType::HWBINDER, getCurrentServingCall());
+ CHECK_EQ(BinderCallType::HWBINDER, getCurrentServingCall())
+ << " after call " << getStackPointerDebugInfo();
return android::hardware::Status::ok();
}
};
@@ -113,17 +126,20 @@
return Status::ok();
}
Status call(int32_t idx) {
+ bool doCallHidl = thisId == kP2Id && idx % 4 < 2;
LOG(INFO) << "AidlServer CALL " << thisId << " to " << otherId << " at idx: " << idx
- << " with tid: " << gettid();
- CHECK_EQ(BinderCallType::BINDER, getCurrentServingCall());
+ << " with tid: " << gettid() << " calling " << (doCallHidl ? "HIDL" : "AIDL");
+ CHECK_EQ(BinderCallType::BINDER, getCurrentServingCall())
+ << " before call " << getStackPointerDebugInfo();
if (idx > 0) {
- if (thisId == kP2Id && idx % 4 < 2) {
+ if (doCallHidl) {
callHidl(otherId, idx - 1);
} else {
callAidl(otherId, idx - 1);
}
}
- CHECK_EQ(BinderCallType::BINDER, getCurrentServingCall());
+ CHECK_EQ(BinderCallType::BINDER, getCurrentServingCall())
+ << " after call " << getStackPointerDebugInfo();
return Status::ok();
}
};
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 751721e..72bd1fb 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -627,12 +627,11 @@
SurfaceComposerClient::Transaction::Transaction(const Transaction& other)
: mId(other.mId),
- mForceSynchronous(other.mForceSynchronous),
mTransactionNestCount(other.mTransactionNestCount),
mAnimation(other.mAnimation),
mEarlyWakeupStart(other.mEarlyWakeupStart),
mEarlyWakeupEnd(other.mEarlyWakeupEnd),
- mContainsBuffer(other.mContainsBuffer),
+ mMayContainBuffer(other.mMayContainBuffer),
mDesiredPresentTime(other.mDesiredPresentTime),
mIsAutoTimestamp(other.mIsAutoTimestamp),
mFrameTimelineInfo(other.mFrameTimelineInfo),
@@ -662,12 +661,10 @@
status_t SurfaceComposerClient::Transaction::readFromParcel(const Parcel* parcel) {
const uint64_t transactionId = parcel->readUint64();
- const uint32_t forceSynchronous = parcel->readUint32();
const uint32_t transactionNestCount = parcel->readUint32();
const bool animation = parcel->readBool();
const bool earlyWakeupStart = parcel->readBool();
const bool earlyWakeupEnd = parcel->readBool();
- const bool containsBuffer = parcel->readBool();
const int64_t desiredPresentTime = parcel->readInt64();
const bool isAutoTimestamp = parcel->readBool();
FrameTimelineInfo frameTimelineInfo;
@@ -740,12 +737,10 @@
// Parsing was successful. Update the object.
mId = transactionId;
- mForceSynchronous = forceSynchronous;
mTransactionNestCount = transactionNestCount;
mAnimation = animation;
mEarlyWakeupStart = earlyWakeupStart;
mEarlyWakeupEnd = earlyWakeupEnd;
- mContainsBuffer = containsBuffer;
mDesiredPresentTime = desiredPresentTime;
mIsAutoTimestamp = isAutoTimestamp;
mFrameTimelineInfo = frameTimelineInfo;
@@ -772,12 +767,10 @@
const_cast<SurfaceComposerClient::Transaction*>(this)->cacheBuffers();
parcel->writeUint64(mId);
- parcel->writeUint32(mForceSynchronous);
parcel->writeUint32(mTransactionNestCount);
parcel->writeBool(mAnimation);
parcel->writeBool(mEarlyWakeupStart);
parcel->writeBool(mEarlyWakeupEnd);
- parcel->writeBool(mContainsBuffer);
parcel->writeInt64(mDesiredPresentTime);
parcel->writeBool(mIsAutoTimestamp);
mFrameTimelineInfo.writeToParcel(parcel);
@@ -876,7 +869,7 @@
mInputWindowCommands.merge(other.mInputWindowCommands);
- mContainsBuffer |= other.mContainsBuffer;
+ mMayContainBuffer |= other.mMayContainBuffer;
mEarlyWakeupStart = mEarlyWakeupStart || other.mEarlyWakeupStart;
mEarlyWakeupEnd = mEarlyWakeupEnd || other.mEarlyWakeupEnd;
mApplyToken = other.mApplyToken;
@@ -892,8 +885,7 @@
mDisplayStates.clear();
mListenerCallbacks.clear();
mInputWindowCommands.clear();
- mContainsBuffer = false;
- mForceSynchronous = 0;
+ mMayContainBuffer = false;
mTransactionNestCount = 0;
mAnimation = false;
mEarlyWakeupStart = false;
@@ -915,12 +907,13 @@
uncacheBuffer.token = BufferCache::getInstance().getToken();
uncacheBuffer.id = cacheId;
- sf->setTransactionState(FrameTimelineInfo{}, {}, {}, 0, Transaction::getDefaultApplyToken(), {},
- systemTime(), true, uncacheBuffer, false, {}, generateId());
+ sf->setTransactionState(FrameTimelineInfo{}, {}, {}, ISurfaceComposer::eOneWay,
+ Transaction::getDefaultApplyToken(), {}, systemTime(), true,
+ uncacheBuffer, false, {}, generateId());
}
void SurfaceComposerClient::Transaction::cacheBuffers() {
- if (!mContainsBuffer) {
+ if (!mMayContainBuffer) {
return;
}
@@ -1005,27 +998,25 @@
Vector<DisplayState> displayStates;
uint32_t flags = 0;
- mForceSynchronous |= synchronous;
-
for (auto const& kv : mComposerStates){
composerStates.add(kv.second);
}
displayStates = std::move(mDisplayStates);
- if (mForceSynchronous) {
+ if (synchronous) {
flags |= ISurfaceComposer::eSynchronous;
}
if (mAnimation) {
flags |= ISurfaceComposer::eAnimation;
}
if (oneWay) {
- if (mForceSynchronous) {
- ALOGE("Transaction attempted to set synchronous and one way at the same time"
- " this is an invalid request. Synchronous will win for safety");
- } else {
- flags |= ISurfaceComposer::eOneWay;
- }
+ if (synchronous) {
+ ALOGE("Transaction attempted to set synchronous and one way at the same time"
+ " this is an invalid request. Synchronous will win for safety");
+ } else {
+ flags |= ISurfaceComposer::eOneWay;
+ }
}
// If both mEarlyWakeupStart and mEarlyWakeupEnd are set
@@ -1464,7 +1455,6 @@
s->what &= ~layer_state_t::eBufferChanged;
s->bufferData = nullptr;
- mContainsBuffer = false;
return bufferData;
}
@@ -1495,7 +1485,6 @@
if (buffer == nullptr) {
s->what &= ~layer_state_t::eBufferChanged;
s->bufferData = nullptr;
- mContainsBuffer = false;
return *this;
}
@@ -1530,7 +1519,7 @@
const std::vector<SurfaceControlStats>&) {},
nullptr);
- mContainsBuffer = true;
+ mMayContainBuffer = true;
return *this;
}
@@ -2025,7 +2014,6 @@
s.layerStackSpaceRect = layerStackRect;
s.orientedDisplaySpaceRect = displayRect;
s.what |= DisplayState::eDisplayProjectionChanged;
- mForceSynchronous = true; // TODO: do we actually still need this?
}
void SurfaceComposerClient::Transaction::setDisplaySize(const sp<IBinder>& token, uint32_t width, uint32_t height) {
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 3c7b162..c8927ad 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -133,7 +133,7 @@
eLayerOpaque = 0x02, // SURFACE_OPAQUE
eLayerSkipScreenshot = 0x40, // SKIP_SCREENSHOT
eLayerSecure = 0x80, // SECURE
- // Queue up BufferStateLayer buffers instead of dropping the oldest buffer when this flag is
+ // Queue up layer buffers instead of dropping the oldest buffer when this flag is
// set. This blocks the client until all the buffers have been presented. If the buffers
// have presentation timestamps, then we may drop buffers.
eEnableBackpressure = 0x100, // ENABLE_BACKPRESSURE
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 8c47ebc..61d4714 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -403,14 +403,15 @@
uint64_t mId;
- uint32_t mForceSynchronous = 0;
uint32_t mTransactionNestCount = 0;
bool mAnimation = false;
bool mEarlyWakeupStart = false;
bool mEarlyWakeupEnd = false;
- // Indicates that the Transaction contains a buffer that should be cached
- bool mContainsBuffer = false;
+ // Indicates that the Transaction may contain buffers that should be cached. The reason this
+ // is only a guess is that buffers can be removed before cache is called. This is only a
+ // hint that at some point a buffer was added to this transaction before apply was called.
+ bool mMayContainBuffer = false;
// mDesiredPresentTime is the time in nanoseconds that the client would like the transaction
// to be presented. When it is not possible to present at exactly that time, it will be
diff --git a/libs/input/Input.cpp b/libs/input/Input.cpp
index 2b7483d..579b28e 100644
--- a/libs/input/Input.cpp
+++ b/libs/input/Input.cpp
@@ -87,6 +87,8 @@
return "AMBIGUOUS_GESTURE";
case MotionClassification::DEEP_PRESS:
return "DEEP_PRESS";
+ case MotionClassification::TWO_FINGER_SWIPE:
+ return "TWO_FINGER_SWIPE";
}
}
diff --git a/libs/input/InputEventLabels.cpp b/libs/input/InputEventLabels.cpp
index 5990ee0..163a2fe 100644
--- a/libs/input/InputEventLabels.cpp
+++ b/libs/input/InputEventLabels.cpp
@@ -23,6 +23,8 @@
namespace android {
+// clang-format off
+
// NOTE: If you add a new keycode here you must also add it to several other files.
// Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
#define KEYCODES_SEQUENCE \
@@ -333,7 +335,11 @@
DEFINE_KEYCODE(DEMO_APP_4), \
DEFINE_KEYCODE(KEYBOARD_BACKLIGHT_DOWN), \
DEFINE_KEYCODE(KEYBOARD_BACKLIGHT_UP), \
- DEFINE_KEYCODE(KEYBOARD_BACKLIGHT_TOGGLE)
+ DEFINE_KEYCODE(KEYBOARD_BACKLIGHT_TOGGLE), \
+ DEFINE_KEYCODE(STYLUS_BUTTON_PRIMARY), \
+ DEFINE_KEYCODE(STYLUS_BUTTON_SECONDARY), \
+ DEFINE_KEYCODE(STYLUS_BUTTON_TERTIARY), \
+ DEFINE_KEYCODE(STYLUS_BUTTON_TAIL)
// NOTE: If you add a new axis here you must also add it to several other files.
// Refer to frameworks/base/core/java/android/view/MotionEvent.java for the full list.
@@ -387,7 +393,6 @@
DEFINE_AXIS(GENERIC_15), \
DEFINE_AXIS(GENERIC_16)
-
// NOTE: If you add new LEDs here, you must also add them to Input.h
#define LEDS_SEQUENCE \
DEFINE_LED(NUM_LOCK), \
@@ -412,6 +417,8 @@
DEFINE_FLAG(GESTURE), \
DEFINE_FLAG(WAKE)
+// clang-format on
+
// --- InputEventLookup ---
const std::unordered_map<std::string, int> InputEventLookup::KEYCODES = {KEYCODES_SEQUENCE};
diff --git a/libs/input/VelocityTracker.cpp b/libs/input/VelocityTracker.cpp
index 527a75b..4a4f734 100644
--- a/libs/input/VelocityTracker.cpp
+++ b/libs/input/VelocityTracker.cpp
@@ -55,6 +55,22 @@
// Nanoseconds per milliseconds.
static const nsecs_t NANOS_PER_MS = 1000000;
+// All axes supported for velocity tracking, mapped to their default strategies.
+// Although other strategies are available for testing and comparison purposes,
+// the default strategy is the one that applications will actually use. Be very careful
+// when adjusting the default strategy because it can dramatically affect
+// (often in a bad way) the user experience.
+static const std::map<int32_t, VelocityTracker::Strategy> DEFAULT_STRATEGY_BY_AXIS =
+ {{AMOTION_EVENT_AXIS_X, VelocityTracker::Strategy::LSQ2},
+ {AMOTION_EVENT_AXIS_Y, VelocityTracker::Strategy::LSQ2},
+ {AMOTION_EVENT_AXIS_SCROLL, VelocityTracker::Strategy::IMPULSE}};
+
+// Axes specifying location on a 2D plane (i.e. X and Y).
+static const std::set<int32_t> PLANAR_AXES = {AMOTION_EVENT_AXIS_X, AMOTION_EVENT_AXIS_Y};
+
+// Axes whose motion values are differential values (i.e. deltas).
+static const std::set<int32_t> DIFFERENTIAL_AXES = {AMOTION_EVENT_AXIS_SCROLL};
+
// Threshold for determining that a pointer has stopped moving.
// Some input devices do not send ACTION_MOVE events in the case where a pointer has
// stopped. We need to detect this case so that we can accurately predict the
@@ -125,12 +141,6 @@
// --- VelocityTracker ---
-const std::map<int32_t, VelocityTracker::Strategy> VelocityTracker::DEFAULT_STRATEGY_BY_AXIS =
- {{AMOTION_EVENT_AXIS_X, VelocityTracker::Strategy::LSQ2},
- {AMOTION_EVENT_AXIS_Y, VelocityTracker::Strategy::LSQ2}};
-
-const std::set<int32_t> VelocityTracker::PLANAR_AXES = {AMOTION_EVENT_AXIS_X, AMOTION_EVENT_AXIS_Y};
-
VelocityTracker::VelocityTracker(const Strategy strategy)
: mLastEventTime(0),
mCurrentPointerIdBits(0),
@@ -141,11 +151,14 @@
}
void VelocityTracker::configureStrategy(int32_t axis) {
+ const bool isDifferentialAxis = DIFFERENTIAL_AXES.find(axis) != DIFFERENTIAL_AXES.end();
+
std::unique_ptr<VelocityTrackerStrategy> createdStrategy;
if (mOverrideStrategy != VelocityTracker::Strategy::DEFAULT) {
- createdStrategy = createStrategy(mOverrideStrategy);
+ createdStrategy = createStrategy(mOverrideStrategy, isDifferentialAxis /* deltaValues */);
} else {
- createdStrategy = createStrategy(VelocityTracker::DEFAULT_STRATEGY_BY_AXIS.at(axis));
+ createdStrategy = createStrategy(DEFAULT_STRATEGY_BY_AXIS.at(axis),
+ isDifferentialAxis /* deltaValues */);
}
LOG_ALWAYS_FATAL_IF(createdStrategy == nullptr,
@@ -154,11 +167,11 @@
}
std::unique_ptr<VelocityTrackerStrategy> VelocityTracker::createStrategy(
- VelocityTracker::Strategy strategy) {
+ VelocityTracker::Strategy strategy, bool deltaValues) {
switch (strategy) {
case VelocityTracker::Strategy::IMPULSE:
ALOGI_IF(DEBUG_STRATEGY, "Initializing impulse strategy");
- return std::make_unique<ImpulseVelocityTrackerStrategy>();
+ return std::make_unique<ImpulseVelocityTrackerStrategy>(deltaValues);
case VelocityTracker::Strategy::LSQ1:
return std::make_unique<LeastSquaresVelocityTrackerStrategy>(1);
@@ -283,9 +296,7 @@
case AMOTION_EVENT_ACTION_HOVER_ENTER:
// Clear all pointers on down before adding the new movement.
clear();
- for (int32_t axis : PLANAR_AXES) {
- axesToProcess.insert(axis);
- }
+ axesToProcess.insert(PLANAR_AXES.begin(), PLANAR_AXES.end());
break;
case AMOTION_EVENT_ACTION_POINTER_DOWN: {
// Start a new movement trace for a pointer that just went down.
@@ -294,16 +305,12 @@
BitSet32 downIdBits;
downIdBits.markBit(event->getPointerId(event->getActionIndex()));
clearPointers(downIdBits);
- for (int32_t axis : PLANAR_AXES) {
- axesToProcess.insert(axis);
- }
+ axesToProcess.insert(PLANAR_AXES.begin(), PLANAR_AXES.end());
break;
}
case AMOTION_EVENT_ACTION_MOVE:
case AMOTION_EVENT_ACTION_HOVER_MOVE:
- for (int32_t axis : PLANAR_AXES) {
- axesToProcess.insert(axis);
- }
+ axesToProcess.insert(PLANAR_AXES.begin(), PLANAR_AXES.end());
break;
case AMOTION_EVENT_ACTION_POINTER_UP:
case AMOTION_EVENT_ACTION_UP: {
@@ -328,6 +335,9 @@
// before adding the movement.
return;
}
+ case AMOTION_EVENT_ACTION_SCROLL:
+ axesToProcess.insert(AMOTION_EVENT_AXIS_SCROLL);
+ break;
default:
// Ignore all other actions.
return;
@@ -1004,7 +1014,8 @@
// --- ImpulseVelocityTrackerStrategy ---
-ImpulseVelocityTrackerStrategy::ImpulseVelocityTrackerStrategy() : mIndex(0) {}
+ImpulseVelocityTrackerStrategy::ImpulseVelocityTrackerStrategy(bool deltaValues)
+ : mDeltaValues(deltaValues), mIndex(0) {}
ImpulseVelocityTrackerStrategy::~ImpulseVelocityTrackerStrategy() {
}
@@ -1112,7 +1123,8 @@
return (work < 0 ? -1.0 : 1.0) * sqrtf(fabsf(work)) * sqrt2;
}
-static float calculateImpulseVelocity(const nsecs_t* t, const float* x, size_t count) {
+static float calculateImpulseVelocity(const nsecs_t* t, const float* x, size_t count,
+ bool deltaValues) {
// The input should be in reversed time order (most recent sample at index i=0)
// t[i] is in nanoseconds, but due to FP arithmetic, convert to seconds inside this function
static constexpr float SECONDS_PER_NANO = 1E-9;
@@ -1123,12 +1135,26 @@
if (t[1] > t[0]) { // Algorithm will still work, but not perfectly
ALOGE("Samples provided to calculateImpulseVelocity in the wrong order");
}
+
+ // If the data values are delta values, we do not have to calculate deltas here.
+ // We can use the delta values directly, along with the calculated time deltas.
+ // Since the data value input is in reversed time order:
+ // [a] for non-delta inputs, instantenous velocity = (x[i] - x[i-1])/(t[i] - t[i-1])
+ // [b] for delta inputs, instantenous velocity = -x[i-1]/(t[i] - t[i - 1])
+ // e.g., let the non-delta values are: V = [2, 3, 7], the equivalent deltas are D = [2, 1, 4].
+ // Since the input is in reversed time order, the input values for this function would be
+ // V'=[7, 3, 2] and D'=[4, 1, 2] for the non-delta and delta values, respectively.
+ //
+ // The equivalent of {(V'[2] - V'[1]) = 2 - 3 = -1} would be {-D'[1] = -1}
+ // Similarly, the equivalent of {(V'[1] - V'[0]) = 3 - 7 = -4} would be {-D'[0] = -4}
+
if (count == 2) { // if 2 points, basic linear calculation
if (t[1] == t[0]) {
ALOGE("Events have identical time stamps t=%" PRId64 ", setting velocity = 0", t[0]);
return 0;
}
- return (x[1] - x[0]) / (SECONDS_PER_NANO * (t[1] - t[0]));
+ const float deltaX = deltaValues ? -x[0] : x[1] - x[0];
+ return deltaX / (SECONDS_PER_NANO * (t[1] - t[0]));
}
// Guaranteed to have at least 3 points here
float work = 0;
@@ -1138,7 +1164,8 @@
continue;
}
float vprev = kineticEnergyToVelocity(work); // v[i-1]
- float vcurr = (x[i] - x[i-1]) / (SECONDS_PER_NANO * (t[i] - t[i-1])); // v[i]
+ const float deltaX = deltaValues ? -x[i-1] : x[i] - x[i-1];
+ float vcurr = deltaX / (SECONDS_PER_NANO * (t[i] - t[i-1])); // v[i]
work += (vcurr - vprev) * fabsf(vcurr);
if (i == count - 1) {
work *= 0.5; // initial condition, case 2) above
@@ -1177,7 +1204,7 @@
return false; // no data
}
outEstimator->coeff[0] = 0;
- outEstimator->coeff[1] = calculateImpulseVelocity(time, positions, m);
+ outEstimator->coeff[1] = calculateImpulseVelocity(time, positions, m, mDeltaValues);
outEstimator->coeff[2] = 0;
outEstimator->time = newestMovement.eventTime;
diff --git a/libs/input/tests/VelocityTracker_test.cpp b/libs/input/tests/VelocityTracker_test.cpp
index 0b7def3..8b00b5c 100644
--- a/libs/input/tests/VelocityTracker_test.cpp
+++ b/libs/input/tests/VelocityTracker_test.cpp
@@ -87,7 +87,7 @@
}
};
-struct MotionEventEntry {
+struct PlanarMotionEventEntry {
std::chrono::nanoseconds eventTime;
std::vector<Position> positions;
};
@@ -136,15 +136,43 @@
return AMOTION_EVENT_ACTION_MOVE;
}
-static std::vector<MotionEvent> createMotionEventStream(
- const std::vector<MotionEventEntry>& motions) {
+static std::vector<MotionEvent> createAxisScrollMotionEventStream(
+ const std::vector<std::pair<std::chrono::nanoseconds, float>>& motions) {
+ std::vector<MotionEvent> events;
+ for (const auto& [timeStamp, value] : motions) {
+ EXPECT_TRUE(!isnan(value)) << "The entry at pointerId must be valid";
+
+ PointerCoords coords[1];
+ coords[0].setAxisValue(AMOTION_EVENT_AXIS_SCROLL, value);
+
+ PointerProperties properties[1];
+ properties[0].id = DEFAULT_POINTER_ID;
+
+ MotionEvent event;
+ ui::Transform identityTransform;
+ event.initialize(InputEvent::nextId(), 5 /*deviceId*/, AINPUT_SOURCE_ROTARY_ENCODER,
+ ADISPLAY_ID_NONE, INVALID_HMAC, AMOTION_EVENT_ACTION_SCROLL,
+ 0 /*actionButton*/, 0 /*flags*/, AMOTION_EVENT_EDGE_FLAG_NONE, AMETA_NONE,
+ 0 /*buttonState*/, MotionClassification::NONE, identityTransform,
+ 0 /*xPrecision*/, 0 /*yPrecision*/, AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform, 0 /*downTime*/,
+ timeStamp.count(), 1 /*pointerCount*/, properties, coords);
+
+ events.emplace_back(event);
+ }
+
+ return events;
+}
+
+static std::vector<MotionEvent> createTouchMotionEventStream(
+ const std::vector<PlanarMotionEventEntry>& motions) {
if (motions.empty()) {
ADD_FAILURE() << "Need at least 1 sample to create a MotionEvent. Received empty vector.";
}
std::vector<MotionEvent> events;
for (size_t i = 0; i < motions.size(); i++) {
- const MotionEventEntry& entry = motions[i];
+ const PlanarMotionEventEntry& entry = motions[i];
BitSet32 pointers = getValidPointers(entry.positions);
const uint32_t pointerCount = pointers.count();
@@ -155,8 +183,8 @@
} else if ((i == motions.size() - 1) && pointerCount == 1) {
action = AMOTION_EVENT_ACTION_UP;
} else {
- const MotionEventEntry& previousEntry = motions[i-1];
- const MotionEventEntry& nextEntry = motions[i+1];
+ const PlanarMotionEventEntry& previousEntry = motions[i-1];
+ const PlanarMotionEventEntry& nextEntry = motions[i+1];
action = resolveAction(previousEntry.positions, entry.positions, nextEntry.positions);
}
@@ -196,11 +224,12 @@
}
static void computeAndCheckVelocity(const VelocityTracker::Strategy strategy,
- const std::vector<MotionEventEntry>& motions, int32_t axis,
- float targetVelocity, uint32_t pointerId = DEFAULT_POINTER_ID) {
+ const std::vector<PlanarMotionEventEntry>& motions,
+ int32_t axis, float targetVelocity,
+ uint32_t pointerId = DEFAULT_POINTER_ID) {
VelocityTracker vt(strategy);
- std::vector<MotionEvent> events = createMotionEventStream(motions);
+ std::vector<MotionEvent> events = createTouchMotionEventStream(motions);
for (MotionEvent event : events) {
vt.addMovement(&event);
}
@@ -208,10 +237,33 @@
checkVelocity(vt.getVelocity(axis, pointerId).value_or(0), targetVelocity);
}
-static void computeAndCheckQuadraticEstimate(const std::vector<MotionEventEntry>& motions,
- const std::array<float, 3>& coefficients) {
+static void computeAndCheckAxisScrollVelocity(
+ const VelocityTracker::Strategy strategy,
+ const std::vector<std::pair<std::chrono::nanoseconds, float>>& motions,
+ std::optional<float> targetVelocity) {
+ VelocityTracker vt(strategy);
+
+ std::vector<MotionEvent> events = createAxisScrollMotionEventStream(motions);
+ for (const MotionEvent& event : events) {
+ vt.addMovement(&event);
+ }
+
+ std::optional<float> velocity = vt.getVelocity(AMOTION_EVENT_AXIS_SCROLL, DEFAULT_POINTER_ID);
+ if (velocity && !targetVelocity) {
+ FAIL() << "Expected no velocity, but found " << *velocity;
+ }
+ if (!velocity && targetVelocity) {
+ FAIL() << "Expected velocity, but found no velocity";
+ }
+ if (velocity) {
+ checkVelocity(*velocity, *targetVelocity);
+ }
+}
+
+static void computeAndCheckQuadraticEstimate(const std::vector<PlanarMotionEventEntry>& motions,
+ const std::array<float, 3>& coefficients) {
VelocityTracker vt(VelocityTracker::Strategy::LSQ2);
- std::vector<MotionEvent> events = createMotionEventStream(motions);
+ std::vector<MotionEvent> events = createTouchMotionEventStream(motions);
for (MotionEvent event : events) {
vt.addMovement(&event);
}
@@ -269,7 +321,7 @@
}
TEST_F(VelocityTrackerTest, TestGetComputedVelocity) {
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{235089067457000ns, {{528.00, 0}}}, {235089084684000ns, {{527.00, 0}}},
{235089093349000ns, {{527.00, 0}}}, {235089095677625ns, {{527.00, 0}}},
{235089101859000ns, {{527.00, 0}}}, {235089110378000ns, {{528.00, 0}}},
@@ -281,7 +333,7 @@
{235089162955851ns, {{560.66, 0}}}, // ACTION_UP
};
VelocityTracker vt(VelocityTracker::Strategy::IMPULSE);
- std::vector<MotionEvent> events = createMotionEventStream(motions);
+ std::vector<MotionEvent> events = createTouchMotionEventStream(motions);
for (const MotionEvent& event : events) {
vt.addMovement(&event);
}
@@ -333,7 +385,7 @@
// Same coordinate is reported 2 times in a row
// It is difficult to determine the correct answer here, but at least the direction
// of the reported velocity should be positive.
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{0ms, {{273, 0}}},
{12585us, {{293, 0}}},
{14730us, {{293, 0}}},
@@ -345,7 +397,7 @@
TEST_F(VelocityTrackerTest, ThreePointsZeroVelocityTest) {
// Same coordinate is reported 3 times in a row
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{0ms, {{293, 0}}},
{6132us, {{293, 0}}},
{11283us, {{293, 0}}},
@@ -357,7 +409,7 @@
TEST_F(VelocityTrackerTest, ThreePointsLinearVelocityTest) {
// Fixed velocity at 5 points per 10 milliseconds
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{0ms, {{0, 0}}}, {10ms, {{5, 0}}}, {20ms, {{10, 0}}}, {20ms, {{10, 0}}}, // ACTION_UP
};
computeAndCheckVelocity(VelocityTracker::Strategy::IMPULSE, motions, AMOTION_EVENT_AXIS_X, 500);
@@ -381,7 +433,7 @@
// --------------- Recorded by hand on swordfish ---------------------------------------------------
TEST_F(VelocityTrackerTest, SwordfishFlingDown) {
// Recording of a fling on Swordfish that could cause a fling in the wrong direction
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{ 0ms, {{271, 96}} },
{ 16071042ns, {{269.786346, 106.922775}} },
{ 35648403ns, {{267.983063, 156.660034}} },
@@ -416,7 +468,7 @@
TEST_F(VelocityTrackerTest, SailfishFlingUpSlow1) {
// Sailfish - fling up - slow - 1
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{ 235089067457000ns, {{528.00, 983.00}} },
{ 235089084684000ns, {{527.00, 981.00}} },
{ 235089093349000ns, {{527.00, 977.00}} },
@@ -448,7 +500,7 @@
TEST_F(VelocityTrackerTest, SailfishFlingUpSlow2) {
// Sailfish - fling up - slow - 2
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{ 235110560704000ns, {{522.00, 1107.00}} },
{ 235110575764000ns, {{522.00, 1107.00}} },
{ 235110584385000ns, {{522.00, 1107.00}} },
@@ -477,7 +529,7 @@
TEST_F(VelocityTrackerTest, SailfishFlingUpSlow3) {
// Sailfish - fling up - slow - 3
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{ 792536237000ns, {{580.00, 1317.00}} },
{ 792541538987ns, {{580.63, 1311.94}} },
{ 792544613000ns, {{581.00, 1309.00}} },
@@ -511,7 +563,7 @@
TEST_F(VelocityTrackerTest, SailfishFlingUpFaster1) {
// Sailfish - fling up - faster - 1
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{ 235160420675000ns, {{610.00, 1042.00}} },
{ 235160428220000ns, {{609.00, 1026.00}} },
{ 235160436544000ns, {{609.00, 1024.00}} },
@@ -545,7 +597,7 @@
TEST_F(VelocityTrackerTest, SailfishFlingUpFaster2) {
// Sailfish - fling up - faster - 2
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{ 847153808000ns, {{576.00, 1264.00}} },
{ 847171174000ns, {{576.00, 1262.00}} },
{ 847179640000ns, {{576.00, 1257.00}} },
@@ -571,7 +623,7 @@
TEST_F(VelocityTrackerTest, SailfishFlingUpFaster3) {
// Sailfish - fling up - faster - 3
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{ 235200532789000ns, {{507.00, 1084.00}} },
{ 235200549221000ns, {{507.00, 1083.00}} },
{ 235200557841000ns, {{507.00, 1081.00}} },
@@ -597,7 +649,7 @@
TEST_F(VelocityTrackerTest, SailfishFlingUpFast1) {
// Sailfish - fling up - fast - 1
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{ 920922149000ns, {{561.00, 1412.00}} },
{ 920930185000ns, {{559.00, 1377.00}} },
{ 920930262463ns, {{558.98, 1376.66}} },
@@ -626,7 +678,7 @@
TEST_F(VelocityTrackerTest, SailfishFlingUpFast2) {
// Sailfish - fling up - fast - 2
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{ 235247153233000ns, {{518.00, 1168.00}} },
{ 235247170452000ns, {{517.00, 1167.00}} },
{ 235247178908000ns, {{515.00, 1159.00}} },
@@ -649,7 +701,7 @@
TEST_F(VelocityTrackerTest, SailfishFlingUpFast3) {
// Sailfish - fling up - fast - 3
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{ 235302568736000ns, {{529.00, 1167.00}} },
{ 235302576644000ns, {{523.00, 1140.00}} },
{ 235302579395063ns, {{520.91, 1130.61}} },
@@ -670,7 +722,7 @@
TEST_F(VelocityTrackerTest, SailfishFlingDownSlow1) {
// Sailfish - fling down - slow - 1
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{ 235655749552755ns, {{582.00, 432.49}} },
{ 235655750638000ns, {{582.00, 433.00}} },
{ 235655758865000ns, {{582.00, 440.00}} },
@@ -704,7 +756,7 @@
TEST_F(VelocityTrackerTest, SailfishFlingDownSlow2) {
// Sailfish - fling down - slow - 2
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{ 235671152083370ns, {{485.24, 558.28}} },
{ 235671154126000ns, {{485.00, 559.00}} },
{ 235671162497000ns, {{484.00, 566.00}} },
@@ -738,7 +790,7 @@
TEST_F(VelocityTrackerTest, SailfishFlingDownSlow3) {
// Sailfish - fling down - slow - 3
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{ 170983201000ns, {{557.00, 533.00}} },
{ 171000668000ns, {{556.00, 534.00}} },
{ 171007359750ns, {{554.73, 535.27}} },
@@ -765,7 +817,7 @@
TEST_F(VelocityTrackerTest, SailfishFlingDownFaster1) {
// Sailfish - fling down - faster - 1
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{ 235695280333000ns, {{558.00, 451.00}} },
{ 235695283971237ns, {{558.43, 454.45}} },
{ 235695289038000ns, {{559.00, 462.00}} },
@@ -795,7 +847,7 @@
TEST_F(VelocityTrackerTest, SailfishFlingDownFaster2) {
// Sailfish - fling down - faster - 2
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{ 235709624766000ns, {{535.00, 579.00}} },
{ 235709642256000ns, {{534.00, 580.00}} },
{ 235709643350278ns, {{533.94, 580.06}} },
@@ -826,7 +878,7 @@
TEST_F(VelocityTrackerTest, SailfishFlingDownFaster3) {
// Sailfish - fling down - faster - 3
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{ 235727628927000ns, {{540.00, 440.00}} },
{ 235727636810000ns, {{537.00, 454.00}} },
{ 235727646176000ns, {{536.00, 454.00}} },
@@ -855,7 +907,7 @@
TEST_F(VelocityTrackerTest, SailfishFlingDownFast1) {
// Sailfish - fling down - fast - 1
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{ 235762352849000ns, {{467.00, 286.00}} },
{ 235762360250000ns, {{443.00, 344.00}} },
{ 235762362787412ns, {{434.77, 363.89}} },
@@ -876,7 +928,7 @@
TEST_F(VelocityTrackerTest, SailfishFlingDownFast2) {
// Sailfish - fling down - fast - 2
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{ 235772487188000ns, {{576.00, 204.00}} },
{ 235772495159000ns, {{553.00, 236.00}} },
{ 235772503568000ns, {{551.00, 240.00}} },
@@ -897,7 +949,7 @@
TEST_F(VelocityTrackerTest, SailfishFlingDownFast3) {
// Sailfish - fling down - fast - 3
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{ 507650295000ns, {{628.00, 233.00}} },
{ 507658234000ns, {{605.00, 269.00}} },
{ 507666784000ns, {{601.00, 274.00}} },
@@ -928,7 +980,7 @@
* part of the fitted data), this can cause large velocity values to be reported instead.
*/
TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_ThreeFingerTap) {
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{ 0us, {{1063, 1128}, {NAN, NAN}, {NAN, NAN}} },
{ 10800us, {{1063, 1128}, {682, 1318}, {NAN, NAN}} }, // POINTER_DOWN
{ 10800us, {{1063, 1128}, {682, 1318}, {397, 1747}} }, // POINTER_DOWN
@@ -955,7 +1007,7 @@
* affected by the liftoff.
*/
TEST_F(VelocityTrackerTest, ShortDelayBeforeActionUp) {
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{0ms, {{10, 0}}}, {10ms, {{20, 0}}}, {20ms, {{30, 0}}}, {30ms, {{30, 0}}}, // ACTION_UP
};
computeAndCheckVelocity(VelocityTracker::Strategy::IMPULSE, motions, AMOTION_EVENT_AXIS_X,
@@ -969,7 +1021,7 @@
* should be assumed to have stopped.
*/
TEST_F(VelocityTrackerTest, LongDelayBeforeActionUp) {
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{0ms, {{10, 0}}},
{10ms, {{20, 0}}},
{20ms, {{30, 0}}},
@@ -985,7 +1037,7 @@
* The final velocity should be reported as zero for all pointers.
*/
TEST_F(VelocityTrackerTest, LongDelayBeforeActionPointerUp) {
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{0ms, {{10, 0}}},
{10ms, {{20, 0}, {100, 0}}},
{20ms, {{30, 0}, {200, 0}}},
@@ -1029,7 +1081,7 @@
* In the test, we would convert these coefficients to (0*(1E3)^0, 0*(1E3)^1, 1*(1E3)^2).
*/
TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Constant) {
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{ 0ms, {{1, 1}} }, // 0 s
{ 1ms, {{1, 1}} }, // 0.001 s
{ 2ms, {{1, 1}} }, // 0.002 s
@@ -1047,7 +1099,7 @@
* Straight line y = x :: the constant and quadratic coefficients are zero.
*/
TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Linear) {
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{ 0ms, {{-2, -2}} },
{ 1ms, {{-1, -1}} },
{ 2ms, {{-0, -0}} },
@@ -1065,7 +1117,7 @@
* Parabola
*/
TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Parabolic) {
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{ 0ms, {{1, 1}} },
{ 1ms, {{4, 4}} },
{ 2ms, {{8, 8}} },
@@ -1083,7 +1135,7 @@
* Parabola
*/
TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Parabolic2) {
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{ 0ms, {{1, 1}} },
{ 1ms, {{4, 4}} },
{ 2ms, {{9, 9}} },
@@ -1101,7 +1153,7 @@
* Parabola :: y = x^2 :: the constant and linear coefficients are zero.
*/
TEST_F(VelocityTrackerTest, LeastSquaresVelocityTrackerStrategyEstimator_Parabolic3) {
- std::vector<MotionEventEntry> motions = {
+ std::vector<PlanarMotionEventEntry> motions = {
{ 0ms, {{4, 4}} },
{ 1ms, {{1, 1}} },
{ 2ms, {{0, 0}} },
@@ -1115,4 +1167,100 @@
computeAndCheckQuadraticEstimate(motions, std::array<float, 3>({0, 0E3, 1E6}));
}
+// Recorded by hand on sailfish, but only the diffs are taken to test cumulative axis velocity.
+TEST_F(VelocityTrackerTest, AxisScrollVelocity) {
+ std::vector<std::pair<std::chrono::nanoseconds, float>> motions = {
+ {235089067457000ns, 0.00}, {235089084684000ns, -1.00}, {235089093349000ns, 0.00},
+ {235089095677625ns, 0.00}, {235089101859000ns, 0.00}, {235089110378000ns, 0.00},
+ {235089112497111ns, 0.25}, {235089118760000ns, 1.75}, {235089126686000ns, 4.00},
+ {235089129316820ns, 1.33}, {235089135199000ns, 3.67}, {235089144297000ns, 6.00},
+ {235089146136443ns, 1.21}, {235089152923000ns, 5.79}, {235089160784000ns, 6.00},
+ {235089162955851ns, 1.66},
+ };
+
+ computeAndCheckAxisScrollVelocity(VelocityTracker::Strategy::IMPULSE, motions, {764.345703});
+}
+
+// --------------- Recorded by hand on a Wear OS device using a rotating side button ---------------
+TEST_F(VelocityTrackerTest, AxisScrollVelocity_ScrollDown) {
+ std::vector<std::pair<std::chrono::nanoseconds, float>> motions = {
+ {224598065152ns, -0.050100}, {224621871104ns, -0.133600}, {224645464064ns, -0.551100},
+ {224669171712ns, -0.801600}, {224687063040ns, -1.035400}, {224706691072ns, -0.484300},
+ {224738213888ns, -0.334000}, {224754401280ns, -0.083500},
+ };
+
+ computeAndCheckAxisScrollVelocity(VelocityTracker::Strategy::IMPULSE, motions, {-27.86});
+}
+
+TEST_F(VelocityTrackerTest, AxisScrollVelocity_ScrollUp) {
+ std::vector<std::pair<std::chrono::nanoseconds, float>> motions = {
+ {269606010880ns, 0.050100}, {269626064896ns, 0.217100}, {269641973760ns, 0.267200},
+ {269658079232ns, 0.267200}, {269674217472ns, 0.267200}, {269690683392ns, 0.367400},
+ {269706133504ns, 0.551100}, {269722173440ns, 0.501000},
+ };
+
+ computeAndCheckAxisScrollVelocity(VelocityTracker::Strategy::IMPULSE, motions, {31.92});
+}
+
+TEST_F(VelocityTrackerTest, AxisScrollVelocity_ScrollDown_ThenUp_ThenDown) {
+ std::vector<std::pair<std::chrono::nanoseconds, float>> motions = {
+ {2580534001664ns, -0.033400}, {2580549992448ns, -0.133600},
+ {2580566769664ns, -0.250500}, {2580581974016ns, -0.183700},
+ {2580597964800ns, -0.267200}, {2580613955584ns, -0.551100},
+ {2580635189248ns, -0.601200}, {2580661927936ns, -0.450900},
+ {2580683161600ns, -0.417500}, {2580705705984ns, -0.150300},
+ {2580722745344ns, -0.016700}, {2580786446336ns, 0.050100},
+ {2580801912832ns, 0.150300}, {2580822360064ns, 0.300600},
+ {2580838088704ns, 0.300600}, {2580854341632ns, 0.400800},
+ {2580869808128ns, 0.517700}, {2580886061056ns, 0.501000},
+ {2580905984000ns, 0.350700}, {2580921974784ns, 0.350700},
+ {2580937965568ns, 0.066800}, {2580974665728ns, 0.016700},
+ {2581034434560ns, -0.066800}, {2581049901056ns, -0.116900},
+ {2581070610432ns, -0.317300}, {2581086076928ns, -0.200400},
+ {2581101805568ns, -0.233800}, {2581118058496ns, -0.417500},
+ {2581134049280ns, -0.417500}, {2581150040064ns, -0.367400},
+ {2581166030848ns, -0.267200}, {2581181759488ns, -0.150300},
+ {2581199847424ns, -0.066800},
+ };
+
+ computeAndCheckAxisScrollVelocity(VelocityTracker::Strategy::IMPULSE, motions, {-9.73});
+}
+
+// ------------------------------- Hand generated test cases ---------------------------------------
+TEST_F(VelocityTrackerTest, AxisScrollVelocity_SimilarDifferentialValues) {
+ std::vector<std::pair<std::chrono::nanoseconds, float>> motions = {{1ns, 2.12}, {3ns, 2.12},
+ {7ns, 2.12}, {8ns, 2.12},
+ {15ns, 2.12}, {18ns, 2.12}};
+
+ computeAndCheckAxisScrollVelocity(VelocityTracker::Strategy::IMPULSE, motions, {1690236059.86});
+}
+
+TEST_F(VelocityTrackerTest, AxisScrollVelocity_OnlyTwoValues) {
+ std::vector<std::pair<std::chrono::nanoseconds, float>> motions = {{1ms, 5}, {2ms, 10}};
+
+ computeAndCheckAxisScrollVelocity(VelocityTracker::Strategy::IMPULSE, motions, {10000});
+}
+
+TEST_F(VelocityTrackerTest, AxisScrollVelocity_ConstantVelocity) {
+ std::vector<std::pair<std::chrono::nanoseconds, float>> motions = {{1ms, 20}, {2ms, 20},
+ {3ms, 20}, {4ms, 20},
+ {5ms, 20}, {6ms, 20}};
+
+ computeAndCheckAxisScrollVelocity(VelocityTracker::Strategy::IMPULSE, motions, {20000});
+}
+
+TEST_F(VelocityTrackerTest, AxisScrollVelocity_NoMotion) {
+ std::vector<std::pair<std::chrono::nanoseconds, float>> motions = {{1ns, 0}, {2ns, 0},
+ {3ns, 0}, {4ns, 0},
+ {5ns, 0}, {6ns, 0}};
+
+ computeAndCheckAxisScrollVelocity(VelocityTracker::Strategy::IMPULSE, motions, {0});
+}
+
+TEST_F(VelocityTrackerTest, AxisScrollVelocity_NoData) {
+ std::vector<std::pair<std::chrono::nanoseconds, float>> motions = {};
+
+ computeAndCheckAxisScrollVelocity(VelocityTracker::Strategy::IMPULSE, motions, std::nullopt);
+}
+
} // namespace android
diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp
index fbfecf6..3503a9e 100644
--- a/libs/nativewindow/Android.bp
+++ b/libs/nativewindow/Android.bp
@@ -61,6 +61,9 @@
// Android O
first_version: "26",
+ export_header_libs: [
+ "libnativewindow_ndk_headers",
+ ],
}
cc_library {
diff --git a/libs/sensor/fuzz/bittube_fuzzer/bittube_fuzzer.cpp b/libs/sensor/fuzz/bittube_fuzzer/bittube_fuzzer.cpp
index 6f10a67..6a61d36 100644
--- a/libs/sensor/fuzz/bittube_fuzzer/bittube_fuzzer.cpp
+++ b/libs/sensor/fuzz/bittube_fuzzer/bittube_fuzzer.cpp
@@ -24,14 +24,14 @@
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
FuzzedDataProvider fdp(data, size);
- BitTube bittube(size);
+ sp<BitTube> bittube(new BitTube(size));
Parcel parcel[5];
- bittube.writeToParcel(parcel);
+ bittube->writeToParcel(parcel);
sp<BitTube> tube(new BitTube(size));
- bittube.sendObjects<uint8_t>(tube, data, size);
+ bittube->sendObjects<uint8_t>(tube, data, size);
uint8_t recvData[size];
for (int i = 0; i < size; i++) recvData[i] = fdp.ConsumeIntegral<uint8_t>();
- bittube.recvObjects<uint8_t>(tube, recvData, size);
+ bittube->recvObjects<uint8_t>(tube, recvData, size);
return 0;
}
diff --git a/libs/ui/include/ui/GraphicBuffer.h b/libs/ui/include/ui/GraphicBuffer.h
index 57be686..dbe475b 100644
--- a/libs/ui/include/ui/GraphicBuffer.h
+++ b/libs/ui/include/ui/GraphicBuffer.h
@@ -270,7 +270,7 @@
// Send a callback when a GraphicBuffer dies.
//
- // This is used for BufferStateLayer caching. GraphicBuffers are refcounted per process. When
+ // This is used for layer caching. GraphicBuffers are refcounted per process. When
// A GraphicBuffer doesn't have any more sp<> in a process, it is destroyed. This causes
// problems when trying to implicitcly cache across process boundaries. Ideally, both sides
// of the cache would hold onto wp<> references. When an app dropped its sp<>, the GraphicBuffer
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index c1e935a..62cf255 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -12,7 +12,10 @@
name: "libETC1",
srcs: ["ETC1/etc1.cpp"],
host_supported: true,
- cflags: ["-Wall", "-Werror"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
target: {
android: {
@@ -37,6 +40,9 @@
symbol_file: "libEGL.map.txt",
first_version: "9",
unversioned_until: "current",
+ export_header_libs: [
+ "libEGL_headers",
+ ],
}
ndk_library {
@@ -44,6 +50,9 @@
symbol_file: "libGLESv1_CM.map.txt",
first_version: "9",
unversioned_until: "current",
+ export_header_libs: [
+ "libGLESv1_CM_headers",
+ ],
}
ndk_library {
@@ -51,6 +60,9 @@
symbol_file: "libGLESv2.map.txt",
first_version: "9",
unversioned_until: "current",
+ export_header_libs: [
+ "libGLESv2_headers",
+ ],
}
ndk_library {
@@ -58,6 +70,9 @@
symbol_file: "libGLESv3.map.txt",
first_version: "18",
unversioned_until: "current",
+ export_header_libs: [
+ "libGLESv3_headers",
+ ],
}
cc_defaults {
@@ -170,7 +185,11 @@
"libEGL_getProcAddress",
"libEGL_blobCache",
],
- ldflags: ["-Wl,--exclude-libs=ALL,--Bsymbolic-functions"],
+ ldflags: [
+ "-Wl,--exclude-libs=libEGL_getProcAddress.a",
+ "-Wl,--exclude-libs=libEGL_blobCache.a",
+ "-Wl,--Bsymbolic-functions",
+ ],
export_include_dirs: ["EGL/include"],
stubs: {
symbol_file: "libEGL.map.txt",
diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp
index efa67db..8348d6c 100644
--- a/opengl/libs/EGL/egl_cache.cpp
+++ b/opengl/libs/EGL/egl_cache.cpp
@@ -28,7 +28,7 @@
// Cache size limits.
static const size_t maxKeySize = 12 * 1024;
static const size_t maxValueSize = 64 * 1024;
-static const size_t maxTotalSize = 2 * 1024 * 1024;
+static const size_t maxTotalSize = 32 * 1024 * 1024;
// The time in seconds to wait before saving newly inserted cache entries.
static const unsigned int deferredSaveDelay = 4;
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index 5b286dc..ddcd51f 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -85,12 +85,12 @@
"libstatspull",
"libstatssocket",
"libutils",
- "libui",
"server_configurable_flags",
],
static_libs: [
"libattestation",
"libpalmrejection",
+ "libui-types",
],
}
@@ -139,6 +139,7 @@
"InputListener.cpp",
"InputReaderBase.cpp",
"InputThread.cpp",
+ "NotifyArgs.cpp",
"VibrationElement.cpp",
],
}
@@ -152,7 +153,6 @@
"libcutils",
"libinput",
"liblog",
- "libui",
"libutils",
],
header_libs: [
@@ -191,7 +191,16 @@
"libinputservice_test",
"Bug-115739809",
"StructLayout_test",
+
+ // native fuzzers
"inputflinger_latencytracker_fuzzer",
+ "inputflinger_cursor_input_fuzzer",
+ "inputflinger_keyboard_input_fuzzer",
+ "inputflinger_multitouch_input_fuzzer",
+ "inputflinger_switch_input_fuzzer",
+ "inputflinger_input_reader_fuzzer",
+ "inputflinger_blocking_queue_fuzzer",
+ "inputflinger_input_classifier_fuzzer",
// Java/Kotlin targets
"CtsWindowManagerDeviceTestCases",
diff --git a/services/inputflinger/InputListener.cpp b/services/inputflinger/InputListener.cpp
index dce327e..0972e22 100644
--- a/services/inputflinger/InputListener.cpp
+++ b/services/inputflinger/InputListener.cpp
@@ -31,308 +31,29 @@
namespace android {
-// --- NotifyConfigurationChangedArgs ---
+// --- InputListenerInterface ---
-NotifyConfigurationChangedArgs::NotifyConfigurationChangedArgs(int32_t id, nsecs_t eventTime)
- : NotifyArgs(id, eventTime) {}
+// Helper to std::visit with lambdas.
+template <typename... V>
+struct Visitor : V... {};
+// explicit deduction guide (not needed as of C++20)
+template <typename... V>
+Visitor(V...) -> Visitor<V...>;
-NotifyConfigurationChangedArgs::NotifyConfigurationChangedArgs(
- const NotifyConfigurationChangedArgs& other)
- : NotifyArgs(other.id, other.eventTime) {}
-
-bool NotifyConfigurationChangedArgs::operator==(const NotifyConfigurationChangedArgs& rhs) const {
- return id == rhs.id && eventTime == rhs.eventTime;
-}
-
-void NotifyConfigurationChangedArgs::notify(InputListenerInterface& listener) const {
- listener.notifyConfigurationChanged(this);
-}
-
-// --- NotifyKeyArgs ---
-
-NotifyKeyArgs::NotifyKeyArgs(int32_t id, nsecs_t eventTime, nsecs_t readTime, int32_t deviceId,
- uint32_t source, int32_t displayId, uint32_t policyFlags,
- int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode,
- int32_t metaState, nsecs_t downTime)
- : NotifyArgs(id, eventTime),
- deviceId(deviceId),
- source(source),
- displayId(displayId),
- policyFlags(policyFlags),
- action(action),
- flags(flags),
- keyCode(keyCode),
- scanCode(scanCode),
- metaState(metaState),
- downTime(downTime),
- readTime(readTime) {}
-
-NotifyKeyArgs::NotifyKeyArgs(const NotifyKeyArgs& other)
- : NotifyArgs(other.id, other.eventTime),
- deviceId(other.deviceId),
- source(other.source),
- displayId(other.displayId),
- policyFlags(other.policyFlags),
- action(other.action),
- flags(other.flags),
- keyCode(other.keyCode),
- scanCode(other.scanCode),
- metaState(other.metaState),
- downTime(other.downTime),
- readTime(other.readTime) {}
-
-bool NotifyKeyArgs::operator==(const NotifyKeyArgs& rhs) const {
- return id == rhs.id && eventTime == rhs.eventTime && readTime == rhs.readTime &&
- deviceId == rhs.deviceId && source == rhs.source && displayId == rhs.displayId &&
- policyFlags == rhs.policyFlags && action == rhs.action && flags == rhs.flags &&
- keyCode == rhs.keyCode && scanCode == rhs.scanCode && metaState == rhs.metaState &&
- downTime == rhs.downTime;
-}
-
-void NotifyKeyArgs::notify(InputListenerInterface& listener) const {
- listener.notifyKey(this);
-}
-
-// --- NotifyMotionArgs ---
-
-NotifyMotionArgs::NotifyMotionArgs(
- int32_t id, nsecs_t eventTime, nsecs_t readTime, int32_t deviceId, uint32_t source,
- int32_t displayId, uint32_t policyFlags, int32_t action, int32_t actionButton,
- int32_t flags, int32_t metaState, int32_t buttonState, MotionClassification classification,
- int32_t edgeFlags, uint32_t pointerCount, const PointerProperties* pointerProperties,
- const PointerCoords* pointerCoords, float xPrecision, float yPrecision,
- float xCursorPosition, float yCursorPosition, nsecs_t downTime,
- const std::vector<TouchVideoFrame>& videoFrames)
- : NotifyArgs(id, eventTime),
- deviceId(deviceId),
- source(source),
- displayId(displayId),
- policyFlags(policyFlags),
- action(action),
- actionButton(actionButton),
- flags(flags),
- metaState(metaState),
- buttonState(buttonState),
- classification(classification),
- edgeFlags(edgeFlags),
- pointerCount(pointerCount),
- xPrecision(xPrecision),
- yPrecision(yPrecision),
- xCursorPosition(xCursorPosition),
- yCursorPosition(yCursorPosition),
- downTime(downTime),
- readTime(readTime),
- videoFrames(videoFrames) {
- for (uint32_t i = 0; i < pointerCount; i++) {
- this->pointerProperties[i].copyFrom(pointerProperties[i]);
- this->pointerCoords[i].copyFrom(pointerCoords[i]);
- }
-}
-
-NotifyMotionArgs::NotifyMotionArgs(const NotifyMotionArgs& other)
- : NotifyArgs(other.id, other.eventTime),
- deviceId(other.deviceId),
- source(other.source),
- displayId(other.displayId),
- policyFlags(other.policyFlags),
- action(other.action),
- actionButton(other.actionButton),
- flags(other.flags),
- metaState(other.metaState),
- buttonState(other.buttonState),
- classification(other.classification),
- edgeFlags(other.edgeFlags),
- pointerCount(other.pointerCount),
- xPrecision(other.xPrecision),
- yPrecision(other.yPrecision),
- xCursorPosition(other.xCursorPosition),
- yCursorPosition(other.yCursorPosition),
- downTime(other.downTime),
- readTime(other.readTime),
- videoFrames(other.videoFrames) {
- for (uint32_t i = 0; i < pointerCount; i++) {
- pointerProperties[i].copyFrom(other.pointerProperties[i]);
- pointerCoords[i].copyFrom(other.pointerCoords[i]);
- }
-}
-
-static inline bool isCursorPositionEqual(float lhs, float rhs) {
- return (isnan(lhs) && isnan(rhs)) || lhs == rhs;
-}
-
-bool NotifyMotionArgs::operator==(const NotifyMotionArgs& rhs) const {
- bool equal = id == rhs.id && eventTime == rhs.eventTime && readTime == rhs.readTime &&
- deviceId == rhs.deviceId && source == rhs.source && displayId == rhs.displayId &&
- policyFlags == rhs.policyFlags && action == rhs.action &&
- actionButton == rhs.actionButton && flags == rhs.flags && metaState == rhs.metaState &&
- buttonState == rhs.buttonState && classification == rhs.classification &&
- edgeFlags == rhs.edgeFlags &&
- pointerCount == rhs.pointerCount
- // PointerProperties and PointerCoords are compared separately below
- && xPrecision == rhs.xPrecision && yPrecision == rhs.yPrecision &&
- isCursorPositionEqual(xCursorPosition, rhs.xCursorPosition) &&
- isCursorPositionEqual(yCursorPosition, rhs.yCursorPosition) &&
- downTime == rhs.downTime && videoFrames == rhs.videoFrames;
- if (!equal) {
- return false;
- }
-
- for (size_t i = 0; i < pointerCount; i++) {
- equal =
- pointerProperties[i] == rhs.pointerProperties[i]
- && pointerCoords[i] == rhs.pointerCoords[i];
- if (!equal) {
- return false;
- }
- }
- return true;
-}
-
-std::string NotifyMotionArgs::dump() const {
- std::string coords;
- for (uint32_t i = 0; i < pointerCount; i++) {
- if (!coords.empty()) {
- coords += ", ";
- }
- coords += StringPrintf("{%" PRIu32 ": ", i);
- coords +=
- StringPrintf("id=%" PRIu32 " x=%.1f y=%.1f pressure=%.1f", pointerProperties[i].id,
- pointerCoords[i].getX(), pointerCoords[i].getY(),
- pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
- const int32_t toolType = pointerProperties[i].toolType;
- if (toolType != AMOTION_EVENT_TOOL_TYPE_FINGER) {
- coords += StringPrintf(" toolType=%s", motionToolTypeToString(toolType));
- }
- const float major = pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR);
- const float minor = pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR);
- const float orientation = pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
- if (major != 0 || minor != 0) {
- coords += StringPrintf(" major=%.1f minor=%.1f orientation=%.1f", major, minor,
- orientation);
- }
- coords += "}";
- }
- return StringPrintf("NotifyMotionArgs(id=%" PRId32 ", eventTime=%" PRId64 ", deviceId=%" PRId32
- ", source=%s, action=%s, pointerCount=%" PRIu32
- " pointers=%s, flags=0x%08x)",
- id, eventTime, deviceId, inputEventSourceToString(source).c_str(),
- MotionEvent::actionToString(action).c_str(), pointerCount, coords.c_str(),
- flags);
-}
-
-void NotifyMotionArgs::notify(InputListenerInterface& listener) const {
- listener.notifyMotion(this);
-}
-
-// --- NotifySwitchArgs ---
-
-NotifySwitchArgs::NotifySwitchArgs(int32_t id, nsecs_t eventTime, uint32_t policyFlags,
- uint32_t switchValues, uint32_t switchMask)
- : NotifyArgs(id, eventTime),
- policyFlags(policyFlags),
- switchValues(switchValues),
- switchMask(switchMask) {}
-
-NotifySwitchArgs::NotifySwitchArgs(const NotifySwitchArgs& other)
- : NotifyArgs(other.id, other.eventTime),
- policyFlags(other.policyFlags),
- switchValues(other.switchValues),
- switchMask(other.switchMask) {}
-
-bool NotifySwitchArgs::operator==(const NotifySwitchArgs rhs) const {
- return id == rhs.id && eventTime == rhs.eventTime && policyFlags == rhs.policyFlags &&
- switchValues == rhs.switchValues && switchMask == rhs.switchMask;
-}
-
-void NotifySwitchArgs::notify(InputListenerInterface& listener) const {
- listener.notifySwitch(this);
-}
-
-// --- NotifySensorArgs ---
-
-NotifySensorArgs::NotifySensorArgs(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source,
- InputDeviceSensorType sensorType,
- InputDeviceSensorAccuracy accuracy, bool accuracyChanged,
- nsecs_t hwTimestamp, std::vector<float> values)
- : NotifyArgs(id, eventTime),
- deviceId(deviceId),
- source(source),
- sensorType(sensorType),
- accuracy(accuracy),
- accuracyChanged(accuracyChanged),
- hwTimestamp(hwTimestamp),
- values(std::move(values)) {}
-
-NotifySensorArgs::NotifySensorArgs(const NotifySensorArgs& other)
- : NotifyArgs(other.id, other.eventTime),
- deviceId(other.deviceId),
- source(other.source),
- sensorType(other.sensorType),
- accuracy(other.accuracy),
- accuracyChanged(other.accuracyChanged),
- hwTimestamp(other.hwTimestamp),
- values(other.values) {}
-
-bool NotifySensorArgs::operator==(const NotifySensorArgs rhs) const {
- return id == rhs.id && eventTime == rhs.eventTime && sensorType == rhs.sensorType &&
- accuracy == rhs.accuracy && accuracyChanged == rhs.accuracyChanged &&
- hwTimestamp == rhs.hwTimestamp && values == rhs.values;
-}
-
-void NotifySensorArgs::notify(InputListenerInterface& listener) const {
- listener.notifySensor(this);
-}
-
-// --- NotifyVibratorStateArgs ---
-
-NotifyVibratorStateArgs::NotifyVibratorStateArgs(int32_t id, nsecs_t eventTime, int32_t deviceId,
- bool isOn)
- : NotifyArgs(id, eventTime), deviceId(deviceId), isOn(isOn) {}
-
-NotifyVibratorStateArgs::NotifyVibratorStateArgs(const NotifyVibratorStateArgs& other)
- : NotifyArgs(other.id, other.eventTime), deviceId(other.deviceId), isOn(other.isOn) {}
-
-bool NotifyVibratorStateArgs::operator==(const NotifyVibratorStateArgs rhs) const {
- return id == rhs.id && eventTime == rhs.eventTime && deviceId == rhs.deviceId &&
- isOn == rhs.isOn;
-}
-
-void NotifyVibratorStateArgs::notify(InputListenerInterface& listener) const {
- listener.notifyVibratorState(this);
-}
-
-// --- NotifyDeviceResetArgs ---
-
-NotifyDeviceResetArgs::NotifyDeviceResetArgs(int32_t id, nsecs_t eventTime, int32_t deviceId)
- : NotifyArgs(id, eventTime), deviceId(deviceId) {}
-
-NotifyDeviceResetArgs::NotifyDeviceResetArgs(const NotifyDeviceResetArgs& other)
- : NotifyArgs(other.id, other.eventTime), deviceId(other.deviceId) {}
-
-bool NotifyDeviceResetArgs::operator==(const NotifyDeviceResetArgs& rhs) const {
- return id == rhs.id && eventTime == rhs.eventTime && deviceId == rhs.deviceId;
-}
-
-void NotifyDeviceResetArgs::notify(InputListenerInterface& listener) const {
- listener.notifyDeviceReset(this);
-}
-
-// --- NotifyPointerCaptureChangedArgs ---
-
-NotifyPointerCaptureChangedArgs::NotifyPointerCaptureChangedArgs(
- int32_t id, nsecs_t eventTime, const PointerCaptureRequest& request)
- : NotifyArgs(id, eventTime), request(request) {}
-
-NotifyPointerCaptureChangedArgs::NotifyPointerCaptureChangedArgs(
- const NotifyPointerCaptureChangedArgs& other)
- : NotifyArgs(other.id, other.eventTime), request(other.request) {}
-
-bool NotifyPointerCaptureChangedArgs::operator==(const NotifyPointerCaptureChangedArgs& rhs) const {
- return id == rhs.id && eventTime == rhs.eventTime && request == rhs.request;
-}
-
-void NotifyPointerCaptureChangedArgs::notify(InputListenerInterface& listener) const {
- listener.notifyPointerCaptureChanged(this);
+void InputListenerInterface::notify(const NotifyArgs& generalArgs) {
+ Visitor v{
+ [&](const NotifyConfigurationChangedArgs& args) { notifyConfigurationChanged(&args); },
+ [&](const NotifyKeyArgs& args) { notifyKey(&args); },
+ [&](const NotifyMotionArgs& args) { notifyMotion(&args); },
+ [&](const NotifySwitchArgs& args) { notifySwitch(&args); },
+ [&](const NotifySensorArgs& args) { notifySensor(&args); },
+ [&](const NotifyVibratorStateArgs& args) { notifyVibratorState(&args); },
+ [&](const NotifyDeviceResetArgs& args) { notifyDeviceReset(&args); },
+ [&](const NotifyPointerCaptureChangedArgs& args) {
+ notifyPointerCaptureChanged(&args);
+ },
+ };
+ std::visit(v, generalArgs);
}
// --- QueuedInputListener ---
@@ -350,47 +71,47 @@
void QueuedInputListener::notifyConfigurationChanged(
const NotifyConfigurationChangedArgs* args) {
traceEvent(__func__, args->id);
- mArgsQueue.emplace_back(std::make_unique<NotifyConfigurationChangedArgs>(*args));
+ mArgsQueue.emplace_back(*args);
}
void QueuedInputListener::notifyKey(const NotifyKeyArgs* args) {
traceEvent(__func__, args->id);
- mArgsQueue.emplace_back(std::make_unique<NotifyKeyArgs>(*args));
+ mArgsQueue.emplace_back(*args);
}
void QueuedInputListener::notifyMotion(const NotifyMotionArgs* args) {
traceEvent(__func__, args->id);
- mArgsQueue.emplace_back(std::make_unique<NotifyMotionArgs>(*args));
+ mArgsQueue.emplace_back(*args);
}
void QueuedInputListener::notifySwitch(const NotifySwitchArgs* args) {
traceEvent(__func__, args->id);
- mArgsQueue.emplace_back(std::make_unique<NotifySwitchArgs>(*args));
+ mArgsQueue.emplace_back(*args);
}
void QueuedInputListener::notifySensor(const NotifySensorArgs* args) {
traceEvent(__func__, args->id);
- mArgsQueue.emplace_back(std::make_unique<NotifySensorArgs>(*args));
+ mArgsQueue.emplace_back(*args);
}
void QueuedInputListener::notifyVibratorState(const NotifyVibratorStateArgs* args) {
traceEvent(__func__, args->id);
- mArgsQueue.emplace_back(std::make_unique<NotifyVibratorStateArgs>(*args));
+ mArgsQueue.emplace_back(*args);
}
void QueuedInputListener::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
traceEvent(__func__, args->id);
- mArgsQueue.emplace_back(std::make_unique<NotifyDeviceResetArgs>(*args));
+ mArgsQueue.emplace_back(*args);
}
void QueuedInputListener::notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) {
traceEvent(__func__, args->id);
- mArgsQueue.emplace_back(std::make_unique<NotifyPointerCaptureChangedArgs>(*args));
+ mArgsQueue.emplace_back(*args);
}
void QueuedInputListener::flush() {
- for (const std::unique_ptr<NotifyArgs>& args : mArgsQueue) {
- args->notify(mInnerListener);
+ for (const NotifyArgs& args : mArgsQueue) {
+ mInnerListener.notify(args);
}
mArgsQueue.clear();
}
diff --git a/services/inputflinger/InputProcessor.cpp b/services/inputflinger/InputProcessor.cpp
index 0749441..02d62bf 100644
--- a/services/inputflinger/InputProcessor.cpp
+++ b/services/inputflinger/InputProcessor.cpp
@@ -22,6 +22,7 @@
#include <android-base/stringprintf.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
+#include <input/Input.h>
#include <inttypes.h>
#include <log/log.h>
#include <algorithm>
@@ -123,40 +124,38 @@
// --- ClassifierEvent ---
-ClassifierEvent::ClassifierEvent(std::unique_ptr<NotifyMotionArgs> args)
- : type(ClassifierEventType::MOTION), args(std::move(args)){};
-ClassifierEvent::ClassifierEvent(std::unique_ptr<NotifyDeviceResetArgs> args)
- : type(ClassifierEventType::DEVICE_RESET), args(std::move(args)){};
-ClassifierEvent::ClassifierEvent(ClassifierEventType type, std::unique_ptr<NotifyArgs> args)
- : type(type), args(std::move(args)){};
+ClassifierEvent::ClassifierEvent(const NotifyMotionArgs& args)
+ : type(ClassifierEventType::MOTION), args(args){};
-ClassifierEvent::ClassifierEvent(ClassifierEvent&& other)
- : type(other.type), args(std::move(other.args)){};
+ClassifierEvent::ClassifierEvent(const NotifyDeviceResetArgs& args)
+ : type(ClassifierEventType::DEVICE_RESET), args(args){};
+
+ClassifierEvent::ClassifierEvent(ClassifierEventType type, std::optional<NotifyArgs> args)
+ : type(type), args(args){};
ClassifierEvent& ClassifierEvent::operator=(ClassifierEvent&& other) {
type = other.type;
- args = std::move(other.args);
+ args = other.args;
return *this;
}
ClassifierEvent ClassifierEvent::createHalResetEvent() {
- return ClassifierEvent(ClassifierEventType::HAL_RESET, nullptr);
+ return ClassifierEvent(ClassifierEventType::HAL_RESET, std::nullopt);
}
ClassifierEvent ClassifierEvent::createExitEvent() {
- return ClassifierEvent(ClassifierEventType::EXIT, nullptr);
+ return ClassifierEvent(ClassifierEventType::EXIT, std::nullopt);
}
std::optional<int32_t> ClassifierEvent::getDeviceId() const {
switch (type) {
case ClassifierEventType::MOTION: {
- NotifyMotionArgs* motionArgs = static_cast<NotifyMotionArgs*>(args.get());
- return motionArgs->deviceId;
+ const NotifyMotionArgs& motionArgs = std::get<NotifyMotionArgs>(*args);
+ return motionArgs.deviceId;
}
case ClassifierEventType::DEVICE_RESET: {
- NotifyDeviceResetArgs* deviceResetArgs =
- static_cast<NotifyDeviceResetArgs*>(args.get());
- return deviceResetArgs->deviceId;
+ const NotifyDeviceResetArgs& deviceResetArgs = std::get<NotifyDeviceResetArgs>(*args);
+ return deviceResetArgs.deviceId;
}
case ClassifierEventType::HAL_RESET: {
return std::nullopt;
@@ -212,12 +211,12 @@
bool halResponseOk = true;
switch (event.type) {
case ClassifierEventType::MOTION: {
- NotifyMotionArgs* motionArgs = static_cast<NotifyMotionArgs*>(event.args.get());
- common::MotionEvent motionEvent = notifyMotionArgsToHalMotionEvent(*motionArgs);
+ NotifyMotionArgs& motionArgs = std::get<NotifyMotionArgs>(*event.args);
+ common::MotionEvent motionEvent = notifyMotionArgsToHalMotionEvent(motionArgs);
common::Classification classification;
ndk::ScopedAStatus response = mService->classify(motionEvent, &classification);
if (response.isOk()) {
- updateClassification(motionArgs->deviceId, motionArgs->eventTime,
+ updateClassification(motionArgs.deviceId, motionArgs.eventTime,
getMotionClassification(classification));
}
break;
@@ -307,8 +306,7 @@
updateLastDownTime(args.deviceId, args.downTime);
}
- ClassifierEvent event(std::make_unique<NotifyMotionArgs>(args));
- enqueueEvent(std::move(event));
+ enqueueEvent(args);
return getClassification(args.deviceId);
}
@@ -328,7 +326,7 @@
std::optional<int32_t> eventDeviceId = event.getDeviceId();
return eventDeviceId && (*eventDeviceId == deviceId);
});
- enqueueEvent(std::make_unique<NotifyDeviceResetArgs>(args));
+ enqueueEvent(args);
}
void MotionClassifier::dump(std::string& dump) {
@@ -436,7 +434,13 @@
mQueuedListener.notifyMotion(args);
} else {
NotifyMotionArgs newArgs(*args);
- newArgs.classification = mMotionClassifier->classify(newArgs);
+ const MotionClassification newClassification = mMotionClassifier->classify(newArgs);
+ LOG_ALWAYS_FATAL_IF(args->classification != MotionClassification::NONE &&
+ newClassification != MotionClassification::NONE,
+ "Conflicting classifications %s (new) and %s (old)!",
+ motionClassificationToString(newClassification),
+ motionClassificationToString(args->classification));
+ newArgs.classification = newClassification;
mQueuedListener.notifyMotion(&newArgs);
}
} // release lock
diff --git a/services/inputflinger/InputProcessor.h b/services/inputflinger/InputProcessor.h
index bbf391e..f4d02b6 100644
--- a/services/inputflinger/InputProcessor.h
+++ b/services/inputflinger/InputProcessor.h
@@ -35,12 +35,12 @@
struct ClassifierEvent {
ClassifierEventType type;
- std::unique_ptr<NotifyArgs> args;
+ std::optional<NotifyArgs> args;
- ClassifierEvent(ClassifierEventType type, std::unique_ptr<NotifyArgs> args);
- ClassifierEvent(std::unique_ptr<NotifyMotionArgs> args);
- ClassifierEvent(std::unique_ptr<NotifyDeviceResetArgs> args);
- ClassifierEvent(ClassifierEvent&& other);
+ ClassifierEvent(ClassifierEventType type, std::optional<NotifyArgs> args);
+ ClassifierEvent(const NotifyMotionArgs& args);
+ ClassifierEvent(const NotifyDeviceResetArgs& args);
+ ClassifierEvent(ClassifierEvent&& other) = default;
ClassifierEvent& operator=(ClassifierEvent&& other);
// Convenience function to create a HAL_RESET event
diff --git a/services/inputflinger/NotifyArgs.cpp b/services/inputflinger/NotifyArgs.cpp
new file mode 100644
index 0000000..1f37774
--- /dev/null
+++ b/services/inputflinger/NotifyArgs.cpp
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2022 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 "NotifyArgs"
+
+#define ATRACE_TAG ATRACE_TAG_INPUT
+
+#include "NotifyArgs.h"
+
+#include <android-base/stringprintf.h>
+#include <android/log.h>
+#include <math.h>
+#include <utils/Trace.h>
+
+using android::base::StringPrintf;
+
+namespace android {
+
+// --- NotifyConfigurationChangedArgs ---
+
+NotifyConfigurationChangedArgs::NotifyConfigurationChangedArgs(int32_t id, nsecs_t eventTime)
+ : id(id), eventTime(eventTime) {}
+
+// --- NotifyKeyArgs ---
+
+NotifyKeyArgs::NotifyKeyArgs(int32_t id, nsecs_t eventTime, nsecs_t readTime, int32_t deviceId,
+ uint32_t source, int32_t displayId, uint32_t policyFlags,
+ int32_t action, int32_t flags, int32_t keyCode, int32_t scanCode,
+ int32_t metaState, nsecs_t downTime)
+ : id(id),
+ eventTime(eventTime),
+ deviceId(deviceId),
+ source(source),
+ displayId(displayId),
+ policyFlags(policyFlags),
+ action(action),
+ flags(flags),
+ keyCode(keyCode),
+ scanCode(scanCode),
+ metaState(metaState),
+ downTime(downTime),
+ readTime(readTime) {}
+
+// --- NotifyMotionArgs ---
+
+NotifyMotionArgs::NotifyMotionArgs(
+ int32_t id, nsecs_t eventTime, nsecs_t readTime, int32_t deviceId, uint32_t source,
+ int32_t displayId, uint32_t policyFlags, int32_t action, int32_t actionButton,
+ int32_t flags, int32_t metaState, int32_t buttonState, MotionClassification classification,
+ int32_t edgeFlags, uint32_t pointerCount, const PointerProperties* pointerProperties,
+ const PointerCoords* pointerCoords, float xPrecision, float yPrecision,
+ float xCursorPosition, float yCursorPosition, nsecs_t downTime,
+ const std::vector<TouchVideoFrame>& videoFrames)
+ : id(id),
+ eventTime(eventTime),
+ deviceId(deviceId),
+ source(source),
+ displayId(displayId),
+ policyFlags(policyFlags),
+ action(action),
+ actionButton(actionButton),
+ flags(flags),
+ metaState(metaState),
+ buttonState(buttonState),
+ classification(classification),
+ edgeFlags(edgeFlags),
+ pointerCount(pointerCount),
+ xPrecision(xPrecision),
+ yPrecision(yPrecision),
+ xCursorPosition(xCursorPosition),
+ yCursorPosition(yCursorPosition),
+ downTime(downTime),
+ readTime(readTime),
+ videoFrames(videoFrames) {
+ for (uint32_t i = 0; i < pointerCount; i++) {
+ this->pointerProperties[i].copyFrom(pointerProperties[i]);
+ this->pointerCoords[i].copyFrom(pointerCoords[i]);
+ }
+}
+
+NotifyMotionArgs::NotifyMotionArgs(const NotifyMotionArgs& other)
+ : id(other.id),
+ eventTime(other.eventTime),
+ deviceId(other.deviceId),
+ source(other.source),
+ displayId(other.displayId),
+ policyFlags(other.policyFlags),
+ action(other.action),
+ actionButton(other.actionButton),
+ flags(other.flags),
+ metaState(other.metaState),
+ buttonState(other.buttonState),
+ classification(other.classification),
+ edgeFlags(other.edgeFlags),
+ pointerCount(other.pointerCount),
+ xPrecision(other.xPrecision),
+ yPrecision(other.yPrecision),
+ xCursorPosition(other.xCursorPosition),
+ yCursorPosition(other.yCursorPosition),
+ downTime(other.downTime),
+ readTime(other.readTime),
+ videoFrames(other.videoFrames) {
+ for (uint32_t i = 0; i < pointerCount; i++) {
+ pointerProperties[i].copyFrom(other.pointerProperties[i]);
+ pointerCoords[i].copyFrom(other.pointerCoords[i]);
+ }
+}
+
+static inline bool isCursorPositionEqual(float lhs, float rhs) {
+ return (isnan(lhs) && isnan(rhs)) || lhs == rhs;
+}
+
+bool NotifyMotionArgs::operator==(const NotifyMotionArgs& rhs) const {
+ bool equal = id == rhs.id && eventTime == rhs.eventTime && readTime == rhs.readTime &&
+ deviceId == rhs.deviceId && source == rhs.source && displayId == rhs.displayId &&
+ policyFlags == rhs.policyFlags && action == rhs.action &&
+ actionButton == rhs.actionButton && flags == rhs.flags && metaState == rhs.metaState &&
+ buttonState == rhs.buttonState && classification == rhs.classification &&
+ edgeFlags == rhs.edgeFlags &&
+ pointerCount == rhs.pointerCount
+ // PointerProperties and PointerCoords are compared separately below
+ && xPrecision == rhs.xPrecision && yPrecision == rhs.yPrecision &&
+ isCursorPositionEqual(xCursorPosition, rhs.xCursorPosition) &&
+ isCursorPositionEqual(yCursorPosition, rhs.yCursorPosition) &&
+ downTime == rhs.downTime && videoFrames == rhs.videoFrames;
+ if (!equal) {
+ return false;
+ }
+
+ for (size_t i = 0; i < pointerCount; i++) {
+ equal = pointerProperties[i] == rhs.pointerProperties[i] &&
+ pointerCoords[i] == rhs.pointerCoords[i];
+ if (!equal) {
+ return false;
+ }
+ }
+ return true;
+}
+
+std::string NotifyMotionArgs::dump() const {
+ std::string coords;
+ for (uint32_t i = 0; i < pointerCount; i++) {
+ if (!coords.empty()) {
+ coords += ", ";
+ }
+ coords += StringPrintf("{%" PRIu32 ": ", i);
+ coords +=
+ StringPrintf("id=%" PRIu32 " x=%.1f y=%.1f pressure=%.1f", pointerProperties[i].id,
+ pointerCoords[i].getX(), pointerCoords[i].getY(),
+ pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
+ const int32_t toolType = pointerProperties[i].toolType;
+ if (toolType != AMOTION_EVENT_TOOL_TYPE_FINGER) {
+ coords += StringPrintf(" toolType=%s", motionToolTypeToString(toolType));
+ }
+ const float major = pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR);
+ const float minor = pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR);
+ const float orientation = pointerCoords[i].getAxisValue(AMOTION_EVENT_AXIS_ORIENTATION);
+ if (major != 0 || minor != 0) {
+ coords += StringPrintf(" major=%.1f minor=%.1f orientation=%.1f", major, minor,
+ orientation);
+ }
+ coords += "}";
+ }
+ return StringPrintf("NotifyMotionArgs(id=%" PRId32 ", eventTime=%" PRId64 ", deviceId=%" PRId32
+ ", source=%s, action=%s, pointerCount=%" PRIu32
+ " pointers=%s, flags=0x%08x)",
+ id, eventTime, deviceId, inputEventSourceToString(source).c_str(),
+ MotionEvent::actionToString(action).c_str(), pointerCount, coords.c_str(),
+ flags);
+}
+
+// --- NotifySwitchArgs ---
+
+NotifySwitchArgs::NotifySwitchArgs(int32_t id, nsecs_t eventTime, uint32_t policyFlags,
+ uint32_t switchValues, uint32_t switchMask)
+ : id(id),
+ eventTime(eventTime),
+ policyFlags(policyFlags),
+ switchValues(switchValues),
+ switchMask(switchMask) {}
+
+// --- NotifySensorArgs ---
+
+NotifySensorArgs::NotifySensorArgs(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source,
+ InputDeviceSensorType sensorType,
+ InputDeviceSensorAccuracy accuracy, bool accuracyChanged,
+ nsecs_t hwTimestamp, std::vector<float> values)
+ : id(id),
+ eventTime(eventTime),
+ deviceId(deviceId),
+ source(source),
+ sensorType(sensorType),
+ accuracy(accuracy),
+ accuracyChanged(accuracyChanged),
+ hwTimestamp(hwTimestamp),
+ values(std::move(values)) {}
+
+// --- NotifyVibratorStateArgs ---
+
+NotifyVibratorStateArgs::NotifyVibratorStateArgs(int32_t id, nsecs_t eventTime, int32_t deviceId,
+ bool isOn)
+ : id(id), eventTime(eventTime), deviceId(deviceId), isOn(isOn) {}
+
+// --- NotifyDeviceResetArgs ---
+
+NotifyDeviceResetArgs::NotifyDeviceResetArgs(int32_t id, nsecs_t eventTime, int32_t deviceId)
+ : id(id), eventTime(eventTime), deviceId(deviceId) {}
+
+// --- NotifyPointerCaptureChangedArgs ---
+
+NotifyPointerCaptureChangedArgs::NotifyPointerCaptureChangedArgs(
+ int32_t id, nsecs_t eventTime, const PointerCaptureRequest& request)
+ : id(id), eventTime(eventTime), request(request) {}
+
+} // namespace android
diff --git a/services/inputflinger/benchmarks/Android.bp b/services/inputflinger/benchmarks/Android.bp
index 75071d5..e5c19af 100644
--- a/services/inputflinger/benchmarks/Android.bp
+++ b/services/inputflinger/benchmarks/Android.bp
@@ -26,7 +26,6 @@
"libinputreporter",
"liblog",
"libstatslog",
- "libui",
"libutils",
],
static_libs: [
diff --git a/services/inputflinger/dispatcher/Android.bp b/services/inputflinger/dispatcher/Android.bp
index cdad9c9..eb79b76 100644
--- a/services/inputflinger/dispatcher/Android.bp
+++ b/services/inputflinger/dispatcher/Android.bp
@@ -63,7 +63,6 @@
"libstatslog",
"libstatspull",
"libstatssocket",
- "libui",
"libgui",
"libutils",
"server_configurable_flags",
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index f6872d1..630d21a 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -41,7 +41,6 @@
#include <input/InputTransport.h>
#include <limits.h>
#include <stddef.h>
-#include <ui/Region.h>
#include <unistd.h>
#include <utils/BitSet.h>
#include <utils/Looper.h>
diff --git a/services/inputflinger/include/InputListener.h b/services/inputflinger/include/InputListener.h
index c8ab6c5..8647bcb 100644
--- a/services/inputflinger/include/InputListener.h
+++ b/services/inputflinger/include/InputListener.h
@@ -21,230 +21,10 @@
#include <input/Input.h>
#include <input/InputDevice.h>
#include <input/TouchVideoFrame.h>
+#include "NotifyArgs.h"
namespace android {
-class InputListenerInterface;
-
-
-/* Superclass of all input event argument objects */
-struct NotifyArgs {
- int32_t id;
- nsecs_t eventTime;
-
- inline NotifyArgs() : id(0), eventTime(0) {}
-
- inline explicit NotifyArgs(int32_t id, nsecs_t eventTime) : id(id), eventTime(eventTime) {}
-
- virtual ~NotifyArgs() { }
-
- virtual void notify(InputListenerInterface& listener) const = 0;
-};
-
-
-/* Describes a configuration change event. */
-struct NotifyConfigurationChangedArgs : public NotifyArgs {
-
- inline NotifyConfigurationChangedArgs() { }
-
- bool operator==(const NotifyConfigurationChangedArgs& rhs) const;
-
- NotifyConfigurationChangedArgs(int32_t id, nsecs_t eventTime);
-
- NotifyConfigurationChangedArgs(const NotifyConfigurationChangedArgs& other);
-
- virtual ~NotifyConfigurationChangedArgs() { }
-
- void notify(InputListenerInterface& listener) const override;
-};
-
-
-/* Describes a key event. */
-struct NotifyKeyArgs : public NotifyArgs {
- int32_t deviceId;
- uint32_t source;
- int32_t displayId;
- uint32_t policyFlags;
- int32_t action;
- int32_t flags;
- int32_t keyCode;
- int32_t scanCode;
- int32_t metaState;
- nsecs_t downTime;
- nsecs_t readTime;
-
- inline NotifyKeyArgs() { }
-
- NotifyKeyArgs(int32_t id, nsecs_t eventTime, nsecs_t readTime, int32_t deviceId,
- uint32_t source, int32_t displayId, uint32_t policyFlags, int32_t action,
- int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
- nsecs_t downTime);
-
- bool operator==(const NotifyKeyArgs& rhs) const;
-
- NotifyKeyArgs(const NotifyKeyArgs& other);
-
- virtual ~NotifyKeyArgs() { }
-
- void notify(InputListenerInterface& listener) const override;
-};
-
-
-/* Describes a motion event. */
-struct NotifyMotionArgs : public NotifyArgs {
- int32_t deviceId;
- uint32_t source;
- int32_t displayId;
- uint32_t policyFlags;
- int32_t action;
- int32_t actionButton;
- int32_t flags;
- int32_t metaState;
- int32_t buttonState;
- /**
- * Classification of the current touch gesture
- */
- MotionClassification classification;
- int32_t edgeFlags;
-
- uint32_t pointerCount;
- PointerProperties pointerProperties[MAX_POINTERS];
- PointerCoords pointerCoords[MAX_POINTERS];
- float xPrecision;
- float yPrecision;
- /**
- * Mouse cursor position when this event is reported relative to the origin of the specified
- * display. Only valid if this is a mouse event (originates from a mouse or from a trackpad in
- * gestures enabled mode.
- */
- float xCursorPosition;
- float yCursorPosition;
- nsecs_t downTime;
- nsecs_t readTime;
- std::vector<TouchVideoFrame> videoFrames;
-
- inline NotifyMotionArgs() { }
-
- NotifyMotionArgs(int32_t id, nsecs_t eventTime, nsecs_t readTime, int32_t deviceId,
- uint32_t source, int32_t displayId, uint32_t policyFlags, int32_t action,
- int32_t actionButton, int32_t flags, int32_t metaState, int32_t buttonState,
- MotionClassification classification, int32_t edgeFlags, uint32_t pointerCount,
- const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
- float xPrecision, float yPrecision, float xCursorPosition,
- float yCursorPosition, nsecs_t downTime,
- const std::vector<TouchVideoFrame>& videoFrames);
-
- NotifyMotionArgs(const NotifyMotionArgs& other);
-
- virtual ~NotifyMotionArgs() { }
-
- bool operator==(const NotifyMotionArgs& rhs) const;
-
- void notify(InputListenerInterface& listener) const override;
-
- std::string dump() const;
-};
-
-/* Describes a sensor event. */
-struct NotifySensorArgs : public NotifyArgs {
- int32_t deviceId;
- uint32_t source;
- InputDeviceSensorType sensorType;
- InputDeviceSensorAccuracy accuracy;
- bool accuracyChanged;
- nsecs_t hwTimestamp;
- std::vector<float> values;
-
- inline NotifySensorArgs() {}
-
- NotifySensorArgs(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source,
- InputDeviceSensorType sensorType, InputDeviceSensorAccuracy accuracy,
- bool accuracyChanged, nsecs_t hwTimestamp, std::vector<float> values);
-
- NotifySensorArgs(const NotifySensorArgs& other);
-
- bool operator==(const NotifySensorArgs rhs) const;
-
- ~NotifySensorArgs() override {}
-
- void notify(InputListenerInterface& listener) const override;
-};
-
-/* Describes a switch event. */
-struct NotifySwitchArgs : public NotifyArgs {
- uint32_t policyFlags;
- uint32_t switchValues;
- uint32_t switchMask;
-
- inline NotifySwitchArgs() { }
-
- NotifySwitchArgs(int32_t id, nsecs_t eventTime, uint32_t policyFlags, uint32_t switchValues,
- uint32_t switchMask);
-
- NotifySwitchArgs(const NotifySwitchArgs& other);
-
- bool operator==(const NotifySwitchArgs rhs) const;
-
- virtual ~NotifySwitchArgs() { }
-
- void notify(InputListenerInterface& listener) const override;
-};
-
-
-/* Describes a device reset event, such as when a device is added,
- * reconfigured, or removed. */
-struct NotifyDeviceResetArgs : public NotifyArgs {
- int32_t deviceId;
-
- inline NotifyDeviceResetArgs() { }
-
- NotifyDeviceResetArgs(int32_t id, nsecs_t eventTime, int32_t deviceId);
-
- NotifyDeviceResetArgs(const NotifyDeviceResetArgs& other);
-
- bool operator==(const NotifyDeviceResetArgs& rhs) const;
-
- virtual ~NotifyDeviceResetArgs() { }
-
- void notify(InputListenerInterface& listener) const override;
-};
-
-/* Describes a change in the state of Pointer Capture. */
-struct NotifyPointerCaptureChangedArgs : public NotifyArgs {
- // The sequence number of the Pointer Capture request, if enabled.
- PointerCaptureRequest request;
-
- inline NotifyPointerCaptureChangedArgs() {}
-
- NotifyPointerCaptureChangedArgs(int32_t id, nsecs_t eventTime, const PointerCaptureRequest&);
-
- NotifyPointerCaptureChangedArgs(const NotifyPointerCaptureChangedArgs& other);
-
- bool operator==(const NotifyPointerCaptureChangedArgs& rhs) const;
-
- virtual ~NotifyPointerCaptureChangedArgs() {}
-
- void notify(InputListenerInterface& listener) const override;
-};
-
-/* Describes a vibrator state event. */
-struct NotifyVibratorStateArgs : public NotifyArgs {
- int32_t deviceId;
- bool isOn;
-
- inline NotifyVibratorStateArgs() {}
-
- NotifyVibratorStateArgs(int32_t id, nsecs_t eventTIme, int32_t deviceId, bool isOn);
-
- NotifyVibratorStateArgs(const NotifyVibratorStateArgs& other);
-
- bool operator==(const NotifyVibratorStateArgs rhs) const;
-
- virtual ~NotifyVibratorStateArgs() {}
-
- void notify(InputListenerInterface& listener) const override;
-};
-
/*
* The interface used by the InputReader to notify the InputListener about input events.
*/
@@ -263,6 +43,8 @@
virtual void notifyVibratorState(const NotifyVibratorStateArgs* args) = 0;
virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) = 0;
virtual void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) = 0;
+
+ void notify(const NotifyArgs& args);
};
/*
@@ -287,7 +69,7 @@
private:
InputListenerInterface& mInnerListener;
- std::vector<std::unique_ptr<NotifyArgs>> mArgsQueue;
+ std::vector<NotifyArgs> mArgsQueue;
};
} // namespace android
diff --git a/services/inputflinger/include/NotifyArgs.h b/services/inputflinger/include/NotifyArgs.h
new file mode 100644
index 0000000..611b1aa
--- /dev/null
+++ b/services/inputflinger/include/NotifyArgs.h
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#pragma once
+
+#include <vector>
+
+#include <input/Input.h>
+#include <input/InputDevice.h>
+#include <input/TouchVideoFrame.h>
+
+namespace android {
+
+/* Describes a configuration change event. */
+struct NotifyConfigurationChangedArgs {
+ int32_t id;
+ nsecs_t eventTime;
+
+ inline NotifyConfigurationChangedArgs() {}
+
+ NotifyConfigurationChangedArgs(int32_t id, nsecs_t eventTime);
+
+ bool operator==(const NotifyConfigurationChangedArgs& rhs) const = default;
+
+ NotifyConfigurationChangedArgs(const NotifyConfigurationChangedArgs& other) = default;
+};
+
+/* Describes a key event. */
+struct NotifyKeyArgs {
+ int32_t id;
+ nsecs_t eventTime;
+
+ int32_t deviceId;
+ uint32_t source;
+ int32_t displayId;
+ uint32_t policyFlags;
+ int32_t action;
+ int32_t flags;
+ int32_t keyCode;
+ int32_t scanCode;
+ int32_t metaState;
+ nsecs_t downTime;
+ nsecs_t readTime;
+
+ inline NotifyKeyArgs() {}
+
+ NotifyKeyArgs(int32_t id, nsecs_t eventTime, nsecs_t readTime, int32_t deviceId,
+ uint32_t source, int32_t displayId, uint32_t policyFlags, int32_t action,
+ int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState,
+ nsecs_t downTime);
+
+ bool operator==(const NotifyKeyArgs& rhs) const = default;
+
+ NotifyKeyArgs(const NotifyKeyArgs& other) = default;
+};
+
+/* Describes a motion event. */
+struct NotifyMotionArgs {
+ int32_t id;
+ nsecs_t eventTime;
+
+ int32_t deviceId;
+ uint32_t source;
+ int32_t displayId;
+ uint32_t policyFlags;
+ int32_t action;
+ int32_t actionButton;
+ int32_t flags;
+ int32_t metaState;
+ int32_t buttonState;
+ /**
+ * Classification of the current touch gesture
+ */
+ MotionClassification classification;
+ int32_t edgeFlags;
+
+ uint32_t pointerCount;
+ PointerProperties pointerProperties[MAX_POINTERS];
+ PointerCoords pointerCoords[MAX_POINTERS];
+ float xPrecision;
+ float yPrecision;
+ /**
+ * Mouse cursor position when this event is reported relative to the origin of the specified
+ * display. Only valid if this is a mouse event (originates from a mouse or from a trackpad in
+ * gestures enabled mode.
+ */
+ float xCursorPosition;
+ float yCursorPosition;
+ nsecs_t downTime;
+ nsecs_t readTime;
+ std::vector<TouchVideoFrame> videoFrames;
+
+ inline NotifyMotionArgs() {}
+
+ NotifyMotionArgs(int32_t id, nsecs_t eventTime, nsecs_t readTime, int32_t deviceId,
+ uint32_t source, int32_t displayId, uint32_t policyFlags, int32_t action,
+ int32_t actionButton, int32_t flags, int32_t metaState, int32_t buttonState,
+ MotionClassification classification, int32_t edgeFlags, uint32_t pointerCount,
+ const PointerProperties* pointerProperties, const PointerCoords* pointerCoords,
+ float xPrecision, float yPrecision, float xCursorPosition,
+ float yCursorPosition, nsecs_t downTime,
+ const std::vector<TouchVideoFrame>& videoFrames);
+
+ NotifyMotionArgs(const NotifyMotionArgs& other);
+
+ bool operator==(const NotifyMotionArgs& rhs) const;
+
+ std::string dump() const;
+};
+
+/* Describes a sensor event. */
+struct NotifySensorArgs {
+ int32_t id;
+ nsecs_t eventTime;
+
+ int32_t deviceId;
+ uint32_t source;
+ InputDeviceSensorType sensorType;
+ InputDeviceSensorAccuracy accuracy;
+ bool accuracyChanged;
+ nsecs_t hwTimestamp;
+ std::vector<float> values;
+
+ inline NotifySensorArgs() {}
+
+ NotifySensorArgs(int32_t id, nsecs_t eventTime, int32_t deviceId, uint32_t source,
+ InputDeviceSensorType sensorType, InputDeviceSensorAccuracy accuracy,
+ bool accuracyChanged, nsecs_t hwTimestamp, std::vector<float> values);
+
+ NotifySensorArgs(const NotifySensorArgs& other) = default;
+};
+
+/* Describes a switch event. */
+struct NotifySwitchArgs {
+ int32_t id;
+ nsecs_t eventTime;
+
+ uint32_t policyFlags;
+ uint32_t switchValues;
+ uint32_t switchMask;
+
+ inline NotifySwitchArgs() {}
+
+ NotifySwitchArgs(int32_t id, nsecs_t eventTime, uint32_t policyFlags, uint32_t switchValues,
+ uint32_t switchMask);
+
+ NotifySwitchArgs(const NotifySwitchArgs& other) = default;
+
+ bool operator==(const NotifySwitchArgs& rhs) const = default;
+};
+
+/* Describes a device reset event, such as when a device is added,
+ * reconfigured, or removed. */
+struct NotifyDeviceResetArgs {
+ int32_t id;
+ nsecs_t eventTime;
+
+ int32_t deviceId;
+
+ inline NotifyDeviceResetArgs() {}
+
+ NotifyDeviceResetArgs(int32_t id, nsecs_t eventTime, int32_t deviceId);
+
+ NotifyDeviceResetArgs(const NotifyDeviceResetArgs& other) = default;
+
+ bool operator==(const NotifyDeviceResetArgs& rhs) const = default;
+};
+
+/* Describes a change in the state of Pointer Capture. */
+struct NotifyPointerCaptureChangedArgs {
+ // The sequence number of the Pointer Capture request, if enabled.
+ int32_t id;
+ nsecs_t eventTime;
+
+ PointerCaptureRequest request;
+
+ inline NotifyPointerCaptureChangedArgs() {}
+
+ NotifyPointerCaptureChangedArgs(int32_t id, nsecs_t eventTime, const PointerCaptureRequest&);
+
+ NotifyPointerCaptureChangedArgs(const NotifyPointerCaptureChangedArgs& other) = default;
+};
+
+/* Describes a vibrator state event. */
+struct NotifyVibratorStateArgs {
+ int32_t id;
+ nsecs_t eventTime;
+
+ int32_t deviceId;
+ bool isOn;
+
+ inline NotifyVibratorStateArgs() {}
+
+ NotifyVibratorStateArgs(int32_t id, nsecs_t eventTIme, int32_t deviceId, bool isOn);
+
+ NotifyVibratorStateArgs(const NotifyVibratorStateArgs& other) = default;
+};
+
+using NotifyArgs = std::variant<NotifyConfigurationChangedArgs, NotifyKeyArgs, NotifyMotionArgs,
+ NotifySensorArgs, NotifySwitchArgs, NotifyDeviceResetArgs,
+ NotifyPointerCaptureChangedArgs, NotifyVibratorStateArgs>;
+
+} // namespace android
diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp
index 01146a3..0f87201 100644
--- a/services/inputflinger/reader/Android.bp
+++ b/services/inputflinger/reader/Android.bp
@@ -69,12 +69,12 @@
"libinput",
"liblog",
"libstatslog",
- "libui",
"libutils",
"libPlatformProperties",
],
static_libs: [
"libc++fs",
+ "libui-types",
],
header_libs: [
"libbatteryservice_headers",
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index c9d21dc..ca7e426 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -76,6 +76,8 @@
static constexpr int32_t FF_STRONG_MAGNITUDE_CHANNEL_IDX = 0;
static constexpr int32_t FF_WEAK_MAGNITUDE_CHANNEL_IDX = 1;
+static constexpr size_t EVENT_BUFFER_SIZE = 256;
+
// Mapping for input battery class node IDs lookup.
// https://www.kernel.org/doc/Documentation/power/power_supply_class.txt
static const std::unordered_map<std::string, InputBatteryClass> BATTERY_CLASSES =
@@ -117,7 +119,8 @@
{"brightness", InputLightClass::BRIGHTNESS},
{"multi_index", InputLightClass::MULTI_INDEX},
{"multi_intensity", InputLightClass::MULTI_INTENSITY},
- {"max_brightness", InputLightClass::MAX_BRIGHTNESS}};
+ {"max_brightness", InputLightClass::MAX_BRIGHTNESS},
+ {"kbd_backlight", InputLightClass::KEYBOARD_BACKLIGHT}};
// Mapping for input multicolor led class node names.
// https://www.kernel.org/doc/html/latest/leds/leds-class-multicolor.html
@@ -365,15 +368,26 @@
info.path = nodePath;
info.name = nodePath.filename();
info.maxBrightness = std::nullopt;
- size_t nameStart = info.name.rfind(":");
- if (nameStart != std::string::npos) {
- // Trim the name to color name
- info.name = info.name.substr(nameStart + 1);
- // Set InputLightClass flag for colors
- const auto it = LIGHT_CLASSES.find(info.name);
- if (it != LIGHT_CLASSES.end()) {
- info.flags |= it->second;
+
+ // Light name should follow the naming pattern <name>:<color>:<function>
+ // Refer kernel docs /leds/leds-class.html for valid supported LED names.
+ std::regex indexPattern("([a-zA-Z0-9_.:]*:)?([a-zA-Z0-9_.]*):([a-zA-Z0-9_.]*)");
+ std::smatch results;
+
+ if (std::regex_match(info.name, results, indexPattern)) {
+ // regex_match will return full match at index 0 and <name> at index 1. For RawLightInfo
+ // we only care about sections <color> and <function> which will be at index 2 and 3.
+ for (int i = 2; i <= 3; i++) {
+ const auto it = LIGHT_CLASSES.find(results.str(i));
+ if (it != LIGHT_CLASSES.end()) {
+ info.flags |= it->second;
+ }
}
+
+ // Set name of the raw light to <function> which represents playerIDs for LEDs that
+ // turn on/off based on the current player ID (Refer to PeripheralController.cpp for
+ // player ID logic)
+ info.name = results.str(3);
}
// Scan the path for all the files
// Refer to https://www.kernel.org/doc/Documentation/leds/leds-class.txt
@@ -1404,17 +1418,28 @@
}
const auto& path = *sysfsRootPathOpt;
- for (const auto& [id, dev] : mDevices) {
- if (dev->associatedDevice && dev->associatedDevice->sysfsRootPath == path) {
- return dev->associatedDevice;
- }
- }
- return std::make_shared<AssociatedDevice>(
+ std::shared_ptr<const AssociatedDevice> associatedDevice = std::make_shared<AssociatedDevice>(
AssociatedDevice{.sysfsRootPath = path,
.countryCode = readCountryCodeLocked(path),
.batteryInfos = readBatteryConfiguration(path),
.lightInfos = readLightsConfiguration(path)});
+
+ bool associatedDeviceChanged = false;
+ for (const auto& [id, dev] : mDevices) {
+ if (dev->associatedDevice && dev->associatedDevice->sysfsRootPath == path) {
+ if (*associatedDevice != *dev->associatedDevice) {
+ associatedDeviceChanged = true;
+ dev->associatedDevice = associatedDevice;
+ }
+ associatedDevice = dev->associatedDevice;
+ }
+ }
+ ALOGI_IF(associatedDeviceChanged,
+ "The AssociatedDevice changed for path '%s'. Using new AssociatedDevice: %s",
+ path.c_str(), associatedDevice->dump().c_str());
+
+ return associatedDevice;
}
void EventHub::vibrate(int32_t deviceId, const VibrationElement& element) {
@@ -1621,15 +1646,12 @@
return std::nullopt;
}
-size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
- ALOG_ASSERT(bufferSize >= 1);
-
+std::vector<RawEvent> EventHub::getEvents(int timeoutMillis) {
std::scoped_lock _l(mLock);
- struct input_event readBuffer[bufferSize];
+ std::array<input_event, EVENT_BUFFER_SIZE> readBuffer;
- RawEvent* event = buffer;
- size_t capacity = bufferSize;
+ std::vector<RawEvent> events;
bool awoken = false;
for (;;) {
nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
@@ -1649,15 +1671,17 @@
for (auto it = mClosingDevices.begin(); it != mClosingDevices.end();) {
std::unique_ptr<Device> device = std::move(*it);
ALOGV("Reporting device closed: id=%d, name=%s\n", device->id, device->path.c_str());
- event->when = now;
- event->deviceId = (device->id == mBuiltInKeyboardId)
+ const int32_t deviceId = (device->id == mBuiltInKeyboardId)
? ReservedInputDeviceId::BUILT_IN_KEYBOARD_ID
: device->id;
- event->type = DEVICE_REMOVED;
- event += 1;
+ events.push_back({
+ .when = now,
+ .deviceId = deviceId,
+ .type = DEVICE_REMOVED,
+ });
it = mClosingDevices.erase(it);
mNeedToSendFinishedDeviceScan = true;
- if (--capacity == 0) {
+ if (events.size() == EVENT_BUFFER_SIZE) {
break;
}
}
@@ -1672,10 +1696,12 @@
std::unique_ptr<Device> device = std::move(*mOpeningDevices.rbegin());
mOpeningDevices.pop_back();
ALOGV("Reporting device opened: id=%d, name=%s\n", device->id, device->path.c_str());
- event->when = now;
- event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
- event->type = DEVICE_ADDED;
- event += 1;
+ const int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
+ events.push_back({
+ .when = now,
+ .deviceId = deviceId,
+ .type = DEVICE_ADDED,
+ });
// Try to find a matching video device by comparing device names
for (auto it = mUnattachedVideoDevices.begin(); it != mUnattachedVideoDevices.end();
@@ -1693,17 +1719,18 @@
ALOGW("Device id %d exists, replaced.", device->id);
}
mNeedToSendFinishedDeviceScan = true;
- if (--capacity == 0) {
+ if (events.size() == EVENT_BUFFER_SIZE) {
break;
}
}
if (mNeedToSendFinishedDeviceScan) {
mNeedToSendFinishedDeviceScan = false;
- event->when = now;
- event->type = FINISHED_DEVICE_SCAN;
- event += 1;
- if (--capacity == 0) {
+ events.push_back({
+ .when = now,
+ .type = FINISHED_DEVICE_SCAN,
+ });
+ if (events.size() == EVENT_BUFFER_SIZE) {
break;
}
}
@@ -1767,12 +1794,13 @@
// This must be an input event
if (eventItem.events & EPOLLIN) {
int32_t readSize =
- read(device->fd, readBuffer, sizeof(struct input_event) * capacity);
+ read(device->fd, readBuffer.data(),
+ sizeof(decltype(readBuffer)::value_type) * readBuffer.size());
if (readSize == 0 || (readSize < 0 && errno == ENODEV)) {
// Device was removed before INotify noticed.
ALOGW("could not get event, removed? (fd: %d size: %" PRId32
- " bufferSize: %zu capacity: %zu errno: %d)\n",
- device->fd, readSize, bufferSize, capacity, errno);
+ " capacity: %zu errno: %d)\n",
+ device->fd, readSize, readBuffer.size(), errno);
deviceChanged = true;
closeDeviceLocked(*device);
} else if (readSize < 0) {
@@ -1782,21 +1810,21 @@
} else if ((readSize % sizeof(struct input_event)) != 0) {
ALOGE("could not get event (wrong size: %d)", readSize);
} else {
- int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
+ const int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
- size_t count = size_t(readSize) / sizeof(struct input_event);
+ const size_t count = size_t(readSize) / sizeof(struct input_event);
for (size_t i = 0; i < count; i++) {
struct input_event& iev = readBuffer[i];
- event->when = processEventTimestamp(iev);
- event->readTime = systemTime(SYSTEM_TIME_MONOTONIC);
- event->deviceId = deviceId;
- event->type = iev.type;
- event->code = iev.code;
- event->value = iev.value;
- event += 1;
- capacity -= 1;
+ events.push_back({
+ .when = processEventTimestamp(iev),
+ .readTime = systemTime(SYSTEM_TIME_MONOTONIC),
+ .deviceId = deviceId,
+ .type = iev.type,
+ .code = iev.code,
+ .value = iev.value,
+ });
}
- if (capacity == 0) {
+ if (events.size() >= EVENT_BUFFER_SIZE) {
// The result buffer is full. Reset the pending event index
// so we will try to read the device again on the next iteration.
mPendingEventIndex -= 1;
@@ -1832,7 +1860,7 @@
}
// Return now if we have collected any events or if we were explicitly awoken.
- if (event != buffer || awoken) {
+ if (!events.empty() || awoken) {
break;
}
@@ -1878,7 +1906,7 @@
}
// All done, return the number of events we read.
- return event - buffer;
+ return events;
}
std::vector<TouchVideoFrame> EventHub::getVideoFrames(int32_t deviceId) {
@@ -2633,4 +2661,9 @@
std::unique_lock<std::mutex> lock(mLock);
}
+std::string EventHub::AssociatedDevice::dump() const {
+ return StringPrintf("path=%s, numBatteries=%zu, numLight=%zu", sysfsRootPath.c_str(),
+ batteryInfos.size(), lightInfos.size());
+}
+
} // namespace android
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index 44a005e..6b9b9f1 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -234,6 +234,10 @@
}
void InputDevice::removeEventHubDevice(int32_t eventHubId) {
+ if (mController != nullptr && mController->getEventHubId() == eventHubId) {
+ // Delete mController, since the corresponding eventhub device is going away
+ mController = nullptr;
+ }
mDevices.erase(eventHubId);
}
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 4c38ce8..8650876 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -120,14 +120,14 @@
}
} // release lock
- size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
+ std::vector<RawEvent> events = mEventHub->getEvents(timeoutMillis);
{ // acquire lock
std::scoped_lock _l(mLock);
mReaderIsAliveCondition.notify_all();
- if (count) {
- processEventsLocked(mEventBuffer, count);
+ if (!events.empty()) {
+ processEventsLocked(events.data(), events.size());
}
if (mNextTimeout != LLONG_MAX) {
diff --git a/services/inputflinger/reader/controller/PeripheralController.cpp b/services/inputflinger/reader/controller/PeripheralController.cpp
index eaf5b51..cedbacb 100644
--- a/services/inputflinger/reader/controller/PeripheralController.cpp
+++ b/services/inputflinger/reader/controller/PeripheralController.cpp
@@ -16,6 +16,7 @@
#include <locale>
#include <regex>
+#include <set>
#include <ftl/enum.h>
@@ -70,7 +71,7 @@
// If the light node doesn't have max brightness, use the default max brightness.
int rawMaxBrightness = rawInfoOpt->maxBrightness.value_or(MAX_BRIGHTNESS);
- float ratio = MAX_BRIGHTNESS / rawMaxBrightness;
+ float ratio = static_cast<float>(MAX_BRIGHTNESS) / rawMaxBrightness;
// Scale the returned brightness in [0, rawMaxBrightness] to [0, 255]
if (rawMaxBrightness != MAX_BRIGHTNESS) {
brightness = brightness * ratio;
@@ -89,7 +90,7 @@
}
// If the light node doesn't have max brightness, use the default max brightness.
int rawMaxBrightness = rawInfo->maxBrightness.value_or(MAX_BRIGHTNESS);
- float ratio = MAX_BRIGHTNESS / rawMaxBrightness;
+ float ratio = static_cast<float>(MAX_BRIGHTNESS) / rawMaxBrightness;
// Scale the requested brightness in [0, 255] to [0, rawMaxBrightness]
if (rawMaxBrightness != MAX_BRIGHTNESS) {
brightness = ceil(brightness / ratio);
@@ -271,7 +272,8 @@
for (const auto& [lightId, light] : mLights) {
// Input device light doesn't support ordinal, always pass 1.
- InputDeviceLightInfo lightInfo(light->name, light->id, light->type, 1 /* ordinal */);
+ InputDeviceLightInfo lightInfo(light->name, light->id, light->type, light->capabilityFlags,
+ 1 /* ordinal */);
deviceInfo->addLightInfo(lightInfo);
}
}
@@ -284,6 +286,8 @@
dump += StringPrintf(INDENT4 "Id: %d", lightId);
dump += StringPrintf(INDENT4 "Name: %s", light->name.c_str());
dump += StringPrintf(INDENT4 "Type: %s", ftl::enum_string(light->type).c_str());
+ dump += StringPrintf(INDENT4 "Capability flags: %s",
+ light->capabilityFlags.string().c_str());
light->dump(dump);
}
}
@@ -363,6 +367,8 @@
std::unordered_map<LightColor, int32_t /* rawLightId */> rawRgbIds;
// Map from player Id to raw light Id
std::unordered_map<int32_t, int32_t> playerIdLightIds;
+ // Set of Keyboard backlights
+ std::set<int32_t> keyboardBacklightIds;
// Check raw lights
const std::vector<int32_t> rawLightIds = getDeviceContext().getRawLightIds();
@@ -391,6 +397,10 @@
}
}
}
+ // Check if this is a Keyboard backlight
+ if (rawInfo->flags.test(InputLightClass::KEYBOARD_BACKLIGHT)) {
+ keyboardBacklightIds.insert(rawId);
+ }
// Check if this is an LED of RGB light
if (rawInfo->flags.test(InputLightClass::RED)) {
hasRedLed = true;
@@ -431,8 +441,21 @@
ALOGD("Rgb light ids [%d, %d, %d] \n", rawRgbIds.at(LightColor::RED),
rawRgbIds.at(LightColor::GREEN), rawRgbIds.at(LightColor::BLUE));
}
+ bool isKeyboardBacklight = keyboardBacklightIds.find(rawRgbIds.at(LightColor::RED)) !=
+ keyboardBacklightIds.end() &&
+ keyboardBacklightIds.find(rawRgbIds.at(LightColor::GREEN)) !=
+ keyboardBacklightIds.end() &&
+ keyboardBacklightIds.find(rawRgbIds.at(LightColor::BLUE)) !=
+ keyboardBacklightIds.end() &&
+ (!rawGlobalId.has_value() ||
+ keyboardBacklightIds.find(rawGlobalId.value()) != keyboardBacklightIds.end());
+
std::unique_ptr<Light> light =
- std::make_unique<RgbLight>(getDeviceContext(), ++mNextId, rawRgbIds, rawGlobalId);
+ std::make_unique<RgbLight>(getDeviceContext(), ++mNextId,
+ isKeyboardBacklight
+ ? InputDeviceLightType::KEYBOARD_BACKLIGHT
+ : InputDeviceLightType::INPUT,
+ rawRgbIds, rawGlobalId);
mLights.insert_or_assign(light->id, std::move(light));
// Remove from raw light info as they've been composed a RBG light.
rawInfos.erase(rawRgbIds.at(LightColor::RED));
@@ -445,6 +468,10 @@
// Check the rest of raw light infos
for (const auto& [rawId, rawInfo] : rawInfos) {
+ InputDeviceLightType type = keyboardBacklightIds.find(rawId) != keyboardBacklightIds.end()
+ ? InputDeviceLightType::KEYBOARD_BACKLIGHT
+ : InputDeviceLightType::INPUT;
+
// If the node is multi-color led, construct a MULTI_COLOR light
if (rawInfo.flags.test(InputLightClass::MULTI_INDEX) &&
rawInfo.flags.test(InputLightClass::MULTI_INTENSITY)) {
@@ -453,7 +480,7 @@
}
std::unique_ptr<Light> light =
std::make_unique<MultiColorLight>(getDeviceContext(), rawInfo.name, ++mNextId,
- rawInfo.id);
+ type, rawInfo.id);
mLights.insert_or_assign(light->id, std::move(light));
continue;
}
@@ -462,7 +489,7 @@
ALOGD("Mono light Id %d name %s \n", rawInfo.id, rawInfo.name.c_str());
}
std::unique_ptr<Light> light = std::make_unique<MonoLight>(getDeviceContext(), rawInfo.name,
- ++mNextId, rawInfo.id);
+ ++mNextId, type, rawInfo.id);
mLights.insert_or_assign(light->id, std::move(light));
}
diff --git a/services/inputflinger/reader/controller/PeripheralController.h b/services/inputflinger/reader/controller/PeripheralController.h
index 25cf435..8ac42c3 100644
--- a/services/inputflinger/reader/controller/PeripheralController.h
+++ b/services/inputflinger/reader/controller/PeripheralController.h
@@ -67,6 +67,7 @@
std::string name;
int32_t id;
InputDeviceLightType type;
+ ftl::Flags<InputDeviceLightCapability> capabilityFlags;
virtual bool setLightColor(int32_t color) { return false; }
virtual std::optional<int32_t> getLightColor() { return std::nullopt; }
@@ -81,8 +82,10 @@
struct MonoLight : public Light {
explicit MonoLight(InputDeviceContext& context, const std::string& name, int32_t id,
- int32_t rawId)
- : Light(context, name, id, InputDeviceLightType::MONO), rawId(rawId) {}
+ InputDeviceLightType type, int32_t rawId)
+ : Light(context, name, id, type), rawId(rawId) {
+ capabilityFlags |= InputDeviceLightCapability::BRIGHTNESS;
+ }
int32_t rawId;
bool setLightColor(int32_t color) override;
@@ -91,15 +94,15 @@
};
struct RgbLight : public Light {
- explicit RgbLight(InputDeviceContext& context, int32_t id,
+ explicit RgbLight(InputDeviceContext& context, int32_t id, InputDeviceLightType type,
const std::unordered_map<LightColor, int32_t>& rawRgbIds,
std::optional<int32_t> rawGlobalId)
- : Light(context, "RGB", id, InputDeviceLightType::RGB),
- rawRgbIds(rawRgbIds),
- rawGlobalId(rawGlobalId) {
+ : Light(context, "RGB", id, type), rawRgbIds(rawRgbIds), rawGlobalId(rawGlobalId) {
brightness = rawGlobalId.has_value()
? getRawLightBrightness(rawGlobalId.value()).value_or(MAX_BRIGHTNESS)
: MAX_BRIGHTNESS;
+ capabilityFlags |= InputDeviceLightCapability::BRIGHTNESS;
+ capabilityFlags |= InputDeviceLightCapability::RGB;
}
// Map from color to raw light id.
std::unordered_map<LightColor, int32_t /* rawLightId */> rawRgbIds;
@@ -114,8 +117,11 @@
struct MultiColorLight : public Light {
explicit MultiColorLight(InputDeviceContext& context, const std::string& name, int32_t id,
- int32_t rawId)
- : Light(context, name, id, InputDeviceLightType::MULTI_COLOR), rawId(rawId) {}
+ InputDeviceLightType type, int32_t rawId)
+ : Light(context, name, id, type), rawId(rawId) {
+ capabilityFlags |= InputDeviceLightCapability::BRIGHTNESS;
+ capabilityFlags |= InputDeviceLightCapability::RGB;
+ }
int32_t rawId;
bool setLightColor(int32_t color) override;
@@ -131,7 +137,7 @@
// Map from player Id to raw light Id
std::unordered_map<int32_t, int32_t> rawLightIds;
- bool setLightPlayerId(int32_t palyerId) override;
+ bool setLightPlayerId(int32_t playerId) override;
std::optional<int32_t> getLightPlayerId() override;
void dump(std::string& dump) override;
};
diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h
index 5cf2214..6933ec7 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/reader/include/EventHub.h
@@ -174,6 +174,8 @@
MULTI_INTENSITY = 0x00000040,
/* The input light has max brightness node. */
MAX_BRIGHTNESS = 0x00000080,
+ /* The input light has kbd_backlight name */
+ KEYBOARD_BACKLIGHT = 0x00000100,
};
enum class InputBatteryClass : uint32_t {
@@ -193,6 +195,9 @@
ftl::Flags<InputLightClass> flags;
std::array<int32_t, COLOR_NUM> rgbIndex;
std::filesystem::path path;
+
+ bool operator==(const RawLightInfo&) const = default;
+ bool operator!=(const RawLightInfo&) const = default;
};
/* Describes a raw battery. */
@@ -201,6 +206,9 @@
std::string name;
ftl::Flags<InputBatteryClass> flags;
std::filesystem::path path;
+
+ bool operator==(const RawBatteryInfo&) const = default;
+ bool operator!=(const RawBatteryInfo&) const = default;
};
/*
@@ -280,7 +288,7 @@
*
* Returns the number of events obtained, or 0 if the timeout expired.
*/
- virtual size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) = 0;
+ virtual std::vector<RawEvent> getEvents(int timeoutMillis) = 0;
virtual std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) = 0;
virtual base::Result<std::pair<InputDeviceSensorType, int32_t>> mapSensor(
int32_t deviceId, int32_t absCode) const = 0;
@@ -498,7 +506,7 @@
bool markSupportedKeyCodes(int32_t deviceId, const std::vector<int32_t>& keyCodes,
uint8_t* outFlags) const override final;
- size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) override final;
+ std::vector<RawEvent> getEvents(int timeoutMillis) override final;
std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) override final;
bool hasScanCode(int32_t deviceId, int32_t scanCode) const override final;
@@ -549,6 +557,10 @@
hardware::input::InputDeviceCountryCode countryCode;
std::unordered_map<int32_t /*batteryId*/, RawBatteryInfo> batteryInfos;
std::unordered_map<int32_t /*lightId*/, RawLightInfo> lightInfos;
+
+ bool operator==(const AssociatedDevice&) const = default;
+ bool operator!=(const AssociatedDevice&) const = default;
+ std::string dump() const;
};
struct Device {
@@ -582,7 +594,7 @@
// A shared_ptr of a device associated with the input device.
// The input devices that have the same sysfs path have the same associated device.
- const std::shared_ptr<const AssociatedDevice> associatedDevice;
+ std::shared_ptr<const AssociatedDevice> associatedDevice;
int32_t controllerNumber;
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index fbce87f..012d43f 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -170,10 +170,6 @@
InputReaderConfiguration mConfig GUARDED_BY(mLock);
- // The event queue.
- static const int EVENT_BUFFER_SIZE = 256;
- RawEvent mEventBuffer[EVENT_BUFFER_SIZE] GUARDED_BY(mLock);
-
// 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
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index 8c241f2..4cd2cce 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -1950,7 +1950,8 @@
mCurrentCookedState.cookedPointerData.pointerProperties,
mCurrentCookedState.cookedPointerData.pointerCoords,
mCurrentCookedState.cookedPointerData.idToIndex, currentIdBits, -1,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+ mOrientedXPrecision, mOrientedYPrecision, mDownTime,
+ MotionClassification::NONE);
mCurrentMotionAborted = true;
}
}
@@ -1970,7 +1971,8 @@
mCurrentCookedState.cookedPointerData.pointerProperties,
mCurrentCookedState.cookedPointerData.pointerCoords,
mCurrentCookedState.cookedPointerData.idToIndex, currentIdBits, -1,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+ mOrientedXPrecision, mOrientedYPrecision, mDownTime,
+ MotionClassification::NONE);
}
} else {
// There may be pointers going up and pointers going down and pointers moving
@@ -2005,7 +2007,8 @@
mLastCookedState.cookedPointerData.pointerProperties,
mLastCookedState.cookedPointerData.pointerCoords,
mLastCookedState.cookedPointerData.idToIndex, dispatchedIdBits, upId,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+ mOrientedXPrecision, mOrientedYPrecision, mDownTime,
+ MotionClassification::NONE);
dispatchedIdBits.clearBit(upId);
mCurrentCookedState.cookedPointerData.canceledIdBits.clearBit(upId);
}
@@ -2020,7 +2023,8 @@
mCurrentCookedState.cookedPointerData.pointerProperties,
mCurrentCookedState.cookedPointerData.pointerCoords,
mCurrentCookedState.cookedPointerData.idToIndex, dispatchedIdBits, -1,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+ mOrientedXPrecision, mOrientedYPrecision, mDownTime,
+ MotionClassification::NONE);
}
// Dispatch pointer down events using the new pointer locations.
@@ -2038,7 +2042,8 @@
mCurrentCookedState.cookedPointerData.pointerProperties,
mCurrentCookedState.cookedPointerData.pointerCoords,
mCurrentCookedState.cookedPointerData.idToIndex, dispatchedIdBits,
- downId, mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+ downId, mOrientedXPrecision, mOrientedYPrecision, mDownTime,
+ MotionClassification::NONE);
}
}
}
@@ -2054,7 +2059,7 @@
mLastCookedState.cookedPointerData.pointerCoords,
mLastCookedState.cookedPointerData.idToIndex,
mLastCookedState.cookedPointerData.hoveringIdBits, -1, mOrientedXPrecision,
- mOrientedYPrecision, mDownTime);
+ mOrientedYPrecision, mDownTime, MotionClassification::NONE);
mSentHoverEnter = false;
}
}
@@ -2071,7 +2076,8 @@
mCurrentCookedState.cookedPointerData.pointerCoords,
mCurrentCookedState.cookedPointerData.idToIndex,
mCurrentCookedState.cookedPointerData.hoveringIdBits, -1,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+ mOrientedXPrecision, mOrientedYPrecision, mDownTime,
+ MotionClassification::NONE);
mSentHoverEnter = true;
}
@@ -2081,7 +2087,8 @@
mCurrentCookedState.cookedPointerData.pointerCoords,
mCurrentCookedState.cookedPointerData.idToIndex,
mCurrentCookedState.cookedPointerData.hoveringIdBits, -1,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+ mOrientedXPrecision, mOrientedYPrecision, mDownTime,
+ MotionClassification::NONE);
}
}
@@ -2098,7 +2105,8 @@
mCurrentCookedState.cookedPointerData.pointerProperties,
mCurrentCookedState.cookedPointerData.pointerCoords,
mCurrentCookedState.cookedPointerData.idToIndex, idBits, -1,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+ mOrientedXPrecision, mOrientedYPrecision, mDownTime,
+ MotionClassification::NONE);
}
}
@@ -2115,7 +2123,8 @@
mCurrentCookedState.cookedPointerData.pointerProperties,
mCurrentCookedState.cookedPointerData.pointerCoords,
mCurrentCookedState.cookedPointerData.idToIndex, idBits, -1,
- mOrientedXPrecision, mOrientedYPrecision, mDownTime);
+ mOrientedXPrecision, mOrientedYPrecision, mDownTime,
+ MotionClassification::NONE);
}
}
@@ -2502,6 +2511,10 @@
// Send events!
int32_t metaState = getContext()->getGlobalMetaState();
int32_t buttonState = mCurrentCookedState.buttonState;
+ const MotionClassification classification =
+ mPointerGesture.currentGestureMode == PointerGesture::Mode::SWIPE
+ ? MotionClassification::TWO_FINGER_SWIPE
+ : MotionClassification::NONE;
uint32_t flags = 0;
@@ -2542,7 +2555,7 @@
flags, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
mPointerGesture.lastGestureProperties, mPointerGesture.lastGestureCoords,
mPointerGesture.lastGestureIdToIndex, dispatchedGestureIdBits, -1, 0, 0,
- mPointerGesture.downTime);
+ mPointerGesture.downTime, classification);
dispatchedGestureIdBits.clear();
} else {
@@ -2561,7 +2574,7 @@
AMOTION_EVENT_EDGE_FLAG_NONE, mPointerGesture.lastGestureProperties,
mPointerGesture.lastGestureCoords,
mPointerGesture.lastGestureIdToIndex, dispatchedGestureIdBits, id, 0,
- 0, mPointerGesture.downTime);
+ 0, mPointerGesture.downTime, classification);
dispatchedGestureIdBits.clearBit(id);
}
@@ -2575,7 +2588,7 @@
mPointerGesture.currentGestureProperties,
mPointerGesture.currentGestureCoords,
mPointerGesture.currentGestureIdToIndex, dispatchedGestureIdBits, -1, 0, 0,
- mPointerGesture.downTime);
+ mPointerGesture.downTime, classification);
}
// Send motion events for all pointers that went down.
@@ -2595,7 +2608,7 @@
mPointerGesture.currentGestureProperties,
mPointerGesture.currentGestureCoords,
mPointerGesture.currentGestureIdToIndex, dispatchedGestureIdBits, id, 0,
- 0, mPointerGesture.downTime);
+ 0, mPointerGesture.downTime, classification);
}
}
@@ -2606,7 +2619,8 @@
mPointerGesture.currentGestureProperties,
mPointerGesture.currentGestureCoords,
mPointerGesture.currentGestureIdToIndex,
- mPointerGesture.currentGestureIdBits, -1, 0, 0, mPointerGesture.downTime);
+ mPointerGesture.currentGestureIdBits, -1, 0, 0, mPointerGesture.downTime,
+ MotionClassification::NONE);
} else if (dispatchedGestureIdBits.isEmpty() && !mPointerGesture.lastGestureIdBits.isEmpty()) {
// Synthesize a hover move event after all pointers go up to indicate that
// the pointer is hovering again even if the user is not currently touching
@@ -2653,6 +2667,10 @@
}
void TouchInputMapper::abortPointerGestures(nsecs_t when, nsecs_t readTime, uint32_t policyFlags) {
+ const MotionClassification classification =
+ mPointerGesture.lastGestureMode == PointerGesture::Mode::SWIPE
+ ? MotionClassification::TWO_FINGER_SWIPE
+ : MotionClassification::NONE;
// Cancel previously dispatches pointers.
if (!mPointerGesture.lastGestureIdBits.isEmpty()) {
int32_t metaState = getContext()->getGlobalMetaState();
@@ -2661,7 +2679,7 @@
metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
mPointerGesture.lastGestureProperties, mPointerGesture.lastGestureCoords,
mPointerGesture.lastGestureIdToIndex, mPointerGesture.lastGestureIdBits, -1,
- 0, 0, mPointerGesture.downTime);
+ 0, 0, mPointerGesture.downTime, classification);
}
// Reset the current pointer gesture.
@@ -3611,7 +3629,8 @@
int32_t edgeFlags, const PointerProperties* properties,
const PointerCoords* coords, const uint32_t* idToIndex,
BitSet32 idBits, int32_t changedId, float xPrecision,
- float yPrecision, nsecs_t downTime) {
+ float yPrecision, nsecs_t downTime,
+ MotionClassification classification) {
PointerCoords pointerCoords[MAX_POINTERS];
PointerProperties pointerProperties[MAX_POINTERS];
uint32_t pointerCount = 0;
@@ -3659,9 +3678,9 @@
[this](TouchVideoFrame& frame) { frame.rotate(this->mInputDeviceOrientation); });
NotifyMotionArgs args(getContext()->getNextId(), when, readTime, deviceId, source, displayId,
policyFlags, action, actionButton, flags, metaState, buttonState,
- MotionClassification::NONE, edgeFlags, pointerCount, pointerProperties,
- pointerCoords, xPrecision, yPrecision, xCursorPosition, yCursorPosition,
- downTime, std::move(frames));
+ classification, edgeFlags, pointerCount, pointerProperties, pointerCoords,
+ xPrecision, yPrecision, xCursorPosition, yCursorPosition, downTime,
+ std::move(frames));
getListener().notifyMotion(&args);
}
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h
index bd4cff6..31806e1 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -779,7 +779,8 @@
int32_t action, int32_t actionButton, int32_t flags, int32_t metaState,
int32_t buttonState, int32_t edgeFlags, const PointerProperties* properties,
const PointerCoords* coords, const uint32_t* idToIndex, BitSet32 idBits,
- int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime);
+ int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime,
+ MotionClassification classification);
// Updates pointer coords and properties for pointers with specified ids that have moved.
// Returns true if any of them changed.
diff --git a/services/inputflinger/tests/EventHub_test.cpp b/services/inputflinger/tests/EventHub_test.cpp
index 6ef6e44..9380c71 100644
--- a/services/inputflinger/tests/EventHub_test.cpp
+++ b/services/inputflinger/tests/EventHub_test.cpp
@@ -99,8 +99,6 @@
};
std::vector<RawEvent> EventHubTest::getEvents(std::optional<size_t> expectedEvents) {
- static constexpr size_t EVENT_BUFFER_SIZE = 256;
- std::array<RawEvent, EVENT_BUFFER_SIZE> eventBuffer;
std::vector<RawEvent> events;
while (true) {
@@ -108,12 +106,12 @@
if (expectedEvents) {
timeout = 2s;
}
- const size_t count =
- mEventHub->getEvents(timeout.count(), eventBuffer.data(), eventBuffer.size());
- if (count == 0) {
+
+ std::vector<RawEvent> newEvents = mEventHub->getEvents(timeout.count());
+ if (newEvents.empty()) {
break;
}
- events.insert(events.end(), eventBuffer.begin(), eventBuffer.begin() + count);
+ events.insert(events.end(), newEvents.begin(), newEvents.end());
if (expectedEvents && events.size() >= *expectedEvents) {
break;
}
diff --git a/services/inputflinger/tests/InputFlingerService_test.cpp b/services/inputflinger/tests/InputFlingerService_test.cpp
index 22ae894..ca548be 100644
--- a/services/inputflinger/tests/InputFlingerService_test.cpp
+++ b/services/inputflinger/tests/InputFlingerService_test.cpp
@@ -33,8 +33,6 @@
#include <inttypes.h>
#include <linux/uinput.h>
#include <log/log.h>
-#include <ui/Rect.h>
-#include <ui/Region.h>
#include <chrono>
#include <thread>
#include <unordered_map>
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index ee6993c..78ea692 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -826,15 +826,14 @@
mExcludedDevices = devices;
}
- size_t getEvents(int, RawEvent* buffer, size_t bufferSize) override {
+ std::vector<RawEvent> getEvents(int) override {
std::scoped_lock lock(mLock);
- const size_t filledSize = std::min(mEvents.size(), bufferSize);
- std::copy(mEvents.begin(), mEvents.begin() + filledSize, buffer);
+ std::vector<RawEvent> buffer;
+ std::swap(buffer, mEvents);
- mEvents.erase(mEvents.begin(), mEvents.begin() + filledSize);
mEventsCondition.notify_all();
- return filledSize;
+ return buffer;
}
std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) override {
@@ -2972,6 +2971,21 @@
ASSERT_EQ(DISPLAY_UNIQUE_ID, mDevice->getAssociatedDisplayUniqueId());
}
+/**
+ * This test reproduces a crash caused by a dangling reference that remains after device is added
+ * and removed. The reference is accessed in InputDevice::dump(..);
+ */
+TEST_F(InputDeviceTest, DumpDoesNotCrash) {
+ constexpr int32_t TEST_EVENTHUB_ID = 10;
+ mFakeEventHub->addDevice(TEST_EVENTHUB_ID, "Test EventHub device", InputDeviceClass::BATTERY);
+
+ InputDevice device(mReader->getContext(), 1 /*id*/, 2 /*generation*/, {} /*identifier*/);
+ device.addEventHubDevice(TEST_EVENTHUB_ID, true /*populateMappers*/);
+ device.removeEventHubDevice(TEST_EVENTHUB_ID);
+ std::string dumpStr, eventHubDevStr;
+ device.dump(dumpStr, eventHubDevStr);
+}
+
// --- InputMapperTest ---
class InputMapperTest : public testing::Test {
@@ -9751,6 +9765,7 @@
ASSERT_EQ(1U, motionArgs.pointerCount);
ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
+ ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
ASSERT_NO_FATAL_FAILURE(
assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
@@ -9772,6 +9787,7 @@
ASSERT_EQ(1U, motionArgs.pointerCount);
ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
+ ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 0,
movingDistance * mPointerMovementScale, 1, 0, 0, 0,
0, 0, 0, 0));
@@ -9809,6 +9825,7 @@
ASSERT_EQ(1U, motionArgs.pointerCount);
ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
+ ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
ASSERT_NO_FATAL_FAILURE(
assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
@@ -9830,6 +9847,7 @@
ASSERT_EQ(1U, motionArgs.pointerCount);
ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
+ ASSERT_EQ(MotionClassification::TWO_FINGER_SWIPE, motionArgs.classification);
// New coordinate is the scaled relative coordinate from the initial coordinate.
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 0,
movingDistance * mPointerMovementScale, 1, 0, 0, 0,
@@ -9863,6 +9881,7 @@
ASSERT_EQ(1U, motionArgs.pointerCount);
ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
+ ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
// One pointer for PRESS, and its coordinate is used as the origin for pointer coordinates.
ASSERT_NO_FATAL_FAILURE(
assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
@@ -9892,9 +9911,11 @@
ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
+ ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
ASSERT_EQ(2U, motionArgs.pointerCount);
ASSERT_EQ(AMOTION_EVENT_ACTION_POINTER_DOWN, motionArgs.action & AMOTION_EVENT_ACTION_MASK);
ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
+ ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
// Two pointers' scaled relative coordinates from their initial centroid.
// Initial y coordinates are 0 as y1 and y2 have the same value.
float cookedX1 = (x1 - x2) / 2 * mPointerXZoomScale;
@@ -9924,6 +9945,7 @@
ASSERT_EQ(2U, motionArgs.pointerCount);
ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
+ ASSERT_EQ(MotionClassification::NONE, motionArgs.classification);
ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], cookedX1,
movingDistance * 2 * mPointerMovementScale, 1, 0, 0,
0, 0, 0, 0, 0));
@@ -10099,7 +10121,7 @@
TEST_F(LightControllerTest, MonoLight) {
RawLightInfo infoMono = {.id = 1,
- .name = "Mono",
+ .name = "mono_light",
.maxBrightness = 255,
.flags = InputLightClass::BRIGHTNESS,
.path = ""};
@@ -10110,7 +10132,29 @@
controller.populateDeviceInfo(&info);
std::vector<InputDeviceLightInfo> lights = info.getLights();
ASSERT_EQ(1U, lights.size());
- ASSERT_EQ(InputDeviceLightType::MONO, lights[0].type);
+ ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
+ ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
+
+ ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_BRIGHTNESS));
+ ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_BRIGHTNESS);
+}
+
+TEST_F(LightControllerTest, MonoKeyboardBacklight) {
+ RawLightInfo infoMono = {.id = 1,
+ .name = "mono_keyboard_backlight",
+ .maxBrightness = 255,
+ .flags = InputLightClass::BRIGHTNESS |
+ InputLightClass::KEYBOARD_BACKLIGHT,
+ .path = ""};
+ mFakeEventHub->addRawLightInfo(infoMono.id, std::move(infoMono));
+
+ PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
+ InputDeviceInfo info;
+ controller.populateDeviceInfo(&info);
+ std::vector<InputDeviceLightInfo> lights = info.getLights();
+ ASSERT_EQ(1U, lights.size());
+ ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
+ ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_BRIGHTNESS));
ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_BRIGHTNESS);
@@ -10141,7 +10185,85 @@
controller.populateDeviceInfo(&info);
std::vector<InputDeviceLightInfo> lights = info.getLights();
ASSERT_EQ(1U, lights.size());
- ASSERT_EQ(InputDeviceLightType::RGB, lights[0].type);
+ ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
+ ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
+ ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
+
+ ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
+ ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
+}
+
+TEST_F(LightControllerTest, CorrectRGBKeyboardBacklight) {
+ RawLightInfo infoRed = {.id = 1,
+ .name = "red_keyboard_backlight",
+ .maxBrightness = 255,
+ .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED |
+ InputLightClass::KEYBOARD_BACKLIGHT,
+ .path = ""};
+ RawLightInfo infoGreen = {.id = 2,
+ .name = "green_keyboard_backlight",
+ .maxBrightness = 255,
+ .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN |
+ InputLightClass::KEYBOARD_BACKLIGHT,
+ .path = ""};
+ RawLightInfo infoBlue = {.id = 3,
+ .name = "blue_keyboard_backlight",
+ .maxBrightness = 255,
+ .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE |
+ InputLightClass::KEYBOARD_BACKLIGHT,
+ .path = ""};
+ mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
+ mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
+ mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
+
+ PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
+ InputDeviceInfo info;
+ controller.populateDeviceInfo(&info);
+ std::vector<InputDeviceLightInfo> lights = info.getLights();
+ ASSERT_EQ(1U, lights.size());
+ ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
+ ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
+ ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
+
+ ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
+ ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
+}
+
+TEST_F(LightControllerTest, IncorrectRGBKeyboardBacklight) {
+ RawLightInfo infoRed = {.id = 1,
+ .name = "red",
+ .maxBrightness = 255,
+ .flags = InputLightClass::BRIGHTNESS | InputLightClass::RED,
+ .path = ""};
+ RawLightInfo infoGreen = {.id = 2,
+ .name = "green",
+ .maxBrightness = 255,
+ .flags = InputLightClass::BRIGHTNESS | InputLightClass::GREEN,
+ .path = ""};
+ RawLightInfo infoBlue = {.id = 3,
+ .name = "blue",
+ .maxBrightness = 255,
+ .flags = InputLightClass::BRIGHTNESS | InputLightClass::BLUE,
+ .path = ""};
+ RawLightInfo infoGlobal = {.id = 3,
+ .name = "global_keyboard_backlight",
+ .maxBrightness = 255,
+ .flags = InputLightClass::BRIGHTNESS | InputLightClass::GLOBAL |
+ InputLightClass::KEYBOARD_BACKLIGHT,
+ .path = ""};
+ mFakeEventHub->addRawLightInfo(infoRed.id, std::move(infoRed));
+ mFakeEventHub->addRawLightInfo(infoGreen.id, std::move(infoGreen));
+ mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoBlue));
+ mFakeEventHub->addRawLightInfo(infoBlue.id, std::move(infoGlobal));
+
+ PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
+ InputDeviceInfo info;
+ controller.populateDeviceInfo(&info);
+ std::vector<InputDeviceLightInfo> lights = info.getLights();
+ ASSERT_EQ(1U, lights.size());
+ ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
+ ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
+ ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
@@ -10149,7 +10271,7 @@
TEST_F(LightControllerTest, MultiColorRGBLight) {
RawLightInfo infoColor = {.id = 1,
- .name = "red",
+ .name = "multi_color",
.maxBrightness = 255,
.flags = InputLightClass::BRIGHTNESS |
InputLightClass::MULTI_INTENSITY |
@@ -10163,7 +10285,34 @@
controller.populateDeviceInfo(&info);
std::vector<InputDeviceLightInfo> lights = info.getLights();
ASSERT_EQ(1U, lights.size());
- ASSERT_EQ(InputDeviceLightType::MULTI_COLOR, lights[0].type);
+ ASSERT_EQ(InputDeviceLightType::INPUT, lights[0].type);
+ ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
+ ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
+
+ ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
+ ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
+}
+
+TEST_F(LightControllerTest, MultiColorRGBKeyboardBacklight) {
+ RawLightInfo infoColor = {.id = 1,
+ .name = "multi_color_keyboard_backlight",
+ .maxBrightness = 255,
+ .flags = InputLightClass::BRIGHTNESS |
+ InputLightClass::MULTI_INTENSITY |
+ InputLightClass::MULTI_INDEX |
+ InputLightClass::KEYBOARD_BACKLIGHT,
+ .path = ""};
+
+ mFakeEventHub->addRawLightInfo(infoColor.id, std::move(infoColor));
+
+ PeripheralController& controller = addControllerAndConfigure<PeripheralController>();
+ InputDeviceInfo info;
+ controller.populateDeviceInfo(&info);
+ std::vector<InputDeviceLightInfo> lights = info.getLights();
+ ASSERT_EQ(1U, lights.size());
+ ASSERT_EQ(InputDeviceLightType::KEYBOARD_BACKLIGHT, lights[0].type);
+ ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
+ ASSERT_TRUE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
ASSERT_TRUE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
ASSERT_EQ(controller.getLightColor(lights[0].id).value_or(-1), LIGHT_COLOR);
@@ -10201,6 +10350,8 @@
std::vector<InputDeviceLightInfo> lights = info.getLights();
ASSERT_EQ(1U, lights.size());
ASSERT_EQ(InputDeviceLightType::PLAYER_ID, lights[0].type);
+ ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::BRIGHTNESS));
+ ASSERT_FALSE(lights[0].capabilityFlags.test(InputDeviceLightCapability::RGB));
ASSERT_FALSE(controller.setLightColor(lights[0].id, LIGHT_COLOR));
ASSERT_TRUE(controller.setLightPlayerId(lights[0].id, LIGHT_PLAYER_ID));
diff --git a/services/inputflinger/tests/fuzzers/Android.bp b/services/inputflinger/tests/fuzzers/Android.bp
index f4ecba2..55c2db6 100644
--- a/services/inputflinger/tests/fuzzers/Android.bp
+++ b/services/inputflinger/tests/fuzzers/Android.bp
@@ -21,7 +21,6 @@
default_applicable_licenses: ["frameworks_native_license"],
}
-
cc_fuzz {
name: "inputflinger_latencytracker_fuzzer",
defaults: [
@@ -34,7 +33,6 @@
"libbase",
"libbinder",
"liblog",
- "libui",
"libutils",
"libinput",
"libinputflinger",
@@ -43,7 +41,7 @@
"LatencyTrackerFuzzer.cpp",
],
fuzz_config: {
- cc: ["android-framework-input@google.com"],
+ cc: ["android-framework-input@google.com"],
},
}
@@ -63,7 +61,6 @@
"libcutils",
"liblog",
"libutils",
- "libui",
"libinput",
"libinputflinger",
"libinputreader",
@@ -75,7 +72,7 @@
"libinputreader_headers",
],
fuzz_config: {
- cc: ["android-framework-input@google.com"],
+ cc: ["android-framework-input@google.com"],
},
}
diff --git a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp
index f5bd297..a9f5a3a 100644
--- a/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/InputReaderFuzzer.cpp
@@ -169,7 +169,6 @@
std::shared_ptr<FuzzEventHub> fuzzEventHub = std::make_shared<FuzzEventHub>(fdp);
std::unique_ptr<FuzzInputReader> reader =
std::make_unique<FuzzInputReader>(fuzzEventHub, fuzzPolicy, fuzzListener);
- fuzzEventHub->addEvents(fdp);
size_t patternCount = fdp->ConsumeIntegralInRange<size_t>(1, 260);
VibrationSequence pattern(patternCount);
for (size_t i = 0; i < patternCount; ++i) {
diff --git a/services/inputflinger/tests/fuzzers/MapperHelpers.h b/services/inputflinger/tests/fuzzers/MapperHelpers.h
index 53a7b16..03c2266 100644
--- a/services/inputflinger/tests/fuzzers/MapperHelpers.h
+++ b/services/inputflinger/tests/fuzzers/MapperHelpers.h
@@ -114,30 +114,12 @@
InputDeviceIdentifier mIdentifier;
std::vector<TouchVideoFrame> mVideoFrames;
PropertyMap mFuzzConfig;
- size_t mCount = 0;
- std::array<RawEvent, kMaxSize> mBuf;
std::shared_ptr<FuzzedDataProvider> mFdp;
public:
FuzzEventHub(std::shared_ptr<FuzzedDataProvider> fdp) : mFdp(std::move(fdp)) {}
~FuzzEventHub() {}
void addProperty(std::string key, std::string value) { mFuzzConfig.addProperty(key, value); }
- void addEvents(std::shared_ptr<FuzzedDataProvider> fdp) {
- mCount = fdp->ConsumeIntegralInRange<size_t>(0, kMaxSize);
-
- for (size_t i = 0; i < mCount; ++i) {
- int32_t type = fdp->ConsumeBool() ? fdp->PickValueInArray(kValidTypes)
- : fdp->ConsumeIntegral<int32_t>();
- int32_t code = fdp->ConsumeBool() ? fdp->PickValueInArray(kValidCodes)
- : fdp->ConsumeIntegral<int32_t>();
- mBuf[i] = {fdp->ConsumeIntegral<nsecs_t>(),
- fdp->ConsumeIntegral<nsecs_t>(),
- fdp->ConsumeIntegral<int32_t>(),
- type,
- code,
- fdp->ConsumeIntegral<int32_t>()};
- }
- }
ftl::Flags<InputDeviceClass> getDeviceClasses(int32_t deviceId) const override {
return ftl::Flags<InputDeviceClass>(mFdp->ConsumeIntegral<uint32_t>());
@@ -168,10 +150,24 @@
return mFdp->ConsumeIntegral<status_t>();
}
void setExcludedDevices(const std::vector<std::string>& devices) override {}
- size_t getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) override {
- for (size_t i = 0; i < mCount; ++i) buffer[i] = mBuf[i];
-
- return mCount;
+ std::vector<RawEvent> getEvents(int timeoutMillis) override {
+ std::vector<RawEvent> events;
+ const size_t count = mFdp->ConsumeIntegralInRange<size_t>(0, kMaxSize);
+ for (size_t i = 0; i < count; ++i) {
+ int32_t type = mFdp->ConsumeBool() ? mFdp->PickValueInArray(kValidTypes)
+ : mFdp->ConsumeIntegral<int32_t>();
+ int32_t code = mFdp->ConsumeBool() ? mFdp->PickValueInArray(kValidCodes)
+ : mFdp->ConsumeIntegral<int32_t>();
+ events.push_back({
+ .when = mFdp->ConsumeIntegral<nsecs_t>(),
+ .readTime = mFdp->ConsumeIntegral<nsecs_t>(),
+ .deviceId = mFdp->ConsumeIntegral<int32_t>(),
+ .type = type,
+ .code = code,
+ .value = mFdp->ConsumeIntegral<int32_t>(),
+ });
+ }
+ return events;
}
std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) override { return mVideoFrames; }
diff --git a/services/stats/StatsAidl.cpp b/services/stats/StatsAidl.cpp
index 8d6a9bd..3de51a4 100644
--- a/services/stats/StatsAidl.cpp
+++ b/services/stats/StatsAidl.cpp
@@ -66,6 +66,61 @@
AStatsEvent_writeBool(event,
atomValue.get<VendorAtomValue::boolValue>());
break;
+ case VendorAtomValue::repeatedIntValue: {
+ const std::optional<std::vector<int>>& repeatedIntValue =
+ atomValue.get<VendorAtomValue::repeatedIntValue>();
+ AStatsEvent_writeInt32Array(event, repeatedIntValue->data(),
+ repeatedIntValue->size());
+ break;
+ }
+ case VendorAtomValue::repeatedLongValue: {
+ const std::optional<std::vector<int64_t>>& repeatedLongValue =
+ atomValue.get<VendorAtomValue::repeatedLongValue>();
+ AStatsEvent_writeInt64Array(event, repeatedLongValue->data(),
+ repeatedLongValue->size());
+ break;
+ }
+ case VendorAtomValue::repeatedFloatValue: {
+ const std::optional<std::vector<float>>& repeatedFloatValue =
+ atomValue.get<VendorAtomValue::repeatedFloatValue>();
+ AStatsEvent_writeFloatArray(event, repeatedFloatValue->data(),
+ repeatedFloatValue->size());
+ break;
+ }
+ case VendorAtomValue::repeatedStringValue: {
+ const std::optional<std::vector<std::optional<std::string>>>& repeatedStringValue =
+ atomValue.get<VendorAtomValue::repeatedStringValue>();
+ const std::vector<std::optional<std::string>>& repeatedStringVector =
+ *repeatedStringValue;
+ const char* cStringArray[repeatedStringVector.size()];
+
+ for (int i = 0; i < repeatedStringVector.size(); ++i) {
+ cStringArray[i] = repeatedStringVector[i]->c_str();
+ }
+
+ AStatsEvent_writeStringArray(event, cStringArray, repeatedStringVector.size());
+ break;
+ }
+ case VendorAtomValue::repeatedBoolValue: {
+ const std::optional<std::vector<bool>>& repeatedBoolValue =
+ atomValue.get<VendorAtomValue::repeatedBoolValue>();
+ const std::vector<bool>& repeatedBoolVector = *repeatedBoolValue;
+ bool boolArray[repeatedBoolValue->size()];
+
+ for (int i = 0; i < repeatedBoolVector.size(); ++i) {
+ boolArray[i] = repeatedBoolVector[i];
+ }
+
+ AStatsEvent_writeBoolArray(event, boolArray, repeatedBoolVector.size());
+ break;
+ }
+ case VendorAtomValue::byteArrayValue: {
+ const std::optional<std::vector<uint8_t>>& byteArrayValue =
+ atomValue.get<VendorAtomValue::byteArrayValue>();
+
+ AStatsEvent_writeByteArray(event, byteArrayValue->data(), byteArrayValue->size());
+ break;
+ }
}
}
AStatsEvent_build(event);
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h
index 3faa068..6832ae1 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h
@@ -18,9 +18,10 @@
#include <TimeStats/TimeStats.h>
#include <utils/Timers.h>
-
#include <memory>
+#include "Feature.h"
+
namespace android {
class HWComposer;
@@ -72,6 +73,8 @@
// TODO(b/121291683): These will become private/internal
virtual void preComposition(CompositionRefreshArgs&) = 0;
+ virtual FeatureFlags getFeatureFlags() const = 0;
+
// Debugging
virtual void dump(std::string&) const = 0;
};
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Feature.h
similarity index 66%
rename from services/surfaceflinger/BufferStateLayer.h
rename to services/surfaceflinger/CompositionEngine/include/compositionengine/Feature.h
index e53e1c1..ee8000a 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Feature.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright 2019 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.
@@ -16,13 +16,15 @@
#pragma once
-#include "Layer.h"
+#include <ftl/flags.h>
+#include <cstdint>
-namespace android {
+namespace android::compositionengine {
-class BufferStateLayer : public Layer {
-public:
- explicit BufferStateLayer(const LayerCreationArgs& args) : Layer(args){};
+enum class Feature : int32_t {
+ kSnapshotLayerMetadata = 1 << 0,
};
-} // namespace android
+using FeatureFlags = ftl::Flags<Feature>;
+
+} // namespace android::compositionengine
\ No newline at end of file
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
index a738da0..fe8cad5 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h
@@ -39,6 +39,10 @@
class Fence;
+namespace gui {
+struct LayerMetadata;
+}
+
namespace compositionengine {
struct LayerFECompositionState;
@@ -144,6 +148,8 @@
// Whether the layer should be rendered with rounded corners.
virtual bool hasRoundedCorners() const = 0;
virtual void setWasClientComposed(const sp<Fence>&) {}
+ virtual const gui::LayerMetadata* getMetadata() const = 0;
+ virtual const gui::LayerMetadata* getRelativeMetadata() const = 0;
};
// TODO(b/121291683): Specialize std::hash<> for sp<T> so these and others can
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h
index 0907926..dd4dbe9 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h
@@ -48,6 +48,8 @@
void preComposition(CompositionRefreshArgs&) override;
+ FeatureFlags getFeatureFlags() const override;
+
// Debugging
void dump(std::string&) const override;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h
index f953d0b..a48cc6f 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h
@@ -53,6 +53,8 @@
MOCK_METHOD1(preComposition, void(CompositionRefreshArgs&));
+ MOCK_CONST_METHOD0(getFeatureFlags, FeatureFlags());
+
MOCK_CONST_METHOD1(dump, void(std::string&));
};
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
index be0dbce..14922a4 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h
@@ -53,6 +53,8 @@
MOCK_CONST_METHOD0(getDebugName, const char*());
MOCK_CONST_METHOD0(getSequence, int32_t());
MOCK_CONST_METHOD0(hasRoundedCorners, bool());
+ MOCK_CONST_METHOD0(getMetadata, gui::LayerMetadata*());
+ MOCK_CONST_METHOD0(getRelativeMetadata, gui::LayerMetadata*());
};
} // namespace android::compositionengine::mock
diff --git a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
index 855507e..a4e1fff 100644
--- a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp
@@ -140,6 +140,10 @@
mNeedsAnotherUpdate = needsAnotherUpdate;
}
+FeatureFlags CompositionEngine::getFeatureFlags() const {
+ return {};
+}
+
void CompositionEngine::dump(std::string&) const {
// The base class has no state to dump, but derived classes might.
}
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
index d7704a8..9102139 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -70,6 +70,7 @@
MOCK_METHOD1(disconnectDisplay, void(HalDisplayId));
MOCK_CONST_METHOD1(hasDeviceComposition, bool(const std::optional<DisplayId>&));
MOCK_CONST_METHOD1(getPresentFence, sp<Fence>(HalDisplayId));
+ MOCK_METHOD(nsecs_t, getPresentTimestamp, (PhysicalDisplayId), (const, override));
MOCK_CONST_METHOD2(getLayerReleaseFence, sp<Fence>(HalDisplayId, HWC2::Layer*));
MOCK_METHOD3(setOutputBuffer,
status_t(HalVirtualDisplayId, const sp<Fence>&, const sp<GraphicBuffer>&));
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 029e449..f8115eb 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -192,17 +192,16 @@
}
void DisplayDevice::setActiveMode(DisplayModeId modeId, const display::DisplaySnapshot& snapshot) {
- const auto modeOpt = snapshot.displayModes().get(modeId);
- LOG_ALWAYS_FATAL_IF(!modeOpt, "Unknown mode");
+ const auto fpsOpt = snapshot.displayModes().get(modeId).transform(
+ [](const DisplayModePtr& mode) { return mode->getFps(); });
- mActiveMode = modeOpt->get();
- const Fps fps = mActiveMode->getFps();
+ LOG_ALWAYS_FATAL_IF(!fpsOpt, "Unknown mode");
+ const Fps fps = *fpsOpt;
ATRACE_INT(mActiveModeFPSTrace.c_str(), fps.getIntValue());
- if (mRefreshRateConfigs) {
- mRefreshRateConfigs->setActiveModeId(modeId);
- }
+ mRefreshRateConfigs->setActiveModeId(modeId);
+
if (mRefreshRateOverlay) {
mRefreshRateOverlay->changeRefreshRate(fps);
}
@@ -224,10 +223,6 @@
constraints, outTimeline);
}
-const DisplayModePtr& DisplayDevice::getActiveMode() const {
- return mActiveMode;
-}
-
nsecs_t DisplayDevice::getVsyncPeriodFromHWC() const {
const auto physicalId = getPhysicalId();
if (!mHwComposer.isConnected(physicalId)) {
@@ -240,17 +235,7 @@
return vsyncPeriod;
}
- return getActiveMode()->getFps().getPeriodNsecs();
-}
-
-nsecs_t DisplayDevice::getRefreshTimestamp() const {
- const nsecs_t now = systemTime(CLOCK_MONOTONIC);
- const auto vsyncPeriodNanos = getVsyncPeriodFromHWC();
- return now - ((now - mLastHwVsync) % vsyncPeriodNanos);
-}
-
-void DisplayDevice::onVsync(nsecs_t timestamp) {
- mLastHwVsync = timestamp;
+ return refreshRateConfigs().getActiveModePtr()->getVsyncPeriod();
}
ui::Dataspace DisplayDevice::getCompositionDataSpace() const {
@@ -312,8 +297,10 @@
}
void DisplayDevice::persistBrightness(bool needsComposite) {
- if (needsComposite && mStagedBrightness && mBrightness != *mStagedBrightness) {
- getCompositionDisplay()->setNextBrightness(*mStagedBrightness);
+ if (mStagedBrightness && mBrightness != *mStagedBrightness) {
+ if (needsComposite) {
+ getCompositionDisplay()->setNextBrightness(*mStagedBrightness);
+ }
mBrightness = *mStagedBrightness;
}
mStagedBrightness = std::nullopt;
@@ -449,7 +436,7 @@
mRefreshRateOverlay = std::make_unique<RefreshRateOverlay>(fpsRange, showSpinnner);
mRefreshRateOverlay->setLayerStack(getLayerStack());
mRefreshRateOverlay->setViewport(getSize());
- mRefreshRateOverlay->changeRefreshRate(getActiveMode()->getFps());
+ mRefreshRateOverlay->changeRefreshRate(getActiveMode().getFps());
}
bool DisplayDevice::onKernelTimerChanged(std::optional<DisplayModeId> desiredModeId,
@@ -490,7 +477,7 @@
}
// Check if we are already at the desired mode
- if (getActiveMode()->getId() == info.mode->getId()) {
+ if (refreshRateConfigs().getActiveModePtr()->getId() == info.mode->getId()) {
return false;
}
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index d79a6b5..510df81 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -189,8 +189,6 @@
/* ------------------------------------------------------------------------
* Display mode management.
*/
- const DisplayModePtr& getActiveMode() const;
-
struct ActiveModeInfo {
DisplayModePtr mode;
scheduler::DisplayModeEvent event = scheduler::DisplayModeEvent::None;
@@ -207,6 +205,10 @@
return mUpcomingActiveMode;
}
+ const DisplayMode& getActiveMode() const REQUIRES(kMainThreadContext) {
+ return mRefreshRateConfigs->getActiveMode();
+ }
+
// Precondition: DisplaySnapshot must contain a mode with DisplayModeId.
void setActiveMode(DisplayModeId, const display::DisplaySnapshot&) REQUIRES(kMainThreadContext);
@@ -226,14 +228,12 @@
}
// Enables an overlay to be displayed with the current refresh rate
- void enableRefreshRateOverlay(bool enable, bool showSpinner);
+ void enableRefreshRateOverlay(bool enable, bool showSpinner) REQUIRES(kMainThreadContext);
bool isRefreshRateOverlayEnabled() const { return mRefreshRateOverlay != nullptr; }
bool onKernelTimerChanged(std::optional<DisplayModeId>, bool timerExpired);
void animateRefreshRateOverlay();
- void onVsync(nsecs_t timestamp);
nsecs_t getVsyncPeriodFromHWC() const;
- nsecs_t getRefreshTimestamp() const;
status_t setRefreshRatePolicy(
const std::optional<scheduler::RefreshRateConfigs::Policy>& policy,
@@ -265,13 +265,11 @@
static ui::Transform::RotationFlags sPrimaryDisplayRotationFlags;
- // allow initial power mode as null.
+ // Allow nullopt as initial power mode.
std::optional<hardware::graphics::composer::hal::PowerMode> mPowerMode;
- DisplayModePtr mActiveMode;
- std::optional<float> mStagedBrightness = std::nullopt;
- float mBrightness = -1.f;
- std::atomic<nsecs_t> mLastHwVsync = 0;
+ std::optional<float> mStagedBrightness;
+ float mBrightness = -1.f;
// TODO(b/182939859): Remove special cases for primary display.
const bool mIsPrimary;
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 486eaf8..96399e2 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -70,7 +70,7 @@
struct ComposerCallback {
virtual void onComposerHalHotplug(hal::HWDisplayId, hal::Connection) = 0;
virtual void onComposerHalRefresh(hal::HWDisplayId) = 0;
- virtual void onComposerHalVsync(hal::HWDisplayId, int64_t timestamp,
+ virtual void onComposerHalVsync(hal::HWDisplayId, nsecs_t timestamp,
std::optional<hal::VsyncPeriodNanos>) = 0;
virtual void onComposerHalVsyncPeriodTimingChanged(hal::HWDisplayId,
const hal::VsyncPeriodChangeTimeline&) = 0;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 15d5041..0a4ad97 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -144,7 +144,7 @@
return mUpdateDeviceProductInfoOnHotplugReconnect;
}
-bool HWComposer::onVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp) {
+bool HWComposer::onVsync(hal::HWDisplayId hwcDisplayId, nsecs_t timestamp) {
const auto displayId = toPhysicalDisplayId(hwcDisplayId);
if (!displayId) {
LOG_HWC_DISPLAY_ERROR(hwcDisplayId, "Invalid HWC display");
@@ -160,13 +160,13 @@
// with the same timestamp when turning the display off and on. This
// is a bug in the HWC implementation, but filter the extra events
// out here so they don't cause havoc downstream.
- if (timestamp == displayData.lastHwVsync) {
+ if (timestamp == displayData.lastPresentTimestamp) {
ALOGW("Ignoring duplicate VSYNC event from HWC for display %s (t=%" PRId64 ")",
to_string(*displayId).c_str(), timestamp);
return false;
}
- displayData.lastHwVsync = timestamp;
+ displayData.lastPresentTimestamp = timestamp;
}
const auto tag = "HW_VSYNC_" + to_string(*displayId);
@@ -485,6 +485,11 @@
return mDisplayData.at(displayId).lastPresentFence;
}
+nsecs_t HWComposer::getPresentTimestamp(PhysicalDisplayId displayId) const {
+ RETURN_IF_INVALID_DISPLAY(displayId, 0);
+ return mDisplayData.at(displayId).lastPresentTimestamp;
+}
+
sp<Fence> HWComposer::getLayerReleaseFence(HalDisplayId displayId, HWC2::Layer* layer) const {
RETURN_IF_INVALID_DISPLAY(displayId, Fence::NO_FENCE);
const auto& displayFences = mDisplayData.at(displayId).releaseFences;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 92a8f30..6c43d8b 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -160,8 +160,9 @@
// reset state when a display is disconnected
virtual void disconnectDisplay(HalDisplayId) = 0;
- // get the present fence received from the last call to present.
+ // Get the present fence/timestamp received from the last call to present.
virtual sp<Fence> getPresentFence(HalDisplayId) const = 0;
+ virtual nsecs_t getPresentTimestamp(PhysicalDisplayId) const = 0;
// Get last release fence for the given layer
virtual sp<Fence> getLayerReleaseFence(HalDisplayId, HWC2::Layer*) const = 0;
@@ -214,7 +215,7 @@
// TODO(b/157555476): Remove when the framework has proper support for headless mode
virtual bool updatesDeviceProductInfoOnHotplugReconnect() const = 0;
- virtual bool onVsync(hal::HWDisplayId, int64_t timestamp) = 0;
+ virtual bool onVsync(hal::HWDisplayId, nsecs_t timestamp) = 0;
virtual void setVsyncEnabled(PhysicalDisplayId, hal::Vsync enabled) = 0;
virtual bool isConnected(PhysicalDisplayId) const = 0;
@@ -343,8 +344,9 @@
// reset state when a display is disconnected
void disconnectDisplay(HalDisplayId) override;
- // get the present fence received from the last call to present.
+ // Get the present fence/timestamp received from the last call to present.
sp<Fence> getPresentFence(HalDisplayId) const override;
+ nsecs_t getPresentTimestamp(PhysicalDisplayId) const override;
// Get last release fence for the given layer
sp<Fence> getLayerReleaseFence(HalDisplayId, HWC2::Layer*) const override;
@@ -387,7 +389,7 @@
bool updatesDeviceProductInfoOnHotplugReconnect() const override;
- bool onVsync(hal::HWDisplayId, int64_t timestamp) override;
+ bool onVsync(hal::HWDisplayId, nsecs_t timestamp) override;
void setVsyncEnabled(PhysicalDisplayId, hal::Vsync enabled) override;
bool isConnected(PhysicalDisplayId) const override;
@@ -456,7 +458,10 @@
struct DisplayData {
std::unique_ptr<HWC2::Display> hwcDisplay;
+
sp<Fence> lastPresentFence = Fence::NO_FENCE; // signals when the last set op retires
+ nsecs_t lastPresentTimestamp = 0;
+
std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
bool validateWasSkipped;
@@ -466,8 +471,6 @@
std::mutex vsyncEnabledLock;
hal::Vsync vsyncEnabled GUARDED_BY(vsyncEnabledLock) = hal::Vsync::DISABLE;
-
- nsecs_t lastHwVsync = 0;
};
std::optional<DisplayIdentificationInfo> onHotplugConnect(hal::HWDisplayId);
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 08b71c2..410e438 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -65,7 +65,6 @@
#include <mutex>
#include <sstream>
-#include "BufferStateLayer.h"
#include "DisplayDevice.h"
#include "DisplayHardware/HWComposer.h"
#include "FrameTimeline.h"
@@ -165,7 +164,6 @@
mLayerCreationFlags(args.flags),
mBorderEnabled(false),
mTextureName(args.textureName),
- mCompositionState{mFlinger->getCompositionEngine().createLayerFECompositionState()},
mHwcSlotGenerator(sp<HwcSlotGenerator>::make()) {
ALOGV("Creating Layer %s", getDebugName());
@@ -239,6 +237,12 @@
mPotentialCursor = args.flags & ISurfaceComposerClient::eCursorWindow;
mProtectedByApp = args.flags & ISurfaceComposerClient::eProtectedByApp;
mDrawingState.dataspace = ui::Dataspace::V0_SRGB;
+
+ mSnapshot->sequence = sequence;
+ mSnapshot->name = getDebugName();
+ mSnapshot->textureName = mTextureName;
+ mSnapshot->premultipliedAlpha = mPremultipliedAlpha;
+ mSnapshot->transform = {};
}
void Layer::onFirstRef() {
@@ -504,40 +508,40 @@
: Hwc2::IComposerClient::BlendMode::COVERAGE;
}
- auto* compositionState = editCompositionState();
- compositionState->outputFilter = getOutputFilter();
- compositionState->isVisible = isVisible();
- compositionState->isOpaque = opaque && !usesRoundedCorners && alpha == 1.f;
- compositionState->shadowRadius = mEffectiveShadowRadius;
+ auto* snapshot = editLayerSnapshot();
+ snapshot->outputFilter = getOutputFilter();
+ snapshot->isVisible = isVisible();
+ snapshot->isOpaque = opaque && !usesRoundedCorners && alpha == 1.f;
+ snapshot->shadowRadius = mEffectiveShadowRadius;
- compositionState->contentDirty = contentDirty;
+ snapshot->contentDirty = contentDirty;
contentDirty = false;
- compositionState->geomLayerBounds = mBounds;
- compositionState->geomLayerTransform = getTransform();
- compositionState->geomInverseLayerTransform = compositionState->geomLayerTransform.inverse();
- compositionState->transparentRegionHint = getActiveTransparentRegion(drawingState);
+ snapshot->geomLayerBounds = mBounds;
+ snapshot->geomLayerTransform = getTransform();
+ snapshot->geomInverseLayerTransform = snapshot->geomLayerTransform.inverse();
+ snapshot->transparentRegionHint = getActiveTransparentRegion(drawingState);
- compositionState->blendMode = static_cast<Hwc2::IComposerClient::BlendMode>(blendMode);
- compositionState->alpha = alpha;
- compositionState->backgroundBlurRadius = drawingState.backgroundBlurRadius;
- compositionState->blurRegions = drawingState.blurRegions;
- compositionState->stretchEffect = getStretchEffect();
+ snapshot->blendMode = static_cast<Hwc2::IComposerClient::BlendMode>(blendMode);
+ snapshot->alpha = alpha;
+ snapshot->backgroundBlurRadius = drawingState.backgroundBlurRadius;
+ snapshot->blurRegions = drawingState.blurRegions;
+ snapshot->stretchEffect = getStretchEffect();
}
void Layer::prepareGeometryCompositionState() {
const auto& drawingState{getDrawingState()};
- auto* compositionState = editCompositionState();
+ auto* snapshot = editLayerSnapshot();
- compositionState->geomBufferSize = getBufferSize(drawingState);
- compositionState->geomContentCrop = getBufferCrop();
- compositionState->geomCrop = getCrop(drawingState);
- compositionState->geomBufferTransform = getBufferTransform();
- compositionState->geomBufferUsesDisplayInverseTransform = getTransformToDisplayInverse();
- compositionState->geomUsesSourceCrop = usesSourceCrop();
- compositionState->isSecure = isSecure();
+ snapshot->geomBufferSize = getBufferSize(drawingState);
+ snapshot->geomContentCrop = getBufferCrop();
+ snapshot->geomCrop = getCrop(drawingState);
+ snapshot->geomBufferTransform = getBufferTransform();
+ snapshot->geomBufferUsesDisplayInverseTransform = getTransformToDisplayInverse();
+ snapshot->geomUsesSourceCrop = usesSourceCrop();
+ snapshot->isSecure = isSecure();
- compositionState->metadata.clear();
+ snapshot->metadata.clear();
const auto& supportedMetadata = mFlinger->getHwComposer().getSupportedLayerGenericMetadata();
for (const auto& [key, mandatory] : supportedMetadata) {
const auto& genericLayerMetadataCompatibilityMap =
@@ -553,45 +557,45 @@
continue;
}
- compositionState->metadata
- .emplace(key, compositionengine::GenericLayerMetadataEntry{mandatory, it->second});
+ snapshot->metadata.emplace(key,
+ compositionengine::GenericLayerMetadataEntry{mandatory,
+ it->second});
}
}
void Layer::preparePerFrameCompositionState() {
const auto& drawingState{getDrawingState()};
- auto* compositionState = editCompositionState();
+ auto* snapshot = editLayerSnapshot();
- compositionState->forceClientComposition = false;
+ snapshot->forceClientComposition = false;
- compositionState->isColorspaceAgnostic = isColorSpaceAgnostic();
- compositionState->dataspace = getDataSpace();
- compositionState->colorTransform = getColorTransform();
- compositionState->colorTransformIsIdentity = !hasColorTransform();
- compositionState->surfaceDamage = surfaceDamageRegion;
- compositionState->hasProtectedContent = isProtected();
- compositionState->dimmingEnabled = isDimmingEnabled();
+ snapshot->isColorspaceAgnostic = isColorSpaceAgnostic();
+ snapshot->dataspace = getDataSpace();
+ snapshot->colorTransform = getColorTransform();
+ snapshot->colorTransformIsIdentity = !hasColorTransform();
+ snapshot->surfaceDamage = surfaceDamageRegion;
+ snapshot->hasProtectedContent = isProtected();
+ snapshot->dimmingEnabled = isDimmingEnabled();
const bool usesRoundedCorners = hasRoundedCorners();
- compositionState->isOpaque =
- isOpaque(drawingState) && !usesRoundedCorners && getAlpha() == 1.0_hf;
+ snapshot->isOpaque = isOpaque(drawingState) && !usesRoundedCorners && getAlpha() == 1.0_hf;
// Force client composition for special cases known only to the front-end.
// Rounded corners no longer force client composition, since we may use a
// hole punch so that the layer will appear to have rounded corners.
if (isHdrY410() || drawShadows() || drawingState.blurRegions.size() > 0 ||
- compositionState->stretchEffect.hasEffect()) {
- compositionState->forceClientComposition = true;
+ snapshot->stretchEffect.hasEffect()) {
+ snapshot->forceClientComposition = true;
}
// If there are no visible region changes, we still need to update blur parameters.
- compositionState->blurRegions = drawingState.blurRegions;
- compositionState->backgroundBlurRadius = drawingState.backgroundBlurRadius;
+ snapshot->blurRegions = drawingState.blurRegions;
+ snapshot->backgroundBlurRadius = drawingState.backgroundBlurRadius;
// Layer framerate is used in caching decisions.
// Retrieve it from the scheduler which maintains an instance of LayerHistory, and store it in
// LayerFECompositionState where it would be visible to Flattener.
- compositionState->fps = mFlinger->getLayerFramerate(systemTime(), getSequence());
+ snapshot->fps = mFlinger->getLayerFramerate(systemTime(), getSequence());
if (hasBufferOrSidebandStream()) {
preparePerFrameBufferCompositionState();
@@ -602,41 +606,41 @@
void Layer::preparePerFrameBufferCompositionState() {
// Sideband layers
- auto* compositionState = editCompositionState();
- if (compositionState->sidebandStream.get() && !compositionState->sidebandStreamHasFrame) {
- compositionState->compositionType =
+ auto* snapshot = editLayerSnapshot();
+ if (snapshot->sidebandStream.get() && !snapshot->sidebandStreamHasFrame) {
+ snapshot->compositionType =
aidl::android::hardware::graphics::composer3::Composition::SIDEBAND;
return;
} else if ((mDrawingState.flags & layer_state_t::eLayerIsDisplayDecoration) != 0) {
- compositionState->compositionType =
+ snapshot->compositionType =
aidl::android::hardware::graphics::composer3::Composition::DISPLAY_DECORATION;
} else {
// Normal buffer layers
- compositionState->hdrMetadata = mBufferInfo.mHdrMetadata;
- compositionState->compositionType = mPotentialCursor
+ snapshot->hdrMetadata = mBufferInfo.mHdrMetadata;
+ snapshot->compositionType = mPotentialCursor
? aidl::android::hardware::graphics::composer3::Composition::CURSOR
: aidl::android::hardware::graphics::composer3::Composition::DEVICE;
}
- compositionState->buffer = getBuffer();
- compositionState->bufferSlot = (mBufferInfo.mBufferSlot == BufferQueue::INVALID_BUFFER_SLOT)
+ snapshot->buffer = getBuffer();
+ snapshot->bufferSlot = (mBufferInfo.mBufferSlot == BufferQueue::INVALID_BUFFER_SLOT)
? 0
: mBufferInfo.mBufferSlot;
- compositionState->acquireFence = mBufferInfo.mFence;
- compositionState->frameNumber = mBufferInfo.mFrameNumber;
- compositionState->sidebandStreamHasFrame = false;
+ snapshot->acquireFence = mBufferInfo.mFence;
+ snapshot->frameNumber = mBufferInfo.mFrameNumber;
+ snapshot->sidebandStreamHasFrame = false;
}
void Layer::preparePerFrameEffectsCompositionState() {
- auto* compositionState = editCompositionState();
- compositionState->color = getColor();
- compositionState->compositionType =
+ auto* snapshot = editLayerSnapshot();
+ snapshot->color = getColor();
+ snapshot->compositionType =
aidl::android::hardware::graphics::composer3::Composition::SOLID_COLOR;
}
void Layer::prepareCursorCompositionState() {
const State& drawingState{getDrawingState()};
- auto* compositionState = editCompositionState();
+ auto* snapshot = editLayerSnapshot();
// Apply the layer's transform, followed by the display's global transform
// Here we're guaranteed that the layer's transform preserves rects
@@ -645,7 +649,7 @@
Rect bounds = reduce(win, getActiveTransparentRegion(drawingState));
Rect frame(getTransform().transform(bounds));
- compositionState->cursorFrame = frame;
+ snapshot->cursorFrame = frame;
}
sp<compositionengine::LayerFE> Layer::asLayerFE() const {
@@ -687,31 +691,30 @@
compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) const {
ATRACE_CALL();
- if (!getCompositionState()) {
+ const auto* snapshot = getLayerSnapshot();
+ if (!snapshot) {
return {};
}
- FloatRect bounds = getBounds();
- half alpha = getAlpha();
-
compositionengine::LayerFE::LayerSettings layerSettings;
- layerSettings.geometry.boundaries = bounds;
- layerSettings.geometry.positionTransform = getTransform().asMatrix4();
+ layerSettings.geometry.boundaries =
+ reduce(snapshot->geomLayerBounds, snapshot->transparentRegionHint);
+ layerSettings.geometry.positionTransform = snapshot->geomLayerTransform.asMatrix4();
// skip drawing content if the targetSettings indicate the content will be occluded
const bool drawContent = targetSettings.realContentIsVisible || targetSettings.clearContent;
layerSettings.skipContentDraw = !drawContent;
if (hasColorTransform()) {
- layerSettings.colorTransform = getColorTransform();
+ layerSettings.colorTransform = snapshot->colorTransform;
}
- const auto roundedCornerState = getRoundedCornerState();
+ const auto& roundedCornerState = snapshot->roundedCorner;
layerSettings.geometry.roundedCornersRadius = roundedCornerState.radius;
layerSettings.geometry.roundedCornersCrop = roundedCornerState.cropRect;
- layerSettings.alpha = alpha;
- layerSettings.sourceDataspace = getDataSpace();
+ layerSettings.alpha = snapshot->alpha;
+ layerSettings.sourceDataspace = snapshot->dataspace;
// Override the dataspace transfer from 170M to sRGB if the device configuration requests this.
// We do this here instead of in buffer info so that dumpsys can still report layers that are
@@ -728,26 +731,24 @@
layerSettings.whitePointNits = targetSettings.whitePointNits;
switch (targetSettings.blurSetting) {
case LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled:
- layerSettings.backgroundBlurRadius = getBackgroundBlurRadius();
- layerSettings.blurRegions = getBlurRegions();
- layerSettings.blurRegionTransform =
- getActiveTransform(getDrawingState()).inverse().asMatrix4();
+ layerSettings.backgroundBlurRadius = snapshot->backgroundBlurRadius;
+ layerSettings.blurRegions = snapshot->blurRegions;
+ layerSettings.blurRegionTransform = snapshot->geomInverseLayerTransform.asMatrix4();
break;
case LayerFE::ClientCompositionTargetSettings::BlurSetting::BackgroundBlurOnly:
- layerSettings.backgroundBlurRadius = getBackgroundBlurRadius();
+ layerSettings.backgroundBlurRadius = snapshot->backgroundBlurRadius;
break;
case LayerFE::ClientCompositionTargetSettings::BlurSetting::BlurRegionsOnly:
- layerSettings.blurRegions = getBlurRegions();
- layerSettings.blurRegionTransform =
- getActiveTransform(getDrawingState()).inverse().asMatrix4();
+ layerSettings.blurRegions = snapshot->blurRegions;
+ layerSettings.blurRegionTransform = snapshot->geomInverseLayerTransform.asMatrix4();
break;
case LayerFE::ClientCompositionTargetSettings::BlurSetting::Disabled:
default:
break;
}
- layerSettings.stretchEffect = getStretchEffect();
+ layerSettings.stretchEffect = snapshot->stretchEffect;
// Record the name of the layer for debugging further down the stack.
- layerSettings.name = getName();
+ layerSettings.name = snapshot->name;
if (hasEffect() && !hasBufferOrSidebandStream()) {
prepareEffectsClientComposition(layerSettings, targetSettings);
@@ -768,7 +769,7 @@
// If layer is blacked out, force alpha to 1 so that we draw a black color layer.
layerSettings.alpha = blackout ? 1.0f : 0.0f;
- layerSettings.name = getName();
+ layerSettings.name = getLayerSnapshot()->name;
}
void Layer::prepareEffectsClientComposition(
@@ -786,39 +787,41 @@
void Layer::prepareBufferStateClientComposition(
compositionengine::LayerFE::LayerSettings& layerSettings,
compositionengine::LayerFE::ClientCompositionTargetSettings& targetSettings) const {
- if (CC_UNLIKELY(!mBufferInfo.mBuffer)) {
- // For surfaceview of tv sideband, there is no activeBuffer
- // in bufferqueue, we need return LayerSettings.
+ ATRACE_CALL();
+ const auto* snapshot = getLayerSnapshot();
+ if (CC_UNLIKELY(!snapshot->externalTexture)) {
+ // If there is no buffer for the layer or we have sidebandstream where there is no
+ // activeBuffer, then we need to return LayerSettings.
return;
}
- const bool blackOutLayer = (isProtected() && !targetSettings.supportsProtectedContent) ||
- ((isSecure() || isProtected()) && !targetSettings.isSecure);
+ const bool blackOutLayer =
+ (snapshot->hasProtectedContent && !targetSettings.supportsProtectedContent) ||
+ ((snapshot->isSecure || snapshot->hasProtectedContent) && !targetSettings.isSecure);
const bool bufferCanBeUsedAsHwTexture =
- mBufferInfo.mBuffer->getUsage() & GraphicBuffer::USAGE_HW_TEXTURE;
+ snapshot->externalTexture->getUsage() & GraphicBuffer::USAGE_HW_TEXTURE;
if (blackOutLayer || !bufferCanBeUsedAsHwTexture) {
ALOGE_IF(!bufferCanBeUsedAsHwTexture, "%s is blacked out as buffer is not gpu readable",
- mName.c_str());
+ snapshot->name.c_str());
prepareClearClientComposition(layerSettings, true /* blackout */);
return;
}
- const State& s(getDrawingState());
- layerSettings.source.buffer.buffer = mBufferInfo.mBuffer;
- layerSettings.source.buffer.isOpaque = isOpaque(s);
- layerSettings.source.buffer.fence = mBufferInfo.mFence;
- layerSettings.source.buffer.textureName = mTextureName;
- layerSettings.source.buffer.usePremultipliedAlpha = getPremultipledAlpha();
- layerSettings.source.buffer.isY410BT2020 = isHdrY410();
- bool hasSmpte2086 = mBufferInfo.mHdrMetadata.validTypes & HdrMetadata::SMPTE2086;
- bool hasCta861_3 = mBufferInfo.mHdrMetadata.validTypes & HdrMetadata::CTA861_3;
+ layerSettings.source.buffer.buffer = snapshot->externalTexture;
+ layerSettings.source.buffer.isOpaque = snapshot->contentOpaque;
+ layerSettings.source.buffer.fence = snapshot->acquireFence;
+ layerSettings.source.buffer.textureName = snapshot->textureName;
+ layerSettings.source.buffer.usePremultipliedAlpha = snapshot->premultipliedAlpha;
+ layerSettings.source.buffer.isY410BT2020 = snapshot->isHdrY410;
+ bool hasSmpte2086 = snapshot->hdrMetadata.validTypes & HdrMetadata::SMPTE2086;
+ bool hasCta861_3 = snapshot->hdrMetadata.validTypes & HdrMetadata::CTA861_3;
float maxLuminance = 0.f;
if (hasSmpte2086 && hasCta861_3) {
- maxLuminance = std::min(mBufferInfo.mHdrMetadata.smpte2086.maxLuminance,
- mBufferInfo.mHdrMetadata.cta8613.maxContentLightLevel);
+ maxLuminance = std::min(snapshot->hdrMetadata.smpte2086.maxLuminance,
+ snapshot->hdrMetadata.cta8613.maxContentLightLevel);
} else if (hasSmpte2086) {
- maxLuminance = mBufferInfo.mHdrMetadata.smpte2086.maxLuminance;
+ maxLuminance = snapshot->hdrMetadata.smpte2086.maxLuminance;
} else if (hasCta861_3) {
- maxLuminance = mBufferInfo.mHdrMetadata.cta8613.maxContentLightLevel;
+ maxLuminance = snapshot->hdrMetadata.cta8613.maxContentLightLevel;
} else {
switch (layerSettings.sourceDataspace & HAL_DATASPACE_TRANSFER_MASK) {
case HAL_DATASPACE_TRANSFER_ST2084:
@@ -829,17 +832,17 @@
}
}
layerSettings.source.buffer.maxLuminanceNits = maxLuminance;
- layerSettings.frameNumber = mCurrentFrameNumber;
- layerSettings.bufferId = mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getId() : 0;
+ layerSettings.frameNumber = snapshot->frameNumber;
+ layerSettings.bufferId = snapshot->externalTexture->getId();
- const bool useFiltering =
- targetSettings.needsFiltering || mNeedsFiltering || bufferNeedsFiltering();
+ const bool useFiltering = targetSettings.needsFiltering ||
+ snapshot->geomLayerTransform.needsBilinearFiltering() || snapshot->bufferNeedsFiltering;
// Query the texture matrix given our current filtering mode.
float textureMatrix[16];
getDrawingTransformMatrix(useFiltering, textureMatrix);
- if (getTransformToDisplayInverse()) {
+ if (snapshot->geomBufferUsesDisplayInverseTransform) {
/*
* the code below applies the primary display's inverse transform to
* the texture transform
@@ -856,25 +859,22 @@
* of a camera where the buffer remains in native orientation,
* we want the pixels to always be upright.
*/
- sp<Layer> p = mDrawingParent.promote();
- if (p != nullptr) {
- const auto parentTransform = p->getTransform();
- tr = tr * inverseOrientation(parentTransform.getOrientation());
- }
+ const auto parentTransform = snapshot->transform;
+ tr = tr * inverseOrientation(parentTransform.getOrientation());
// and finally apply it to the original texture matrix
const mat4 texTransform(mat4(static_cast<const float*>(textureMatrix)) * tr);
memcpy(textureMatrix, texTransform.asArray(), sizeof(textureMatrix));
}
- const Rect win{getBounds()};
- float bufferWidth = getBufferSize(s).getWidth();
- float bufferHeight = getBufferSize(s).getHeight();
+ const Rect win{layerSettings.geometry.boundaries};
+ float bufferWidth = snapshot->bufferSize.getWidth();
+ float bufferHeight = snapshot->bufferSize.getHeight();
- // BufferStateLayers can have a "buffer size" of [0, 0, -1, -1] when no display frame has
+ // Layers can have a "buffer size" of [0, 0, -1, -1] when no display frame has
// been set and there is no parent layer bounds. In that case, the scale is meaningless so
// ignore them.
- if (!getBufferSize(s).isValid()) {
+ if (!snapshot->bufferSize.isValid()) {
bufferWidth = float(win.right) - float(win.left);
bufferHeight = float(win.bottom) - float(win.top);
}
@@ -2182,35 +2182,17 @@
void Layer::prepareShadowClientComposition(LayerFE::LayerSettings& caster,
const Rect& layerStackRect) const {
- renderengine::ShadowSettings state = mFlinger->mDrawingState.globalShadowSettings;
-
- // Note: this preserves existing behavior of shadowing the entire layer and not cropping it if
- // transparent regions are present. This may not be necessary since shadows are typically cast
- // by layers without transparent regions.
- state.boundaries = mBounds;
+ const auto* snapshot = getLayerSnapshot();
+ renderengine::ShadowSettings state = snapshot->shadowSettings;
+ if (state.length <= 0.f || (state.ambientColor.a <= 0.f && state.spotColor.a <= 0.f)) {
+ return;
+ }
// Shift the spot light x-position to the middle of the display and then
// offset it by casting layer's screen pos.
- state.lightPos.x = (layerStackRect.width() / 2.f) - mScreenBounds.left;
- state.lightPos.y -= mScreenBounds.top;
-
- state.length = mEffectiveShadowRadius;
-
- if (state.length > 0.f) {
- const float casterAlpha = caster.alpha;
- const bool casterIsOpaque =
- ((caster.source.buffer.buffer != nullptr) && caster.source.buffer.isOpaque);
-
- // If the casting layer is translucent, we need to fill in the shadow underneath the layer.
- // Otherwise the generated shadow will only be shown around the casting layer.
- state.casterIsTranslucent = !casterIsOpaque || (casterAlpha < 1.0f);
- state.ambientColor *= casterAlpha;
- state.spotColor *= casterAlpha;
-
- if (state.ambientColor.a > 0.f && state.spotColor.a > 0.f) {
- caster.shadow = state;
- }
- }
+ state.lightPos.x = (layerStackRect.width() / 2.f) - snapshot->transformedBounds.left;
+ state.lightPos.y -= snapshot->transformedBounds.top;
+ caster.shadow = state;
}
bool Layer::findInHierarchy(const sp<Layer>& l) {
@@ -3035,17 +3017,6 @@
mFlinger->getTransactionCallbackInvoker().addCallbackHandles(mDrawingState.callbackHandles,
jankData);
-
- sp<Fence> releaseFence = Fence::NO_FENCE;
- for (auto& handle : mDrawingState.callbackHandles) {
- if (handle->releasePreviousBuffer &&
- mDrawingState.releaseBufferEndpoint == handle->listener) {
- releaseFence =
- handle->previousReleaseFence ? handle->previousReleaseFence : Fence::NO_FENCE;
- break;
- }
- }
-
mDrawingState.callbackHandles = {};
}
@@ -3177,8 +3148,7 @@
const BufferData& bufferData, nsecs_t postTime, nsecs_t desiredPresentTime,
bool isAutoTimestamp, std::optional<nsecs_t> dequeueTime,
const FrameTimelineInfo& info) {
- ATRACE_CALL();
-
+ ATRACE_FORMAT("setBuffer %s - hasBuffer=%s", getDebugName(), (buffer ? "true" : "false"));
if (!buffer) {
return false;
}
@@ -3187,6 +3157,7 @@
bufferData.flags.test(BufferData::BufferDataChange::frameNumberChanged);
const uint64_t frameNumber =
frameNumberChanged ? bufferData.frameNumber : mDrawingState.frameNumber + 1;
+ ATRACE_FORMAT_INSTANT("setBuffer %s - %" PRIu64, getDebugName(), frameNumber);
if (mDrawingState.buffer) {
mReleasePreviousBuffer = true;
@@ -3419,13 +3390,14 @@
bool Layer::latchSidebandStream(bool& recomputeVisibleRegions) {
// We need to update the sideband stream if the layer has both a buffer and a sideband stream.
- editCompositionState()->sidebandStreamHasFrame = hasFrameUpdate() && mSidebandStream.get();
+ auto* snapshot = editLayerSnapshot();
+ snapshot->sidebandStreamHasFrame = hasFrameUpdate() && mSidebandStream.get();
if (mSidebandStreamChanged.exchange(false)) {
const State& s(getDrawingState());
// mSidebandStreamChanged was true
mSidebandStream = s.sidebandStream;
- editCompositionState()->sidebandStream = mSidebandStream;
+ snapshot->sidebandStream = mSidebandStream;
if (mSidebandStream != nullptr) {
setTransactionFlags(eTransactionNeeded);
mFlinger->setTransactionFlags(eTraversalNeeded);
@@ -3538,7 +3510,7 @@
sp<Layer> Layer::createClone() {
LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, LayerMetadata());
args.textureName = mTextureName;
- sp<BufferStateLayer> layer = mFlinger->getFactory().createBufferStateLayer(args);
+ sp<Layer> layer = mFlinger->getFactory().createBufferStateLayer(args);
layer->mHwcSlotGenerator = mHwcSlotGenerator;
layer->setInitialValuesForClone(sp<Layer>::fromExisting(this));
return layer;
@@ -3825,12 +3797,15 @@
}
}
-compositionengine::LayerFECompositionState* Layer::editCompositionState() {
- return mCompositionState.get();
+const Layer::LayerSnapshot* Layer::getLayerSnapshot() const {
+ return mSnapshot.get();
}
+Layer::LayerSnapshot* Layer::editLayerSnapshot() {
+ return mSnapshot.get();
+}
const compositionengine::LayerFECompositionState* Layer::getCompositionState() const {
- return mCompositionState.get();
+ return mSnapshot.get();
}
void Layer::useSurfaceDamage() {
@@ -3943,9 +3918,14 @@
mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence));
} else if (const auto displayId = PhysicalDisplayId::tryCast(display->getId());
displayId && mFlinger->getHwComposer().isConnected(*displayId)) {
- // The HWC doesn't support present fences, so use the refresh
- // timestamp instead.
- const nsecs_t actualPresentTime = display->getRefreshTimestamp();
+ // The HWC doesn't support present fences, so use the present timestamp instead.
+ const nsecs_t presentTimestamp =
+ mFlinger->getHwComposer().getPresentTimestamp(*displayId);
+
+ const nsecs_t now = systemTime(CLOCK_MONOTONIC);
+ const nsecs_t vsyncPeriod = display->getVsyncPeriodFromHWC();
+ const nsecs_t actualPresentTime = now - ((now - presentTimestamp) % vsyncPeriod);
+
mFlinger->mTimeStats->setPresentTime(layerId, mCurrentFrameNumber, actualPresentTime,
refreshRate, renderRate, vote, gameMode);
mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(),
@@ -4225,13 +4205,79 @@
return;
}
+ auto* snapshot = editLayerSnapshot();
if (updateGeometry) {
prepareBasicGeometryCompositionState();
prepareGeometryCompositionState();
+ snapshot->roundedCorner = getRoundedCornerState();
+ snapshot->stretchEffect = getStretchEffect();
+ snapshot->transformedBounds = mScreenBounds;
+ if (mEffectiveShadowRadius > 0.f) {
+ snapshot->shadowSettings = mFlinger->mDrawingState.globalShadowSettings;
+
+ // Note: this preserves existing behavior of shadowing the entire layer and not cropping
+ // it if transparent regions are present. This may not be necessary since shadows are
+ // typically cast by layers without transparent regions.
+ snapshot->shadowSettings.boundaries = mBounds;
+
+ const float casterAlpha = snapshot->alpha;
+ const bool casterIsOpaque =
+ ((mBufferInfo.mBuffer != nullptr) && isOpaque(mDrawingState));
+
+ // If the casting layer is translucent, we need to fill in the shadow underneath the
+ // layer. Otherwise the generated shadow will only be shown around the casting layer.
+ snapshot->shadowSettings.casterIsTranslucent = !casterIsOpaque || (casterAlpha < 1.0f);
+ snapshot->shadowSettings.ambientColor *= casterAlpha;
+ snapshot->shadowSettings.spotColor *= casterAlpha;
+ }
+ snapshot->shadowSettings.length = mEffectiveShadowRadius;
}
+ snapshot->contentOpaque = isOpaque(mDrawingState);
+ snapshot->isHdrY410 = isHdrY410();
+ snapshot->bufferNeedsFiltering = bufferNeedsFiltering();
+ sp<Layer> p = mDrawingParent.promote();
+ if (p != nullptr) {
+ snapshot->transform = p->getTransform();
+ } else {
+ snapshot->transform.reset();
+ }
+ snapshot->bufferSize = getBufferSize(mDrawingState);
+ snapshot->externalTexture = mBufferInfo.mBuffer;
preparePerFrameCompositionState();
}
+void Layer::updateMetadataSnapshot(const LayerMetadata& parentMetadata) {
+ mSnapshot->layerMetadata = parentMetadata;
+ mSnapshot->layerMetadata.merge(mDrawingState.metadata);
+ for (const sp<Layer>& child : mDrawingChildren) {
+ child->updateMetadataSnapshot(mSnapshot->layerMetadata);
+ }
+}
+
+void Layer::updateRelativeMetadataSnapshot(const LayerMetadata& relativeLayerMetadata,
+ std::unordered_set<Layer*>& visited) {
+ if (visited.find(this) != visited.end()) {
+ ALOGW("Cycle containing layer %s detected in z-order relatives", getDebugName());
+ return;
+ }
+ visited.insert(this);
+
+ mSnapshot->relativeLayerMetadata = relativeLayerMetadata;
+
+ if (mDrawingState.zOrderRelatives.empty()) {
+ return;
+ }
+ LayerMetadata childRelativeLayerMetadata = mSnapshot->relativeLayerMetadata;
+ childRelativeLayerMetadata.merge(mSnapshot->layerMetadata);
+ for (wp<Layer> weakRelative : mDrawingState.zOrderRelatives) {
+ sp<Layer> relative = weakRelative.promote();
+ if (!relative) {
+ continue;
+ }
+ relative->updateRelativeMetadataSnapshot(childRelativeLayerMetadata, visited);
+ }
+}
+
// ---------------------------------------------------------------------------
std::ostream& operator<<(std::ostream& stream, const Layer::FrameRate& rate) {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 5030fd8..4ff86e5 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -38,6 +38,7 @@
#include <utils/Timers.h>
#include <compositionengine/LayerFE.h>
+#include <compositionengine/LayerFECompositionState.h>
#include <scheduler/Fps.h>
#include <scheduler/Seamlessness.h>
@@ -144,6 +145,31 @@
bool hasRoundedCorners() const { return radius.x > 0.0f && radius.y > 0.0f; }
};
+ // LayerSnapshot stores Layer state used by Composition Engine and Render Engine. Composition
+ // Engine uses a pointer to LayerSnapshot (as LayerFECompositionState*) and the LayerSettings
+ // passed to Render Engine are created using properties stored on this struct.
+ //
+ // TODO(b/238781169) Implement LayerFE as a separate subclass. Migrate LayerSnapshot to that
+ // LayerFE subclass.
+ struct LayerSnapshot : public compositionengine::LayerFECompositionState {
+ int32_t sequence;
+ std::string name;
+ uint32_t textureName;
+ bool contentOpaque;
+ RoundedCornerState roundedCorner;
+ StretchEffect stretchEffect;
+ FloatRect transformedBounds;
+ renderengine::ShadowSettings shadowSettings;
+ bool premultipliedAlpha;
+ bool isHdrY410;
+ bool bufferNeedsFiltering;
+ ui::Transform transform;
+ Rect bufferSize;
+ std::shared_ptr<renderengine::ExternalTexture> externalTexture;
+ LayerMetadata layerMetadata;
+ LayerMetadata relativeLayerMetadata;
+ };
+
using FrameRate = scheduler::LayerInfo::FrameRate;
using FrameRateCompatibility = scheduler::LayerInfo::FrameRateCompatibility;
@@ -392,7 +418,9 @@
ui::Dataspace getRequestedDataSpace() const;
virtual sp<compositionengine::LayerFE> getCompositionEngineLayerFE() const;
- compositionengine::LayerFECompositionState* editCompositionState();
+
+ const LayerSnapshot* getLayerSnapshot() const;
+ LayerSnapshot* editLayerSnapshot();
// If we have received a new buffer this frame, we will pass its surface
// damage down to hardware composer. Otherwise, we must send a region with
@@ -585,6 +613,12 @@
mClearClientCompositionFenceOnLayerDisplayed = false;
}
+ const LayerMetadata* getMetadata() const override { return &mSnapshot->layerMetadata; }
+
+ const LayerMetadata* getRelativeMetadata() const override {
+ return &mSnapshot->relativeLayerMetadata;
+ }
+
const char* getDebugName() const override;
bool setShadowRadius(float shadowRadius);
@@ -867,7 +901,17 @@
bool simpleBufferUpdate(const layer_state_t&) const;
static bool isOpaqueFormat(PixelFormat format);
+
+ // Updates the LayerSnapshot. This must be called prior to sending layer data to
+ // CompositionEngine or RenderEngine (i.e. before calling CompositionEngine::present or
+ // Layer::prepareClientComposition).
+ //
+ // TODO(b/238781169) Remove direct calls to RenderEngine::drawLayers that don't go through
+ // CompositionEngine to create a single path for composing layers.
void updateSnapshot(bool updateGeometry);
+ void updateMetadataSnapshot(const LayerMetadata& parentMetadata);
+ void updateRelativeMetadataSnapshot(const LayerMetadata& relativeLayerMetadata,
+ std::unordered_set<Layer*>& visited);
protected:
friend class impl::SurfaceInterceptor;
@@ -1166,8 +1210,6 @@
// the mStateLock.
ui::Transform::RotationFlags mTransformHint = ui::Transform::ROT_0;
- std::unique_ptr<compositionengine::LayerFECompositionState> mCompositionState;
-
ReleaseCallbackId mPreviousReleaseCallbackId = ReleaseCallbackId::INVALID_ID;
uint64_t mPreviousReleasedFrameNumber = 0;
@@ -1200,6 +1242,8 @@
ui::Transform mRequestedTransform;
sp<HwcSlotGenerator> mHwcSlotGenerator;
+
+ std::unique_ptr<LayerSnapshot> mSnapshot = std::make_unique<LayerSnapshot>();
};
std::ostream& operator<<(std::ostream& stream, const Layer::FrameRate& rate);
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 5705255..8dd3b0f 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -203,25 +203,14 @@
return 0.0f;
}
- // (b/133849373) ROT_90 screencap images produced upside down
- auto area = sample_area;
- if (orientation & ui::Transform::ROT_90) {
- area.top = height - area.top;
- area.bottom = height - area.bottom;
- std::swap(area.top, area.bottom);
-
- area.left = width - area.left;
- area.right = width - area.right;
- std::swap(area.left, area.right);
- }
-
- const uint32_t pixelCount = (area.bottom - area.top) * (area.right - area.left);
+ const uint32_t pixelCount =
+ (sample_area.bottom - sample_area.top) * (sample_area.right - sample_area.left);
uint32_t accumulatedLuma = 0;
// Calculates luma with approximation of Rec. 709 primaries
- for (int32_t row = area.top; row < area.bottom; ++row) {
+ for (int32_t row = sample_area.top; row < sample_area.bottom; ++row) {
const uint32_t* rowBase = data + row * stride;
- for (int32_t column = area.left; column < area.right; ++column) {
+ for (int32_t column = sample_area.left; column < sample_area.right; ++column) {
uint32_t pixel = rowBase[column];
const uint32_t r = pixel & 0xFF;
const uint32_t g = (pixel >> 8) & 0xFF;
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index 00886f0..3cb052c 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -48,24 +48,6 @@
} fixedRateBelowThresholdLayersScore;
};
-template <typename Iterator>
-const DisplayModePtr& getMaxScoreRefreshRate(Iterator begin, Iterator end) {
- const auto it =
- std::max_element(begin, end, [](RefreshRateScore max, RefreshRateScore current) {
- const auto& [modeIt, overallScore, _] = current;
-
- std::string name = to_string(modeIt->second->getFps());
- ALOGV("%s scores %.2f", name.c_str(), overallScore);
-
- ATRACE_INT(name.c_str(), static_cast<int>(std::round(overallScore * 100)));
-
- constexpr float kEpsilon = 0.0001f;
- return overallScore > max.overallScore * (1 + kEpsilon);
- });
-
- return it->modeIt->second;
-}
-
constexpr RefreshRateConfigs::GlobalSignals kNoSignals;
std::string formatLayerInfo(const RefreshRateConfigs::LayerRequirement& layer, float weight) {
@@ -137,6 +119,34 @@
} // namespace
+struct RefreshRateConfigs::RefreshRateScoreComparator {
+ bool operator()(const RefreshRateScore& lhs, const RefreshRateScore& rhs) const {
+ const auto& [modeIt, overallScore, _] = lhs;
+
+ std::string name = to_string(modeIt->second->getFps());
+ ALOGV("%s sorting scores %.2f", name.c_str(), overallScore);
+
+ ATRACE_INT(name.c_str(), static_cast<int>(std::round(overallScore * 100)));
+
+ constexpr float kEpsilon = 0.0001f;
+ if (std::abs(overallScore - rhs.overallScore) > kEpsilon) {
+ return overallScore > rhs.overallScore;
+ }
+
+ // If overallScore tie we will pick the higher refresh rate if
+ // high refresh rate is the priority else the lower refresh rate.
+ if (refreshRateOrder == RefreshRateOrder::Descending) {
+ using fps_approx_ops::operator>;
+ return modeIt->second->getFps() > rhs.modeIt->second->getFps();
+ } else {
+ using fps_approx_ops::operator<;
+ return modeIt->second->getFps() < rhs.modeIt->second->getFps();
+ }
+ }
+
+ const RefreshRateOrder refreshRateOrder;
+};
+
std::string RefreshRateConfigs::Policy::toString() const {
return base::StringPrintf("{defaultModeId=%d, allowGroupSwitching=%s"
", primaryRange=%s, appRequestRange=%s}",
@@ -218,6 +228,13 @@
return 0;
}
+float RefreshRateConfigs::calculateRefreshRateScoreForFps(Fps refreshRate) const {
+ const float ratio =
+ refreshRate.getValue() / mAppRequestRefreshRates.back()->second->getFps().getValue();
+ // Use ratio^2 to get a lower score the more we get further from peak
+ return ratio * ratio;
+}
+
float RefreshRateConfigs::calculateLayerScoreLocked(const LayerRequirement& layer, Fps refreshRate,
bool isSeamlessSwitch) const {
// Slightly prefer seamless switches.
@@ -226,10 +243,7 @@
// If the layer wants Max, give higher score to the higher refresh rate
if (layer.vote == LayerVoteType::Max) {
- const auto& maxRefreshRate = mAppRequestRefreshRates.back()->second;
- const auto ratio = refreshRate.getValue() / maxRefreshRate->getFps().getValue();
- // use ratio^2 to get a lower score the more we get further from peak
- return ratio * ratio;
+ return calculateRefreshRateScoreForFps(refreshRate);
}
if (layer.vote == LayerVoteType::ExplicitExact) {
@@ -258,24 +272,24 @@
kNonExactMatchingPenalty;
}
-auto RefreshRateConfigs::getBestRefreshRate(const std::vector<LayerRequirement>& layers,
- GlobalSignals signals) const
- -> std::pair<DisplayModePtr, GlobalSignals> {
+auto RefreshRateConfigs::getRankedRefreshRates(const std::vector<LayerRequirement>& layers,
+ GlobalSignals signals) const
+ -> std::pair<std::vector<RefreshRateRanking>, GlobalSignals> {
std::lock_guard lock(mLock);
- if (mGetBestRefreshRateCache &&
- mGetBestRefreshRateCache->arguments == std::make_pair(layers, signals)) {
- return mGetBestRefreshRateCache->result;
+ if (mGetRankedRefreshRatesCache &&
+ mGetRankedRefreshRatesCache->arguments == std::make_pair(layers, signals)) {
+ return mGetRankedRefreshRatesCache->result;
}
- const auto result = getBestRefreshRateLocked(layers, signals);
- mGetBestRefreshRateCache = GetBestRefreshRateCache{{layers, signals}, result};
+ const auto result = getRankedRefreshRatesLocked(layers, signals);
+ mGetRankedRefreshRatesCache = GetRankedRefreshRatesCache{{layers, signals}, result};
return result;
}
-auto RefreshRateConfigs::getBestRefreshRateLocked(const std::vector<LayerRequirement>& layers,
- GlobalSignals signals) const
- -> std::pair<DisplayModePtr, GlobalSignals> {
+auto RefreshRateConfigs::getRankedRefreshRatesLocked(const std::vector<LayerRequirement>& layers,
+ GlobalSignals signals) const
+ -> std::pair<std::vector<RefreshRateRanking>, GlobalSignals> {
using namespace fps_approx_ops;
ATRACE_CALL();
ALOGV("%s: %zu layers", __func__, layers.size());
@@ -285,8 +299,8 @@
// Keep the display at max refresh rate for the duration of powering on the display.
if (signals.powerOnImminent) {
ALOGV("Power On Imminent");
- const auto& max = getMaxRefreshRateByPolicyLocked(activeMode.getGroup());
- return {max, GlobalSignals{.powerOnImminent = true}};
+ return {getRefreshRatesByPolicyLocked(activeMode.getGroup(), RefreshRateOrder::Descending),
+ GlobalSignals{.powerOnImminent = true}};
}
int noVoteLayers = 0;
@@ -295,7 +309,6 @@
int explicitDefaultVoteLayers = 0;
int explicitExactOrMultipleVoteLayers = 0;
int explicitExact = 0;
- float maxExplicitWeight = 0;
int seamedFocusedLayers = 0;
for (const auto& layer : layers) {
@@ -311,15 +324,12 @@
break;
case LayerVoteType::ExplicitDefault:
explicitDefaultVoteLayers++;
- maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
break;
case LayerVoteType::ExplicitExactOrMultiple:
explicitExactOrMultipleVoteLayers++;
- maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
break;
case LayerVoteType::ExplicitExact:
explicitExact++;
- maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
break;
case LayerVoteType::Heuristic:
break;
@@ -348,9 +358,9 @@
// Consider the touch event if there are no Explicit* layers. Otherwise wait until after we've
// selected a refresh rate to see if we should apply touch boost.
if (signals.touch && !hasExplicitVoteLayers) {
- const DisplayModePtr& max = getMaxRefreshRateByPolicyLocked(anchorGroup);
- ALOGV("TouchBoost - choose %s", to_string(max->getFps()).c_str());
- return {max, GlobalSignals{.touch = true}};
+ ALOGV("Touch Boost");
+ return {getRefreshRatesByPolicyLocked(anchorGroup, RefreshRateOrder::Descending),
+ GlobalSignals{.touch = true}};
}
// If the primary range consists of a single refresh rate then we can only
@@ -360,22 +370,22 @@
isApproxEqual(policy->primaryRange.min, policy->primaryRange.max);
if (!signals.touch && signals.idle && !(primaryRangeIsSingleRate && hasExplicitVoteLayers)) {
- const DisplayModePtr& min = getMinRefreshRateByPolicyLocked();
- ALOGV("Idle - choose %s", to_string(min->getFps()).c_str());
- return {min, GlobalSignals{.idle = true}};
+ ALOGV("Idle");
+ return {getRefreshRatesByPolicyLocked(activeMode.getGroup(), RefreshRateOrder::Ascending),
+ GlobalSignals{.idle = true}};
}
if (layers.empty() || noVoteLayers == layers.size()) {
- const DisplayModePtr& max = getMaxRefreshRateByPolicyLocked(anchorGroup);
- ALOGV("no layers with votes - choose %s", to_string(max->getFps()).c_str());
- return {max, kNoSignals};
+ ALOGV("No layers with votes");
+ return {getRefreshRatesByPolicyLocked(anchorGroup, RefreshRateOrder::Descending),
+ kNoSignals};
}
// Only if all layers want Min we should return Min
if (noVoteLayers + minVoteLayers == layers.size()) {
- const DisplayModePtr& min = getMinRefreshRateByPolicyLocked();
- ALOGV("all layers Min - choose %s", to_string(min->getFps()).c_str());
- return {min, kNoSignals};
+ ALOGV("All layers Min");
+ return {getRefreshRatesByPolicyLocked(activeMode.getGroup(), RefreshRateOrder::Ascending),
+ kNoSignals};
}
// Find the best refresh rate based on score
@@ -522,22 +532,29 @@
}
// Now that we scored all the refresh rates we need to pick the one that got the highest
- // overallScore. In case of a tie we will pick the higher refresh rate if any of the layers
- // wanted Max, or the lower otherwise.
- const DisplayModePtr& bestRefreshRate = maxVoteLayers > 0
- ? getMaxScoreRefreshRate(scores.rbegin(), scores.rend())
- : getMaxScoreRefreshRate(scores.begin(), scores.end());
+ // overallScore. Sort the scores based on their overallScore in descending order of priority.
+ const RefreshRateOrder refreshRateOrder =
+ maxVoteLayers > 0 ? RefreshRateOrder::Descending : RefreshRateOrder::Ascending;
+ std::sort(scores.begin(), scores.end(),
+ RefreshRateScoreComparator{.refreshRateOrder = refreshRateOrder});
+ std::vector<RefreshRateRanking> rankedRefreshRates;
+ rankedRefreshRates.reserve(scores.size());
+
+ std::transform(scores.begin(), scores.end(), back_inserter(rankedRefreshRates),
+ [](const RefreshRateScore& score) {
+ return RefreshRateRanking{score.modeIt->second, score.overallScore};
+ });
if (primaryRangeIsSingleRate) {
// If we never scored any layers, then choose the rate from the primary
// range instead of picking a random score from the app range.
if (std::all_of(scores.begin(), scores.end(),
[](RefreshRateScore score) { return score.overallScore == 0; })) {
- const DisplayModePtr& max = getMaxRefreshRateByPolicyLocked(anchorGroup);
- ALOGV("layers not scored - choose %s", to_string(max->getFps()).c_str());
- return {max, kNoSignals};
+ ALOGV("Layers not scored");
+ return {getRefreshRatesByPolicyLocked(anchorGroup, RefreshRateOrder::Descending),
+ kNoSignals};
} else {
- return {bestRefreshRate, kNoSignals};
+ return {rankedRefreshRates, kNoSignals};
}
}
@@ -545,8 +562,6 @@
// interactive (as opposed to ExplicitExactOrMultiple) and therefore if those posted an explicit
// vote we should not change it if we get a touch event. Only apply touch boost if it will
// actually increase the refresh rate over the normal selection.
- const DisplayModePtr& touchRefreshRate = getMaxRefreshRateByPolicyLocked(anchorGroup);
-
const bool touchBoostForExplicitExact = [&] {
if (mSupportsFrameRateOverrideByContent) {
// Enable touch boost if there are other layers besides exact
@@ -557,15 +572,18 @@
}
}();
+ const auto& touchRefreshRates =
+ getRefreshRatesByPolicyLocked(anchorGroup, RefreshRateOrder::Descending);
using fps_approx_ops::operator<;
if (signals.touch && explicitDefaultVoteLayers == 0 && touchBoostForExplicitExact &&
- bestRefreshRate->getFps() < touchRefreshRate->getFps()) {
- ALOGV("TouchBoost - choose %s", to_string(touchRefreshRate->getFps()).c_str());
- return {touchRefreshRate, GlobalSignals{.touch = true}};
+ scores.front().modeIt->second->getFps() <
+ touchRefreshRates.front().displayModePtr->getFps()) {
+ ALOGV("Touch Boost");
+ return {touchRefreshRates, GlobalSignals{.touch = true}};
}
- return {bestRefreshRate, kNoSignals};
+ return {rankedRefreshRates, kNoSignals};
}
std::unordered_map<uid_t, std::vector<const RefreshRateConfigs::LayerRequirement*>>
@@ -670,11 +688,13 @@
continue;
}
- // Now that we scored all the refresh rates we need to pick the one that got the highest
- // score.
+ // Now that we scored all the refresh rates we need to pick the lowest refresh rate
+ // that got the highest score.
const DisplayModePtr& bestRefreshRate =
- getMaxScoreRefreshRate(scores.begin(), scores.end());
-
+ std::min_element(scores.begin(), scores.end(),
+ RefreshRateScoreComparator{.refreshRateOrder =
+ RefreshRateOrder::Ascending})
+ ->modeIt->second;
frameRateOverrides.emplace(uid, bestRefreshRate->getFps());
}
@@ -715,16 +735,6 @@
return mPrimaryRefreshRates.front()->second;
}
-DisplayModePtr RefreshRateConfigs::getMaxRefreshRateByPolicy() const {
- std::lock_guard lock(mLock);
- return getMaxRefreshRateByPolicyLocked();
-}
-
-const DisplayModePtr& RefreshRateConfigs::getMaxRefreshRateByPolicyLocked() const {
- const int anchorGroup = getActiveModeItLocked()->second->getGroup();
- return getMaxRefreshRateByPolicyLocked(anchorGroup);
-}
-
const DisplayModePtr& RefreshRateConfigs::getMaxRefreshRateByPolicyLocked(int anchorGroup) const {
for (auto it = mPrimaryRefreshRates.rbegin(); it != mPrimaryRefreshRates.rend(); ++it) {
const auto& mode = (*it)->second;
@@ -733,14 +743,41 @@
}
}
- const auto& activeMode = *getActiveModeItLocked()->second;
- ALOGE("Can't find max refresh rate by policy with the same mode group as the current mode %s",
- to_string(activeMode).c_str());
+ ALOGE("Can't find max refresh rate by policy with the same group %d", anchorGroup);
// Default to the highest refresh rate.
return mPrimaryRefreshRates.back()->second;
}
+std::vector<RefreshRateRanking> RefreshRateConfigs::getRefreshRatesByPolicyLocked(
+ std::optional<int> anchorGroupOpt, RefreshRateOrder refreshRateOrder) const {
+ std::vector<RefreshRateRanking> rankings;
+ const auto makeRanking = [&](const DisplayModeIterator it) REQUIRES(mLock) {
+ const auto& mode = it->second;
+ const bool inverseScore = (refreshRateOrder == RefreshRateOrder::Ascending);
+ const float score = calculateRefreshRateScoreForFps(mode->getFps());
+ if (!anchorGroupOpt || mode->getGroup() == anchorGroupOpt) {
+ rankings.push_back(RefreshRateRanking{mode, inverseScore ? 1.0f / score : score});
+ }
+ };
+
+ if (refreshRateOrder == RefreshRateOrder::Ascending) {
+ std::for_each(mPrimaryRefreshRates.begin(), mPrimaryRefreshRates.end(), makeRanking);
+ } else {
+ std::for_each(mPrimaryRefreshRates.rbegin(), mPrimaryRefreshRates.rend(), makeRanking);
+ }
+
+ if (!rankings.empty() || !anchorGroupOpt) {
+ return rankings;
+ }
+
+ ALOGW("Can't find %s refresh rate by policy with the same mode group"
+ " as the mode group %d",
+ refreshRateOrder == RefreshRateOrder::Ascending ? "min" : "max", anchorGroupOpt.value());
+
+ return getRefreshRatesByPolicyLocked(/*anchorGroupOpt*/ std::nullopt, refreshRateOrder);
+}
+
DisplayModePtr RefreshRateConfigs::getActiveModePtr() const {
std::lock_guard lock(mLock);
return getActiveModeItLocked()->second;
@@ -760,9 +797,9 @@
void RefreshRateConfigs::setActiveModeId(DisplayModeId modeId) {
std::lock_guard lock(mLock);
- // Invalidate the cached invocation to getBestRefreshRate. This forces
- // the refresh rate to be recomputed on the next call to getBestRefreshRate.
- mGetBestRefreshRateCache.reset();
+ // Invalidate the cached invocation to getRankedRefreshRates. This forces
+ // the refresh rate to be recomputed on the next call to getRankedRefreshRates.
+ mGetRankedRefreshRatesCache.reset();
mActiveModeIt = mDisplayModes.find(modeId);
LOG_ALWAYS_FATAL_IF(mActiveModeIt == mDisplayModes.end());
@@ -797,9 +834,9 @@
void RefreshRateConfigs::updateDisplayModes(DisplayModes modes, DisplayModeId activeModeId) {
std::lock_guard lock(mLock);
- // Invalidate the cached invocation to getBestRefreshRate. This forces
- // the refresh rate to be recomputed on the next call to getBestRefreshRate.
- mGetBestRefreshRateCache.reset();
+ // Invalidate the cached invocation to getRankedRefreshRates. This forces
+ // the refresh rate to be recomputed on the next call to getRankedRefreshRates.
+ mGetRankedRefreshRatesCache.reset();
mDisplayModes = std::move(modes);
mActiveModeIt = mDisplayModes.find(activeModeId);
@@ -843,7 +880,7 @@
ALOGE("Invalid refresh rate policy: %s", policy.toString().c_str());
return BAD_VALUE;
}
- mGetBestRefreshRateCache.reset();
+ mGetRankedRefreshRatesCache.reset();
Policy previousPolicy = *getCurrentPolicyLocked();
mDisplayManagerPolicy = policy;
if (*getCurrentPolicyLocked() == previousPolicy) {
@@ -858,7 +895,7 @@
if (policy && !isPolicyValidLocked(*policy)) {
return BAD_VALUE;
}
- mGetBestRefreshRateCache.reset();
+ mGetRankedRefreshRatesCache.reset();
Policy previousPolicy = *getCurrentPolicyLocked();
mOverridePolicy = policy;
if (*getCurrentPolicyLocked() == previousPolicy) {
@@ -958,7 +995,8 @@
return KernelIdleTimerAction::TurnOff;
}
- const DisplayModePtr& maxByPolicy = getMaxRefreshRateByPolicyLocked();
+ const DisplayModePtr& maxByPolicy =
+ getMaxRefreshRateByPolicyLocked(getActiveModeItLocked()->second->getGroup());
if (minByPolicy == maxByPolicy) {
// Turn on the timer when the min of the primary range is below the device min.
if (const Policy* currentPolicy = getCurrentPolicyLocked();
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index 19bcb94..0642fcb 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -44,6 +44,15 @@
return static_cast<DisplayModeEvent>(static_cast<T>(lhs) | static_cast<T>(rhs));
}
+struct RefreshRateRanking {
+ DisplayModePtr displayModePtr;
+ float score = 0.0f;
+
+ bool operator==(const RefreshRateRanking& ranking) const {
+ return displayModePtr == ranking.displayModePtr && score == ranking.score;
+ }
+};
+
using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride;
/**
@@ -195,9 +204,9 @@
}
};
- // Returns the refresh rate that best fits the given layers, and whether the refresh rate was
- // chosen based on touch boost and/or idle timer.
- std::pair<DisplayModePtr, GlobalSignals> getBestRefreshRate(
+ // Returns the list in the descending order of refresh rates desired
+ // based on their overall score, and the GlobalSignals that were considered.
+ std::pair<std::vector<RefreshRateRanking>, GlobalSignals> getRankedRefreshRates(
const std::vector<LayerRequirement>&, GlobalSignals) const EXCLUDES(mLock);
FpsRange getSupportedRefreshRateRange() const EXCLUDES(mLock) {
@@ -208,10 +217,6 @@
std::optional<Fps> onKernelTimerChanged(std::optional<DisplayModeId> desiredActiveModeId,
bool timerExpired) const EXCLUDES(mLock);
- // Returns the highest refresh rate according to the current policy. May change at runtime. Only
- // uses the primary range, not the app request range.
- DisplayModePtr getMaxRefreshRateByPolicy() const EXCLUDES(mLock);
-
void setActiveModeId(DisplayModeId) EXCLUDES(mLock) REQUIRES(kMainThreadContext);
// See mActiveModeIt for thread safety.
@@ -343,7 +348,7 @@
// See mActiveModeIt for thread safety.
DisplayModeIterator getActiveModeItLocked() const REQUIRES(mLock);
- std::pair<DisplayModePtr, GlobalSignals> getBestRefreshRateLocked(
+ std::pair<std::vector<RefreshRateRanking>, GlobalSignals> getRankedRefreshRatesLocked(
const std::vector<LayerRequirement>&, GlobalSignals) const REQUIRES(mLock);
// Returns number of display frames and remainder when dividing the layer refresh period by
@@ -356,12 +361,23 @@
// Returns the highest refresh rate according to the current policy. May change at runtime. Only
// uses the primary range, not the app request range.
- const DisplayModePtr& getMaxRefreshRateByPolicyLocked() const REQUIRES(mLock);
const DisplayModePtr& getMaxRefreshRateByPolicyLocked(int anchorGroup) const REQUIRES(mLock);
+ struct RefreshRateScoreComparator;
+
+ enum class RefreshRateOrder { Ascending, Descending };
+
+ // Returns the rankings in RefreshRateOrder. May change at runtime.
+ // Only uses the primary range, not the app request range.
+ std::vector<RefreshRateRanking> getRefreshRatesByPolicyLocked(std::optional<int> anchorGroupOpt,
+ RefreshRateOrder) const
+ REQUIRES(mLock);
+
const Policy* getCurrentPolicyLocked() const REQUIRES(mLock);
bool isPolicyValidLocked(const Policy& policy) const REQUIRES(mLock);
+ // Returns the refresh rate score as a ratio to max refresh rate, which has a score of 1.
+ float calculateRefreshRateScoreForFps(Fps refreshRate) const REQUIRES(mLock);
// calculates a score for a layer. Used to determine the display refresh rate
// and the frame rate override for certains applications.
float calculateLayerScoreLocked(const LayerRequirement&, Fps refreshRate,
@@ -410,11 +426,11 @@
const Config mConfig;
bool mSupportsFrameRateOverrideByContent;
- struct GetBestRefreshRateCache {
+ struct GetRankedRefreshRatesCache {
std::pair<std::vector<LayerRequirement>, GlobalSignals> arguments;
- std::pair<DisplayModePtr, GlobalSignals> result;
+ std::pair<std::vector<RefreshRateRanking>, GlobalSignals> result;
};
- mutable std::optional<GetBestRefreshRateCache> mGetBestRefreshRateCache GUARDED_BY(mLock);
+ mutable std::optional<GetRankedRefreshRatesCache> mGetRankedRefreshRatesCache GUARDED_BY(mLock);
// Declare mIdleTimer last to ensure its thread joins before the mutex/callbacks are destroyed.
std::mutex mIdleTimerCallbacksMutex;
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index ff6b461..6d68bac 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -674,7 +674,9 @@
if (currentState == newState) return {};
currentState = std::forward<T>(newState);
- std::tie(newMode, consideredSignals) = chooseDisplayMode();
+ const auto [rankings, signals] = getRankedDisplayModes();
+ newMode = rankings.front().displayModePtr;
+ consideredSignals = signals;
frameRateOverridesChanged = updateFrameRateOverrides(consideredSignals, newMode->getFps());
if (mPolicy.mode == newMode) {
@@ -699,7 +701,8 @@
return consideredSignals;
}
-auto Scheduler::chooseDisplayMode() -> std::pair<DisplayModePtr, GlobalSignals> {
+auto Scheduler::getRankedDisplayModes()
+ -> std::pair<std::vector<RefreshRateRanking>, GlobalSignals> {
ATRACE_CALL();
const auto configs = holdRefreshRateConfigs();
@@ -712,14 +715,14 @@
.idle = mPolicy.idleTimer == TimerState::Expired,
.powerOnImminent = powerOnImminent};
- return configs->getBestRefreshRate(mPolicy.contentRequirements, signals);
+ return configs->getRankedRefreshRates(mPolicy.contentRequirements, signals);
}
DisplayModePtr Scheduler::getPreferredDisplayMode() {
std::lock_guard<std::mutex> lock(mPolicyLock);
// Make sure the stored mode is up to date.
if (mPolicy.mode) {
- mPolicy.mode = chooseDisplayMode().first;
+ mPolicy.mode = getRankedDisplayModes().first.front().displayModePtr;
}
return mPolicy.mode;
}
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index afb3459..f567205 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -95,8 +95,8 @@
~ISchedulerCallback() = default;
};
-class Scheduler : impl::MessageQueue {
- using Impl = impl::MessageQueue;
+class Scheduler : android::impl::MessageQueue {
+ using Impl = android::impl::MessageQueue;
public:
Scheduler(ICompositor&, ISchedulerCallback&, FeatureFlags);
@@ -130,7 +130,7 @@
ConnectionHandle createConnection(const char* connectionName, frametimeline::TokenManager*,
std::chrono::nanoseconds workDuration,
std::chrono::nanoseconds readyDuration,
- impl::EventThread::InterceptVSyncsCallback);
+ android::impl::EventThread::InterceptVSyncsCallback);
sp<IDisplayEventConnection> createDisplayEventConnection(
ConnectionHandle, EventRegistrationFlags eventRegistration = {});
@@ -269,16 +269,18 @@
template <typename S, typename T>
GlobalSignals applyPolicy(S Policy::*, T&&) EXCLUDES(mPolicyLock);
- // Returns the display mode that fulfills the policy, and the signals that were considered.
- std::pair<DisplayModePtr, GlobalSignals> chooseDisplayMode() REQUIRES(mPolicyLock);
+ // Returns the list of display modes in descending order of their priority that fulfills the
+ // policy, and the signals that were considered.
+ std::pair<std::vector<RefreshRateRanking>, GlobalSignals> getRankedDisplayModes()
+ REQUIRES(mPolicyLock);
bool updateFrameRateOverrides(GlobalSignals, Fps displayRefreshRate) REQUIRES(mPolicyLock);
void dispatchCachedReportedMode() REQUIRES(mPolicyLock) EXCLUDES(mRefreshRateConfigsLock);
- impl::EventThread::ThrottleVsyncCallback makeThrottleVsyncCallback() const
+ android::impl::EventThread::ThrottleVsyncCallback makeThrottleVsyncCallback() const
EXCLUDES(mRefreshRateConfigsLock);
- impl::EventThread::GetVsyncPeriodFunction makeGetVsyncPeriodFunction() const;
+ android::impl::EventThread::GetVsyncPeriodFunction makeGetVsyncPeriodFunction() const;
std::shared_ptr<RefreshRateConfigs> holdRefreshRateConfigs() const
EXCLUDES(mRefreshRateConfigsLock) {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e31490c..7d3fc98 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -106,7 +106,6 @@
#include <ui/DisplayIdentification.h>
#include "BackgroundExecutor.h"
-#include "BufferStateLayer.h"
#include "Client.h"
#include "Colorizer.h"
#include "Display/DisplayMap.h"
@@ -681,7 +680,7 @@
sp<IBinder> input(defaultServiceManager()->getService(String16("inputflinger")));
- static_cast<void>(mScheduler->schedule([=] {
+ static_cast<void>(mScheduler->schedule([=]() FTL_FAKE_GUARD(kMainThreadContext) {
if (input == nullptr) {
ALOGE("Failed to link to input service");
} else {
@@ -709,8 +708,9 @@
mBootStage = BootStage::FINISHED;
- if (property_get_bool("sf.debug.show_refresh_rate_overlay", false)) {
- FTL_FAKE_GUARD(mStateLock, enableRefreshRateOverlay(true));
+ if (base::GetBoolProperty("sf.debug.show_refresh_rate_overlay"s, false)) {
+ ftl::FakeGuard guard(mStateLock);
+ enableRefreshRateOverlay(true);
}
}));
}
@@ -814,16 +814,37 @@
enableHalVirtualDisplays(true);
}
- // Process any initial hotplug and resulting display changes.
+ // Process hotplug for displays connected at boot.
LOG_ALWAYS_FATAL_IF(!configureLocked(),
"Initial display configuration failed: HWC did not hotplug");
- processDisplayChangesLocked();
- const auto display = getDefaultDisplayDeviceLocked();
+ // Commit primary display.
+ sp<const DisplayDevice> display;
+ if (const auto indexOpt = mCurrentState.getDisplayIndex(getPrimaryDisplayIdLocked())) {
+ const auto& displays = mCurrentState.displays;
+
+ const auto& token = displays.keyAt(*indexOpt);
+ const auto& state = displays.valueAt(*indexOpt);
+
+ processDisplayAdded(token, state);
+ mDrawingState.displays.add(token, state);
+
+ display = getDefaultDisplayDeviceLocked();
+ }
+
LOG_ALWAYS_FATAL_IF(!display, "Failed to configure the primary display");
LOG_ALWAYS_FATAL_IF(!getHwComposer().isConnected(display->getPhysicalId()),
"Primary display is disconnected");
+ // TODO(b/241285876): The Scheduler needlessly depends on creating the CompositionEngine part of
+ // the DisplayDevice, hence the above commit of the primary display. Remove that special case by
+ // initializing the Scheduler after configureLocked, once decoupled from DisplayDevice.
+ initScheduler(display);
+ dispatchDisplayHotplugEvent(display->getPhysicalId(), true);
+
+ // Commit secondary display(s).
+ processDisplayChangesLocked();
+
// initialize our drawing state
mDrawingState = mCurrentState;
@@ -1039,7 +1060,7 @@
const PhysicalDisplayId displayId = snapshot.displayId();
- info->activeDisplayModeId = display->getActiveMode()->getId().value();
+ info->activeDisplayModeId = display->refreshRateConfigs().getActiveModePtr()->getId().value();
info->activeColorMode = display->getCompositionDisplay()->getState().colorMode;
info->supportedColorModes = getDisplayColorModes(displayId);
info->hdrCapabilities = display->getHdrCapabilities();
@@ -1163,7 +1184,7 @@
return;
}
- if (display->getActiveMode()->getResolution() != upcomingModeInfo.mode->getResolution()) {
+ if (display->getActiveMode().getResolution() != upcomingModeInfo.mode->getResolution()) {
auto& state = mCurrentState.displays.editValueFor(display->getDisplayToken());
// We need to generate new sequenceId in order to recreate the display (and this
// way the framebuffer).
@@ -1249,7 +1270,7 @@
ALOGV("%s changing active mode to %d(%s) for display %s", __func__, desiredModeId.value(),
to_string(*refreshRateOpt).c_str(), to_string(display->getId()).c_str());
- if (display->getActiveMode()->getId() == desiredModeId) {
+ if (display->getActiveMode().getId() == desiredModeId) {
// we are already in the requested mode, there is nothing left to do
desiredActiveModeChangeDone(display);
continue;
@@ -1298,7 +1319,7 @@
const auto display = getDisplayDeviceLocked(*displayToUpdateImmediately);
const auto desiredActiveMode = display->getDesiredActiveMode();
if (desiredActiveMode &&
- display->getActiveMode()->getId() == desiredActiveMode->mode->getId()) {
+ display->getActiveMode().getId() == desiredActiveMode->mode->getId()) {
desiredActiveModeChangeDone(display);
}
}
@@ -1872,17 +1893,12 @@
ATRACE_FORMAT("onComposerHalVsync%s", tracePeriod.c_str());
Mutex::Autolock lock(mStateLock);
- const auto displayId = getHwComposer().toPhysicalDisplayId(hwcDisplayId);
- if (displayId) {
- const auto token = getPhysicalDisplayTokenLocked(*displayId);
- const auto display = getDisplayDeviceLocked(token);
- display->onVsync(timestamp);
- }
if (!getHwComposer().onVsync(hwcDisplayId, timestamp)) {
return;
}
+ const auto displayId = getHwComposer().toPhysicalDisplayId(hwcDisplayId);
const bool isActiveDisplay =
displayId && getPhysicalDisplayTokenLocked(*displayId) == mActiveDisplayToken;
if (!isActiveDisplay) {
@@ -2087,7 +2103,7 @@
activeDisplay->getPowerMode() == hal::PowerMode::ON;
if (mPowerHintSessionEnabled) {
const auto& display = FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked()).get();
- const Period vsyncPeriod = Period::fromNs(display->getActiveMode()->getVsyncPeriod());
+ const Period vsyncPeriod = Period::fromNs(display->getActiveMode().getVsyncPeriod());
mPowerAdvisor->setCommitStart(frameTime);
mPowerAdvisor->setExpectedPresentTime(mExpectedPresentTime);
@@ -2190,6 +2206,13 @@
}
mPowerAdvisor->setDisplays(displayIds);
+ const bool updateTaskMetadata = mCompositionEngine->getFeatureFlags().test(
+ compositionengine::Feature::kSnapshotLayerMetadata);
+ if (updateTaskMetadata && (mVisibleRegionsDirty || mLayerMetadataSnapshotNeeded)) {
+ updateLayerMetadataSnapshot();
+ mLayerMetadataSnapshotNeeded = false;
+ }
+
if (DOES_CONTAIN_BORDER) {
refreshArgs.borderInfoList.clear();
mDrawingState.traverse([&refreshArgs](Layer* layer) {
@@ -2953,10 +2976,13 @@
LOG_FATAL_IF(!displaySurface);
auto display = setupNewDisplayDeviceInternal(displayToken, std::move(compositionDisplay), state,
displaySurface, producer);
- if (display->isPrimary()) {
- initScheduler(display);
- }
- if (!state.isVirtual()) {
+
+ if (mScheduler && !display->isVirtual()) {
+ // Display modes are reloaded on hotplug reconnect.
+ if (display->isPrimary()) {
+ mScheduler->setRefreshRateConfigs(display->holdRefreshRateConfigs());
+ }
+
dispatchDisplayHotplugEvent(display->getPhysicalId(), true);
}
@@ -3061,7 +3087,7 @@
void SurfaceFlinger::updateInternalDisplayVsyncLocked(const sp<DisplayDevice>& activeDisplay) {
mVsyncConfiguration->reset();
- const Fps refreshRate = activeDisplay->refreshRateConfigs().getActiveMode().getFps();
+ const Fps refreshRate = activeDisplay->getActiveMode().getFps();
updatePhaseConfiguration(refreshRate);
mRefreshRateStats->setRefreshRate(refreshRate);
}
@@ -3368,20 +3394,16 @@
mScheduler->onFrameRateOverridesChanged(mAppConnectionHandle, displayId);
}
-void SurfaceFlinger::initScheduler(const sp<DisplayDevice>& display) {
- if (mScheduler) {
- // If the scheduler is already initialized, this means that we received
- // a hotplug(connected) on the primary display. In that case we should
- // update the scheduler with the most recent display information.
- ALOGW("Scheduler already initialized, updating instead");
- mScheduler->setRefreshRateConfigs(display->holdRefreshRateConfigs());
- return;
- }
- const auto currRefreshRate = display->getActiveMode()->getFps();
- mRefreshRateStats = std::make_unique<scheduler::RefreshRateStats>(*mTimeStats, currRefreshRate,
- hal::PowerMode::OFF);
+void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) {
+ LOG_ALWAYS_FATAL_IF(mScheduler);
- mVsyncConfiguration = getFactory().createVsyncConfiguration(currRefreshRate);
+ const auto activeModePtr = display->refreshRateConfigs().getActiveModePtr();
+ const Fps activeRefreshRate = activeModePtr->getFps();
+ mRefreshRateStats =
+ std::make_unique<scheduler::RefreshRateStats>(*mTimeStats, activeRefreshRate,
+ hal::PowerMode::OFF);
+
+ mVsyncConfiguration = getFactory().createVsyncConfiguration(activeRefreshRate);
mVsyncModulator = sp<VsyncModulator>::make(mVsyncConfiguration->getCurrentConfigs());
using Feature = scheduler::Feature;
@@ -3414,7 +3436,7 @@
mScheduler->startTimers();
const auto configs = mVsyncConfiguration->getCurrentConfigs();
- const nsecs_t vsyncPeriod = currRefreshRate.getPeriodNsecs();
+ const nsecs_t vsyncPeriod = activeRefreshRate.getPeriodNsecs();
mAppConnectionHandle =
mScheduler->createConnection("app", mFrameTimeline->getTokenManager(),
/*workDuration=*/configs.late.appWorkDuration,
@@ -3442,7 +3464,7 @@
// This is a bit hacky, but this avoids a back-pointer into the main SF
// classes from EventThread, and there should be no run-time binder cost
// anyway since there are no connected apps at this point.
- mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, display->getActiveMode());
+ mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, activeModePtr);
}
void SurfaceFlinger::updatePhaseConfiguration(const Fps& refreshRate) {
@@ -4425,7 +4447,10 @@
layer->setGameModeForTree(static_cast<GameMode>(gameMode));
}
- if (layer->setMetadata(s.metadata)) flags |= eTraversalNeeded;
+ if (layer->setMetadata(s.metadata)) {
+ flags |= eTraversalNeeded;
+ mLayerMetadataSnapshotNeeded = true;
+ }
}
if (what & layer_state_t::eColorSpaceAgnosticChanged) {
if (layer->setColorSpaceAgnostic(s.colorSpaceAgnostic)) {
@@ -4915,6 +4940,25 @@
const auto flag = args.empty() ? ""s : std::string(String8(args[0]));
+ // Traversal of drawing state must happen on the main thread.
+ // Otherwise, SortedVector may have shared ownership during concurrent
+ // traversals, which can result in use-after-frees.
+ std::string compositionLayers;
+ mScheduler
+ ->schedule([&] {
+ StringAppendF(&compositionLayers, "Composition layers\n");
+ mDrawingState.traverseInZOrder([&](Layer* layer) {
+ auto* compositionState = layer->getCompositionState();
+ if (!compositionState || !compositionState->isVisible) return;
+
+ android::base::StringAppendF(&compositionLayers, "* Layer %p (%s)\n", layer,
+ layer->getDebugName() ? layer->getDebugName()
+ : "<unknown>");
+ compositionState->dump(compositionLayers);
+ });
+ })
+ .get();
+
bool dumpLayers = true;
{
TimedLock lock(mStateLock, s2ns(1), __func__);
@@ -4927,7 +4971,7 @@
(it->second)(args, asProto, result);
dumpLayers = false;
} else if (!asProto) {
- dumpAllLocked(args, result);
+ dumpAllLocked(args, compositionLayers, result);
}
}
@@ -5234,7 +5278,8 @@
}
}
-void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, std::string& result) const {
+void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, const std::string& compositionLayers,
+ std::string& result) const {
const bool colorize = !args.empty() && args[0] == String16("--color");
Colorizer colorizer(colorize);
@@ -5282,18 +5327,7 @@
StringAppendF(&result, "Visible layers (count = %zu)\n", mNumLayers.load());
colorizer.reset(result);
- {
- StringAppendF(&result, "Composition layers\n");
- mDrawingState.traverseInZOrder([&](Layer* layer) {
- auto* compositionState = layer->getCompositionState();
- if (!compositionState || !compositionState->isVisible) return;
-
- android::base::StringAppendF(&result, "* Layer %p (%s)\n", layer,
- layer->getDebugName() ? layer->getDebugName()
- : "<unknown>");
- compositionState->dump(result);
- });
- }
+ result.append(compositionLayers);
colorizer.bold(result);
StringAppendF(&result, "Displays (%zu entries)\n", mDisplays.size());
@@ -5331,10 +5365,10 @@
if (const auto display = getDefaultDisplayDeviceLocked()) {
std::string fps, xDpi, yDpi;
- if (const auto activeMode = display->getActiveMode()) {
- fps = to_string(activeMode->getFps());
+ if (const auto activeModePtr = display->refreshRateConfigs().getActiveModePtr()) {
+ fps = to_string(activeModePtr->getFps());
- const auto dpi = activeMode->getDpi();
+ const auto dpi = activeModePtr->getDpi();
xDpi = base::StringPrintf("%.2f", dpi.x);
yDpi = base::StringPrintf("%.2f", dpi.y);
} else {
@@ -5834,19 +5868,17 @@
return NO_ERROR;
}
case 1034: {
- auto future = mScheduler->schedule([&] {
- switch (n = data.readInt32()) {
- case 0:
- case 1:
- FTL_FAKE_GUARD(mStateLock,
- enableRefreshRateOverlay(static_cast<bool>(n)));
- break;
- default: {
- reply->writeBool(
- FTL_FAKE_GUARD(mStateLock, isRefreshRateOverlayEnabled()));
- }
- }
- });
+ auto future = mScheduler->schedule(
+ [&]() FTL_FAKE_GUARD(mStateLock) FTL_FAKE_GUARD(kMainThreadContext) {
+ switch (n = data.readInt32()) {
+ case 0:
+ case 1:
+ enableRefreshRateOverlay(static_cast<bool>(n));
+ break;
+ default:
+ reply->writeBool(isRefreshRateOverlayEnabled());
+ }
+ });
future.wait();
return NO_ERROR;
@@ -6636,6 +6668,11 @@
std::vector<Layer*> renderedLayers;
bool disableBlurs = false;
traverseLayers([&](Layer* layer) {
+ // Layer::prepareClientComposition uses the layer's snapshot to populate the resulting
+ // LayerSettings. Calling Layer::updateSnapshot ensures that LayerSettings are
+ // generated with the layer's current buffer and geometry.
+ layer->updateSnapshot(true /* updateGeometry */);
+
disableBlurs |= layer->getDrawingState().sidebandStream != nullptr;
Region clip(renderArea.getBounds());
@@ -6782,12 +6819,12 @@
// TODO(b/140204874): Leave the event in until we do proper testing with all apps that might
// be depending in this callback.
- const auto activeMode = display->getActiveMode();
+ const auto activeModePtr = display->refreshRateConfigs().getActiveModePtr();
if (isDisplayActiveLocked(display)) {
- mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, activeMode);
+ mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, activeModePtr);
toggleKernelIdleTimer();
} else {
- mScheduler->onNonPrimaryDisplayModeChanged(mAppConnectionHandle, activeMode);
+ mScheduler->onNonPrimaryDisplayModeChanged(mAppConnectionHandle, activeModePtr);
}
auto preferredModeOpt =
@@ -7077,7 +7114,7 @@
mRegionSamplingThread->onCompositionComplete(mScheduler->getScheduledFrameTime());
}
-void SurfaceFlinger::onActiveDisplaySizeChanged(const sp<DisplayDevice>& activeDisplay) {
+void SurfaceFlinger::onActiveDisplaySizeChanged(const sp<const DisplayDevice>& activeDisplay) {
mScheduler->onActiveDisplayAreaChanged(activeDisplay->getWidth() * activeDisplay->getHeight());
getRenderEngine().onActiveDisplaySizeChanged(activeDisplay->getSize());
}
@@ -7208,6 +7245,31 @@
return true;
}
+void SurfaceFlinger::updateLayerMetadataSnapshot() {
+ LayerMetadata parentMetadata;
+ for (const auto& layer : mDrawingState.layersSortedByZ) {
+ layer->updateMetadataSnapshot(parentMetadata);
+ }
+
+ std::unordered_set<Layer*> visited;
+ mDrawingState.traverse([&visited](Layer* layer) {
+ if (visited.find(layer) != visited.end()) {
+ return;
+ }
+
+ // If the layer isRelativeOf, then either it's relative metadata will be set
+ // recursively when updateRelativeMetadataSnapshot is called on its relative parent or
+ // it's relative parent has been deleted. Clear the layer's relativeLayerMetadata to ensure
+ // that layers with deleted relative parents don't hold stale relativeLayerMetadata.
+ if (layer->getDrawingState().isRelativeOf) {
+ layer->editLayerSnapshot()->relativeLayerMetadata = {};
+ return;
+ }
+
+ layer->updateRelativeMetadataSnapshot({}, visited);
+ });
+}
+
// gui::ISurfaceComposer
binder::Status SurfaceComposerAIDL::bootFinished() {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index f7684a0..85d11ba 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -333,7 +333,6 @@
private:
friend class BufferLayer;
- friend class BufferStateLayer;
friend class Client;
friend class FpsReporter;
friend class TunnelModeEnabledReporter;
@@ -374,7 +373,20 @@
const LayerVector::StateSet stateSet = LayerVector::StateSet::Invalid;
LayerVector layersSortedByZ;
- DefaultKeyedVector< wp<IBinder>, DisplayDeviceState> displays;
+
+ // TODO(b/241285876): Replace deprecated DefaultKeyedVector with ftl::SmallMap.
+ DefaultKeyedVector<wp<IBinder>, DisplayDeviceState> displays;
+
+ std::optional<size_t> getDisplayIndex(PhysicalDisplayId displayId) const {
+ for (size_t i = 0; i < displays.size(); i++) {
+ const auto& state = displays.valueAt(i);
+ if (state.physical && state.physical->id == displayId) {
+ return i;
+ }
+ }
+
+ return {};
+ }
bool colorMatrixChanged = true;
mat4 colorMatrix;
@@ -596,7 +608,7 @@
void binderDied(const wp<IBinder>& who) override;
// HWC2::ComposerCallback overrides:
- void onComposerHalVsync(hal::HWDisplayId, int64_t timestamp,
+ void onComposerHalVsync(hal::HWDisplayId, nsecs_t timestamp,
std::optional<hal::VsyncPeriodNanos>) override;
void onComposerHalHotplug(hal::HWDisplayId, hal::Connection) override;
void onComposerHalRefresh(hal::HWDisplayId) override;
@@ -687,6 +699,7 @@
bool latchBuffers();
void updateLayerGeometry();
+ void updateLayerMetadataSnapshot();
void updateInputFlinger();
void persistDisplayBrightness(bool needsComposite) REQUIRES(kMainThreadContext);
@@ -695,7 +708,7 @@
void commitInputWindowCommands() REQUIRES(mStateLock);
void updateCursorAsync();
- void initScheduler(const sp<DisplayDevice>& display) REQUIRES(mStateLock);
+ void initScheduler(const sp<const DisplayDevice>&) REQUIRES(mStateLock);
void updatePhaseConfiguration(const Fps&) REQUIRES(mStateLock);
void setVsyncConfig(const VsyncModulator::VsyncConfig&, nsecs_t vsyncPeriod);
@@ -1027,12 +1040,13 @@
void onActiveDisplayChangedLocked(const sp<DisplayDevice>& activeDisplay)
REQUIRES(mStateLock, kMainThreadContext);
- void onActiveDisplaySizeChanged(const sp<DisplayDevice>& activeDisplay);
+ void onActiveDisplaySizeChanged(const sp<const DisplayDevice>&);
/*
* Debugging & dumpsys
*/
- void dumpAllLocked(const DumpArgs& args, std::string& result) const REQUIRES(mStateLock);
+ void dumpAllLocked(const DumpArgs& args, const std::string& compositionLayers,
+ std::string& result) const REQUIRES(mStateLock);
void dumpHwcLayersMinidumpLocked(std::string& result) const REQUIRES(mStateLock);
void appendSfConfigString(std::string& result) const;
@@ -1163,6 +1177,9 @@
bool mSomeDataspaceChanged = false;
bool mForceTransactionDisplayChange = false;
+ // Set if LayerMetadata has changed since the last LayerMetadata snapshot.
+ bool mLayerMetadataSnapshotNeeded = false;
+
// Tracks layers that have pending frames which are candidates for being
// latched.
std::unordered_set<sp<Layer>, SpHash<Layer>> mLayersWithQueuedFrames;
@@ -1328,7 +1345,7 @@
std::unique_ptr<Hwc2::PowerAdvisor> mPowerAdvisor;
- void enableRefreshRateOverlay(bool enable) REQUIRES(mStateLock);
+ void enableRefreshRateOverlay(bool enable) REQUIRES(mStateLock, kMainThreadContext);
// Flag used to set override desired display mode from backdoor
bool mDebugDisplayModeSetByBackdoor = false;
diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
index 319d014..3e30dcb 100644
--- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
+++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
@@ -22,7 +22,6 @@
#include <cutils/properties.h>
#include <ui/GraphicBuffer.h>
-#include "BufferStateLayer.h"
#include "DisplayDevice.h"
#include "FrameTracer/FrameTracer.h"
#include "Layer.h"
@@ -89,8 +88,8 @@
return compositionengine::impl::createCompositionEngine();
}
-sp<BufferStateLayer> DefaultFactory::createBufferStateLayer(const LayerCreationArgs& args) {
- return sp<BufferStateLayer>::make(args);
+sp<Layer> DefaultFactory::createBufferStateLayer(const LayerCreationArgs& args) {
+ return sp<Layer>::make(args);
}
sp<Layer> DefaultFactory::createEffectLayer(const LayerCreationArgs& args) {
diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.h b/services/surfaceflinger/SurfaceFlingerDefaultFactory.h
index 6602240..6fca402 100644
--- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.h
+++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.h
@@ -41,7 +41,7 @@
std::unique_ptr<surfaceflinger::NativeWindowSurface> createNativeWindowSurface(
const sp<IGraphicBufferProducer>&) override;
std::unique_ptr<compositionengine::CompositionEngine> createCompositionEngine() override;
- sp<BufferStateLayer> createBufferStateLayer(const LayerCreationArgs& args) override;
+ sp<Layer> createBufferStateLayer(const LayerCreationArgs& args) override;
sp<Layer> createEffectLayer(const LayerCreationArgs& args) override;
std::unique_ptr<FrameTracer> createFrameTracer() override;
std::unique_ptr<frametimeline::FrameTimeline> createFrameTimeline(
diff --git a/services/surfaceflinger/SurfaceFlingerFactory.h b/services/surfaceflinger/SurfaceFlingerFactory.h
index dc2afd3..6d18ade 100644
--- a/services/surfaceflinger/SurfaceFlingerFactory.h
+++ b/services/surfaceflinger/SurfaceFlingerFactory.h
@@ -31,7 +31,6 @@
typedef int32_t PixelFormat;
class BufferLayerConsumer;
-class BufferStateLayer;
class DisplayDevice;
class FrameTracer;
class GraphicBuffer;
@@ -89,7 +88,7 @@
virtual std::unique_ptr<compositionengine::CompositionEngine> createCompositionEngine() = 0;
- virtual sp<BufferStateLayer> createBufferStateLayer(const LayerCreationArgs& args) = 0;
+ virtual sp<Layer> createBufferStateLayer(const LayerCreationArgs& args) = 0;
virtual sp<Layer> createEffectLayer(const LayerCreationArgs& args) = 0;
virtual std::unique_ptr<FrameTracer> createFrameTracer() = 0;
virtual std::unique_ptr<frametimeline::FrameTimeline> createFrameTimeline(
diff --git a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
index 6501e20..8817178 100644
--- a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
+++ b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
@@ -80,8 +80,8 @@
return compositionengine::impl::createCompositionEngine();
}
- sp<BufferStateLayer> createBufferStateLayer(const LayerCreationArgs& args) {
- return sp<BufferStateLayer>::make(args);
+ sp<Layer> createBufferStateLayer(const LayerCreationArgs& args) {
+ return sp<Layer>::make(args);
}
sp<Layer> createEffectLayer(const LayerCreationArgs& args) { return sp<Layer>::make(args); }
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
index 2297618..69dbfe0 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
@@ -30,7 +30,6 @@
#include <ui/DisplayStatInfo.h>
#include <ui/DynamicDisplayInfo.h>
-#include "BufferStateLayer.h"
#include "DisplayDevice.h"
#include "DisplayHardware/ComposerHal.h"
#include "FrameTimeline/FrameTimeline.h"
@@ -355,9 +354,7 @@
return compositionengine::impl::createCompositionEngine();
}
- sp<BufferStateLayer> createBufferStateLayer(const LayerCreationArgs &) override {
- return nullptr;
- }
+ sp<Layer> createBufferStateLayer(const LayerCreationArgs &) override { return nullptr; }
sp<Layer> createEffectLayer(const LayerCreationArgs &args) override {
return sp<Layer>::make(args);
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp
index 9ece260..0a142c3 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp
@@ -14,7 +14,6 @@
* limitations under the License.
*
*/
-#include <BufferStateLayer.h>
#include <Client.h>
#include <DisplayDevice.h>
#include <LayerRenderArea.h>
@@ -109,8 +108,7 @@
void LayerFuzzer::invokeBufferStateLayer() {
TestableSurfaceFlinger flinger;
sp<Client> client = sp<Client>::make(sp<SurfaceFlinger>::fromExisting(flinger.flinger()));
- sp<BufferStateLayer> layer =
- sp<BufferStateLayer>::make(createLayerCreationArgs(&flinger, client));
+ sp<Layer> layer = sp<Layer>::make(createLayerCreationArgs(&flinger, client));
sp<Fence> fence = sp<Fence>::make();
const std::shared_ptr<FenceTime> fenceTime = std::make_shared<FenceTime>(fence);
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
index 3fc2b7e..66bac44 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
@@ -322,7 +322,7 @@
LayerCreationArgs args(flinger.flinger(), client,
mFdp.ConsumeRandomLengthString(kRandomStringLength) /*name*/,
mFdp.ConsumeIntegral<uint16_t>() /*layerFlags*/, LayerMetadata());
- sp<Layer> layer = sp<BufferStateLayer>::make(args);
+ sp<Layer> layer = sp<Layer>::make(args);
layer->setFrameRateSelectionPriority(mFdp.ConsumeIntegral<int16_t>());
}
@@ -350,7 +350,7 @@
const RefreshRateConfigs::GlobalSignals globalSignals = {.touch = false, .idle = false};
std::vector<LayerRequirement> layers = {{.weight = mFdp.ConsumeFloatingPoint<float>()}};
- refreshRateConfigs.getBestRefreshRate(layers, globalSignals);
+ refreshRateConfigs.getRankedRefreshRates(layers, globalSignals);
layers[0].name = mFdp.ConsumeRandomLengthString(kRandomStringLength);
layers[0].ownerUid = mFdp.ConsumeIntegral<uint16_t>();
diff --git a/services/surfaceflinger/layerproto/Android.bp b/services/surfaceflinger/layerproto/Android.bp
index 973a439..7287dd0 100644
--- a/services/surfaceflinger/layerproto/Android.bp
+++ b/services/surfaceflinger/layerproto/Android.bp
@@ -44,10 +44,11 @@
}
java_library_static {
- name: "layersprotosnano",
+ name: "layersprotoslite",
host_supported: true,
proto: {
- type: "nano",
+ type: "lite",
+ include_dirs: ["external/protobuf/src"],
},
srcs: ["*.proto"],
sdk_version: "core_platform",
@@ -56,7 +57,7 @@
jarjar_rules: "jarjar-rules.txt",
},
host: {
- static_libs: ["libprotobuf-java-nano"],
+ static_libs: ["libprotobuf-java-lite"],
},
},
}
diff --git a/services/surfaceflinger/tests/LayerBorder_test.cpp b/services/surfaceflinger/tests/LayerBorder_test.cpp
index 0d55ec1..85108ad 100644
--- a/services/surfaceflinger/tests/LayerBorder_test.cpp
+++ b/services/surfaceflinger/tests/LayerBorder_test.cpp
@@ -215,13 +215,13 @@
});
}
-TEST_F(LayerBorderTest, BufferStateLayer) {
+TEST_F(LayerBorderTest, LayerWithBuffer) {
asTransaction([&](Transaction& t) {
t.hide(mEffectLayer1);
t.hide(mEffectLayer2);
t.show(mContainerLayer);
- sp<SurfaceControl> bufferStateLayer =
+ sp<SurfaceControl> layer =
mClient->createSurface(String8("BufferState"), 0 /* width */, 0 /* height */,
PIXEL_FORMAT_RGBA_8888,
ISurfaceComposerClient::eFXSurfaceBufferState,
@@ -236,9 +236,9 @@
TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 200, 200), Color::GREEN);
TransactionUtils::fillGraphicBufferColor(buffer, Rect(200, 200, 400, 400), Color::BLUE);
- t.setBuffer(bufferStateLayer, buffer);
- t.setPosition(bufferStateLayer, 100, 100);
- t.show(bufferStateLayer);
+ t.setBuffer(layer, buffer);
+ t.setPosition(layer, 100, 100);
+ t.show(layer);
t.enableBorder(mContainerLayer, true, 20, mColorOrange);
});
}
diff --git a/services/surfaceflinger/tests/LayerCallback_test.cpp b/services/surfaceflinger/tests/LayerCallback_test.cpp
index 1460fe1..26dbc76 100644
--- a/services/surfaceflinger/tests/LayerCallback_test.cpp
+++ b/services/surfaceflinger/tests/LayerCallback_test.cpp
@@ -51,7 +51,7 @@
LayerTransactionTest::TearDown();
}
- virtual sp<SurfaceControl> createBufferStateLayer() {
+ virtual sp<SurfaceControl> createLayerWithBuffer() {
return createLayer(mClient, "test", 0, 0, ISurfaceComposerClient::eFXSurfaceBufferState);
}
@@ -164,7 +164,7 @@
TEST_F(LayerCallbackTest, BufferColor) {
sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer = createLayerWithBuffer());
Transaction transaction;
CallbackHelper callback;
@@ -183,7 +183,7 @@
TEST_F(LayerCallbackTest, NoBufferNoColor) {
sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer = createLayerWithBuffer());
Transaction transaction;
CallbackHelper callback;
@@ -206,7 +206,7 @@
TEST_F(LayerCallbackTest, BufferNoColor) {
sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer = createLayerWithBuffer());
Transaction transaction;
CallbackHelper callback;
@@ -228,7 +228,7 @@
TEST_F(LayerCallbackTest, NoBufferColor) {
sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer = createLayerWithBuffer());
Transaction transaction;
CallbackHelper callback;
@@ -266,7 +266,7 @@
TEST_F(LayerCallbackTest, OffScreen) {
sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer = createLayerWithBuffer());
Transaction transaction;
CallbackHelper callback;
@@ -288,8 +288,8 @@
TEST_F(LayerCallbackTest, MergeBufferNoColor) {
sp<SurfaceControl> layer1, layer2;
- ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer());
- ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer1 = createLayerWithBuffer());
+ ASSERT_NO_FATAL_FAILURE(layer2 = createLayerWithBuffer());
Transaction transaction1, transaction2;
CallbackHelper callback1, callback2;
@@ -322,8 +322,8 @@
TEST_F(LayerCallbackTest, MergeNoBufferColor) {
sp<SurfaceControl> layer1, layer2;
- ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer());
- ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer1 = createLayerWithBuffer());
+ ASSERT_NO_FATAL_FAILURE(layer2 = createLayerWithBuffer());
Transaction transaction1, transaction2;
CallbackHelper callback1, callback2;
@@ -357,8 +357,8 @@
TEST_F(LayerCallbackTest, MergeOneBufferOneColor) {
sp<SurfaceControl> layer1, layer2;
- ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer());
- ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer1 = createLayerWithBuffer());
+ ASSERT_NO_FATAL_FAILURE(layer2 = createLayerWithBuffer());
Transaction transaction1, transaction2;
CallbackHelper callback1, callback2;
@@ -392,8 +392,8 @@
}
TEST_F(LayerCallbackTest, Merge_SameCallback) {
sp<SurfaceControl> layer1, layer2;
- ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer());
- ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer1 = createLayerWithBuffer());
+ ASSERT_NO_FATAL_FAILURE(layer2 = createLayerWithBuffer());
Transaction transaction1, transaction2;
CallbackHelper callback;
@@ -418,7 +418,7 @@
TEST_F(LayerCallbackTest, Merge_SameLayer) {
sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer = createLayerWithBuffer());
Transaction transaction1, transaction2;
CallbackHelper callback1, callback2;
@@ -485,7 +485,7 @@
TEST_F(LayerCallbackTest, MultipleTransactions) {
sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer = createLayerWithBuffer());
Transaction transaction;
CallbackHelper callback;
@@ -510,7 +510,7 @@
TEST_F(LayerCallbackTest, MultipleTransactions_NoStateChange) {
sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer = createLayerWithBuffer());
Transaction transaction;
CallbackHelper callback;
@@ -541,7 +541,7 @@
TEST_F(LayerCallbackTest, MultipleTransactions_SameStateChange) {
sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer = createLayerWithBuffer());
Transaction transaction;
CallbackHelper callback;
@@ -579,8 +579,8 @@
TEST_F(LayerCallbackTest, MultipleTransactions_Merge) {
sp<SurfaceControl> layer1, layer2;
- ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer());
- ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer1 = createLayerWithBuffer());
+ ASSERT_NO_FATAL_FAILURE(layer2 = createLayerWithBuffer());
Transaction transaction1, transaction2;
CallbackHelper callback1, callback2;
@@ -799,7 +799,7 @@
// TODO (b/183181768): Fix & re-enable
TEST_F(LayerCallbackTest, DISABLED_MultipleTransactions_SingleFrame) {
sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer = createLayerWithBuffer());
Transaction transaction;
CallbackHelper callback;
@@ -823,7 +823,7 @@
TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_NoStateChange) {
sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer = createLayerWithBuffer());
// Normal call to set up test
Transaction transaction;
@@ -858,7 +858,7 @@
TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_SameStateChange) {
sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer = createLayerWithBuffer());
// Normal call to set up test
Transaction transaction;
@@ -901,7 +901,7 @@
TEST_F(LayerCallbackTest, DesiredPresentTime) {
sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer = createLayerWithBuffer());
Transaction transaction;
CallbackHelper callback;
@@ -925,7 +925,7 @@
TEST_F(LayerCallbackTest, DesiredPresentTime_Multiple) {
sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer = createLayerWithBuffer());
Transaction transaction;
CallbackHelper callback1;
@@ -971,7 +971,7 @@
// TODO (b/183181768): Fix & re-enable
TEST_F(LayerCallbackTest, DISABLED_DesiredPresentTime_OutOfOrder) {
sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer = createLayerWithBuffer());
Transaction transaction;
CallbackHelper callback1;
@@ -1015,7 +1015,7 @@
TEST_F(LayerCallbackTest, DesiredPresentTime_Past) {
sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer = createLayerWithBuffer());
Transaction transaction;
CallbackHelper callback;
@@ -1039,7 +1039,7 @@
TEST_F(LayerCallbackTest, ExpectedPresentTime) {
sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer = createLayerWithBuffer());
Transaction transaction;
CallbackHelper callback;
@@ -1065,8 +1065,8 @@
// b202394221
TEST_F(LayerCallbackTest, EmptyBufferStateChanges) {
sp<SurfaceControl> bufferLayer, emptyBufferLayer;
- ASSERT_NO_FATAL_FAILURE(bufferLayer = createBufferStateLayer());
- ASSERT_NO_FATAL_FAILURE(emptyBufferLayer = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayerWithBuffer());
+ ASSERT_NO_FATAL_FAILURE(emptyBufferLayer = createLayerWithBuffer());
Transaction transaction;
CallbackHelper callback;
@@ -1120,7 +1120,7 @@
TEST_F(LayerCallbackTest, CommitCallbackOffscreenLayer) {
sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer = createLayerWithBuffer());
sp<SurfaceControl> offscreenLayer =
createSurface(mClient, "Offscreen Layer", 0, 0, PIXEL_FORMAT_RGBA_8888,
ISurfaceComposerClient::eFXSurfaceBufferState, layer.get());
@@ -1151,7 +1151,7 @@
TEST_F(LayerCallbackTest, TransactionCommittedCallback_BSL) {
sp<SurfaceControl> layer;
- ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer());
+ ASSERT_NO_FATAL_FAILURE(layer = createLayerWithBuffer());
Transaction transaction;
CallbackHelper callback;
diff --git a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp
index bbe7ae8..bf7cae9 100644
--- a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp
+++ b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp
@@ -399,7 +399,7 @@
.apply();
ASSERT_NO_FATAL_FAILURE(
fillBufferQueueLayerColor(layerTransparent, Color::TRANSPARENT, 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layerR, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(layerR, Color::RED, 32, 32));
getScreenCapture()->expectColor(Rect(16, 16, 48, 48), Color::RED);
}
@@ -482,7 +482,7 @@
}
}
-// RED: Color layer base color and BufferQueueLayer/BufferStateLayer fill
+// RED: Color layer base color and Layer buffer fill
// BLUE: prior background color
// GREEN: final background color
// BLACK: no color or fill
@@ -516,7 +516,7 @@
case ISurfaceComposerClient::eFXSurfaceBufferState:
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", width, height, layerType));
if (bufferFill) {
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, fillColor, width, height));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(layer, fillColor, width, height));
expectedColor = fillColor;
}
Transaction().setCrop(layer, Rect(0, 0, width, height)).apply();
@@ -832,7 +832,7 @@
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(
layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(layer, Color::RED, 32, 32));
const Rect crop(8, 8, 24, 24);
Transaction().setCrop(layer, crop).apply();
@@ -863,7 +863,7 @@
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(
layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(layer, Color::RED, 32, 32));
{
SCOPED_TRACE("empty rect");
@@ -944,7 +944,7 @@
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(
layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(layer, Color::RED, 32, 32));
const Rect crop(8, 8, 24, 24);
Transaction().setPosition(layer, 32, 32).setCrop(layer, crop).apply();
@@ -972,7 +972,7 @@
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(
layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(layer, Color::RED, 32, 32));
const Rect frame(8, 8, 24, 24);
Transaction t;
@@ -988,7 +988,7 @@
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(
layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(layer, Color::RED, 32, 32));
Transaction t;
{
@@ -1014,7 +1014,7 @@
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(
layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 10, 10));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(layer, Color::RED, 10, 10));
// A layer with a buffer will have a computed size that matches the buffer size.
auto shot = getScreenCapture();
@@ -1026,11 +1026,11 @@
sp<SurfaceControl> parent, child;
ASSERT_NO_FATAL_FAILURE(
parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(parent, Color::RED, 32, 32));
ASSERT_NO_FATAL_FAILURE(
child = createLayer("test", 10, 10, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(child, Color::BLUE, 10, 10));
Transaction().reparent(child, parent).apply();
@@ -1047,7 +1047,7 @@
ASSERT_NO_FATAL_FAILURE(
child = createLayer("test", 10, 10, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(child, Color::BLUE, 10, 10));
Transaction().reparent(child, parent).apply();
@@ -1061,7 +1061,7 @@
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(
layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(layer, Color::RED, 32, 32));
std::this_thread::sleep_for(500ms);
@@ -1080,9 +1080,9 @@
child = createLayer("test", 10, 10, ISurfaceComposerClient::eFXSurfaceBufferState));
Transaction().reparent(child, parent).apply();
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(parent, Color::RED, 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(child, Color::BLUE, 10, 10));
Rect childDst(0, 16, 32, 32);
Transaction t;
TransactionUtils::setFrame(t, child, Rect(0, 0, 10, 10), childDst);
@@ -1099,7 +1099,7 @@
ASSERT_NO_FATAL_FAILURE(
layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(layer, Color::RED, 32, 32));
auto shot = getScreenCapture();
shot->expectColor(Rect(0, 0, 32, 32), Color::RED);
@@ -1111,7 +1111,7 @@
ASSERT_NO_FATAL_FAILURE(
layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(layer, Color::RED, 32, 32));
{
SCOPED_TRACE("set buffer 1");
@@ -1120,7 +1120,7 @@
shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
}
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::BLUE, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(layer, Color::BLUE, 32, 32));
{
SCOPED_TRACE("set buffer 2");
@@ -1129,7 +1129,7 @@
shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK);
}
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(layer, Color::RED, 32, 32));
{
SCOPED_TRACE("set buffer 3");
@@ -1148,7 +1148,7 @@
ASSERT_NO_FATAL_FAILURE(
layer2 = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer1, Color::RED, 64, 64));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(layer1, Color::RED, 64, 64));
{
SCOPED_TRACE("set layer 1 buffer red");
@@ -1156,7 +1156,7 @@
shot->expectColor(Rect(0, 0, 64, 64), Color::RED);
}
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer2, Color::BLUE, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(layer2, Color::BLUE, 32, 32));
{
SCOPED_TRACE("set layer 2 buffer blue");
@@ -1166,7 +1166,7 @@
shot->expectColor(Rect(0, 32, 32, 64), Color::RED);
}
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer1, Color::GREEN, 64, 64));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(layer1, Color::GREEN, 64, 64));
{
SCOPED_TRACE("set layer 1 buffer green");
auto shot = getScreenCapture();
@@ -1175,7 +1175,7 @@
shot->expectColor(Rect(0, 32, 32, 64), Color::GREEN);
}
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer2, Color::WHITE, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(layer2, Color::WHITE, 32, 32));
{
SCOPED_TRACE("set layer 2 buffer white");
diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h
index 0e8f3dd..774c1d7 100644
--- a/services/surfaceflinger/tests/LayerTransactionTest.h
+++ b/services/surfaceflinger/tests/LayerTransactionTest.h
@@ -137,8 +137,8 @@
postBufferQueueLayerBuffer(layer);
}
- virtual void fillBufferStateLayerColor(const sp<SurfaceControl>& layer, const Color& color,
- int32_t bufferWidth, int32_t bufferHeight) {
+ virtual void fillBufferLayerColor(const sp<SurfaceControl>& layer, const Color& color,
+ int32_t bufferWidth, int32_t bufferHeight) {
sp<GraphicBuffer> buffer =
sp<GraphicBuffer>::make(static_cast<uint32_t>(bufferWidth),
static_cast<uint32_t>(bufferHeight), PIXEL_FORMAT_RGBA_8888,
@@ -159,7 +159,7 @@
fillBufferQueueLayerColor(layer, color, bufferWidth, bufferHeight);
break;
case ISurfaceComposerClient::eFXSurfaceBufferState:
- fillBufferStateLayerColor(layer, color, bufferWidth, bufferHeight);
+ fillBufferLayerColor(layer, color, bufferWidth, bufferHeight);
break;
default:
ASSERT_TRUE(false) << "unsupported layer type: " << mLayerType;
diff --git a/services/surfaceflinger/tests/LayerTransaction_test.cpp b/services/surfaceflinger/tests/LayerTransaction_test.cpp
index c206e1f..cbd54e7 100644
--- a/services/surfaceflinger/tests/LayerTransaction_test.cpp
+++ b/services/surfaceflinger/tests/LayerTransaction_test.cpp
@@ -32,7 +32,7 @@
Transaction().setTransformToDisplayInverse(layer, false).apply();
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::GREEN, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(layer, Color::GREEN, 32, 32));
Transaction().setTransformToDisplayInverse(layer, true).apply();
}
@@ -161,7 +161,7 @@
TEST_F(LayerTransactionTest, BufferTakesPriorityOverBlur) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(layer, Color::RED, 32, 32));
Transaction().setBackgroundBlurRadius(layer, 5).apply();
{
SCOPED_TRACE("BufferTakesPriorityOverBlur");
@@ -174,7 +174,7 @@
TEST_F(LayerTransactionTest, BufferTakesPriorityOverColor) {
sp<SurfaceControl> layer;
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(layer, Color::RED, 32, 32));
Transaction().setColor(layer, {Color::GREEN.r, Color::GREEN.g, Color::GREEN.b}).apply();
{
SCOPED_TRACE("BufferTakesPriorityOverColor");
diff --git a/services/surfaceflinger/tests/MirrorLayer_test.cpp b/services/surfaceflinger/tests/MirrorLayer_test.cpp
index a921aa8..faaef5d 100644
--- a/services/surfaceflinger/tests/MirrorLayer_test.cpp
+++ b/services/surfaceflinger/tests/MirrorLayer_test.cpp
@@ -193,14 +193,14 @@
shot->expectColor(Rect(750, 750, 950, 950), Color::GREEN);
}
- sp<SurfaceControl> bufferStateLayer =
- createLayer("BufferStateLayer", 200, 200, ISurfaceComposerClient::eFXSurfaceBufferState,
+ sp<SurfaceControl> layer =
+ createLayer("Layer", 200, 200, ISurfaceComposerClient::eFXSurfaceBufferState,
mChildLayer.get());
- fillBufferStateLayerColor(bufferStateLayer, Color::BLUE, 200, 200);
- Transaction().show(bufferStateLayer).apply();
+ fillBufferLayerColor(layer, Color::BLUE, 200, 200);
+ Transaction().show(layer).apply();
{
- SCOPED_TRACE("Initial Mirror BufferStateLayer");
+ SCOPED_TRACE("Initial Mirror Layer");
auto shot = screenshot();
// Buffer mirror
shot->expectColor(Rect(550, 550, 750, 750), Color::BLUE);
@@ -208,9 +208,9 @@
shot->expectColor(Rect(750, 750, 950, 950), Color::GREEN);
}
- fillBufferStateLayerColor(bufferStateLayer, Color::WHITE, 200, 200);
+ fillBufferLayerColor(layer, Color::WHITE, 200, 200);
{
- SCOPED_TRACE("Update BufferStateLayer");
+ SCOPED_TRACE("Update Layer");
auto shot = screenshot();
// Buffer mirror
shot->expectColor(Rect(550, 550, 750, 750), Color::WHITE);
@@ -218,9 +218,9 @@
shot->expectColor(Rect(750, 750, 950, 950), Color::GREEN);
}
- Transaction().reparent(bufferStateLayer, nullptr).apply();
+ Transaction().reparent(layer, nullptr).apply();
{
- SCOPED_TRACE("Removed BufferStateLayer");
+ SCOPED_TRACE("Removed Layer");
auto shot = screenshot();
// Buffer mirror
shot->expectColor(Rect(550, 550, 750, 750), Color::GREEN);
@@ -283,7 +283,7 @@
sp<SurfaceControl> grandchild =
createLayer("Grandchild layer", 50, 50, ISurfaceComposerClient::eFXSurfaceBufferState,
mChildLayer.get());
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(grandchild, Color::BLUE, 50, 50));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(grandchild, Color::BLUE, 50, 50));
Rect childBounds = Rect(50, 50, 450, 450);
asTransaction([&](Transaction& t) {
diff --git a/services/surfaceflinger/tests/ScreenCapture_test.cpp b/services/surfaceflinger/tests/ScreenCapture_test.cpp
index d78c8a9..3a5e532 100644
--- a/services/surfaceflinger/tests/ScreenCapture_test.cpp
+++ b/services/surfaceflinger/tests/ScreenCapture_test.cpp
@@ -371,7 +371,7 @@
ScreenCaptureResults captureResults;
ASSERT_EQ(BAD_VALUE, ScreenCapture::captureLayers(args, captureResults));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(child, Color::RED, 32, 32));
SurfaceComposerClient::Transaction().apply(true);
ASSERT_EQ(NO_ERROR, ScreenCapture::captureLayers(args, captureResults));
ScreenCapture sc(captureResults.buffer, captureResults.capturedHdrLayers);
@@ -449,8 +449,8 @@
ISurfaceComposerClient::eFXSurfaceBufferState,
redLayer.get());
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(redLayer, Color::RED, 60, 60));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(blueLayer, Color::BLUE, 30, 30));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(redLayer, Color::RED, 60, 60));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(blueLayer, Color::BLUE, 30, 30));
SurfaceComposerClient::Transaction()
.setLayer(redLayer, INT32_MAX - 1)
@@ -484,8 +484,8 @@
ISurfaceComposerClient::eFXSurfaceBufferState,
redLayer.get());
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(redLayer, Color::RED, 60, 60));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(blueLayer, Color::BLUE, 30, 30));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(redLayer, Color::RED, 60, 60));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(blueLayer, Color::BLUE, 30, 30));
SurfaceComposerClient::Transaction()
.setLayer(redLayer, INT32_MAX - 1)
@@ -549,8 +549,8 @@
ISurfaceComposerClient::eSecure |
ISurfaceComposerClient::eFXSurfaceBufferState,
redLayer.get());
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(redLayer, Color::RED, 60, 60));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(secureLayer, Color::BLUE, 30, 30));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(redLayer, Color::RED, 60, 60));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(secureLayer, Color::BLUE, 30, 30));
auto redLayerHandle = redLayer->getHandle();
Transaction()
@@ -803,7 +803,7 @@
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test layer", 32, 32,
ISurfaceComposerClient::eFXSurfaceBufferState,
mBGSurfaceControl.get()));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(layer, Color::RED, 32, 32));
Transaction().show(layer).setLayer(layer, INT32_MAX).apply();
LayerCaptureArgs captureArgs;
@@ -825,7 +825,7 @@
mCapture->expectColor(Rect(0, 0, 32, 32),
Color{expectedColor, expectedColor, expectedColor, 255}, tolerance);
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::BLUE, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(layer, Color::BLUE, 32, 32));
ScreenCapture::captureLayers(&mCapture, captureArgs);
expectedColor = luminance.b * 255;
@@ -838,7 +838,7 @@
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test layer", 32, 32,
ISurfaceComposerClient::eFXSurfaceBufferState,
mBGSurfaceControl.get()));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(layer, Color::RED, 32, 32));
Transaction().show(layer).hide(mFGSurfaceControl).reparent(layer, nullptr).apply();
@@ -865,7 +865,7 @@
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test layer", 32, 32,
ISurfaceComposerClient::eFXSurfaceBufferState,
mBGSurfaceControl.get()));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::BLACK, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(layer, Color::BLACK, 32, 32));
Transaction()
.show(layer)
.setLayer(layer, INT32_MAX)
@@ -885,7 +885,7 @@
ASSERT_NO_FATAL_FAILURE(layer = createLayer("test layer", 32, 32,
ISurfaceComposerClient::eFXSurfaceBufferState,
mBGSurfaceControl.get()));
- ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::BLACK, 32, 32));
+ ASSERT_NO_FATAL_FAILURE(fillBufferLayerColor(layer, Color::BLACK, 32, 32));
Transaction()
.show(layer)
.setLayer(layer, INT32_MAX)
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index dec14d0..4469df0 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -109,6 +109,7 @@
"SurfaceFlinger_SetDisplayStateTest.cpp",
"SurfaceFlinger_SetPowerModeInternalTest.cpp",
"SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp",
+ "SurfaceFlinger_UpdateLayerMetadataSnapshotTest.cpp",
"SchedulerTest.cpp",
"SetFrameRateTest.cpp",
"RefreshRateConfigsTest.cpp",
diff --git a/services/surfaceflinger/tests/unittests/CachingTest.cpp b/services/surfaceflinger/tests/unittests/CachingTest.cpp
index 9082a22..c1cbbfb 100644
--- a/services/surfaceflinger/tests/unittests/CachingTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CachingTest.cpp
@@ -20,7 +20,8 @@
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <gui/BufferQueue.h>
-#include "BufferStateLayer.h"
+
+#include "HwcSlotGenerator.h"
namespace android {
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 9485f48..7148c11 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -491,7 +491,7 @@
static constexpr IComposerClient::BlendMode BLENDMODE =
IComposerClient::BlendMode::PREMULTIPLIED;
- static void setupLatchedBuffer(CompositionTest* test, sp<BufferStateLayer> layer) {
+ static void setupLatchedBuffer(CompositionTest* test, sp<Layer> layer) {
Mock::VerifyAndClear(test->mRenderEngine);
const auto buffer = std::make_shared<
@@ -515,7 +515,7 @@
Mock::VerifyAndClear(test->mRenderEngine);
}
- static void setupLayerState(CompositionTest* test, sp<BufferStateLayer> layer) {
+ static void setupLayerState(CompositionTest* test, sp<Layer> layer) {
setupLatchedBuffer(test, layer);
}
@@ -699,7 +699,7 @@
using Base = BaseLayerProperties<SidebandLayerProperties>;
static constexpr IComposerClient::BlendMode BLENDMODE = IComposerClient::BlendMode::NONE;
- static void setupLayerState(CompositionTest* test, sp<BufferStateLayer> layer) {
+ static void setupLayerState(CompositionTest* test, sp<Layer> layer) {
sp<NativeHandle> stream =
NativeHandle::create(reinterpret_cast<native_handle_t*>(DEFAULT_SIDEBAND_STREAM),
false);
@@ -780,14 +780,14 @@
struct CursorLayerProperties : public BaseLayerProperties<CursorLayerProperties> {
using Base = BaseLayerProperties<CursorLayerProperties>;
- static void setupLayerState(CompositionTest* test, sp<BufferStateLayer> layer) {
+ static void setupLayerState(CompositionTest* test, sp<Layer> layer) {
Base::setupLayerState(test, layer);
test->mFlinger.setLayerPotentialCursor(layer, true);
}
};
struct NoLayerVariant {
- using FlingerLayerType = sp<BufferStateLayer>;
+ using FlingerLayerType = sp<Layer>;
static FlingerLayerType createLayer(CompositionTest*) { return FlingerLayerType(); }
static void injectLayer(CompositionTest*, FlingerLayerType) {}
@@ -892,17 +892,17 @@
template <typename LayerProperties>
struct BufferLayerVariant : public BaseLayerVariant<LayerProperties> {
using Base = BaseLayerVariant<LayerProperties>;
- using FlingerLayerType = sp<BufferStateLayer>;
+ using FlingerLayerType = sp<Layer>;
static FlingerLayerType createLayer(CompositionTest* test) {
test->mFlinger.mutableTexturePool().push_back(DEFAULT_TEXTURE_ID);
FlingerLayerType layer =
- Base::template createLayerWithFactory<BufferStateLayer>(test, [test]() {
+ Base::template createLayerWithFactory<Layer>(test, [test]() {
LayerCreationArgs args(test->mFlinger.flinger(), sp<Client>(), "test-layer",
LayerProperties::LAYER_FLAGS, LayerMetadata());
args.textureName = test->mFlinger.mutableTexturePool().back();
- return sp<BufferStateLayer>::make(args);
+ return sp<Layer>::make(args);
});
LayerProperties::setupLayerState(test, layer);
diff --git a/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp b/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp
index 9789df5..1cd9e49 100644
--- a/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp
+++ b/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp
@@ -24,7 +24,6 @@
#include <gtest/gtest.h>
#include <gui/LayerMetadata.h>
-#include "BufferStateLayer.h"
#include "FpsReporter.h"
#include "Layer.h"
#include "TestableSurfaceFlinger.h"
@@ -79,7 +78,7 @@
static constexpr int32_t PRIORITY_UNSET = -1;
void setupScheduler();
- sp<BufferStateLayer> createBufferStateLayer(LayerMetadata metadata);
+ sp<Layer> createBufferStateLayer(LayerMetadata metadata);
TestableSurfaceFlinger mFlinger;
mock::FrameTimeline mFrameTimeline =
@@ -115,10 +114,10 @@
ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
}
-sp<BufferStateLayer> FpsReporterTest::createBufferStateLayer(LayerMetadata metadata = {}) {
+sp<Layer> FpsReporterTest::createBufferStateLayer(LayerMetadata metadata = {}) {
sp<Client> client;
LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", LAYER_FLAGS, metadata);
- return sp<BufferStateLayer>::make(args);
+ return sp<Layer>::make(args);
}
void FpsReporterTest::setupScheduler() {
diff --git a/services/surfaceflinger/tests/unittests/GameModeTest.cpp b/services/surfaceflinger/tests/unittests/GameModeTest.cpp
index cd857c3..29aa717 100644
--- a/services/surfaceflinger/tests/unittests/GameModeTest.cpp
+++ b/services/surfaceflinger/tests/unittests/GameModeTest.cpp
@@ -53,11 +53,10 @@
ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
}
- sp<BufferStateLayer> createBufferStateLayer() {
+ sp<Layer> createLayer() {
sp<Client> client;
- LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", 0,
- LayerMetadata());
- return sp<BufferStateLayer>::make(args);
+ LayerCreationArgs args(mFlinger.flinger(), client, "layer", 0, LayerMetadata());
+ return sp<Layer>::make(args);
}
void setupScheduler() {
@@ -108,9 +107,9 @@
};
TEST_F(GameModeTest, SetGameModeSetsForAllCurrentChildren) {
- sp<BufferStateLayer> rootLayer = createBufferStateLayer();
- sp<BufferStateLayer> childLayer1 = createBufferStateLayer();
- sp<BufferStateLayer> childLayer2 = createBufferStateLayer();
+ sp<Layer> rootLayer = createLayer();
+ sp<Layer> childLayer1 = createLayer();
+ sp<Layer> childLayer2 = createLayer();
rootLayer->addChild(childLayer1);
rootLayer->addChild(childLayer2);
rootLayer->setGameModeForTree(GameMode::Performance);
@@ -121,8 +120,8 @@
}
TEST_F(GameModeTest, AddChildAppliesGameModeFromParent) {
- sp<BufferStateLayer> rootLayer = createBufferStateLayer();
- sp<BufferStateLayer> childLayer = createBufferStateLayer();
+ sp<Layer> rootLayer = createLayer();
+ sp<Layer> childLayer = createLayer();
rootLayer->setGameModeForTree(GameMode::Performance);
rootLayer->addChild(childLayer);
@@ -131,8 +130,8 @@
}
TEST_F(GameModeTest, RemoveChildResetsGameMode) {
- sp<BufferStateLayer> rootLayer = createBufferStateLayer();
- sp<BufferStateLayer> childLayer = createBufferStateLayer();
+ sp<Layer> rootLayer = createLayer();
+ sp<Layer> childLayer = createLayer();
rootLayer->setGameModeForTree(GameMode::Performance);
rootLayer->addChild(childLayer);
@@ -144,9 +143,9 @@
}
TEST_F(GameModeTest, ReparentingDoesNotOverrideMetadata) {
- sp<BufferStateLayer> rootLayer = createBufferStateLayer();
- sp<BufferStateLayer> childLayer1 = createBufferStateLayer();
- sp<BufferStateLayer> childLayer2 = createBufferStateLayer();
+ sp<Layer> rootLayer = createLayer();
+ sp<Layer> childLayer1 = createLayer();
+ sp<Layer> childLayer2 = createLayer();
rootLayer->setGameModeForTree(GameMode::Standard);
rootLayer->addChild(childLayer1);
diff --git a/services/surfaceflinger/tests/unittests/LayerTestUtils.cpp b/services/surfaceflinger/tests/unittests/LayerTestUtils.cpp
index 14304d1..ee42e19 100644
--- a/services/surfaceflinger/tests/unittests/LayerTestUtils.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerTestUtils.cpp
@@ -29,7 +29,7 @@
sp<Client> client;
LayerCreationArgs args(flinger.flinger(), client, "buffer-state-layer", LAYER_FLAGS,
LayerMetadata());
- return sp<BufferStateLayer>::make(args);
+ return sp<Layer>::make(args);
}
sp<Layer> EffectLayerFactory::createLayer(TestableSurfaceFlinger& flinger) {
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index 5d9b2a8..a706c4b 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -41,6 +41,7 @@
struct TestableRefreshRateConfigs : RefreshRateConfigs {
using RefreshRateConfigs::RefreshRateConfigs;
+ using RefreshRateConfigs::RefreshRateOrder;
void setActiveModeId(DisplayModeId modeId) {
ftl::FakeGuard guard(kMainThreadContext);
@@ -67,19 +68,30 @@
return getMinRefreshRateByPolicyLocked();
}
+ DisplayModePtr getMaxRefreshRateByPolicy() const {
+ std::lock_guard lock(mLock);
+ return getMaxRefreshRateByPolicyLocked(getActiveModeItLocked()->second->getGroup());
+ }
+
+ std::vector<RefreshRateRanking> getRefreshRatesByPolicy(
+ std::optional<int> anchorGroupOpt, RefreshRateOrder refreshRateOrder) const {
+ std::lock_guard lock(mLock);
+ return RefreshRateConfigs::getRefreshRatesByPolicyLocked(anchorGroupOpt, refreshRateOrder);
+ }
+
const std::vector<Fps>& knownFrameRates() const { return mKnownFrameRates; }
- using RefreshRateConfigs::GetBestRefreshRateCache;
- auto& mutableGetBestRefreshRateCache() { return mGetBestRefreshRateCache; }
+ using RefreshRateConfigs::GetRankedRefreshRatesCache;
+ auto& mutableGetRankedRefreshRatesCache() { return mGetRankedRefreshRatesCache; }
- auto getBestRefreshRateAndSignals(const std::vector<LayerRequirement>& layers,
- GlobalSignals signals) const {
- return RefreshRateConfigs::getBestRefreshRate(layers, signals);
+ auto getRankedRefreshRatesAndSignals(const std::vector<LayerRequirement>& layers,
+ GlobalSignals signals) const {
+ return RefreshRateConfigs::getRankedRefreshRates(layers, signals);
}
DisplayModePtr getBestRefreshRate(const std::vector<LayerRequirement>& layers = {},
GlobalSignals signals = {}) const {
- return getBestRefreshRateAndSignals(layers, signals).first;
+ return getRankedRefreshRatesAndSignals(layers, signals).first.front().displayModePtr;
}
};
@@ -977,16 +989,116 @@
EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers));
}
+TEST_F(RefreshRateConfigsTest, getMaxRefreshRatesByPolicy) {
+ // The kModes_30_60_90 contains two kMode72_G1, kMode120_G1 which are from the
+ // different group.
+ TestableRefreshRateConfigs configs(kModes_30_60_90, kModeId60);
+ const std::vector<RefreshRateRanking>& expectedRefreshRates = {RefreshRateRanking{kMode90},
+ RefreshRateRanking{kMode60},
+ RefreshRateRanking{kMode30}};
+
+ const std::vector<RefreshRateRanking>& refreshRates =
+ configs.getRefreshRatesByPolicy(configs.getActiveMode().getGroup(),
+ TestableRefreshRateConfigs::RefreshRateOrder::
+ Descending);
+
+ ASSERT_EQ(expectedRefreshRates.size(), refreshRates.size());
+ for (size_t i = 0; i < expectedRefreshRates.size(); ++i) {
+ EXPECT_EQ(expectedRefreshRates[i].displayModePtr, refreshRates[i].displayModePtr)
+ << "Expected fps " << expectedRefreshRates[i].displayModePtr->getFps().getIntValue()
+ << " Actual fps " << refreshRates[i].displayModePtr->getFps().getIntValue();
+ }
+}
+
+TEST_F(RefreshRateConfigsTest, getMinRefreshRatesByPolicy) {
+ // The kModes_30_60_90 contains two kMode72_G1, kMode120_G1 which are from the
+ // different group.
+ TestableRefreshRateConfigs configs(kModes_30_60_90, kModeId60);
+ const std::vector<RefreshRateRanking>& expectedRefreshRates = {RefreshRateRanking{kMode30},
+ RefreshRateRanking{kMode60},
+ RefreshRateRanking{kMode90}};
+
+ const std::vector<RefreshRateRanking>& refreshRates =
+ configs.getRefreshRatesByPolicy(configs.getActiveMode().getGroup(),
+ TestableRefreshRateConfigs::RefreshRateOrder::
+ Ascending);
+
+ ASSERT_EQ(expectedRefreshRates.size(), refreshRates.size());
+ for (size_t i = 0; i < expectedRefreshRates.size(); ++i) {
+ EXPECT_EQ(expectedRefreshRates[i].displayModePtr, refreshRates[i].displayModePtr)
+ << "Expected fps " << expectedRefreshRates[i].displayModePtr->getFps().getIntValue()
+ << " Actual fps " << refreshRates[i].displayModePtr->getFps().getIntValue();
+ }
+}
+
+TEST_F(RefreshRateConfigsTest, getMinRefreshRatesByPolicyOutsideTheGroup) {
+ // The kModes_30_60_90 contains two kMode72_G1, kMode120_G1 which are from the
+ // different group.
+ TestableRefreshRateConfigs configs(kModes_30_60_90, kModeId72);
+ const std::vector<RefreshRateRanking>& expectedRefreshRates = {RefreshRateRanking{kMode30},
+ RefreshRateRanking{kMode60},
+ RefreshRateRanking{kMode90}};
+
+ EXPECT_GE(configs.setDisplayManagerPolicy({kModeId60, {30_Hz, 90_Hz}, {30_Hz, 90_Hz}}), 0);
+
+ const std::vector<RefreshRateRanking>& refreshRates =
+ configs.getRefreshRatesByPolicy(/*anchorGroupOpt*/ std::nullopt,
+ TestableRefreshRateConfigs::RefreshRateOrder::
+ Ascending);
+
+ ASSERT_EQ(expectedRefreshRates.size(), refreshRates.size());
+ for (size_t i = 0; i < expectedRefreshRates.size(); ++i) {
+ EXPECT_EQ(expectedRefreshRates[i].displayModePtr, refreshRates[i].displayModePtr)
+ << "Expected fps " << expectedRefreshRates[i].displayModePtr->getFps().getIntValue()
+ << " Actual fps " << refreshRates[i].displayModePtr->getFps().getIntValue();
+ }
+}
+
+TEST_F(RefreshRateConfigsTest, getMaxRefreshRatesByPolicyOutsideTheGroup) {
+ // The kModes_30_60_90 contains two kMode72_G1, kMode120_G1 which are from the
+ // different group.
+ TestableRefreshRateConfigs configs(kModes_30_60_90, kModeId72);
+ const std::vector<RefreshRateRanking>& expectedRefreshRates = {RefreshRateRanking{kMode90},
+ RefreshRateRanking{kMode60},
+ RefreshRateRanking{kMode30}};
+
+ EXPECT_GE(configs.setDisplayManagerPolicy({kModeId60, {30_Hz, 90_Hz}, {30_Hz, 90_Hz}}), 0);
+
+ const std::vector<RefreshRateRanking>& refreshRates =
+ configs.getRefreshRatesByPolicy(/*anchorGroupOpt*/ std::nullopt,
+ TestableRefreshRateConfigs::RefreshRateOrder::
+ Descending);
+
+ ASSERT_EQ(expectedRefreshRates.size(), refreshRates.size());
+ for (size_t i = 0; i < expectedRefreshRates.size(); ++i) {
+ EXPECT_EQ(expectedRefreshRates[i].displayModePtr, refreshRates[i].displayModePtr)
+ << "Expected fps " << expectedRefreshRates[i].displayModePtr->getFps().getIntValue()
+ << " Actual fps " << refreshRates[i].displayModePtr->getFps().getIntValue();
+ }
+}
+
TEST_F(RefreshRateConfigsTest, powerOnImminentConsidered) {
RefreshRateConfigs configs(kModes_60_90, kModeId60);
+ std::vector<RefreshRateRanking> expectedRefreshRates = {RefreshRateRanking{kMode90},
+ RefreshRateRanking{kMode60}};
- auto [refreshRate, signals] = configs.getBestRefreshRate({}, {});
+ auto [refreshRates, signals] = configs.getRankedRefreshRates({}, {});
EXPECT_FALSE(signals.powerOnImminent);
- EXPECT_EQ(kMode90, refreshRate);
+ ASSERT_EQ(expectedRefreshRates.size(), refreshRates.size());
+ for (size_t i = 0; i < expectedRefreshRates.size(); ++i) {
+ EXPECT_EQ(expectedRefreshRates[i].displayModePtr, refreshRates[i].displayModePtr)
+ << "Expected fps " << expectedRefreshRates[i].displayModePtr->getFps().getIntValue()
+ << " Actual fps " << refreshRates[i].displayModePtr->getFps().getIntValue();
+ }
- std::tie(refreshRate, signals) = configs.getBestRefreshRate({}, {.powerOnImminent = true});
+ std::tie(refreshRates, signals) = configs.getRankedRefreshRates({}, {.powerOnImminent = true});
EXPECT_TRUE(signals.powerOnImminent);
- EXPECT_EQ(kMode90, refreshRate);
+ ASSERT_EQ(expectedRefreshRates.size(), refreshRates.size());
+ for (size_t i = 0; i < expectedRefreshRates.size(); ++i) {
+ EXPECT_EQ(expectedRefreshRates[i].displayModePtr, refreshRates[i].displayModePtr)
+ << "Expected fps " << expectedRefreshRates[i].displayModePtr->getFps().getIntValue()
+ << " Actual fps " << refreshRates[i].displayModePtr->getFps().getIntValue();
+ }
std::vector<LayerRequirement> layers = {{.weight = 1.f}};
auto& lr1 = layers[0];
@@ -994,22 +1106,35 @@
lr1.desiredRefreshRate = 60_Hz;
lr1.name = "60Hz ExplicitExactOrMultiple";
- std::tie(refreshRate, signals) = configs.getBestRefreshRate(layers, {.powerOnImminent = false});
- EXPECT_FALSE(signals.powerOnImminent);
- EXPECT_EQ(kMode60, refreshRate);
-
- std::tie(refreshRate, signals) = configs.getBestRefreshRate(layers, {.powerOnImminent = true});
+ std::tie(refreshRates, signals) =
+ configs.getRankedRefreshRates(layers, {.powerOnImminent = true});
EXPECT_TRUE(signals.powerOnImminent);
- EXPECT_EQ(kMode90, refreshRate);
+ ASSERT_EQ(expectedRefreshRates.size(), refreshRates.size());
+ for (size_t i = 0; i < expectedRefreshRates.size(); ++i) {
+ EXPECT_EQ(expectedRefreshRates[i].displayModePtr, refreshRates[i].displayModePtr)
+ << "Expected fps " << expectedRefreshRates[i].displayModePtr->getFps().getIntValue()
+ << " Actual fps " << refreshRates[i].displayModePtr->getFps().getIntValue();
+ }
+
+ expectedRefreshRates = {RefreshRateRanking{kMode60}, RefreshRateRanking{kMode90}};
+ std::tie(refreshRates, signals) =
+ configs.getRankedRefreshRates(layers, {.powerOnImminent = false});
+ EXPECT_FALSE(signals.powerOnImminent);
+ ASSERT_EQ(expectedRefreshRates.size(), refreshRates.size());
+ for (size_t i = 0; i < expectedRefreshRates.size(); ++i) {
+ EXPECT_EQ(expectedRefreshRates[i].displayModePtr, refreshRates[i].displayModePtr)
+ << "Expected fps " << expectedRefreshRates[i].displayModePtr->getFps().getIntValue()
+ << " Actual fps " << refreshRates[i].displayModePtr->getFps().getIntValue();
+ }
}
TEST_F(RefreshRateConfigsTest, touchConsidered) {
RefreshRateConfigs configs(kModes_60_90, kModeId60);
- auto [_, signals] = configs.getBestRefreshRate({}, {});
+ auto [_, signals] = configs.getRankedRefreshRates({}, {});
EXPECT_FALSE(signals.touch);
- std::tie(std::ignore, signals) = configs.getBestRefreshRate({}, {.touch = true});
+ std::tie(std::ignore, signals) = configs.getRankedRefreshRates({}, {.touch = true});
EXPECT_TRUE(signals.touch);
std::vector<LayerRequirement> layers = {{.weight = 1.f}, {.weight = 1.f}};
@@ -1022,16 +1147,16 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 60_Hz;
lr2.name = "60Hz Heuristic";
- std::tie(std::ignore, signals) = configs.getBestRefreshRate(layers, {.touch = true});
+ std::tie(std::ignore, signals) = configs.getRankedRefreshRates(layers, {.touch = true});
EXPECT_TRUE(signals.touch);
lr1.vote = LayerVoteType::ExplicitDefault;
lr1.desiredRefreshRate = 60_Hz;
- lr1.name = "60Hz ExplicitExactOrMultiple";
+ lr1.name = "60Hz ExplicitDefault";
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 60_Hz;
lr2.name = "60Hz Heuristic";
- std::tie(std::ignore, signals) = configs.getBestRefreshRate(layers, {.touch = true});
+ std::tie(std::ignore, signals) = configs.getRankedRefreshRates(layers, {.touch = true});
EXPECT_FALSE(signals.touch);
lr1.vote = LayerVoteType::ExplicitExactOrMultiple;
@@ -1040,16 +1165,16 @@
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 60_Hz;
lr2.name = "60Hz Heuristic";
- std::tie(std::ignore, signals) = configs.getBestRefreshRate(layers, {.touch = true});
+ std::tie(std::ignore, signals) = configs.getRankedRefreshRates(layers, {.touch = true});
EXPECT_TRUE(signals.touch);
lr1.vote = LayerVoteType::ExplicitDefault;
lr1.desiredRefreshRate = 60_Hz;
- lr1.name = "60Hz ExplicitExactOrMultiple";
+ lr1.name = "60Hz ExplicitDefault";
lr2.vote = LayerVoteType::Heuristic;
lr2.desiredRefreshRate = 60_Hz;
lr2.name = "60Hz Heuristic";
- std::tie(std::ignore, signals) = configs.getBestRefreshRate(layers, {.touch = true});
+ std::tie(std::ignore, signals) = configs.getRankedRefreshRates(layers, {.touch = true});
EXPECT_FALSE(signals.touch);
}
@@ -1187,9 +1312,10 @@
lr.name = "60Hz ExplicitDefault";
lr.focused = true;
- const auto [mode, signals] = configs.getBestRefreshRate(layers, {.touch = true, .idle = true});
+ const auto [mode, signals] =
+ configs.getRankedRefreshRates(layers, {.touch = true, .idle = true});
- EXPECT_EQ(mode, kMode60);
+ EXPECT_EQ(mode.begin()->displayModePtr, kMode60);
EXPECT_FALSE(signals.touch);
}
@@ -1209,14 +1335,147 @@
EXPECT_EQ(kMode90, configs.getBestRefreshRate(layers, {.idle = true}));
}
+TEST_F(RefreshRateConfigsTest, testDisplayModeOrdering) {
+ TestableRefreshRateConfigs configs(kModes_30_60_72_90_120, kModeId60);
+
+ std::vector<LayerRequirement> layers = {{.weight = 1.f},
+ {.weight = 1.f},
+ {.weight = 1.f},
+ {.weight = 1.f},
+ {.weight = 1.f}};
+ auto& lr1 = layers[0];
+ auto& lr2 = layers[1];
+ auto& lr3 = layers[2];
+ auto& lr4 = layers[3];
+ auto& lr5 = layers[4];
+
+ lr1.desiredRefreshRate = 90_Hz;
+ lr1.name = "90Hz";
+ lr1.focused = true;
+
+ lr2.desiredRefreshRate = 60_Hz;
+ lr2.name = "60Hz";
+ lr2.focused = true;
+
+ lr3.desiredRefreshRate = 72_Hz;
+ lr3.name = "72Hz";
+ lr3.focused = true;
+
+ lr4.desiredRefreshRate = 120_Hz;
+ lr4.name = "120Hz";
+ lr4.focused = true;
+
+ lr5.desiredRefreshRate = 30_Hz;
+ lr5.name = "30Hz";
+ lr5.focused = true;
+
+ std::vector<RefreshRateRanking> expectedRankings = {
+ RefreshRateRanking{kMode120}, RefreshRateRanking{kMode90}, RefreshRateRanking{kMode72},
+ RefreshRateRanking{kMode60}, RefreshRateRanking{kMode30},
+ };
+
+ std::vector<RefreshRateRanking> actualOrder =
+ configs.getRankedRefreshRatesAndSignals(layers, {}).first;
+ ASSERT_EQ(expectedRankings.size(), actualOrder.size());
+ for (size_t i = 0; i < expectedRankings.size(); ++i) {
+ EXPECT_EQ(expectedRankings[i].displayModePtr, actualOrder[i].displayModePtr)
+ << "Expected fps " << expectedRankings[i].displayModePtr->getFps().getIntValue()
+ << " Actual fps " << actualOrder[i].displayModePtr->getFps().getIntValue();
+ }
+
+ lr1.vote = LayerVoteType::Max;
+ lr1.name = "Max";
+
+ lr2.desiredRefreshRate = 60_Hz;
+ lr2.name = "60Hz";
+
+ lr3.desiredRefreshRate = 72_Hz;
+ lr3.name = "72Hz";
+
+ lr4.desiredRefreshRate = 90_Hz;
+ lr4.name = "90Hz";
+
+ lr5.desiredRefreshRate = 120_Hz;
+ lr5.name = "120Hz";
+
+ expectedRankings = {
+ RefreshRateRanking{kMode120}, RefreshRateRanking{kMode90}, RefreshRateRanking{kMode72},
+ RefreshRateRanking{kMode60}, RefreshRateRanking{kMode30},
+ };
+
+ actualOrder = configs.getRankedRefreshRatesAndSignals(layers, {}).first;
+
+ ASSERT_EQ(expectedRankings.size(), actualOrder.size());
+ for (size_t i = 0; i < expectedRankings.size(); ++i) {
+ EXPECT_EQ(expectedRankings[i].displayModePtr, actualOrder[i].displayModePtr)
+ << "Expected fps " << expectedRankings[i].displayModePtr->getFps().getIntValue()
+ << " Actual fps " << actualOrder[i].displayModePtr->getFps().getIntValue();
+ }
+
+ lr1.vote = LayerVoteType::Heuristic;
+ lr1.desiredRefreshRate = 30_Hz;
+ lr1.name = "30Hz";
+
+ lr2.desiredRefreshRate = 120_Hz;
+ lr2.name = "120Hz";
+
+ lr3.desiredRefreshRate = 60_Hz;
+ lr3.name = "60Hz";
+
+ lr5.desiredRefreshRate = 72_Hz;
+ lr5.name = "72Hz";
+
+ expectedRankings = {
+ RefreshRateRanking{kMode30}, RefreshRateRanking{kMode60}, RefreshRateRanking{kMode90},
+ RefreshRateRanking{kMode120}, RefreshRateRanking{kMode72},
+ };
+
+ actualOrder = configs.getRankedRefreshRatesAndSignals(layers, {}).first;
+ ASSERT_EQ(expectedRankings.size(), actualOrder.size());
+ for (size_t i = 0; i < expectedRankings.size(); ++i) {
+ EXPECT_EQ(expectedRankings[i].displayModePtr, actualOrder[i].displayModePtr)
+ << "Expected fps " << expectedRankings[i].displayModePtr->getFps().getIntValue()
+ << " Actual fps " << actualOrder[i].displayModePtr->getFps().getIntValue();
+ }
+
+ lr1.desiredRefreshRate = 120_Hz;
+ lr1.name = "120Hz";
+ lr1.weight = 0.0f;
+
+ lr2.desiredRefreshRate = 60_Hz;
+ lr2.name = "60Hz";
+ lr2.vote = LayerVoteType::NoVote;
+
+ lr3.name = "60Hz-2";
+ lr3.vote = LayerVoteType::Heuristic;
+
+ lr4.vote = LayerVoteType::ExplicitExact;
+
+ lr5.desiredRefreshRate = 120_Hz;
+ lr5.name = "120Hz-2";
+
+ expectedRankings = {
+ RefreshRateRanking{kMode90}, RefreshRateRanking{kMode60}, RefreshRateRanking{kMode120},
+ RefreshRateRanking{kMode72}, RefreshRateRanking{kMode30},
+ };
+
+ actualOrder = configs.getRankedRefreshRatesAndSignals(layers, {}).first;
+ ASSERT_EQ(expectedRankings.size(), actualOrder.size());
+ for (size_t i = 0; i < expectedRankings.size(); ++i) {
+ EXPECT_EQ(expectedRankings[i].displayModePtr, actualOrder[i].displayModePtr)
+ << "Expected fps " << expectedRankings[i].displayModePtr->getFps().getIntValue()
+ << " Actual fps " << actualOrder[i].displayModePtr->getFps().getIntValue();
+ }
+}
+
TEST_F(RefreshRateConfigsTest,
getBestRefreshRate_withDisplayManagerRequestingSingleRate_onlySwitchesRatesForExplicitFocusedLayers) {
TestableRefreshRateConfigs configs(kModes_60_90, kModeId90);
EXPECT_GE(configs.setDisplayManagerPolicy({kModeId90, {90_Hz, 90_Hz}, {60_Hz, 90_Hz}}), 0);
- const auto [mode, signals] = configs.getBestRefreshRateAndSignals({}, {});
- EXPECT_EQ(mode, kMode90);
+ const auto [mode, signals] = configs.getRankedRefreshRatesAndSignals({}, {});
+ EXPECT_EQ(mode.front().displayModePtr, kMode90);
EXPECT_FALSE(signals.touch);
std::vector<LayerRequirement> layers = {{.weight = 1.f}};
@@ -1593,11 +1852,12 @@
layers[0].desiredRefreshRate = 90_Hz;
const auto [refreshRate, signals] =
- configs.getBestRefreshRateAndSignals(layers, {.touch = touchActive, .idle = true});
+ configs.getRankedRefreshRatesAndSignals(layers,
+ {.touch = touchActive, .idle = true});
// Refresh rate will be chosen by either touch state or idle state.
EXPECT_EQ(!touchActive, signals.idle);
- return refreshRate->getId();
+ return refreshRate.front().displayModePtr->getId();
};
EXPECT_GE(configs.setDisplayManagerPolicy({kModeId60, {60_Hz, 90_Hz}, {60_Hz, 90_Hz}}), 0);
@@ -1756,24 +2016,26 @@
using GlobalSignals = RefreshRateConfigs::GlobalSignals;
const auto args = std::make_pair(std::vector<LayerRequirement>{},
GlobalSignals{.touch = true, .idle = true});
- const auto result = std::make_pair(kMode90, GlobalSignals{.touch = true});
- configs.mutableGetBestRefreshRateCache() = {args, result};
+ const auto result = std::make_pair(std::vector<RefreshRateRanking>{RefreshRateRanking{kMode90}},
+ GlobalSignals{.touch = true});
- EXPECT_EQ(result, configs.getBestRefreshRateAndSignals(args.first, args.second));
+ configs.mutableGetRankedRefreshRatesCache() = {args, result};
+
+ EXPECT_EQ(result, configs.getRankedRefreshRatesAndSignals(args.first, args.second));
}
TEST_F(RefreshRateConfigsTest, getBestRefreshRate_WritesCache) {
TestableRefreshRateConfigs configs(kModes_30_60_72_90_120, kModeId60);
- EXPECT_FALSE(configs.mutableGetBestRefreshRateCache());
+ EXPECT_FALSE(configs.mutableGetRankedRefreshRatesCache());
std::vector<LayerRequirement> layers = {{.weight = 1.f}, {.weight = 0.5f}};
RefreshRateConfigs::GlobalSignals globalSignals{.touch = true, .idle = true};
- const auto result = configs.getBestRefreshRateAndSignals(layers, globalSignals);
+ const auto result = configs.getRankedRefreshRatesAndSignals(layers, globalSignals);
- const auto& cache = configs.mutableGetBestRefreshRateCache();
+ const auto& cache = configs.mutableGetRankedRefreshRatesCache();
ASSERT_TRUE(cache);
EXPECT_EQ(cache->arguments, std::make_pair(layers, globalSignals));
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
index abf1786..ac63a0e 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
@@ -21,7 +21,6 @@
#include <gtest/gtest.h>
#include <gui/LayerMetadata.h>
-#include "BufferStateLayer.h"
#include "Layer.h"
#include "TestableSurfaceFlinger.h"
#include "mock/DisplayHardware/MockComposer.h"
@@ -58,7 +57,7 @@
static constexpr int32_t PRIORITY_UNSET = -1;
void setupScheduler();
- sp<BufferStateLayer> createBufferStateLayer();
+ sp<Layer> createBufferStateLayer();
sp<Layer> createEffectLayer();
void setParent(Layer* child, Layer* parent);
@@ -87,12 +86,11 @@
ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
}
-
-sp<BufferStateLayer> RefreshRateSelectionTest::createBufferStateLayer() {
+sp<Layer> RefreshRateSelectionTest::createBufferStateLayer() {
sp<Client> client;
LayerCreationArgs args(mFlinger.flinger(), client, "buffer-queue-layer", LAYER_FLAGS,
LayerMetadata());
- return sp<BufferStateLayer>::make(args);
+ return sp<Layer>::make(args);
}
sp<Layer> RefreshRateSelectionTest::createEffectLayer() {
diff --git a/services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp b/services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp
index f19e554..409e1ef 100644
--- a/services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp
@@ -106,40 +106,6 @@
testing::Eq(0.0));
}
-// workaround for b/133849373
-TEST_F(RegionSamplingTest, orientation_90) {
- std::generate(buffer.begin(), buffer.end(),
- [n = 0]() mutable { return (n++ > (kStride * kHeight >> 1)) ? kBlack : kWhite; });
-
- Rect tl_region{0, 0, 4, 4};
- EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_0,
- tl_region),
- testing::Eq(1.0));
- EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_180,
- tl_region),
- testing::Eq(1.0));
- EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_90,
- tl_region),
- testing::Eq(0.0));
- EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_270,
- tl_region),
- testing::Eq(0.0));
-
- Rect br_region{kWidth - 4, kHeight - 4, kWidth, kHeight};
- EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_0,
- br_region),
- testing::Eq(0.0));
- EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_180,
- br_region),
- testing::Eq(0.0));
- EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_90,
- br_region),
- testing::Eq(1.0));
- EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_270,
- br_region),
- testing::Eq(1.0));
-}
-
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
index 51c6bea..dfcfd91 100644
--- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
@@ -24,7 +24,6 @@
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
-#include "BufferStateLayer.h"
#include "Layer.h"
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
index 57937dc..6b7e353 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_DisplayModeSwitching.cpp
@@ -20,6 +20,7 @@
#include "DisplayTransactionTestHelpers.h"
+#include <ftl/fake_guard.h>
#include <scheduler/Fps.h>
namespace android {
@@ -111,8 +112,10 @@
}
TEST_F(DisplayModeSwitchingTest, changeRefreshRate_OnActiveDisplay_WithRefreshRequired) {
+ ftl::FakeGuard guard(kMainThreadContext);
+
ASSERT_FALSE(mDisplay->getDesiredActiveMode().has_value());
- ASSERT_EQ(mDisplay->getActiveMode()->getId(), kModeId60);
+ ASSERT_EQ(mDisplay->getActiveMode().getId(), kModeId60);
mFlinger.onActiveDisplayChanged(mDisplay);
@@ -121,7 +124,7 @@
ASSERT_TRUE(mDisplay->getDesiredActiveMode().has_value());
ASSERT_EQ(mDisplay->getDesiredActiveMode()->mode->getId(), kModeId90);
- ASSERT_EQ(mDisplay->getActiveMode()->getId(), kModeId60);
+ ASSERT_EQ(mDisplay->getActiveMode().getId(), kModeId60);
// Verify that next commit will call setActiveConfigWithConstraints in HWC
const VsyncPeriodChangeTimeline timeline{.refreshRequired = true};
@@ -134,7 +137,7 @@
Mock::VerifyAndClearExpectations(mComposer);
ASSERT_TRUE(mDisplay->getDesiredActiveMode().has_value());
- ASSERT_EQ(mDisplay->getActiveMode()->getId(), kModeId60);
+ ASSERT_EQ(mDisplay->getActiveMode().getId(), kModeId60);
// Verify that the next commit will complete the mode change and send
// a onModeChanged event to the framework.
@@ -144,10 +147,12 @@
Mock::VerifyAndClearExpectations(mAppEventThread);
ASSERT_FALSE(mDisplay->getDesiredActiveMode().has_value());
- ASSERT_EQ(mDisplay->getActiveMode()->getId(), kModeId90);
+ ASSERT_EQ(mDisplay->getActiveMode().getId(), kModeId90);
}
TEST_F(DisplayModeSwitchingTest, changeRefreshRate_OnActiveDisplay_WithoutRefreshRequired) {
+ ftl::FakeGuard guard(kMainThreadContext);
+
ASSERT_FALSE(mDisplay->getDesiredActiveMode().has_value());
mFlinger.onActiveDisplayChanged(mDisplay);
@@ -157,7 +162,7 @@
ASSERT_TRUE(mDisplay->getDesiredActiveMode().has_value());
ASSERT_EQ(mDisplay->getDesiredActiveMode()->mode->getId(), kModeId90);
- ASSERT_EQ(mDisplay->getActiveMode()->getId(), kModeId60);
+ ASSERT_EQ(mDisplay->getActiveMode().getId(), kModeId60);
// Verify that next commit will call setActiveConfigWithConstraints in HWC
// and complete the mode change.
@@ -172,15 +177,17 @@
mFlinger.commit();
ASSERT_FALSE(mDisplay->getDesiredActiveMode().has_value());
- ASSERT_EQ(mDisplay->getActiveMode()->getId(), kModeId90);
+ ASSERT_EQ(mDisplay->getActiveMode().getId(), kModeId90);
}
TEST_F(DisplayModeSwitchingTest, twoConsecutiveSetDesiredDisplayModeSpecs) {
+ ftl::FakeGuard guard(kMainThreadContext);
+
// Test that if we call setDesiredDisplayModeSpecs while a previous mode change
// is still being processed the later call will be respected.
ASSERT_FALSE(mDisplay->getDesiredActiveMode().has_value());
- ASSERT_EQ(mDisplay->getActiveMode()->getId(), kModeId60);
+ ASSERT_EQ(mDisplay->getActiveMode().getId(), kModeId60);
mFlinger.onActiveDisplayChanged(mDisplay);
@@ -214,12 +221,14 @@
mFlinger.commit();
ASSERT_FALSE(mDisplay->getDesiredActiveMode().has_value());
- ASSERT_EQ(mDisplay->getActiveMode()->getId(), kModeId120);
+ ASSERT_EQ(mDisplay->getActiveMode().getId(), kModeId120);
}
TEST_F(DisplayModeSwitchingTest, changeResolution_OnActiveDisplay_WithoutRefreshRequired) {
+ ftl::FakeGuard guard(kMainThreadContext);
+
ASSERT_FALSE(mDisplay->getDesiredActiveMode().has_value());
- ASSERT_EQ(mDisplay->getActiveMode()->getId(), kModeId60);
+ ASSERT_EQ(mDisplay->getActiveMode().getId(), kModeId60);
mFlinger.onActiveDisplayChanged(mDisplay);
@@ -228,7 +237,7 @@
ASSERT_TRUE(mDisplay->getDesiredActiveMode().has_value());
ASSERT_EQ(mDisplay->getDesiredActiveMode()->mode->getId(), kModeId90_4K);
- ASSERT_EQ(mDisplay->getActiveMode()->getId(), kModeId60);
+ ASSERT_EQ(mDisplay->getActiveMode().getId(), kModeId60);
// Verify that next commit will call setActiveConfigWithConstraints in HWC
// and complete the mode change.
@@ -263,7 +272,7 @@
mDisplay = mFlinger.getDisplay(displayToken);
ASSERT_FALSE(mDisplay->getDesiredActiveMode().has_value());
- ASSERT_EQ(mDisplay->getActiveMode()->getId(), kModeId90_4K);
+ ASSERT_EQ(mDisplay->getActiveMode().getId(), kModeId90_4K);
}
} // namespace
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
index ec2c2b4..073c459 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
@@ -17,6 +17,8 @@
#undef LOG_TAG
#define LOG_TAG "LibSurfaceFlingerUnittests"
+#include <ftl/fake_guard.h>
+
#include "DisplayHardware/DisplayMode.h"
#include "DisplayTransactionTestHelpers.h"
@@ -265,7 +267,7 @@
// --------------------------------------------------------------------
// Postconditions
- ASSERT_TRUE(device != nullptr);
+ ASSERT_NE(nullptr, device);
EXPECT_EQ(Case::Display::DISPLAY_ID::get(), device->getId());
EXPECT_EQ(static_cast<bool>(Case::Display::VIRTUAL), device->isVirtual());
EXPECT_EQ(static_cast<bool>(Case::Display::SECURE), device->isSecure());
@@ -282,8 +284,8 @@
device->receivesInput());
if constexpr (Case::Display::CONNECTION_TYPE::value) {
- EXPECT_NE(nullptr, device->getActiveMode());
- EXPECT_EQ(Case::Display::HWC_ACTIVE_CONFIG_ID, device->getActiveMode()->getHwcId());
+ ftl::FakeGuard guard(kMainThreadContext);
+ EXPECT_EQ(Case::Display::HWC_ACTIVE_CONFIG_ID, device->getActiveMode().getHwcId());
}
}
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_UpdateLayerMetadataSnapshotTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_UpdateLayerMetadataSnapshotTest.cpp
new file mode 100644
index 0000000..0cf3bdf
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_UpdateLayerMetadataSnapshotTest.cpp
@@ -0,0 +1,212 @@
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <gui/LayerMetadata.h>
+
+#include "TestableSurfaceFlinger.h"
+#include "mock/MockEventThread.h"
+#include "mock/MockVsyncController.h"
+
+namespace android {
+
+using testing::_;
+using testing::Return;
+using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector;
+
+class SurfaceFlingerUpdateLayerMetadataSnapshotTest : public testing::Test {
+public:
+ SurfaceFlingerUpdateLayerMetadataSnapshotTest() { setupScheduler(); }
+
+protected:
+ void setupScheduler() {
+ auto eventThread = std::make_unique<mock::EventThread>();
+ auto sfEventThread = std::make_unique<mock::EventThread>();
+
+ EXPECT_CALL(*eventThread, registerDisplayEventConnection(_));
+ EXPECT_CALL(*eventThread, createEventConnection(_, _))
+ .WillOnce(Return(sp<EventThreadConnection>::make(eventThread.get(),
+ mock::EventThread::kCallingUid,
+ ResyncCallback())));
+
+ EXPECT_CALL(*sfEventThread, registerDisplayEventConnection(_));
+ EXPECT_CALL(*sfEventThread, createEventConnection(_, _))
+ .WillOnce(Return(sp<EventThreadConnection>::make(sfEventThread.get(),
+ mock::EventThread::kCallingUid,
+ ResyncCallback())));
+
+ auto vsyncController = std::make_unique<mock::VsyncController>();
+ auto vsyncTracker = std::make_unique<mock::VSyncTracker>();
+
+ EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
+ EXPECT_CALL(*vsyncTracker, currentPeriod())
+ .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
+ EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
+ mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker),
+ std::move(eventThread), std::move(sfEventThread));
+ }
+
+ sp<Layer> createLayer(const char* name, LayerMetadata layerMetadata) {
+ return sp<Layer>::make(
+ LayerCreationArgs{mFlinger.flinger(), nullptr, name, 0, layerMetadata});
+ }
+
+ TestableSurfaceFlinger mFlinger;
+};
+
+class LayerMetadataBuilder {
+public:
+ LayerMetadataBuilder(LayerMetadata layerMetadata = {}) : mLayerMetadata(layerMetadata) {}
+
+ LayerMetadataBuilder& setInt32(uint32_t key, int32_t value) {
+ mLayerMetadata.setInt32(key, value);
+ return *this;
+ }
+
+ LayerMetadata build() { return mLayerMetadata; }
+
+private:
+ LayerMetadata mLayerMetadata;
+};
+
+bool operator==(const LayerMetadata& lhs, const LayerMetadata& rhs) {
+ return lhs.mMap == rhs.mMap;
+}
+
+std::ostream& operator<<(std::ostream& stream, const LayerMetadata& layerMetadata) {
+ stream << "LayerMetadata{";
+ for (auto it = layerMetadata.mMap.cbegin(); it != layerMetadata.mMap.cend(); it++) {
+ if (it != layerMetadata.mMap.cbegin()) {
+ stream << ", ";
+ }
+ stream << layerMetadata.itemToString(it->first, ":");
+ }
+ return stream << "}";
+}
+
+// Test that the snapshot's layer metadata is set.
+TEST_F(SurfaceFlingerUpdateLayerMetadataSnapshotTest, updatesSnapshotMetadata) {
+ auto layerMetadata = LayerMetadataBuilder().setInt32(METADATA_TASK_ID, 1).build();
+ auto layer = createLayer("layer", layerMetadata);
+ mFlinger.mutableDrawingState().layersSortedByZ.add(layer);
+
+ mFlinger.updateLayerMetadataSnapshot();
+
+ ASSERT_EQ(layer->getLayerSnapshot()->layerMetadata, layerMetadata);
+}
+
+// Test that snapshot layer metadata is set by merging the child's metadata on top of its
+// parent's metadata.
+TEST_F(SurfaceFlingerUpdateLayerMetadataSnapshotTest, mergesSnapshotMetadata) {
+ auto layerAMetadata = LayerMetadataBuilder()
+ .setInt32(METADATA_OWNER_UID, 1)
+ .setInt32(METADATA_TASK_ID, 2)
+ .build();
+ auto layerA = createLayer("parent", layerAMetadata);
+ auto layerBMetadata = LayerMetadataBuilder().setInt32(METADATA_TASK_ID, 3).build();
+ auto layerB = createLayer("child", layerBMetadata);
+ layerA->addChild(layerB);
+ layerA->commitChildList();
+ mFlinger.mutableDrawingState().layersSortedByZ.add(layerA);
+
+ mFlinger.updateLayerMetadataSnapshot();
+
+ ASSERT_EQ(layerA->getLayerSnapshot()->layerMetadata, layerAMetadata);
+ auto expectedChildMetadata =
+ LayerMetadataBuilder(layerAMetadata).setInt32(METADATA_TASK_ID, 3).build();
+ ASSERT_EQ(layerB->getLayerSnapshot()->layerMetadata, expectedChildMetadata);
+}
+
+// Test that snapshot relative layer metadata is set to the parent's layer metadata merged on top of
+// that parent's relative layer metadata.
+TEST_F(SurfaceFlingerUpdateLayerMetadataSnapshotTest, updatesRelativeMetadata) {
+ auto layerAMetadata = LayerMetadataBuilder().setInt32(METADATA_TASK_ID, 1).build();
+ auto layerA = createLayer("relative-parent", layerAMetadata);
+ auto layerAHandle = layerA->getHandle();
+ auto layerBMetadata = LayerMetadataBuilder().setInt32(METADATA_TASK_ID, 2).build();
+ auto layerB = createLayer("relative-child", layerBMetadata);
+ layerB->setRelativeLayer(layerAHandle, 1);
+ mFlinger.mutableDrawingState().layersSortedByZ.add(layerA);
+ mFlinger.mutableDrawingState().layersSortedByZ.add(layerB);
+
+ mFlinger.updateLayerMetadataSnapshot();
+
+ ASSERT_EQ(layerA->getLayerSnapshot()->relativeLayerMetadata, LayerMetadata{});
+ ASSERT_EQ(layerB->getLayerSnapshot()->relativeLayerMetadata, layerAMetadata);
+}
+
+// Test that snapshot relative layer metadata is set correctly when a layer is interleaved within
+// two other layers.
+//
+// Layer
+// A
+// / \
+// B D
+// /
+// C
+//
+// Z-order Relatives
+// B <- D <- C
+TEST_F(SurfaceFlingerUpdateLayerMetadataSnapshotTest, updatesRelativeMetadataInterleaved) {
+ auto layerAMetadata = LayerMetadataBuilder().setInt32(METADATA_OWNER_UID, 1).build();
+ auto layerA = createLayer("layer-a", layerAMetadata);
+ auto layerBMetadata = LayerMetadataBuilder()
+ .setInt32(METADATA_TASK_ID, 2)
+ .setInt32(METADATA_OWNER_PID, 3)
+ .build();
+ auto layerB = createLayer("layer-b", layerBMetadata);
+ auto layerBHandle = layerB->getHandle();
+ auto layerC = createLayer("layer-c", {});
+ auto layerDMetadata = LayerMetadataBuilder().setInt32(METADATA_TASK_ID, 4).build();
+ auto layerD = createLayer("layer-d", layerDMetadata);
+ auto layerDHandle = layerD->getHandle();
+ layerB->addChild(layerC);
+ layerA->addChild(layerB);
+ layerA->addChild(layerD);
+ layerC->setRelativeLayer(layerDHandle, 1);
+ layerD->setRelativeLayer(layerBHandle, 1);
+ layerA->commitChildList();
+ mFlinger.mutableDrawingState().layersSortedByZ.add(layerA);
+
+ mFlinger.updateLayerMetadataSnapshot();
+
+ auto expectedLayerDRelativeMetadata = LayerMetadataBuilder()
+ // From layer A, parent of relative parent
+ .setInt32(METADATA_OWNER_UID, 1)
+ // From layer B, relative parent
+ .setInt32(METADATA_TASK_ID, 2)
+ .setInt32(METADATA_OWNER_PID, 3)
+ .build();
+ ASSERT_EQ(layerD->getLayerSnapshot()->relativeLayerMetadata, expectedLayerDRelativeMetadata);
+ auto expectedLayerCRelativeMetadata =
+ LayerMetadataBuilder()
+ // From layer A, parent of relative parent
+ .setInt32(METADATA_OWNER_UID, 1)
+ // From layer B, relative parent of relative parent
+ .setInt32(METADATA_OWNER_PID, 3)
+ // From layer D, relative parent
+ .setInt32(METADATA_TASK_ID, 4)
+ .build();
+ ASSERT_EQ(layerC->getLayerSnapshot()->relativeLayerMetadata, expectedLayerCRelativeMetadata);
+}
+
+TEST_F(SurfaceFlingerUpdateLayerMetadataSnapshotTest,
+ updatesRelativeMetadataMultipleRelativeChildren) {
+ auto layerAMetadata = LayerMetadataBuilder().setInt32(METADATA_OWNER_UID, 1).build();
+ auto layerA = createLayer("layer-a", layerAMetadata);
+ auto layerAHandle = layerA->getHandle();
+ auto layerB = createLayer("layer-b", {});
+ auto layerC = createLayer("layer-c", {});
+ layerB->setRelativeLayer(layerAHandle, 1);
+ layerC->setRelativeLayer(layerAHandle, 2);
+ layerA->commitChildList();
+ mFlinger.mutableDrawingState().layersSortedByZ.add(layerA);
+ mFlinger.mutableDrawingState().layersSortedByZ.add(layerB);
+ mFlinger.mutableDrawingState().layersSortedByZ.add(layerC);
+
+ mFlinger.updateLayerMetadataSnapshot();
+
+ ASSERT_EQ(layerA->getLayerSnapshot()->relativeLayerMetadata, LayerMetadata{});
+ ASSERT_EQ(layerB->getLayerSnapshot()->relativeLayerMetadata, layerAMetadata);
+ ASSERT_EQ(layerC->getLayerSnapshot()->relativeLayerMetadata, layerAMetadata);
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 1ce6e18..13389a1 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -30,7 +30,6 @@
#include <ftl/fake_guard.h>
#include <gui/ScreenCaptureResults.h>
-#include "BufferStateLayer.h"
#include "DisplayDevice.h"
#include "FakeVsyncConfiguration.h"
#include "FrameTracer/FrameTracer.h"
@@ -120,9 +119,7 @@
return compositionengine::impl::createCompositionEngine();
}
- sp<BufferStateLayer> createBufferStateLayer(const LayerCreationArgs&) override {
- return nullptr;
- }
+ sp<Layer> createBufferStateLayer(const LayerCreationArgs&) override { return nullptr; }
sp<Layer> createEffectLayer(const LayerCreationArgs&) override { return nullptr; }
@@ -288,7 +285,7 @@
const sp<NativeHandle>& sidebandStream) {
layer->mDrawingState.sidebandStream = sidebandStream;
layer->mSidebandStream = sidebandStream;
- layer->editCompositionState()->sidebandStream = sidebandStream;
+ layer->editLayerSnapshot()->sidebandStream = sidebandStream;
}
void setLayerCompositionType(const sp<Layer>& layer,
@@ -480,6 +477,8 @@
return mFlinger->mirrorLayer(args, mirrorFromHandle, outHandle, outLayerId);
}
+ void updateLayerMetadataSnapshot() { mFlinger->updateLayerMetadataSnapshot(); }
+
/* ------------------------------------------------------------------------
* Read-only access to private data to assert post-conditions.
*/
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index efb9e0c..b493d11 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -347,8 +347,7 @@
state.state.bufferData->acquireFence = std::move(fence);
state.state.layerId = layerId;
state.state.surface =
- sp<BufferStateLayer>::make(
- LayerCreationArgs(mFlinger.flinger(), nullptr, "TestLayer", 0, {}))
+ sp<Layer>::make(LayerCreationArgs(mFlinger.flinger(), nullptr, "TestLayer", 0, {}))
->getHandle();
state.state.bufferData->flags = BufferData::BufferDataChange::fenceChanged;
diff --git a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
index cd64325..1173d1c 100644
--- a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
@@ -56,11 +56,11 @@
ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
}
- sp<BufferStateLayer> createBufferStateLayer() {
+ sp<Layer> createLayer() {
sp<Client> client;
LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", 0,
LayerMetadata());
- return sp<BufferStateLayer>::make(args);
+ return sp<Layer>::make(args);
}
void commitTransaction(Layer* layer) {
@@ -101,7 +101,7 @@
FenceToFenceTimeMap fenceFactory;
void BLASTTransactionSendsFrameTracerEvents() {
- sp<BufferStateLayer> layer = createBufferStateLayer();
+ sp<Layer> layer = createLayer();
sp<Fence> fence(sp<Fence>::make());
int32_t layerId = layer->getSequence();
diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
index d5823c3..ae03db4 100644
--- a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
@@ -56,11 +56,10 @@
ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
}
- sp<BufferStateLayer> createBufferStateLayer() {
+ sp<Layer> createLayer() {
sp<Client> client;
- LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", 0,
- LayerMetadata());
- return sp<BufferStateLayer>::make(args);
+ LayerCreationArgs args(mFlinger.flinger(), client, "layer", 0, LayerMetadata());
+ return sp<Layer>::make(args);
}
void commitTransaction(Layer* layer) {
@@ -101,7 +100,7 @@
FenceToFenceTimeMap fenceFactory;
void PresentedSurfaceFrameForBufferlessTransaction() {
- sp<BufferStateLayer> layer = createBufferStateLayer();
+ sp<Layer> layer = createLayer();
FrameTimelineInfo ftInfo;
ftInfo.vsyncId = 1;
ftInfo.inputEventId = 0;
@@ -116,7 +115,7 @@
}
void PresentedSurfaceFrameForBufferTransaction() {
- sp<BufferStateLayer> layer = createBufferStateLayer();
+ sp<Layer> layer = createLayer();
sp<Fence> fence(sp<Fence>::make());
auto acquireFence = fenceFactory.createFenceTimeForTest(fence);
BufferData bufferData;
@@ -150,7 +149,7 @@
}
void DroppedSurfaceFrameForBufferTransaction() {
- sp<BufferStateLayer> layer = createBufferStateLayer();
+ sp<Layer> layer = createLayer();
sp<Fence> fence1(sp<Fence>::make());
auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1);
@@ -208,7 +207,7 @@
}
void BufferlessSurfaceFramePromotedToBufferSurfaceFrame() {
- sp<BufferStateLayer> layer = createBufferStateLayer();
+ sp<Layer> layer = createLayer();
FrameTimelineInfo ftInfo;
ftInfo.vsyncId = 1;
ftInfo.inputEventId = 0;
@@ -249,7 +248,7 @@
}
void BufferlessSurfaceFrameNotCreatedIfBufferSufaceFrameExists() {
- sp<BufferStateLayer> layer = createBufferStateLayer();
+ sp<Layer> layer = createLayer();
sp<Fence> fence(sp<Fence>::make());
auto acquireFence = fenceFactory.createFenceTimeForTest(fence);
BufferData bufferData;
@@ -275,7 +274,7 @@
}
void MultipleSurfaceFramesPresentedTogether() {
- sp<BufferStateLayer> layer = createBufferStateLayer();
+ sp<Layer> layer = createLayer();
FrameTimelineInfo ftInfo;
ftInfo.vsyncId = 1;
ftInfo.inputEventId = 0;
@@ -336,7 +335,7 @@
}
void PendingSurfaceFramesRemovedAfterClassification() {
- sp<BufferStateLayer> layer = createBufferStateLayer();
+ sp<Layer> layer = createLayer();
sp<Fence> fence1(sp<Fence>::make());
auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1);
@@ -388,7 +387,7 @@
}
void BufferSurfaceFrame_ReplaceValidTokenBufferWithInvalidTokenBuffer() {
- sp<BufferStateLayer> layer = createBufferStateLayer();
+ sp<Layer> layer = createLayer();
sp<Fence> fence1(sp<Fence>::make());
auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1);
@@ -477,7 +476,7 @@
}
void MultipleCommitsBeforeLatch() {
- sp<BufferStateLayer> layer = createBufferStateLayer();
+ sp<Layer> layer = createLayer();
uint32_t surfaceFramesPendingClassification = 0;
std::vector<std::shared_ptr<frametimeline::SurfaceFrame>> bufferlessSurfaceFrames;
for (int i = 0; i < 10; i += 2) {
diff --git a/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp b/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp
index 45ebb85..da87f1d 100644
--- a/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TunnelModeEnabledReporterTest.cpp
@@ -22,7 +22,6 @@
#include <gtest/gtest.h>
#include <gui/LayerMetadata.h>
-#include "BufferStateLayer.h"
#include "TestableSurfaceFlinger.h"
#include "TunnelModeEnabledReporter.h"
#include "mock/DisplayHardware/MockComposer.h"
@@ -64,7 +63,7 @@
void setupScheduler();
void setupComposer(uint32_t virtualDisplayCount);
- sp<BufferStateLayer> createBufferStateLayer(LayerMetadata metadata);
+ sp<Layer> createBufferStateLayer(LayerMetadata metadata);
TestableSurfaceFlinger mFlinger;
Hwc2::mock::Composer* mComposer = nullptr;
@@ -95,11 +94,10 @@
mTunnelModeEnabledReporter->removeListener(mTunnelModeEnabledListener);
}
-sp<BufferStateLayer> TunnelModeEnabledReporterTest::createBufferStateLayer(
- LayerMetadata metadata = {}) {
+sp<Layer> TunnelModeEnabledReporterTest::createBufferStateLayer(LayerMetadata metadata = {}) {
sp<Client> client;
LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", LAYER_FLAGS, metadata);
- return sp<BufferStateLayer>::make(args);
+ return sp<Layer>::make(args);
}
void TunnelModeEnabledReporterTest::setupScheduler() {
diff --git a/services/surfaceflinger/tests/unittests/mock/MockLayer.h b/services/surfaceflinger/tests/unittests/mock/MockLayer.h
index 48d05cb..0d94f4c 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockLayer.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockLayer.h
@@ -18,14 +18,12 @@
#include <gmock/gmock.h>
-#include "BufferStateLayer.h"
-
namespace android::mock {
-class MockLayer : public BufferStateLayer {
+class MockLayer : public Layer {
public:
MockLayer(SurfaceFlinger* flinger, std::string name)
- : BufferStateLayer(LayerCreationArgs(flinger, nullptr, std::move(name), 0, {})) {
+ : Layer(LayerCreationArgs(flinger, nullptr, std::move(name), 0, {})) {
EXPECT_CALL(*this, getDefaultFrameRateCompatibility())
.WillOnce(testing::Return(scheduler::LayerInfo::FrameRateCompatibility::Default));
}
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 5719b5c..a87f82f 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -27,6 +27,9 @@
symbol_file: "libvulkan.map.txt",
first_version: "24",
unversioned_until: "current",
+ export_header_libs: [
+ "ndk_vulkan_headers",
+ ],
}
cc_library_shared {