Merge "libbinder: Don't abort when rpc parcel size is invalid" am: ec602d42c6 am: 6ae415f09c am: 864d1b731c am: 84657f326e am: 2280c1a688
Original change: https://android-review.googlesource.com/c/platform/frameworks/native/+/2153944
Change-Id: I69bb41437ee1060a2c3660b7d52a715ca636cef9
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/cmds/atrace/atrace.rc b/cmds/atrace/atrace.rc
index 5267b02..891b1c6 100644
--- a/cmds/atrace/atrace.rc
+++ b/cmds/atrace/atrace.rc
@@ -181,6 +181,8 @@
chmod 0666 /sys/kernel/tracing/events/clk/clk_enable/enable
chmod 0666 /sys/kernel/debug/tracing/events/clk/clk_set_rate/enable
chmod 0666 /sys/kernel/tracing/events/clk/clk_set_rate/enable
+ chmod 0666 /sys/kernel/debug/tracing/events/printk/console/enable
+ chmod 0666 /sys/kernel/tracing/events/printk/console/enable
# disk
chmod 0666 /sys/kernel/tracing/events/f2fs/f2fs_get_data_block/enable
diff --git a/data/etc/android.hardware.type.automotive.xml b/data/etc/android.hardware.type.automotive.xml
index 113945b..a9b4b05 100644
--- a/data/etc/android.hardware.type.automotive.xml
+++ b/data/etc/android.hardware.type.automotive.xml
@@ -17,6 +17,4 @@
<!-- These features determine that the device running android is a car. -->
<permissions>
<feature name="android.hardware.type.automotive" />
- <!-- TODO: Revert this after enabling work profiles refer b/170332519 -->
- <unavailable-feature name="android.software.managed_users"/>
</permissions>
diff --git a/include/input/Input.h b/include/input/Input.h
index e7d68fc..e0c9de4 100644
--- a/include/input/Input.h
+++ b/include/input/Input.h
@@ -1059,6 +1059,48 @@
uint32_t seq;
};
+/* Pointer icon styles.
+ * Must match the definition in android.view.PointerIcon.
+ *
+ * Due to backwards compatibility and public api constraints, this is a duplicate (but type safe)
+ * definition of PointerIcon.java.
+ *
+ * TODO(b/235023317) move this definition to an aidl and statically assign to the below java public
+ * api values.
+ *
+ * WARNING: Keep these definitions in sync with
+ * frameworks/base/core/java/android/view/PointerIcon.java
+ */
+enum class PointerIconStyle : int32_t {
+ TYPE_CUSTOM = -1,
+ TYPE_NULL = 0,
+ TYPE_ARROW = 1000,
+ TYPE_CONTEXT_MENU = 1001,
+ TYPE_HAND = 1002,
+ TYPE_HELP = 1003,
+ TYPE_WAIT = 1004,
+ TYPE_CELL = 1006,
+ TYPE_CROSSHAIR = 1007,
+ TYPE_TEXT = 1008,
+ TYPE_VERTICAL_TEXT = 1009,
+ TYPE_ALIAS = 1010,
+ TYPE_COPY = 1011,
+ TYPE_NO_DROP = 1012,
+ TYPE_ALL_SCROLL = 1013,
+ TYPE_HORIZONTAL_DOUBLE_ARROW = 1014,
+ TYPE_VERTICAL_DOUBLE_ARROW = 1015,
+ TYPE_TOP_RIGHT_DOUBLE_ARROW = 1016,
+ TYPE_TOP_LEFT_DOUBLE_ARROW = 1017,
+ TYPE_ZOOM_IN = 1018,
+ TYPE_ZOOM_OUT = 1019,
+ TYPE_GRAB = 1020,
+ TYPE_GRABBING = 1021,
+
+ TYPE_SPOT_HOVER = 2000,
+ TYPE_SPOT_TOUCH = 2001,
+ TYPE_SPOT_ANCHOR = 2002,
+};
+
} // namespace android
#endif // _LIBINPUT_INPUT_H
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 5f9a37d..dbc7bfa 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -452,8 +452,11 @@
*/
class InputConsumer {
public:
- /* Creates a consumer associated with an input channel. */
+ /* Create a consumer associated with an input channel. */
explicit InputConsumer(const std::shared_ptr<InputChannel>& channel);
+ /* Create a consumer associated with an input channel, override resampling system property */
+ explicit InputConsumer(const std::shared_ptr<InputChannel>& channel,
+ bool enableTouchResampling);
/* Destroys the consumer and releases its input channel. */
~InputConsumer();
diff --git a/include/input/PropertyMap.h b/include/input/PropertyMap.h
index 451918b..b1e3f85 100644
--- a/include/input/PropertyMap.h
+++ b/include/input/PropertyMap.h
@@ -18,10 +18,8 @@
#define _UTILS_PROPERTY_MAP_H
#include <android-base/result.h>
-#include <utils/Errors.h>
-#include <utils/KeyedVector.h>
-#include <utils/String8.h>
#include <utils/Tokenizer.h>
+#include <unordered_map>
namespace android {
@@ -58,30 +56,27 @@
/* Adds a property.
* Replaces the property with the same key if it is already present.
*/
- void addProperty(const String8& key, const String8& value);
-
- /* Returns true if the property map contains the specified key. */
- bool hasProperty(const String8& key) const;
+ void addProperty(const std::string& key, const std::string& value);
/* Gets the value of a property and parses it.
* Returns true and sets outValue if the key was found and its value was parsed successfully.
* Otherwise returns false and does not modify outValue. (Also logs a warning.)
*/
- bool tryGetProperty(const String8& key, String8& outValue) const;
- bool tryGetProperty(const String8& key, bool& outValue) const;
- bool tryGetProperty(const String8& key, int32_t& outValue) const;
- bool tryGetProperty(const String8& key, float& outValue) const;
+ bool tryGetProperty(const std::string& key, std::string& outValue) const;
+ bool tryGetProperty(const std::string& key, bool& outValue) const;
+ bool tryGetProperty(const std::string& key, int32_t& outValue) const;
+ bool tryGetProperty(const std::string& key, float& outValue) const;
/* Adds all values from the specified property map. */
void addAll(const PropertyMap* map);
- /* Gets the underlying property map. */
- inline const KeyedVector<String8, String8>& getProperties() const { return mProperties; }
-
/* Loads a property map from a file. */
static android::base::Result<std::unique_ptr<PropertyMap>> load(const char* filename);
private:
+ /* Returns true if the property map contains the specified key. */
+ bool hasProperty(const std::string& key) const;
+
class Parser {
PropertyMap* mMap;
Tokenizer* mTokenizer;
@@ -95,11 +90,11 @@
status_t parseType();
status_t parseKey();
status_t parseKeyProperty();
- status_t parseModifier(const String8& token, int32_t* outMetaState);
+ status_t parseModifier(const std::string& token, int32_t* outMetaState);
status_t parseCharacterLiteral(char16_t* outCharacter);
};
- KeyedVector<String8, String8> mProperties;
+ std::unordered_map<std::string, std::string> mProperties;
};
} // namespace android
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 441a4a8..5e9f540 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -260,10 +260,6 @@
},
afdo: true,
-
- header_abi_checker: {
- diff_flags: ["-allow-adding-removing-weak-symbols"],
- },
}
cc_library_static {
@@ -367,9 +363,7 @@
local_include_dir: "aidl",
host_supported: true,
srcs: [
- "aidl/android/content/pm/IPackageChangeObserver.aidl",
"aidl/android/content/pm/IPackageManagerNative.aidl",
- "aidl/android/content/pm/PackageChangeEvent.aidl",
"aidl/android/content/pm/IStagedApexObserver.aidl",
"aidl/android/content/pm/ApexStagedEvent.aidl",
"aidl/android/content/pm/StagedApexInfo.aidl",
diff --git a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
index 7c99f76..f8a8843 100644
--- a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
+++ b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
@@ -17,7 +17,6 @@
package android.content.pm;
-import android.content.pm.IPackageChangeObserver;
import android.content.pm.IStagedApexObserver;
import android.content.pm.StagedApexInfo;
@@ -92,18 +91,6 @@
*/
@utf8InCpp String getModuleMetadataPackageName();
- /* Returns the names of all packages. */
- @utf8InCpp String[] getAllPackages();
-
- /** Register an extra package change observer to receive the multi-cast. */
- void registerPackageChangeObserver(in IPackageChangeObserver observer);
-
- /**
- * Unregister an existing package change observer.
- * This does nothing if this observer was not already registered.
- */
- void unregisterPackageChangeObserver(in IPackageChangeObserver observer);
-
/**
* Returns true if the package has the SHA 256 version of the signing certificate.
* @see PackageManager#hasSigningCertificate(String, byte[], int), where type
diff --git a/libs/binder/aidl/android/content/pm/PackageChangeEvent.aidl b/libs/binder/aidl/android/content/pm/PackageChangeEvent.aidl
deleted file mode 100644
index e30e907..0000000
--- a/libs/binder/aidl/android/content/pm/PackageChangeEvent.aidl
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.pm;
-
-/**
- * This event is designed for notification to native code listener about
- * any changes on a package including update, deletion and etc.
- *
- * @hide
- */
-parcelable PackageChangeEvent {
- @utf8InCpp String packageName;
- long version;
- long lastUpdateTimeMillis;
- boolean newInstalled;
- boolean dataRemoved;
- boolean isDeleted;
-}
diff --git a/libs/binder/include/binder/IInterface.h b/libs/binder/include/binder/IInterface.h
index 9f7e2c8..dc572ac 100644
--- a/libs/binder/include/binder/IInterface.h
+++ b/libs/binder/include/binder/IInterface.h
@@ -219,80 +219,79 @@
namespace internal {
constexpr const char* const kManualInterfaces[] = {
- "android.app.IActivityManager",
- "android.app.IUidObserver",
- "android.drm.IDrm",
- "android.dvr.IVsyncCallback",
- "android.dvr.IVsyncService",
- "android.gfx.tests.ICallback",
- "android.gfx.tests.IIPCTest",
- "android.gfx.tests.ISafeInterfaceTest",
- "android.graphicsenv.IGpuService",
- "android.gui.IConsumerListener",
- "android.gui.IGraphicBufferConsumer",
- "android.gui.ITransactionComposerListener",
- "android.gui.SensorEventConnection",
- "android.gui.SensorServer",
- "android.hardware.ICamera",
- "android.hardware.ICameraClient",
- "android.hardware.ICameraRecordingProxy",
- "android.hardware.ICameraRecordingProxyListener",
- "android.hardware.ICrypto",
- "android.hardware.IOMXObserver",
- "android.hardware.IStreamListener",
- "android.hardware.IStreamSource",
- "android.media.IAudioService",
- "android.media.IDataSource",
- "android.media.IDrmClient",
- "android.media.IMediaCodecList",
- "android.media.IMediaDrmService",
- "android.media.IMediaExtractor",
- "android.media.IMediaExtractorService",
- "android.media.IMediaHTTPConnection",
- "android.media.IMediaHTTPService",
- "android.media.IMediaLogService",
- "android.media.IMediaMetadataRetriever",
- "android.media.IMediaMetricsService",
- "android.media.IMediaPlayer",
- "android.media.IMediaPlayerClient",
- "android.media.IMediaPlayerService",
- "android.media.IMediaRecorder",
- "android.media.IMediaRecorderClient",
- "android.media.IMediaResourceMonitor",
- "android.media.IMediaSource",
- "android.media.IRemoteDisplay",
- "android.media.IRemoteDisplayClient",
- "android.media.IResourceManagerClient",
- "android.media.IResourceManagerService",
- "android.os.IComplexTypeInterface",
- "android.os.IPermissionController",
- "android.os.IPingResponder",
- "android.os.IProcessInfoService",
- "android.os.ISchedulingPolicyService",
- "android.os.IStringConstants",
- "android.os.storage.IObbActionListener",
- "android.os.storage.IStorageEventListener",
- "android.os.storage.IStorageManager",
- "android.os.storage.IStorageShutdownObserver",
- "android.service.vr.IPersistentVrStateCallbacks",
- "android.service.vr.IVrManager",
- "android.service.vr.IVrStateCallbacks",
- "android.ui.ISurfaceComposer",
- "android.ui.ISurfaceComposerClient",
- "android.utils.IMemory",
- "android.utils.IMemoryHeap",
- "com.android.car.procfsinspector.IProcfsInspector",
- "com.android.internal.app.IAppOpsCallback",
- "com.android.internal.app.IAppOpsService",
- "com.android.internal.app.IBatteryStats",
- "com.android.internal.os.IResultReceiver",
- "com.android.internal.os.IShellCallback",
- "drm.IDrmManagerService",
- "drm.IDrmServiceListener",
- "IAAudioClient",
- "IAAudioService",
- "VtsFuzzer",
- nullptr,
+ "android.app.IActivityManager",
+ "android.app.IUidObserver",
+ "android.drm.IDrm",
+ "android.dvr.IVsyncCallback",
+ "android.dvr.IVsyncService",
+ "android.gfx.tests.ICallback",
+ "android.gfx.tests.IIPCTest",
+ "android.gfx.tests.ISafeInterfaceTest",
+ "android.graphicsenv.IGpuService",
+ "android.gui.IConsumerListener",
+ "android.gui.IGraphicBufferConsumer",
+ "android.gui.ITransactionComposerListener",
+ "android.gui.SensorEventConnection",
+ "android.gui.SensorServer",
+ "android.hardware.ICamera",
+ "android.hardware.ICameraClient",
+ "android.hardware.ICameraRecordingProxy",
+ "android.hardware.ICameraRecordingProxyListener",
+ "android.hardware.ICrypto",
+ "android.hardware.IOMXObserver",
+ "android.hardware.IStreamListener",
+ "android.hardware.IStreamSource",
+ "android.media.IAudioService",
+ "android.media.IDataSource",
+ "android.media.IDrmClient",
+ "android.media.IMediaCodecList",
+ "android.media.IMediaDrmService",
+ "android.media.IMediaExtractor",
+ "android.media.IMediaExtractorService",
+ "android.media.IMediaHTTPConnection",
+ "android.media.IMediaHTTPService",
+ "android.media.IMediaLogService",
+ "android.media.IMediaMetadataRetriever",
+ "android.media.IMediaMetricsService",
+ "android.media.IMediaPlayer",
+ "android.media.IMediaPlayerClient",
+ "android.media.IMediaPlayerService",
+ "android.media.IMediaRecorder",
+ "android.media.IMediaRecorderClient",
+ "android.media.IMediaResourceMonitor",
+ "android.media.IMediaSource",
+ "android.media.IRemoteDisplay",
+ "android.media.IRemoteDisplayClient",
+ "android.media.IResourceManagerClient",
+ "android.media.IResourceManagerService",
+ "android.os.IComplexTypeInterface",
+ "android.os.IPermissionController",
+ "android.os.IPingResponder",
+ "android.os.IProcessInfoService",
+ "android.os.ISchedulingPolicyService",
+ "android.os.IStringConstants",
+ "android.os.storage.IObbActionListener",
+ "android.os.storage.IStorageEventListener",
+ "android.os.storage.IStorageManager",
+ "android.os.storage.IStorageShutdownObserver",
+ "android.service.vr.IPersistentVrStateCallbacks",
+ "android.service.vr.IVrManager",
+ "android.service.vr.IVrStateCallbacks",
+ "android.ui.ISurfaceComposer",
+ "android.utils.IMemory",
+ "android.utils.IMemoryHeap",
+ "com.android.car.procfsinspector.IProcfsInspector",
+ "com.android.internal.app.IAppOpsCallback",
+ "com.android.internal.app.IAppOpsService",
+ "com.android.internal.app.IBatteryStats",
+ "com.android.internal.os.IResultReceiver",
+ "com.android.internal.os.IShellCallback",
+ "drm.IDrmManagerService",
+ "drm.IDrmServiceListener",
+ "IAAudioClient",
+ "IAAudioService",
+ "VtsFuzzer",
+ nullptr,
};
constexpr const char* const kDownstreamManualInterfaces[] = {
diff --git a/libs/bufferqueueconverter/Android.bp b/libs/bufferqueueconverter/Android.bp
index c5d3a32..5f145a1 100644
--- a/libs/bufferqueueconverter/Android.bp
+++ b/libs/bufferqueueconverter/Android.bp
@@ -22,6 +22,7 @@
double_loadable: true,
srcs: [
+ ":libgui_frame_event_aidl",
"BufferQueueConverter.cpp",
],
diff --git a/libs/graphicsenv/GraphicsEnv.cpp b/libs/graphicsenv/GraphicsEnv.cpp
index 7f0cac5..4a0a839 100644
--- a/libs/graphicsenv/GraphicsEnv.cpp
+++ b/libs/graphicsenv/GraphicsEnv.cpp
@@ -364,26 +364,61 @@
return (mUseAngle == YES) ? true : false;
}
+bool GraphicsEnv::angleIsSystemDriver() {
+ // Make sure we are init'ed
+ if (mAngleAppName.empty()) {
+ ALOGV("App name is empty. setAngleInfo() has not been called to enable ANGLE.");
+ return false;
+ }
+
+ return (mAngleIsSystemDriver == YES) ? true : false;
+}
+
+bool GraphicsEnv::shouldForceLegacyDriver() {
+ // Make sure we are init'ed
+ if (mAngleAppName.empty()) {
+ ALOGV("App name is empty. setAngleInfo() has not been called to enable ANGLE.");
+ return false;
+ }
+
+ return (mAngleIsSystemDriver == YES && mUseAngle == NO) ? true : false;
+}
+
+std::string GraphicsEnv::getLegacySuffix() {
+ return mLegacyDriverSuffix;
+}
+
void GraphicsEnv::updateUseAngle() {
mUseAngle = NO;
const char* ANGLE_PREFER_ANGLE = "angle";
+ const char* ANGLE_PREFER_LEGACY = "legacy";
+ // The following is a deprecated version of "legacy"
const char* ANGLE_PREFER_NATIVE = "native";
mUseAngle = NO;
if (mAngleDeveloperOptIn == ANGLE_PREFER_ANGLE) {
- ALOGV("User set \"Developer Options\" to force the use of ANGLE");
+ ALOGI("Using ANGLE, the %s GLES driver for package '%s'",
+ mAngleIsSystemDriver == YES ? "system" : "optional", mAngleAppName.c_str());
mUseAngle = YES;
- } else if (mAngleDeveloperOptIn == ANGLE_PREFER_NATIVE) {
- ALOGV("User set \"Developer Options\" to force the use of Native");
+ } else if (mAngleDeveloperOptIn == ANGLE_PREFER_LEGACY ||
+ mAngleDeveloperOptIn == ANGLE_PREFER_NATIVE) {
+ ALOGI("Using the (%s) Legacy GLES driver for package '%s'",
+ mAngleIsSystemDriver == YES ? "optional" : "system", mAngleAppName.c_str());
} else {
ALOGV("User set invalid \"Developer Options\": '%s'", mAngleDeveloperOptIn.c_str());
}
}
void GraphicsEnv::setAngleInfo(const std::string path, const std::string appName,
- const std::string developerOptIn,
+ const bool angleIsSystemDriver, const std::string developerOptIn,
const std::vector<std::string> eglFeatures) {
+ // Set whether ANGLE is the system driver:
+ mAngleIsSystemDriver = angleIsSystemDriver ? YES : NO;
+
+ // Note: Given the current logic and lack of the old rules file processing,
+ // there seems to be little chance that mUseAngle != UNKNOWN. Leave this
+ // for now, even though it seems outdated.
if (mUseAngle != UNKNOWN) {
// We've already figured out an answer for this app, so just return.
ALOGV("Already evaluated the rules file for '%s': use ANGLE = %s", appName.c_str(),
@@ -404,6 +439,25 @@
updateUseAngle();
}
+void GraphicsEnv::setLegacyDriverInfo(const std::string appName, const bool angleIsSystemDriver,
+ const std::string legacyDriverName) {
+ ALOGV("setting legacy app name to '%s'", appName.c_str());
+ mAngleAppName = appName;
+
+ // Force the use of the legacy driver instead of ANGLE
+ const char* ANGLE_PREFER_LEGACY = "legacy";
+ mAngleDeveloperOptIn = ANGLE_PREFER_LEGACY;
+ ALOGV("setting ANGLE application opt-in to 'legacy'");
+
+ // Set whether ANGLE is the system driver:
+ mAngleIsSystemDriver = angleIsSystemDriver ? YES : NO;
+
+ mLegacyDriverSuffix = legacyDriverName;
+
+ // Update the current status of whether we should use ANGLE or not
+ updateUseAngle();
+}
+
void GraphicsEnv::setLayerPaths(NativeLoaderNamespace* appNamespace, const std::string layerPaths) {
if (mLayerPaths.empty()) {
mLayerPaths = layerPaths;
diff --git a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
index 56d1139..82a6b6c 100644
--- a/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
+++ b/libs/graphicsenv/include/graphicsenv/GraphicsEnv.h
@@ -91,17 +91,28 @@
bool shouldUseAngle(std::string appName);
// Check if this app process should use ANGLE.
bool shouldUseAngle();
+ // If ANGLE is the system GLES driver
+ bool angleIsSystemDriver();
+ // If should use legacy driver instead of a system ANGLE driver
+ bool shouldForceLegacyDriver();
// Set a search path for loading ANGLE libraries. The path is a list of
// directories separated by ':'. A directory can be contained in a zip file
// (libraries must be stored uncompressed and page aligned); such elements
// in the search path must have a '!' after the zip filename, e.g.
// /system/app/ANGLEPrebuilt/ANGLEPrebuilt.apk!/lib/arm64-v8a
- void setAngleInfo(const std::string path, const std::string appName, std::string devOptIn,
+ void setAngleInfo(const std::string path, const std::string appName,
+ const bool angleIsSystemDriver, std::string devOptIn,
const std::vector<std::string> eglFeatures);
+ // Set the state so that the legacy driver will be used, and in case ANGLE
+ // is the system driver, provide the name of the legacy driver.
+ void setLegacyDriverInfo(const std::string appName, const bool angleIsSystemDriver,
+ const std::string legacyDriverName);
// Get the ANGLE driver namespace.
android_namespace_t* getAngleNamespace();
// Get the app name for ANGLE debug message.
std::string& getAngleAppName();
+ // Get the legacy driver's suffix name.
+ std::string getLegacySuffix();
const std::vector<std::string>& getAngleEglFeatures();
@@ -156,6 +167,10 @@
std::string mAngleDeveloperOptIn;
// ANGLE EGL features;
std::vector<std::string> mAngleEglFeatures;
+ // ANGLE is System Driver flag.
+ UseAngle mAngleIsSystemDriver = UNKNOWN;
+ // Legacy driver name to use when ANGLE is the system driver.
+ std::string mLegacyDriverSuffix;
// Use ANGLE flag.
UseAngle mUseAngle = UNKNOWN;
// Vulkan debug layers libs.
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 5a2b92b..d7bc500 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -120,6 +120,12 @@
path: "aidl/",
}
+filegroup {
+ name: "libgui_frame_event_aidl",
+ srcs: ["aidl/android/gui/FrameEvent.aidl"],
+ path: "aidl/",
+}
+
cc_library_static {
name: "libgui_aidl_static",
vendor_available: true,
@@ -136,16 +142,24 @@
"include",
],
+ include_dirs: [
+ "frameworks/native/include",
+ ],
+
export_shared_lib_headers: [
"libbinder",
],
static_libs: [
"libui-types",
+ "libgui_window_info_static",
],
aidl: {
export_aidl_headers: true,
+ include_dirs: [
+ "frameworks/native/libs/gui",
+ ],
},
}
@@ -179,19 +193,18 @@
"BufferHubConsumer.cpp",
"BufferHubProducer.cpp",
"BufferItemConsumer.cpp",
+ "CompositorTiming.cpp",
"ConsumerBase.cpp",
"CpuConsumer.cpp",
"DebugEGLImageTracker.cpp",
"DisplayEventDispatcher.cpp",
"DisplayEventReceiver.cpp",
- "FrameTimelineInfo.cpp",
"GLConsumer.cpp",
"IConsumerListener.cpp",
"IGraphicBufferConsumer.cpp",
"IGraphicBufferProducer.cpp",
"IProducerListener.cpp",
"ISurfaceComposer.cpp",
- "ISurfaceComposerClient.cpp",
"ITransactionCompletedListener.cpp",
"LayerDebugInfo.cpp",
"LayerMetadata.cpp",
@@ -282,10 +295,16 @@
defaults: ["libgui_bufferqueue-defaults"],
srcs: [
+ ":libgui_frame_event_aidl",
":inputconstants_aidl",
":libgui_bufferqueue_sources",
- ":libgui_aidl",
],
+
+ aidl: {
+ include_dirs: [
+ "frameworks/native/libs/gui",
+ ],
+ },
}
filegroup {
@@ -404,6 +423,7 @@
],
srcs: [
+ ":libgui_frame_event_aidl",
"mock/GraphicBufferConsumer.cpp",
"mock/GraphicBufferProducer.cpp",
],
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index aba81f6..3bf2e19 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -33,6 +33,7 @@
#include <utils/Trace.h>
#include <private/gui/ComposerService.h>
+#include <private/gui/ComposerServiceAIDL.h>
#include <chrono>
@@ -158,9 +159,8 @@
id++;
mBufferItemConsumer->setName(String8(consumerName.c_str()));
mBufferItemConsumer->setFrameAvailableListener(this);
- mBufferItemConsumer->setBufferFreedListener(this);
- ComposerService::getComposerService()->getMaxAcquiredBufferCount(&mMaxAcquiredBuffers);
+ ComposerServiceAIDL::getComposerService()->getMaxAcquiredBufferCount(&mMaxAcquiredBuffers);
mBufferItemConsumer->setMaxAcquiredBufferCount(mMaxAcquiredBuffers);
mCurrentMaxAcquiredBufferCount = mMaxAcquiredBuffers;
mNumAcquired = 0;
@@ -566,7 +566,7 @@
if (dequeueTime != mDequeueTimestamps.end()) {
Parcel p;
p.writeInt64(dequeueTime->second);
- t->setMetadata(mSurfaceControl, METADATA_DEQUEUE_TIME, p);
+ t->setMetadata(mSurfaceControl, gui::METADATA_DEQUEUE_TIME, p);
mDequeueTimestamps.erase(dequeueTime);
}
}
@@ -599,6 +599,7 @@
}
void BLASTBufferQueue::acquireAndReleaseBuffer() {
+ BBQ_TRACE();
BufferItem bufferItem;
status_t status =
mBufferItemConsumer->acquireBuffer(&bufferItem, 0 /* expectedPresent */, false);
@@ -612,6 +613,7 @@
}
void BLASTBufferQueue::flushAndWaitForFreeBuffer(std::unique_lock<std::mutex>& lock) {
+ BBQ_TRACE();
if (!mSyncedFrameNumbers.empty() && mNumFrameAvailable > 0) {
// We are waiting on a previous sync's transaction callback so allow another sync
// transaction to proceed.
@@ -642,8 +644,8 @@
bool waitForTransactionCallback = !mSyncedFrameNumbers.empty();
{
- BBQ_TRACE();
std::unique_lock _lock{mMutex};
+ BBQ_TRACE();
const bool syncTransactionSet = mTransactionReadyCallback != nullptr;
BQA_LOGV("onFrameAvailable-start syncTransactionSet=%s", boolToString(syncTransactionSet));
@@ -1119,7 +1121,6 @@
if (mBufferItemConsumer != nullptr) {
mBufferItemConsumer->abandon();
mBufferItemConsumer->setFrameAvailableListener(nullptr);
- mBufferItemConsumer->setBufferFreedListener(nullptr);
}
mBufferItemConsumer = nullptr;
mConsumer = nullptr;
diff --git a/libs/gui/CompositorTiming.cpp b/libs/gui/CompositorTiming.cpp
new file mode 100644
index 0000000..50f7b25
--- /dev/null
+++ b/libs/gui/CompositorTiming.cpp
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "CompositorTiming"
+
+#include <cutils/compiler.h>
+#include <gui/CompositorTiming.h>
+#include <log/log.h>
+
+namespace android::gui {
+
+CompositorTiming::CompositorTiming(nsecs_t vsyncDeadline, nsecs_t vsyncPeriod, nsecs_t vsyncPhase,
+ nsecs_t presentLatency) {
+ if (CC_UNLIKELY(vsyncPeriod <= 0)) {
+ ALOGE("Invalid VSYNC period");
+ return;
+ }
+
+ const nsecs_t idealLatency = [=] {
+ // Modulo rounds toward 0 not INT64_MIN, so treat signs separately.
+ if (vsyncPhase < 0) return -vsyncPhase % vsyncPeriod;
+
+ const nsecs_t latency = (vsyncPeriod - vsyncPhase) % vsyncPeriod;
+ return latency > 0 ? latency : vsyncPeriod;
+ }();
+
+ // Snap the latency to a value that removes scheduling jitter from the composite and present
+ // times, which often have >1ms of jitter. Reducing jitter is important if an app attempts to
+ // extrapolate something like user input to an accurate present time. Snapping also allows an
+ // app to precisely calculate vsyncPhase with (presentLatency % interval).
+ const nsecs_t bias = vsyncPeriod / 2;
+ const nsecs_t extraVsyncs = (presentLatency - idealLatency + bias) / vsyncPeriod;
+ const nsecs_t snappedLatency =
+ extraVsyncs > 0 ? idealLatency + extraVsyncs * vsyncPeriod : idealLatency;
+
+ this->deadline = vsyncDeadline - idealLatency;
+ this->interval = vsyncPeriod;
+ this->presentLatency = snappedLatency;
+}
+
+} // namespace android::gui
diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp
index dfdce20..501e69a 100644
--- a/libs/gui/DisplayEventDispatcher.cpp
+++ b/libs/gui/DisplayEventDispatcher.cpp
@@ -35,11 +35,14 @@
static constexpr nsecs_t WAITING_FOR_VSYNC_TIMEOUT = ms2ns(300);
-DisplayEventDispatcher::DisplayEventDispatcher(
- const sp<Looper>& looper, ISurfaceComposer::VsyncSource vsyncSource,
- ISurfaceComposer::EventRegistrationFlags eventRegistration)
- : mLooper(looper), mReceiver(vsyncSource, eventRegistration), mWaitingForVsync(false),
- mLastVsyncCount(0), mLastScheduleVsyncTime(0) {
+DisplayEventDispatcher::DisplayEventDispatcher(const sp<Looper>& looper,
+ gui::ISurfaceComposer::VsyncSource vsyncSource,
+ EventRegistrationFlags eventRegistration)
+ : mLooper(looper),
+ mReceiver(vsyncSource, eventRegistration),
+ mWaitingForVsync(false),
+ mLastVsyncCount(0),
+ mLastScheduleVsyncTime(0) {
ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this);
}
diff --git a/libs/gui/DisplayEventReceiver.cpp b/libs/gui/DisplayEventReceiver.cpp
index bfb7769..c52fb6b 100644
--- a/libs/gui/DisplayEventReceiver.cpp
+++ b/libs/gui/DisplayEventReceiver.cpp
@@ -19,10 +19,9 @@
#include <utils/Errors.h>
#include <gui/DisplayEventReceiver.h>
-#include <gui/ISurfaceComposer.h>
#include <gui/VsyncEventData.h>
-#include <private/gui/ComposerService.h>
+#include <private/gui/ComposerServiceAIDL.h>
#include <private/gui/BitTube.h>
@@ -32,15 +31,20 @@
// ---------------------------------------------------------------------------
-DisplayEventReceiver::DisplayEventReceiver(
- ISurfaceComposer::VsyncSource vsyncSource,
- ISurfaceComposer::EventRegistrationFlags eventRegistration) {
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+DisplayEventReceiver::DisplayEventReceiver(gui::ISurfaceComposer::VsyncSource vsyncSource,
+ EventRegistrationFlags eventRegistration) {
+ sp<gui::ISurfaceComposer> sf(ComposerServiceAIDL::getComposerService());
if (sf != nullptr) {
- mEventConnection = sf->createDisplayEventConnection(vsyncSource, eventRegistration);
+ mEventConnection = nullptr;
+ binder::Status status =
+ sf->createDisplayEventConnection(vsyncSource,
+ static_cast<
+ gui::ISurfaceComposer::EventRegistration>(
+ eventRegistration.get()),
+ &mEventConnection);
if (mEventConnection != nullptr) {
mDataChannel = std::make_unique<gui::BitTube>();
- const auto status = mEventConnection->stealReceiveChannel(mDataChannel.get());
+ status = mEventConnection->stealReceiveChannel(mDataChannel.get());
if (!status.isOk()) {
ALOGE("stealReceiveChannel failed: %s", status.toString8().c_str());
mInitError = std::make_optional<status_t>(status.transactionError());
diff --git a/libs/gui/FrameTimelineInfo.cpp b/libs/gui/FrameTimelineInfo.cpp
deleted file mode 100644
index 3800b88..0000000
--- a/libs/gui/FrameTimelineInfo.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2021 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 "FrameTimelineInfo"
-
-#include <inttypes.h>
-
-#include <android/os/IInputConstants.h>
-#include <gui/FrameTimelineInfo.h>
-#include <gui/LayerState.h>
-#include <private/gui/ParcelUtils.h>
-#include <utils/Errors.h>
-
-#include <cmath>
-
-using android::os::IInputConstants;
-
-namespace android {
-
-status_t FrameTimelineInfo::write(Parcel& output) const {
- SAFE_PARCEL(output.writeInt64, vsyncId);
- SAFE_PARCEL(output.writeInt32, inputEventId);
- SAFE_PARCEL(output.writeInt64, startTimeNanos);
- return NO_ERROR;
-}
-
-status_t FrameTimelineInfo::read(const Parcel& input) {
- SAFE_PARCEL(input.readInt64, &vsyncId);
- SAFE_PARCEL(input.readInt32, &inputEventId);
- SAFE_PARCEL(input.readInt64, &startTimeNanos);
- return NO_ERROR;
-}
-
-void FrameTimelineInfo::merge(const FrameTimelineInfo& other) {
- // When merging vsync Ids we take the oldest valid one
- if (vsyncId != INVALID_VSYNC_ID && other.vsyncId != INVALID_VSYNC_ID) {
- if (other.vsyncId > vsyncId) {
- vsyncId = other.vsyncId;
- inputEventId = other.inputEventId;
- startTimeNanos = other.startTimeNanos;
- }
- } else if (vsyncId == INVALID_VSYNC_ID) {
- vsyncId = other.vsyncId;
- inputEventId = other.inputEventId;
- startTimeNanos = other.startTimeNanos;
- }
-}
-
-void FrameTimelineInfo::clear() {
- vsyncId = INVALID_VSYNC_ID;
- inputEventId = IInputConstants::INVALID_INPUT_EVENT_ID;
- startTimeNanos = 0;
-}
-
-}; // namespace android
diff --git a/libs/gui/GLConsumerUtils.cpp b/libs/gui/GLConsumerUtils.cpp
index 7a06c3d..a1c69e7 100644
--- a/libs/gui/GLConsumerUtils.cpp
+++ b/libs/gui/GLConsumerUtils.cpp
@@ -27,6 +27,13 @@
void GLConsumer::computeTransformMatrix(float outTransform[16],
const sp<GraphicBuffer>& buf, const Rect& cropRect, uint32_t transform,
bool filtering) {
+ computeTransformMatrix(outTransform, buf->getWidth(), buf->getHeight(), buf->getPixelFormat(),
+ cropRect, transform, filtering);
+}
+
+void GLConsumer::computeTransformMatrix(float outTransform[16], float bufferWidth,
+ float bufferHeight, PixelFormat pixelFormat,
+ const Rect& cropRect, uint32_t transform, bool filtering) {
// Transform matrices
static const mat4 mtxFlipH(
-1, 0, 0, 0,
@@ -60,8 +67,6 @@
if (!cropRect.isEmpty()) {
float tx = 0.0f, ty = 0.0f, sx = 1.0f, sy = 1.0f;
- float bufferWidth = buf->getWidth();
- float bufferHeight = buf->getHeight();
float shrinkAmount = 0.0f;
if (filtering) {
// In order to prevent bilinear sampling beyond the edge of the
@@ -70,7 +75,7 @@
// off each end, but because the chroma channels of YUV420 images
// are subsampled we may need to shrink the crop region by a whole
// texel on each side.
- switch (buf->getPixelFormat()) {
+ switch (pixelFormat) {
case PIXEL_FORMAT_RGBA_8888:
case PIXEL_FORMAT_RGBX_8888:
case PIXEL_FORMAT_RGBA_FP16:
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 24d39fe..af64b3b 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -25,8 +25,6 @@
#include <binder/Parcel.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/ISurfaceComposer.h>
-#include <gui/ISurfaceComposerClient.h>
-#include <gui/LayerDebugInfo.h>
#include <gui/LayerState.h>
#include <private/gui/ParcelUtils.h>
#include <stdint.h>
@@ -37,7 +35,6 @@
#include <ui/DisplayState.h>
#include <ui/DynamicDisplayInfo.h>
#include <ui/HdrCapabilities.h>
-#include <ui/StaticDisplayInfo.h>
#include <utils/Log.h>
// ---------------------------------------------------------------------------
@@ -63,14 +60,6 @@
virtual ~BpSurfaceComposer();
- virtual sp<ISurfaceComposerClient> createConnection()
- {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- remote()->transact(BnSurfaceComposer::CREATE_CONNECTION, data, &reply);
- return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
- }
-
status_t setTransactionState(const FrameTimelineInfo& frameTimelineInfo,
const Vector<ComposerState>& state,
const Vector<DisplayState>& displays, uint32_t flags,
@@ -82,7 +71,7 @@
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- SAFE_PARCEL(frameTimelineInfo.write, data);
+ frameTimelineInfo.writeToParcel(&data);
SAFE_PARCEL(data.writeUint32, static_cast<uint32_t>(state.size()));
for (const auto& s : state) {
@@ -119,905 +108,6 @@
data, &reply);
}
}
-
- void bootFinished() override {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply);
- }
-
- bool authenticateSurfaceTexture(
- const sp<IGraphicBufferProducer>& bufferProducer) const override {
- Parcel data, reply;
- int err = NO_ERROR;
- err = data.writeInterfaceToken(
- ISurfaceComposer::getInterfaceDescriptor());
- if (err != NO_ERROR) {
- ALOGE("ISurfaceComposer::authenticateSurfaceTexture: error writing "
- "interface descriptor: %s (%d)", strerror(-err), -err);
- return false;
- }
- err = data.writeStrongBinder(IInterface::asBinder(bufferProducer));
- if (err != NO_ERROR) {
- ALOGE("ISurfaceComposer::authenticateSurfaceTexture: error writing "
- "strong binder to parcel: %s (%d)", strerror(-err), -err);
- return false;
- }
- err = remote()->transact(BnSurfaceComposer::AUTHENTICATE_SURFACE, data,
- &reply);
- if (err != NO_ERROR) {
- ALOGE("ISurfaceComposer::authenticateSurfaceTexture: error "
- "performing transaction: %s (%d)", strerror(-err), -err);
- return false;
- }
- int32_t result = 0;
- err = reply.readInt32(&result);
- if (err != NO_ERROR) {
- ALOGE("ISurfaceComposer::authenticateSurfaceTexture: error "
- "retrieving result: %s (%d)", strerror(-err), -err);
- return false;
- }
- return result != 0;
- }
-
- status_t getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported) const override {
- if (!outSupported) {
- return UNEXPECTED_NULL;
- }
- outSupported->clear();
-
- Parcel data, reply;
-
- status_t err = data.writeInterfaceToken(
- ISurfaceComposer::getInterfaceDescriptor());
- if (err != NO_ERROR) {
- return err;
- }
-
- err = remote()->transact(
- BnSurfaceComposer::GET_SUPPORTED_FRAME_TIMESTAMPS,
- data, &reply);
- if (err != NO_ERROR) {
- return err;
- }
-
- int32_t result = 0;
- err = reply.readInt32(&result);
- if (err != NO_ERROR) {
- return err;
- }
- if (result != NO_ERROR) {
- return result;
- }
-
- std::vector<int32_t> supported;
- err = reply.readInt32Vector(&supported);
- if (err != NO_ERROR) {
- return err;
- }
-
- outSupported->reserve(supported.size());
- for (int32_t s : supported) {
- outSupported->push_back(static_cast<FrameEvent>(s));
- }
- return NO_ERROR;
- }
-
- sp<IDisplayEventConnection> createDisplayEventConnection(
- VsyncSource vsyncSource, EventRegistrationFlags eventRegistration) override {
- Parcel data, reply;
- sp<IDisplayEventConnection> result;
- int err = data.writeInterfaceToken(
- ISurfaceComposer::getInterfaceDescriptor());
- if (err != NO_ERROR) {
- return result;
- }
- data.writeInt32(static_cast<int32_t>(vsyncSource));
- data.writeUint32(eventRegistration.get());
- err = remote()->transact(
- BnSurfaceComposer::CREATE_DISPLAY_EVENT_CONNECTION,
- data, &reply);
- if (err != NO_ERROR) {
- ALOGE("ISurfaceComposer::createDisplayEventConnection: error performing "
- "transaction: %s (%d)", strerror(-err), -err);
- return result;
- }
- result = interface_cast<IDisplayEventConnection>(reply.readStrongBinder());
- return result;
- }
-
- status_t getStaticDisplayInfo(const sp<IBinder>& display,
- ui::StaticDisplayInfo* info) override {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- data.writeStrongBinder(display);
- remote()->transact(BnSurfaceComposer::GET_STATIC_DISPLAY_INFO, data, &reply);
- const status_t result = reply.readInt32();
- if (result != NO_ERROR) return result;
- return reply.read(*info);
- }
-
- status_t getDynamicDisplayInfo(const sp<IBinder>& display,
- ui::DynamicDisplayInfo* info) override {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- data.writeStrongBinder(display);
- remote()->transact(BnSurfaceComposer::GET_DYNAMIC_DISPLAY_INFO, data, &reply);
- const status_t result = reply.readInt32();
- if (result != NO_ERROR) return result;
- return reply.read(*info);
- }
-
- status_t getDisplayNativePrimaries(const sp<IBinder>& display,
- ui::DisplayPrimaries& primaries) override {
- Parcel data, reply;
- status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (result != NO_ERROR) {
- ALOGE("getDisplayNativePrimaries failed to writeInterfaceToken: %d", result);
- return result;
- }
- result = data.writeStrongBinder(display);
- if (result != NO_ERROR) {
- ALOGE("getDisplayNativePrimaries failed to writeStrongBinder: %d", result);
- return result;
- }
- result = remote()->transact(BnSurfaceComposer::GET_DISPLAY_NATIVE_PRIMARIES, data, &reply);
- if (result != NO_ERROR) {
- ALOGE("getDisplayNativePrimaries failed to transact: %d", result);
- return result;
- }
- result = reply.readInt32();
- if (result == NO_ERROR) {
- memcpy(&primaries, reply.readInplace(sizeof(ui::DisplayPrimaries)),
- sizeof(ui::DisplayPrimaries));
- }
- return result;
- }
-
- status_t setActiveColorMode(const sp<IBinder>& display, ColorMode colorMode) override {
- Parcel data, reply;
- status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (result != NO_ERROR) {
- ALOGE("setActiveColorMode failed to writeInterfaceToken: %d", result);
- return result;
- }
- result = data.writeStrongBinder(display);
- if (result != NO_ERROR) {
- ALOGE("setActiveColorMode failed to writeStrongBinder: %d", result);
- return result;
- }
- result = data.writeInt32(static_cast<int32_t>(colorMode));
- if (result != NO_ERROR) {
- ALOGE("setActiveColorMode failed to writeInt32: %d", result);
- return result;
- }
- result = remote()->transact(BnSurfaceComposer::SET_ACTIVE_COLOR_MODE, data, &reply);
- if (result != NO_ERROR) {
- ALOGE("setActiveColorMode failed to transact: %d", result);
- return result;
- }
- return static_cast<status_t>(reply.readInt32());
- }
-
- status_t setBootDisplayMode(const sp<IBinder>& display,
- ui::DisplayModeId displayModeId) override {
- Parcel data, reply;
- status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (result != NO_ERROR) {
- ALOGE("setBootDisplayMode failed to writeInterfaceToken: %d", result);
- return result;
- }
- result = data.writeStrongBinder(display);
- if (result != NO_ERROR) {
- ALOGE("setBootDisplayMode failed to writeStrongBinder: %d", result);
- return result;
- }
- result = data.writeInt32(displayModeId);
- if (result != NO_ERROR) {
- ALOGE("setBootDisplayMode failed to writeIint32: %d", result);
- return result;
- }
- result = remote()->transact(BnSurfaceComposer::SET_BOOT_DISPLAY_MODE, data, &reply);
- if (result != NO_ERROR) {
- ALOGE("setBootDisplayMode failed to transact: %d", result);
- }
- return result;
- }
-
- status_t clearAnimationFrameStats() override {
- Parcel data, reply;
- status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (result != NO_ERROR) {
- ALOGE("clearAnimationFrameStats failed to writeInterfaceToken: %d", result);
- return result;
- }
- result = remote()->transact(BnSurfaceComposer::CLEAR_ANIMATION_FRAME_STATS, data, &reply);
- if (result != NO_ERROR) {
- ALOGE("clearAnimationFrameStats failed to transact: %d", result);
- return result;
- }
- return reply.readInt32();
- }
-
- status_t getAnimationFrameStats(FrameStats* outStats) const override {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- remote()->transact(BnSurfaceComposer::GET_ANIMATION_FRAME_STATS, data, &reply);
- reply.read(*outStats);
- return reply.readInt32();
- }
-
- virtual status_t overrideHdrTypes(const sp<IBinder>& display,
- const std::vector<ui::Hdr>& hdrTypes) {
- Parcel data, reply;
- SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor());
- SAFE_PARCEL(data.writeStrongBinder, display);
-
- std::vector<int32_t> hdrTypesVector;
- for (ui::Hdr i : hdrTypes) {
- hdrTypesVector.push_back(static_cast<int32_t>(i));
- }
- SAFE_PARCEL(data.writeInt32Vector, hdrTypesVector);
-
- status_t result = remote()->transact(BnSurfaceComposer::OVERRIDE_HDR_TYPES, data, &reply);
- if (result != NO_ERROR) {
- ALOGE("overrideHdrTypes failed to transact: %d", result);
- return result;
- }
- return result;
- }
-
- status_t onPullAtom(const int32_t atomId, std::string* pulledData, bool* success) {
- Parcel data, reply;
- SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor());
- SAFE_PARCEL(data.writeInt32, atomId);
-
- status_t err = remote()->transact(BnSurfaceComposer::ON_PULL_ATOM, data, &reply);
- if (err != NO_ERROR) {
- ALOGE("onPullAtom failed to transact: %d", err);
- return err;
- }
-
- int32_t size = 0;
- SAFE_PARCEL(reply.readInt32, &size);
- const void* dataPtr = reply.readInplace(size);
- if (dataPtr == nullptr) {
- return UNEXPECTED_NULL;
- }
- pulledData->assign((const char*)dataPtr, size);
- SAFE_PARCEL(reply.readBool, success);
- return NO_ERROR;
- }
-
- status_t enableVSyncInjections(bool enable) override {
- Parcel data, reply;
- status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (result != NO_ERROR) {
- ALOGE("enableVSyncInjections failed to writeInterfaceToken: %d", result);
- return result;
- }
- result = data.writeBool(enable);
- if (result != NO_ERROR) {
- ALOGE("enableVSyncInjections failed to writeBool: %d", result);
- return result;
- }
- result = remote()->transact(BnSurfaceComposer::ENABLE_VSYNC_INJECTIONS, data, &reply,
- IBinder::FLAG_ONEWAY);
- if (result != NO_ERROR) {
- ALOGE("enableVSyncInjections failed to transact: %d", result);
- return result;
- }
- return result;
- }
-
- status_t injectVSync(nsecs_t when) override {
- Parcel data, reply;
- status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (result != NO_ERROR) {
- ALOGE("injectVSync failed to writeInterfaceToken: %d", result);
- return result;
- }
- result = data.writeInt64(when);
- if (result != NO_ERROR) {
- ALOGE("injectVSync failed to writeInt64: %d", result);
- return result;
- }
- result = remote()->transact(BnSurfaceComposer::INJECT_VSYNC, data, &reply,
- IBinder::FLAG_ONEWAY);
- if (result != NO_ERROR) {
- ALOGE("injectVSync failed to transact: %d", result);
- return result;
- }
- return result;
- }
-
- status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) override {
- if (!outLayers) {
- return UNEXPECTED_NULL;
- }
-
- Parcel data, reply;
-
- status_t err = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (err != NO_ERROR) {
- return err;
- }
-
- err = remote()->transact(BnSurfaceComposer::GET_LAYER_DEBUG_INFO, data, &reply);
- if (err != NO_ERROR) {
- return err;
- }
-
- int32_t result = 0;
- err = reply.readInt32(&result);
- if (err != NO_ERROR) {
- return err;
- }
- if (result != NO_ERROR) {
- return result;
- }
-
- outLayers->clear();
- return reply.readParcelableVector(outLayers);
- }
-
- status_t getCompositionPreference(ui::Dataspace* defaultDataspace,
- ui::PixelFormat* defaultPixelFormat,
- ui::Dataspace* wideColorGamutDataspace,
- ui::PixelFormat* wideColorGamutPixelFormat) const override {
- Parcel data, reply;
- status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (error != NO_ERROR) {
- return error;
- }
- error = remote()->transact(BnSurfaceComposer::GET_COMPOSITION_PREFERENCE, data, &reply);
- if (error != NO_ERROR) {
- return error;
- }
- error = static_cast<status_t>(reply.readInt32());
- if (error == NO_ERROR) {
- *defaultDataspace = static_cast<ui::Dataspace>(reply.readInt32());
- *defaultPixelFormat = static_cast<ui::PixelFormat>(reply.readInt32());
- *wideColorGamutDataspace = static_cast<ui::Dataspace>(reply.readInt32());
- *wideColorGamutPixelFormat = static_cast<ui::PixelFormat>(reply.readInt32());
- }
- return error;
- }
-
- status_t getColorManagement(bool* outGetColorManagement) const override {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- remote()->transact(BnSurfaceComposer::GET_COLOR_MANAGEMENT, data, &reply);
- bool result;
- status_t err = reply.readBool(&result);
- if (err == NO_ERROR) {
- *outGetColorManagement = result;
- }
- return err;
- }
-
- status_t getDisplayedContentSamplingAttributes(const sp<IBinder>& display,
- ui::PixelFormat* outFormat,
- ui::Dataspace* outDataspace,
- uint8_t* outComponentMask) const override {
- if (!outFormat || !outDataspace || !outComponentMask) return BAD_VALUE;
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- data.writeStrongBinder(display);
-
- status_t error =
- remote()->transact(BnSurfaceComposer::GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES,
- data, &reply);
- if (error != NO_ERROR) {
- return error;
- }
-
- uint32_t value = 0;
- error = reply.readUint32(&value);
- if (error != NO_ERROR) {
- return error;
- }
- *outFormat = static_cast<ui::PixelFormat>(value);
-
- error = reply.readUint32(&value);
- if (error != NO_ERROR) {
- return error;
- }
- *outDataspace = static_cast<ui::Dataspace>(value);
-
- error = reply.readUint32(&value);
- if (error != NO_ERROR) {
- return error;
- }
- *outComponentMask = static_cast<uint8_t>(value);
- return error;
- }
-
- status_t setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
- uint8_t componentMask, uint64_t maxFrames) override {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- data.writeStrongBinder(display);
- data.writeBool(enable);
- data.writeByte(static_cast<int8_t>(componentMask));
- data.writeUint64(maxFrames);
- status_t result =
- remote()->transact(BnSurfaceComposer::SET_DISPLAY_CONTENT_SAMPLING_ENABLED, data,
- &reply);
- return result;
- }
-
- status_t getDisplayedContentSample(const sp<IBinder>& display, uint64_t maxFrames,
- uint64_t timestamp,
- DisplayedFrameStats* outStats) const override {
- if (!outStats) return BAD_VALUE;
-
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- data.writeStrongBinder(display);
- data.writeUint64(maxFrames);
- data.writeUint64(timestamp);
-
- status_t result =
- remote()->transact(BnSurfaceComposer::GET_DISPLAYED_CONTENT_SAMPLE, data, &reply);
-
- if (result != NO_ERROR) {
- return result;
- }
-
- result = reply.readUint64(&outStats->numFrames);
- if (result != NO_ERROR) {
- return result;
- }
-
- result = reply.readUint64Vector(&outStats->component_0_sample);
- if (result != NO_ERROR) {
- return result;
- }
- result = reply.readUint64Vector(&outStats->component_1_sample);
- if (result != NO_ERROR) {
- return result;
- }
- result = reply.readUint64Vector(&outStats->component_2_sample);
- if (result != NO_ERROR) {
- return result;
- }
- result = reply.readUint64Vector(&outStats->component_3_sample);
- return result;
- }
-
- status_t getProtectedContentSupport(bool* outSupported) const override {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- status_t error =
- remote()->transact(BnSurfaceComposer::GET_PROTECTED_CONTENT_SUPPORT, data, &reply);
- if (error != NO_ERROR) {
- return error;
- }
- error = reply.readBool(outSupported);
- return error;
- }
-
- status_t addRegionSamplingListener(const Rect& samplingArea, const sp<IBinder>& stopLayerHandle,
- const sp<IRegionSamplingListener>& listener) override {
- Parcel data, reply;
- status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (error != NO_ERROR) {
- ALOGE("addRegionSamplingListener: Failed to write interface token");
- return error;
- }
- error = data.write(samplingArea);
- if (error != NO_ERROR) {
- ALOGE("addRegionSamplingListener: Failed to write sampling area");
- return error;
- }
- error = data.writeStrongBinder(stopLayerHandle);
- if (error != NO_ERROR) {
- ALOGE("addRegionSamplingListener: Failed to write stop layer handle");
- return error;
- }
- error = data.writeStrongBinder(IInterface::asBinder(listener));
- if (error != NO_ERROR) {
- ALOGE("addRegionSamplingListener: Failed to write listener");
- return error;
- }
- error = remote()->transact(BnSurfaceComposer::ADD_REGION_SAMPLING_LISTENER, data, &reply);
- if (error != NO_ERROR) {
- ALOGE("addRegionSamplingListener: Failed to transact");
- }
- return error;
- }
-
- status_t removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener) override {
- Parcel data, reply;
- status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (error != NO_ERROR) {
- ALOGE("removeRegionSamplingListener: Failed to write interface token");
- return error;
- }
- error = data.writeStrongBinder(IInterface::asBinder(listener));
- if (error != NO_ERROR) {
- ALOGE("removeRegionSamplingListener: Failed to write listener");
- return error;
- }
- error = remote()->transact(BnSurfaceComposer::REMOVE_REGION_SAMPLING_LISTENER, data,
- &reply);
- if (error != NO_ERROR) {
- ALOGE("removeRegionSamplingListener: Failed to transact");
- }
- return error;
- }
-
- virtual status_t addFpsListener(int32_t taskId, const sp<gui::IFpsListener>& listener) {
- Parcel data, reply;
- SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor());
- SAFE_PARCEL(data.writeInt32, taskId);
- SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(listener));
- const status_t error =
- remote()->transact(BnSurfaceComposer::ADD_FPS_LISTENER, data, &reply);
- if (error != OK) {
- ALOGE("addFpsListener: Failed to transact");
- }
- return error;
- }
-
- virtual status_t removeFpsListener(const sp<gui::IFpsListener>& listener) {
- Parcel data, reply;
- SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor());
- SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(listener));
-
- const status_t error =
- remote()->transact(BnSurfaceComposer::REMOVE_FPS_LISTENER, data, &reply);
- if (error != OK) {
- ALOGE("removeFpsListener: Failed to transact");
- }
- return error;
- }
-
- virtual status_t addTunnelModeEnabledListener(
- const sp<gui::ITunnelModeEnabledListener>& listener) {
- Parcel data, reply;
- SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor());
- SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(listener));
-
- const status_t error =
- remote()->transact(BnSurfaceComposer::ADD_TUNNEL_MODE_ENABLED_LISTENER, data,
- &reply);
- if (error != NO_ERROR) {
- ALOGE("addTunnelModeEnabledListener: Failed to transact");
- }
- return error;
- }
-
- virtual status_t removeTunnelModeEnabledListener(
- const sp<gui::ITunnelModeEnabledListener>& listener) {
- Parcel data, reply;
- SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor());
- SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(listener));
-
- const status_t error =
- remote()->transact(BnSurfaceComposer::REMOVE_TUNNEL_MODE_ENABLED_LISTENER, data,
- &reply);
- if (error != NO_ERROR) {
- ALOGE("removeTunnelModeEnabledListener: Failed to transact");
- }
- return error;
- }
-
- status_t setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken,
- ui::DisplayModeId defaultMode, bool allowGroupSwitching,
- float primaryRefreshRateMin, float primaryRefreshRateMax,
- float appRequestRefreshRateMin,
- float appRequestRefreshRateMax) override {
- Parcel data, reply;
- status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayModeSpecs: failed to writeInterfaceToken: %d", result);
- return result;
- }
- result = data.writeStrongBinder(displayToken);
- if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayModeSpecs: failed to write display token: %d", result);
- return result;
- }
- result = data.writeInt32(defaultMode);
- if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayModeSpecs failed to write defaultMode: %d", result);
- return result;
- }
- result = data.writeBool(allowGroupSwitching);
- if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayModeSpecs failed to write allowGroupSwitching: %d", result);
- return result;
- }
- result = data.writeFloat(primaryRefreshRateMin);
- if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayModeSpecs failed to write primaryRefreshRateMin: %d", result);
- return result;
- }
- result = data.writeFloat(primaryRefreshRateMax);
- if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayModeSpecs failed to write primaryRefreshRateMax: %d", result);
- return result;
- }
- result = data.writeFloat(appRequestRefreshRateMin);
- if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayModeSpecs failed to write appRequestRefreshRateMin: %d",
- result);
- return result;
- }
- result = data.writeFloat(appRequestRefreshRateMax);
- if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayModeSpecs failed to write appRequestRefreshRateMax: %d",
- result);
- return result;
- }
-
- result =
- remote()->transact(BnSurfaceComposer::SET_DESIRED_DISPLAY_MODE_SPECS, data, &reply);
- if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayModeSpecs failed to transact: %d", result);
- return result;
- }
- return reply.readInt32();
- }
-
- status_t getDesiredDisplayModeSpecs(const sp<IBinder>& displayToken,
- ui::DisplayModeId* outDefaultMode,
- bool* outAllowGroupSwitching,
- float* outPrimaryRefreshRateMin,
- float* outPrimaryRefreshRateMax,
- float* outAppRequestRefreshRateMin,
- float* outAppRequestRefreshRateMax) override {
- if (!outDefaultMode || !outAllowGroupSwitching || !outPrimaryRefreshRateMin ||
- !outPrimaryRefreshRateMax || !outAppRequestRefreshRateMin ||
- !outAppRequestRefreshRateMax) {
- return BAD_VALUE;
- }
- Parcel data, reply;
- status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayModeSpecs failed to writeInterfaceToken: %d", result);
- return result;
- }
- result = data.writeStrongBinder(displayToken);
- if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayModeSpecs failed to writeStrongBinder: %d", result);
- return result;
- }
- result =
- remote()->transact(BnSurfaceComposer::GET_DESIRED_DISPLAY_MODE_SPECS, data, &reply);
- if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayModeSpecs failed to transact: %d", result);
- return result;
- }
-
- result = reply.readInt32(outDefaultMode);
- if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayModeSpecs failed to read defaultMode: %d", result);
- return result;
- }
- if (*outDefaultMode < 0) {
- ALOGE("%s: defaultMode must be non-negative but it was %d", __func__, *outDefaultMode);
- return BAD_VALUE;
- }
-
- result = reply.readBool(outAllowGroupSwitching);
- if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayModeSpecs failed to read allowGroupSwitching: %d", result);
- return result;
- }
- result = reply.readFloat(outPrimaryRefreshRateMin);
- if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayModeSpecs failed to read primaryRefreshRateMin: %d", result);
- return result;
- }
- result = reply.readFloat(outPrimaryRefreshRateMax);
- if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayModeSpecs failed to read primaryRefreshRateMax: %d", result);
- return result;
- }
- result = reply.readFloat(outAppRequestRefreshRateMin);
- if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayModeSpecs failed to read appRequestRefreshRateMin: %d", result);
- return result;
- }
- result = reply.readFloat(outAppRequestRefreshRateMax);
- if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayModeSpecs failed to read appRequestRefreshRateMax: %d", result);
- return result;
- }
- return reply.readInt32();
- }
-
- status_t setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor,
- float lightPosY, float lightPosZ, float lightRadius) override {
- Parcel data, reply;
- status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (error != NO_ERROR) {
- ALOGE("setGlobalShadowSettings: failed to write interface token: %d", error);
- return error;
- }
-
- std::vector<float> shadowConfig = {ambientColor.r, ambientColor.g, ambientColor.b,
- ambientColor.a, spotColor.r, spotColor.g,
- spotColor.b, spotColor.a, lightPosY,
- lightPosZ, lightRadius};
-
- error = data.writeFloatVector(shadowConfig);
- if (error != NO_ERROR) {
- ALOGE("setGlobalShadowSettings: failed to write shadowConfig: %d", error);
- return error;
- }
-
- error = remote()->transact(BnSurfaceComposer::SET_GLOBAL_SHADOW_SETTINGS, data, &reply,
- IBinder::FLAG_ONEWAY);
- if (error != NO_ERROR) {
- ALOGE("setGlobalShadowSettings: failed to transact: %d", error);
- return error;
- }
- return NO_ERROR;
- }
-
- status_t getDisplayDecorationSupport(
- const sp<IBinder>& displayToken,
- std::optional<common::DisplayDecorationSupport>* outSupport) const override {
- Parcel data, reply;
- status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (error != NO_ERROR) {
- ALOGE("getDisplayDecorationSupport: failed to write interface token: %d", error);
- return error;
- }
- error = data.writeStrongBinder(displayToken);
- if (error != NO_ERROR) {
- ALOGE("getDisplayDecorationSupport: failed to write display token: %d", error);
- return error;
- }
- error = remote()->transact(BnSurfaceComposer::GET_DISPLAY_DECORATION_SUPPORT, data, &reply);
- if (error != NO_ERROR) {
- ALOGE("getDisplayDecorationSupport: failed to transact: %d", error);
- return error;
- }
- bool support;
- error = reply.readBool(&support);
- if (error != NO_ERROR) {
- ALOGE("getDisplayDecorationSupport: failed to read support: %d", error);
- return error;
- }
-
- if (support) {
- int32_t format, alphaInterpretation;
- error = reply.readInt32(&format);
- if (error != NO_ERROR) {
- ALOGE("getDisplayDecorationSupport: failed to read format: %d", error);
- return error;
- }
- error = reply.readInt32(&alphaInterpretation);
- if (error != NO_ERROR) {
- ALOGE("getDisplayDecorationSupport: failed to read alphaInterpretation: %d", error);
- return error;
- }
- outSupport->emplace();
- outSupport->value().format = static_cast<common::PixelFormat>(format);
- outSupport->value().alphaInterpretation =
- static_cast<common::AlphaInterpretation>(alphaInterpretation);
- } else {
- outSupport->reset();
- }
- return NO_ERROR;
- }
-
- status_t setFrameRate(const sp<IGraphicBufferProducer>& surface, float frameRate,
- int8_t compatibility, int8_t changeFrameRateStrategy) override {
- Parcel data, reply;
- SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor());
- SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(surface));
- SAFE_PARCEL(data.writeFloat, frameRate);
- SAFE_PARCEL(data.writeByte, compatibility);
- SAFE_PARCEL(data.writeByte, changeFrameRateStrategy);
-
- status_t err = remote()->transact(BnSurfaceComposer::SET_FRAME_RATE, data, &reply);
- if (err != NO_ERROR) {
- ALOGE("setFrameRate: failed to transact: %s (%d)", strerror(-err), err);
- return err;
- }
-
- return reply.readInt32();
- }
-
- status_t setFrameTimelineInfo(const sp<IGraphicBufferProducer>& surface,
- const FrameTimelineInfo& frameTimelineInfo) override {
- Parcel data, reply;
- status_t err = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- if (err != NO_ERROR) {
- ALOGE("%s: failed writing interface token: %s (%d)", __func__, strerror(-err), -err);
- return err;
- }
-
- err = data.writeStrongBinder(IInterface::asBinder(surface));
- if (err != NO_ERROR) {
- ALOGE("%s: failed writing strong binder: %s (%d)", __func__, strerror(-err), -err);
- return err;
- }
-
- SAFE_PARCEL(frameTimelineInfo.write, data);
-
- err = remote()->transact(BnSurfaceComposer::SET_FRAME_TIMELINE_INFO, data, &reply);
- if (err != NO_ERROR) {
- ALOGE("%s: failed to transact: %s (%d)", __func__, strerror(-err), err);
- return err;
- }
-
- return reply.readInt32();
- }
-
- status_t addTransactionTraceListener(
- const sp<gui::ITransactionTraceListener>& listener) override {
- Parcel data, reply;
- SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor());
- SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(listener));
-
- return remote()->transact(BnSurfaceComposer::ADD_TRANSACTION_TRACE_LISTENER, data, &reply);
- }
-
- /**
- * Get priority of the RenderEngine in surface flinger.
- */
- int getGPUContextPriority() override {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- status_t err =
- remote()->transact(BnSurfaceComposer::GET_GPU_CONTEXT_PRIORITY, data, &reply);
- if (err != NO_ERROR) {
- ALOGE("getGPUContextPriority failed to read data: %s (%d)", strerror(-err), err);
- return 0;
- }
- return reply.readInt32();
- }
-
- status_t getMaxAcquiredBufferCount(int* buffers) const override {
- Parcel data, reply;
- data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- status_t err =
- remote()->transact(BnSurfaceComposer::GET_MAX_ACQUIRED_BUFFER_COUNT, data, &reply);
- if (err != NO_ERROR) {
- ALOGE("getMaxAcquiredBufferCount failed to read data: %s (%d)", strerror(-err), err);
- return err;
- }
-
- return reply.readInt32(buffers);
- }
-
- status_t addWindowInfosListener(
- const sp<IWindowInfosListener>& windowInfosListener) const override {
- Parcel data, reply;
- SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor());
- SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(windowInfosListener));
- return remote()->transact(BnSurfaceComposer::ADD_WINDOW_INFOS_LISTENER, data, &reply);
- }
-
- status_t removeWindowInfosListener(
- const sp<IWindowInfosListener>& windowInfosListener) const override {
- Parcel data, reply;
- SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor());
- SAFE_PARCEL(data.writeStrongBinder, IInterface::asBinder(windowInfosListener));
- return remote()->transact(BnSurfaceComposer::REMOVE_WINDOW_INFOS_LISTENER, data, &reply);
- }
-
- status_t setOverrideFrameRate(uid_t uid, float frameRate) override {
- Parcel data, reply;
- SAFE_PARCEL(data.writeInterfaceToken, ISurfaceComposer::getInterfaceDescriptor());
- SAFE_PARCEL(data.writeUint32, uid);
- SAFE_PARCEL(data.writeFloat, frameRate);
-
- status_t err = remote()->transact(BnSurfaceComposer::SET_OVERRIDE_FRAME_RATE, data, &reply);
- if (err != NO_ERROR) {
- ALOGE("setOverrideFrameRate: failed to transact %s (%d)", strerror(-err), err);
- return err;
- }
-
- return NO_ERROR;
- }
};
// Out-of-line virtual method definition to trigger vtable emission in this
@@ -1031,18 +121,12 @@
status_t BnSurfaceComposer::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
- switch(code) {
- case CREATE_CONNECTION: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> b = IInterface::asBinder(createConnection());
- reply->writeStrongBinder(b);
- return NO_ERROR;
- }
+ switch (code) {
case SET_TRANSACTION_STATE: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
FrameTimelineInfo frameTimelineInfo;
- SAFE_PARCEL(frameTimelineInfo.read, data);
+ frameTimelineInfo.readFromParcel(&data);
uint32_t count = 0;
SAFE_PARCEL_READ_SIZE(data.readUint32, &count, data.dataSize());
@@ -1102,642 +186,6 @@
uncachedBuffer, hasListenerCallbacks, listenerCallbacks,
transactionId);
}
- case BOOT_FINISHED: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- bootFinished();
- return NO_ERROR;
- }
- case AUTHENTICATE_SURFACE: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IGraphicBufferProducer> bufferProducer =
- interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
- int32_t result = authenticateSurfaceTexture(bufferProducer) ? 1 : 0;
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case GET_SUPPORTED_FRAME_TIMESTAMPS: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- std::vector<FrameEvent> supportedTimestamps;
- status_t result = getSupportedFrameTimestamps(&supportedTimestamps);
- status_t err = reply->writeInt32(result);
- if (err != NO_ERROR) {
- return err;
- }
- if (result != NO_ERROR) {
- return result;
- }
-
- std::vector<int32_t> supported;
- supported.reserve(supportedTimestamps.size());
- for (FrameEvent s : supportedTimestamps) {
- supported.push_back(static_cast<int32_t>(s));
- }
- return reply->writeInt32Vector(supported);
- }
- case CREATE_DISPLAY_EVENT_CONNECTION: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- auto vsyncSource = static_cast<ISurfaceComposer::VsyncSource>(data.readInt32());
- EventRegistrationFlags eventRegistration =
- static_cast<EventRegistration>(data.readUint32());
-
- sp<IDisplayEventConnection> connection(
- createDisplayEventConnection(vsyncSource, eventRegistration));
- reply->writeStrongBinder(IInterface::asBinder(connection));
- return NO_ERROR;
- }
- case GET_STATIC_DISPLAY_INFO: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- ui::StaticDisplayInfo info;
- const sp<IBinder> display = data.readStrongBinder();
- const status_t result = getStaticDisplayInfo(display, &info);
- SAFE_PARCEL(reply->writeInt32, result);
- if (result != NO_ERROR) return result;
- SAFE_PARCEL(reply->write, info);
- return NO_ERROR;
- }
- case GET_DYNAMIC_DISPLAY_INFO: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- ui::DynamicDisplayInfo info;
- const sp<IBinder> display = data.readStrongBinder();
- const status_t result = getDynamicDisplayInfo(display, &info);
- SAFE_PARCEL(reply->writeInt32, result);
- if (result != NO_ERROR) return result;
- SAFE_PARCEL(reply->write, info);
- return NO_ERROR;
- }
- case GET_DISPLAY_NATIVE_PRIMARIES: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- ui::DisplayPrimaries primaries;
- sp<IBinder> display = nullptr;
-
- status_t result = data.readStrongBinder(&display);
- if (result != NO_ERROR) {
- ALOGE("getDisplayNativePrimaries failed to readStrongBinder: %d", result);
- return result;
- }
-
- result = getDisplayNativePrimaries(display, primaries);
- reply->writeInt32(result);
- if (result == NO_ERROR) {
- memcpy(reply->writeInplace(sizeof(ui::DisplayPrimaries)), &primaries,
- sizeof(ui::DisplayPrimaries));
- }
-
- return NO_ERROR;
- }
- case SET_ACTIVE_COLOR_MODE: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> display = nullptr;
- status_t result = data.readStrongBinder(&display);
- if (result != NO_ERROR) {
- ALOGE("getActiveColorMode failed to readStrongBinder: %d", result);
- return result;
- }
- int32_t colorModeInt = 0;
- result = data.readInt32(&colorModeInt);
- if (result != NO_ERROR) {
- ALOGE("setActiveColorMode failed to readInt32: %d", result);
- return result;
- }
- result = setActiveColorMode(display,
- static_cast<ColorMode>(colorModeInt));
- result = reply->writeInt32(result);
- return result;
- }
- case SET_BOOT_DISPLAY_MODE: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> display = nullptr;
- status_t result = data.readStrongBinder(&display);
- if (result != NO_ERROR) {
- ALOGE("setBootDisplayMode failed to readStrongBinder: %d", result);
- return result;
- }
- ui::DisplayModeId displayModeId;
- result = data.readInt32(&displayModeId);
- if (result != NO_ERROR) {
- ALOGE("setBootDisplayMode failed to readInt32: %d", result);
- return result;
- }
- return setBootDisplayMode(display, displayModeId);
- }
- case CLEAR_ANIMATION_FRAME_STATS: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- status_t result = clearAnimationFrameStats();
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case GET_ANIMATION_FRAME_STATS: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- FrameStats stats;
- status_t result = getAnimationFrameStats(&stats);
- reply->write(stats);
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case ENABLE_VSYNC_INJECTIONS: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- bool enable = false;
- status_t result = data.readBool(&enable);
- if (result != NO_ERROR) {
- ALOGE("enableVSyncInjections failed to readBool: %d", result);
- return result;
- }
- return enableVSyncInjections(enable);
- }
- case INJECT_VSYNC: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- int64_t when = 0;
- status_t result = data.readInt64(&when);
- if (result != NO_ERROR) {
- ALOGE("enableVSyncInjections failed to readInt64: %d", result);
- return result;
- }
- return injectVSync(when);
- }
- case GET_LAYER_DEBUG_INFO: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- std::vector<LayerDebugInfo> outLayers;
- status_t result = getLayerDebugInfo(&outLayers);
- reply->writeInt32(result);
- if (result == NO_ERROR)
- {
- result = reply->writeParcelableVector(outLayers);
- }
- return result;
- }
- case GET_COMPOSITION_PREFERENCE: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- ui::Dataspace defaultDataspace;
- ui::PixelFormat defaultPixelFormat;
- ui::Dataspace wideColorGamutDataspace;
- ui::PixelFormat wideColorGamutPixelFormat;
- status_t error =
- getCompositionPreference(&defaultDataspace, &defaultPixelFormat,
- &wideColorGamutDataspace, &wideColorGamutPixelFormat);
- reply->writeInt32(error);
- if (error == NO_ERROR) {
- reply->writeInt32(static_cast<int32_t>(defaultDataspace));
- reply->writeInt32(static_cast<int32_t>(defaultPixelFormat));
- reply->writeInt32(static_cast<int32_t>(wideColorGamutDataspace));
- reply->writeInt32(static_cast<int32_t>(wideColorGamutPixelFormat));
- }
- return error;
- }
- case GET_COLOR_MANAGEMENT: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- bool result;
- status_t error = getColorManagement(&result);
- if (error == NO_ERROR) {
- reply->writeBool(result);
- }
- return error;
- }
- case GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
-
- sp<IBinder> display = data.readStrongBinder();
- ui::PixelFormat format;
- ui::Dataspace dataspace;
- uint8_t component = 0;
- auto result =
- getDisplayedContentSamplingAttributes(display, &format, &dataspace, &component);
- if (result == NO_ERROR) {
- reply->writeUint32(static_cast<uint32_t>(format));
- reply->writeUint32(static_cast<uint32_t>(dataspace));
- reply->writeUint32(static_cast<uint32_t>(component));
- }
- return result;
- }
- case SET_DISPLAY_CONTENT_SAMPLING_ENABLED: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
-
- sp<IBinder> display = nullptr;
- bool enable = false;
- int8_t componentMask = 0;
- uint64_t maxFrames = 0;
- status_t result = data.readStrongBinder(&display);
- if (result != NO_ERROR) {
- ALOGE("setDisplayContentSamplingEnabled failure in reading Display token: %d",
- result);
- return result;
- }
-
- result = data.readBool(&enable);
- if (result != NO_ERROR) {
- ALOGE("setDisplayContentSamplingEnabled failure in reading enable: %d", result);
- return result;
- }
-
- result = data.readByte(static_cast<int8_t*>(&componentMask));
- if (result != NO_ERROR) {
- ALOGE("setDisplayContentSamplingEnabled failure in reading component mask: %d",
- result);
- return result;
- }
-
- result = data.readUint64(&maxFrames);
- if (result != NO_ERROR) {
- ALOGE("setDisplayContentSamplingEnabled failure in reading max frames: %d", result);
- return result;
- }
-
- return setDisplayContentSamplingEnabled(display, enable,
- static_cast<uint8_t>(componentMask), maxFrames);
- }
- case GET_DISPLAYED_CONTENT_SAMPLE: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
-
- sp<IBinder> display = data.readStrongBinder();
- uint64_t maxFrames = 0;
- uint64_t timestamp = 0;
-
- status_t result = data.readUint64(&maxFrames);
- if (result != NO_ERROR) {
- ALOGE("getDisplayedContentSample failure in reading max frames: %d", result);
- return result;
- }
-
- result = data.readUint64(×tamp);
- if (result != NO_ERROR) {
- ALOGE("getDisplayedContentSample failure in reading timestamp: %d", result);
- return result;
- }
-
- DisplayedFrameStats stats;
- result = getDisplayedContentSample(display, maxFrames, timestamp, &stats);
- if (result == NO_ERROR) {
- reply->writeUint64(stats.numFrames);
- reply->writeUint64Vector(stats.component_0_sample);
- reply->writeUint64Vector(stats.component_1_sample);
- reply->writeUint64Vector(stats.component_2_sample);
- reply->writeUint64Vector(stats.component_3_sample);
- }
- return result;
- }
- case GET_PROTECTED_CONTENT_SUPPORT: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- bool result;
- status_t error = getProtectedContentSupport(&result);
- if (error == NO_ERROR) {
- reply->writeBool(result);
- }
- return error;
- }
- case ADD_REGION_SAMPLING_LISTENER: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- Rect samplingArea;
- status_t result = data.read(samplingArea);
- if (result != NO_ERROR) {
- ALOGE("addRegionSamplingListener: Failed to read sampling area");
- return result;
- }
- sp<IBinder> stopLayerHandle;
- result = data.readNullableStrongBinder(&stopLayerHandle);
- if (result != NO_ERROR) {
- ALOGE("addRegionSamplingListener: Failed to read stop layer handle");
- return result;
- }
- sp<IRegionSamplingListener> listener;
- result = data.readNullableStrongBinder(&listener);
- if (result != NO_ERROR) {
- ALOGE("addRegionSamplingListener: Failed to read listener");
- return result;
- }
- return addRegionSamplingListener(samplingArea, stopLayerHandle, listener);
- }
- case REMOVE_REGION_SAMPLING_LISTENER: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IRegionSamplingListener> listener;
- status_t result = data.readNullableStrongBinder(&listener);
- if (result != NO_ERROR) {
- ALOGE("removeRegionSamplingListener: Failed to read listener");
- return result;
- }
- return removeRegionSamplingListener(listener);
- }
- case ADD_FPS_LISTENER: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- int32_t taskId;
- status_t result = data.readInt32(&taskId);
- if (result != NO_ERROR) {
- ALOGE("addFpsListener: Failed to read layer handle");
- return result;
- }
- sp<gui::IFpsListener> listener;
- result = data.readNullableStrongBinder(&listener);
- if (result != NO_ERROR) {
- ALOGE("addFpsListener: Failed to read listener");
- return result;
- }
- return addFpsListener(taskId, listener);
- }
- case REMOVE_FPS_LISTENER: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<gui::IFpsListener> listener;
- status_t result = data.readNullableStrongBinder(&listener);
- if (result != NO_ERROR) {
- ALOGE("removeFpsListener: Failed to read listener");
- return result;
- }
- return removeFpsListener(listener);
- }
- case ADD_TUNNEL_MODE_ENABLED_LISTENER: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<gui::ITunnelModeEnabledListener> listener;
- status_t result = data.readNullableStrongBinder(&listener);
- if (result != NO_ERROR) {
- ALOGE("addTunnelModeEnabledListener: Failed to read listener");
- return result;
- }
- return addTunnelModeEnabledListener(listener);
- }
- case REMOVE_TUNNEL_MODE_ENABLED_LISTENER: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<gui::ITunnelModeEnabledListener> listener;
- status_t result = data.readNullableStrongBinder(&listener);
- if (result != NO_ERROR) {
- ALOGE("removeTunnelModeEnabledListener: Failed to read listener");
- return result;
- }
- return removeTunnelModeEnabledListener(listener);
- }
- case SET_DESIRED_DISPLAY_MODE_SPECS: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> displayToken = data.readStrongBinder();
- ui::DisplayModeId defaultMode;
- status_t result = data.readInt32(&defaultMode);
- if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayModeSpecs: failed to read defaultMode: %d", result);
- return result;
- }
- if (defaultMode < 0) {
- ALOGE("%s: defaultMode must be non-negative but it was %d", __func__, defaultMode);
- return BAD_VALUE;
- }
- bool allowGroupSwitching;
- result = data.readBool(&allowGroupSwitching);
- if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayModeSpecs: failed to read allowGroupSwitching: %d", result);
- return result;
- }
- float primaryRefreshRateMin;
- result = data.readFloat(&primaryRefreshRateMin);
- if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayModeSpecs: failed to read primaryRefreshRateMin: %d",
- result);
- return result;
- }
- float primaryRefreshRateMax;
- result = data.readFloat(&primaryRefreshRateMax);
- if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayModeSpecs: failed to read primaryRefreshRateMax: %d",
- result);
- return result;
- }
- float appRequestRefreshRateMin;
- result = data.readFloat(&appRequestRefreshRateMin);
- if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayModeSpecs: failed to read appRequestRefreshRateMin: %d",
- result);
- return result;
- }
- float appRequestRefreshRateMax;
- result = data.readFloat(&appRequestRefreshRateMax);
- if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayModeSpecs: failed to read appRequestRefreshRateMax: %d",
- result);
- return result;
- }
- result = setDesiredDisplayModeSpecs(displayToken, defaultMode, allowGroupSwitching,
- primaryRefreshRateMin, primaryRefreshRateMax,
- appRequestRefreshRateMin, appRequestRefreshRateMax);
- if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayModeSpecs: failed to call setDesiredDisplayModeSpecs: "
- "%d",
- result);
- return result;
- }
- reply->writeInt32(result);
- return result;
- }
- case GET_DESIRED_DISPLAY_MODE_SPECS: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> displayToken = data.readStrongBinder();
- ui::DisplayModeId defaultMode;
- bool allowGroupSwitching;
- float primaryRefreshRateMin;
- float primaryRefreshRateMax;
- float appRequestRefreshRateMin;
- float appRequestRefreshRateMax;
-
- status_t result =
- getDesiredDisplayModeSpecs(displayToken, &defaultMode, &allowGroupSwitching,
- &primaryRefreshRateMin, &primaryRefreshRateMax,
- &appRequestRefreshRateMin,
- &appRequestRefreshRateMax);
- if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayModeSpecs: failed to get getDesiredDisplayModeSpecs: "
- "%d",
- result);
- return result;
- }
-
- result = reply->writeInt32(defaultMode);
- if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayModeSpecs: failed to write defaultMode: %d", result);
- return result;
- }
- result = reply->writeBool(allowGroupSwitching);
- if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayModeSpecs: failed to write allowGroupSwitching: %d",
- result);
- return result;
- }
- result = reply->writeFloat(primaryRefreshRateMin);
- if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayModeSpecs: failed to write primaryRefreshRateMin: %d",
- result);
- return result;
- }
- result = reply->writeFloat(primaryRefreshRateMax);
- if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayModeSpecs: failed to write primaryRefreshRateMax: %d",
- result);
- return result;
- }
- result = reply->writeFloat(appRequestRefreshRateMin);
- if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayModeSpecs: failed to write appRequestRefreshRateMin: %d",
- result);
- return result;
- }
- result = reply->writeFloat(appRequestRefreshRateMax);
- if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayModeSpecs: failed to write appRequestRefreshRateMax: %d",
- result);
- return result;
- }
- reply->writeInt32(result);
- return result;
- }
- case SET_GLOBAL_SHADOW_SETTINGS: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
-
- std::vector<float> shadowConfig;
- status_t error = data.readFloatVector(&shadowConfig);
- if (error != NO_ERROR || shadowConfig.size() != 11) {
- ALOGE("setGlobalShadowSettings: failed to read shadowConfig: %d", error);
- return error;
- }
-
- half4 ambientColor = {shadowConfig[0], shadowConfig[1], shadowConfig[2],
- shadowConfig[3]};
- half4 spotColor = {shadowConfig[4], shadowConfig[5], shadowConfig[6], shadowConfig[7]};
- float lightPosY = shadowConfig[8];
- float lightPosZ = shadowConfig[9];
- float lightRadius = shadowConfig[10];
- return setGlobalShadowSettings(ambientColor, spotColor, lightPosY, lightPosZ,
- lightRadius);
- }
- case GET_DISPLAY_DECORATION_SUPPORT: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> displayToken;
- SAFE_PARCEL(data.readNullableStrongBinder, &displayToken);
- std::optional<common::DisplayDecorationSupport> support;
- auto error = getDisplayDecorationSupport(displayToken, &support);
- if (error != NO_ERROR) {
- ALOGE("getDisplayDecorationSupport failed with error %d", error);
- return error;
- }
- reply->writeBool(support.has_value());
- if (support) {
- reply->writeInt32(static_cast<int32_t>(support.value().format));
- reply->writeInt32(static_cast<int32_t>(support.value().alphaInterpretation));
- }
- return error;
- }
- case SET_FRAME_RATE: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> binder;
- SAFE_PARCEL(data.readStrongBinder, &binder);
-
- sp<IGraphicBufferProducer> surface = interface_cast<IGraphicBufferProducer>(binder);
- if (!surface) {
- ALOGE("setFrameRate: failed to cast to IGraphicBufferProducer");
- return BAD_VALUE;
- }
- float frameRate;
- SAFE_PARCEL(data.readFloat, &frameRate);
-
- int8_t compatibility;
- SAFE_PARCEL(data.readByte, &compatibility);
-
- int8_t changeFrameRateStrategy;
- SAFE_PARCEL(data.readByte, &changeFrameRateStrategy);
-
- status_t result =
- setFrameRate(surface, frameRate, compatibility, changeFrameRateStrategy);
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case SET_FRAME_TIMELINE_INFO: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> binder;
- status_t err = data.readStrongBinder(&binder);
- if (err != NO_ERROR) {
- ALOGE("setFrameTimelineInfo: failed to read strong binder: %s (%d)", strerror(-err),
- -err);
- return err;
- }
- sp<IGraphicBufferProducer> surface = interface_cast<IGraphicBufferProducer>(binder);
- if (!surface) {
- ALOGE("setFrameTimelineInfo: failed to cast to IGraphicBufferProducer: %s (%d)",
- strerror(-err), -err);
- return err;
- }
-
- FrameTimelineInfo frameTimelineInfo;
- SAFE_PARCEL(frameTimelineInfo.read, data);
-
- status_t result = setFrameTimelineInfo(surface, frameTimelineInfo);
- reply->writeInt32(result);
- return NO_ERROR;
- }
- case ADD_TRANSACTION_TRACE_LISTENER: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<gui::ITransactionTraceListener> listener;
- SAFE_PARCEL(data.readStrongBinder, &listener);
-
- return addTransactionTraceListener(listener);
- }
- case GET_GPU_CONTEXT_PRIORITY: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- int priority = getGPUContextPriority();
- SAFE_PARCEL(reply->writeInt32, priority);
- return NO_ERROR;
- }
- case GET_MAX_ACQUIRED_BUFFER_COUNT: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- int buffers = 0;
- int err = getMaxAcquiredBufferCount(&buffers);
- if (err != NO_ERROR) {
- return err;
- }
- SAFE_PARCEL(reply->writeInt32, buffers);
- return NO_ERROR;
- }
- case OVERRIDE_HDR_TYPES: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IBinder> display = nullptr;
- SAFE_PARCEL(data.readStrongBinder, &display);
-
- std::vector<int32_t> hdrTypes;
- SAFE_PARCEL(data.readInt32Vector, &hdrTypes);
-
- std::vector<ui::Hdr> hdrTypesVector;
- for (int i : hdrTypes) {
- hdrTypesVector.push_back(static_cast<ui::Hdr>(i));
- }
- return overrideHdrTypes(display, hdrTypesVector);
- }
- case ON_PULL_ATOM: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- int32_t atomId = 0;
- SAFE_PARCEL(data.readInt32, &atomId);
-
- std::string pulledData;
- bool success;
- status_t err = onPullAtom(atomId, &pulledData, &success);
- SAFE_PARCEL(reply->writeByteArray, pulledData.size(),
- reinterpret_cast<const uint8_t*>(pulledData.data()));
- SAFE_PARCEL(reply->writeBool, success);
- return err;
- }
- case ADD_WINDOW_INFOS_LISTENER: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IWindowInfosListener> listener;
- SAFE_PARCEL(data.readStrongBinder, &listener);
-
- return addWindowInfosListener(listener);
- }
- case REMOVE_WINDOW_INFOS_LISTENER: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
- sp<IWindowInfosListener> listener;
- SAFE_PARCEL(data.readStrongBinder, &listener);
-
- return removeWindowInfosListener(listener);
- }
- case SET_OVERRIDE_FRAME_RATE: {
- CHECK_INTERFACE(ISurfaceComposer, data, reply);
-
- uid_t uid;
- SAFE_PARCEL(data.readUint32, &uid);
-
- float frameRate;
- SAFE_PARCEL(data.readFloat, &frameRate);
-
- return setOverrideFrameRate(uid, frameRate);
- }
default: {
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp
deleted file mode 100644
index 5e7a7ec..0000000
--- a/libs/gui/ISurfaceComposerClient.cpp
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (C) 2007 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.
- */
-
-// tag as surfaceflinger
-#define LOG_TAG "SurfaceFlinger"
-
-#include <gui/ISurfaceComposerClient.h>
-
-#include <gui/IGraphicBufferProducer.h>
-
-#include <binder/SafeInterface.h>
-
-#include <ui/FrameStats.h>
-
-namespace android {
-
-namespace { // Anonymous
-
-enum class Tag : uint32_t {
- CREATE_SURFACE = IBinder::FIRST_CALL_TRANSACTION,
- CREATE_WITH_SURFACE_PARENT,
- CLEAR_LAYER_FRAME_STATS,
- GET_LAYER_FRAME_STATS,
- MIRROR_SURFACE,
- LAST = MIRROR_SURFACE,
-};
-
-} // Anonymous namespace
-
-class BpSurfaceComposerClient : public SafeBpInterface<ISurfaceComposerClient> {
-public:
- explicit BpSurfaceComposerClient(const sp<IBinder>& impl)
- : SafeBpInterface<ISurfaceComposerClient>(impl, "BpSurfaceComposerClient") {}
-
- ~BpSurfaceComposerClient() override;
-
- status_t createSurface(const String8& name, uint32_t width, uint32_t height, PixelFormat format,
- uint32_t flags, const sp<IBinder>& parent, LayerMetadata metadata,
- sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp,
- int32_t* outLayerId, uint32_t* outTransformHint) override {
- return callRemote<decltype(&ISurfaceComposerClient::createSurface)>(Tag::CREATE_SURFACE,
- name, width, height,
- format, flags, parent,
- std::move(metadata),
- handle, gbp, outLayerId,
- outTransformHint);
- }
-
- status_t createWithSurfaceParent(const String8& name, uint32_t width, uint32_t height,
- PixelFormat format, uint32_t flags,
- const sp<IGraphicBufferProducer>& parent,
- LayerMetadata metadata, sp<IBinder>* handle,
- sp<IGraphicBufferProducer>* gbp, int32_t* outLayerId,
- uint32_t* outTransformHint) override {
- return callRemote<decltype(
- &ISurfaceComposerClient::createWithSurfaceParent)>(Tag::CREATE_WITH_SURFACE_PARENT,
- name, width, height, format,
- flags, parent,
- std::move(metadata), handle, gbp,
- outLayerId, outTransformHint);
- }
-
- status_t clearLayerFrameStats(const sp<IBinder>& handle) const override {
- return callRemote<decltype(
- &ISurfaceComposerClient::clearLayerFrameStats)>(Tag::CLEAR_LAYER_FRAME_STATS,
- handle);
- }
-
- status_t getLayerFrameStats(const sp<IBinder>& handle, FrameStats* outStats) const override {
- return callRemote<decltype(
- &ISurfaceComposerClient::getLayerFrameStats)>(Tag::GET_LAYER_FRAME_STATS, handle,
- outStats);
- }
-
- status_t mirrorSurface(const sp<IBinder>& mirrorFromHandle, sp<IBinder>* outHandle,
- int32_t* outLayerId) override {
- return callRemote<decltype(&ISurfaceComposerClient::mirrorSurface)>(Tag::MIRROR_SURFACE,
- mirrorFromHandle,
- outHandle, outLayerId);
- }
-};
-
-// Out-of-line virtual method definition to trigger vtable emission in this
-// translation unit (see clang warning -Wweak-vtables)
-BpSurfaceComposerClient::~BpSurfaceComposerClient() {}
-
-IMPLEMENT_META_INTERFACE(SurfaceComposerClient, "android.ui.ISurfaceComposerClient");
-
-// ----------------------------------------------------------------------
-
-status_t BnSurfaceComposerClient::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
- uint32_t flags) {
- if (code < IBinder::FIRST_CALL_TRANSACTION || code > static_cast<uint32_t>(Tag::LAST)) {
- return BBinder::onTransact(code, data, reply, flags);
- }
- auto tag = static_cast<Tag>(code);
- switch (tag) {
- case Tag::CREATE_SURFACE:
- return callLocal(data, reply, &ISurfaceComposerClient::createSurface);
- case Tag::CREATE_WITH_SURFACE_PARENT:
- return callLocal(data, reply, &ISurfaceComposerClient::createWithSurfaceParent);
- case Tag::CLEAR_LAYER_FRAME_STATS:
- return callLocal(data, reply, &ISurfaceComposerClient::clearLayerFrameStats);
- case Tag::GET_LAYER_FRAME_STATS:
- return callLocal(data, reply, &ISurfaceComposerClient::getLayerFrameStats);
- case Tag::MIRROR_SURFACE:
- return callLocal(data, reply, &ISurfaceComposerClient::mirrorSurface);
- }
-}
-
-} // namespace android
diff --git a/libs/gui/LayerDebugInfo.cpp b/libs/gui/LayerDebugInfo.cpp
index ea5fb29..15b2221 100644
--- a/libs/gui/LayerDebugInfo.cpp
+++ b/libs/gui/LayerDebugInfo.cpp
@@ -27,7 +27,7 @@
#define RETURN_ON_ERROR(X) do {status_t res = (X); if (res != NO_ERROR) return res;} while(false)
-namespace android {
+namespace android::gui {
status_t LayerDebugInfo::writeToParcel(Parcel* parcel) const {
RETURN_ON_ERROR(parcel->writeCString(mName.c_str()));
@@ -149,4 +149,4 @@
return result;
}
-} // android
+} // namespace android::gui
diff --git a/libs/gui/LayerMetadata.cpp b/libs/gui/LayerMetadata.cpp
index 189d51a..4e12fd3 100644
--- a/libs/gui/LayerMetadata.cpp
+++ b/libs/gui/LayerMetadata.cpp
@@ -23,7 +23,7 @@
using android::base::StringPrintf;
-namespace android {
+namespace android::gui {
LayerMetadata::LayerMetadata() = default;
@@ -144,4 +144,4 @@
}
}
-} // namespace android
+} // namespace android::gui
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 502031c..bb66085 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -19,10 +19,10 @@
#include <cinttypes>
#include <cmath>
+#include <android/gui/ISurfaceComposerClient.h>
#include <android/native_window.h>
#include <binder/Parcel.h>
#include <gui/IGraphicBufferProducer.h>
-#include <gui/ISurfaceComposerClient.h>
#include <gui/LayerState.h>
#include <private/gui/ParcelUtils.h>
#include <system/window.h>
@@ -63,9 +63,11 @@
frameRate(0.0f),
frameRateCompatibility(ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT),
changeFrameRateStrategy(ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS),
+ defaultFrameRateCompatibility(ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT),
fixedTransformHint(ui::Transform::ROT_INVALID),
autoRefresh(false),
isTrustedOverlay(false),
+ borderEnabled(false),
bufferCrop(Rect::INVALID_RECT),
destinationFrame(Rect::INVALID_RECT),
dropInputMode(gui::DropInputMode::NONE) {
@@ -100,7 +102,12 @@
SAFE_PARCEL(output.write, transparentRegion);
SAFE_PARCEL(output.writeUint32, transform);
SAFE_PARCEL(output.writeBool, transformToDisplayInverse);
-
+ SAFE_PARCEL(output.writeBool, borderEnabled);
+ SAFE_PARCEL(output.writeFloat, borderWidth);
+ SAFE_PARCEL(output.writeFloat, borderColor.r);
+ SAFE_PARCEL(output.writeFloat, borderColor.g);
+ SAFE_PARCEL(output.writeFloat, borderColor.b);
+ SAFE_PARCEL(output.writeFloat, borderColor.a);
SAFE_PARCEL(output.writeUint32, static_cast<uint32_t>(dataspace));
SAFE_PARCEL(output.write, hdrMetadata);
SAFE_PARCEL(output.write, surfaceDamageRegion);
@@ -131,6 +138,7 @@
SAFE_PARCEL(output.writeFloat, frameRate);
SAFE_PARCEL(output.writeByte, frameRateCompatibility);
SAFE_PARCEL(output.writeByte, changeFrameRateStrategy);
+ SAFE_PARCEL(output.writeByte, defaultFrameRateCompatibility);
SAFE_PARCEL(output.writeUint32, fixedTransformHint);
SAFE_PARCEL(output.writeBool, autoRefresh);
SAFE_PARCEL(output.writeBool, dimmingEnabled);
@@ -200,6 +208,17 @@
SAFE_PARCEL(input.read, transparentRegion);
SAFE_PARCEL(input.readUint32, &transform);
SAFE_PARCEL(input.readBool, &transformToDisplayInverse);
+ SAFE_PARCEL(input.readBool, &borderEnabled);
+ SAFE_PARCEL(input.readFloat, &tmpFloat);
+ borderWidth = tmpFloat;
+ SAFE_PARCEL(input.readFloat, &tmpFloat);
+ borderColor.r = tmpFloat;
+ SAFE_PARCEL(input.readFloat, &tmpFloat);
+ borderColor.g = tmpFloat;
+ SAFE_PARCEL(input.readFloat, &tmpFloat);
+ borderColor.b = tmpFloat;
+ SAFE_PARCEL(input.readFloat, &tmpFloat);
+ borderColor.a = tmpFloat;
uint32_t tmpUint32 = 0;
SAFE_PARCEL(input.readUint32, &tmpUint32);
@@ -240,6 +259,7 @@
SAFE_PARCEL(input.readFloat, &frameRate);
SAFE_PARCEL(input.readByte, &frameRateCompatibility);
SAFE_PARCEL(input.readByte, &changeFrameRateStrategy);
+ SAFE_PARCEL(input.readByte, &defaultFrameRateCompatibility);
SAFE_PARCEL(input.readUint32, &tmpUint32);
fixedTransformHint = static_cast<ui::Transform::RotationFlags>(tmpUint32);
SAFE_PARCEL(input.readBool, &autoRefresh);
@@ -550,6 +570,16 @@
what |= eShadowRadiusChanged;
shadowRadius = other.shadowRadius;
}
+ if (other.what & eRenderBorderChanged) {
+ what |= eRenderBorderChanged;
+ borderEnabled = other.borderEnabled;
+ borderWidth = other.borderWidth;
+ borderColor = other.borderColor;
+ }
+ if (other.what & eDefaultFrameRateCompatibilityChanged) {
+ what |= eDefaultFrameRateCompatibilityChanged;
+ defaultFrameRateCompatibility = other.defaultFrameRateCompatibility;
+ }
if (other.what & eFrameRateSelectionPriority) {
what |= eFrameRateSelectionPriority;
frameRateSelectionPriority = other.frameRateSelectionPriority;
@@ -641,29 +671,44 @@
changes |= !other.focusRequests.empty();
focusRequests.insert(focusRequests.end(), std::make_move_iterator(other.focusRequests.begin()),
std::make_move_iterator(other.focusRequests.end()));
- changes |= other.syncInputWindows && !syncInputWindows;
- syncInputWindows |= other.syncInputWindows;
+ changes |= !other.windowInfosReportedListeners.empty();
+ windowInfosReportedListeners.insert(other.windowInfosReportedListeners.begin(),
+ other.windowInfosReportedListeners.end());
return changes;
}
bool InputWindowCommands::empty() const {
- return focusRequests.empty() && !syncInputWindows;
+ return focusRequests.empty() && windowInfosReportedListeners.empty();
}
void InputWindowCommands::clear() {
focusRequests.clear();
- syncInputWindows = false;
+ windowInfosReportedListeners.clear();
}
status_t InputWindowCommands::write(Parcel& output) const {
SAFE_PARCEL(output.writeParcelableVector, focusRequests);
- SAFE_PARCEL(output.writeBool, syncInputWindows);
+
+ SAFE_PARCEL(output.writeInt32, windowInfosReportedListeners.size());
+ for (const auto& listener : windowInfosReportedListeners) {
+ SAFE_PARCEL(output.writeStrongBinder, listener);
+ }
+
return NO_ERROR;
}
status_t InputWindowCommands::read(const Parcel& input) {
SAFE_PARCEL(input.readParcelableVector, &focusRequests);
- SAFE_PARCEL(input.readBool, &syncInputWindows);
+
+ int listenerSize = 0;
+ SAFE_PARCEL_READ_SIZE(input.readInt32, &listenerSize, input.dataSize());
+ windowInfosReportedListeners.reserve(listenerSize);
+ for (int i = 0; i < listenerSize; i++) {
+ sp<gui::IWindowInfosReportedListener> listener;
+ SAFE_PARCEL(input.readStrongBinder, &listener);
+ windowInfosReportedListeners.insert(listener);
+ }
+
return NO_ERROR;
}
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 54b6d6a..e8aac2f 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -39,6 +39,7 @@
#include <ui/GraphicBuffer.h>
#include <ui/Region.h>
+#include <gui/AidlStatusUtil.h>
#include <gui/BufferItem.h>
#include <gui/IProducerListener.h>
@@ -49,6 +50,7 @@
namespace android {
+using gui::aidl_utils::statusTFromBinderStatus;
using ui::Dataspace;
namespace {
@@ -182,7 +184,7 @@
gui::DisplayStatInfo stats;
binder::Status status = composerServiceAIDL()->getDisplayStats(nullptr, &stats);
if (!status.isOk()) {
- return status.transactionError();
+ return statusTFromBinderStatus(status);
}
*outRefreshDuration = stats.vsyncPeriod;
@@ -355,7 +357,7 @@
*supported = false;
binder::Status status = composerServiceAIDL()->isWideColorDisplay(display, supported);
- return status.transactionError();
+ return statusTFromBinderStatus(status);
}
status_t Surface::getHdrSupport(bool* supported) {
@@ -366,12 +368,13 @@
return NAME_NOT_FOUND;
}
- ui::DynamicDisplayInfo info;
- if (status_t err = composerService()->getDynamicDisplayInfo(display, &info); err != NO_ERROR) {
- return err;
+ gui::DynamicDisplayInfo info;
+ if (binder::Status status = composerServiceAIDL()->getDynamicDisplayInfo(display, &info);
+ !status.isOk()) {
+ return statusTFromBinderStatus(status);
}
- *supported = !info.hdrCapabilities.getSupportedHdrTypes().empty();
+ *supported = !info.hdrCapabilities.supportedHdrTypes.empty();
return NO_ERROR;
}
@@ -1256,10 +1259,10 @@
mQueriedSupportedTimestamps = true;
std::vector<FrameEvent> supportedFrameTimestamps;
- status_t err = composerService()->getSupportedFrameTimestamps(
- &supportedFrameTimestamps);
+ binder::Status status =
+ composerServiceAIDL()->getSupportedFrameTimestamps(&supportedFrameTimestamps);
- if (err != NO_ERROR) {
+ if (!status.isOk()) {
return;
}
@@ -1287,15 +1290,12 @@
if (err == NO_ERROR) {
return NO_ERROR;
}
- sp<ISurfaceComposer> surfaceComposer = composerService();
+ sp<gui::ISurfaceComposer> surfaceComposer = composerServiceAIDL();
if (surfaceComposer == nullptr) {
return -EPERM; // likely permissions error
}
- if (surfaceComposer->authenticateSurfaceTexture(mGraphicBufferProducer)) {
- *value = 1;
- } else {
- *value = 0;
- }
+ // ISurfaceComposer no longer supports authenticateSurfaceTexture
+ *value = 0;
return NO_ERROR;
}
case NATIVE_WINDOW_CONCRETE_TYPE:
@@ -1867,7 +1867,11 @@
auto startTimeNanos = static_cast<int64_t>(va_arg(args, int64_t));
ALOGV("Surface::%s", __func__);
- return setFrameTimelineInfo({frameTimelineVsyncId, inputEventId, startTimeNanos});
+ FrameTimelineInfo ftlInfo;
+ ftlInfo.vsyncId = frameTimelineVsyncId;
+ ftlInfo.inputEventId = inputEventId;
+ ftlInfo.startTimeNanos = startTimeNanos;
+ return setFrameTimelineInfo(ftlInfo);
}
bool Surface::transformToDisplayInverse() const {
@@ -2623,22 +2627,18 @@
mSurfaceListener->onBuffersDiscarded(discardedBufs);
}
-status_t Surface::setFrameRate(float frameRate, int8_t compatibility,
- int8_t changeFrameRateStrategy) {
- ATRACE_CALL();
- ALOGV("Surface::setFrameRate");
-
- if (!ValidateFrameRate(frameRate, compatibility, changeFrameRateStrategy,
- "Surface::setFrameRate")) {
- return BAD_VALUE;
- }
-
- return composerService()->setFrameRate(mGraphicBufferProducer, frameRate, compatibility,
- changeFrameRateStrategy);
+[[deprecated]] status_t Surface::setFrameRate(float /*frameRate*/, int8_t /*compatibility*/,
+ int8_t /*changeFrameRateStrategy*/) {
+ ALOGI("Surface::setFrameRate is deprecated, setFrameRate hint is dropped as destination is not "
+ "SurfaceFlinger");
+ // ISurfaceComposer no longer supports setFrameRate, we will return NO_ERROR when the api is
+ // called to avoid apps crashing, as BAD_VALUE can generate fatal exception in apps.
+ return NO_ERROR;
}
-status_t Surface::setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo) {
- return composerService()->setFrameTimelineInfo(mGraphicBufferProducer, frameTimelineInfo);
+status_t Surface::setFrameTimelineInfo(const FrameTimelineInfo& /*frameTimelineInfo*/) {
+ // ISurfaceComposer no longer supports setFrameTimelineInfo
+ return BAD_VALUE;
}
sp<IBinder> Surface::getSurfaceControlHandle() const {
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 9358e29..16dbc92 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -19,8 +19,11 @@
#include <stdint.h>
#include <sys/types.h>
+#include <android/gui/BnWindowInfosReportedListener.h>
#include <android/gui/DisplayState.h>
+#include <android/gui/ISurfaceComposerClient.h>
#include <android/gui/IWindowInfosListener.h>
+#include <android/os/IInputConstants.h>
#include <utils/Errors.h>
#include <utils/Log.h>
#include <utils/SortedVector.h>
@@ -33,11 +36,11 @@
#include <system/graphics.h>
+#include <gui/AidlStatusUtil.h>
#include <gui/BufferItemConsumer.h>
#include <gui/CpuConsumer.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/ISurfaceComposer.h>
-#include <gui/ISurfaceComposerClient.h>
#include <gui/LayerState.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
@@ -61,6 +64,7 @@
using gui::WindowInfo;
using gui::WindowInfoHandle;
using gui::WindowInfosListener;
+using gui::aidl_utils::statusTFromBinderStatus;
using ui::ColorMode;
// ---------------------------------------------------------------------------
@@ -111,7 +115,6 @@
if (instance.mComposerService == nullptr) {
if (ComposerService::getInstance().connectLocked()) {
ALOGD("ComposerService reconnected");
- WindowInfosListenerReporter::getInstance()->reconnect(instance.mComposerService);
}
}
return instance.mComposerService;
@@ -159,6 +162,7 @@
if (instance.mComposerService == nullptr) {
if (ComposerServiceAIDL::getInstance().connectLocked()) {
ALOGD("ComposerServiceAIDL reconnected");
+ WindowInfosListenerReporter::getInstance()->reconnect(instance.mComposerService);
}
}
return instance.mComposerService;
@@ -632,7 +636,8 @@
mDesiredPresentTime(other.mDesiredPresentTime),
mIsAutoTimestamp(other.mIsAutoTimestamp),
mFrameTimelineInfo(other.mFrameTimelineInfo),
- mApplyToken(other.mApplyToken) {
+ mApplyToken(other.mApplyToken),
+ mWindowInfosReportedEvent(other.mWindowInfosReportedEvent) {
mDisplayStates = other.mDisplayStates;
mComposerStates = other.mComposerStates;
mInputWindowCommands = other.mInputWindowCommands;
@@ -657,6 +662,7 @@
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();
@@ -666,7 +672,7 @@
const int64_t desiredPresentTime = parcel->readInt64();
const bool isAutoTimestamp = parcel->readBool();
FrameTimelineInfo frameTimelineInfo;
- SAFE_PARCEL(frameTimelineInfo.read, *parcel);
+ frameTimelineInfo.readFromParcel(parcel);
sp<IBinder> applyToken;
parcel->readNullableStrongBinder(&applyToken);
@@ -734,6 +740,7 @@
inputWindowCommands.read(*parcel);
// Parsing was successful. Update the object.
+ mId = transactionId;
mForceSynchronous = forceSynchronous;
mTransactionNestCount = transactionNestCount;
mAnimation = animation;
@@ -765,6 +772,7 @@
const_cast<SurfaceComposerClient::Transaction*>(this)->cacheBuffers();
+ parcel->writeUint64(mId);
parcel->writeUint32(mForceSynchronous);
parcel->writeUint32(mTransactionNestCount);
parcel->writeBool(mAnimation);
@@ -773,7 +781,7 @@
parcel->writeBool(mContainsBuffer);
parcel->writeInt64(mDesiredPresentTime);
parcel->writeBool(mIsAutoTimestamp);
- SAFE_PARCEL(mFrameTimelineInfo.write, *parcel);
+ mFrameTimelineInfo.writeToParcel(parcel);
parcel->writeStrongBinder(mApplyToken);
parcel->writeUint32(static_cast<uint32_t>(mDisplayStates.size()));
for (auto const& displayState : mDisplayStates) {
@@ -873,8 +881,11 @@
mEarlyWakeupStart = mEarlyWakeupStart || other.mEarlyWakeupStart;
mEarlyWakeupEnd = mEarlyWakeupEnd || other.mEarlyWakeupEnd;
mApplyToken = other.mApplyToken;
+ if (other.mWindowInfosReportedEvent) {
+ mWindowInfosReportedEvent = std::move(other.mWindowInfosReportedEvent);
+ }
- mFrameTimelineInfo.merge(other.mFrameTimelineInfo);
+ mergeFrameTimelineInfo(mFrameTimelineInfo, other.mFrameTimelineInfo);
other.clear();
return *this;
@@ -893,8 +904,9 @@
mEarlyWakeupEnd = false;
mDesiredPresentTime = 0;
mIsAutoTimestamp = true;
- mFrameTimelineInfo.clear();
+ clearFrameTimelineInfo(mFrameTimelineInfo);
mApplyToken = nullptr;
+ mWindowInfosReportedEvent = nullptr;
}
uint64_t SurfaceComposerClient::Transaction::getId() {
@@ -1041,6 +1053,10 @@
hasListenerCallbacks, listenerCallbacks, mId);
mId = generateId();
+ if (mWindowInfosReportedEvent && !mWindowInfosReportedEvent->wait()) {
+ ALOGE("Timed out waiting for window infos to be reported.");
+ }
+
// Clear the current states and flags
clear();
@@ -1085,7 +1101,7 @@
if (status.isOk()) {
*id = *DisplayId::fromValue<PhysicalDisplayId>(static_cast<uint64_t>(displayId));
}
- return status.transactionError();
+ return statusTFromBinderStatus(status);
}
std::optional<PhysicalDisplayId> SurfaceComposerClient::getInternalDisplayId() {
@@ -1727,8 +1743,25 @@
return *this;
}
+class NotifyWindowInfosReported : public gui::BnWindowInfosReportedListener {
+public:
+ NotifyWindowInfosReported(
+ std::shared_ptr<SurfaceComposerClient::Event> windowInfosReportedEvent)
+ : mWindowInfosReportedEvent(windowInfosReportedEvent) {}
+
+ binder::Status onWindowInfosReported() {
+ mWindowInfosReportedEvent->set();
+ return binder::Status::ok();
+ }
+
+private:
+ std::shared_ptr<SurfaceComposerClient::Event> mWindowInfosReportedEvent;
+};
+
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::syncInputWindows() {
- mInputWindowCommands.syncInputWindows = true;
+ mWindowInfosReportedEvent = std::make_shared<Event>();
+ mInputWindowCommands.windowInfosReportedListeners.insert(
+ sp<NotifyWindowInfosReported>::make(mWindowInfosReportedEvent));
return *this;
}
@@ -1835,6 +1868,19 @@
return *this;
}
+SurfaceComposerClient::Transaction&
+SurfaceComposerClient::Transaction::setDefaultFrameRateCompatibility(const sp<SurfaceControl>& sc,
+ int8_t compatibility) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
+ s->what |= layer_state_t::eDefaultFrameRateCompatibilityChanged;
+ s->defaultFrameRateCompatibility = compatibility;
+ return *this;
+}
+
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFixedTransformHint(
const sp<SurfaceControl>& sc, int32_t fixedTransformHint) {
layer_state_t* s = getLayerState(sc);
@@ -1853,7 +1899,7 @@
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameTimelineInfo(
const FrameTimelineInfo& frameTimelineInfo) {
- mFrameTimelineInfo.merge(frameTimelineInfo);
+ mergeFrameTimelineInfo(mFrameTimelineInfo, frameTimelineInfo);
return *this;
}
@@ -1947,6 +1993,23 @@
return *this;
}
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::enableBorder(
+ const sp<SurfaceControl>& sc, bool shouldEnable, float width, const half4& color) {
+ layer_state_t* s = getLayerState(sc);
+ if (!s) {
+ mStatus = BAD_INDEX;
+ return *this;
+ }
+
+ s->what |= layer_state_t::eRenderBorderChanged;
+ s->borderEnabled = shouldEnable;
+ s->borderWidth = width;
+ s->borderColor = color;
+
+ registerSurfaceControlForCallback(sc);
+ return *this;
+}
+
// ---------------------------------------------------------------------------
DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp<IBinder>& token) {
@@ -2012,6 +2075,31 @@
s.what |= DisplayState::eDisplaySizeChanged;
}
+// copied from FrameTimelineInfo::merge()
+void SurfaceComposerClient::Transaction::mergeFrameTimelineInfo(FrameTimelineInfo& t,
+ const FrameTimelineInfo& other) {
+ // When merging vsync Ids we take the oldest valid one
+ if (t.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID &&
+ other.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) {
+ if (other.vsyncId > t.vsyncId) {
+ t.vsyncId = other.vsyncId;
+ t.inputEventId = other.inputEventId;
+ t.startTimeNanos = other.startTimeNanos;
+ }
+ } else if (t.vsyncId == FrameTimelineInfo::INVALID_VSYNC_ID) {
+ t.vsyncId = other.vsyncId;
+ t.inputEventId = other.inputEventId;
+ t.startTimeNanos = other.startTimeNanos;
+ }
+}
+
+// copied from FrameTimelineInfo::clear()
+void SurfaceComposerClient::Transaction::clearFrameTimelineInfo(FrameTimelineInfo& t) {
+ t.vsyncId = FrameTimelineInfo::INVALID_VSYNC_ID;
+ t.inputEventId = os::IInputConstants::INVALID_INPUT_EVENT_ID;
+ t.startTimeNanos = 0;
+}
+
// ---------------------------------------------------------------------------
SurfaceComposerClient::SurfaceComposerClient() : mStatus(NO_INIT) {}
@@ -2020,11 +2108,11 @@
: mStatus(NO_ERROR), mClient(client) {}
void SurfaceComposerClient::onFirstRef() {
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ sp<gui::ISurfaceComposer> sf(ComposerServiceAIDL::getComposerService());
if (sf != nullptr && mStatus == NO_INIT) {
sp<ISurfaceComposerClient> conn;
- conn = sf->createConnection();
- if (conn != nullptr) {
+ binder::Status status = sf->createConnection(&conn);
+ if (status.isOk() && conn != nullptr) {
mClient = conn;
mStatus = NO_ERROR;
}
@@ -2062,7 +2150,7 @@
}
sp<SurfaceControl> SurfaceComposerClient::createSurface(const String8& name, uint32_t w, uint32_t h,
- PixelFormat format, uint32_t flags,
+ PixelFormat format, int32_t flags,
const sp<IBinder>& parentHandle,
LayerMetadata metadata,
uint32_t* outTransformHint) {
@@ -2072,38 +2160,9 @@
return s;
}
-sp<SurfaceControl> SurfaceComposerClient::createWithSurfaceParent(const String8& name, uint32_t w,
- uint32_t h, PixelFormat format,
- uint32_t flags, Surface* parent,
- LayerMetadata metadata,
- uint32_t* outTransformHint) {
- sp<SurfaceControl> sur;
- status_t err = mStatus;
-
- if (mStatus == NO_ERROR) {
- sp<IBinder> handle;
- sp<IGraphicBufferProducer> parentGbp = parent->getIGraphicBufferProducer();
- sp<IGraphicBufferProducer> gbp;
-
- uint32_t transformHint = 0;
- int32_t id = -1;
- err = mClient->createWithSurfaceParent(name, w, h, format, flags, parentGbp,
- std::move(metadata), &handle, &gbp, &id,
- &transformHint);
- if (outTransformHint) {
- *outTransformHint = transformHint;
- }
- ALOGE_IF(err, "SurfaceComposerClient::createWithSurfaceParent error %s", strerror(-err));
- if (err == NO_ERROR) {
- return new SurfaceControl(this, handle, gbp, id, transformHint);
- }
- }
- return nullptr;
-}
-
status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32_t w, uint32_t h,
PixelFormat format,
- sp<SurfaceControl>* outSurface, uint32_t flags,
+ sp<SurfaceControl>* outSurface, int32_t flags,
const sp<IBinder>& parentHandle,
LayerMetadata metadata,
uint32_t* outTransformHint) {
@@ -2111,21 +2170,17 @@
status_t err = mStatus;
if (mStatus == NO_ERROR) {
- sp<IBinder> handle;
- sp<IGraphicBufferProducer> gbp;
-
- uint32_t transformHint = 0;
- int32_t id = -1;
- err = mClient->createSurface(name, w, h, format, flags, parentHandle, std::move(metadata),
- &handle, &gbp, &id, &transformHint);
-
+ gui::CreateSurfaceResult result;
+ binder::Status status = mClient->createSurface(std::string(name.string()), flags,
+ parentHandle, std::move(metadata), &result);
+ err = statusTFromBinderStatus(status);
if (outTransformHint) {
- *outTransformHint = transformHint;
+ *outTransformHint = result.transformHint;
}
ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err));
if (err == NO_ERROR) {
- *outSurface =
- new SurfaceControl(this, handle, gbp, id, w, h, format, transformHint, flags);
+ *outSurface = new SurfaceControl(this, result.handle, result.layerId, w, h, format,
+ result.transformHint, flags);
}
}
return err;
@@ -2136,12 +2191,12 @@
return nullptr;
}
- sp<IBinder> handle;
sp<IBinder> mirrorFromHandle = mirrorFromSurface->getHandle();
- int32_t layer_id = -1;
- status_t err = mClient->mirrorSurface(mirrorFromHandle, &handle, &layer_id);
+ gui::MirrorSurfaceResult result;
+ const binder::Status status = mClient->mirrorSurface(mirrorFromHandle, &result);
+ const status_t err = statusTFromBinderStatus(status);
if (err == NO_ERROR) {
- return new SurfaceControl(this, handle, nullptr, layer_id, true /* owned */);
+ return new SurfaceControl(this, result.handle, result.layerId);
}
return nullptr;
}
@@ -2150,7 +2205,8 @@
if (mStatus != NO_ERROR) {
return mStatus;
}
- return mClient->clearLayerFrameStats(token);
+ const binder::Status status = mClient->clearLayerFrameStats(token);
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::getLayerFrameStats(const sp<IBinder>& token,
@@ -2158,19 +2214,38 @@
if (mStatus != NO_ERROR) {
return mStatus;
}
- return mClient->getLayerFrameStats(token, outStats);
+ gui::FrameStats stats;
+ const binder::Status status = mClient->getLayerFrameStats(token, &stats);
+ if (status.isOk()) {
+ outStats->refreshPeriodNano = stats.refreshPeriodNano;
+ outStats->desiredPresentTimesNano.setCapacity(stats.desiredPresentTimesNano.size());
+ for (const auto& t : stats.desiredPresentTimesNano) {
+ outStats->desiredPresentTimesNano.add(t);
+ }
+ outStats->actualPresentTimesNano.setCapacity(stats.actualPresentTimesNano.size());
+ for (const auto& t : stats.actualPresentTimesNano) {
+ outStats->actualPresentTimesNano.add(t);
+ }
+ outStats->frameReadyTimesNano.setCapacity(stats.frameReadyTimesNano.size());
+ for (const auto& t : stats.frameReadyTimesNano) {
+ outStats->frameReadyTimesNano.add(t);
+ }
+ }
+ return statusTFromBinderStatus(status);
}
// ----------------------------------------------------------------------------
status_t SurfaceComposerClient::enableVSyncInjections(bool enable) {
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- return sf->enableVSyncInjections(enable);
+ sp<gui::ISurfaceComposer> sf(ComposerServiceAIDL::getComposerService());
+ binder::Status status = sf->enableVSyncInjections(enable);
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::injectVSync(nsecs_t when) {
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- return sf->injectVSync(when);
+ sp<gui::ISurfaceComposer> sf(ComposerServiceAIDL::getComposerService());
+ binder::Status status = sf->injectVSync(when);
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::getDisplayState(const sp<IBinder>& display,
@@ -2184,17 +2259,106 @@
state->layerStackSpaceRect =
ui::Size(ds.layerStackSpaceRect.width, ds.layerStackSpaceRect.height);
}
- return status.transactionError();
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::getStaticDisplayInfo(const sp<IBinder>& display,
- ui::StaticDisplayInfo* info) {
- return ComposerService::getComposerService()->getStaticDisplayInfo(display, info);
+ ui::StaticDisplayInfo* outInfo) {
+ using Tag = android::gui::DeviceProductInfo::ManufactureOrModelDate::Tag;
+ gui::StaticDisplayInfo ginfo;
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->getStaticDisplayInfo(display, &ginfo);
+ if (status.isOk()) {
+ // convert gui::StaticDisplayInfo to ui::StaticDisplayInfo
+ outInfo->connectionType = static_cast<ui::DisplayConnectionType>(ginfo.connectionType);
+ outInfo->density = ginfo.density;
+ outInfo->secure = ginfo.secure;
+ outInfo->installOrientation = static_cast<ui::Rotation>(ginfo.installOrientation);
+
+ DeviceProductInfo info;
+ std::optional<gui::DeviceProductInfo> dpi = ginfo.deviceProductInfo;
+ gui::DeviceProductInfo::ManufactureOrModelDate& date = dpi->manufactureOrModelDate;
+ info.name = dpi->name;
+ if (dpi->manufacturerPnpId.size() > 0) {
+ // copid from PnpId = std::array<char, 4> in ui/DeviceProductInfo.h
+ constexpr int kMaxPnpIdSize = 4;
+ size_t count = std::max<size_t>(kMaxPnpIdSize, dpi->manufacturerPnpId.size());
+ std::copy_n(dpi->manufacturerPnpId.begin(), count, info.manufacturerPnpId.begin());
+ }
+ if (dpi->relativeAddress.size() > 0) {
+ std::copy(dpi->relativeAddress.begin(), dpi->relativeAddress.end(),
+ std::back_inserter(info.relativeAddress));
+ }
+ info.productId = dpi->productId;
+ if (date.getTag() == Tag::modelYear) {
+ DeviceProductInfo::ModelYear modelYear;
+ modelYear.year = static_cast<uint32_t>(date.get<Tag::modelYear>().year);
+ info.manufactureOrModelDate = modelYear;
+ } else if (date.getTag() == Tag::manufactureYear) {
+ DeviceProductInfo::ManufactureYear manufactureYear;
+ manufactureYear.year = date.get<Tag::manufactureYear>().modelYear.year;
+ info.manufactureOrModelDate = manufactureYear;
+ } else if (date.getTag() == Tag::manufactureWeekAndYear) {
+ DeviceProductInfo::ManufactureWeekAndYear weekAndYear;
+ weekAndYear.year =
+ date.get<Tag::manufactureWeekAndYear>().manufactureYear.modelYear.year;
+ weekAndYear.week = date.get<Tag::manufactureWeekAndYear>().week;
+ info.manufactureOrModelDate = weekAndYear;
+ }
+
+ outInfo->deviceProductInfo = info;
+ }
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::getDynamicDisplayInfo(const sp<IBinder>& display,
- ui::DynamicDisplayInfo* info) {
- return ComposerService::getComposerService()->getDynamicDisplayInfo(display, info);
+ ui::DynamicDisplayInfo* outInfo) {
+ gui::DynamicDisplayInfo ginfo;
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->getDynamicDisplayInfo(display, &ginfo);
+ if (status.isOk()) {
+ // convert gui::DynamicDisplayInfo to ui::DynamicDisplayInfo
+ outInfo->supportedDisplayModes.clear();
+ outInfo->supportedDisplayModes.reserve(ginfo.supportedDisplayModes.size());
+ for (const auto& mode : ginfo.supportedDisplayModes) {
+ ui::DisplayMode outMode;
+ outMode.id = mode.id;
+ outMode.resolution.width = mode.resolution.width;
+ outMode.resolution.height = mode.resolution.height;
+ outMode.xDpi = mode.xDpi;
+ outMode.yDpi = mode.yDpi;
+ outMode.refreshRate = mode.refreshRate;
+ outMode.appVsyncOffset = mode.appVsyncOffset;
+ outMode.sfVsyncOffset = mode.sfVsyncOffset;
+ outMode.presentationDeadline = mode.presentationDeadline;
+ outMode.group = mode.group;
+ outInfo->supportedDisplayModes.push_back(outMode);
+ }
+
+ outInfo->activeDisplayModeId = ginfo.activeDisplayModeId;
+
+ outInfo->supportedColorModes.clear();
+ outInfo->supportedColorModes.reserve(ginfo.supportedColorModes.size());
+ for (const auto& cmode : ginfo.supportedColorModes) {
+ outInfo->supportedColorModes.push_back(static_cast<ui::ColorMode>(cmode));
+ }
+
+ outInfo->activeColorMode = static_cast<ui::ColorMode>(ginfo.activeColorMode);
+
+ std::vector<ui::Hdr> types;
+ types.reserve(ginfo.hdrCapabilities.supportedHdrTypes.size());
+ for (const auto& hdr : ginfo.hdrCapabilities.supportedHdrTypes) {
+ types.push_back(static_cast<ui::Hdr>(hdr));
+ }
+ outInfo->hdrCapabilities = HdrCapabilities(types, ginfo.hdrCapabilities.maxLuminance,
+ ginfo.hdrCapabilities.maxAverageLuminance,
+ ginfo.hdrCapabilities.minLuminance);
+
+ outInfo->autoLowLatencyModeSupported = ginfo.autoLowLatencyModeSupported;
+ outInfo->gameContentTypeSupported = ginfo.gameContentTypeSupported;
+ outInfo->preferredBootDisplayMode = ginfo.preferredBootDisplayMode;
+ }
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::getActiveDisplayMode(const sp<IBinder>& display,
@@ -2218,10 +2382,13 @@
const sp<IBinder>& displayToken, ui::DisplayModeId defaultMode, bool allowGroupSwitching,
float primaryRefreshRateMin, float primaryRefreshRateMax, float appRequestRefreshRateMin,
float appRequestRefreshRateMax) {
- return ComposerService::getComposerService()
- ->setDesiredDisplayModeSpecs(displayToken, defaultMode, allowGroupSwitching,
- primaryRefreshRateMin, primaryRefreshRateMax,
- appRequestRefreshRateMin, appRequestRefreshRateMax);
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()
+ ->setDesiredDisplayModeSpecs(displayToken, defaultMode, allowGroupSwitching,
+ primaryRefreshRateMin, primaryRefreshRateMax,
+ appRequestRefreshRateMin,
+ appRequestRefreshRateMax);
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::getDesiredDisplayModeSpecs(const sp<IBinder>& displayToken,
@@ -2231,41 +2398,81 @@
float* outPrimaryRefreshRateMax,
float* outAppRequestRefreshRateMin,
float* outAppRequestRefreshRateMax) {
- return ComposerService::getComposerService()
- ->getDesiredDisplayModeSpecs(displayToken, outDefaultMode, outAllowGroupSwitching,
- outPrimaryRefreshRateMin, outPrimaryRefreshRateMax,
- outAppRequestRefreshRateMin, outAppRequestRefreshRateMax);
+ if (!outDefaultMode || !outAllowGroupSwitching || !outPrimaryRefreshRateMin ||
+ !outPrimaryRefreshRateMax || !outAppRequestRefreshRateMin || !outAppRequestRefreshRateMax) {
+ return BAD_VALUE;
+ }
+ gui::DisplayModeSpecs specs;
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->getDesiredDisplayModeSpecs(displayToken,
+ &specs);
+ if (status.isOk()) {
+ *outDefaultMode = specs.defaultMode;
+ *outAllowGroupSwitching = specs.allowGroupSwitching;
+ *outPrimaryRefreshRateMin = specs.primaryRefreshRateMin;
+ *outPrimaryRefreshRateMax = specs.primaryRefreshRateMax;
+ *outAppRequestRefreshRateMin = specs.appRequestRefreshRateMin;
+ *outAppRequestRefreshRateMax = specs.appRequestRefreshRateMax;
+ }
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::getDisplayNativePrimaries(const sp<IBinder>& display,
ui::DisplayPrimaries& outPrimaries) {
- return ComposerService::getComposerService()->getDisplayNativePrimaries(display, outPrimaries);
+ gui::DisplayPrimaries primaries;
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->getDisplayNativePrimaries(display,
+ &primaries);
+ if (status.isOk()) {
+ outPrimaries.red.X = primaries.red.X;
+ outPrimaries.red.Y = primaries.red.Y;
+ outPrimaries.red.Z = primaries.red.Z;
+
+ outPrimaries.green.X = primaries.green.X;
+ outPrimaries.green.Y = primaries.green.Y;
+ outPrimaries.green.Z = primaries.green.Z;
+
+ outPrimaries.blue.X = primaries.blue.X;
+ outPrimaries.blue.Y = primaries.blue.Y;
+ outPrimaries.blue.Z = primaries.blue.Z;
+
+ outPrimaries.white.X = primaries.white.X;
+ outPrimaries.white.Y = primaries.white.Y;
+ outPrimaries.white.Z = primaries.white.Z;
+ }
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::setActiveColorMode(const sp<IBinder>& display,
ColorMode colorMode) {
- return ComposerService::getComposerService()->setActiveColorMode(display, colorMode);
+ binder::Status status = ComposerServiceAIDL::getComposerService()
+ ->setActiveColorMode(display, static_cast<int>(colorMode));
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::getBootDisplayModeSupport(bool* support) {
binder::Status status =
ComposerServiceAIDL::getComposerService()->getBootDisplayModeSupport(support);
- return status.transactionError();
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::setBootDisplayMode(const sp<IBinder>& display,
ui::DisplayModeId displayModeId) {
- return ComposerService::getComposerService()->setBootDisplayMode(display, displayModeId);
+ binder::Status status = ComposerServiceAIDL::getComposerService()
+ ->setBootDisplayMode(display, static_cast<int>(displayModeId));
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::clearBootDisplayMode(const sp<IBinder>& display) {
binder::Status status =
ComposerServiceAIDL::getComposerService()->clearBootDisplayMode(display);
- return status.transactionError();
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::setOverrideFrameRate(uid_t uid, float frameRate) {
- return ComposerService::getComposerService()->setOverrideFrameRate(uid, frameRate);
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->setOverrideFrameRate(uid, frameRate);
+ return statusTFromBinderStatus(status);
}
void SurfaceComposerClient::setAutoLowLatencyMode(const sp<IBinder>& display, bool on) {
@@ -2284,57 +2491,137 @@
status_t SurfaceComposerClient::getCompositionPreference(
ui::Dataspace* defaultDataspace, ui::PixelFormat* defaultPixelFormat,
ui::Dataspace* wideColorGamutDataspace, ui::PixelFormat* wideColorGamutPixelFormat) {
- return ComposerService::getComposerService()
- ->getCompositionPreference(defaultDataspace, defaultPixelFormat,
- wideColorGamutDataspace, wideColorGamutPixelFormat);
+ gui::CompositionPreference pref;
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->getCompositionPreference(&pref);
+ if (status.isOk()) {
+ *defaultDataspace = static_cast<ui::Dataspace>(pref.defaultDataspace);
+ *defaultPixelFormat = static_cast<ui::PixelFormat>(pref.defaultPixelFormat);
+ *wideColorGamutDataspace = static_cast<ui::Dataspace>(pref.wideColorGamutDataspace);
+ *wideColorGamutPixelFormat = static_cast<ui::PixelFormat>(pref.wideColorGamutPixelFormat);
+ }
+ return statusTFromBinderStatus(status);
}
bool SurfaceComposerClient::getProtectedContentSupport() {
bool supported = false;
- ComposerService::getComposerService()->getProtectedContentSupport(&supported);
+ ComposerServiceAIDL::getComposerService()->getProtectedContentSupport(&supported);
return supported;
}
status_t SurfaceComposerClient::clearAnimationFrameStats() {
- return ComposerService::getComposerService()->clearAnimationFrameStats();
+ binder::Status status = ComposerServiceAIDL::getComposerService()->clearAnimationFrameStats();
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::getAnimationFrameStats(FrameStats* outStats) {
- return ComposerService::getComposerService()->getAnimationFrameStats(outStats);
+ gui::FrameStats stats;
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->getAnimationFrameStats(&stats);
+ if (status.isOk()) {
+ outStats->refreshPeriodNano = stats.refreshPeriodNano;
+ outStats->desiredPresentTimesNano.setCapacity(stats.desiredPresentTimesNano.size());
+ for (const auto& t : stats.desiredPresentTimesNano) {
+ outStats->desiredPresentTimesNano.add(t);
+ }
+ outStats->actualPresentTimesNano.setCapacity(stats.actualPresentTimesNano.size());
+ for (const auto& t : stats.actualPresentTimesNano) {
+ outStats->actualPresentTimesNano.add(t);
+ }
+ outStats->frameReadyTimesNano.setCapacity(stats.frameReadyTimesNano.size());
+ for (const auto& t : stats.frameReadyTimesNano) {
+ outStats->frameReadyTimesNano.add(t);
+ }
+ }
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::overrideHdrTypes(const sp<IBinder>& display,
const std::vector<ui::Hdr>& hdrTypes) {
- return ComposerService::getComposerService()->overrideHdrTypes(display, hdrTypes);
+ std::vector<int32_t> hdrTypesVector;
+ hdrTypesVector.reserve(hdrTypes.size());
+ for (auto t : hdrTypes) {
+ hdrTypesVector.push_back(static_cast<int32_t>(t));
+ }
+
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->overrideHdrTypes(display, hdrTypesVector);
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::onPullAtom(const int32_t atomId, std::string* outData,
bool* success) {
- return ComposerService::getComposerService()->onPullAtom(atomId, outData, success);
+ gui::PullAtomData pad;
+ binder::Status status = ComposerServiceAIDL::getComposerService()->onPullAtom(atomId, &pad);
+ if (status.isOk()) {
+ outData->assign((const char*)pad.data.data(), pad.data.size());
+ *success = pad.success;
+ }
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::getDisplayedContentSamplingAttributes(const sp<IBinder>& display,
ui::PixelFormat* outFormat,
ui::Dataspace* outDataspace,
uint8_t* outComponentMask) {
- return ComposerService::getComposerService()
- ->getDisplayedContentSamplingAttributes(display, outFormat, outDataspace,
- outComponentMask);
+ if (!outFormat || !outDataspace || !outComponentMask) {
+ return BAD_VALUE;
+ }
+
+ gui::ContentSamplingAttributes attrs;
+ binder::Status status = ComposerServiceAIDL::getComposerService()
+ ->getDisplayedContentSamplingAttributes(display, &attrs);
+ if (status.isOk()) {
+ *outFormat = static_cast<ui::PixelFormat>(attrs.format);
+ *outDataspace = static_cast<ui::Dataspace>(attrs.dataspace);
+ *outComponentMask = static_cast<uint8_t>(attrs.componentMask);
+ }
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::setDisplayContentSamplingEnabled(const sp<IBinder>& display,
bool enable, uint8_t componentMask,
uint64_t maxFrames) {
- return ComposerService::getComposerService()->setDisplayContentSamplingEnabled(display, enable,
- componentMask,
- maxFrames);
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()
+ ->setDisplayContentSamplingEnabled(display, enable,
+ static_cast<int8_t>(componentMask),
+ static_cast<int64_t>(maxFrames));
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::getDisplayedContentSample(const sp<IBinder>& display,
uint64_t maxFrames, uint64_t timestamp,
DisplayedFrameStats* outStats) {
- return ComposerService::getComposerService()->getDisplayedContentSample(display, maxFrames,
- timestamp, outStats);
+ if (!outStats) {
+ return BAD_VALUE;
+ }
+
+ gui::DisplayedFrameStats stats;
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->getDisplayedContentSample(display, maxFrames,
+ timestamp, &stats);
+ if (status.isOk()) {
+ // convert gui::DisplayedFrameStats to ui::DisplayedFrameStats
+ outStats->numFrames = static_cast<uint64_t>(stats.numFrames);
+ outStats->component_0_sample.reserve(stats.component_0_sample.size());
+ for (const auto& s : stats.component_0_sample) {
+ outStats->component_0_sample.push_back(static_cast<uint64_t>(s));
+ }
+ outStats->component_1_sample.reserve(stats.component_1_sample.size());
+ for (const auto& s : stats.component_1_sample) {
+ outStats->component_1_sample.push_back(static_cast<uint64_t>(s));
+ }
+ outStats->component_2_sample.reserve(stats.component_2_sample.size());
+ for (const auto& s : stats.component_2_sample) {
+ outStats->component_2_sample.push_back(static_cast<uint64_t>(s));
+ }
+ outStats->component_3_sample.reserve(stats.component_3_sample.size());
+ for (const auto& s : stats.component_3_sample) {
+ outStats->component_3_sample.push_back(static_cast<uint64_t>(s));
+ }
+ }
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::isWideColorDisplay(const sp<IBinder>& display,
@@ -2342,39 +2629,55 @@
binder::Status status =
ComposerServiceAIDL::getComposerService()->isWideColorDisplay(display,
outIsWideColorDisplay);
- return status.transactionError();
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::addRegionSamplingListener(
const Rect& samplingArea, const sp<IBinder>& stopLayerHandle,
const sp<IRegionSamplingListener>& listener) {
- return ComposerService::getComposerService()->addRegionSamplingListener(samplingArea,
- stopLayerHandle,
- listener);
+ gui::ARect rect;
+ rect.left = samplingArea.left;
+ rect.top = samplingArea.top;
+ rect.right = samplingArea.right;
+ rect.bottom = samplingArea.bottom;
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->addRegionSamplingListener(rect,
+ stopLayerHandle,
+ listener);
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::removeRegionSamplingListener(
const sp<IRegionSamplingListener>& listener) {
- return ComposerService::getComposerService()->removeRegionSamplingListener(listener);
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->removeRegionSamplingListener(listener);
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::addFpsListener(int32_t taskId,
const sp<gui::IFpsListener>& listener) {
- return ComposerService::getComposerService()->addFpsListener(taskId, listener);
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->addFpsListener(taskId, listener);
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::removeFpsListener(const sp<gui::IFpsListener>& listener) {
- return ComposerService::getComposerService()->removeFpsListener(listener);
+ binder::Status status = ComposerServiceAIDL::getComposerService()->removeFpsListener(listener);
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::addTunnelModeEnabledListener(
const sp<gui::ITunnelModeEnabledListener>& listener) {
- return ComposerService::getComposerService()->addTunnelModeEnabledListener(listener);
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->addTunnelModeEnabledListener(listener);
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::removeTunnelModeEnabledListener(
const sp<gui::ITunnelModeEnabledListener>& listener) {
- return ComposerService::getComposerService()->removeTunnelModeEnabledListener(listener);
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->removeTunnelModeEnabledListener(listener);
+ return statusTFromBinderStatus(status);
}
bool SurfaceComposerClient::getDisplayBrightnessSupport(const sp<IBinder>& displayToken) {
@@ -2390,7 +2693,7 @@
binder::Status status =
ComposerServiceAIDL::getComposerService()->setDisplayBrightness(displayToken,
brightness);
- return status.transactionError();
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::addHdrLayerInfoListener(
@@ -2398,7 +2701,7 @@
binder::Status status =
ComposerServiceAIDL::getComposerService()->addHdrLayerInfoListener(displayToken,
listener);
- return status.transactionError();
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::removeHdrLayerInfoListener(
@@ -2406,45 +2709,76 @@
binder::Status status =
ComposerServiceAIDL::getComposerService()->removeHdrLayerInfoListener(displayToken,
listener);
- return status.transactionError();
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::notifyPowerBoost(int32_t boostId) {
binder::Status status = ComposerServiceAIDL::getComposerService()->notifyPowerBoost(boostId);
- return status.transactionError();
+ return statusTFromBinderStatus(status);
}
status_t SurfaceComposerClient::setGlobalShadowSettings(const half4& ambientColor,
const half4& spotColor, float lightPosY,
float lightPosZ, float lightRadius) {
- return ComposerService::getComposerService()->setGlobalShadowSettings(ambientColor, spotColor,
- lightPosY, lightPosZ,
- lightRadius);
+ gui::Color ambientColorG, spotColorG;
+ ambientColorG.r = ambientColor.r;
+ ambientColorG.g = ambientColor.g;
+ ambientColorG.b = ambientColor.b;
+ ambientColorG.a = ambientColor.a;
+ spotColorG.r = spotColor.r;
+ spotColorG.g = spotColor.g;
+ spotColorG.b = spotColor.b;
+ spotColorG.a = spotColor.a;
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->setGlobalShadowSettings(ambientColorG,
+ spotColorG,
+ lightPosY, lightPosZ,
+ lightRadius);
+ return statusTFromBinderStatus(status);
}
std::optional<DisplayDecorationSupport> SurfaceComposerClient::getDisplayDecorationSupport(
const sp<IBinder>& displayToken) {
+ std::optional<gui::DisplayDecorationSupport> gsupport;
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->getDisplayDecorationSupport(displayToken,
+ &gsupport);
std::optional<DisplayDecorationSupport> support;
- ComposerService::getComposerService()->getDisplayDecorationSupport(displayToken, &support);
+ if (status.isOk() && gsupport.has_value()) {
+ support->format = static_cast<aidl::android::hardware::graphics::common::PixelFormat>(
+ gsupport->format);
+ support->alphaInterpretation =
+ static_cast<aidl::android::hardware::graphics::common::AlphaInterpretation>(
+ gsupport->alphaInterpretation);
+ }
return support;
}
-int SurfaceComposerClient::getGPUContextPriority() {
- return ComposerService::getComposerService()->getGPUContextPriority();
+int SurfaceComposerClient::getGpuContextPriority() {
+ int priority;
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->getGpuContextPriority(&priority);
+ if (!status.isOk()) {
+ status_t err = statusTFromBinderStatus(status);
+ ALOGE("getGpuContextPriority failed to read data: %s (%d)", strerror(-err), err);
+ return 0;
+ }
+ return priority;
}
status_t SurfaceComposerClient::addWindowInfosListener(
const sp<WindowInfosListener>& windowInfosListener,
std::pair<std::vector<gui::WindowInfo>, std::vector<gui::DisplayInfo>>* outInitialInfo) {
return WindowInfosListenerReporter::getInstance()
- ->addWindowInfosListener(windowInfosListener, ComposerService::getComposerService(),
+ ->addWindowInfosListener(windowInfosListener, ComposerServiceAIDL::getComposerService(),
outInitialInfo);
}
status_t SurfaceComposerClient::removeWindowInfosListener(
const sp<WindowInfosListener>& windowInfosListener) {
return WindowInfosListenerReporter::getInstance()
- ->removeWindowInfosListener(windowInfosListener, ComposerService::getComposerService());
+ ->removeWindowInfosListener(windowInfosListener,
+ ComposerServiceAIDL::getComposerService());
}
// ----------------------------------------------------------------------------
@@ -2455,7 +2789,7 @@
if (s == nullptr) return NO_INIT;
binder::Status status = s->captureDisplay(captureArgs, captureListener);
- return status.transactionError();
+ return statusTFromBinderStatus(status);
}
status_t ScreenshotClient::captureDisplay(DisplayId displayId,
@@ -2464,7 +2798,7 @@
if (s == nullptr) return NO_INIT;
binder::Status status = s->captureDisplayById(displayId.value, captureListener);
- return status.transactionError();
+ return statusTFromBinderStatus(status);
}
status_t ScreenshotClient::captureLayers(const LayerCaptureArgs& captureArgs,
@@ -2473,7 +2807,7 @@
if (s == nullptr) return NO_INIT;
binder::Status status = s->captureLayers(captureArgs, captureListener);
- return status.transactionError();
+ return statusTFromBinderStatus(status);
}
// ---------------------------------------------------------------------------------
@@ -2515,4 +2849,17 @@
}
}
+// ---------------------------------------------------------------------------------
+
+void SurfaceComposerClient::Event::set() {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mComplete = true;
+ mConditionVariable.notify_all();
+}
+
+bool SurfaceComposerClient::Event::wait() {
+ std::unique_lock<std::mutex> lock(mMutex);
+ return mConditionVariable.wait_for(lock, sTimeout, [this] { return mComplete; });
+}
+
} // namespace android
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index 654fb33..84257de 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -49,12 +49,10 @@
// ============================================================================
SurfaceControl::SurfaceControl(const sp<SurfaceComposerClient>& client, const sp<IBinder>& handle,
- const sp<IGraphicBufferProducer>& gbp, int32_t layerId,
- uint32_t w, uint32_t h, PixelFormat format, uint32_t transform,
- uint32_t flags)
+ int32_t layerId, uint32_t w, uint32_t h, PixelFormat format,
+ uint32_t transform, uint32_t flags)
: mClient(client),
mHandle(handle),
- mGraphicBufferProducer(gbp),
mLayerId(layerId),
mTransformHint(transform),
mWidth(w),
@@ -65,7 +63,6 @@
SurfaceControl::SurfaceControl(const sp<SurfaceControl>& other) {
mClient = other->mClient;
mHandle = other->mHandle;
- mGraphicBufferProducer = other->mGraphicBufferProducer;
mTransformHint = other->mTransformHint;
mLayerId = other->mLayerId;
mWidth = other->mWidth;
@@ -165,11 +162,11 @@
void SurfaceControl::updateDefaultBufferSize(uint32_t width, uint32_t height) {
Mutex::Autolock _l(mLock);
- mWidth = width; mHeight = height;
+ mWidth = width;
+ mHeight = height;
if (mBbq) {
mBbq->update(mBbqChild, width, height, mFormat);
}
-
}
sp<IBinder> SurfaceControl::getLayerStateHandle() const
@@ -245,9 +242,7 @@
*outSurfaceControl =
new SurfaceControl(new SurfaceComposerClient(
interface_cast<ISurfaceComposerClient>(client)),
- handle.get(), nullptr, layerId,
- width, height, format,
- transformHint);
+ handle.get(), layerId, width, height, format, transformHint);
return NO_ERROR;
}
diff --git a/libs/gui/TransactionTracing.cpp b/libs/gui/TransactionTracing.cpp
index eedc3df..59450fb 100644
--- a/libs/gui/TransactionTracing.cpp
+++ b/libs/gui/TransactionTracing.cpp
@@ -15,9 +15,9 @@
*/
#include "gui/TransactionTracing.h"
-#include "gui/ISurfaceComposer.h"
+#include "android/gui/ISurfaceComposer.h"
-#include <private/gui/ComposerService.h>
+#include <private/gui/ComposerServiceAIDL.h>
namespace android {
@@ -32,7 +32,7 @@
if (sInstance == nullptr) {
sInstance = new TransactionTraceListener;
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ sp<gui::ISurfaceComposer> sf(ComposerServiceAIDL::getComposerService());
sf->addTransactionTraceListener(sInstance);
}
@@ -50,4 +50,4 @@
return mTracingEnabled;
}
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/libs/gui/WindowInfo.cpp b/libs/gui/WindowInfo.cpp
index 4e966d1..804ce4f 100644
--- a/libs/gui/WindowInfo.cpp
+++ b/libs/gui/WindowInfo.cpp
@@ -76,7 +76,7 @@
info.inputConfig == inputConfig && info.displayId == displayId &&
info.replaceTouchableRegionWithCrop == replaceTouchableRegionWithCrop &&
info.applicationInfo == applicationInfo && info.layoutParamsType == layoutParamsType &&
- info.layoutParamsFlags == layoutParamsFlags && info.isClone == isClone;
+ info.layoutParamsFlags == layoutParamsFlags;
}
status_t WindowInfo::writeToParcel(android::Parcel* parcel) const {
@@ -124,8 +124,7 @@
parcel->write(touchableRegion) ?:
parcel->writeBool(replaceTouchableRegionWithCrop) ?:
parcel->writeStrongBinder(touchableRegionCropHandle.promote()) ?:
- parcel->writeStrongBinder(windowToken) ?:
- parcel->writeBool(isClone);
+ parcel->writeStrongBinder(windowToken);
// clang-format on
return status;
}
@@ -176,8 +175,7 @@
parcel->read(touchableRegion) ?:
parcel->readBool(&replaceTouchableRegionWithCrop) ?:
parcel->readNullableStrongBinder(&touchableRegionCropHandleSp) ?:
- parcel->readNullableStrongBinder(&windowToken) ?:
- parcel->readBool(&isClone);
+ parcel->readNullableStrongBinder(&windowToken);
// clang-format on
if (status != OK) {
diff --git a/libs/gui/WindowInfosListenerReporter.cpp b/libs/gui/WindowInfosListenerReporter.cpp
index cfc7dbc..01e865d 100644
--- a/libs/gui/WindowInfosListenerReporter.cpp
+++ b/libs/gui/WindowInfosListenerReporter.cpp
@@ -14,7 +14,8 @@
* limitations under the License.
*/
-#include <gui/ISurfaceComposer.h>
+#include <android/gui/ISurfaceComposer.h>
+#include <gui/AidlStatusUtil.h>
#include <gui/WindowInfosListenerReporter.h>
namespace android {
@@ -23,6 +24,7 @@
using gui::IWindowInfosReportedListener;
using gui::WindowInfo;
using gui::WindowInfosListener;
+using gui::aidl_utils::statusTFromBinderStatus;
sp<WindowInfosListenerReporter> WindowInfosListenerReporter::getInstance() {
static sp<WindowInfosListenerReporter> sInstance = new WindowInfosListenerReporter;
@@ -31,13 +33,14 @@
status_t WindowInfosListenerReporter::addWindowInfosListener(
const sp<WindowInfosListener>& windowInfosListener,
- const sp<ISurfaceComposer>& surfaceComposer,
+ const sp<gui::ISurfaceComposer>& surfaceComposer,
std::pair<std::vector<gui::WindowInfo>, std::vector<gui::DisplayInfo>>* outInitialInfo) {
status_t status = OK;
{
std::scoped_lock lock(mListenersMutex);
if (mWindowInfosListeners.empty()) {
- status = surfaceComposer->addWindowInfosListener(this);
+ binder::Status s = surfaceComposer->addWindowInfosListener(this);
+ status = statusTFromBinderStatus(s);
}
if (status == OK) {
@@ -55,12 +58,13 @@
status_t WindowInfosListenerReporter::removeWindowInfosListener(
const sp<WindowInfosListener>& windowInfosListener,
- const sp<ISurfaceComposer>& surfaceComposer) {
+ const sp<gui::ISurfaceComposer>& surfaceComposer) {
status_t status = OK;
{
std::scoped_lock lock(mListenersMutex);
if (mWindowInfosListeners.size() == 1) {
- status = surfaceComposer->removeWindowInfosListener(this);
+ binder::Status s = surfaceComposer->removeWindowInfosListener(this);
+ status = statusTFromBinderStatus(s);
// Clear the last stored state since we're disabling updates and don't want to hold
// stale values
mLastWindowInfos.clear();
@@ -78,7 +82,8 @@
binder::Status WindowInfosListenerReporter::onWindowInfosChanged(
const std::vector<WindowInfo>& windowInfos, const std::vector<DisplayInfo>& displayInfos,
const sp<IWindowInfosReportedListener>& windowInfosReportedListener) {
- std::unordered_set<sp<WindowInfosListener>, SpHash<WindowInfosListener>> windowInfosListeners;
+ std::unordered_set<sp<WindowInfosListener>, gui::SpHash<WindowInfosListener>>
+ windowInfosListeners;
{
std::scoped_lock lock(mListenersMutex);
@@ -101,7 +106,7 @@
return binder::Status::ok();
}
-void WindowInfosListenerReporter::reconnect(const sp<ISurfaceComposer>& composerService) {
+void WindowInfosListenerReporter::reconnect(const sp<gui::ISurfaceComposer>& composerService) {
std::scoped_lock lock(mListenersMutex);
if (!mWindowInfosListeners.empty()) {
composerService->addWindowInfosListener(this);
diff --git a/libs/gui/aidl/android/gui/Rect.aidl b/libs/gui/aidl/android/gui/ARect.aidl
similarity index 98%
rename from libs/gui/aidl/android/gui/Rect.aidl
rename to libs/gui/aidl/android/gui/ARect.aidl
index 1b13761..5785907 100644
--- a/libs/gui/aidl/android/gui/Rect.aidl
+++ b/libs/gui/aidl/android/gui/ARect.aidl
@@ -20,7 +20,7 @@
// TODO(b/221473398):
// use hardware/interfaces/graphics/common/aidl/android/hardware/graphics/common/Rect.aidl
/** @hide */
-parcelable Rect {
+parcelable ARect {
/// Minimum X coordinate of the rectangle.
int left;
diff --git a/libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl b/libs/gui/aidl/android/gui/Color.aidl
similarity index 64%
copy from libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl
copy to libs/gui/aidl/android/gui/Color.aidl
index 6929a6c..12af066 100644
--- a/libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl
+++ b/libs/gui/aidl/android/gui/Color.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * 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.
@@ -14,15 +14,12 @@
* limitations under the License.
*/
-package android.content.pm;
+package android.gui;
-import android.content.pm.PackageChangeEvent;
-
-/**
- * This is a non-blocking notification when a package has changed.
- *
- * @hide
- */
-oneway interface IPackageChangeObserver {
- void onPackageChanged(in PackageChangeEvent event);
+/** @hide */
+parcelable Color {
+ float r;
+ float g;
+ float b;
+ float a;
}
diff --git a/libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl b/libs/gui/aidl/android/gui/CompositionPreference.aidl
similarity index 63%
copy from libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl
copy to libs/gui/aidl/android/gui/CompositionPreference.aidl
index 6929a6c..b615824 100644
--- a/libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl
+++ b/libs/gui/aidl/android/gui/CompositionPreference.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * 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.
@@ -14,15 +14,12 @@
* limitations under the License.
*/
-package android.content.pm;
+package android.gui;
-import android.content.pm.PackageChangeEvent;
-
-/**
- * This is a non-blocking notification when a package has changed.
- *
- * @hide
- */
-oneway interface IPackageChangeObserver {
- void onPackageChanged(in PackageChangeEvent event);
+/** @hide */
+parcelable CompositionPreference {
+ int /*ui::Dataspace*/ defaultDataspace;
+ int /*ui::PixelFormat*/ defaultPixelFormat;
+ int /*ui::Dataspace*/ wideColorGamutDataspace;
+ int /*ui::PixelFormat*/ wideColorGamutPixelFormat;
}
diff --git a/libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl b/libs/gui/aidl/android/gui/ContentSamplingAttributes.aidl
similarity index 64%
copy from libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl
copy to libs/gui/aidl/android/gui/ContentSamplingAttributes.aidl
index 6929a6c..5d913b1 100644
--- a/libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl
+++ b/libs/gui/aidl/android/gui/ContentSamplingAttributes.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * 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.
@@ -14,15 +14,11 @@
* limitations under the License.
*/
-package android.content.pm;
+package android.gui;
-import android.content.pm.PackageChangeEvent;
-
-/**
- * This is a non-blocking notification when a package has changed.
- *
- * @hide
- */
-oneway interface IPackageChangeObserver {
- void onPackageChanged(in PackageChangeEvent event);
+/** @hide */
+parcelable ContentSamplingAttributes {
+ int /*ui::PixelFormat*/ format;
+ int /*ui::Dataspace*/ dataspace;
+ byte componentMask;
}
diff --git a/libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl b/libs/gui/aidl/android/gui/CreateSurfaceResult.aidl
similarity index 64%
rename from libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl
rename to libs/gui/aidl/android/gui/CreateSurfaceResult.aidl
index 6929a6c..39e4916 100644
--- a/libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl
+++ b/libs/gui/aidl/android/gui/CreateSurfaceResult.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * 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.
@@ -14,15 +14,11 @@
* limitations under the License.
*/
-package android.content.pm;
+package android.gui;
-import android.content.pm.PackageChangeEvent;
-
-/**
- * This is a non-blocking notification when a package has changed.
- *
- * @hide
- */
-oneway interface IPackageChangeObserver {
- void onPackageChanged(in PackageChangeEvent event);
+/** @hide */
+parcelable CreateSurfaceResult {
+ IBinder handle;
+ int layerId;
+ int transformHint;
}
diff --git a/libs/gui/aidl/android/gui/DeviceProductInfo.aidl b/libs/gui/aidl/android/gui/DeviceProductInfo.aidl
new file mode 100644
index 0000000..98404cf
--- /dev/null
+++ b/libs/gui/aidl/android/gui/DeviceProductInfo.aidl
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+package android.gui;
+
+// Product-specific information about the display or the directly connected device on the
+// display chain. For example, if the display is transitively connected, this field may contain
+// product information about the intermediate device.
+
+/** @hide */
+parcelable DeviceProductInfo {
+ parcelable ModelYear {
+ int year;
+ }
+
+ parcelable ManufactureYear {
+ ModelYear modelYear;
+ }
+
+ parcelable ManufactureWeekAndYear {
+ ManufactureYear manufactureYear;
+
+ // 1-base week number. Week numbering may not be consistent between manufacturers.
+ int week;
+ }
+
+ union ManufactureOrModelDate {
+ ModelYear modelYear;
+ ManufactureYear manufactureYear;
+ ManufactureWeekAndYear manufactureWeekAndYear;
+ }
+
+ // Display name.
+ @utf8InCpp String name;
+
+ // NULL-terminated Manufacturer plug and play ID.
+ byte[] manufacturerPnpId;
+
+ // Manufacturer product ID.
+ @utf8InCpp String productId;
+
+ ManufactureOrModelDate manufactureOrModelDate;
+
+ byte[] relativeAddress;
+}
diff --git a/libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl b/libs/gui/aidl/android/gui/DisplayConnectionType.aidl
similarity index 64%
copy from libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl
copy to libs/gui/aidl/android/gui/DisplayConnectionType.aidl
index 6929a6c..72c4ede 100644
--- a/libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl
+++ b/libs/gui/aidl/android/gui/DisplayConnectionType.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * 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.
@@ -14,15 +14,11 @@
* limitations under the License.
*/
-package android.content.pm;
+package android.gui;
-import android.content.pm.PackageChangeEvent;
-
-/**
- * This is a non-blocking notification when a package has changed.
- *
- * @hide
- */
-oneway interface IPackageChangeObserver {
- void onPackageChanged(in PackageChangeEvent event);
+/** @hide */
+@Backing(type="int")
+enum DisplayConnectionType {
+ Internal = 0,
+ External = 1
}
diff --git a/libs/input/android/os/BlockUntrustedTouchesMode.aidl b/libs/gui/aidl/android/gui/DisplayDecorationSupport.aidl
similarity index 60%
rename from libs/input/android/os/BlockUntrustedTouchesMode.aidl
rename to libs/gui/aidl/android/gui/DisplayDecorationSupport.aidl
index 9504e99..0230496 100644
--- a/libs/input/android/os/BlockUntrustedTouchesMode.aidl
+++ b/libs/gui/aidl/android/gui/DisplayDecorationSupport.aidl
@@ -1,5 +1,5 @@
/**
- * Copyright (c) 2020, The Android Open Source Project
+ * 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.
@@ -14,22 +14,12 @@
* limitations under the License.
*/
-package android.os;
+package android.gui;
-
-/**
- * Block untrusted touches feature mode.
- *
- * @hide
- */
-@Backing(type="int")
-enum BlockUntrustedTouchesMode {
- /** Feature is off. */
- DISABLED,
-
- /** Untrusted touches are flagged but not blocked. */
- PERMISSIVE,
-
- /** Untrusted touches are blocked. */
- BLOCK
+// TODO(b/222607970):
+// remove this aidl and use android.hardware.graphics.common.DisplayDecorationSupport
+/** @hide */
+parcelable DisplayDecorationSupport {
+ int format;
+ int alphaInterpretation;
}
diff --git a/libs/gui/aidl/android/gui/Rect.aidl b/libs/gui/aidl/android/gui/DisplayMode.aidl
similarity index 60%
copy from libs/gui/aidl/android/gui/Rect.aidl
copy to libs/gui/aidl/android/gui/DisplayMode.aidl
index 1b13761..3cd77f8 100644
--- a/libs/gui/aidl/android/gui/Rect.aidl
+++ b/libs/gui/aidl/android/gui/DisplayMode.aidl
@@ -16,20 +16,21 @@
package android.gui;
-// copied from libs/arect/include/android/rect.h
-// TODO(b/221473398):
-// use hardware/interfaces/graphics/common/aidl/android/hardware/graphics/common/Rect.aidl
+import android.gui.Size;
+
+// Mode supported by physical display.
+// Make sure to sync with libui DisplayMode.h
+
/** @hide */
-parcelable Rect {
- /// Minimum X coordinate of the rectangle.
- int left;
+parcelable DisplayMode {
+ int id;
+ Size resolution;
+ float xDpi = 0.0f;
+ float yDpi = 0.0f;
- /// Minimum Y coordinate of the rectangle.
- int top;
-
- /// Maximum X coordinate of the rectangle.
- int right;
-
- /// Maximum Y coordinate of the rectangle.
- int bottom;
+ float refreshRate = 0.0f;
+ long appVsyncOffset = 0;
+ long sfVsyncOffset = 0;
+ long presentationDeadline = 0;
+ int group = -1;
}
diff --git a/libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl b/libs/gui/aidl/android/gui/DisplayModeSpecs.aidl
similarity index 64%
copy from libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl
copy to libs/gui/aidl/android/gui/DisplayModeSpecs.aidl
index 6929a6c..fb4fcdf 100644
--- a/libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl
+++ b/libs/gui/aidl/android/gui/DisplayModeSpecs.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * 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.
@@ -14,15 +14,14 @@
* limitations under the License.
*/
-package android.content.pm;
+package android.gui;
-import android.content.pm.PackageChangeEvent;
-
-/**
- * This is a non-blocking notification when a package has changed.
- *
- * @hide
- */
-oneway interface IPackageChangeObserver {
- void onPackageChanged(in PackageChangeEvent event);
+/** @hide */
+parcelable DisplayModeSpecs {
+ int defaultMode;
+ boolean allowGroupSwitching;
+ float primaryRefreshRateMin;
+ float primaryRefreshRateMax;
+ float appRequestRefreshRateMin;
+ float appRequestRefreshRateMax;
}
diff --git a/libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl b/libs/gui/aidl/android/gui/DisplayPrimaries.aidl
similarity index 64%
copy from libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl
copy to libs/gui/aidl/android/gui/DisplayPrimaries.aidl
index 6929a6c..dbf668c 100644
--- a/libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl
+++ b/libs/gui/aidl/android/gui/DisplayPrimaries.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * 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.
@@ -14,15 +14,20 @@
* limitations under the License.
*/
-package android.content.pm;
+package android.gui;
-import android.content.pm.PackageChangeEvent;
+// copied from libui ConfigStoreTypes.h
-/**
- * This is a non-blocking notification when a package has changed.
- *
- * @hide
- */
-oneway interface IPackageChangeObserver {
- void onPackageChanged(in PackageChangeEvent event);
+/** @hide */
+parcelable DisplayPrimaries {
+ parcelable CieXyz {
+ float X;
+ float Y;
+ float Z;
+ }
+
+ CieXyz red;
+ CieXyz green;
+ CieXyz blue;
+ CieXyz white;
}
diff --git a/libs/gui/aidl/android/gui/DisplayedFrameStats.aidl b/libs/gui/aidl/android/gui/DisplayedFrameStats.aidl
new file mode 100644
index 0000000..f4b6dad
--- /dev/null
+++ b/libs/gui/aidl/android/gui/DisplayedFrameStats.aidl
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+package android.gui;
+
+/** @hide */
+parcelable DisplayedFrameStats {
+ /* The number of frames represented by this sample. */
+ long numFrames = 0;
+
+ /* A histogram counting how many times a pixel of a given value was displayed onscreen for
+ * FORMAT_COMPONENT_0. The buckets of the histogram are evenly weighted, the number of buckets
+ * is device specific. eg, for RGBA_8888, if sampleComponent0 is {10, 6, 4, 1} this means that
+ * 10 red pixels were displayed onscreen in range 0x00->0x3F, 6 red pixels
+ * were displayed onscreen in range 0x40->0x7F, etc.
+ */
+ long[] component_0_sample;
+
+ /* The same sample definition as sampleComponent0, but for FORMAT_COMPONENT_1. */
+ long[] component_1_sample;
+
+ /* The same sample definition as sampleComponent0, but for FORMAT_COMPONENT_2. */
+ long[] component_2_sample;
+
+ /* The same sample definition as sampleComponent0, but for FORMAT_COMPONENT_3. */
+ long[] component_3_sample;
+}
diff --git a/libs/gui/aidl/android/gui/DynamicDisplayInfo.aidl b/libs/gui/aidl/android/gui/DynamicDisplayInfo.aidl
new file mode 100644
index 0000000..57e6081
--- /dev/null
+++ b/libs/gui/aidl/android/gui/DynamicDisplayInfo.aidl
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+package android.gui;
+
+import android.gui.DisplayMode;
+import android.gui.HdrCapabilities;
+
+// Information about a physical display which may change on hotplug reconnect.
+// Make sure to sync with libui DynamicDisplayInfo.h
+
+/** @hide */
+parcelable DynamicDisplayInfo {
+ List<DisplayMode> supportedDisplayModes;
+
+ int activeDisplayModeId;
+
+ int[] supportedColorModes;
+ int activeColorMode;
+ HdrCapabilities hdrCapabilities;
+
+ // True if the display reports support for HDMI 2.1 Auto Low Latency Mode.
+ // For more information, see the HDMI 2.1 specification.
+ boolean autoLowLatencyModeSupported;
+
+ // True if the display reports support for Game Content Type.
+ // For more information, see the HDMI 1.4 specification.
+ boolean gameContentTypeSupported;
+
+ // The boot display mode preferred by the implementation.
+ int preferredBootDisplayMode;
+}
diff --git a/libs/gui/aidl/android/gui/Rect.aidl b/libs/gui/aidl/android/gui/FrameEvent.aidl
similarity index 60%
copy from libs/gui/aidl/android/gui/Rect.aidl
copy to libs/gui/aidl/android/gui/FrameEvent.aidl
index 1b13761..aaabdb5 100644
--- a/libs/gui/aidl/android/gui/Rect.aidl
+++ b/libs/gui/aidl/android/gui/FrameEvent.aidl
@@ -16,20 +16,20 @@
package android.gui;
-// copied from libs/arect/include/android/rect.h
-// TODO(b/221473398):
-// use hardware/interfaces/graphics/common/aidl/android/hardware/graphics/common/Rect.aidl
+// Identifiers for all the events that may be recorded or reported.
+
/** @hide */
-parcelable Rect {
- /// Minimum X coordinate of the rectangle.
- int left;
-
- /// Minimum Y coordinate of the rectangle.
- int top;
-
- /// Maximum X coordinate of the rectangle.
- int right;
-
- /// Maximum Y coordinate of the rectangle.
- int bottom;
+@Backing(type="int")
+enum FrameEvent {
+ POSTED = 0,
+ REQUESTED_PRESENT = 1,
+ LATCH = 2,
+ ACQUIRE = 3,
+ FIRST_REFRESH_START = 4,
+ LAST_REFRESH_START = 5,
+ GPU_COMPOSITION_DONE = 6,
+ DISPLAY_PRESENT = 7,
+ DEQUEUE_READY = 8,
+ RELEASE = 9,
+ EVENT_COUNT = 10 // Not an actual event.
}
diff --git a/libs/gui/aidl/android/gui/FrameStats.aidl b/libs/gui/aidl/android/gui/FrameStats.aidl
new file mode 100644
index 0000000..a145e74
--- /dev/null
+++ b/libs/gui/aidl/android/gui/FrameStats.aidl
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+package android.gui;
+
+// Make sure to sync with libui FrameStats.h
+
+/** @hide */
+parcelable FrameStats {
+ /*
+ * Approximate refresh time, in nanoseconds.
+ */
+ long refreshPeriodNano;
+
+ /*
+ * The times in nanoseconds for when the frame contents were posted by the producer (e.g.
+ * the application). They are either explicitly set or defaulted to the time when
+ * Surface::queueBuffer() was called.
+ */
+ long[] desiredPresentTimesNano;
+
+ /*
+ * The times in milliseconds for when the frame contents were presented on the screen.
+ */
+ long[] actualPresentTimesNano;
+
+ /*
+ * The times in nanoseconds for when the frame contents were ready to be presented. Note that
+ * a frame can be posted and still it contents being rendered asynchronously in GL. In such a
+ * case these are the times when the frame contents were completely rendered (i.e. their fences
+ * signaled).
+ */
+ long[] frameReadyTimesNano;
+}
diff --git a/libs/gui/include/gui/FrameTimelineInfo.h b/libs/gui/aidl/android/gui/FrameTimelineInfo.aidl
similarity index 69%
rename from libs/gui/include/gui/FrameTimelineInfo.h
rename to libs/gui/aidl/android/gui/FrameTimelineInfo.aidl
index 255ce56..6ffe466 100644
--- a/libs/gui/include/gui/FrameTimelineInfo.h
+++ b/libs/gui/aidl/android/gui/FrameTimelineInfo.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright 2021 The Android Open Source Project
+ * 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.
@@ -14,36 +14,23 @@
* limitations under the License.
*/
-#pragma once
+package android.gui;
-#include <stdint.h>
-
-#include <binder/Parcel.h>
-
-namespace android {
-
-struct FrameTimelineInfo {
+/** @hide */
+parcelable FrameTimelineInfo {
// Needs to be in sync with android.graphics.FrameInfo.INVALID_VSYNC_ID in java
- static constexpr int64_t INVALID_VSYNC_ID = -1;
+ const long INVALID_VSYNC_ID = -1;
// The vsync id that was used to start the transaction
- int64_t vsyncId = INVALID_VSYNC_ID;
+ long vsyncId = INVALID_VSYNC_ID;
// The id of the input event that caused this buffer
// Default is android::os::IInputConstants::INVALID_INPUT_EVENT_ID = 0
// We copy the value of the input event ID instead of including the header, because libgui
// header libraries containing FrameTimelineInfo must be available to vendors, but libinput is
// not directly vendor available.
- int32_t inputEventId = 0;
+ int inputEventId = 0;
// The current time in nanoseconds the application started to render the frame.
- int64_t startTimeNanos = 0;
-
- status_t write(Parcel& output) const;
- status_t read(const Parcel& input);
-
- void merge(const FrameTimelineInfo& other);
- void clear();
-};
-
-} // namespace android
+ long startTimeNanos = 0;
+}
diff --git a/libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl b/libs/gui/aidl/android/gui/HdrCapabilities.aidl
similarity index 64%
copy from libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl
copy to libs/gui/aidl/android/gui/HdrCapabilities.aidl
index 6929a6c..9d06da9 100644
--- a/libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl
+++ b/libs/gui/aidl/android/gui/HdrCapabilities.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * 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.
@@ -14,15 +14,14 @@
* limitations under the License.
*/
-package android.content.pm;
+package android.gui;
-import android.content.pm.PackageChangeEvent;
+// Make sure to sync with libui HdrCapabilities.h
-/**
- * This is a non-blocking notification when a package has changed.
- *
- * @hide
- */
-oneway interface IPackageChangeObserver {
- void onPackageChanged(in PackageChangeEvent event);
+/** @hide */
+parcelable HdrCapabilities {
+ int[] supportedHdrTypes;
+ float maxLuminance;
+ float maxAverageLuminance;
+ float minLuminance;
}
diff --git a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
index b31b37b..730d758 100644
--- a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
+++ b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
@@ -16,39 +16,99 @@
package android.gui;
-import android.gui.DisplayCaptureArgs;
+import android.gui.Color;
+import android.gui.CompositionPreference;
+import android.gui.ContentSamplingAttributes;
import android.gui.DisplayBrightness;
+import android.gui.DisplayCaptureArgs;
+import android.gui.DisplayDecorationSupport;
+import android.gui.DisplayedFrameStats;
+import android.gui.DisplayModeSpecs;
+import android.gui.DisplayPrimaries;
import android.gui.DisplayState;
import android.gui.DisplayStatInfo;
+import android.gui.DynamicDisplayInfo;
+import android.gui.FrameEvent;
+import android.gui.FrameStats;
+import android.gui.IDisplayEventConnection;
+import android.gui.IFpsListener;
import android.gui.IHdrLayerInfoListener;
-import android.gui.LayerCaptureArgs;
+import android.gui.IRegionSamplingListener;
import android.gui.IScreenCaptureListener;
+import android.gui.ISurfaceComposerClient;
+import android.gui.ITransactionTraceListener;
+import android.gui.ITunnelModeEnabledListener;
+import android.gui.IWindowInfosListener;
+import android.gui.LayerCaptureArgs;
+import android.gui.LayerDebugInfo;
+import android.gui.PullAtomData;
+import android.gui.ARect;
+import android.gui.StaticDisplayInfo;
/** @hide */
interface ISurfaceComposer {
- /* create a virtual display
+ enum VsyncSource {
+ eVsyncSourceApp = 0,
+ eVsyncSourceSurfaceFlinger = 1
+ }
+
+ enum EventRegistration {
+ modeChanged = 1 << 0,
+ frameRateOverride = 1 << 1,
+ }
+
+ /**
+ * Signal that we're done booting.
+ * Requires ACCESS_SURFACE_FLINGER permission
+ */
+ // Note this must be the 1st method, so IBinder::FIRST_CALL_TRANSACTION
+ // is assigned, as it is called from Java by ActivityManagerService.
+ void bootFinished();
+
+ /**
+ * Create a display event connection
+ */
+ @nullable IDisplayEventConnection createDisplayEventConnection(VsyncSource vsyncSource,
+ EventRegistration eventRegistration);
+
+ /**
+ * Create a connection with SurfaceFlinger.
+ */
+ @nullable ISurfaceComposerClient createConnection();
+
+ /**
+ * Create a virtual display
* requires ACCESS_SURFACE_FLINGER permission.
*/
@nullable IBinder createDisplay(@utf8InCpp String displayName, boolean secure);
- /* destroy a virtual display
+ /**
+ * Destroy a virtual display
* requires ACCESS_SURFACE_FLINGER permission.
*/
void destroyDisplay(IBinder display);
- /* get stable IDs for connected physical displays.
+ /**
+ * Get stable IDs for connected physical displays.
*/
long[] getPhysicalDisplayIds();
long getPrimaryPhysicalDisplayId();
- /* get token for a physical display given its stable ID obtained via getPhysicalDisplayIds or a
- * DisplayEventReceiver hotplug event.
+ /**
+ * Get token for a physical display given its stable ID obtained via getPhysicalDisplayIds or
+ * a DisplayEventReceiver hotplug event.
*/
@nullable IBinder getPhysicalDisplayToken(long displayId);
- /* set display power mode. depending on the mode, it can either trigger
+ /**
+ * Returns the frame timestamps supported by SurfaceFlinger.
+ */
+ FrameEvent[] getSupportedFrameTimestamps();
+
+ /**
+ * Set display power mode. depending on the mode, it can either trigger
* screen on, off or low power mode and wait for it to complete.
* requires ACCESS_SURFACE_FLINGER permission.
*/
@@ -60,12 +120,31 @@
* video frames */
DisplayStatInfo getDisplayStats(@nullable IBinder display);
- /**
+ /**
* Get transactional state of given display.
*/
DisplayState getDisplayState(IBinder display);
/**
+ * Gets immutable information about given physical display.
+ */
+ StaticDisplayInfo getStaticDisplayInfo(IBinder display);
+
+ /**
+ * Gets dynamic information about given physical display.
+ */
+ DynamicDisplayInfo getDynamicDisplayInfo(IBinder display);
+
+ DisplayPrimaries getDisplayNativePrimaries(IBinder display);
+
+ void setActiveColorMode(IBinder display, int colorMode);
+
+ /**
+ * Sets the user-preferred display mode that a device should boot in.
+ */
+ void setBootDisplayMode(IBinder display, int displayModeId);
+
+ /**
* Clears the user-preferred display mode. The device should now boot in system preferred
* display mode.
*/
@@ -110,7 +189,9 @@
* match the size of the output buffer.
*/
void captureDisplay(in DisplayCaptureArgs args, IScreenCaptureListener listener);
+
void captureDisplayById(long displayId, IScreenCaptureListener listener);
+
/**
* Capture a subtree of the layer hierarchy, potentially ignoring the root node.
* This requires READ_FRAME_BUFFER permission. This function will fail if there
@@ -118,13 +199,163 @@
*/
void captureLayers(in LayerCaptureArgs args, IScreenCaptureListener listener);
- /*
+ /**
+ * Clears the frame statistics for animations.
+ *
+ * Requires the ACCESS_SURFACE_FLINGER permission.
+ */
+ void clearAnimationFrameStats();
+
+ /**
+ * Gets the frame statistics for animations.
+ *
+ * Requires the ACCESS_SURFACE_FLINGER permission.
+ */
+ FrameStats getAnimationFrameStats();
+
+ /**
+ * Overrides the supported HDR modes for the given display device.
+ *
+ * Requires the ACCESS_SURFACE_FLINGER permission.
+ */
+ void overrideHdrTypes(IBinder display, in int[] hdrTypes);
+
+ /**
+ * Pulls surfaceflinger atoms global stats and layer stats to pipe to statsd.
+ *
+ * Requires the calling uid be from system server.
+ */
+ PullAtomData onPullAtom(int atomId);
+
+ oneway void enableVSyncInjections(boolean enable);
+
+ oneway void injectVSync(long when);
+
+ /**
+ * Gets the list of active layers in Z order for debugging purposes
+ *
+ * Requires the ACCESS_SURFACE_FLINGER permission.
+ */
+ List<LayerDebugInfo> getLayerDebugInfo();
+
+ boolean getColorManagement();
+
+ /**
+ * Gets the composition preference of the default data space and default pixel format,
+ * as well as the wide color gamut data space and wide color gamut pixel format.
+ * If the wide color gamut data space is V0_SRGB, then it implies that the platform
+ * has no wide color gamut support.
+ *
+ */
+ CompositionPreference getCompositionPreference();
+
+ /**
+ * Requires the ACCESS_SURFACE_FLINGER permission.
+ */
+ ContentSamplingAttributes getDisplayedContentSamplingAttributes(IBinder display);
+
+ /**
+ * Turns on the color sampling engine on the display.
+ *
+ * Requires the ACCESS_SURFACE_FLINGER permission.
+ */
+ void setDisplayContentSamplingEnabled(IBinder display, boolean enable, byte componentMask, long maxFrames);
+
+ /**
+ * Returns statistics on the color profile of the last frame displayed for a given display
+ *
+ * Requires the ACCESS_SURFACE_FLINGER permission.
+ */
+ DisplayedFrameStats getDisplayedContentSample(IBinder display, long maxFrames, long timestamp);
+
+ /**
+ * Gets whether SurfaceFlinger can support protected content in GPU composition.
+ */
+ boolean getProtectedContentSupport();
+
+ /**
* Queries whether the given display is a wide color display.
* Requires the ACCESS_SURFACE_FLINGER permission.
*/
boolean isWideColorDisplay(IBinder token);
- /*
+ /**
+ * Registers a listener to stream median luma updates from SurfaceFlinger.
+ *
+ * The sampling area is bounded by both samplingArea and the given stopLayerHandle
+ * (i.e., only layers behind the stop layer will be captured and sampled).
+ *
+ * Multiple listeners may be provided so long as they have independent listeners.
+ * If multiple listeners are provided, the effective sampling region for each listener will
+ * be bounded by whichever stop layer has a lower Z value.
+ *
+ * Requires the same permissions as captureLayers and captureScreen.
+ */
+ void addRegionSamplingListener(in ARect samplingArea, @nullable IBinder stopLayerHandle, IRegionSamplingListener listener);
+
+ /**
+ * Removes a listener that was streaming median luma updates from SurfaceFlinger.
+ */
+ void removeRegionSamplingListener(IRegionSamplingListener listener);
+
+ /**
+ * Registers a listener that streams fps updates from SurfaceFlinger.
+ *
+ * The listener will stream fps updates for the layer tree rooted at the layer denoted by the
+ * task ID, i.e., the layer must have the task ID as part of its layer metadata with key
+ * METADATA_TASK_ID. If there is no such layer, then no fps is expected to be reported.
+ *
+ * Multiple listeners may be supported.
+ *
+ * Requires the READ_FRAME_BUFFER permission.
+ */
+ void addFpsListener(int taskId, IFpsListener listener);
+
+ /**
+ * Removes a listener that was streaming fps updates from SurfaceFlinger.
+ */
+ void removeFpsListener(IFpsListener listener);
+
+ /**
+ * Registers a listener to receive tunnel mode enabled updates from SurfaceFlinger.
+ *
+ * Requires ACCESS_SURFACE_FLINGER permission.
+ */
+ void addTunnelModeEnabledListener(ITunnelModeEnabledListener listener);
+
+ /**
+ * Removes a listener that was receiving tunnel mode enabled updates from SurfaceFlinger.
+ *
+ * Requires ACCESS_SURFACE_FLINGER permission.
+ */
+ void removeTunnelModeEnabledListener(ITunnelModeEnabledListener listener);
+
+ /**
+ * Sets the refresh rate boundaries for the display.
+ *
+ * The primary refresh rate range represents display manager's general guidance on the display
+ * modes we'll consider when switching refresh rates. Unless we get an explicit signal from an
+ * app, we should stay within this range.
+ *
+ * The app request refresh rate range allows us to consider more display modes when switching
+ * refresh rates. Although we should generally stay within the primary range, specific
+ * considerations, such as layer frame rate settings specified via the setFrameRate() api, may
+ * cause us to go outside the primary range. We never go outside the app request range. The app
+ * request range will be greater than or equal to the primary refresh rate range, never smaller.
+ *
+ * defaultMode is used to narrow the list of display modes SurfaceFlinger will consider
+ * switching between. Only modes with a mode group and resolution matching defaultMode
+ * will be considered for switching. The defaultMode corresponds to an ID of mode in the list
+ * of supported modes returned from getDynamicDisplayInfo().
+ */
+ void setDesiredDisplayModeSpecs(
+ IBinder displayToken, int defaultMode,
+ boolean allowGroupSwitching, float primaryRefreshRateMin, float primaryRefreshRateMax,
+ float appRequestRefreshRateMin, float appRequestRefreshRateMax);
+
+ DisplayModeSpecs getDesiredDisplayModeSpecs(IBinder displayToken);
+
+ /**
* Gets whether brightness operations are supported on a display.
*
* displayToken
@@ -138,7 +369,7 @@
*/
boolean getDisplayBrightnessSupport(IBinder displayToken);
- /*
+ /**
* Sets the brightness of a display.
*
* displayToken
@@ -153,7 +384,7 @@
*/
void setDisplayBrightness(IBinder displayToken, in DisplayBrightness brightness);
- /*
+ /**
* Adds a listener that receives HDR layer information. This is used in combination
* with setDisplayBrightness to adjust the display brightness depending on factors such
* as whether or not HDR is in use.
@@ -162,7 +393,7 @@
*/
void addHdrLayerInfoListener(IBinder displayToken, IHdrLayerInfoListener listener);
- /*
+ /**
* Removes a listener that was added with addHdrLayerInfoListener.
*
* Returns NO_ERROR upon success, NAME_NOT_FOUND if the display is invalid, and BAD_VALUE if
@@ -171,7 +402,7 @@
*/
void removeHdrLayerInfoListener(IBinder displayToken, IHdrLayerInfoListener listener);
- /*
+ /**
* Sends a power boost to the composer. This function is asynchronous.
*
* boostId
@@ -179,5 +410,78 @@
*
* Returns NO_ERROR upon success.
*/
- void notifyPowerBoost(int boostId);
+ oneway void notifyPowerBoost(int boostId);
+
+ /*
+ * Sets the global configuration for all the shadows drawn by SurfaceFlinger. Shadow follows
+ * material design guidelines.
+ *
+ * ambientColor
+ * Color to the ambient shadow. The alpha is premultiplied.
+ *
+ * spotColor
+ * Color to the spot shadow. The alpha is premultiplied. The position of the spot shadow
+ * depends on the light position.
+ *
+ * lightPosY/lightPosZ
+ * Position of the light used to cast the spot shadow. The X value is always the display
+ * width / 2.
+ *
+ * lightRadius
+ * Radius of the light casting the shadow.
+ */
+ oneway void setGlobalShadowSettings(in Color ambientColor, in Color spotColor, float lightPosY, float lightPosZ, float lightRadius);
+
+ /**
+ * Gets whether a display supports DISPLAY_DECORATION layers.
+ *
+ * displayToken
+ * The token of the display.
+ * outSupport
+ * An output parameter for whether/how the display supports
+ * DISPLAY_DECORATION layers.
+ *
+ * Returns NO_ERROR upon success. Otherwise,
+ * NAME_NOT_FOUND if the display is invalid, or
+ * BAD_VALUE if the output parameter is invalid.
+ */
+ @nullable DisplayDecorationSupport getDisplayDecorationSupport(IBinder displayToken);
+
+ /**
+ * Set the override frame rate for a specified uid by GameManagerService.
+ * Passing the frame rate and uid to SurfaceFlinger to update the override mapping
+ * in the scheduler.
+ */
+ void setOverrideFrameRate(int uid, float frameRate);
+
+ /**
+ * Adds a TransactionTraceListener to listen for transaction tracing state updates.
+ */
+ void addTransactionTraceListener(ITransactionTraceListener listener);
+
+ /**
+ * Gets priority of the RenderEngine in SurfaceFlinger.
+ */
+ int getGpuContextPriority();
+
+ /**
+ * Gets the number of buffers SurfaceFlinger would need acquire. This number
+ * would be propagated to the client via MIN_UNDEQUEUED_BUFFERS so that the
+ * client could allocate enough buffers to match SF expectations of the
+ * pipeline depth. SurfaceFlinger will make sure that it will give the app at
+ * least the time configured as the 'appDuration' before trying to latch
+ * the buffer.
+ *
+ * The total buffers needed for a given configuration is basically the
+ * numbers of vsyncs a single buffer is used across the stack. For the default
+ * configuration a buffer is held ~1 vsync by the app, ~1 vsync by SurfaceFlinger
+ * and 1 vsync by the display. The extra buffers are calculated as the
+ * number of additional buffers on top of the 2 buffers already present
+ * in MIN_UNDEQUEUED_BUFFERS.
+ */
+ int getMaxAcquiredBufferCount();
+
+ void addWindowInfosListener(IWindowInfosListener windowInfosListener);
+
+ void removeWindowInfosListener(IWindowInfosListener windowInfosListener);
}
diff --git a/libs/gui/aidl/android/gui/ISurfaceComposerClient.aidl b/libs/gui/aidl/android/gui/ISurfaceComposerClient.aidl
new file mode 100644
index 0000000..71933aa
--- /dev/null
+++ b/libs/gui/aidl/android/gui/ISurfaceComposerClient.aidl
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+package android.gui;
+
+import android.gui.CreateSurfaceResult;
+import android.gui.FrameStats;
+import android.gui.LayerMetadata;
+import android.gui.MirrorSurfaceResult;
+
+/** @hide */
+interface ISurfaceComposerClient {
+
+ // flags for createSurface()
+ // (keep in sync with SurfaceControl.java)
+ const int eHidden = 0x00000004;
+ const int eDestroyBackbuffer = 0x00000020;
+ const int eSkipScreenshot = 0x00000040;
+ const int eSecure = 0x00000080;
+ const int eNonPremultiplied = 0x00000100;
+ const int eOpaque = 0x00000400;
+ const int eProtectedByApp = 0x00000800;
+ const int eProtectedByDRM = 0x00001000;
+ const int eCursorWindow = 0x00002000;
+ const int eNoColorFill = 0x00004000;
+
+ const int eFXSurfaceBufferQueue = 0x00000000;
+ const int eFXSurfaceEffect = 0x00020000;
+ const int eFXSurfaceBufferState = 0x00040000;
+ const int eFXSurfaceContainer = 0x00080000;
+ const int eFXSurfaceMask = 0x000F0000;
+
+ /**
+ * Requires ACCESS_SURFACE_FLINGER permission
+ */
+ CreateSurfaceResult createSurface(@utf8InCpp String name, int flags, @nullable IBinder parent, in LayerMetadata metadata);
+
+ /**
+ * Requires ACCESS_SURFACE_FLINGER permission
+ */
+ void clearLayerFrameStats(IBinder handle);
+
+ /**
+ * Requires ACCESS_SURFACE_FLINGER permission
+ */
+ FrameStats getLayerFrameStats(IBinder handle);
+
+ MirrorSurfaceResult mirrorSurface(IBinder mirrorFromHandle);
+}
diff --git a/libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl b/libs/gui/aidl/android/gui/LayerDebugInfo.aidl
similarity index 63%
copy from libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl
copy to libs/gui/aidl/android/gui/LayerDebugInfo.aidl
index 6929a6c..faca980 100644
--- a/libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl
+++ b/libs/gui/aidl/android/gui/LayerDebugInfo.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * 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.
@@ -14,15 +14,6 @@
* limitations under the License.
*/
-package android.content.pm;
+package android.gui;
-import android.content.pm.PackageChangeEvent;
-
-/**
- * This is a non-blocking notification when a package has changed.
- *
- * @hide
- */
-oneway interface IPackageChangeObserver {
- void onPackageChanged(in PackageChangeEvent event);
-}
+parcelable LayerDebugInfo cpp_header "gui/LayerDebugInfo.h";
diff --git a/libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl b/libs/gui/aidl/android/gui/LayerMetadata.aidl
similarity index 63%
copy from libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl
copy to libs/gui/aidl/android/gui/LayerMetadata.aidl
index 6929a6c..1368ac5 100644
--- a/libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl
+++ b/libs/gui/aidl/android/gui/LayerMetadata.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * 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.
@@ -14,15 +14,6 @@
* limitations under the License.
*/
-package android.content.pm;
+package android.gui;
-import android.content.pm.PackageChangeEvent;
-
-/**
- * This is a non-blocking notification when a package has changed.
- *
- * @hide
- */
-oneway interface IPackageChangeObserver {
- void onPackageChanged(in PackageChangeEvent event);
-}
+parcelable LayerMetadata cpp_header "gui/LayerMetadata.h";
diff --git a/libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl b/libs/gui/aidl/android/gui/MirrorSurfaceResult.aidl
similarity index 64%
copy from libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl
copy to libs/gui/aidl/android/gui/MirrorSurfaceResult.aidl
index 6929a6c..9fac3e8 100644
--- a/libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl
+++ b/libs/gui/aidl/android/gui/MirrorSurfaceResult.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * 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.
@@ -14,15 +14,10 @@
* limitations under the License.
*/
-package android.content.pm;
+package android.gui;
-import android.content.pm.PackageChangeEvent;
-
-/**
- * This is a non-blocking notification when a package has changed.
- *
- * @hide
- */
-oneway interface IPackageChangeObserver {
- void onPackageChanged(in PackageChangeEvent event);
+/** @hide */
+parcelable MirrorSurfaceResult {
+ IBinder handle;
+ int layerId;
}
diff --git a/libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl b/libs/gui/aidl/android/gui/PullAtomData.aidl
similarity index 64%
copy from libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl
copy to libs/gui/aidl/android/gui/PullAtomData.aidl
index 6929a6c..14d33c6 100644
--- a/libs/binder/aidl/android/content/pm/IPackageChangeObserver.aidl
+++ b/libs/gui/aidl/android/gui/PullAtomData.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * 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.
@@ -14,15 +14,10 @@
* limitations under the License.
*/
-package android.content.pm;
+package android.gui;
-import android.content.pm.PackageChangeEvent;
-
-/**
- * This is a non-blocking notification when a package has changed.
- *
- * @hide
- */
-oneway interface IPackageChangeObserver {
- void onPackageChanged(in PackageChangeEvent event);
+/** @hide */
+parcelable PullAtomData {
+ @utf8InCpp String data;
+ boolean success;
}
diff --git a/libs/gui/aidl/android/gui/Rect.aidl b/libs/gui/aidl/android/gui/StaticDisplayInfo.aidl
similarity index 60%
copy from libs/gui/aidl/android/gui/Rect.aidl
copy to libs/gui/aidl/android/gui/StaticDisplayInfo.aidl
index 1b13761..0ccda56 100644
--- a/libs/gui/aidl/android/gui/Rect.aidl
+++ b/libs/gui/aidl/android/gui/StaticDisplayInfo.aidl
@@ -16,20 +16,15 @@
package android.gui;
-// copied from libs/arect/include/android/rect.h
-// TODO(b/221473398):
-// use hardware/interfaces/graphics/common/aidl/android/hardware/graphics/common/Rect.aidl
+import android.gui.DisplayConnectionType;
+import android.gui.DeviceProductInfo;
+import android.gui.Rotation;
+
/** @hide */
-parcelable Rect {
- /// Minimum X coordinate of the rectangle.
- int left;
-
- /// Minimum Y coordinate of the rectangle.
- int top;
-
- /// Maximum X coordinate of the rectangle.
- int right;
-
- /// Maximum Y coordinate of the rectangle.
- int bottom;
+parcelable StaticDisplayInfo {
+ DisplayConnectionType connectionType = DisplayConnectionType.Internal;
+ float density;
+ boolean secure;
+ @nullable DeviceProductInfo deviceProductInfo;
+ Rotation installOrientation = Rotation.Rotation0;
}
diff --git a/libs/gui/fuzzer/Android.bp b/libs/gui/fuzzer/Android.bp
new file mode 100644
index 0000000..f1c529d
--- /dev/null
+++ b/libs/gui/fuzzer/Android.bp
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2021 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.
+ */
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
+cc_defaults {
+ name: "libgui_fuzzer_defaults",
+ static_libs: [
+ "android.hidl.token@1.0-utils",
+ "libbinder_random_parcel",
+ "libgui_aidl_static",
+ "libgui_window_info_static",
+ "libpdx",
+ "libgmock",
+ "libgui_mocks",
+ "libgmock_ndk",
+ "libgmock_main",
+ "libgtest_ndk_c++",
+ "libgmock_main_ndk",
+ "librenderengine_mocks",
+ "perfetto_trace_protos",
+ "libcompositionengine_mocks",
+ "perfetto_trace_protos",
+ ],
+ shared_libs: [
+ "android.hardware.configstore@1.0",
+ "android.hardware.configstore-utils",
+ "android.hardware.graphics.bufferqueue@1.0",
+ "android.hardware.graphics.bufferqueue@2.0",
+ "android.hardware.power-V2-cpp",
+ "android.hidl.token@1.0",
+ "libSurfaceFlingerProp",
+ "libgui",
+ "libbase",
+ "liblog",
+ "libEGL",
+ "libGLESv2",
+ "libbinder",
+ "libcutils",
+ "libhidlbase",
+ "libinput",
+ "libui",
+ "libutils",
+ "libnativewindow",
+ "libvndksupport",
+ "libbufferhubqueue",
+ ],
+ header_libs: [
+ "libdvr_headers",
+ "libui_fuzzableDataspaces_headers",
+ ],
+ fuzz_config: {
+ cc: [
+ "android-media-fuzzing-reports@google.com",
+ ],
+ componentid: 155276,
+ },
+}
+
+cc_fuzz {
+ name: "libgui_surfaceComposer_fuzzer",
+ srcs: [
+ "libgui_surfaceComposer_fuzzer.cpp",
+ ],
+ defaults: [
+ "libgui_fuzzer_defaults",
+ ],
+}
diff --git a/libs/gui/fuzzer/README.md b/libs/gui/fuzzer/README.md
new file mode 100644
index 0000000..c9e8b65
--- /dev/null
+++ b/libs/gui/fuzzer/README.md
@@ -0,0 +1,42 @@
+# Fuzzers for Libgui
+
+## Table of contents
++ [libgui_surfaceComposer_fuzzer](#SurfaceComposer)
+
+# <a name="libgui_surfaceComposer_fuzzer"></a> Fuzzer for SurfaceComposer
+
+SurfaceComposer supports the following parameters:
+1. SurfaceWidth (parameter name:`width`)
+2. SurfaceHeight (parameter name:`height`)
+3. TransactionStateFlags (parameter name:`flags`)
+4. TransformHint (parameter name:`outTransformHint`)
+5. SurfacePixelFormat (parameter name:`format`)
+6. LayerId (parameter name:`outLayerId`)
+7. SurfaceComposerTags (parameter name:`surfaceTag`)
+8. PowerBoostID (parameter name:`boostId`)
+9. VsyncSource (parameter name:`vsyncSource`)
+10. EventRegistrationFlags (parameter name:`eventRegistration`)
+11. FrameRateCompatibility (parameter name:`frameRateCompatibility`)
+12. ChangeFrameRateStrategy (parameter name:`changeFrameRateStrategy`)
+13. HdrTypes (parameter name:`hdrTypes`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+|`surfaceTag` | 0.`BnSurfaceComposer::BOOT_FINISHED`, 1.`BnSurfaceComposer::CREATE_CONNECTION`, 2.`BnSurfaceComposer::GET_STATIC_DISPLAY_INFO`, 3.`BnSurfaceComposer::CREATE_DISPLAY_EVENT_CONNECTION`, 4.`BnSurfaceComposer::CREATE_DISPLAY`, 5.`BnSurfaceComposer::DESTROY_DISPLAY`, 6.`BnSurfaceComposer::GET_PHYSICAL_DISPLAY_TOKEN`, 7.`BnSurfaceComposer::SET_TRANSACTION_STATE`, 8.`BnSurfaceComposer::AUTHENTICATE_SURFACE`, 9.`BnSurfaceComposer::GET_SUPPORTED_FRAME_TIMESTAMPS`, 10.`BnSurfaceComposer::GET_DISPLAY_STATE`, 11.`BnSurfaceComposer::CAPTURE_DISPLAY`, 12.`BnSurfaceComposer::CAPTURE_LAYERS`, 13.`BnSurfaceComposer::CLEAR_ANIMATION_FRAME_STATS`, 14.`BnSurfaceComposer::GET_ANIMATION_FRAME_STATS`, 15.`BnSurfaceComposer::SET_POWER_MODE`, 16.`BnSurfaceComposer::GET_DISPLAY_STATS`, 17.`BnSurfaceComposer::SET_ACTIVE_COLOR_MODE`, 18.`BnSurfaceComposer::ENABLE_VSYNC_INJECTIONS`, 19.`BnSurfaceComposer::INJECT_VSYNC`, 20.`BnSurfaceComposer::GET_LAYER_DEBUG_INFO`, 21.`BnSurfaceComposer::GET_COMPOSITION_PREFERENCE`, 22.`BnSurfaceComposer::GET_COLOR_MANAGEMENT`, 23.`BnSurfaceComposer::GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES`, 24.`BnSurfaceComposer::SET_DISPLAY_CONTENT_SAMPLING_ENABLED`, 25.`BnSurfaceComposer::GET_DISPLAYED_CONTENT_SAMPLE`, 26.`BnSurfaceComposer::GET_PROTECTED_CONTENT_SUPPORT`, 27.`BnSurfaceComposer::IS_WIDE_COLOR_DISPLAY`, 28.`BnSurfaceComposer::GET_DISPLAY_NATIVE_PRIMARIES`, 29.`BnSurfaceComposer::GET_PHYSICAL_DISPLAY_IDS`, 30.`BnSurfaceComposer::ADD_REGION_SAMPLING_LISTENER`, 31.`BnSurfaceComposer::REMOVE_REGION_SAMPLING_LISTENER`, 32.`BnSurfaceComposer::SET_DESIRED_DISPLAY_MODE_SPECS`, 33.`BnSurfaceComposer::GET_DESIRED_DISPLAY_MODE_SPECS`, 34.`BnSurfaceComposer::GET_DISPLAY_BRIGHTNESS_SUPPORT`, 35.`BnSurfaceComposer::SET_DISPLAY_BRIGHTNESS`, 36.`BnSurfaceComposer::CAPTURE_DISPLAY_BY_ID`, 37.`BnSurfaceComposer::NOTIFY_POWER_BOOST`, 38.`BnSurfaceComposer::SET_GLOBAL_SHADOW_SETTINGS`, 39.`BnSurfaceComposer::SET_AUTO_LOW_LATENCY_MODE`, 40.`BnSurfaceComposer::SET_GAME_CONTENT_TYPE`, 41.`BnSurfaceComposer::SET_FRAME_RATE`, 42.`BnSurfaceComposer::ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN`, 43.`BnSurfaceComposer::SET_FRAME_TIMELINE_INFO`, 44.`BnSurfaceComposer::ADD_TRANSACTION_TRACE_LISTENER`, 45.`BnSurfaceComposer::GET_GPU_CONTEXT_PRIORITY`, 46.`BnSurfaceComposer::GET_MAX_ACQUIRED_BUFFER_COUNT`, 47.`BnSurfaceComposer::GET_DYNAMIC_DISPLAY_INFO`, 48.`BnSurfaceComposer::ADD_FPS_LISTENER`, 49.`BnSurfaceComposer::REMOVE_FPS_LISTENER`, 50.`BnSurfaceComposer::OVERRIDE_HDR_TYPES`, 51.`BnSurfaceComposer::ADD_HDR_LAYER_INFO_LISTENER`, 52.`BnSurfaceComposer::REMOVE_HDR_LAYER_INFO_LISTENER`, 53.`BnSurfaceComposer::ON_PULL_ATOM`, 54.`BnSurfaceComposer::ADD_TUNNEL_MODE_ENABLED_LISTENER`, 55.`BnSurfaceComposer::REMOVE_TUNNEL_MODE_ENABLED_LISTENER` | Value obtained from FuzzedDataProvider|
+|`boostId`| 0.`hardware::power::Boost::INTERACTION`, 1.`hardware::power::Boost::DISPLAY_UPDATE_IMMINENT`, 2.`hardware::power::Boost::ML_ACC`, 3.`hardware::power::Boost::AUDIO_LAUNCH`, 4.`hardware::power::Boost::CAMERA_LAUNCH`, 5.`hardware::power::Boost::CAMERA_SHOT` |Value obtained from FuzzedDataProvider|
+|`vsyncSource`| 0.`ISurfaceComposer::eVsyncSourceApp`, 1.`ISurfaceComposer::eVsyncSourceSurfaceFlinger`, |Value obtained from FuzzedDataProvider|
+|`eventRegistration`| 0.`ISurfaceComposer::EventRegistration::modeChanged`, 1.`ISurfaceComposer::EventRegistration::frameRateOverride` |Value obtained from FuzzedDataProvider|
+|`frameRateCompatibility`| 0.`ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT`, 1.`ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE` |Value obtained from FuzzedDataProvider|
+|`changeFrameRateStrategy`| 0.`ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS`, 1.`ANATIVEWINDOW_CHANGE_FRAME_RATE_ALWAYS` |Value obtained from FuzzedDataProvider|
+|`hdrTypes`| 0.`ui::Hdr::DOLBY_VISION`, 1.`ui::Hdr::HDR10`, 2.`ui::Hdr::HLG`, 3.`ui::Hdr::HDR10_PLUS` |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) libgui_surfaceComposer_fuzzer
+```
+2. Run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/libgui_surfaceComposer_fuzzer/libgui_surfaceComposer_fuzzer
+```
diff --git a/libs/gui/fuzzer/libgui_fuzzer_utils.h b/libs/gui/fuzzer/libgui_fuzzer_utils.h
new file mode 100644
index 0000000..98e2ea3
--- /dev/null
+++ b/libs/gui/fuzzer/libgui_fuzzer_utils.h
@@ -0,0 +1,311 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <android/gui/BnRegionSamplingListener.h>
+#include <android/gui/BnSurfaceComposer.h>
+#include <android/gui/BnSurfaceComposerClient.h>
+#include <android/gui/IDisplayEventConnection.h>
+#include <android/gui/ISurfaceComposerClient.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <gmock/gmock.h>
+#include <gui/BLASTBufferQueue.h>
+#include <gui/DisplayEventDispatcher.h>
+#include <gui/IGraphicBufferProducer.h>
+#include <gui/LayerDebugInfo.h>
+#include <gui/LayerState.h>
+#include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
+#include <gui/bufferqueue/2.0/H2BGraphicBufferProducer.h>
+#include <ui/fuzzer/FuzzableDataspaces.h>
+
+namespace android {
+
+constexpr uint32_t kOrientation[] = {
+ ui::Transform::ROT_0, ui::Transform::FLIP_H, ui::Transform::FLIP_V,
+ ui::Transform::ROT_90, ui::Transform::ROT_180, ui::Transform::ROT_270,
+};
+
+Rect getRect(FuzzedDataProvider* fdp) {
+ const int32_t left = fdp->ConsumeIntegral<int32_t>();
+ const int32_t top = fdp->ConsumeIntegral<int32_t>();
+ const int32_t right = fdp->ConsumeIntegral<int32_t>();
+ const int32_t bottom = fdp->ConsumeIntegral<int32_t>();
+ return Rect(left, top, right, bottom);
+}
+
+gui::DisplayBrightness getBrightness(FuzzedDataProvider* fdp) {
+ static constexpr float kMinBrightness = 0;
+ static constexpr float kMaxBrightness = 1;
+ gui::DisplayBrightness brightness;
+ brightness.sdrWhitePoint =
+ fdp->ConsumeFloatingPointInRange<float>(kMinBrightness, kMaxBrightness);
+ brightness.sdrWhitePointNits =
+ fdp->ConsumeFloatingPointInRange<float>(kMinBrightness, kMaxBrightness);
+ brightness.displayBrightness =
+ fdp->ConsumeFloatingPointInRange<float>(kMinBrightness, kMaxBrightness);
+ brightness.displayBrightnessNits =
+ fdp->ConsumeFloatingPointInRange<float>(kMinBrightness, kMaxBrightness);
+ return brightness;
+}
+
+class FakeBnSurfaceComposer : public gui::BnSurfaceComposer {
+public:
+ MOCK_METHOD(binder::Status, bootFinished, (), (override));
+ MOCK_METHOD(binder::Status, createDisplayEventConnection,
+ (gui::ISurfaceComposer::VsyncSource, gui::ISurfaceComposer::EventRegistration,
+ sp<gui::IDisplayEventConnection>*),
+ (override));
+ MOCK_METHOD(binder::Status, createConnection, (sp<gui::ISurfaceComposerClient>*), (override));
+ MOCK_METHOD(binder::Status, createDisplay, (const std::string&, bool, sp<IBinder>*),
+ (override));
+ MOCK_METHOD(binder::Status, destroyDisplay, (const sp<IBinder>&), (override));
+ MOCK_METHOD(binder::Status, getPhysicalDisplayIds, (std::vector<int64_t>*), (override));
+ MOCK_METHOD(binder::Status, getPrimaryPhysicalDisplayId, (int64_t*), (override));
+ MOCK_METHOD(binder::Status, getPhysicalDisplayToken, (int64_t, sp<IBinder>*), (override));
+ MOCK_METHOD(binder::Status, setPowerMode, (const sp<IBinder>&, int), (override));
+ MOCK_METHOD(binder::Status, getSupportedFrameTimestamps, (std::vector<FrameEvent>*),
+ (override));
+ MOCK_METHOD(binder::Status, getDisplayStats, (const sp<IBinder>&, gui::DisplayStatInfo*),
+ (override));
+ MOCK_METHOD(binder::Status, getDisplayState, (const sp<IBinder>&, gui::DisplayState*),
+ (override));
+ MOCK_METHOD(binder::Status, getStaticDisplayInfo, (const sp<IBinder>&, gui::StaticDisplayInfo*),
+ (override));
+ MOCK_METHOD(binder::Status, getDynamicDisplayInfo,
+ (const sp<IBinder>&, gui::DynamicDisplayInfo*), (override));
+ MOCK_METHOD(binder::Status, getDisplayNativePrimaries,
+ (const sp<IBinder>&, gui::DisplayPrimaries*), (override));
+ MOCK_METHOD(binder::Status, setActiveColorMode, (const sp<IBinder>&, int), (override));
+ MOCK_METHOD(binder::Status, setBootDisplayMode, (const sp<IBinder>&, int), (override));
+ MOCK_METHOD(binder::Status, clearBootDisplayMode, (const sp<IBinder>&), (override));
+ MOCK_METHOD(binder::Status, getBootDisplayModeSupport, (bool*), (override));
+ MOCK_METHOD(binder::Status, setAutoLowLatencyMode, (const sp<IBinder>&, bool), (override));
+ MOCK_METHOD(binder::Status, setGameContentType, (const sp<IBinder>&, bool), (override));
+ MOCK_METHOD(binder::Status, captureDisplay,
+ (const DisplayCaptureArgs&, const sp<IScreenCaptureListener>&), (override));
+ MOCK_METHOD(binder::Status, captureDisplayById, (int64_t, const sp<IScreenCaptureListener>&),
+ (override));
+ MOCK_METHOD(binder::Status, captureLayers,
+ (const LayerCaptureArgs&, const sp<IScreenCaptureListener>&), (override));
+ MOCK_METHOD(binder::Status, clearAnimationFrameStats, (), (override));
+ MOCK_METHOD(binder::Status, getAnimationFrameStats, (gui::FrameStats*), (override));
+ MOCK_METHOD(binder::Status, overrideHdrTypes, (const sp<IBinder>&, const std::vector<int32_t>&),
+ (override));
+ MOCK_METHOD(binder::Status, onPullAtom, (int32_t, gui::PullAtomData*), (override));
+ MOCK_METHOD(binder::Status, enableVSyncInjections, (bool), (override));
+ MOCK_METHOD(binder::Status, injectVSync, (int64_t), (override));
+ MOCK_METHOD(binder::Status, getLayerDebugInfo, (std::vector<gui::LayerDebugInfo>*), (override));
+ MOCK_METHOD(binder::Status, getColorManagement, (bool*), (override));
+ MOCK_METHOD(binder::Status, getCompositionPreference, (gui::CompositionPreference*),
+ (override));
+ MOCK_METHOD(binder::Status, getDisplayedContentSamplingAttributes,
+ (const sp<IBinder>&, gui::ContentSamplingAttributes*), (override));
+ MOCK_METHOD(binder::Status, setDisplayContentSamplingEnabled,
+ (const sp<IBinder>&, bool, int8_t, int64_t), (override));
+ MOCK_METHOD(binder::Status, getDisplayedContentSample,
+ (const sp<IBinder>&, int64_t, int64_t, gui::DisplayedFrameStats*), (override));
+ MOCK_METHOD(binder::Status, getProtectedContentSupport, (bool*), (override));
+ MOCK_METHOD(binder::Status, isWideColorDisplay, (const sp<IBinder>&, bool*), (override));
+ MOCK_METHOD(binder::Status, addRegionSamplingListener,
+ (const gui::ARect&, const sp<IBinder>&, const sp<gui::IRegionSamplingListener>&),
+ (override));
+ MOCK_METHOD(binder::Status, removeRegionSamplingListener,
+ (const sp<gui::IRegionSamplingListener>&), (override));
+ MOCK_METHOD(binder::Status, addFpsListener, (int32_t, const sp<gui::IFpsListener>&),
+ (override));
+ MOCK_METHOD(binder::Status, removeFpsListener, (const sp<gui::IFpsListener>&), (override));
+ MOCK_METHOD(binder::Status, addTunnelModeEnabledListener,
+ (const sp<gui::ITunnelModeEnabledListener>&), (override));
+ MOCK_METHOD(binder::Status, removeTunnelModeEnabledListener,
+ (const sp<gui::ITunnelModeEnabledListener>&), (override));
+ MOCK_METHOD(binder::Status, setDesiredDisplayModeSpecs,
+ (const sp<IBinder>&, int32_t, bool, float, float, float,
+ float appRequestRefreshRateMax),
+ (override));
+ MOCK_METHOD(binder::Status, getDesiredDisplayModeSpecs,
+ (const sp<IBinder>&, gui::DisplayModeSpecs*), (override));
+ MOCK_METHOD(binder::Status, getDisplayBrightnessSupport, (const sp<IBinder>&, bool*),
+ (override));
+ MOCK_METHOD(binder::Status, setDisplayBrightness,
+ (const sp<IBinder>&, const gui::DisplayBrightness&), (override));
+ MOCK_METHOD(binder::Status, addHdrLayerInfoListener,
+ (const sp<IBinder>&, const sp<gui::IHdrLayerInfoListener>&), (override));
+ MOCK_METHOD(binder::Status, removeHdrLayerInfoListener,
+ (const sp<IBinder>&, const sp<gui::IHdrLayerInfoListener>&), (override));
+ MOCK_METHOD(binder::Status, notifyPowerBoost, (int), (override));
+ MOCK_METHOD(binder::Status, setGlobalShadowSettings,
+ (const gui::Color&, const gui::Color&, float, float, float), (override));
+ MOCK_METHOD(binder::Status, getDisplayDecorationSupport,
+ (const sp<IBinder>&, std::optional<gui::DisplayDecorationSupport>*), (override));
+ MOCK_METHOD(binder::Status, setOverrideFrameRate, (int32_t, float), (override));
+ MOCK_METHOD(binder::Status, addTransactionTraceListener,
+ (const sp<gui::ITransactionTraceListener>&), (override));
+ MOCK_METHOD(binder::Status, getGpuContextPriority, (int32_t*), (override));
+ MOCK_METHOD(binder::Status, getMaxAcquiredBufferCount, (int32_t*), (override));
+ MOCK_METHOD(binder::Status, addWindowInfosListener, (const sp<gui::IWindowInfosListener>&),
+ (override));
+ MOCK_METHOD(binder::Status, removeWindowInfosListener, (const sp<gui::IWindowInfosListener>&),
+ (override));
+};
+
+class FakeBnSurfaceComposerClient : public gui::BnSurfaceComposerClient {
+public:
+ MOCK_METHOD(binder::Status, createSurface,
+ (const std::string& name, int32_t flags, const sp<IBinder>& parent,
+ const gui::LayerMetadata& metadata, gui::CreateSurfaceResult* outResult),
+ (override));
+
+ MOCK_METHOD(binder::Status, clearLayerFrameStats, (const sp<IBinder>& handle), (override));
+
+ MOCK_METHOD(binder::Status, getLayerFrameStats,
+ (const sp<IBinder>& handle, gui::FrameStats* outStats), (override));
+
+ MOCK_METHOD(binder::Status, mirrorSurface,
+ (const sp<IBinder>& mirrorFromHandle, gui::MirrorSurfaceResult* outResult),
+ (override));
+};
+
+class FakeDisplayEventDispatcher : public DisplayEventDispatcher {
+public:
+ FakeDisplayEventDispatcher(const sp<Looper>& looper,
+ gui::ISurfaceComposer::VsyncSource vsyncSource,
+ gui::ISurfaceComposer::EventRegistration eventRegistration)
+ : DisplayEventDispatcher(looper, vsyncSource, eventRegistration){};
+
+ MOCK_METHOD4(dispatchVsync, void(nsecs_t, PhysicalDisplayId, uint32_t, VsyncEventData));
+ MOCK_METHOD3(dispatchHotplug, void(nsecs_t, PhysicalDisplayId, bool));
+ MOCK_METHOD4(dispatchModeChanged, void(nsecs_t, PhysicalDisplayId, int32_t, nsecs_t));
+ MOCK_METHOD2(dispatchNullEvent, void(nsecs_t, PhysicalDisplayId));
+ MOCK_METHOD3(dispatchFrameRateOverrides,
+ void(nsecs_t, PhysicalDisplayId, std::vector<FrameRateOverride>));
+};
+
+} // namespace android
+
+namespace android::hardware {
+
+namespace graphics::bufferqueue::V1_0::utils {
+
+class FakeGraphicBufferProducerV1 : public HGraphicBufferProducer {
+public:
+ FakeGraphicBufferProducerV1() {
+ ON_CALL(*this, setMaxDequeuedBufferCount).WillByDefault([]() { return 0; });
+ ON_CALL(*this, setAsyncMode).WillByDefault([]() { return 0; });
+ ON_CALL(*this, detachBuffer).WillByDefault([]() { return 0; });
+ ON_CALL(*this, cancelBuffer).WillByDefault([]() { return 0; });
+ ON_CALL(*this, disconnect).WillByDefault([]() { return 0; });
+ ON_CALL(*this, setSidebandStream).WillByDefault([]() { return 0; });
+ ON_CALL(*this, allowAllocation).WillByDefault([]() { return 0; });
+ ON_CALL(*this, setGenerationNumber).WillByDefault([]() { return 0; });
+ ON_CALL(*this, setSharedBufferMode).WillByDefault([]() { return 0; });
+ ON_CALL(*this, setAutoRefresh).WillByDefault([]() { return 0; });
+ ON_CALL(*this, setDequeueTimeout).WillByDefault([]() { return 0; });
+ ON_CALL(*this, setLegacyBufferDrop).WillByDefault([]() { return 0; });
+ };
+ MOCK_METHOD2(requestBuffer, Return<void>(int, requestBuffer_cb));
+ MOCK_METHOD1(setMaxDequeuedBufferCount, Return<int32_t>(int32_t));
+ MOCK_METHOD1(setAsyncMode, Return<int32_t>(bool));
+ MOCK_METHOD6(dequeueBuffer,
+ Return<void>(uint32_t, uint32_t, graphics::common::V1_0::PixelFormat, uint32_t,
+ bool, dequeueBuffer_cb));
+ MOCK_METHOD1(detachBuffer, Return<int32_t>(int));
+ MOCK_METHOD1(detachNextBuffer, Return<void>(detachNextBuffer_cb));
+ MOCK_METHOD2(attachBuffer, Return<void>(const media::V1_0::AnwBuffer&, attachBuffer_cb));
+ MOCK_METHOD3(
+ queueBuffer,
+ Return<void>(
+ int,
+ const graphics::bufferqueue::V1_0::IGraphicBufferProducer::QueueBufferInput&,
+ queueBuffer_cb));
+ MOCK_METHOD2(cancelBuffer, Return<int32_t>(int, const hidl_handle&));
+ MOCK_METHOD2(query, Return<void>(int32_t, query_cb));
+ MOCK_METHOD4(connect,
+ Return<void>(const sp<graphics::bufferqueue::V1_0::IProducerListener>&, int32_t,
+ bool, connect_cb));
+ MOCK_METHOD2(disconnect,
+ Return<int32_t>(
+ int, graphics::bufferqueue::V1_0::IGraphicBufferProducer::DisconnectMode));
+ MOCK_METHOD1(setSidebandStream, Return<int32_t>(const hidl_handle&));
+ MOCK_METHOD4(allocateBuffers,
+ Return<void>(uint32_t, uint32_t, graphics::common::V1_0::PixelFormat, uint32_t));
+ MOCK_METHOD1(allowAllocation, Return<int32_t>(bool));
+ MOCK_METHOD1(setGenerationNumber, Return<int32_t>(uint32_t));
+ MOCK_METHOD1(getConsumerName, Return<void>(getConsumerName_cb));
+ MOCK_METHOD1(setSharedBufferMode, Return<int32_t>(bool));
+ MOCK_METHOD1(setAutoRefresh, Return<int32_t>(bool));
+ MOCK_METHOD1(setDequeueTimeout, Return<int32_t>(nsecs_t));
+ MOCK_METHOD1(setLegacyBufferDrop, Return<int32_t>(bool));
+ MOCK_METHOD1(getLastQueuedBuffer, Return<void>(getLastQueuedBuffer_cb));
+ MOCK_METHOD1(getFrameTimestamps, Return<void>(getFrameTimestamps_cb));
+ MOCK_METHOD1(getUniqueId, Return<void>(getUniqueId_cb));
+};
+
+}; // namespace graphics::bufferqueue::V1_0::utils
+
+namespace graphics::bufferqueue::V2_0::utils {
+
+class FakeGraphicBufferProducerV2 : public HGraphicBufferProducer {
+public:
+ FakeGraphicBufferProducerV2() {
+ ON_CALL(*this, setMaxDequeuedBufferCount).WillByDefault([]() { return Status::OK; });
+ ON_CALL(*this, setAsyncMode).WillByDefault([]() { return Status::OK; });
+ ON_CALL(*this, detachBuffer).WillByDefault([]() { return Status::OK; });
+ ON_CALL(*this, cancelBuffer).WillByDefault([]() { return Status::OK; });
+ ON_CALL(*this, disconnect).WillByDefault([]() { return Status::OK; });
+ ON_CALL(*this, allocateBuffers).WillByDefault([]() { return Status::OK; });
+ ON_CALL(*this, allowAllocation).WillByDefault([]() { return Status::OK; });
+ ON_CALL(*this, setGenerationNumber).WillByDefault([]() { return Status::OK; });
+ ON_CALL(*this, setDequeueTimeout).WillByDefault([]() { return Status::OK; });
+ ON_CALL(*this, getUniqueId).WillByDefault([]() { return 0; });
+ };
+ MOCK_METHOD2(requestBuffer, Return<void>(int, requestBuffer_cb));
+ MOCK_METHOD1(setMaxDequeuedBufferCount, Return<graphics::bufferqueue::V2_0::Status>(int));
+ MOCK_METHOD1(setAsyncMode, Return<graphics::bufferqueue::V2_0::Status>(bool));
+ MOCK_METHOD2(
+ dequeueBuffer,
+ Return<void>(
+ const graphics::bufferqueue::V2_0::IGraphicBufferProducer::DequeueBufferInput&,
+ dequeueBuffer_cb));
+ MOCK_METHOD1(detachBuffer, Return<graphics::bufferqueue::V2_0::Status>(int));
+ MOCK_METHOD1(detachNextBuffer, Return<void>(detachNextBuffer_cb));
+ MOCK_METHOD3(attachBuffer,
+ Return<void>(const graphics::common::V1_2::HardwareBuffer&, uint32_t,
+ attachBuffer_cb));
+ MOCK_METHOD3(
+ queueBuffer,
+ Return<void>(
+ int,
+ const graphics::bufferqueue::V2_0::IGraphicBufferProducer::QueueBufferInput&,
+ queueBuffer_cb));
+ MOCK_METHOD2(cancelBuffer,
+ Return<graphics::bufferqueue::V2_0::Status>(int, const hidl_handle&));
+ MOCK_METHOD2(query, Return<void>(int32_t, query_cb));
+ MOCK_METHOD4(connect,
+ Return<void>(const sp<graphics::bufferqueue::V2_0::IProducerListener>&,
+ graphics::bufferqueue::V2_0::ConnectionType, bool, connect_cb));
+ MOCK_METHOD1(disconnect,
+ Return<graphics::bufferqueue::V2_0::Status>(
+ graphics::bufferqueue::V2_0::ConnectionType));
+ MOCK_METHOD4(allocateBuffers,
+ Return<graphics::bufferqueue::V2_0::Status>(uint32_t, uint32_t, uint32_t,
+ uint64_t));
+ MOCK_METHOD1(allowAllocation, Return<graphics::bufferqueue::V2_0::Status>(bool));
+ MOCK_METHOD1(setGenerationNumber, Return<graphics::bufferqueue::V2_0::Status>(uint32_t));
+ MOCK_METHOD1(getConsumerName, Return<void>(getConsumerName_cb));
+ MOCK_METHOD1(setDequeueTimeout, Return<graphics::bufferqueue::V2_0::Status>(int64_t));
+ MOCK_METHOD0(getUniqueId, Return<uint64_t>());
+};
+
+}; // namespace graphics::bufferqueue::V2_0::utils
+}; // namespace android::hardware
diff --git a/libs/gui/fuzzer/libgui_surfaceComposer_fuzzer.cpp b/libs/gui/fuzzer/libgui_surfaceComposer_fuzzer.cpp
new file mode 100644
index 0000000..6d5427b
--- /dev/null
+++ b/libs/gui/fuzzer/libgui_surfaceComposer_fuzzer.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fuzzbinder/libbinder_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <libgui_fuzzer_utils.h>
+
+using namespace android;
+
+class SurfaceComposerFuzzer {
+public:
+ SurfaceComposerFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){};
+ void process();
+
+private:
+ FuzzedDataProvider mFdp;
+};
+
+void SurfaceComposerFuzzer::process() {
+ sp<FakeBnSurfaceComposer> composer(new FakeBnSurfaceComposer());
+ fuzzService(composer.get(), std::move(mFdp));
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ SurfaceComposerFuzzer surfaceComposerFuzzer(data, size);
+ surfaceComposerFuzzer.process();
+ return 0;
+}
diff --git a/libs/gui/include/gui/AidlStatusUtil.h b/libs/gui/include/gui/AidlStatusUtil.h
new file mode 100644
index 0000000..55be27b
--- /dev/null
+++ b/libs/gui/include/gui/AidlStatusUtil.h
@@ -0,0 +1,114 @@
+/*
+ * 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 <binder/Status.h>
+
+// Extracted from frameworks/av/media/libaudioclient/include/media/AidlConversionUtil.h
+namespace android::gui::aidl_utils {
+
+/**
+ * Return the equivalent Android status_t from a binder exception code.
+ *
+ * Generally one should use statusTFromBinderStatus() instead.
+ *
+ * Exception codes can be generated from a remote Java service exception, translate
+ * them for use on the Native side.
+ *
+ * Note: for EX_TRANSACTION_FAILED and EX_SERVICE_SPECIFIC a more detailed error code
+ * can be found from transactionError() or serviceSpecificErrorCode().
+ */
+static inline status_t statusTFromExceptionCode(int32_t exceptionCode) {
+ using namespace ::android::binder;
+ switch (exceptionCode) {
+ case Status::EX_NONE:
+ return OK;
+ case Status::EX_SECURITY: // Java SecurityException, rethrows locally in Java
+ return PERMISSION_DENIED;
+ case Status::EX_BAD_PARCELABLE: // Java BadParcelableException, rethrows in Java
+ case Status::EX_ILLEGAL_ARGUMENT: // Java IllegalArgumentException, rethrows in Java
+ case Status::EX_NULL_POINTER: // Java NullPointerException, rethrows in Java
+ return BAD_VALUE;
+ case Status::EX_ILLEGAL_STATE: // Java IllegalStateException, rethrows in Java
+ case Status::EX_UNSUPPORTED_OPERATION: // Java UnsupportedOperationException, rethrows
+ return INVALID_OPERATION;
+ case Status::EX_HAS_REPLY_HEADER: // Native strictmode violation
+ case Status::EX_PARCELABLE: // Java bootclass loader (not standard exception), rethrows
+ case Status::EX_NETWORK_MAIN_THREAD: // Java NetworkOnMainThreadException, rethrows
+ case Status::EX_TRANSACTION_FAILED: // Native - see error code
+ case Status::EX_SERVICE_SPECIFIC: // Java ServiceSpecificException,
+ // rethrows in Java with integer error code
+ return UNKNOWN_ERROR;
+ }
+ return UNKNOWN_ERROR;
+}
+
+/**
+ * Return the equivalent Android status_t from a binder status.
+ *
+ * Used to handle errors from a AIDL method declaration
+ *
+ * [oneway] void method(type0 param0, ...)
+ *
+ * or the following (where return_type is not a status_t)
+ *
+ * return_type method(type0 param0, ...)
+ */
+static inline status_t statusTFromBinderStatus(const ::android::binder::Status &status) {
+ return status.isOk() ? OK // check OK,
+ : status.serviceSpecificErrorCode() // service-side error, not standard Java exception
+ // (fromServiceSpecificError)
+ ?: status.transactionError() // a native binder transaction error (fromStatusT)
+ ?: statusTFromExceptionCode(status.exceptionCode()); // a service-side error with a
+ // standard Java exception (fromExceptionCode)
+}
+
+/**
+ * Return a binder::Status from native service status.
+ *
+ * This is used for methods not returning an explicit status_t,
+ * where Java callers expect an exception, not an integer return value.
+ */
+static inline ::android::binder::Status binderStatusFromStatusT(
+ status_t status, const char *optionalMessage = nullptr) {
+ const char *const emptyIfNull = optionalMessage == nullptr ? "" : optionalMessage;
+ // From binder::Status instructions:
+ // Prefer a generic exception code when possible, then a service specific
+ // code, and finally a status_t for low level failures or legacy support.
+ // Exception codes and service specific errors map to nicer exceptions for
+ // Java clients.
+
+ using namespace ::android::binder;
+ switch (status) {
+ case OK:
+ return Status::ok();
+ case PERMISSION_DENIED: // throw SecurityException on Java side
+ return Status::fromExceptionCode(Status::EX_SECURITY, emptyIfNull);
+ case BAD_VALUE: // throw IllegalArgumentException on Java side
+ return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, emptyIfNull);
+ case INVALID_OPERATION: // throw IllegalStateException on Java side
+ return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, emptyIfNull);
+ }
+
+ // A service specific error will not show on status.transactionError() so
+ // be sure to use statusTFromBinderStatus() for reliable error handling.
+
+ // throw a ServiceSpecificException.
+ return Status::fromServiceSpecificError(status, emptyIfNull);
+}
+
+} // namespace android::gui::aidl_utils
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index 9d28791..2ed5260 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -69,9 +69,7 @@
bool mPreviouslyConnected GUARDED_BY(mMutex);
};
-class BLASTBufferQueue
- : public ConsumerBase::FrameAvailableListener, public BufferItemConsumer::BufferFreedListener
-{
+class BLASTBufferQueue : public ConsumerBase::FrameAvailableListener {
public:
BLASTBufferQueue(const std::string& name, bool updateDestinationFrame = true);
BLASTBufferQueue(const std::string& name, const sp<SurfaceControl>& surface, int width,
@@ -83,7 +81,6 @@
sp<Surface> getSurface(bool includeSurfaceControlHandle);
bool isSameSurfaceControl(const sp<SurfaceControl>& surfaceControl) const;
- void onBufferFreed(const wp<GraphicBuffer>&/* graphicBuffer*/) override { /* TODO */ }
void onFrameReplaced(const BufferItem& item) override;
void onFrameAvailable(const BufferItem& item) override;
void onFrameDequeued(const uint64_t) override;
diff --git a/libs/gui/include/gui/CompositorTiming.h b/libs/gui/include/gui/CompositorTiming.h
new file mode 100644
index 0000000..cb8ca7a
--- /dev/null
+++ b/libs/gui/include/gui/CompositorTiming.h
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <utils/Timers.h>
+
+namespace android::gui {
+
+// Expected timing of the next composited frame, based on the timing of the latest frames.
+struct CompositorTiming {
+ static constexpr nsecs_t kDefaultVsyncPeriod = 16'666'667;
+
+ CompositorTiming() = default;
+ CompositorTiming(nsecs_t vsyncDeadline, nsecs_t vsyncPeriod, nsecs_t vsyncPhase,
+ nsecs_t presentLatency);
+
+ // Time point when compositing is expected to start.
+ nsecs_t deadline = 0;
+
+ // Duration between consecutive frames. In other words, the VSYNC period.
+ nsecs_t interval = kDefaultVsyncPeriod;
+
+ // Duration between composite start and present. For missed frames, the extra latency is rounded
+ // to a multiple of the VSYNC period, such that the remainder (presentLatency % interval) always
+ // evaluates to the VSYNC phase offset.
+ nsecs_t presentLatency = kDefaultVsyncPeriod;
+};
+
+} // namespace android::gui
diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h
index a342539..bf3a07b 100644
--- a/libs/gui/include/gui/DisplayEventDispatcher.h
+++ b/libs/gui/include/gui/DisplayEventDispatcher.h
@@ -23,10 +23,10 @@
class DisplayEventDispatcher : public LooperCallback {
public:
- explicit DisplayEventDispatcher(
- const sp<Looper>& looper,
- ISurfaceComposer::VsyncSource vsyncSource = ISurfaceComposer::eVsyncSourceApp,
- ISurfaceComposer::EventRegistrationFlags eventRegistration = {});
+ explicit DisplayEventDispatcher(const sp<Looper>& looper,
+ gui::ISurfaceComposer::VsyncSource vsyncSource =
+ gui::ISurfaceComposer::VsyncSource::eVsyncSourceApp,
+ EventRegistrationFlags eventRegistration = {});
status_t initialize();
void dispose();
diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h
index cf7a4e5..0f4907f 100644
--- a/libs/gui/include/gui/DisplayEventReceiver.h
+++ b/libs/gui/include/gui/DisplayEventReceiver.h
@@ -20,20 +20,26 @@
#include <stdint.h>
#include <sys/types.h>
+#include <ftl/flags.h>
+
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/Timers.h>
+#include <android/gui/ISurfaceComposer.h>
#include <binder/IInterface.h>
-#include <gui/ISurfaceComposer.h>
#include <gui/VsyncEventData.h>
+#include <ui/DisplayId.h>
+
// ----------------------------------------------------------------------------
namespace android {
// ----------------------------------------------------------------------------
+using EventRegistrationFlags = ftl::Flags<gui::ISurfaceComposer::EventRegistration>;
+
using gui::IDisplayEventConnection;
using gui::ParcelableVsyncEventData;
using gui::VsyncEventData;
@@ -111,9 +117,9 @@
* To receive ModeChanged and/or FrameRateOverrides events specify this in
* the constructor. Other events start being delivered immediately.
*/
- explicit DisplayEventReceiver(
- ISurfaceComposer::VsyncSource vsyncSource = ISurfaceComposer::eVsyncSourceApp,
- ISurfaceComposer::EventRegistrationFlags eventRegistration = {});
+ explicit DisplayEventReceiver(gui::ISurfaceComposer::VsyncSource vsyncSource =
+ gui::ISurfaceComposer::VsyncSource::eVsyncSourceApp,
+ EventRegistrationFlags eventRegistration = {});
/*
* ~DisplayEventReceiver severs the connection with SurfaceFlinger, new events
diff --git a/libs/gui/include/gui/FrameTimestamps.h b/libs/gui/include/gui/FrameTimestamps.h
index dd3de58..c08a9b1 100644
--- a/libs/gui/include/gui/FrameTimestamps.h
+++ b/libs/gui/include/gui/FrameTimestamps.h
@@ -17,6 +17,9 @@
#ifndef ANDROID_GUI_FRAMETIMESTAMPS_H
#define ANDROID_GUI_FRAMETIMESTAMPS_H
+#include <android/gui/FrameEvent.h>
+
+#include <gui/CompositorTiming.h>
#include <ui/FenceTime.h>
#include <utils/Flattenable.h>
#include <utils/StrongPointer.h>
@@ -31,22 +34,8 @@
struct FrameEvents;
class FrameEventHistoryDelta;
-
-// Identifiers for all the events that may be recorded or reported.
-enum class FrameEvent {
- POSTED,
- REQUESTED_PRESENT,
- LATCH,
- ACQUIRE,
- FIRST_REFRESH_START,
- LAST_REFRESH_START,
- GPU_COMPOSITION_DONE,
- DISPLAY_PRESENT,
- DEQUEUE_READY,
- RELEASE,
- EVENT_COUNT, // Not an actual event.
-};
-
+using gui::CompositorTiming;
+using gui::FrameEvent;
// A collection of timestamps corresponding to a single frame.
struct FrameEvents {
@@ -96,12 +85,6 @@
std::shared_ptr<FenceTime> releaseFence{FenceTime::NO_FENCE};
};
-struct CompositorTiming {
- nsecs_t deadline{0};
- nsecs_t interval{16666667};
- nsecs_t presentLatency{16666667};
-};
-
// A short history of frames that are synchronized between the consumer and
// producer via deltas.
class FrameEventHistory {
diff --git a/libs/gui/include/gui/GLConsumer.h b/libs/gui/include/gui/GLConsumer.h
index 2f538ff..ba268ab 100644
--- a/libs/gui/include/gui/GLConsumer.h
+++ b/libs/gui/include/gui/GLConsumer.h
@@ -138,6 +138,10 @@
const sp<GraphicBuffer>& buf, const Rect& cropRect,
uint32_t transform, bool filtering);
+ static void computeTransformMatrix(float outTransform[16], float bufferWidth,
+ float bufferHeight, PixelFormat pixelFormat,
+ const Rect& cropRect, uint32_t transform, bool filtering);
+
// Scale the crop down horizontally or vertically such that it has the
// same aspect ratio as the buffer does.
static Rect scaleDownCrop(const Rect& crop, uint32_t bufferWidth,
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index a610e94..1e85131 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -17,6 +17,7 @@
#pragma once
#include <android/gui/DisplayBrightness.h>
+#include <android/gui/FrameTimelineInfo.h>
#include <android/gui/IDisplayEventConnection.h>
#include <android/gui/IFpsListener.h>
#include <android/gui/IHdrLayerInfoListener.h>
@@ -27,8 +28,6 @@
#include <android/gui/IWindowInfosListener.h>
#include <binder/IBinder.h>
#include <binder/IInterface.h>
-#include <ftl/flags.h>
-#include <gui/FrameTimelineInfo.h>
#include <gui/ITransactionCompletedListener.h>
#include <gui/SpHash.h>
#include <math/vec4.h>
@@ -61,13 +60,10 @@
struct DisplayStatInfo;
struct DisplayState;
struct InputWindowCommands;
-class LayerDebugInfo;
class HdrCapabilities;
-class IGraphicBufferProducer;
-class ISurfaceComposerClient;
class Rect;
-enum class FrameEvent;
+using gui::FrameTimelineInfo;
using gui::IDisplayEventConnection;
using gui::IRegionSamplingListener;
using gui::IScreenCaptureListener;
@@ -77,6 +73,7 @@
struct DisplayCaptureArgs;
struct LayerCaptureArgs;
+class LayerDebugInfo;
} // namespace gui
@@ -85,7 +82,6 @@
struct DisplayMode;
struct DisplayState;
struct DynamicDisplayInfo;
-struct StaticDisplayInfo;
} // namespace ui
@@ -97,8 +93,6 @@
public:
DECLARE_META_INTERFACE(SurfaceComposer)
- static constexpr size_t MAX_LAYERS = 4096;
-
// flags for setTransactionState()
enum {
eSynchronous = 0x01,
@@ -116,28 +110,6 @@
eOneWay = 0x20
};
- enum VsyncSource {
- eVsyncSourceApp = 0,
- eVsyncSourceSurfaceFlinger = 1
- };
-
- enum class EventRegistration {
- modeChanged = 1 << 0,
- frameRateOverride = 1 << 1,
- };
-
- using EventRegistrationFlags = ftl::Flags<EventRegistration>;
-
- /*
- * Create a connection with SurfaceFlinger.
- */
- virtual sp<ISurfaceComposerClient> createConnection() = 0;
-
- /* return an IDisplayEventConnection */
- virtual sp<IDisplayEventConnection> createDisplayEventConnection(
- VsyncSource vsyncSource = eVsyncSourceApp,
- EventRegistrationFlags eventRegistration = {}) = 0;
-
/* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */
virtual status_t setTransactionState(
const FrameTimelineInfo& frameTimelineInfo, const Vector<ComposerState>& state,
@@ -145,293 +117,6 @@
const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) = 0;
-
- /* signal that we're done booting.
- * Requires ACCESS_SURFACE_FLINGER permission
- */
- virtual void bootFinished() = 0;
-
- /* verify that an IGraphicBufferProducer was created by SurfaceFlinger.
- */
- virtual bool authenticateSurfaceTexture(
- const sp<IGraphicBufferProducer>& surface) const = 0;
-
- /* Returns the frame timestamps supported by SurfaceFlinger.
- */
- virtual status_t getSupportedFrameTimestamps(
- std::vector<FrameEvent>* outSupported) const = 0;
-
- /**
- * Gets immutable information about given physical display.
- */
- virtual status_t getStaticDisplayInfo(const sp<IBinder>& display, ui::StaticDisplayInfo*) = 0;
-
- /**
- * Gets dynamic information about given physical display.
- */
- virtual status_t getDynamicDisplayInfo(const sp<IBinder>& display, ui::DynamicDisplayInfo*) = 0;
-
- virtual status_t getDisplayNativePrimaries(const sp<IBinder>& display,
- ui::DisplayPrimaries& primaries) = 0;
- virtual status_t setActiveColorMode(const sp<IBinder>& display,
- ui::ColorMode colorMode) = 0;
-
- /**
- * Sets the user-preferred display mode that a device should boot in.
- */
- virtual status_t setBootDisplayMode(const sp<IBinder>& display, ui::DisplayModeId) = 0;
-
- /* Clears the frame statistics for animations.
- *
- * Requires the ACCESS_SURFACE_FLINGER permission.
- */
- virtual status_t clearAnimationFrameStats() = 0;
-
- /* Gets the frame statistics for animations.
- *
- * Requires the ACCESS_SURFACE_FLINGER permission.
- */
- virtual status_t getAnimationFrameStats(FrameStats* outStats) const = 0;
-
- /* Overrides the supported HDR modes for the given display device.
- *
- * Requires the ACCESS_SURFACE_FLINGER permission.
- */
- virtual status_t overrideHdrTypes(const sp<IBinder>& display,
- const std::vector<ui::Hdr>& hdrTypes) = 0;
-
- /* Pulls surfaceflinger atoms global stats and layer stats to pipe to statsd.
- *
- * Requires the calling uid be from system server.
- */
- virtual status_t onPullAtom(const int32_t atomId, std::string* outData, bool* success) = 0;
-
- virtual status_t enableVSyncInjections(bool enable) = 0;
-
- virtual status_t injectVSync(nsecs_t when) = 0;
-
- /* Gets the list of active layers in Z order for debugging purposes
- *
- * Requires the ACCESS_SURFACE_FLINGER permission.
- */
- virtual status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) = 0;
-
- virtual status_t getColorManagement(bool* outGetColorManagement) const = 0;
-
- /* Gets the composition preference of the default data space and default pixel format,
- * as well as the wide color gamut data space and wide color gamut pixel format.
- * If the wide color gamut data space is V0_SRGB, then it implies that the platform
- * has no wide color gamut support.
- *
- * Requires the ACCESS_SURFACE_FLINGER permission.
- */
- virtual status_t getCompositionPreference(ui::Dataspace* defaultDataspace,
- ui::PixelFormat* defaultPixelFormat,
- ui::Dataspace* wideColorGamutDataspace,
- ui::PixelFormat* wideColorGamutPixelFormat) const = 0;
- /*
- * Requires the ACCESS_SURFACE_FLINGER permission.
- */
- virtual status_t getDisplayedContentSamplingAttributes(const sp<IBinder>& display,
- ui::PixelFormat* outFormat,
- ui::Dataspace* outDataspace,
- uint8_t* outComponentMask) const = 0;
-
- /* Turns on the color sampling engine on the display.
- *
- * Requires the ACCESS_SURFACE_FLINGER permission.
- */
- virtual status_t setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
- uint8_t componentMask,
- uint64_t maxFrames) = 0;
-
- /* Returns statistics on the color profile of the last frame displayed for a given display
- *
- * Requires the ACCESS_SURFACE_FLINGER permission.
- */
- virtual status_t getDisplayedContentSample(const sp<IBinder>& display, uint64_t maxFrames,
- uint64_t timestamp,
- DisplayedFrameStats* outStats) const = 0;
-
- /*
- * Gets whether SurfaceFlinger can support protected content in GPU composition.
- * Requires the ACCESS_SURFACE_FLINGER permission.
- */
- virtual status_t getProtectedContentSupport(bool* outSupported) const = 0;
-
- /* Registers a listener to stream median luma updates from SurfaceFlinger.
- *
- * The sampling area is bounded by both samplingArea and the given stopLayerHandle
- * (i.e., only layers behind the stop layer will be captured and sampled).
- *
- * Multiple listeners may be provided so long as they have independent listeners.
- * If multiple listeners are provided, the effective sampling region for each listener will
- * be bounded by whichever stop layer has a lower Z value.
- *
- * Requires the same permissions as captureLayers and captureScreen.
- */
- virtual status_t addRegionSamplingListener(const Rect& samplingArea,
- const sp<IBinder>& stopLayerHandle,
- const sp<IRegionSamplingListener>& listener) = 0;
-
- /*
- * Removes a listener that was streaming median luma updates from SurfaceFlinger.
- */
- virtual status_t removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener) = 0;
-
- /* Registers a listener that streams fps updates from SurfaceFlinger.
- *
- * The listener will stream fps updates for the layer tree rooted at the layer denoted by the
- * task ID, i.e., the layer must have the task ID as part of its layer metadata with key
- * METADATA_TASK_ID. If there is no such layer, then no fps is expected to be reported.
- *
- * Multiple listeners may be supported.
- *
- * Requires the READ_FRAME_BUFFER permission.
- */
- virtual status_t addFpsListener(int32_t taskId, const sp<gui::IFpsListener>& listener) = 0;
- /*
- * Removes a listener that was streaming fps updates from SurfaceFlinger.
- */
- virtual status_t removeFpsListener(const sp<gui::IFpsListener>& listener) = 0;
-
- /* Registers a listener to receive tunnel mode enabled updates from SurfaceFlinger.
- *
- * Requires ACCESS_SURFACE_FLINGER permission.
- */
- virtual status_t addTunnelModeEnabledListener(
- const sp<gui::ITunnelModeEnabledListener>& listener) = 0;
-
- /*
- * Removes a listener that was receiving tunnel mode enabled updates from SurfaceFlinger.
- *
- * Requires ACCESS_SURFACE_FLINGER permission.
- */
- virtual status_t removeTunnelModeEnabledListener(
- const sp<gui::ITunnelModeEnabledListener>& listener) = 0;
-
- /* Sets the refresh rate boundaries for the display.
- *
- * The primary refresh rate range represents display manager's general guidance on the display
- * modes we'll consider when switching refresh rates. Unless we get an explicit signal from an
- * app, we should stay within this range.
- *
- * The app request refresh rate range allows us to consider more display modes when switching
- * refresh rates. Although we should generally stay within the primary range, specific
- * considerations, such as layer frame rate settings specified via the setFrameRate() api, may
- * cause us to go outside the primary range. We never go outside the app request range. The app
- * request range will be greater than or equal to the primary refresh rate range, never smaller.
- *
- * defaultMode is used to narrow the list of display modes SurfaceFlinger will consider
- * switching between. Only modes with a mode group and resolution matching defaultMode
- * will be considered for switching. The defaultMode corresponds to an ID of mode in the list
- * of supported modes returned from getDynamicDisplayInfo().
- */
- virtual status_t setDesiredDisplayModeSpecs(
- const sp<IBinder>& displayToken, ui::DisplayModeId defaultMode,
- bool allowGroupSwitching, float primaryRefreshRateMin, float primaryRefreshRateMax,
- float appRequestRefreshRateMin, float appRequestRefreshRateMax) = 0;
-
- virtual status_t getDesiredDisplayModeSpecs(const sp<IBinder>& displayToken,
- ui::DisplayModeId* outDefaultMode,
- bool* outAllowGroupSwitching,
- float* outPrimaryRefreshRateMin,
- float* outPrimaryRefreshRateMax,
- float* outAppRequestRefreshRateMin,
- float* outAppRequestRefreshRateMax) = 0;
-
- /*
- * Sets the global configuration for all the shadows drawn by SurfaceFlinger. Shadow follows
- * material design guidelines.
- *
- * ambientColor
- * Color to the ambient shadow. The alpha is premultiplied.
- *
- * spotColor
- * Color to the spot shadow. The alpha is premultiplied. The position of the spot shadow
- * depends on the light position.
- *
- * lightPosY/lightPosZ
- * Position of the light used to cast the spot shadow. The X value is always the display
- * width / 2.
- *
- * lightRadius
- * Radius of the light casting the shadow.
- */
- virtual status_t setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor,
- float lightPosY, float lightPosZ,
- float lightRadius) = 0;
-
- /*
- * Gets whether a display supports DISPLAY_DECORATION layers.
- *
- * displayToken
- * The token of the display.
- * outSupport
- * An output parameter for whether/how the display supports
- * DISPLAY_DECORATION layers.
- *
- * Returns NO_ERROR upon success. Otherwise,
- * NAME_NOT_FOUND if the display is invalid, or
- * BAD_VALUE if the output parameter is invalid.
- */
- virtual status_t getDisplayDecorationSupport(
- const sp<IBinder>& displayToken,
- std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
- outSupport) const = 0;
-
- /*
- * Sets the intended frame rate for a surface. See ANativeWindow_setFrameRate() for more info.
- */
- virtual status_t setFrameRate(const sp<IGraphicBufferProducer>& surface, float frameRate,
- int8_t compatibility, int8_t changeFrameRateStrategy) = 0;
-
- /*
- * Set the override frame rate for a specified uid by GameManagerService.
- * Passing the frame rate and uid to SurfaceFlinger to update the override mapping
- * in the scheduler.
- */
- virtual status_t setOverrideFrameRate(uid_t uid, float frameRate) = 0;
-
- /*
- * Sets the frame timeline vsync info received from choreographer that corresponds to next
- * buffer submitted on that surface.
- */
- virtual status_t setFrameTimelineInfo(const sp<IGraphicBufferProducer>& surface,
- const FrameTimelineInfo& frameTimelineInfo) = 0;
-
- /*
- * Adds a TransactionTraceListener to listen for transaction tracing state updates.
- */
- virtual status_t addTransactionTraceListener(
- const sp<gui::ITransactionTraceListener>& listener) = 0;
-
- /**
- * Gets priority of the RenderEngine in SurfaceFlinger.
- */
- virtual int getGPUContextPriority() = 0;
-
- /**
- * Gets the number of buffers SurfaceFlinger would need acquire. This number
- * would be propagated to the client via MIN_UNDEQUEUED_BUFFERS so that the
- * client could allocate enough buffers to match SF expectations of the
- * pipeline depth. SurfaceFlinger will make sure that it will give the app at
- * least the time configured as the 'appDuration' before trying to latch
- * the buffer.
- *
- * The total buffers needed for a given configuration is basically the
- * numbers of vsyncs a single buffer is used across the stack. For the default
- * configuration a buffer is held ~1 vsync by the app, ~1 vsync by SurfaceFlinger
- * and 1 vsync by the display. The extra buffers are calculated as the
- * number of additional buffers on top of the 2 buffers already present
- * in MIN_UNDEQUEUED_BUFFERS.
- */
- virtual status_t getMaxAcquiredBufferCount(int* buffers) const = 0;
-
- virtual status_t addWindowInfosListener(
- const sp<gui::IWindowInfosListener>& windowInfosListener) const = 0;
- virtual status_t removeWindowInfosListener(
- const sp<gui::IWindowInfosListener>& windowInfosListener) const = 0;
};
// ----------------------------------------------------------------------------
@@ -442,77 +127,77 @@
// Note: BOOT_FINISHED must remain this value, it is called from
// Java by ActivityManagerService.
BOOT_FINISHED = IBinder::FIRST_CALL_TRANSACTION,
- CREATE_CONNECTION,
- GET_STATIC_DISPLAY_INFO,
- CREATE_DISPLAY_EVENT_CONNECTION,
- CREATE_DISPLAY, // Deprecated. Autogenerated by .aidl now.
- DESTROY_DISPLAY, // Deprecated. Autogenerated by .aidl now.
- GET_PHYSICAL_DISPLAY_TOKEN, // Deprecated. Autogenerated by .aidl now.
+ CREATE_CONNECTION, // Deprecated. Autogenerated by .aidl now.
+ GET_STATIC_DISPLAY_INFO, // Deprecated. Autogenerated by .aidl now.
+ CREATE_DISPLAY_EVENT_CONNECTION, // Deprecated. Autogenerated by .aidl now.
+ CREATE_DISPLAY, // Deprecated. Autogenerated by .aidl now.
+ DESTROY_DISPLAY, // Deprecated. Autogenerated by .aidl now.
+ GET_PHYSICAL_DISPLAY_TOKEN, // Deprecated. Autogenerated by .aidl now.
SET_TRANSACTION_STATE,
- AUTHENTICATE_SURFACE,
- GET_SUPPORTED_FRAME_TIMESTAMPS,
- GET_DISPLAY_MODES, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
- GET_ACTIVE_DISPLAY_MODE, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
+ AUTHENTICATE_SURFACE, // Deprecated. Autogenerated by .aidl now.
+ GET_SUPPORTED_FRAME_TIMESTAMPS, // Deprecated. Autogenerated by .aidl now.
+ GET_DISPLAY_MODES, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
+ GET_ACTIVE_DISPLAY_MODE, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
GET_DISPLAY_STATE,
- CAPTURE_DISPLAY, // Deprecated. Autogenerated by .aidl now.
- CAPTURE_LAYERS, // Deprecated. Autogenerated by .aidl now.
- CLEAR_ANIMATION_FRAME_STATS,
- GET_ANIMATION_FRAME_STATS,
- SET_POWER_MODE, // Deprecated. Autogenerated by .aidl now.
+ CAPTURE_DISPLAY, // Deprecated. Autogenerated by .aidl now.
+ CAPTURE_LAYERS, // Deprecated. Autogenerated by .aidl now.
+ CLEAR_ANIMATION_FRAME_STATS, // Deprecated. Autogenerated by .aidl now.
+ GET_ANIMATION_FRAME_STATS, // Deprecated. Autogenerated by .aidl now.
+ SET_POWER_MODE, // Deprecated. Autogenerated by .aidl now.
GET_DISPLAY_STATS,
- GET_HDR_CAPABILITIES, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
- GET_DISPLAY_COLOR_MODES, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
- GET_ACTIVE_COLOR_MODE, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
- SET_ACTIVE_COLOR_MODE,
- ENABLE_VSYNC_INJECTIONS,
- INJECT_VSYNC,
- GET_LAYER_DEBUG_INFO,
- GET_COMPOSITION_PREFERENCE,
- GET_COLOR_MANAGEMENT,
- GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES,
- SET_DISPLAY_CONTENT_SAMPLING_ENABLED,
+ GET_HDR_CAPABILITIES, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
+ GET_DISPLAY_COLOR_MODES, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
+ GET_ACTIVE_COLOR_MODE, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
+ SET_ACTIVE_COLOR_MODE, // Deprecated. Autogenerated by .aidl now.
+ ENABLE_VSYNC_INJECTIONS, // Deprecated. Autogenerated by .aidl now.
+ INJECT_VSYNC, // Deprecated. Autogenerated by .aidl now.
+ GET_LAYER_DEBUG_INFO, // Deprecated. Autogenerated by .aidl now.
+ GET_COMPOSITION_PREFERENCE, // Deprecated. Autogenerated by .aidl now.
+ GET_COLOR_MANAGEMENT, // Deprecated. Autogenerated by .aidl now.
+ GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES, // Deprecated. Autogenerated by .aidl now.
+ SET_DISPLAY_CONTENT_SAMPLING_ENABLED, // Deprecated. Autogenerated by .aidl now.
GET_DISPLAYED_CONTENT_SAMPLE,
- GET_PROTECTED_CONTENT_SUPPORT,
- IS_WIDE_COLOR_DISPLAY, // Deprecated. Autogenerated by .aidl now.
- GET_DISPLAY_NATIVE_PRIMARIES,
- GET_PHYSICAL_DISPLAY_IDS, // Deprecated. Autogenerated by .aidl now.
- ADD_REGION_SAMPLING_LISTENER,
- REMOVE_REGION_SAMPLING_LISTENER,
- SET_DESIRED_DISPLAY_MODE_SPECS,
- GET_DESIRED_DISPLAY_MODE_SPECS,
- GET_DISPLAY_BRIGHTNESS_SUPPORT, // Deprecated. Autogenerated by .aidl now.
- SET_DISPLAY_BRIGHTNESS, // Deprecated. Autogenerated by .aidl now.
- CAPTURE_DISPLAY_BY_ID, // Deprecated. Autogenerated by .aidl now.
- NOTIFY_POWER_BOOST, // Deprecated. Autogenerated by .aidl now.
+ GET_PROTECTED_CONTENT_SUPPORT, // Deprecated. Autogenerated by .aidl now.
+ IS_WIDE_COLOR_DISPLAY, // Deprecated. Autogenerated by .aidl now.
+ GET_DISPLAY_NATIVE_PRIMARIES, // Deprecated. Autogenerated by .aidl now.
+ GET_PHYSICAL_DISPLAY_IDS, // Deprecated. Autogenerated by .aidl now.
+ ADD_REGION_SAMPLING_LISTENER, // Deprecated. Autogenerated by .aidl now.
+ REMOVE_REGION_SAMPLING_LISTENER, // Deprecated. Autogenerated by .aidl now.
+ SET_DESIRED_DISPLAY_MODE_SPECS, // Deprecated. Autogenerated by .aidl now.
+ GET_DESIRED_DISPLAY_MODE_SPECS, // Deprecated. Autogenerated by .aidl now.
+ GET_DISPLAY_BRIGHTNESS_SUPPORT, // Deprecated. Autogenerated by .aidl now.
+ SET_DISPLAY_BRIGHTNESS, // Deprecated. Autogenerated by .aidl now.
+ CAPTURE_DISPLAY_BY_ID, // Deprecated. Autogenerated by .aidl now.
+ NOTIFY_POWER_BOOST, // Deprecated. Autogenerated by .aidl now.
SET_GLOBAL_SHADOW_SETTINGS,
GET_AUTO_LOW_LATENCY_MODE_SUPPORT, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
SET_AUTO_LOW_LATENCY_MODE, // Deprecated. Autogenerated by .aidl now.
GET_GAME_CONTENT_TYPE_SUPPORT, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
SET_GAME_CONTENT_TYPE, // Deprecated. Use GET_DYNAMIC_DISPLAY_INFO instead.
- SET_FRAME_RATE,
+ SET_FRAME_RATE, // Deprecated. Autogenerated by .aidl now.
// Deprecated. Use DisplayManager.setShouldAlwaysRespectAppRequestedMode(true);
ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN,
- SET_FRAME_TIMELINE_INFO,
- ADD_TRANSACTION_TRACE_LISTENER,
+ SET_FRAME_TIMELINE_INFO, // Deprecated. Autogenerated by .aidl now.
+ ADD_TRANSACTION_TRACE_LISTENER, // Deprecated. Autogenerated by .aidl now.
GET_GPU_CONTEXT_PRIORITY,
GET_MAX_ACQUIRED_BUFFER_COUNT,
- GET_DYNAMIC_DISPLAY_INFO,
- ADD_FPS_LISTENER,
- REMOVE_FPS_LISTENER,
- OVERRIDE_HDR_TYPES,
- ADD_HDR_LAYER_INFO_LISTENER, // Deprecated. Autogenerated by .aidl now.
- REMOVE_HDR_LAYER_INFO_LISTENER, // Deprecated. Autogenerated by .aidl now.
- ON_PULL_ATOM,
- ADD_TUNNEL_MODE_ENABLED_LISTENER,
- REMOVE_TUNNEL_MODE_ENABLED_LISTENER,
- ADD_WINDOW_INFOS_LISTENER,
- REMOVE_WINDOW_INFOS_LISTENER,
- GET_PRIMARY_PHYSICAL_DISPLAY_ID, // Deprecated. Autogenerated by .aidl now.
+ GET_DYNAMIC_DISPLAY_INFO, // Deprecated. Autogenerated by .aidl now.
+ ADD_FPS_LISTENER, // Deprecated. Autogenerated by .aidl now.
+ REMOVE_FPS_LISTENER, // Deprecated. Autogenerated by .aidl now.
+ OVERRIDE_HDR_TYPES, // Deprecated. Autogenerated by .aidl now.
+ ADD_HDR_LAYER_INFO_LISTENER, // Deprecated. Autogenerated by .aidl now.
+ REMOVE_HDR_LAYER_INFO_LISTENER, // Deprecated. Autogenerated by .aidl now.
+ ON_PULL_ATOM, // Deprecated. Autogenerated by .aidl now.
+ ADD_TUNNEL_MODE_ENABLED_LISTENER, // Deprecated. Autogenerated by .aidl now.
+ REMOVE_TUNNEL_MODE_ENABLED_LISTENER, // Deprecated. Autogenerated by .aidl now.
+ ADD_WINDOW_INFOS_LISTENER, // Deprecated. Autogenerated by .aidl now.
+ REMOVE_WINDOW_INFOS_LISTENER, // Deprecated. Autogenerated by .aidl now.
+ GET_PRIMARY_PHYSICAL_DISPLAY_ID, // Deprecated. Autogenerated by .aidl now.
GET_DISPLAY_DECORATION_SUPPORT,
GET_BOOT_DISPLAY_MODE_SUPPORT, // Deprecated. Autogenerated by .aidl now.
- SET_BOOT_DISPLAY_MODE,
- CLEAR_BOOT_DISPLAY_MODE, // Deprecated. Autogenerated by .aidl now.
- SET_OVERRIDE_FRAME_RATE,
+ SET_BOOT_DISPLAY_MODE, // Deprecated. Autogenerated by .aidl now.
+ CLEAR_BOOT_DISPLAY_MODE, // Deprecated. Autogenerated by .aidl now.
+ SET_OVERRIDE_FRAME_RATE, // Deprecated. Autogenerated by .aidl now.
// Always append new enum to the end.
};
diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h
deleted file mode 100644
index 9e9e191..0000000
--- a/libs/gui/include/gui/ISurfaceComposerClient.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2007 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 <binder/IInterface.h>
-#include <binder/SafeInterface.h>
-#include <gui/LayerMetadata.h>
-#include <ui/PixelFormat.h>
-
-#include <unordered_map>
-
-namespace android {
-
-class FrameStats;
-class IGraphicBufferProducer;
-
-class ISurfaceComposerClient : public IInterface {
-public:
- DECLARE_META_INTERFACE(SurfaceComposerClient)
-
- // flags for createSurface()
- enum { // (keep in sync with SurfaceControl.java)
- eHidden = 0x00000004,
- eDestroyBackbuffer = 0x00000020,
- eSkipScreenshot = 0x00000040,
- eSecure = 0x00000080,
- eNonPremultiplied = 0x00000100,
- eOpaque = 0x00000400,
- eProtectedByApp = 0x00000800,
- eProtectedByDRM = 0x00001000,
- eCursorWindow = 0x00002000,
- eNoColorFill = 0x00004000,
-
- eFXSurfaceBufferQueue = 0x00000000,
- eFXSurfaceEffect = 0x00020000,
- eFXSurfaceBufferState = 0x00040000,
- eFXSurfaceContainer = 0x00080000,
- eFXSurfaceMask = 0x000F0000,
- };
-
- // TODO(b/172002646): Clean up the Surface Creation Arguments
- /*
- * Requires ACCESS_SURFACE_FLINGER permission
- */
- virtual status_t createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format,
- uint32_t flags, const sp<IBinder>& parent,
- LayerMetadata metadata, sp<IBinder>* handle,
- sp<IGraphicBufferProducer>* gbp, int32_t* outLayerId,
- uint32_t* outTransformHint) = 0;
-
- /*
- * Requires ACCESS_SURFACE_FLINGER permission
- */
- virtual status_t createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h,
- PixelFormat format, uint32_t flags,
- const sp<IGraphicBufferProducer>& parent,
- LayerMetadata metadata, sp<IBinder>* handle,
- sp<IGraphicBufferProducer>* gbp, int32_t* outLayerId,
- uint32_t* outTransformHint) = 0;
-
- /*
- * Requires ACCESS_SURFACE_FLINGER permission
- */
- virtual status_t clearLayerFrameStats(const sp<IBinder>& handle) const = 0;
-
- /*
- * Requires ACCESS_SURFACE_FLINGER permission
- */
- virtual status_t getLayerFrameStats(const sp<IBinder>& handle, FrameStats* outStats) const = 0;
-
- virtual status_t mirrorSurface(const sp<IBinder>& mirrorFromHandle, sp<IBinder>* outHandle,
- int32_t* outLayerId) = 0;
-};
-
-class BnSurfaceComposerClient : public SafeBnInterface<ISurfaceComposerClient> {
-public:
- BnSurfaceComposerClient()
- : SafeBnInterface<ISurfaceComposerClient>("BnSurfaceComposerClient") {}
-
- status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override;
-};
-
-} // namespace android
diff --git a/libs/gui/include/gui/LayerDebugInfo.h b/libs/gui/include/gui/LayerDebugInfo.h
index af834d7..dbb80e5 100644
--- a/libs/gui/include/gui/LayerDebugInfo.h
+++ b/libs/gui/include/gui/LayerDebugInfo.h
@@ -25,7 +25,7 @@
#include <string>
#include <math/vec4.h>
-namespace android {
+namespace android::gui {
/* Class for transporting debug info from SurfaceFlinger to authorized
* recipients. The class is intended to be a data container. There are
@@ -52,7 +52,7 @@
uint32_t mZ = 0 ;
int32_t mWidth = -1;
int32_t mHeight = -1;
- Rect mCrop = Rect::INVALID_RECT;
+ android::Rect mCrop = android::Rect::INVALID_RECT;
half4 mColor = half4(1.0_hf, 1.0_hf, 1.0_hf, 0.0_hf);
uint32_t mFlags = 0;
PixelFormat mPixelFormat = PIXEL_FORMAT_NONE;
@@ -71,4 +71,4 @@
std::string to_string(const LayerDebugInfo& info);
-} // namespace android
+} // namespace android::gui
diff --git a/libs/gui/include/gui/LayerMetadata.h b/libs/gui/include/gui/LayerMetadata.h
index 27f4d37..5af5989 100644
--- a/libs/gui/include/gui/LayerMetadata.h
+++ b/libs/gui/include/gui/LayerMetadata.h
@@ -20,7 +20,7 @@
#include <unordered_map>
-namespace android {
+namespace android::gui {
enum {
METADATA_OWNER_UID = 1,
@@ -69,4 +69,13 @@
ftl_last = Battery
};
-} // namespace android
+} // namespace android::gui
+
+using android::gui::METADATA_ACCESSIBILITY_ID;
+using android::gui::METADATA_DEQUEUE_TIME;
+using android::gui::METADATA_GAME_MODE;
+using android::gui::METADATA_MOUSE_CURSOR;
+using android::gui::METADATA_OWNER_PID;
+using android::gui::METADATA_OWNER_UID;
+using android::gui::METADATA_TASK_ID;
+using android::gui::METADATA_WINDOW_TYPE;
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 0a9b75a..f3701e8 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -21,6 +21,7 @@
#include <stdint.h>
#include <sys/types.h>
+#include <android/gui/IWindowInfosReportedListener.h>
#include <android/native_window.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/ITransactionCompletedListener.h>
@@ -51,7 +52,9 @@
namespace android {
class Parcel;
-class ISurfaceComposerClient;
+
+using gui::ISurfaceComposerClient;
+using gui::LayerMetadata;
struct client_cache_t {
wp<IBinder> token = nullptr;
@@ -153,7 +156,7 @@
eLayerStackChanged = 0x00000080,
eDimmingEnabledChanged = 0x00000400,
eShadowRadiusChanged = 0x00000800,
- /* unused 0x00001000, */
+ eRenderBorderChanged = 0x00001000,
eBufferCropChanged = 0x00002000,
eRelativeLayerChanged = 0x00004000,
eReparent = 0x00008000,
@@ -163,7 +166,7 @@
eTransformToDisplayInverseChanged = 0x00080000,
eCropChanged = 0x00100000,
eBufferChanged = 0x00200000,
- /* unused 0x00400000, */
+ eDefaultFrameRateCompatibilityChanged = 0x00400000,
eDataspaceChanged = 0x00800000,
eHdrMetadataChanged = 0x01000000,
eSurfaceDamageRegionChanged = 0x02000000,
@@ -273,6 +276,9 @@
int8_t frameRateCompatibility;
int8_t changeFrameRateStrategy;
+ // Default frame rate compatibility used to set the layer refresh rate votetype.
+ int8_t defaultFrameRateCompatibility;
+
// Set by window manager indicating the layer and all its children are
// in a different orientation than the display. The hint suggests that
// the graphic producers should receive a transform hint as if the
@@ -291,6 +297,11 @@
// should be trusted for input occlusion detection purposes
bool isTrustedOverlay;
+ // Flag to indicate if border needs to be enabled on the layer
+ bool borderEnabled;
+ float borderWidth;
+ half4 borderColor;
+
// Stretch effect to be applied to this layer
StretchEffect stretchEffect;
@@ -352,7 +363,9 @@
struct InputWindowCommands {
std::vector<gui::FocusRequest> focusRequests;
- bool syncInputWindows{false};
+ std::unordered_set<sp<gui::IWindowInfosReportedListener>,
+ SpHash<gui::IWindowInfosReportedListener>>
+ windowInfosReportedListeners;
// Merges the passed in commands and returns true if there were any changes.
bool merge(const InputWindowCommands& other);
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index ab9ebaa..267c28f 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -17,8 +17,8 @@
#ifndef ANDROID_GUI_SURFACE_H
#define ANDROID_GUI_SURFACE_H
+#include <android/gui/FrameTimelineInfo.h>
#include <gui/BufferQueueDefs.h>
-#include <gui/FrameTimelineInfo.h>
#include <gui/HdrMetadata.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/IProducerListener.h>
@@ -41,6 +41,8 @@
class ISurfaceComposer;
+using gui::FrameTimelineInfo;
+
/* This is the same as ProducerListener except that onBuffersDiscarded is
* called with a vector of graphic buffers instead of buffer slots.
*/
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index b598b43..24399ff 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -38,6 +38,9 @@
#include <ui/GraphicTypes.h>
#include <ui/PixelFormat.h>
#include <ui/Rotation.h>
+#include <ui/StaticDisplayInfo.h>
+
+#include <android/gui/ISurfaceComposerClient.h>
#include <gui/CpuConsumer.h>
#include <gui/ISurfaceComposer.h>
@@ -52,14 +55,15 @@
namespace android {
class HdrCapabilities;
-class ISurfaceComposerClient;
class IGraphicBufferProducer;
class ITunnelModeEnabledListener;
class Region;
using gui::DisplayCaptureArgs;
using gui::IRegionSamplingListener;
+using gui::ISurfaceComposerClient;
using gui::LayerCaptureArgs;
+using gui::LayerMetadata;
struct SurfaceControlStats {
SurfaceControlStats(const sp<SurfaceControl>& sc, nsecs_t latchTime,
@@ -215,7 +219,7 @@
/**
* Gets the context priority of surface flinger's render engine.
*/
- static int getGPUContextPriority();
+ static int getGpuContextPriority();
/**
* Uncaches a buffer in ISurfaceComposer. It must be uncached via a transaction so that it is
@@ -311,7 +315,7 @@
uint32_t w, // width in pixel
uint32_t h, // height in pixel
PixelFormat format, // pixel-format desired
- uint32_t flags = 0, // usage flags
+ int32_t flags = 0, // usage flags
const sp<IBinder>& parentHandle = nullptr, // parentHandle
LayerMetadata metadata = LayerMetadata(), // metadata
uint32_t* outTransformHint = nullptr);
@@ -321,21 +325,11 @@
uint32_t h, // height in pixel
PixelFormat format, // pixel-format desired
sp<SurfaceControl>* outSurface,
- uint32_t flags = 0, // usage flags
+ int32_t flags = 0, // usage flags
const sp<IBinder>& parentHandle = nullptr, // parentHandle
LayerMetadata metadata = LayerMetadata(), // metadata
uint32_t* outTransformHint = nullptr);
- //! Create a surface
- sp<SurfaceControl> createWithSurfaceParent(const String8& name, // name of the surface
- uint32_t w, // width in pixel
- uint32_t h, // height in pixel
- PixelFormat format, // pixel-format desired
- uint32_t flags = 0, // usage flags
- Surface* parent = nullptr, // parent
- LayerMetadata metadata = LayerMetadata(), // metadata
- uint32_t* outTransformHint = nullptr);
-
// Creates a mirrored hierarchy for the mirrorFromSurface. This returns a SurfaceControl
// which is a parent of the root of the mirrored hierarchy.
//
@@ -393,9 +387,27 @@
std::unordered_set<sp<SurfaceControl>, SCHash> surfaceControls;
};
+ // TODO(b/222421815) this class should be removed when
+ // SurfaceComposerClient::Transaction::syncInputWindows is removed and replaced with a method
+ // for adding callbacks to InputWindowCommands.
+ class Event {
+ private:
+ static constexpr std::chrono::seconds sTimeout{5};
+
+ bool mComplete = false;
+ std::condition_variable mConditionVariable;
+ std::mutex mMutex;
+
+ public:
+ void set();
+ bool wait();
+ };
+
class Transaction : public Parcelable {
private:
void releaseBufferIfOverwriting(const layer_state_t& state);
+ static void mergeFrameTimelineInfo(FrameTimelineInfo& t, const FrameTimelineInfo& other);
+ static void clearFrameTimelineInfo(FrameTimelineInfo& t);
protected:
std::unordered_map<sp<IBinder>, ComposerState, IBinderHash> mComposerStates;
@@ -440,6 +452,8 @@
InputWindowCommands mInputWindowCommands;
int mStatus = NO_ERROR;
+ std::shared_ptr<Event> mWindowInfosReportedEvent = nullptr;
+
layer_state_t* getLayerState(const sp<SurfaceControl>& sc);
DisplayState& getDisplayState(const sp<IBinder>& token);
@@ -587,6 +601,9 @@
Transaction& setFrameRate(const sp<SurfaceControl>& sc, float frameRate,
int8_t compatibility, int8_t changeFrameRateStrategy);
+ Transaction& setDefaultFrameRateCompatibility(const sp<SurfaceControl>& sc,
+ int8_t compatibility);
+
// Set by window manager indicating the layer and all its children are
// in a different orientation than the display. The hint suggests that
// the graphic producers should receive a transform hint as if the
@@ -633,6 +650,9 @@
const Rect& destinationFrame);
Transaction& setDropInputMode(const sp<SurfaceControl>& sc, gui::DropInputMode mode);
+ Transaction& enableBorder(const sp<SurfaceControl>& sc, bool shouldEnable, float width,
+ const half4& color);
+
status_t setDisplaySurface(const sp<IBinder>& token,
const sp<IGraphicBufferProducer>& bufferProducer);
diff --git a/libs/gui/include/gui/SurfaceControl.h b/libs/gui/include/gui/SurfaceControl.h
index b72cf83..e4a1350 100644
--- a/libs/gui/include/gui/SurfaceControl.h
+++ b/libs/gui/include/gui/SurfaceControl.h
@@ -24,11 +24,12 @@
#include <utils/RefBase.h>
#include <utils/threads.h>
+#include <android/gui/ISurfaceComposerClient.h>
+
#include <ui/FrameStats.h>
#include <ui/PixelFormat.h>
#include <ui/Region.h>
-#include <gui/ISurfaceComposerClient.h>
#include <math/vec3.h>
namespace android {
@@ -93,8 +94,7 @@
explicit SurfaceControl(const sp<SurfaceControl>& other);
SurfaceControl(const sp<SurfaceComposerClient>& client, const sp<IBinder>& handle,
- const sp<IGraphicBufferProducer>& gbp, int32_t layerId,
- uint32_t width = 0, uint32_t height = 0, PixelFormat format = 0,
+ int32_t layerId, uint32_t width = 0, uint32_t height = 0, PixelFormat format = 0,
uint32_t transformHint = 0, uint32_t flags = 0);
sp<SurfaceControl> getParentingLayer();
@@ -115,8 +115,7 @@
status_t validate() const;
sp<SurfaceComposerClient> mClient;
- sp<IBinder> mHandle;
- sp<IGraphicBufferProducer> mGraphicBufferProducer;
+ sp<IBinder> mHandle;
mutable Mutex mLock;
mutable sp<Surface> mSurfaceData;
mutable sp<BLASTBufferQueue> mBbq;
diff --git a/libs/gui/include/gui/TraceUtils.h b/libs/gui/include/gui/TraceUtils.h
index e5d2684..0009615 100644
--- a/libs/gui/include/gui/TraceUtils.h
+++ b/libs/gui/include/gui/TraceUtils.h
@@ -27,6 +27,8 @@
#define ATRACE_FORMAT_BEGIN(fmt, ...) TraceUtils::atraceFormatBegin(fmt, ##__VA_ARGS__)
+#define ATRACE_FORMAT_INSTANT(fmt, ...) TraceUtils::intantFormat(fmt, ##__VA_ARGS__)
+
namespace android {
class TraceUtils {
@@ -50,6 +52,20 @@
ATRACE_BEGIN(buf);
}
+ static void intantFormat(const char* fmt, ...) {
+ if (CC_LIKELY(!ATRACE_ENABLED())) return;
+
+ const int BUFFER_SIZE = 256;
+ va_list ap;
+ char buf[BUFFER_SIZE];
+
+ va_start(ap, fmt);
+ vsnprintf(buf, BUFFER_SIZE, fmt, ap);
+ va_end(ap);
+
+ ATRACE_INSTANT(buf);
+ }
+
}; // class TraceUtils
} /* namespace android */
diff --git a/libs/gui/include/gui/VsyncEventData.h b/libs/gui/include/gui/VsyncEventData.h
index 8e99539..dfdae21 100644
--- a/libs/gui/include/gui/VsyncEventData.h
+++ b/libs/gui/include/gui/VsyncEventData.h
@@ -16,7 +16,7 @@
#pragma once
-#include <gui/FrameTimelineInfo.h>
+#include <android/gui/FrameTimelineInfo.h>
#include <array>
diff --git a/libs/gui/include/gui/WindowInfo.h b/libs/gui/include/gui/WindowInfo.h
index 169f7f0..ac74c8a 100644
--- a/libs/gui/include/gui/WindowInfo.h
+++ b/libs/gui/include/gui/WindowInfo.h
@@ -171,6 +171,8 @@
static_cast<uint32_t>(os::InputConfig::SPY),
INTERCEPTS_STYLUS =
static_cast<uint32_t>(os::InputConfig::INTERCEPTS_STYLUS),
+ CLONE =
+ static_cast<uint32_t>(os::InputConfig::CLONE),
// clang-format on
};
@@ -236,8 +238,6 @@
void setInputConfig(ftl::Flags<InputConfig> config, bool value);
- bool isClone = false;
-
void addTouchableRegion(const Rect& region);
bool touchableRegionContainsPoint(int32_t x, int32_t y) const;
diff --git a/libs/gui/include/gui/WindowInfosListenerReporter.h b/libs/gui/include/gui/WindowInfosListenerReporter.h
index 3b4aed4..2754442 100644
--- a/libs/gui/include/gui/WindowInfosListenerReporter.h
+++ b/libs/gui/include/gui/WindowInfosListenerReporter.h
@@ -17,15 +17,14 @@
#pragma once
#include <android/gui/BnWindowInfosListener.h>
+#include <android/gui/ISurfaceComposer.h>
#include <android/gui/IWindowInfosReportedListener.h>
#include <binder/IBinder.h>
-#include <gui/ISurfaceComposer.h>
#include <gui/SpHash.h>
#include <gui/WindowInfosListener.h>
#include <unordered_set>
namespace android {
-class ISurfaceComposer;
class WindowInfosListenerReporter : public gui::BnWindowInfosListener {
public:
@@ -33,17 +32,17 @@
binder::Status onWindowInfosChanged(const std::vector<gui::WindowInfo>&,
const std::vector<gui::DisplayInfo>&,
const sp<gui::IWindowInfosReportedListener>&) override;
-
status_t addWindowInfosListener(
- const sp<gui::WindowInfosListener>& windowInfosListener, const sp<ISurfaceComposer>&,
+ const sp<gui::WindowInfosListener>& windowInfosListener,
+ const sp<gui::ISurfaceComposer>&,
std::pair<std::vector<gui::WindowInfo>, std::vector<gui::DisplayInfo>>* outInitialInfo);
status_t removeWindowInfosListener(const sp<gui::WindowInfosListener>& windowInfosListener,
- const sp<ISurfaceComposer>& surfaceComposer);
- void reconnect(const sp<ISurfaceComposer>&);
+ const sp<gui::ISurfaceComposer>& surfaceComposer);
+ void reconnect(const sp<gui::ISurfaceComposer>&);
private:
std::mutex mListenersMutex;
- std::unordered_set<sp<gui::WindowInfosListener>, SpHash<gui::WindowInfosListener>>
+ std::unordered_set<sp<gui::WindowInfosListener>, gui::SpHash<gui::WindowInfosListener>>
mWindowInfosListeners GUARDED_BY(mListenersMutex);
std::vector<gui::WindowInfo> mLastWindowInfos GUARDED_BY(mListenersMutex);
diff --git a/libs/gui/include/private/gui/ComposerServiceAIDL.h b/libs/gui/include/private/gui/ComposerServiceAIDL.h
index 9a96976..2963583 100644
--- a/libs/gui/include/private/gui/ComposerServiceAIDL.h
+++ b/libs/gui/include/private/gui/ComposerServiceAIDL.h
@@ -20,6 +20,7 @@
#include <sys/types.h>
#include <android/gui/ISurfaceComposer.h>
+#include <ui/DisplayId.h>
#include <utils/Singleton.h>
#include <utils/StrongPointer.h>
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index fc68ad2..7b37b25 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -24,6 +24,7 @@
"BLASTBufferQueue_test.cpp",
"BufferItemConsumer_test.cpp",
"BufferQueue_test.cpp",
+ "CompositorTiming_test.cpp",
"CpuConsumer_test.cpp",
"EndToEndNativeInputTest.cpp",
"DisplayInfo_test.cpp",
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
index b993289..3e563b2 100644
--- a/libs/gui/tests/BLASTBufferQueue_test.cpp
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -19,6 +19,7 @@
#include <gui/BLASTBufferQueue.h>
#include <android/hardware/graphics/common/1.2/types.h>
+#include <gui/AidlStatusUtil.h>
#include <gui/BufferQueueCore.h>
#include <gui/BufferQueueProducer.h>
#include <gui/FrameTimestamps.h>
@@ -305,8 +306,9 @@
const sp<SyncScreenCaptureListener> captureListener = new SyncScreenCaptureListener();
binder::Status status = sf->captureDisplay(captureArgs, captureListener);
- if (status.transactionError() != NO_ERROR) {
- return status.transactionError();
+ status_t err = gui::aidl_utils::statusTFromBinderStatus(status);
+ if (err != NO_ERROR) {
+ return err;
}
captureResults = captureListener->waitForResults();
return captureResults.result;
@@ -1146,6 +1148,7 @@
ASSERT_EQ(NO_ERROR, captureDisplay(mCaptureArgs, mCaptureResults));
ASSERT_NO_FATAL_FAILURE(
checkScreenCapture(r, g, b, {0, 0, (int32_t)mDisplayWidth, (int32_t)mDisplayHeight}));
+ sync.apply();
}
// This test will currently fail because the old surfacecontrol will steal the last presented buffer
diff --git a/libs/gui/tests/CompositorTiming_test.cpp b/libs/gui/tests/CompositorTiming_test.cpp
new file mode 100644
index 0000000..d8bb21d
--- /dev/null
+++ b/libs/gui/tests/CompositorTiming_test.cpp
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+#include <gtest/gtest.h>
+#include <gui/CompositorTiming.h>
+
+namespace android::test {
+namespace {
+
+constexpr nsecs_t kMillisecond = 1'000'000;
+constexpr nsecs_t kVsyncPeriod = 8'333'333;
+constexpr nsecs_t kVsyncPhase = -2'166'667;
+constexpr nsecs_t kIdealLatency = -kVsyncPhase;
+
+} // namespace
+
+TEST(CompositorTimingTest, InvalidVsyncPeriod) {
+ const nsecs_t vsyncDeadline = systemTime();
+ constexpr nsecs_t kInvalidVsyncPeriod = -1;
+
+ const gui::CompositorTiming timing(vsyncDeadline, kInvalidVsyncPeriod, kVsyncPhase,
+ kIdealLatency);
+
+ EXPECT_EQ(timing.deadline, 0);
+ EXPECT_EQ(timing.interval, gui::CompositorTiming::kDefaultVsyncPeriod);
+ EXPECT_EQ(timing.presentLatency, gui::CompositorTiming::kDefaultVsyncPeriod);
+}
+
+TEST(CompositorTimingTest, PresentLatencySnapping) {
+ for (nsecs_t presentDelay = 0, compositeTime = systemTime(); presentDelay < 10 * kVsyncPeriod;
+ presentDelay += kMillisecond, compositeTime += kVsyncPeriod) {
+ const nsecs_t presentLatency = kIdealLatency + presentDelay;
+ const nsecs_t vsyncDeadline = compositeTime + presentLatency + kVsyncPeriod;
+
+ const gui::CompositorTiming timing(vsyncDeadline, kVsyncPeriod, kVsyncPhase,
+ presentLatency);
+
+ EXPECT_EQ(timing.deadline, compositeTime + presentDelay + kVsyncPeriod);
+ EXPECT_EQ(timing.interval, kVsyncPeriod);
+
+ // The presentDelay should be rounded to a multiple of the VSYNC period, such that the
+ // remainder (presentLatency % interval) always evaluates to the VSYNC phase offset.
+ EXPECT_GE(timing.presentLatency, kIdealLatency);
+ EXPECT_EQ(timing.presentLatency % timing.interval, kIdealLatency);
+ }
+}
+
+} // namespace android::test
diff --git a/libs/gui/tests/RegionSampling_test.cpp b/libs/gui/tests/RegionSampling_test.cpp
index c9106be..b18b544 100644
--- a/libs/gui/tests/RegionSampling_test.cpp
+++ b/libs/gui/tests/RegionSampling_test.cpp
@@ -19,14 +19,16 @@
#include <android/gui/BnRegionSamplingListener.h>
#include <binder/ProcessState.h>
+#include <gui/AidlStatusUtil.h>
#include <gui/DisplayEventReceiver.h>
#include <gui/ISurfaceComposer.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
-#include <private/gui/ComposerService.h>
+#include <private/gui/ComposerServiceAIDL.h>
#include <utils/Looper.h>
using namespace std::chrono_literals;
+using android::gui::aidl_utils::statusTFromBinderStatus;
namespace android::test {
@@ -242,24 +244,33 @@
};
TEST_F(RegionSamplingTest, invalidLayerHandle_doesNotCrash) {
- sp<ISurfaceComposer> composer = ComposerService::getComposerService();
+ sp<gui::ISurfaceComposer> composer = ComposerServiceAIDL::getComposerService();
sp<Listener> listener = new Listener();
- const Rect sampleArea{100, 100, 200, 200};
+ gui::ARect sampleArea;
+ sampleArea.left = 100;
+ sampleArea.top = 100;
+ sampleArea.right = 200;
+ sampleArea.bottom = 200;
// Passing in composer service as the layer handle should not crash, we'll
// treat it as a layer that no longer exists and silently allow sampling to
// occur.
- status_t status = composer->addRegionSamplingListener(sampleArea,
- IInterface::asBinder(composer), listener);
- ASSERT_EQ(NO_ERROR, status);
+ binder::Status status =
+ composer->addRegionSamplingListener(sampleArea, IInterface::asBinder(composer),
+ listener);
+ ASSERT_EQ(NO_ERROR, statusTFromBinderStatus(status));
composer->removeRegionSamplingListener(listener);
}
TEST_F(RegionSamplingTest, DISABLED_CollectsLuma) {
fill_render(rgba_green);
- sp<ISurfaceComposer> composer = ComposerService::getComposerService();
+ sp<gui::ISurfaceComposer> composer = ComposerServiceAIDL::getComposerService();
sp<Listener> listener = new Listener();
- const Rect sampleArea{100, 100, 200, 200};
+ gui::ARect sampleArea;
+ sampleArea.left = 100;
+ sampleArea.top = 100;
+ sampleArea.right = 200;
+ sampleArea.bottom = 200;
composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), listener);
EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received";
@@ -271,9 +282,13 @@
TEST_F(RegionSamplingTest, DISABLED_CollectsChangingLuma) {
fill_render(rgba_green);
- sp<ISurfaceComposer> composer = ComposerService::getComposerService();
+ sp<gui::ISurfaceComposer> composer = ComposerServiceAIDL::getComposerService();
sp<Listener> listener = new Listener();
- const Rect sampleArea{100, 100, 200, 200};
+ gui::ARect sampleArea;
+ sampleArea.left = 100;
+ sampleArea.top = 100;
+ sampleArea.right = 200;
+ sampleArea.bottom = 200;
composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), listener);
EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received";
@@ -291,13 +306,21 @@
TEST_F(RegionSamplingTest, DISABLED_CollectsLumaFromTwoRegions) {
fill_render(rgba_green);
- sp<ISurfaceComposer> composer = ComposerService::getComposerService();
+ sp<gui::ISurfaceComposer> composer = ComposerServiceAIDL::getComposerService();
sp<Listener> greenListener = new Listener();
- const Rect greenSampleArea{100, 100, 200, 200};
+ gui::ARect greenSampleArea;
+ greenSampleArea.left = 100;
+ greenSampleArea.top = 100;
+ greenSampleArea.right = 200;
+ greenSampleArea.bottom = 200;
composer->addRegionSamplingListener(greenSampleArea, mTopLayer->getHandle(), greenListener);
sp<Listener> grayListener = new Listener();
- const Rect graySampleArea{500, 100, 600, 200};
+ gui::ARect graySampleArea;
+ graySampleArea.left = 500;
+ graySampleArea.top = 100;
+ graySampleArea.right = 600;
+ graySampleArea.bottom = 200;
composer->addRegionSamplingListener(graySampleArea, mTopLayer->getHandle(), grayListener);
EXPECT_TRUE(grayListener->wait_event(300ms))
@@ -312,29 +335,49 @@
}
TEST_F(RegionSamplingTest, DISABLED_TestIfInvalidInputParameters) {
- sp<ISurfaceComposer> composer = ComposerService::getComposerService();
+ sp<gui::ISurfaceComposer> composer = ComposerServiceAIDL::getComposerService();
sp<Listener> listener = new Listener();
- const Rect sampleArea{100, 100, 200, 200};
+
+ gui::ARect invalidRect;
+ invalidRect.left = Rect::INVALID_RECT.left;
+ invalidRect.top = Rect::INVALID_RECT.top;
+ invalidRect.right = Rect::INVALID_RECT.right;
+ invalidRect.bottom = Rect::INVALID_RECT.bottom;
+
+ gui::ARect sampleArea;
+ sampleArea.left = 100;
+ sampleArea.top = 100;
+ sampleArea.right = 200;
+ sampleArea.bottom = 200;
// Invalid input sampleArea
EXPECT_EQ(BAD_VALUE,
- composer->addRegionSamplingListener(Rect::INVALID_RECT, mTopLayer->getHandle(),
- listener));
+ statusTFromBinderStatus(composer->addRegionSamplingListener(invalidRect,
+ mTopLayer->getHandle(),
+ listener)));
listener->reset();
// Invalid input binder
- EXPECT_EQ(NO_ERROR, composer->addRegionSamplingListener(sampleArea, NULL, listener));
+ EXPECT_EQ(NO_ERROR,
+ statusTFromBinderStatus(
+ composer->addRegionSamplingListener(sampleArea, NULL, listener)));
// Invalid input listener
EXPECT_EQ(BAD_VALUE,
- composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), NULL));
- EXPECT_EQ(BAD_VALUE, composer->removeRegionSamplingListener(NULL));
+ statusTFromBinderStatus(composer->addRegionSamplingListener(sampleArea,
+ mTopLayer->getHandle(),
+ NULL)));
+ EXPECT_EQ(BAD_VALUE, statusTFromBinderStatus(composer->removeRegionSamplingListener(NULL)));
// remove the listener
composer->removeRegionSamplingListener(listener);
}
TEST_F(RegionSamplingTest, DISABLED_TestCallbackAfterRemoveListener) {
fill_render(rgba_green);
- sp<ISurfaceComposer> composer = ComposerService::getComposerService();
+ sp<gui::ISurfaceComposer> composer = ComposerServiceAIDL::getComposerService();
sp<Listener> listener = new Listener();
- const Rect sampleArea{100, 100, 200, 200};
+ gui::ARect sampleArea;
+ sampleArea.left = 100;
+ sampleArea.top = 100;
+ sampleArea.right = 200;
+ sampleArea.bottom = 200;
composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), listener);
fill_render(rgba_green);
@@ -349,13 +392,18 @@
}
TEST_F(RegionSamplingTest, DISABLED_CollectsLumaFromMovingLayer) {
- sp<ISurfaceComposer> composer = ComposerService::getComposerService();
+ sp<gui::ISurfaceComposer> composer = ComposerServiceAIDL::getComposerService();
sp<Listener> listener = new Listener();
Rect sampleArea{100, 100, 200, 200};
+ gui::ARect sampleAreaA;
+ sampleAreaA.left = sampleArea.left;
+ sampleAreaA.top = sampleArea.top;
+ sampleAreaA.right = sampleArea.right;
+ sampleAreaA.bottom = sampleArea.bottom;
// Test: listener in (100, 100). See layer before move, no layer after move.
fill_render(rgba_blue);
- composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), listener);
+ composer->addRegionSamplingListener(sampleAreaA, mTopLayer->getHandle(), listener);
EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received";
EXPECT_NEAR(listener->luma(), luma_blue, error_margin);
listener->reset();
@@ -367,7 +415,11 @@
// Test: listener offset to (600, 600). No layer before move, see layer after move.
fill_render(rgba_green);
sampleArea.offsetTo(600, 600);
- composer->addRegionSamplingListener(sampleArea, mTopLayer->getHandle(), listener);
+ sampleAreaA.left = sampleArea.left;
+ sampleAreaA.top = sampleArea.top;
+ sampleAreaA.right = sampleArea.right;
+ sampleAreaA.bottom = sampleArea.bottom;
+ composer->addRegionSamplingListener(sampleAreaA, mTopLayer->getHandle(), listener);
EXPECT_TRUE(listener->wait_event(300ms)) << "timed out waiting for luma event to be received";
EXPECT_NEAR(listener->luma(), luma_gray, error_margin);
listener->reset();
diff --git a/libs/gui/tests/SamplingDemo.cpp b/libs/gui/tests/SamplingDemo.cpp
index a083a22..f98437b 100644
--- a/libs/gui/tests/SamplingDemo.cpp
+++ b/libs/gui/tests/SamplingDemo.cpp
@@ -26,7 +26,7 @@
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
#include <gui/SurfaceControl.h>
-#include <private/gui/ComposerService.h>
+#include <private/gui/ComposerServiceAIDL.h>
#include <utils/Trace.h>
using namespace std::chrono_literals;
@@ -121,10 +121,22 @@
const Rect backButtonArea{200, 1606, 248, 1654};
sp<android::Button> backButton = new android::Button("BackButton", backButtonArea);
- sp<ISurfaceComposer> composer = ComposerService::getComposerService();
- composer->addRegionSamplingListener(homeButtonArea, homeButton->getStopLayerHandle(),
+ gui::ARect homeButtonAreaA;
+ homeButtonAreaA.left = 490;
+ homeButtonAreaA.top = 1606;
+ homeButtonAreaA.right = 590;
+ homeButtonAreaA.bottom = 1654;
+
+ gui::ARect backButtonAreaA;
+ backButtonAreaA.left = 200;
+ backButtonAreaA.top = 1606;
+ backButtonAreaA.right = 248;
+ backButtonAreaA.bottom = 1654;
+
+ sp<gui::ISurfaceComposer> composer = ComposerServiceAIDL::getComposerService();
+ composer->addRegionSamplingListener(homeButtonAreaA, homeButton->getStopLayerHandle(),
homeButton);
- composer->addRegionSamplingListener(backButtonArea, backButton->getStopLayerHandle(),
+ composer->addRegionSamplingListener(backButtonAreaA, backButton->getStopLayerHandle(),
backButton);
ProcessState::self()->startThreadPool();
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 065cd7a..391a0aa 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -24,6 +24,7 @@
#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
#include <binder/ProcessState.h>
#include <configstore/Utils.h>
+#include <gui/AidlStatusUtil.h>
#include <gui/BufferItemConsumer.h>
#include <gui/IProducerListener.h>
#include <gui/ISurfaceComposer.h>
@@ -212,8 +213,9 @@
const sp<SyncScreenCaptureListener> captureListener = new SyncScreenCaptureListener();
binder::Status status = sf->captureDisplay(captureArgs, captureListener);
- if (status.transactionError() != NO_ERROR) {
- return status.transactionError();
+ status_t err = gui::aidl_utils::statusTFromBinderStatus(status);
+ if (err != NO_ERROR) {
+ return err;
}
captureResults = captureListener->waitForResults();
return captureResults.result;
@@ -690,11 +692,6 @@
mSupportsPresent = supportsPresent;
}
- sp<ISurfaceComposerClient> createConnection() override { return nullptr; }
- sp<IDisplayEventConnection> createDisplayEventConnection(
- ISurfaceComposer::VsyncSource, ISurfaceComposer::EventRegistrationFlags) override {
- return nullptr;
- }
status_t setTransactionState(const FrameTimelineInfo& /*frameTimelineInfo*/,
const Vector<ComposerState>& /*state*/,
const Vector<DisplayState>& /*displays*/, uint32_t /*flags*/,
@@ -708,179 +705,6 @@
return NO_ERROR;
}
- void bootFinished() override {}
- bool authenticateSurfaceTexture(
- const sp<IGraphicBufferProducer>& /*surface*/) const override {
- return false;
- }
-
- status_t getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported)
- const override {
- *outSupported = {
- FrameEvent::REQUESTED_PRESENT,
- FrameEvent::ACQUIRE,
- FrameEvent::LATCH,
- FrameEvent::FIRST_REFRESH_START,
- FrameEvent::LAST_REFRESH_START,
- FrameEvent::GPU_COMPOSITION_DONE,
- FrameEvent::DEQUEUE_READY,
- FrameEvent::RELEASE
- };
- if (mSupportsPresent) {
- outSupported->push_back(
- FrameEvent::DISPLAY_PRESENT);
- }
- return NO_ERROR;
- }
-
- status_t getStaticDisplayInfo(const sp<IBinder>& /*display*/, ui::StaticDisplayInfo*) override {
- return NO_ERROR;
- }
- status_t getDynamicDisplayInfo(const sp<IBinder>& /*display*/,
- ui::DynamicDisplayInfo*) override {
- return NO_ERROR;
- }
- status_t getDisplayNativePrimaries(const sp<IBinder>& /*display*/,
- ui::DisplayPrimaries& /*primaries*/) override {
- return NO_ERROR;
- }
- status_t setActiveColorMode(const sp<IBinder>& /*display*/, ColorMode /*colorMode*/) override {
- return NO_ERROR;
- }
- status_t setBootDisplayMode(const sp<IBinder>& /*display*/, ui::DisplayModeId /*id*/) override {
- return NO_ERROR;
- }
-
- status_t clearAnimationFrameStats() override { return NO_ERROR; }
- status_t getAnimationFrameStats(FrameStats* /*outStats*/) const override {
- return NO_ERROR;
- }
- status_t overrideHdrTypes(const sp<IBinder>& /*display*/,
- const std::vector<ui::Hdr>& /*hdrTypes*/) override {
- return NO_ERROR;
- }
- status_t onPullAtom(const int32_t /*atomId*/, std::string* /*outData*/,
- bool* /*success*/) override {
- return NO_ERROR;
- }
- status_t enableVSyncInjections(bool /*enable*/) override {
- return NO_ERROR;
- }
- status_t injectVSync(nsecs_t /*when*/) override { return NO_ERROR; }
- status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* /*layers*/) override {
- return NO_ERROR;
- }
- status_t getCompositionPreference(
- ui::Dataspace* /*outDefaultDataspace*/, ui::PixelFormat* /*outDefaultPixelFormat*/,
- ui::Dataspace* /*outWideColorGamutDataspace*/,
- ui::PixelFormat* /*outWideColorGamutPixelFormat*/) const override {
- return NO_ERROR;
- }
- status_t getDisplayedContentSamplingAttributes(const sp<IBinder>& /*display*/,
- ui::PixelFormat* /*outFormat*/,
- ui::Dataspace* /*outDataspace*/,
- uint8_t* /*outComponentMask*/) const override {
- return NO_ERROR;
- }
- status_t setDisplayContentSamplingEnabled(const sp<IBinder>& /*display*/, bool /*enable*/,
- uint8_t /*componentMask*/,
- uint64_t /*maxFrames*/) override {
- return NO_ERROR;
- }
- status_t getDisplayedContentSample(const sp<IBinder>& /*display*/, uint64_t /*maxFrames*/,
- uint64_t /*timestamp*/,
- DisplayedFrameStats* /*outStats*/) const override {
- return NO_ERROR;
- }
-
- status_t getColorManagement(bool* /*outGetColorManagement*/) const override { return NO_ERROR; }
- status_t getProtectedContentSupport(bool* /*outSupported*/) const override { return NO_ERROR; }
-
- status_t addRegionSamplingListener(const Rect& /*samplingArea*/,
- const sp<IBinder>& /*stopLayerHandle*/,
- const sp<IRegionSamplingListener>& /*listener*/) override {
- return NO_ERROR;
- }
- status_t removeRegionSamplingListener(
- const sp<IRegionSamplingListener>& /*listener*/) override {
- return NO_ERROR;
- }
- status_t addFpsListener(int32_t /*taskId*/, const sp<gui::IFpsListener>& /*listener*/) {
- return NO_ERROR;
- }
- status_t removeFpsListener(const sp<gui::IFpsListener>& /*listener*/) { return NO_ERROR; }
-
- status_t addTunnelModeEnabledListener(const sp<gui::ITunnelModeEnabledListener>& /*listener*/) {
- return NO_ERROR;
- }
-
- status_t removeTunnelModeEnabledListener(
- const sp<gui::ITunnelModeEnabledListener>& /*listener*/) {
- return NO_ERROR;
- }
-
- status_t setDesiredDisplayModeSpecs(const sp<IBinder>& /*displayToken*/,
- ui::DisplayModeId /*defaultMode*/,
- bool /*allowGroupSwitching*/,
- float /*primaryRefreshRateMin*/,
- float /*primaryRefreshRateMax*/,
- float /*appRequestRefreshRateMin*/,
- float /*appRequestRefreshRateMax*/) {
- return NO_ERROR;
- }
- status_t getDesiredDisplayModeSpecs(const sp<IBinder>& /*displayToken*/,
- ui::DisplayModeId* /*outDefaultMode*/,
- bool* /*outAllowGroupSwitching*/,
- float* /*outPrimaryRefreshRateMin*/,
- float* /*outPrimaryRefreshRateMax*/,
- float* /*outAppRequestRefreshRateMin*/,
- float* /*outAppRequestRefreshRateMax*/) override {
- return NO_ERROR;
- };
-
- status_t setGlobalShadowSettings(const half4& /*ambientColor*/, const half4& /*spotColor*/,
- float /*lightPosY*/, float /*lightPosZ*/,
- float /*lightRadius*/) override {
- return NO_ERROR;
- }
-
- status_t getDisplayDecorationSupport(
- const sp<IBinder>& /*displayToken*/,
- std::optional<DisplayDecorationSupport>* /*outSupport*/) const override {
- return NO_ERROR;
- }
-
- status_t setFrameRate(const sp<IGraphicBufferProducer>& /*surface*/, float /*frameRate*/,
- int8_t /*compatibility*/, int8_t /*changeFrameRateStrategy*/) override {
- return NO_ERROR;
- }
-
- status_t setFrameTimelineInfo(const sp<IGraphicBufferProducer>& /*surface*/,
- const FrameTimelineInfo& /*frameTimelineInfo*/) override {
- return NO_ERROR;
- }
-
- status_t addTransactionTraceListener(
- const sp<gui::ITransactionTraceListener>& /*listener*/) override {
- return NO_ERROR;
- }
-
- int getGPUContextPriority() override { return 0; };
-
- status_t getMaxAcquiredBufferCount(int* /*buffers*/) const override { return NO_ERROR; }
-
- status_t addWindowInfosListener(
- const sp<gui::IWindowInfosListener>& /*windowInfosListener*/) const override {
- return NO_ERROR;
- }
-
- status_t removeWindowInfosListener(
- const sp<gui::IWindowInfosListener>& /*windowInfosListener*/) const override {
- return NO_ERROR;
- }
-
- status_t setOverrideFrameRate(uid_t /*uid*/, float /*frameRate*/) override { return NO_ERROR; }
-
protected:
IBinder* onAsBinder() override { return nullptr; }
@@ -894,6 +718,20 @@
void setSupportsPresent(bool supportsPresent) { mSupportsPresent = supportsPresent; }
+ binder::Status bootFinished() override { return binder::Status::ok(); }
+
+ binder::Status createDisplayEventConnection(
+ VsyncSource /*vsyncSource*/, EventRegistration /*eventRegistration*/,
+ sp<gui::IDisplayEventConnection>* outConnection) override {
+ *outConnection = nullptr;
+ return binder::Status::ok();
+ }
+
+ binder::Status createConnection(sp<gui::ISurfaceComposerClient>* outClient) override {
+ *outClient = nullptr;
+ return binder::Status::ok();
+ }
+
binder::Status createDisplay(const std::string& /*displayName*/, bool /*secure*/,
sp<IBinder>* /*outDisplay*/) override {
return binder::Status::ok();
@@ -920,6 +758,21 @@
return binder::Status::ok();
}
+ binder::Status getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported) override {
+ *outSupported = {FrameEvent::REQUESTED_PRESENT,
+ FrameEvent::ACQUIRE,
+ FrameEvent::LATCH,
+ FrameEvent::FIRST_REFRESH_START,
+ FrameEvent::LAST_REFRESH_START,
+ FrameEvent::GPU_COMPOSITION_DONE,
+ FrameEvent::DEQUEUE_READY,
+ FrameEvent::RELEASE};
+ if (mSupportsPresent) {
+ outSupported->push_back(FrameEvent::DISPLAY_PRESENT);
+ }
+ return binder::Status::ok();
+ }
+
binder::Status getDisplayStats(const sp<IBinder>& /*display*/,
gui::DisplayStatInfo* /*outStatInfo*/) override {
return binder::Status::ok();
@@ -930,6 +783,30 @@
return binder::Status::ok();
}
+ binder::Status getStaticDisplayInfo(const sp<IBinder>& /*display*/,
+ gui::StaticDisplayInfo* /*outInfo*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status getDynamicDisplayInfo(const sp<IBinder>& /*display*/,
+ gui::DynamicDisplayInfo* /*outInfo*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status getDisplayNativePrimaries(const sp<IBinder>& /*display*/,
+ gui::DisplayPrimaries* /*outPrimaries*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status setActiveColorMode(const sp<IBinder>& /*display*/, int /*colorMode*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status setBootDisplayMode(const sp<IBinder>& /*display*/,
+ int /*displayModeId*/) override {
+ return binder::Status::ok();
+ }
+
binder::Status clearBootDisplayMode(const sp<IBinder>& /*display*/) override {
return binder::Status::ok();
}
@@ -960,11 +837,107 @@
return binder::Status::ok();
}
+ binder::Status clearAnimationFrameStats() override { return binder::Status::ok(); }
+
+ binder::Status getAnimationFrameStats(gui::FrameStats* /*outStats*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status overrideHdrTypes(const sp<IBinder>& /*display*/,
+ const std::vector<int32_t>& /*hdrTypes*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status onPullAtom(int32_t /*atomId*/, gui::PullAtomData* /*outPullData*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status enableVSyncInjections(bool /*enable*/) override { return binder::Status::ok(); }
+
+ binder::Status injectVSync(int64_t /*when*/) override { return binder::Status::ok(); }
+
+ binder::Status getLayerDebugInfo(std::vector<gui::LayerDebugInfo>* /*outLayers*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status getColorManagement(bool* /*outGetColorManagement*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status getCompositionPreference(gui::CompositionPreference* /*outPref*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status getDisplayedContentSamplingAttributes(
+ const sp<IBinder>& /*display*/, gui::ContentSamplingAttributes* /*outAttrs*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status setDisplayContentSamplingEnabled(const sp<IBinder>& /*display*/, bool /*enable*/,
+ int8_t /*componentMask*/,
+ int64_t /*maxFrames*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status getProtectedContentSupport(bool* /*outSupporte*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status getDisplayedContentSample(const sp<IBinder>& /*display*/, int64_t /*maxFrames*/,
+ int64_t /*timestamp*/,
+ gui::DisplayedFrameStats* /*outStats*/) override {
+ return binder::Status::ok();
+ }
+
binder::Status isWideColorDisplay(const sp<IBinder>& /*token*/,
bool* /*outIsWideColorDisplay*/) override {
return binder::Status::ok();
}
+ binder::Status addRegionSamplingListener(
+ const gui::ARect& /*samplingArea*/, const sp<IBinder>& /*stopLayerHandle*/,
+ const sp<gui::IRegionSamplingListener>& /*listener*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status removeRegionSamplingListener(
+ const sp<gui::IRegionSamplingListener>& /*listener*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status addFpsListener(int32_t /*taskId*/,
+ const sp<gui::IFpsListener>& /*listener*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status removeFpsListener(const sp<gui::IFpsListener>& /*listener*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status addTunnelModeEnabledListener(
+ const sp<gui::ITunnelModeEnabledListener>& /*listener*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status removeTunnelModeEnabledListener(
+ const sp<gui::ITunnelModeEnabledListener>& /*listener*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status setDesiredDisplayModeSpecs(const sp<IBinder>& /*displayToken*/,
+ int32_t /*defaultMode*/, bool /*allowGroupSwitching*/,
+ float /*primaryRefreshRateMin*/,
+ float /*primaryRefreshRateMax*/,
+ float /*appRequestRefreshRateMin*/,
+ float /*appRequestRefreshRateMax*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status getDesiredDisplayModeSpecs(const sp<IBinder>& /*displayToken*/,
+ gui::DisplayModeSpecs* /*outSpecs*/) override {
+ return binder::Status::ok();
+ }
+
binder::Status getDisplayBrightnessSupport(const sp<IBinder>& /*displayToken*/,
bool* /*outSupport*/) override {
return binder::Status::ok();
@@ -989,6 +962,45 @@
binder::Status notifyPowerBoost(int /*boostId*/) override { return binder::Status::ok(); }
+ binder::Status setGlobalShadowSettings(const gui::Color& /*ambientColor*/,
+ const gui::Color& /*spotColor*/, float /*lightPosY*/,
+ float /*lightPosZ*/, float /*lightRadius*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status getDisplayDecorationSupport(
+ const sp<IBinder>& /*displayToken*/,
+ std::optional<gui::DisplayDecorationSupport>* /*outSupport*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status setOverrideFrameRate(int32_t /*uid*/, float /*frameRate*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status addTransactionTraceListener(
+ const sp<gui::ITransactionTraceListener>& /*listener*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status getGpuContextPriority(int32_t* /*outPriority*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status getMaxAcquiredBufferCount(int32_t* /*buffers*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status addWindowInfosListener(
+ const sp<gui::IWindowInfosListener>& /*windowInfosListener*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status removeWindowInfosListener(
+ const sp<gui::IWindowInfosListener>& /*windowInfosListener*/) override {
+ return binder::Status::ok();
+ }
+
protected:
IBinder* onAsBinder() override { return nullptr; }
@@ -1034,10 +1046,10 @@
class TestSurface : public Surface {
public:
- TestSurface(const sp<IGraphicBufferProducer>& bufferProducer,
- FenceToFenceTimeMap* fenceMap)
- : Surface(bufferProducer),
- mFakeSurfaceComposer(new FakeSurfaceComposer) {
+ TestSurface(const sp<IGraphicBufferProducer>& bufferProducer, FenceToFenceTimeMap* fenceMap)
+ : Surface(bufferProducer),
+ mFakeSurfaceComposer(new FakeSurfaceComposer),
+ mFakeSurfaceComposerAIDL(new FakeSurfaceComposerAIDL) {
mFakeFrameEventHistory = new FakeProducerFrameEventHistory(fenceMap);
mFrameEventHistory.reset(mFakeFrameEventHistory);
}
@@ -1048,6 +1060,10 @@
return mFakeSurfaceComposer;
}
+ sp<gui::ISurfaceComposer> composerServiceAIDL() const override {
+ return mFakeSurfaceComposerAIDL;
+ }
+
nsecs_t now() const override {
return mNow;
}
@@ -1058,6 +1074,7 @@
public:
sp<FakeSurfaceComposer> mFakeSurfaceComposer;
+ sp<FakeSurfaceComposerAIDL> mFakeSurfaceComposerAIDL;
nsecs_t mNow = 0;
// mFrameEventHistory owns the instance of FakeProducerFrameEventHistory,
@@ -1070,20 +1087,30 @@
protected:
struct FenceAndFenceTime {
explicit FenceAndFenceTime(FenceToFenceTimeMap& fenceMap)
- : mFence(new Fence),
- mFenceTime(fenceMap.createFenceTimeForTest(mFence)) {}
- sp<Fence> mFence { nullptr };
- std::shared_ptr<FenceTime> mFenceTime { nullptr };
+ : mFenceTime(fenceMap.createFenceTimeForTest(mFence)) {}
+
+ sp<Fence> mFence = sp<Fence>::make();
+ std::shared_ptr<FenceTime> mFenceTime;
};
+ static CompositorTiming makeCompositorTiming(nsecs_t deadline = 1'000'000'000,
+ nsecs_t interval = 16'666'667,
+ nsecs_t presentLatency = 50'000'000) {
+ CompositorTiming timing;
+ timing.deadline = deadline;
+ timing.interval = interval;
+ timing.presentLatency = presentLatency;
+ return timing;
+ }
+
struct RefreshEvents {
RefreshEvents(FenceToFenceTimeMap& fenceMap, nsecs_t refreshStart)
- : mFenceMap(fenceMap),
- kCompositorTiming(
- {refreshStart, refreshStart + 1, refreshStart + 2 }),
- kStartTime(refreshStart + 3),
- kGpuCompositionDoneTime(refreshStart + 4),
- kPresentTime(refreshStart + 5) {}
+ : mFenceMap(fenceMap),
+ kCompositorTiming(
+ makeCompositorTiming(refreshStart, refreshStart + 1, refreshStart + 2)),
+ kStartTime(refreshStart + 3),
+ kGpuCompositionDoneTime(refreshStart + 4),
+ kPresentTime(refreshStart + 5) {}
void signalPostCompositeFences() {
mFenceMap.signalAllForTest(
@@ -1093,8 +1120,8 @@
FenceToFenceTimeMap& mFenceMap;
- FenceAndFenceTime mGpuCompositionDone { mFenceMap };
- FenceAndFenceTime mPresent { mFenceMap };
+ FenceAndFenceTime mGpuCompositionDone{mFenceMap};
+ FenceAndFenceTime mPresent{mFenceMap};
const CompositorTiming kCompositorTiming;
@@ -1360,11 +1387,7 @@
// This test verifies that the frame timestamps are retrieved if explicitly
// enabled via native_window_enable_frame_timestamps.
TEST_F(GetFrameTimestampsTest, EnabledSimple) {
- CompositorTiming initialCompositorTiming {
- 1000000000, // 1s deadline
- 16666667, // 16ms interval
- 50000000, // 50ms present latency
- };
+ const CompositorTiming initialCompositorTiming = makeCompositorTiming();
mCfeh->initializeCompositorTiming(initialCompositorTiming);
enableFrameTimestamps();
@@ -1424,6 +1447,7 @@
TEST_F(GetFrameTimestampsTest, QueryPresentSupported) {
bool displayPresentSupported = true;
mSurface->mFakeSurfaceComposer->setSupportsPresent(displayPresentSupported);
+ mSurface->mFakeSurfaceComposerAIDL->setSupportsPresent(displayPresentSupported);
// Verify supported bits are forwarded.
int supportsPresent = -1;
@@ -1435,6 +1459,7 @@
TEST_F(GetFrameTimestampsTest, QueryPresentNotSupported) {
bool displayPresentSupported = false;
mSurface->mFakeSurfaceComposer->setSupportsPresent(displayPresentSupported);
+ mSurface->mFakeSurfaceComposerAIDL->setSupportsPresent(displayPresentSupported);
// Verify supported bits are forwarded.
int supportsPresent = -1;
@@ -1501,11 +1526,7 @@
// This verifies the compositor timing is updated by refresh events
// and piggy backed on a queue, dequeue, and enabling of timestamps..
TEST_F(GetFrameTimestampsTest, CompositorTimingUpdatesBasic) {
- CompositorTiming initialCompositorTiming {
- 1000000000, // 1s deadline
- 16666667, // 16ms interval
- 50000000, // 50ms present latency
- };
+ const CompositorTiming initialCompositorTiming = makeCompositorTiming();
mCfeh->initializeCompositorTiming(initialCompositorTiming);
enableFrameTimestamps();
@@ -1586,11 +1607,7 @@
// This verifies the compositor deadline properly snaps to the the next
// deadline based on the current time.
TEST_F(GetFrameTimestampsTest, CompositorTimingDeadlineSnaps) {
- CompositorTiming initialCompositorTiming {
- 1000000000, // 1s deadline
- 16666667, // 16ms interval
- 50000000, // 50ms present latency
- };
+ const CompositorTiming initialCompositorTiming = makeCompositorTiming();
mCfeh->initializeCompositorTiming(initialCompositorTiming);
enableFrameTimestamps();
@@ -2012,6 +2029,7 @@
TEST_F(GetFrameTimestampsTest, PresentUnsupportedNoSync) {
enableFrameTimestamps();
mSurface->mFakeSurfaceComposer->setSupportsPresent(false);
+ mSurface->mFakeSurfaceComposerAIDL->setSupportsPresent(false);
// Dequeue and queue frame 1.
const uint64_t fId1 = getNextFrameId();
diff --git a/libs/gui/tests/WindowInfo_test.cpp b/libs/gui/tests/WindowInfo_test.cpp
index 99658cc..c51b244 100644
--- a/libs/gui/tests/WindowInfo_test.cpp
+++ b/libs/gui/tests/WindowInfo_test.cpp
@@ -71,7 +71,6 @@
i.applicationInfo.name = "ApplicationFooBar";
i.applicationInfo.token = new BBinder();
i.applicationInfo.dispatchingTimeoutMillis = 0x12345678ABCD;
- i.isClone = true;
Parcel p;
i.writeToParcel(&p);
@@ -102,7 +101,6 @@
ASSERT_EQ(i.replaceTouchableRegionWithCrop, i2.replaceTouchableRegionWithCrop);
ASSERT_EQ(i.touchableRegionCropHandle, i2.touchableRegionCropHandle);
ASSERT_EQ(i.applicationInfo, i2.applicationInfo);
- ASSERT_EQ(i.isClone, i2.isClone);
}
TEST(InputApplicationInfo, Parcelling) {
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index b2fec79..5030d60 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -26,7 +26,6 @@
filegroup {
name: "inputconstants_aidl",
srcs: [
- "android/os/BlockUntrustedTouchesMode.aidl",
"android/os/IInputConstants.aidl",
"android/os/InputEventInjectionResult.aidl",
"android/os/InputEventInjectionSync.aidl",
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 6195052..8d8433b 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -51,7 +51,7 @@
// Latency added during resampling. A few milliseconds doesn't hurt much but
// reduces the impact of mispredicted touch positions.
-static const nsecs_t RESAMPLE_LATENCY = 5 * NANOS_PER_MS;
+const std::chrono::duration RESAMPLE_LATENCY = 5ms;
// Minimum time difference between consecutive samples before attempting to resample.
static const nsecs_t RESAMPLE_MIN_DELTA = 2 * NANOS_PER_MS;
@@ -721,7 +721,11 @@
// --- InputConsumer ---
InputConsumer::InputConsumer(const std::shared_ptr<InputChannel>& channel)
- : mResampleTouch(isTouchResamplingEnabled()), mChannel(channel), mMsgDeferred(false) {}
+ : InputConsumer(channel, isTouchResamplingEnabled()) {}
+
+InputConsumer::InputConsumer(const std::shared_ptr<InputChannel>& channel,
+ bool enableTouchResampling)
+ : mResampleTouch(enableTouchResampling), mChannel(channel), mMsgDeferred(false) {}
InputConsumer::~InputConsumer() {
}
@@ -751,7 +755,10 @@
// Receive a fresh message.
status_t result = mChannel->receiveMessage(&mMsg);
if (result == OK) {
- mConsumeTimes.emplace(mMsg.header.seq, systemTime(SYSTEM_TIME_MONOTONIC));
+ const auto [_, inserted] =
+ mConsumeTimes.emplace(mMsg.header.seq, systemTime(SYSTEM_TIME_MONOTONIC));
+ LOG_ALWAYS_FATAL_IF(!inserted, "Already have a consume time for seq=%" PRIu32,
+ mMsg.header.seq);
}
if (result) {
// Consume the next batched event unless batches are being held for later.
@@ -918,7 +925,7 @@
nsecs_t sampleTime = frameTime;
if (mResampleTouch) {
- sampleTime -= RESAMPLE_LATENCY;
+ sampleTime -= std::chrono::nanoseconds(RESAMPLE_LATENCY).count();
}
ssize_t split = findSampleNoLaterThan(batch, sampleTime);
if (split < 0) {
@@ -1166,6 +1173,11 @@
return;
}
+ if (current->eventTime == sampleTime) {
+ // Prevents having 2 events with identical times and coordinates.
+ return;
+ }
+
// Resample touch coordinates.
History oldLastResample;
oldLastResample.initializeFrom(touchState.lastResample);
diff --git a/libs/input/Keyboard.cpp b/libs/input/Keyboard.cpp
index c3f5151..3f8467d 100644
--- a/libs/input/Keyboard.cpp
+++ b/libs/input/Keyboard.cpp
@@ -49,25 +49,23 @@
const PropertyMap* deviceConfiguration) {
// Use the configured key layout if available.
if (deviceConfiguration) {
- String8 keyLayoutName;
- if (deviceConfiguration->tryGetProperty(String8("keyboard.layout"),
- keyLayoutName)) {
+ std::string keyLayoutName;
+ if (deviceConfiguration->tryGetProperty("keyboard.layout", keyLayoutName)) {
status_t status = loadKeyLayout(deviceIdentifier, keyLayoutName.c_str());
if (status == NAME_NOT_FOUND) {
ALOGE("Configuration for keyboard device '%s' requested keyboard layout '%s' but "
- "it was not found.",
- deviceIdentifier.name.c_str(), keyLayoutName.string());
+ "it was not found.",
+ deviceIdentifier.name.c_str(), keyLayoutName.c_str());
}
}
- String8 keyCharacterMapName;
- if (deviceConfiguration->tryGetProperty(String8("keyboard.characterMap"),
- keyCharacterMapName)) {
+ std::string keyCharacterMapName;
+ if (deviceConfiguration->tryGetProperty("keyboard.characterMap", keyCharacterMapName)) {
status_t status = loadKeyCharacterMap(deviceIdentifier, keyCharacterMapName.c_str());
if (status == NAME_NOT_FOUND) {
ALOGE("Configuration for keyboard device '%s' requested keyboard character "
- "map '%s' but it was not found.",
- deviceIdentifier.name.c_str(), keyCharacterMapName.string());
+ "map '%s' but it was not found.",
+ deviceIdentifier.name.c_str(), keyCharacterMapName.c_str());
}
}
@@ -165,7 +163,7 @@
return false;
}
bool isSpecialFunction = false;
- config->tryGetProperty(String8("keyboard.specialFunction"), isSpecialFunction);
+ config->tryGetProperty("keyboard.specialFunction", isSpecialFunction);
return isSpecialFunction;
}
@@ -180,8 +178,7 @@
if (deviceConfiguration) {
bool builtIn = false;
- if (deviceConfiguration->tryGetProperty(String8("keyboard.builtIn"), builtIn)
- && builtIn) {
+ if (deviceConfiguration->tryGetProperty("keyboard.builtIn", builtIn) && builtIn) {
return true;
}
}
diff --git a/libs/input/PropertyMap.cpp b/libs/input/PropertyMap.cpp
index a842166..662e568 100644
--- a/libs/input/PropertyMap.cpp
+++ b/libs/input/PropertyMap.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "PropertyMap"
#include <input/PropertyMap.h>
+#include <log/log.h>
// Enables debug output for the parser.
#define DEBUG_PARSER 0
@@ -39,25 +40,25 @@
mProperties.clear();
}
-void PropertyMap::addProperty(const String8& key, const String8& value) {
- mProperties.add(key, value);
+void PropertyMap::addProperty(const std::string& key, const std::string& value) {
+ mProperties.emplace(key, value);
}
-bool PropertyMap::hasProperty(const String8& key) const {
- return mProperties.indexOfKey(key) >= 0;
+bool PropertyMap::hasProperty(const std::string& key) const {
+ return mProperties.find(key) != mProperties.end();
}
-bool PropertyMap::tryGetProperty(const String8& key, String8& outValue) const {
- ssize_t index = mProperties.indexOfKey(key);
- if (index < 0) {
+bool PropertyMap::tryGetProperty(const std::string& key, std::string& outValue) const {
+ auto it = mProperties.find(key);
+ if (it == mProperties.end()) {
return false;
}
- outValue = mProperties.valueAt(index);
+ outValue = it->second;
return true;
}
-bool PropertyMap::tryGetProperty(const String8& key, bool& outValue) const {
+bool PropertyMap::tryGetProperty(const std::string& key, bool& outValue) const {
int32_t intValue;
if (!tryGetProperty(key, intValue)) {
return false;
@@ -67,34 +68,34 @@
return true;
}
-bool PropertyMap::tryGetProperty(const String8& key, int32_t& outValue) const {
- String8 stringValue;
+bool PropertyMap::tryGetProperty(const std::string& key, int32_t& outValue) const {
+ std::string stringValue;
if (!tryGetProperty(key, stringValue) || stringValue.length() == 0) {
return false;
}
char* end;
- int value = strtol(stringValue.string(), &end, 10);
+ int value = strtol(stringValue.c_str(), &end, 10);
if (*end != '\0') {
- ALOGW("Property key '%s' has invalid value '%s'. Expected an integer.", key.string(),
- stringValue.string());
+ ALOGW("Property key '%s' has invalid value '%s'. Expected an integer.", key.c_str(),
+ stringValue.c_str());
return false;
}
outValue = value;
return true;
}
-bool PropertyMap::tryGetProperty(const String8& key, float& outValue) const {
- String8 stringValue;
+bool PropertyMap::tryGetProperty(const std::string& key, float& outValue) const {
+ std::string stringValue;
if (!tryGetProperty(key, stringValue) || stringValue.length() == 0) {
return false;
}
char* end;
- float value = strtof(stringValue.string(), &end);
+ float value = strtof(stringValue.c_str(), &end);
if (*end != '\0') {
- ALOGW("Property key '%s' has invalid value '%s'. Expected a float.", key.string(),
- stringValue.string());
+ ALOGW("Property key '%s' has invalid value '%s'. Expected a float.", key.c_str(),
+ stringValue.c_str());
return false;
}
outValue = value;
@@ -102,8 +103,8 @@
}
void PropertyMap::addAll(const PropertyMap* map) {
- for (size_t i = 0; i < map->mProperties.size(); i++) {
- mProperties.add(map->mProperties.keyAt(i), map->mProperties.valueAt(i));
+ for (const auto& [key, value] : map->mProperties) {
+ mProperties.emplace(key, value);
}
}
@@ -184,13 +185,13 @@
return BAD_VALUE;
}
- if (mMap->hasProperty(keyToken)) {
+ if (mMap->hasProperty(keyToken.string())) {
ALOGE("%s: Duplicate property value for key '%s'.",
mTokenizer->getLocation().string(), keyToken.string());
return BAD_VALUE;
}
- mMap->addProperty(keyToken, valueToken);
+ mMap->addProperty(keyToken.string(), valueToken.string());
}
mTokenizer->nextLine();
diff --git a/libs/input/PropertyMap_fuzz.cpp b/libs/input/PropertyMap_fuzz.cpp
index afb97a1..d985dc1 100755
--- a/libs/input/PropertyMap_fuzz.cpp
+++ b/libs/input/PropertyMap_fuzz.cpp
@@ -17,32 +17,22 @@
#include "android-base/file.h"
#include "fuzzer/FuzzedDataProvider.h"
#include "input/PropertyMap.h"
-#include "utils/String8.h"
static constexpr int MAX_FILE_SIZE = 256;
static constexpr int MAX_STR_LEN = 2048;
static constexpr int MAX_OPERATIONS = 1000;
-static const std::vector<std::function<void(FuzzedDataProvider*, android::PropertyMap)>>
+static const std::vector<std::function<void(FuzzedDataProvider*, android::PropertyMap&)>>
operations = {
- [](FuzzedDataProvider*, android::PropertyMap propertyMap) -> void {
- propertyMap.getProperties();
- },
- [](FuzzedDataProvider*, android::PropertyMap propertyMap) -> void {
+ [](FuzzedDataProvider*, android::PropertyMap& propertyMap) -> void {
propertyMap.clear();
},
- [](FuzzedDataProvider* dataProvider, android::PropertyMap propertyMap) -> void {
- std::string keyStr = dataProvider->ConsumeRandomLengthString(MAX_STR_LEN);
- android::String8 key = android::String8(keyStr.c_str());
- propertyMap.hasProperty(key);
- },
- [](FuzzedDataProvider* dataProvider, android::PropertyMap propertyMap) -> void {
- std::string keyStr = dataProvider->ConsumeRandomLengthString(MAX_STR_LEN);
- android::String8 key = android::String8(keyStr.c_str());
- android::String8 out;
+ [](FuzzedDataProvider* dataProvider, android::PropertyMap& propertyMap) -> void {
+ std::string key = dataProvider->ConsumeRandomLengthString(MAX_STR_LEN);
+ std::string out;
propertyMap.tryGetProperty(key, out);
},
- [](FuzzedDataProvider* dataProvider, android::PropertyMap /*unused*/) -> void {
+ [](FuzzedDataProvider* dataProvider, android::PropertyMap& /*unused*/) -> void {
TemporaryFile tf;
// Generate file contents
std::string contents = dataProvider->ConsumeRandomLengthString(MAX_FILE_SIZE);
@@ -54,17 +44,15 @@
}
android::PropertyMap::load(tf.path);
},
- [](FuzzedDataProvider* dataProvider, android::PropertyMap propertyMap) -> void {
- std::string keyStr = dataProvider->ConsumeRandomLengthString(MAX_STR_LEN);
- std::string valStr = dataProvider->ConsumeRandomLengthString(MAX_STR_LEN);
- android::String8 key = android::String8(keyStr.c_str());
- android::String8 val = android::String8(valStr.c_str());
+ [](FuzzedDataProvider* dataProvider, android::PropertyMap& propertyMap) -> void {
+ std::string key = dataProvider->ConsumeRandomLengthString(MAX_STR_LEN);
+ std::string val = dataProvider->ConsumeRandomLengthString(MAX_STR_LEN);
propertyMap.addProperty(key, val);
},
};
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
FuzzedDataProvider dataProvider(data, size);
- android::PropertyMap propertyMap = android::PropertyMap();
+ android::PropertyMap propertyMap;
int opsRun = 0;
while (dataProvider.remaining_bytes() > 0 && opsRun++ < MAX_OPERATIONS) {
diff --git a/libs/input/VelocityTracker.cpp b/libs/input/VelocityTracker.cpp
index 7f427f2..76aaf61 100644
--- a/libs/input/VelocityTracker.cpp
+++ b/libs/input/VelocityTracker.cpp
@@ -27,6 +27,8 @@
#include <utils/BitSet.h>
#include <utils/Timers.h>
+using std::literals::chrono_literals::operator""ms;
+
namespace android {
/**
@@ -57,8 +59,14 @@
// 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
// velocity after the pointer starts moving again.
-static const nsecs_t ASSUME_POINTER_STOPPED_TIME = 40 * NANOS_PER_MS;
+static const std::chrono::duration ASSUME_POINTER_STOPPED_TIME = 40ms;
+static std::string toString(std::chrono::nanoseconds t) {
+ std::stringstream stream;
+ stream.precision(1);
+ stream << std::fixed << std::chrono::duration<float, std::milli>(t).count() << " ms";
+ return stream.str();
+}
static float vectorDot(const float* a, const float* b, uint32_t m) {
float r = 0;
@@ -146,18 +154,14 @@
VelocityTracker::Strategy strategy) {
switch (strategy) {
case VelocityTracker::Strategy::IMPULSE:
- if (DEBUG_STRATEGY) {
- ALOGI("Initializing impulse strategy");
- }
+ ALOGI_IF(DEBUG_STRATEGY, "Initializing impulse strategy");
return std::make_unique<ImpulseVelocityTrackerStrategy>();
case VelocityTracker::Strategy::LSQ1:
return std::make_unique<LeastSquaresVelocityTrackerStrategy>(1);
case VelocityTracker::Strategy::LSQ2:
- if (DEBUG_STRATEGY && !DEBUG_IMPULSE) {
- ALOGI("Initializing lsq2 strategy");
- }
+ ALOGI_IF(DEBUG_STRATEGY && !DEBUG_IMPULSE, "Initializing lsq2 strategy");
return std::make_unique<LeastSquaresVelocityTrackerStrategy>(2);
case VelocityTracker::Strategy::LSQ3:
@@ -221,12 +225,11 @@
idBits.clearLastMarkedBit();
}
- if ((mCurrentPointerIdBits.value & idBits.value)
- && eventTime >= mLastEventTime + ASSUME_POINTER_STOPPED_TIME) {
- if (DEBUG_VELOCITY) {
- ALOGD("VelocityTracker: stopped for %0.3f ms, clearing state.",
- (eventTime - mLastEventTime) * 0.000001f);
- }
+ if ((mCurrentPointerIdBits.value & idBits.value) &&
+ std::chrono::nanoseconds(eventTime - mLastEventTime) > ASSUME_POINTER_STOPPED_TIME) {
+ ALOGD_IF(DEBUG_VELOCITY, "VelocityTracker: stopped for %s, clearing state.",
+ toString(std::chrono::nanoseconds(eventTime - mLastEventTime)).c_str());
+
// We have not received any movements for too long. Assume that all pointers
// have stopped.
mStrategy->clear();
@@ -281,8 +284,18 @@
case AMOTION_EVENT_ACTION_MOVE:
case AMOTION_EVENT_ACTION_HOVER_MOVE:
break;
- default:
- // Ignore all other actions because they do not convey any new information about
+ case AMOTION_EVENT_ACTION_POINTER_UP:
+ case AMOTION_EVENT_ACTION_UP: {
+ std::chrono::nanoseconds delaySinceLastEvent(event->getEventTime() - mLastEventTime);
+ if (delaySinceLastEvent > ASSUME_POINTER_STOPPED_TIME) {
+ ALOGD_IF(DEBUG_VELOCITY,
+ "VelocityTracker: stopped for %s, clearing state upon pointer liftoff.",
+ toString(delaySinceLastEvent).c_str());
+ // We have not received any movements for too long. Assume that all pointers
+ // have stopped.
+ mStrategy->clear();
+ }
+ // These actions because they do not convey any new information about
// pointer movement. We also want to preserve the last known velocity of the pointers.
// Note that ACTION_UP and ACTION_POINTER_UP always report the last known position
// of the pointers that went up. ACTION_POINTER_UP does include the new position of
@@ -292,6 +305,10 @@
// before adding the movement.
return;
}
+ default:
+ // Ignore all other actions.
+ return;
+ }
size_t pointerCount = event->getPointerCount();
if (pointerCount > MAX_POINTERS) {
@@ -438,10 +455,10 @@
static bool solveLeastSquares(const std::vector<float>& x, const std::vector<float>& y,
const std::vector<float>& w, uint32_t n, float* outB, float* outDet) {
const size_t m = x.size();
- if (DEBUG_STRATEGY) {
- ALOGD("solveLeastSquares: m=%d, n=%d, x=%s, y=%s, w=%s", int(m), int(n),
- vectorToString(x).c_str(), vectorToString(y).c_str(), vectorToString(w).c_str());
- }
+
+ ALOGD_IF(DEBUG_STRATEGY, "solveLeastSquares: m=%d, n=%d, x=%s, y=%s, w=%s", int(m), int(n),
+ vectorToString(x).c_str(), vectorToString(y).c_str(), vectorToString(w).c_str());
+
LOG_ALWAYS_FATAL_IF(m != y.size() || m != w.size(), "Mismatched vector sizes");
// Expand the X vector to a matrix A, pre-multiplied by the weights.
@@ -452,9 +469,9 @@
a[i][h] = a[i - 1][h] * x[h];
}
}
- if (DEBUG_STRATEGY) {
- ALOGD(" - a=%s", matrixToString(&a[0][0], m, n, false /*rowMajor*/).c_str());
- }
+
+ ALOGD_IF(DEBUG_STRATEGY, " - a=%s",
+ matrixToString(&a[0][0], m, n, false /*rowMajor*/).c_str());
// Apply the Gram-Schmidt process to A to obtain its QR decomposition.
float q[n][m]; // orthonormal basis, column-major order
@@ -473,9 +490,7 @@
float norm = vectorNorm(&q[j][0], m);
if (norm < 0.000001f) {
// vectors are linearly dependent or zero so no solution
- if (DEBUG_STRATEGY) {
- ALOGD(" - no solution, norm=%f", norm);
- }
+ ALOGD_IF(DEBUG_STRATEGY, " - no solution, norm=%f", norm);
return false;
}
@@ -518,9 +533,8 @@
}
outB[i] /= r[i][i];
}
- if (DEBUG_STRATEGY) {
- ALOGD(" - b=%s", vectorToString(outB, n).c_str());
- }
+
+ ALOGD_IF(DEBUG_STRATEGY, " - b=%s", vectorToString(outB, n).c_str());
// Calculate the coefficient of determination as 1 - (SSerr / SStot) where
// SSerr is the residual sum of squares (variance of the error),
@@ -546,11 +560,11 @@
sstot += w[h] * w[h] * var * var;
}
*outDet = sstot > 0.000001f ? 1.0f - (sserr / sstot) : 1;
- if (DEBUG_STRATEGY) {
- ALOGD(" - sserr=%f", sserr);
- ALOGD(" - sstot=%f", sstot);
- ALOGD(" - det=%f", *outDet);
- }
+
+ ALOGD_IF(DEBUG_STRATEGY, " - sserr=%f", sserr);
+ ALOGD_IF(DEBUG_STRATEGY, " - sstot=%f", sstot);
+ ALOGD_IF(DEBUG_STRATEGY, " - det=%f", *outDet);
+
return true;
}
@@ -673,11 +687,11 @@
outEstimator->time = newestMovement.eventTime;
outEstimator->degree = degree;
outEstimator->confidence = xdet * ydet;
- if (DEBUG_STRATEGY) {
- ALOGD("estimate: degree=%d, xCoeff=%s, yCoeff=%s, confidence=%f",
- int(outEstimator->degree), vectorToString(outEstimator->xCoeff, n).c_str(),
- vectorToString(outEstimator->yCoeff, n).c_str(), outEstimator->confidence);
- }
+
+ ALOGD_IF(DEBUG_STRATEGY, "estimate: degree=%d, xCoeff=%s, yCoeff=%s, confidence=%f",
+ int(outEstimator->degree), vectorToString(outEstimator->xCoeff, n).c_str(),
+ vectorToString(outEstimator->yCoeff, n).c_str(), outEstimator->confidence);
+
return true;
}
}
@@ -1185,9 +1199,10 @@
outEstimator->time = newestMovement.eventTime;
outEstimator->degree = 2; // similar results to 2nd degree fit
outEstimator->confidence = 1;
- if (DEBUG_STRATEGY) {
- ALOGD("velocity: (%.1f, %.1f)", outEstimator->xCoeff[1], outEstimator->yCoeff[1]);
- }
+
+ ALOGD_IF(DEBUG_STRATEGY, "velocity: (%.1f, %.1f)", outEstimator->xCoeff[1],
+ outEstimator->yCoeff[1]);
+
if (DEBUG_IMPULSE) {
// TODO(b/134179997): delete this block once the switch to 'impulse' is complete.
// Calculate the lsq2 velocity for the same inputs to allow runtime comparisons
diff --git a/libs/input/android/os/InputConfig.aidl b/libs/input/android/os/InputConfig.aidl
index 6d1b396..4e644ff 100644
--- a/libs/input/android/os/InputConfig.aidl
+++ b/libs/input/android/os/InputConfig.aidl
@@ -144,4 +144,10 @@
* It is not valid to set this configuration if {@link #TRUSTED_OVERLAY} is not set.
*/
INTERCEPTS_STYLUS = 1 << 15,
+
+ /**
+ * The window is a clone of another window. This may be treated differently since there's
+ * likely a duplicate window with the same client token, but different bounds.
+ */
+ CLONE = 1 << 16,
}
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index d947cd9..c53811a 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -16,6 +16,7 @@
"InputDevice_test.cpp",
"InputEvent_test.cpp",
"InputPublisherAndConsumer_test.cpp",
+ "TouchResampling_test.cpp",
"TouchVideoFrame_test.cpp",
"VelocityTracker_test.cpp",
"VerifiedInputEvent_test.cpp",
diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp
index 05bc0bc..70e4fda 100644
--- a/libs/input/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp
@@ -16,17 +16,10 @@
#include "TestHelpers.h"
-#include <unistd.h>
-#include <sys/mman.h>
-#include <time.h>
-
#include <attestation/HmacKeyManager.h>
-#include <cutils/ashmem.h>
#include <gtest/gtest.h>
#include <gui/constants.h>
#include <input/InputTransport.h>
-#include <utils/StopWatch.h>
-#include <utils/Timers.h>
using android::base::Result;
diff --git a/libs/input/tests/TouchResampling_test.cpp b/libs/input/tests/TouchResampling_test.cpp
new file mode 100644
index 0000000..c09a8e9
--- /dev/null
+++ b/libs/input/tests/TouchResampling_test.cpp
@@ -0,0 +1,562 @@
+/*
+ * 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.
+ */
+
+#include "TestHelpers.h"
+
+#include <chrono>
+#include <vector>
+
+#include <attestation/HmacKeyManager.h>
+#include <gtest/gtest.h>
+#include <input/InputTransport.h>
+
+using namespace std::chrono_literals;
+
+namespace android {
+
+struct Pointer {
+ int32_t id;
+ float x;
+ float y;
+};
+
+struct InputEventEntry {
+ std::chrono::nanoseconds eventTime;
+ std::vector<Pointer> pointers;
+ int32_t action;
+};
+
+class TouchResamplingTest : public testing::Test {
+protected:
+ std::unique_ptr<InputPublisher> mPublisher;
+ std::unique_ptr<InputConsumer> mConsumer;
+ PreallocatedInputEventFactory mEventFactory;
+
+ uint32_t mSeq = 1;
+
+ void SetUp() override {
+ std::unique_ptr<InputChannel> serverChannel, clientChannel;
+ status_t result =
+ InputChannel::openInputChannelPair("channel name", serverChannel, clientChannel);
+ ASSERT_EQ(OK, result);
+
+ mPublisher = std::make_unique<InputPublisher>(std::move(serverChannel));
+ mConsumer = std::make_unique<InputConsumer>(std::move(clientChannel),
+ true /* enableTouchResampling */);
+ }
+
+ status_t publishSimpleMotionEventWithCoords(int32_t action, nsecs_t eventTime,
+ const std::vector<PointerProperties>& properties,
+ const std::vector<PointerCoords>& coords);
+ void publishSimpleMotionEvent(int32_t action, nsecs_t eventTime,
+ const std::vector<Pointer>& pointers);
+ void publishInputEventEntries(const std::vector<InputEventEntry>& entries);
+ void consumeInputEventEntries(const std::vector<InputEventEntry>& entries,
+ std::chrono::nanoseconds frameTime);
+ void receiveResponseUntilSequence(uint32_t seq);
+};
+
+status_t TouchResamplingTest::publishSimpleMotionEventWithCoords(
+ int32_t action, nsecs_t eventTime, const std::vector<PointerProperties>& properties,
+ const std::vector<PointerCoords>& coords) {
+ const ui::Transform identityTransform;
+ const nsecs_t downTime = 0;
+
+ if (action == AMOTION_EVENT_ACTION_DOWN && eventTime != 0) {
+ ADD_FAILURE() << "Downtime should be equal to 0 (hardcoded for convenience)";
+ }
+ return mPublisher->publishMotionEvent(mSeq++, InputEvent::nextId(), 1 /*deviceId*/,
+ AINPUT_SOURCE_TOUCHSCREEN, 0 /*displayId*/, INVALID_HMAC,
+ action, 0 /*actionButton*/, 0 /*flags*/, 0 /*edgeFlags*/,
+ AMETA_NONE, 0 /*buttonState*/, MotionClassification::NONE,
+ identityTransform, 0 /*xPrecision*/, 0 /*yPrecision*/,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION,
+ AMOTION_EVENT_INVALID_CURSOR_POSITION, identityTransform,
+ downTime, eventTime, properties.size(), properties.data(),
+ coords.data());
+}
+
+void TouchResamplingTest::publishSimpleMotionEvent(int32_t action, nsecs_t eventTime,
+ const std::vector<Pointer>& pointers) {
+ std::vector<PointerProperties> properties;
+ std::vector<PointerCoords> coords;
+
+ for (const Pointer& pointer : pointers) {
+ properties.push_back({});
+ properties.back().clear();
+ properties.back().id = pointer.id;
+ properties.back().toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
+
+ coords.push_back({});
+ coords.back().clear();
+ coords.back().setAxisValue(AMOTION_EVENT_AXIS_X, pointer.x);
+ coords.back().setAxisValue(AMOTION_EVENT_AXIS_Y, pointer.y);
+ }
+
+ status_t result = publishSimpleMotionEventWithCoords(action, eventTime, properties, coords);
+ ASSERT_EQ(OK, result);
+}
+
+/**
+ * Each entry is published separately, one entry at a time. As a result, action is used here
+ * on a per-entry basis.
+ */
+void TouchResamplingTest::publishInputEventEntries(const std::vector<InputEventEntry>& entries) {
+ for (const InputEventEntry& entry : entries) {
+ publishSimpleMotionEvent(entry.action, entry.eventTime.count(), entry.pointers);
+ }
+}
+
+/**
+ * Inside the publisher, read responses repeatedly until the desired sequence number is returned.
+ *
+ * Sometimes, when you call 'sendFinishedSignal', you would be finishing a batch which is comprised
+ * of several input events. As a result, consumer will generate multiple 'finish' signals on your
+ * behalf.
+ *
+ * In this function, we call 'receiveConsumerResponse' in a loop until the desired sequence number
+ * is returned.
+ */
+void TouchResamplingTest::receiveResponseUntilSequence(uint32_t seq) {
+ size_t consumedEvents = 0;
+ while (consumedEvents < 100) {
+ android::base::Result<InputPublisher::ConsumerResponse> response =
+ mPublisher->receiveConsumerResponse();
+ ASSERT_TRUE(response.ok());
+ ASSERT_TRUE(std::holds_alternative<InputPublisher::Finished>(*response));
+ const InputPublisher::Finished& finish = std::get<InputPublisher::Finished>(*response);
+ ASSERT_TRUE(finish.handled)
+ << "publisher receiveFinishedSignal should have set handled to consumer's reply";
+ if (finish.seq == seq) {
+ return;
+ }
+ consumedEvents++;
+ }
+ FAIL() << "Got " << consumedEvents << "events, but still no event with seq=" << seq;
+}
+
+/**
+ * All entries are compared against a single MotionEvent, but the same data structure
+ * InputEventEntry is used here for simpler code. As a result, the entire array of InputEventEntry
+ * must contain identical values for the action field.
+ */
+void TouchResamplingTest::consumeInputEventEntries(const std::vector<InputEventEntry>& entries,
+ std::chrono::nanoseconds frameTime) {
+ ASSERT_GE(entries.size(), 1U) << "Must have at least 1 InputEventEntry to compare against";
+
+ uint32_t consumeSeq;
+ InputEvent* event;
+
+ status_t status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, frameTime.count(),
+ &consumeSeq, &event);
+ ASSERT_EQ(OK, status);
+ MotionEvent* motionEvent = static_cast<MotionEvent*>(event);
+
+ ASSERT_EQ(entries.size() - 1, motionEvent->getHistorySize());
+ for (size_t i = 0; i < entries.size(); i++) { // most recent sample is last
+ SCOPED_TRACE(i);
+ const InputEventEntry& entry = entries[i];
+ ASSERT_EQ(entry.action, motionEvent->getAction());
+ ASSERT_EQ(entry.eventTime.count(), motionEvent->getHistoricalEventTime(i));
+ ASSERT_EQ(entry.pointers.size(), motionEvent->getPointerCount());
+
+ for (size_t p = 0; p < motionEvent->getPointerCount(); p++) {
+ SCOPED_TRACE(p);
+ // The pointers can be in any order, both in MotionEvent as well as InputEventEntry
+ ssize_t motionEventPointerIndex = motionEvent->findPointerIndex(entry.pointers[p].id);
+ ASSERT_GE(motionEventPointerIndex, 0) << "Pointer must be present in MotionEvent";
+ ASSERT_EQ(entry.pointers[p].x,
+ motionEvent->getHistoricalAxisValue(AMOTION_EVENT_AXIS_X,
+ motionEventPointerIndex, i));
+ ASSERT_EQ(entry.pointers[p].x,
+ motionEvent->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_X,
+ motionEventPointerIndex, i));
+ ASSERT_EQ(entry.pointers[p].y,
+ motionEvent->getHistoricalAxisValue(AMOTION_EVENT_AXIS_Y,
+ motionEventPointerIndex, i));
+ ASSERT_EQ(entry.pointers[p].y,
+ motionEvent->getHistoricalRawAxisValue(AMOTION_EVENT_AXIS_Y,
+ motionEventPointerIndex, i));
+ }
+ }
+
+ status = mConsumer->sendFinishedSignal(consumeSeq, true);
+ ASSERT_EQ(OK, status);
+
+ receiveResponseUntilSequence(consumeSeq);
+}
+
+/**
+ * Timeline
+ * ---------+------------------+------------------+--------+-----------------+----------------------
+ * 0 ms 10 ms 20 ms 25 ms 35 ms
+ * ACTION_DOWN ACTION_MOVE ACTION_MOVE ^ ^
+ * | |
+ * resampled value |
+ * frameTime
+ * Typically, the prediction is made for time frameTime - RESAMPLE_LATENCY, or 30 ms in this case
+ * However, that would be 10 ms later than the last real sample (which came in at 20 ms).
+ * Therefore, the resampling should happen at 20 ms + RESAMPLE_MAX_PREDICTION = 28 ms.
+ * In this situation, though, resample time is further limited by taking half of the difference
+ * between the last two real events, which would put this time at:
+ * 20 ms + (20 ms - 10 ms) / 2 = 25 ms.
+ */
+TEST_F(TouchResamplingTest, EventIsResampled) {
+ std::chrono::nanoseconds frameTime;
+ std::vector<InputEventEntry> entries, expectedEntries;
+
+ // Initial ACTION_DOWN should be separate, because the first consume event will only return
+ // InputEvent with a single action.
+ entries = {
+ // id x y
+ {0ms, {{0, 10, 20}}, AMOTION_EVENT_ACTION_DOWN},
+ };
+ publishInputEventEntries(entries);
+ frameTime = 5ms;
+ expectedEntries = {
+ // id x y
+ {0ms, {{0, 10, 20}}, AMOTION_EVENT_ACTION_DOWN},
+ };
+ consumeInputEventEntries(expectedEntries, frameTime);
+
+ // Two ACTION_MOVE events 10 ms apart that move in X direction and stay still in Y
+ entries = {
+ // id x y
+ {10ms, {{0, 20, 30}}, AMOTION_EVENT_ACTION_MOVE},
+ {20ms, {{0, 30, 30}}, AMOTION_EVENT_ACTION_MOVE},
+ };
+ publishInputEventEntries(entries);
+ frameTime = 35ms;
+ expectedEntries = {
+ // id x y
+ {10ms, {{0, 20, 30}}, AMOTION_EVENT_ACTION_MOVE},
+ {20ms, {{0, 30, 30}}, AMOTION_EVENT_ACTION_MOVE},
+ {25ms, {{0, 35, 30}}, AMOTION_EVENT_ACTION_MOVE}, // resampled value
+ };
+ consumeInputEventEntries(expectedEntries, frameTime);
+}
+
+/**
+ * Same as above test, but use pointer id=1 instead of 0 to make sure that system does not
+ * have these hardcoded.
+ */
+TEST_F(TouchResamplingTest, EventIsResampledWithDifferentId) {
+ std::chrono::nanoseconds frameTime;
+ std::vector<InputEventEntry> entries, expectedEntries;
+
+ // Initial ACTION_DOWN should be separate, because the first consume event will only return
+ // InputEvent with a single action.
+ entries = {
+ // id x y
+ {0ms, {{1, 10, 20}}, AMOTION_EVENT_ACTION_DOWN},
+ };
+ publishInputEventEntries(entries);
+ frameTime = 5ms;
+ expectedEntries = {
+ // id x y
+ {0ms, {{1, 10, 20}}, AMOTION_EVENT_ACTION_DOWN},
+ };
+ consumeInputEventEntries(expectedEntries, frameTime);
+
+ // Two ACTION_MOVE events 10 ms apart that move in X direction and stay still in Y
+ entries = {
+ // id x y
+ {10ms, {{1, 20, 30}}, AMOTION_EVENT_ACTION_MOVE},
+ {20ms, {{1, 30, 30}}, AMOTION_EVENT_ACTION_MOVE},
+ };
+ publishInputEventEntries(entries);
+ frameTime = 35ms;
+ expectedEntries = {
+ // id x y
+ {10ms, {{1, 20, 30}}, AMOTION_EVENT_ACTION_MOVE},
+ {20ms, {{1, 30, 30}}, AMOTION_EVENT_ACTION_MOVE},
+ {25ms, {{1, 35, 30}}, AMOTION_EVENT_ACTION_MOVE}, // resampled value
+ };
+ consumeInputEventEntries(expectedEntries, frameTime);
+}
+
+/**
+ * Event should not be resampled when sample time is equal to event time.
+ */
+TEST_F(TouchResamplingTest, SampleTimeEqualsEventTime) {
+ std::chrono::nanoseconds frameTime;
+ std::vector<InputEventEntry> entries, expectedEntries;
+
+ // Initial ACTION_DOWN should be separate, because the first consume event will only return
+ // InputEvent with a single action.
+ entries = {
+ // id x y
+ {0ms, {{0, 10, 20}}, AMOTION_EVENT_ACTION_DOWN},
+ };
+ publishInputEventEntries(entries);
+ frameTime = 5ms;
+ expectedEntries = {
+ // id x y
+ {0ms, {{0, 10, 20}}, AMOTION_EVENT_ACTION_DOWN},
+ };
+ consumeInputEventEntries(expectedEntries, frameTime);
+
+ // Two ACTION_MOVE events 10 ms apart that move in X direction and stay still in Y
+ entries = {
+ // id x y
+ {10ms, {{0, 20, 30}}, AMOTION_EVENT_ACTION_MOVE},
+ {20ms, {{0, 30, 30}}, AMOTION_EVENT_ACTION_MOVE},
+ };
+ publishInputEventEntries(entries);
+ frameTime = 20ms + 5ms /*RESAMPLE_LATENCY*/;
+ expectedEntries = {
+ // id x y
+ {10ms, {{0, 20, 30}}, AMOTION_EVENT_ACTION_MOVE},
+ {20ms, {{0, 30, 30}}, AMOTION_EVENT_ACTION_MOVE},
+ // no resampled event because the time of resample falls exactly on the existing event
+ };
+ consumeInputEventEntries(expectedEntries, frameTime);
+}
+
+/**
+ * Once we send a resampled value to the app, we should continue to "lie" if the pointer
+ * does not move. So, if the pointer keeps the same coordinates, resampled value should continue
+ * to be used.
+ */
+TEST_F(TouchResamplingTest, ResampledValueIsUsedForIdenticalCoordinates) {
+ std::chrono::nanoseconds frameTime;
+ std::vector<InputEventEntry> entries, expectedEntries;
+
+ // Initial ACTION_DOWN should be separate, because the first consume event will only return
+ // InputEvent with a single action.
+ entries = {
+ // id x y
+ {0ms, {{0, 10, 20}}, AMOTION_EVENT_ACTION_DOWN},
+ };
+ publishInputEventEntries(entries);
+ frameTime = 5ms;
+ expectedEntries = {
+ // id x y
+ {0ms, {{0, 10, 20}}, AMOTION_EVENT_ACTION_DOWN},
+ };
+ consumeInputEventEntries(expectedEntries, frameTime);
+
+ // Two ACTION_MOVE events 10 ms apart that move in X direction and stay still in Y
+ entries = {
+ // id x y
+ {10ms, {{0, 20, 30}}, AMOTION_EVENT_ACTION_MOVE},
+ {20ms, {{0, 30, 30}}, AMOTION_EVENT_ACTION_MOVE},
+ };
+ publishInputEventEntries(entries);
+ frameTime = 35ms;
+ expectedEntries = {
+ // id x y
+ {10ms, {{0, 20, 30}}, AMOTION_EVENT_ACTION_MOVE},
+ {20ms, {{0, 30, 30}}, AMOTION_EVENT_ACTION_MOVE},
+ {25ms, {{0, 35, 30}}, AMOTION_EVENT_ACTION_MOVE}, // resampled value
+ };
+ consumeInputEventEntries(expectedEntries, frameTime);
+
+ // Coordinate value 30 has been resampled to 35. When a new event comes in with value 30 again,
+ // the system should still report 35.
+ entries = {
+ // id x y
+ {40ms, {{0, 30, 30}}, AMOTION_EVENT_ACTION_MOVE},
+ };
+ publishInputEventEntries(entries);
+ frameTime = 45ms + 5ms /*RESAMPLE_LATENCY*/;
+ expectedEntries = {
+ // id x y
+ {40ms, {{0, 35, 30}}, AMOTION_EVENT_ACTION_MOVE}, // original event, rewritten
+ {45ms, {{0, 35, 30}}, AMOTION_EVENT_ACTION_MOVE}, // resampled event, rewritten
+ };
+ consumeInputEventEntries(expectedEntries, frameTime);
+}
+
+TEST_F(TouchResamplingTest, OldEventReceivedAfterResampleOccurs) {
+ std::chrono::nanoseconds frameTime;
+ std::vector<InputEventEntry> entries, expectedEntries;
+
+ // Initial ACTION_DOWN should be separate, because the first consume event will only return
+ // InputEvent with a single action.
+ entries = {
+ // id x y
+ {0ms, {{0, 10, 20}}, AMOTION_EVENT_ACTION_DOWN},
+ };
+ publishInputEventEntries(entries);
+ frameTime = 5ms;
+ expectedEntries = {
+ // id x y
+ {0ms, {{0, 10, 20}}, AMOTION_EVENT_ACTION_DOWN},
+ };
+ consumeInputEventEntries(expectedEntries, frameTime);
+
+ // Two ACTION_MOVE events 10 ms apart that move in X direction and stay still in Y
+ entries = {
+ // id x y
+ {10ms, {{0, 20, 30}}, AMOTION_EVENT_ACTION_MOVE},
+ {20ms, {{0, 30, 30}}, AMOTION_EVENT_ACTION_MOVE},
+ };
+ publishInputEventEntries(entries);
+ frameTime = 35ms;
+ expectedEntries = {
+ // id x y
+ {10ms, {{0, 20, 30}}, AMOTION_EVENT_ACTION_MOVE},
+ {20ms, {{0, 30, 30}}, AMOTION_EVENT_ACTION_MOVE},
+ {25ms, {{0, 35, 30}}, AMOTION_EVENT_ACTION_MOVE}, // resampled value
+ };
+ consumeInputEventEntries(expectedEntries, frameTime);
+ // Above, the resampled event is at 25ms rather than at 30 ms = 35ms - RESAMPLE_LATENCY
+ // because we are further bound by how far we can extrapolate by the "last time delta".
+ // That's 50% of (20 ms - 10ms) => 5ms. So we can't predict more than 5 ms into the future
+ // from the event at 20ms, which is why the resampled event is at t = 25 ms.
+
+ // We resampled the event to 25 ms. Now, an older 'real' event comes in.
+ entries = {
+ // id x y
+ {24ms, {{0, 40, 30}}, AMOTION_EVENT_ACTION_MOVE},
+ };
+ publishInputEventEntries(entries);
+ frameTime = 50ms;
+ expectedEntries = {
+ // id x y
+ {24ms, {{0, 35, 30}}, AMOTION_EVENT_ACTION_MOVE}, // original event, rewritten
+ {26ms, {{0, 45, 30}}, AMOTION_EVENT_ACTION_MOVE}, // resampled event, rewritten
+ };
+ consumeInputEventEntries(expectedEntries, frameTime);
+}
+
+TEST_F(TouchResamplingTest, TwoPointersAreResampledIndependently) {
+ std::chrono::nanoseconds frameTime;
+ std::vector<InputEventEntry> entries, expectedEntries;
+
+ // full action for when a pointer with id=1 appears (some other pointer must already be present)
+ constexpr int32_t actionPointer1Down =
+ AMOTION_EVENT_ACTION_POINTER_DOWN + (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+
+ // full action for when a pointer with id=0 disappears (some other pointer must still remain)
+ constexpr int32_t actionPointer0Up =
+ AMOTION_EVENT_ACTION_POINTER_UP + (0 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+
+ // Initial ACTION_DOWN should be separate, because the first consume event will only return
+ // InputEvent with a single action.
+ entries = {
+ // id x y
+ {0ms, {{0, 100, 100}}, AMOTION_EVENT_ACTION_DOWN},
+ };
+ publishInputEventEntries(entries);
+ frameTime = 5ms;
+ expectedEntries = {
+ // id x y
+ {0ms, {{0, 100, 100}}, AMOTION_EVENT_ACTION_DOWN},
+ };
+ consumeInputEventEntries(expectedEntries, frameTime);
+
+ entries = {
+ // id x y
+ {10ms, {{0, 100, 100}}, AMOTION_EVENT_ACTION_MOVE},
+ };
+ publishInputEventEntries(entries);
+ frameTime = 10ms + 5ms /*RESAMPLE_LATENCY*/;
+ expectedEntries = {
+ // id x y
+ {10ms, {{0, 100, 100}}, AMOTION_EVENT_ACTION_MOVE},
+ // no resampled value because frameTime - RESAMPLE_LATENCY == eventTime
+ };
+ consumeInputEventEntries(expectedEntries, frameTime);
+
+ // Second pointer id=1 appears
+ entries = {
+ // id x y
+ {15ms, {{0, 100, 100}, {1, 500, 500}}, actionPointer1Down},
+ };
+ publishInputEventEntries(entries);
+ frameTime = 20ms + 5ms /*RESAMPLE_LATENCY*/;
+ expectedEntries = {
+ // id x y
+ {15ms, {{0, 100, 100}, {1, 500, 500}}, actionPointer1Down},
+ // no resampled value because frameTime - RESAMPLE_LATENCY == eventTime
+ };
+ consumeInputEventEntries(expectedEntries, frameTime);
+
+ // Both pointers move
+ entries = {
+ // id x y
+ {30ms, {{0, 100, 100}, {1, 500, 500}}, AMOTION_EVENT_ACTION_MOVE},
+ {40ms, {{0, 120, 120}, {1, 600, 600}}, AMOTION_EVENT_ACTION_MOVE},
+ };
+ publishInputEventEntries(entries);
+ frameTime = 45ms + 5ms /*RESAMPLE_LATENCY*/;
+ expectedEntries = {
+ // id x y
+ {30ms, {{0, 100, 100}, {1, 500, 500}}, AMOTION_EVENT_ACTION_MOVE},
+ {40ms, {{0, 120, 120}, {1, 600, 600}}, AMOTION_EVENT_ACTION_MOVE},
+ {45ms, {{0, 130, 130}, {1, 650, 650}}, AMOTION_EVENT_ACTION_MOVE}, // resampled value
+ };
+ consumeInputEventEntries(expectedEntries, frameTime);
+
+ // Both pointers move again
+ entries = {
+ // id x y
+ {60ms, {{0, 120, 120}, {1, 600, 600}}, AMOTION_EVENT_ACTION_MOVE},
+ {70ms, {{0, 130, 130}, {1, 700, 700}}, AMOTION_EVENT_ACTION_MOVE},
+ };
+ publishInputEventEntries(entries);
+ frameTime = 75ms + 5ms /*RESAMPLE_LATENCY*/;
+ /**
+ * The sample at t = 60, pointer id 0 is not equal to 120, because this value of 120 was
+ * received twice, and resampled to 130. So if we already reported it as "130", we continue
+ * to report it as such. Similar with pointer id 1.
+ */
+ expectedEntries = {
+ {60ms,
+ {{0, 130, 130}, // not 120! because it matches previous real event
+ {1, 650, 650}},
+ AMOTION_EVENT_ACTION_MOVE},
+ {70ms, {{0, 130, 130}, {1, 700, 700}}, AMOTION_EVENT_ACTION_MOVE},
+ {75ms, {{0, 135, 135}, {1, 750, 750}}, AMOTION_EVENT_ACTION_MOVE}, // resampled value
+ };
+ consumeInputEventEntries(expectedEntries, frameTime);
+
+ // First pointer id=0 leaves the screen
+ entries = {
+ // id x y
+ {80ms, {{1, 600, 600}}, actionPointer0Up},
+ };
+ publishInputEventEntries(entries);
+ frameTime = 90ms;
+ expectedEntries = {
+ // id x y
+ {80ms, {{1, 600, 600}}, actionPointer0Up},
+ // no resampled event for ACTION_POINTER_UP
+ };
+ consumeInputEventEntries(expectedEntries, frameTime);
+
+ // Remaining pointer id=1 is still present, but doesn't move
+ entries = {
+ // id x y
+ {90ms, {{1, 600, 600}}, AMOTION_EVENT_ACTION_MOVE},
+ };
+ publishInputEventEntries(entries);
+ frameTime = 100ms;
+ expectedEntries = {
+ // id x y
+ {90ms, {{1, 600, 600}}, AMOTION_EVENT_ACTION_MOVE},
+ /**
+ * The latest event with ACTION_MOVE was at t = 70, coord = 700.
+ * Use that value for resampling here: (600 - 700) / (90 - 70) * 5 + 600
+ */
+ {95ms, {{1, 575, 575}}, AMOTION_EVENT_ACTION_MOVE}, // resampled value
+ };
+ consumeInputEventEntries(expectedEntries, frameTime);
+}
+
+} // namespace android
diff --git a/libs/input/tests/VelocityTracker_test.cpp b/libs/input/tests/VelocityTracker_test.cpp
index a87b187..4a445de 100644
--- a/libs/input/tests/VelocityTracker_test.cpp
+++ b/libs/input/tests/VelocityTracker_test.cpp
@@ -26,7 +26,9 @@
#include <gui/constants.h>
#include <input/VelocityTracker.h>
-using namespace std::chrono_literals;
+using std::literals::chrono_literals::operator""ms;
+using std::literals::chrono_literals::operator""ns;
+using std::literals::chrono_literals::operator""us;
using android::base::StringPrintf;
namespace android {
@@ -149,8 +151,7 @@
if (i == 0) {
action = AMOTION_EVENT_ACTION_DOWN;
EXPECT_EQ(1U, pointerCount) << "First event should only have 1 pointer";
- } else if (i == motions.size() - 1) {
- EXPECT_EQ(1U, pointerCount) << "Last event should only have 1 pointer";
+ } else if ((i == motions.size() - 1) && pointerCount == 1) {
action = AMOTION_EVENT_ACTION_UP;
} else {
const MotionEventEntry& previousEntry = motions[i-1];
@@ -195,7 +196,7 @@
static void computeAndCheckVelocity(const VelocityTracker::Strategy strategy,
const std::vector<MotionEventEntry>& motions, int32_t axis,
- float targetVelocity) {
+ float targetVelocity, uint32_t pointerId = DEFAULT_POINTER_ID) {
VelocityTracker vt(strategy);
float Vx, Vy;
@@ -204,7 +205,7 @@
vt.addMovement(&event);
}
- vt.getVelocity(DEFAULT_POINTER_ID, &Vx, &Vy);
+ vt.getVelocity(pointerId, &Vx, &Vy);
switch (axis) {
case AMOTION_EVENT_AXIS_X:
@@ -846,13 +847,71 @@
// Velocity should actually be zero, but we expect 0.016 here instead.
// This is close enough to zero, and is likely caused by division by a very small number.
- computeAndCheckVelocity(VelocityTracker::Strategy::LSQ2, motions, AMOTION_EVENT_AXIS_X, -0.016);
- computeAndCheckVelocity(VelocityTracker::Strategy::LSQ2, motions, AMOTION_EVENT_AXIS_Y, -0.016);
+ computeAndCheckVelocity(VelocityTracker::Strategy::LSQ2, motions, AMOTION_EVENT_AXIS_X, 0);
+ computeAndCheckVelocity(VelocityTracker::Strategy::LSQ2, motions, AMOTION_EVENT_AXIS_Y, 0);
computeAndCheckVelocity(VelocityTracker::Strategy::IMPULSE, motions, AMOTION_EVENT_AXIS_X, 0);
computeAndCheckVelocity(VelocityTracker::Strategy::IMPULSE, motions, AMOTION_EVENT_AXIS_Y, 0);
}
/**
+ * ================= Pointer liftoff ===============================================================
+ */
+
+/**
+ * The last movement of a pointer is always ACTION_POINTER_UP or ACTION_UP. If there's a short delay
+ * between the last ACTION_MOVE and the next ACTION_POINTER_UP or ACTION_UP, velocity should not be
+ * affected by the liftoff.
+ */
+TEST_F(VelocityTrackerTest, ShortDelayBeforeActionUp) {
+ std::vector<MotionEventEntry> motions = {
+ {0ms, {{10, 0}}}, {10ms, {{20, 0}}}, {20ms, {{30, 0}}}, {30ms, {{30, 0}}}, // ACTION_UP
+ };
+ computeAndCheckVelocity(VelocityTracker::Strategy::IMPULSE, motions, AMOTION_EVENT_AXIS_X,
+ 1000);
+ computeAndCheckVelocity(VelocityTracker::Strategy::LSQ2, motions, AMOTION_EVENT_AXIS_X, 1000);
+}
+
+/**
+ * The last movement of a single pointer is ACTION_UP. If there's a long delay between the last
+ * ACTION_MOVE and the final ACTION_UP, velocity should be reported as zero because the pointer
+ * should be assumed to have stopped.
+ */
+TEST_F(VelocityTrackerTest, LongDelayBeforeActionUp) {
+ std::vector<MotionEventEntry> motions = {
+ {0ms, {{10, 0}}},
+ {10ms, {{20, 0}}},
+ {20ms, {{30, 0}}},
+ {3000ms, {{30, 0}}}, // ACTION_UP
+ };
+ computeAndCheckVelocity(VelocityTracker::Strategy::IMPULSE, motions, AMOTION_EVENT_AXIS_X, 0);
+ computeAndCheckVelocity(VelocityTracker::Strategy::LSQ2, motions, AMOTION_EVENT_AXIS_X, 0);
+}
+
+/**
+ * The last movement of a pointer is always ACTION_POINTER_UP or ACTION_UP. If there's a long delay
+ * before ACTION_POINTER_UP event, the movement should be assumed to have stopped.
+ * The final velocity should be reported as zero for all pointers.
+ */
+TEST_F(VelocityTrackerTest, LongDelayBeforeActionPointerUp) {
+ std::vector<MotionEventEntry> motions = {
+ {0ms, {{10, 0}}},
+ {10ms, {{20, 0}, {100, 0}}},
+ {20ms, {{30, 0}, {200, 0}}},
+ {30ms, {{30, 0}, {300, 0}}},
+ {40ms, {{30, 0}, {400, 0}}},
+ {3000ms, {{30, 0}}}, // ACTION_POINTER_UP
+ };
+ computeAndCheckVelocity(VelocityTracker::Strategy::IMPULSE, motions, AMOTION_EVENT_AXIS_X, 0,
+ /*pointerId*/ 0);
+ computeAndCheckVelocity(VelocityTracker::Strategy::LSQ2, motions, AMOTION_EVENT_AXIS_X, 0,
+ /*pointerId*/ 0);
+ computeAndCheckVelocity(VelocityTracker::Strategy::IMPULSE, motions, AMOTION_EVENT_AXIS_X, 0,
+ /*pointerId*/ 1);
+ computeAndCheckVelocity(VelocityTracker::Strategy::LSQ2, motions, AMOTION_EVENT_AXIS_X, 0,
+ /*pointerId*/ 1);
+}
+
+/**
* ================== Tests for least squares fitting ==============================================
*
* Special care must be taken when constructing tests for LeastSquaresVelocityTrackerStrategy
diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp
index 8240b08..539cbaa 100644
--- a/libs/nativedisplay/AChoreographer.cpp
+++ b/libs/nativedisplay/AChoreographer.cpp
@@ -18,8 +18,8 @@
//#define LOG_NDEBUG 0
#include <android-base/thread_annotations.h>
+#include <android/gui/ISurfaceComposer.h>
#include <gui/DisplayEventDispatcher.h>
-#include <gui/ISurfaceComposer.h>
#include <jni.h>
#include <private/android/choreographer.h>
#include <utils/Looper.h>
@@ -198,7 +198,7 @@
}
Choreographer::Choreographer(const sp<Looper>& looper)
- : DisplayEventDispatcher(looper, ISurfaceComposer::VsyncSource::eVsyncSourceApp),
+ : DisplayEventDispatcher(looper, gui::ISurfaceComposer::VsyncSource::eVsyncSourceApp),
mLooper(looper),
mThreadId(std::this_thread::get_id()) {
std::lock_guard<std::mutex> _l(gChoreographers.lock);
diff --git a/libs/nativedisplay/Android.bp b/libs/nativedisplay/Android.bp
index 4659b96..8d8a2bc 100644
--- a/libs/nativedisplay/Android.bp
+++ b/libs/nativedisplay/Android.bp
@@ -53,6 +53,7 @@
version_script: "libnativedisplay.map.txt",
srcs: [
+ ":libgui_frame_event_aidl",
"AChoreographer.cpp",
"ADisplay.cpp",
"surfacetexture/surface_texture.cpp",
diff --git a/libs/nativewindow/AHardwareBuffer.cpp b/libs/nativewindow/AHardwareBuffer.cpp
index 4a1784e..f3009dd 100644
--- a/libs/nativewindow/AHardwareBuffer.cpp
+++ b/libs/nativewindow/AHardwareBuffer.cpp
@@ -357,12 +357,12 @@
return INVALID_OPERATION;
}
- GraphicBuffer* gBuffer = new GraphicBuffer();
+ sp<GraphicBuffer> gBuffer(new GraphicBuffer());
status_t err = gBuffer->unflatten(data, dataLen, fdData, fdCount);
if (err != NO_ERROR) {
return err;
}
- *outBuffer = AHardwareBuffer_from_GraphicBuffer(gBuffer);
+ *outBuffer = AHardwareBuffer_from_GraphicBuffer(gBuffer.get());
// Ensure the buffer has a positive ref-count.
AHardwareBuffer_acquire(*outBuffer);
diff --git a/libs/nativewindow/ANativeWindow.cpp b/libs/nativewindow/ANativeWindow.cpp
index 18a4b2d..731f989 100644
--- a/libs/nativewindow/ANativeWindow.cpp
+++ b/libs/nativewindow/ANativeWindow.cpp
@@ -176,8 +176,8 @@
static_cast<int>(HAL_DATASPACE_BT2020_HLG));
static_assert(static_cast<int>(ADATASPACE_BT2020_ITU_HLG) ==
static_cast<int>(HAL_DATASPACE_BT2020_ITU_HLG));
- static_assert(static_cast<int>(DEPTH) == static_cast<int>(HAL_DATASPACE_DEPTH));
- static_assert(static_cast<int>(DYNAMIC_DEPTH) == static_cast<int>(HAL_DATASPACE_DYNAMIC_DEPTH));
+ static_assert(static_cast<int>(ADATASPACE_DEPTH) == static_cast<int>(HAL_DATASPACE_DEPTH));
+ static_assert(static_cast<int>(ADATASPACE_DYNAMIC_DEPTH) == static_cast<int>(HAL_DATASPACE_DYNAMIC_DEPTH));
if (!window || !query(window, NATIVE_WINDOW_IS_VALID) ||
!isDataSpaceValid(window, dataSpace)) {
@@ -193,6 +193,13 @@
return query(window, NATIVE_WINDOW_DATASPACE);
}
+int32_t ANativeWindow_getBuffersDefaultDataSpace(ANativeWindow* window) {
+ if (!window || !query(window, NATIVE_WINDOW_IS_VALID)) {
+ return -EINVAL;
+ }
+ return query(window, NATIVE_WINDOW_DEFAULT_DATASPACE);
+}
+
int32_t ANativeWindow_setFrameRate(ANativeWindow* window, float frameRate, int8_t compatibility) {
return ANativeWindow_setFrameRateWithChangeStrategy(window, frameRate, compatibility,
ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS);
diff --git a/libs/nativewindow/include/android/data_space.h b/libs/nativewindow/include/android/data_space.h
index 771844f..ad4cc4a 100644
--- a/libs/nativewindow/include/android/data_space.h
+++ b/libs/nativewindow/include/android/data_space.h
@@ -548,14 +548,14 @@
*
* This value is valid with formats HAL_PIXEL_FORMAT_Y16 and HAL_PIXEL_FORMAT_BLOB.
*/
- DEPTH = 4096,
+ ADATASPACE_DEPTH = 4096,
/**
* ISO 16684-1:2011(E) Dynamic Depth:
*
* Embedded depth metadata following the dynamic depth specification.
*/
- DYNAMIC_DEPTH = 4098
+ ADATASPACE_DYNAMIC_DEPTH = 4098
};
__END_DECLS
diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h
index f0e1c4d..20f4b52 100644
--- a/libs/nativewindow/include/android/native_window.h
+++ b/libs/nativewindow/include/android/native_window.h
@@ -227,6 +227,16 @@
*/
int32_t ANativeWindow_getBuffersDataSpace(ANativeWindow* window) __INTRODUCED_IN(28);
+/**
+ * Get the default dataspace of the buffers in window as set by the consumer.
+ *
+ * Available since API level 34.
+ *
+ * \return the dataspace of buffers in window, ADATASPACE_UNKNOWN is returned if
+ * dataspace is unknown, or -EINVAL if window is invalid.
+ */
+int32_t ANativeWindow_getBuffersDefaultDataSpace(ANativeWindow* window) __INTRODUCED_IN(34);
+
/** Compatibility value for ANativeWindow_setFrameRate. */
enum ANativeWindow_FrameRateCompatibility {
/**
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index a54af1f..79f49e1 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -1034,6 +1034,11 @@
* This surface is ignored while choosing the refresh rate.
*/
ANATIVEWINDOW_FRAME_RATE_NO_VOTE,
+
+ /**
+ * This surface will vote for the minimum refresh rate.
+ */
+ ANATIVEWINDOW_FRAME_RATE_MIN
};
static inline int native_window_set_frame_rate(struct ANativeWindow* window, float frameRate,
diff --git a/libs/nativewindow/libnativewindow.map.txt b/libs/nativewindow/libnativewindow.map.txt
index 988132c..f8c9e4a 100644
--- a/libs/nativewindow/libnativewindow.map.txt
+++ b/libs/nativewindow/libnativewindow.map.txt
@@ -21,6 +21,7 @@
ANativeWindow_cancelBuffer; # llndk
ANativeWindow_dequeueBuffer; # llndk
ANativeWindow_getBuffersDataSpace; # introduced=28
+ ANativeWindow_getBuffersDefaultDataSpace; # introduced=34
ANativeWindow_getFormat;
ANativeWindow_getHeight;
ANativeWindow_getLastDequeueDuration; # apex # introduced=30
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index 22dd866..6dc01b9 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -921,7 +921,8 @@
// Finally, we cut the layer into 3 parts, with top and bottom parts having rounded corners
// and the middle part without rounded corners.
- const int32_t radius = ceil(layer.geometry.roundedCornersRadius);
+ const int32_t radius = ceil(
+ (layer.geometry.roundedCornersRadius.x + layer.geometry.roundedCornersRadius.y) / 2.0);
const Rect topRect(bounds.left, bounds.top, bounds.right, bounds.top + radius);
setScissor(topRect);
drawMesh(mesh);
@@ -1266,23 +1267,24 @@
const half3 solidColor = layer.source.solidColor;
const half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer.alpha);
+ const float radius =
+ (layer.geometry.roundedCornersRadius.x + layer.geometry.roundedCornersRadius.y) /
+ 2.0f;
// Buffer sources will have a black solid color ignored in the shader,
// so in that scenario the solid color passed here is arbitrary.
- setupLayerBlending(usePremultipliedAlpha, isOpaque, disableTexture, color,
- layer.geometry.roundedCornersRadius);
+ setupLayerBlending(usePremultipliedAlpha, isOpaque, disableTexture, color, radius);
if (layer.disableBlending) {
glDisable(GL_BLEND);
}
setSourceDataSpace(layer.sourceDataspace);
if (layer.shadow.length > 0.0f) {
- handleShadow(layer.geometry.boundaries, layer.geometry.roundedCornersRadius,
- layer.shadow);
+ handleShadow(layer.geometry.boundaries, radius, layer.shadow);
}
// We only want to do a special handling for rounded corners when having rounded corners
// is the only reason it needs to turn on blending, otherwise, we handle it like the
// usual way since it needs to turn on blending anyway.
- else if (layer.geometry.roundedCornersRadius > 0.0 && color.a >= 1.0f && isOpaque) {
+ else if (radius > 0.0 && color.a >= 1.0f && isOpaque) {
handleRoundedCorners(display, layer, mesh);
} else {
drawMesh(mesh);
diff --git a/libs/renderengine/include/renderengine/BorderRenderInfo.h b/libs/renderengine/include/renderengine/BorderRenderInfo.h
new file mode 100644
index 0000000..0ee6661
--- /dev/null
+++ b/libs/renderengine/include/renderengine/BorderRenderInfo.h
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+#pragma once
+#include <math/mat4.h>
+#include <ui/Region.h>
+
+namespace android {
+namespace renderengine {
+
+struct BorderRenderInfo {
+ float width = 0;
+ half4 color;
+ Region combinedRegion;
+
+ bool operator==(const BorderRenderInfo& rhs) const {
+ return (width == rhs.width && color == rhs.color &&
+ combinedRegion.hasSameRects(rhs.combinedRegion));
+ }
+};
+
+} // namespace renderengine
+} // namespace android
\ No newline at end of file
diff --git a/libs/renderengine/include/renderengine/DisplaySettings.h b/libs/renderengine/include/renderengine/DisplaySettings.h
index 59ef991..25fe9f2 100644
--- a/libs/renderengine/include/renderengine/DisplaySettings.h
+++ b/libs/renderengine/include/renderengine/DisplaySettings.h
@@ -22,6 +22,7 @@
#include <math/mat4.h>
#include <renderengine/PrintMatrix.h>
+#include <renderengine/BorderRenderInfo.h>
#include <ui/GraphicTypes.h>
#include <ui/Rect.h>
#include <ui/Region.h>
@@ -79,6 +80,8 @@
// Configures the rendering intent of the output display. This is used for tonemapping.
aidl::android::hardware::graphics::composer3::RenderIntent renderIntent =
aidl::android::hardware::graphics::composer3::RenderIntent::TONE_MAP_COLORIMETRIC;
+
+ std::vector<renderengine::BorderRenderInfo> borderInfoList;
};
static inline bool operator==(const DisplaySettings& lhs, const DisplaySettings& rhs) {
@@ -90,7 +93,8 @@
lhs.deviceHandlesColorTransform == rhs.deviceHandlesColorTransform &&
lhs.orientation == rhs.orientation &&
lhs.targetLuminanceNits == rhs.targetLuminanceNits &&
- lhs.dimmingStage == rhs.dimmingStage && lhs.renderIntent == rhs.renderIntent;
+ lhs.dimmingStage == rhs.dimmingStage && lhs.renderIntent == rhs.renderIntent &&
+ lhs.borderInfoList == rhs.borderInfoList;
}
static const char* orientation_to_string(uint32_t orientation) {
diff --git a/libs/renderengine/include/renderengine/LayerSettings.h b/libs/renderengine/include/renderengine/LayerSettings.h
index 154e526..b3a617c 100644
--- a/libs/renderengine/include/renderengine/LayerSettings.h
+++ b/libs/renderengine/include/renderengine/LayerSettings.h
@@ -87,7 +87,7 @@
// rectangle to figure out how to apply the radius for this layer. The crop rectangle will be
// in local layer coordinate space, so we have to take the layer transform into account when
// walking up the tree.
- float roundedCornersRadius = 0.0;
+ vec2 roundedCornersRadius = vec2(0.0f, 0.0f);
// Rectangle within which corners will be rounded.
FloatRect roundedCornersCrop = FloatRect();
@@ -258,7 +258,8 @@
PrintTo(settings.boundaries, os);
*os << "\n .positionTransform = ";
PrintMatrix(settings.positionTransform, os);
- *os << "\n .roundedCornersRadius = " << settings.roundedCornersRadius;
+ *os << "\n .roundedCornersRadiusX = " << settings.roundedCornersRadius.x;
+ *os << "\n .roundedCornersRadiusY = " << settings.roundedCornersRadius.y;
*os << "\n .roundedCornersCrop = ";
PrintTo(settings.roundedCornersCrop, os);
*os << "\n}";
diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp
index f3064f3..c39f0a9 100644
--- a/libs/renderengine/skia/Cache.cpp
+++ b/libs/renderengine/skia/Cache.cpp
@@ -66,7 +66,7 @@
Geometry{
.boundaries = rect,
.roundedCornersCrop = rect,
- .roundedCornersRadius = 50.f,
+ .roundedCornersRadius = {50.f, 50.f},
},
// drawShadow ignores alpha
.shadow =
@@ -87,7 +87,7 @@
Geometry{
.boundaries = smallerRect,
.roundedCornersCrop = rect,
- .roundedCornersRadius = 50.f,
+ .roundedCornersRadius = {50.f, 50.f},
},
.source =
PixelSource{
@@ -148,7 +148,7 @@
// In reduced shader mode, all non-zero round rect radii get the same code path.
for (float roundedCornersRadius : {0.0f, 50.0f}) {
// roundedCornersCrop is always set, but the radius triggers the behavior
- layer.geometry.roundedCornersRadius = roundedCornersRadius;
+ layer.geometry.roundedCornersRadius = {roundedCornersRadius, roundedCornersRadius};
for (bool isOpaque : {true, false}) {
layer.source.buffer.isOpaque = isOpaque;
for (auto alpha : {half(.2f), half(1.0f)}) {
@@ -181,7 +181,7 @@
for (auto transform : {mat4(), kScaleAndTranslate}) {
layer.geometry.positionTransform = transform;
for (float roundedCornersRadius : {0.0f, 50.f}) {
- layer.geometry.roundedCornersRadius = roundedCornersRadius;
+ layer.geometry.roundedCornersRadius = {roundedCornersRadius, roundedCornersRadius};
auto layers = std::vector<LayerSettings>{layer};
renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache,
base::unique_fd());
@@ -238,7 +238,7 @@
.geometry =
Geometry{
.boundaries = rect,
- .roundedCornersRadius = 27, // larger than the 20 above.
+ .roundedCornersRadius = {27.f, 27.f},
.roundedCornersCrop =
FloatRect(0, 0, displayRect.width(), displayRect.height()),
},
@@ -275,9 +275,9 @@
// larger than the layer bounds.
.positionTransform = kFlip,
.boundaries = rect,
- .roundedCornersRadius = 94.2551,
- .roundedCornersCrop = FloatRect(
- -93.75, 0, displayRect.width() + 93.75, displayRect.height()),
+ .roundedCornersRadius = {94.2551f, 94.2551f},
+ .roundedCornersCrop = FloatRect(-93.75, 0, displayRect.width() + 93.75,
+ displayRect.height()),
},
.source = PixelSource{.buffer =
Buffer{
@@ -307,10 +307,11 @@
// the boundaries have to be smaller than the rounded crop so that
// clipRRect is used instead of drawRRect
.boundaries = small,
- .roundedCornersRadius = 50.f,
+ .roundedCornersRadius = {50.f, 50.f},
.roundedCornersCrop = rect,
},
- .source = PixelSource{
+ .source =
+ PixelSource{
.solidColor = half3(0.f, 0.f, 0.f),
},
.sourceDataspace = kDestDataSpace,
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index 97271cb..a0bba59 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -24,16 +24,35 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GrContextOptions.h>
+#include <SkBlendMode.h>
#include <SkCanvas.h>
+#include <SkColor.h>
#include <SkColorFilter.h>
#include <SkColorMatrix.h>
#include <SkColorSpace.h>
+#include <SkData.h>
#include <SkGraphics.h>
#include <SkImage.h>
#include <SkImageFilters.h>
+#include <SkImageInfo.h>
+#include <SkM44.h>
+#include <SkMatrix.h>
+#include <SkPaint.h>
+#include <SkPath.h>
+#include <SkPoint.h>
+#include <SkPoint3.h>
+#include <SkRect.h>
+#include <SkRefCnt.h>
#include <SkRegion.h>
+#include <SkRRect.h>
+#include <SkRuntimeEffect.h>
+#include <SkSamplingOptions.h>
+#include <SkScalar.h>
+#include <SkShader.h>
#include <SkShadowUtils.h>
+#include <SkString.h>
#include <SkSurface.h>
+#include <SkTileMode.h>
#include <android-base/stringprintf.h>
#include <gl/GrGLInterface.h>
#include <gui/TraceUtils.h>
@@ -52,8 +71,6 @@
#include "../gl/GLExtensions.h"
#include "Cache.h"
#include "ColorSpaces.h"
-#include "SkBlendMode.h"
-#include "SkImageInfo.h"
#include "filters/BlurFilter.h"
#include "filters/GaussianBlurFilter.h"
#include "filters/KawaseBlurFilter.h"
@@ -311,7 +328,7 @@
mProtectedPlaceholderSurface(protectedPlaceholder),
mDefaultPixelFormat(static_cast<PixelFormat>(args.pixelFormat)),
mUseColorManagement(args.useColorManagement) {
- sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface());
+ sk_sp<const GrGLInterface> glInterface = GrGLMakeNativeInterface();
LOG_ALWAYS_FATAL_IF(!glInterface.get());
GrContextOptions options;
@@ -762,15 +779,9 @@
const DisplaySettings& display, const std::vector<LayerSettings>& layers,
const std::shared_ptr<ExternalTexture>& buffer, const bool /*useFramebufferCache*/,
base::unique_fd&& bufferFence) {
- ATRACE_NAME("SkiaGL::drawLayers");
+ ATRACE_NAME("SkiaGL::drawLayersInternal");
std::lock_guard<std::mutex> lock(mRenderingMutex);
- if (layers.empty()) {
- ALOGV("Drawing empty layer stack");
- resultPromise->set_value({NO_ERROR, base::unique_fd()});
- return;
- }
-
if (buffer == nullptr) {
ALOGE("No output buffer provided. Aborting GPU composition.");
resultPromise->set_value({BAD_VALUE, base::unique_fd()});
@@ -1228,6 +1239,26 @@
activeSurface->flush();
}
}
+ for (const auto& borderRenderInfo : display.borderInfoList) {
+ SkPaint p;
+ p.setColor(SkColor4f{borderRenderInfo.color.r, borderRenderInfo.color.g,
+ borderRenderInfo.color.b, borderRenderInfo.color.a});
+ p.setAntiAlias(true);
+ p.setStyle(SkPaint::kStroke_Style);
+ p.setStrokeWidth(borderRenderInfo.width);
+ SkRegion sk_region;
+ SkPath path;
+
+ // Construct a final SkRegion using Regions
+ for (const auto& r : borderRenderInfo.combinedRegion) {
+ sk_region.op({r.left, r.top, r.right, r.bottom}, SkRegion::kUnion_Op);
+ }
+
+ sk_region.getBoundaryPath(&path);
+ canvas->drawPath(path, p);
+ path.close();
+ }
+
surfaceAutoSaveRestore.restore();
mCapture->endCapture();
{
@@ -1276,7 +1307,7 @@
* produce the insected roundRect. If false, the returned state of the radii param is undefined.
*/
static bool intersectionIsRoundRect(const SkRect& bounds, const SkRect& crop,
- const SkRect& insetCrop, float cornerRadius,
+ const SkRect& insetCrop, const vec2& cornerRadius,
SkVector radii[4]) {
const bool leftEqual = bounds.fLeft == crop.fLeft;
const bool topEqual = bounds.fTop == crop.fTop;
@@ -1288,8 +1319,8 @@
// In particular the round rect implementation will scale the value of all corner radii
// if the sum of the radius along any edge is greater than the length of that edge.
// See https://www.w3.org/TR/css-backgrounds-3/#corner-overlap
- const bool requiredWidth = bounds.width() > (cornerRadius * 2);
- const bool requiredHeight = bounds.height() > (cornerRadius * 2);
+ const bool requiredWidth = bounds.width() > (cornerRadius.x * 2);
+ const bool requiredHeight = bounds.height() > (cornerRadius.y * 2);
if (!requiredWidth || !requiredHeight) {
return false;
}
@@ -1298,7 +1329,7 @@
// contained within the cropped shape and does not need rounded.
// compute the UpperLeft corner radius
if (leftEqual && topEqual) {
- radii[0].set(cornerRadius, cornerRadius);
+ radii[0].set(cornerRadius.x, cornerRadius.y);
} else if ((leftEqual && bounds.fTop >= insetCrop.fTop) ||
(topEqual && bounds.fLeft >= insetCrop.fLeft)) {
radii[0].set(0, 0);
@@ -1307,7 +1338,7 @@
}
// compute the UpperRight corner radius
if (rightEqual && topEqual) {
- radii[1].set(cornerRadius, cornerRadius);
+ radii[1].set(cornerRadius.x, cornerRadius.y);
} else if ((rightEqual && bounds.fTop >= insetCrop.fTop) ||
(topEqual && bounds.fRight <= insetCrop.fRight)) {
radii[1].set(0, 0);
@@ -1316,7 +1347,7 @@
}
// compute the BottomRight corner radius
if (rightEqual && bottomEqual) {
- radii[2].set(cornerRadius, cornerRadius);
+ radii[2].set(cornerRadius.x, cornerRadius.y);
} else if ((rightEqual && bounds.fBottom <= insetCrop.fBottom) ||
(bottomEqual && bounds.fRight <= insetCrop.fRight)) {
radii[2].set(0, 0);
@@ -1325,7 +1356,7 @@
}
// compute the BottomLeft corner radius
if (leftEqual && bottomEqual) {
- radii[3].set(cornerRadius, cornerRadius);
+ radii[3].set(cornerRadius.x, cornerRadius.y);
} else if ((leftEqual && bounds.fBottom <= insetCrop.fBottom) ||
(bottomEqual && bounds.fLeft >= insetCrop.fLeft)) {
radii[3].set(0, 0);
@@ -1338,22 +1369,22 @@
inline std::pair<SkRRect, SkRRect> SkiaGLRenderEngine::getBoundsAndClip(const FloatRect& boundsRect,
const FloatRect& cropRect,
- const float cornerRadius) {
+ const vec2& cornerRadius) {
const SkRect bounds = getSkRect(boundsRect);
const SkRect crop = getSkRect(cropRect);
SkRRect clip;
- if (cornerRadius > 0) {
+ if (cornerRadius.x > 0 && cornerRadius.y > 0) {
// it the crop and the bounds are equivalent or there is no crop then we don't need a clip
if (bounds == crop || crop.isEmpty()) {
- return {SkRRect::MakeRectXY(bounds, cornerRadius, cornerRadius), clip};
+ return {SkRRect::MakeRectXY(bounds, cornerRadius.x, cornerRadius.y), clip};
}
// This makes an effort to speed up common, simple bounds + clip combinations by
// converting them to a single RRect draw. It is possible there are other cases
// that can be converted.
if (crop.contains(bounds)) {
- const auto insetCrop = crop.makeInset(cornerRadius, cornerRadius);
+ const auto insetCrop = crop.makeInset(cornerRadius.x, cornerRadius.y);
if (insetCrop.contains(bounds)) {
return {SkRRect::MakeRect(bounds), clip}; // clip is empty - no rounding required
}
@@ -1367,7 +1398,7 @@
}
// we didn't hit any of our fast paths so set the clip to the cropRect
- clip.setRectXY(crop, cornerRadius, cornerRadius);
+ clip.setRectXY(crop, cornerRadius.x, cornerRadius.y);
}
// if we hit this point then we either don't have rounded corners or we are going to rely
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h
index 5ef9944..34f18c1 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.h
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.h
@@ -41,6 +41,10 @@
#include "filters/LinearEffect.h"
#include "filters/StretchShaderFactory.h"
+class SkData;
+
+struct SkPoint3;
+
namespace android {
namespace renderengine {
namespace skia {
@@ -90,7 +94,8 @@
inline SkRect getSkRect(const FloatRect& layer);
inline SkRect getSkRect(const Rect& layer);
inline std::pair<SkRRect, SkRRect> getBoundsAndClip(const FloatRect& bounds,
- const FloatRect& crop, float cornerRadius);
+ const FloatRect& crop,
+ const vec2& cornerRadius);
inline bool layerHasBlur(const LayerSettings& layer, bool colorTransformModifiesAlpha);
inline SkColor getSkColor(const vec4& color);
inline SkM44 getSkM44(const mat4& matrix);
diff --git a/libs/renderengine/skia/debug/SkiaCapture.cpp b/libs/renderengine/skia/debug/SkiaCapture.cpp
index 856fff4..b21b01c 100644
--- a/libs/renderengine/skia/debug/SkiaCapture.cpp
+++ b/libs/renderengine/skia/debug/SkiaCapture.cpp
@@ -27,6 +27,9 @@
#include <utils/Trace.h>
#include "CommonPool.h"
+#include "SkCanvas.h"
+#include "SkRect.h"
+#include "SkTypeface.h"
#include "src/utils/SkMultiPictureDocument.h"
namespace android {
diff --git a/libs/renderengine/skia/debug/SkiaCapture.h b/libs/renderengine/skia/debug/SkiaCapture.h
index f194629..d65a579 100644
--- a/libs/renderengine/skia/debug/SkiaCapture.h
+++ b/libs/renderengine/skia/debug/SkiaCapture.h
@@ -19,13 +19,15 @@
#include <SkDocument.h>
#include <SkNWayCanvas.h>
#include <SkPictureRecorder.h>
+#include <SkRefCnt.h>
+#include <SkStream.h>
#include <SkSurface.h>
+#include "tools/SkSharingProc.h"
#include <chrono>
#include <mutex>
#include "CaptureTimer.h"
-#include "tools/SkSharingProc.h"
namespace android {
namespace renderengine {
diff --git a/libs/renderengine/skia/filters/BlurFilter.cpp b/libs/renderengine/skia/filters/BlurFilter.cpp
index 63cc02b..2557ac9 100644
--- a/libs/renderengine/skia/filters/BlurFilter.cpp
+++ b/libs/renderengine/skia/filters/BlurFilter.cpp
@@ -17,7 +17,6 @@
#define ATRACE_TAG ATRACE_TAG_GRAPHICS
#include "BlurFilter.h"
#include <SkCanvas.h>
-#include <SkData.h>
#include <SkPaint.h>
#include <SkRRect.h>
#include <SkRuntimeEffect.h>
diff --git a/libs/renderengine/skia/filters/GaussianBlurFilter.cpp b/libs/renderengine/skia/filters/GaussianBlurFilter.cpp
index 55867a9..f3b6ab9 100644
--- a/libs/renderengine/skia/filters/GaussianBlurFilter.cpp
+++ b/libs/renderengine/skia/filters/GaussianBlurFilter.cpp
@@ -18,7 +18,6 @@
#include "GaussianBlurFilter.h"
#include <SkCanvas.h>
-#include <SkData.h>
#include <SkPaint.h>
#include <SkRRect.h>
#include <SkRuntimeEffect.h>
diff --git a/libs/renderengine/skia/filters/KawaseBlurFilter.cpp b/libs/renderengine/skia/filters/KawaseBlurFilter.cpp
index bfde06f..e370c39 100644
--- a/libs/renderengine/skia/filters/KawaseBlurFilter.cpp
+++ b/libs/renderengine/skia/filters/KawaseBlurFilter.cpp
@@ -18,7 +18,6 @@
#include "KawaseBlurFilter.h"
#include <SkCanvas.h>
-#include <SkData.h>
#include <SkPaint.h>
#include <SkRRect.h>
#include <SkRuntimeEffect.h>
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index 7c70a74..f289730 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -444,7 +444,9 @@
const ubyte4& backgroundColor) {
const Rect casterRect(castingLayer.geometry.boundaries);
Region casterRegion = Region(casterRect);
- const float casterCornerRadius = castingLayer.geometry.roundedCornersRadius;
+ const float casterCornerRadius = (castingLayer.geometry.roundedCornersRadius.x +
+ castingLayer.geometry.roundedCornersRadius.y) /
+ 2.0;
if (casterCornerRadius > 0.0f) {
// ignore the corners if a corner radius is set
Rect cornerRect(casterCornerRadius, casterCornerRadius);
@@ -1129,7 +1131,7 @@
renderengine::LayerSettings layer;
layer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
layer.geometry.boundaries = fullscreenRect().toFloatRect();
- layer.geometry.roundedCornersRadius = 5.0f;
+ layer.geometry.roundedCornersRadius = {5.0f, 5.0f};
layer.geometry.roundedCornersCrop = fullscreenRect().toFloatRect();
SourceVariant::fillColor(layer, 1.0f, 0.0f, 0.0f, this);
layer.alpha = 1.0f;
@@ -1606,6 +1608,36 @@
drawEmptyLayers();
}
+TEST_P(RenderEngineTest, drawLayers_fillRedBufferAndEmptyBuffer) {
+ const auto& renderEngineFactory = GetParam();
+ if (renderEngineFactory->type() == renderengine::RenderEngine::RenderEngineType::GLES) {
+ // GLES-specific test
+ return;
+ }
+
+ initializeRenderEngine();
+ renderengine::DisplaySettings settings;
+ settings.physicalDisplay = fullscreenRect();
+ settings.clip = fullscreenRect();
+ settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
+
+ // add a red layer
+ renderengine::LayerSettings layerOne{
+ .geometry.boundaries = fullscreenRect().toFloatRect(),
+ .source.solidColor = half3(1.0f, 0.0f, 0.0f),
+ .alpha = 1.f,
+ };
+
+ std::vector<renderengine::LayerSettings> layersFirst{layerOne};
+ invokeDraw(settings, layersFirst);
+ expectBufferColor(fullscreenRect(), 255, 0, 0, 255);
+
+ // re-draw with an empty layer above it, and we get a transparent black one
+ std::vector<renderengine::LayerSettings> layersSecond;
+ invokeDraw(settings, layersSecond);
+ expectBufferColor(fullscreenRect(), 0, 0, 0, 0);
+}
+
TEST_P(RenderEngineTest, drawLayers_withoutBuffers_withColorTransform) {
initializeRenderEngine();
@@ -2131,7 +2163,7 @@
casterBounds.offsetBy(shadowLength + 1, shadowLength + 1);
renderengine::LayerSettings castingLayer;
castingLayer.geometry.boundaries = casterBounds.toFloatRect();
- castingLayer.geometry.roundedCornersRadius = 3.0f;
+ castingLayer.geometry.roundedCornersRadius = {3.0f, 3.0f};
castingLayer.geometry.roundedCornersCrop = casterBounds.toFloatRect();
castingLayer.alpha = 1.0f;
renderengine::ShadowSettings settings =
@@ -2219,7 +2251,8 @@
renderengine::LayerSettings redLayer;
redLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
redLayer.geometry.boundaries = fullscreenRect().toFloatRect();
- redLayer.geometry.roundedCornersRadius = 5.0f;
+ redLayer.geometry.roundedCornersRadius = {5.0f, 5.0f};
+
redLayer.geometry.roundedCornersCrop = fullscreenRect().toFloatRect();
// Red background.
redLayer.source.solidColor = half3(1.0f, 0.0f, 0.0f);
@@ -2231,7 +2264,7 @@
renderengine::LayerSettings greenLayer;
greenLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
greenLayer.geometry.boundaries = fullscreenRect().toFloatRect();
- greenLayer.geometry.roundedCornersRadius = 5.0f;
+ greenLayer.geometry.roundedCornersRadius = {5.0f, 5.0f};
// Bottom right corner is not going to be rounded.
greenLayer.geometry.roundedCornersCrop =
Rect(DEFAULT_DISPLAY_WIDTH / 3, DEFAULT_DISPLAY_HEIGHT / 3, DEFAULT_DISPLAY_HEIGHT,
@@ -2268,7 +2301,7 @@
renderengine::LayerSettings redLayer;
redLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
redLayer.geometry.boundaries = fullscreenRect().toFloatRect();
- redLayer.geometry.roundedCornersRadius = 5.0f;
+ redLayer.geometry.roundedCornersRadius = {5.0f, 5.0f};
redLayer.geometry.roundedCornersCrop = fullscreenRect().toFloatRect();
// Red background.
redLayer.source.solidColor = half3(1.0f, 0.0f, 0.0f);
@@ -2313,7 +2346,7 @@
renderengine::LayerSettings redLayer;
redLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
redLayer.geometry.boundaries = FloatRect(0, 0, DEFAULT_DISPLAY_WIDTH, 32);
- redLayer.geometry.roundedCornersRadius = 64;
+ redLayer.geometry.roundedCornersRadius = {64.0f, 64.0f};
redLayer.geometry.roundedCornersCrop = FloatRect(0, 0, DEFAULT_DISPLAY_WIDTH, 128);
// Red background.
redLayer.source.solidColor = half3(1.0f, 0.0f, 0.0f);
@@ -2334,6 +2367,49 @@
expectBufferColor(Point(DEFAULT_DISPLAY_WIDTH / 2, 31), 255, 0, 0, 255);
}
+TEST_P(RenderEngineTest, testRoundedCornersXY) {
+ if (GetParam()->type() != renderengine::RenderEngine::RenderEngineType::SKIA_GL) {
+ GTEST_SKIP();
+ }
+
+ initializeRenderEngine();
+
+ renderengine::DisplaySettings settings;
+ settings.physicalDisplay = fullscreenRect();
+ settings.clip = fullscreenRect();
+ settings.outputDataspace = ui::Dataspace::V0_SRGB_LINEAR;
+
+ std::vector<renderengine::LayerSettings> layers;
+
+ renderengine::LayerSettings redLayer;
+ redLayer.sourceDataspace = ui::Dataspace::V0_SRGB_LINEAR;
+ redLayer.geometry.boundaries = fullscreenRect().toFloatRect();
+ redLayer.geometry.roundedCornersRadius = {5.0f, 20.0f};
+ redLayer.geometry.roundedCornersCrop = fullscreenRect().toFloatRect();
+ // Red background.
+ redLayer.source.solidColor = half3(1.0f, 0.0f, 0.0f);
+ redLayer.alpha = 1.0f;
+
+ layers.push_back(redLayer);
+
+ invokeDraw(settings, layers);
+
+ // Due to roundedCornersRadius, the corners are untouched.
+ expectBufferColor(Point(0, 0), 0, 0, 0, 0);
+ expectBufferColor(Point(DEFAULT_DISPLAY_WIDTH - 1, 0), 0, 0, 0, 0);
+ expectBufferColor(Point(0, DEFAULT_DISPLAY_HEIGHT - 1), 0, 0, 0, 0);
+ expectBufferColor(Point(DEFAULT_DISPLAY_WIDTH - 1, DEFAULT_DISPLAY_HEIGHT - 1), 0, 0, 0, 0);
+
+ // Y-axis draws a larger radius, check that its untouched as well
+ expectBufferColor(Point(0, DEFAULT_DISPLAY_HEIGHT - 5), 0, 0, 0, 0);
+ expectBufferColor(Point(DEFAULT_DISPLAY_WIDTH - 1, DEFAULT_DISPLAY_HEIGHT - 5), 0, 0, 0, 0);
+ expectBufferColor(Point(DEFAULT_DISPLAY_WIDTH - 1, 5), 0, 0, 0, 0);
+ expectBufferColor(Point(0, 5), 0, 0, 0, 0);
+
+ // middle should be red
+ expectBufferColor(Point(DEFAULT_DISPLAY_WIDTH / 2, DEFAULT_DISPLAY_HEIGHT / 2), 255, 0, 0, 255);
+}
+
TEST_P(RenderEngineTest, testClear) {
initializeRenderEngine();
@@ -2411,6 +2487,55 @@
expectBufferColor(rect, 0, 128, 0, 128);
}
+TEST_P(RenderEngineTest, testBorder) {
+ if (GetParam()->type() != renderengine::RenderEngine::RenderEngineType::SKIA_GL) {
+ GTEST_SKIP();
+ }
+
+ if (!GetParam()->useColorManagement()) {
+ GTEST_SKIP();
+ }
+
+ initializeRenderEngine();
+
+ const ui::Dataspace dataspace = ui::Dataspace::V0_SRGB;
+
+ const auto displayRect = Rect(1080, 2280);
+ renderengine::DisplaySettings display{
+ .physicalDisplay = displayRect,
+ .clip = displayRect,
+ .outputDataspace = dataspace,
+ };
+ display.borderInfoList.clear();
+ renderengine::BorderRenderInfo info;
+ info.combinedRegion = Region(Rect(99, 99, 199, 199));
+ info.width = 20.0f;
+ info.color = half4{1.0f, 128.0f / 255.0f, 0.0f, 1.0f};
+ display.borderInfoList.emplace_back(info);
+
+ const auto greenBuffer = allocateAndFillSourceBuffer(1, 1, ubyte4(0, 255, 0, 255));
+ const renderengine::LayerSettings greenLayer{
+ .geometry.boundaries = FloatRect(0.f, 0.f, 1.f, 1.f),
+ .source =
+ renderengine::PixelSource{
+ .buffer =
+ renderengine::Buffer{
+ .buffer = greenBuffer,
+ .usePremultipliedAlpha = true,
+ },
+ },
+ .alpha = 1.0f,
+ .sourceDataspace = dataspace,
+ .whitePointNits = 200.f,
+ };
+
+ std::vector<renderengine::LayerSettings> layers;
+ layers.emplace_back(greenLayer);
+ invokeDraw(display, layers);
+
+ expectBufferColor(Rect(99, 99, 101, 101), 255, 128, 0, 255, 1);
+}
+
TEST_P(RenderEngineTest, testDimming) {
if (GetParam()->type() == renderengine::RenderEngine::RenderEngineType::GLES) {
GTEST_SKIP();
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 0f771a9..ca8adfa 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -127,7 +127,6 @@
"DebugUtils.cpp",
"DeviceProductInfo.cpp",
"DisplayIdentification.cpp",
- "DisplayMode.cpp",
"DynamicDisplayInfo.cpp",
"Fence.cpp",
"FenceTime.cpp",
@@ -139,11 +138,9 @@
"GraphicBuffer.cpp",
"GraphicBufferAllocator.cpp",
"GraphicBufferMapper.cpp",
- "HdrCapabilities.cpp",
"PixelFormat.cpp",
"PublicFormat.cpp",
"StaticAsserts.cpp",
- "StaticDisplayInfo.cpp",
],
include_dirs: [
@@ -241,10 +238,6 @@
],
afdo: true,
-
- header_abi_checker: {
- diff_flags: ["-allow-adding-removing-weak-symbols"],
- },
}
cc_library_headers {
diff --git a/libs/ui/DeviceProductInfo.cpp b/libs/ui/DeviceProductInfo.cpp
index 04d9d3c..3306012 100644
--- a/libs/ui/DeviceProductInfo.cpp
+++ b/libs/ui/DeviceProductInfo.cpp
@@ -17,7 +17,6 @@
#include <ui/DeviceProductInfo.h>
#include <android-base/stringprintf.h>
-#include <ui/FlattenableHelpers.h>
#include <utils/Log.h>
#define RETURN_IF_ERROR(op) \
@@ -27,35 +26,6 @@
using base::StringAppendF;
-size_t DeviceProductInfo::getFlattenedSize() const {
- return FlattenableHelpers::getFlattenedSize(name) +
- FlattenableHelpers::getFlattenedSize(manufacturerPnpId) +
- FlattenableHelpers::getFlattenedSize(productId) +
- FlattenableHelpers::getFlattenedSize(manufactureOrModelDate) +
- FlattenableHelpers::getFlattenedSize(relativeAddress);
-}
-
-status_t DeviceProductInfo::flatten(void* buffer, size_t size) const {
- if (size < getFlattenedSize()) {
- return NO_MEMORY;
- }
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, name));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, manufacturerPnpId));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, productId));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, manufactureOrModelDate));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, relativeAddress));
- return OK;
-}
-
-status_t DeviceProductInfo::unflatten(void const* buffer, size_t size) {
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &name));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &manufacturerPnpId));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &productId));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &manufactureOrModelDate));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &relativeAddress));
- return OK;
-}
-
void DeviceProductInfo::dump(std::string& result) const {
StringAppendF(&result, "{name=\"%s\", ", name.c_str());
StringAppendF(&result, "manufacturerPnpId=%s, ", manufacturerPnpId.data());
diff --git a/libs/ui/DisplayMode.cpp b/libs/ui/DisplayMode.cpp
deleted file mode 100644
index cf05dbf..0000000
--- a/libs/ui/DisplayMode.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <ui/DisplayMode.h>
-
-#include <cstdint>
-
-#include <ui/FlattenableHelpers.h>
-
-#define RETURN_IF_ERROR(op) \
- if (const status_t status = (op); status != OK) return status;
-
-namespace android::ui {
-
-size_t DisplayMode::getFlattenedSize() const {
- return FlattenableHelpers::getFlattenedSize(id) +
- FlattenableHelpers::getFlattenedSize(resolution) +
- FlattenableHelpers::getFlattenedSize(xDpi) +
- FlattenableHelpers::getFlattenedSize(yDpi) +
- FlattenableHelpers::getFlattenedSize(refreshRate) +
- FlattenableHelpers::getFlattenedSize(appVsyncOffset) +
- FlattenableHelpers::getFlattenedSize(sfVsyncOffset) +
- FlattenableHelpers::getFlattenedSize(presentationDeadline) +
- FlattenableHelpers::getFlattenedSize(group);
-}
-
-status_t DisplayMode::flatten(void* buffer, size_t size) const {
- if (size < getFlattenedSize()) {
- return NO_MEMORY;
- }
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, id));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, resolution));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, xDpi));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, yDpi));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, refreshRate));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, appVsyncOffset));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, sfVsyncOffset));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, presentationDeadline));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, group));
- return OK;
-}
-
-status_t DisplayMode::unflatten(const void* buffer, size_t size) {
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &id));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &resolution));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &xDpi));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &yDpi));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &refreshRate));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &appVsyncOffset));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &sfVsyncOffset));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &presentationDeadline));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &group));
- return OK;
-}
-
-} // namespace android::ui
diff --git a/libs/ui/DynamicDisplayInfo.cpp b/libs/ui/DynamicDisplayInfo.cpp
index 78ba996..f5feea9 100644
--- a/libs/ui/DynamicDisplayInfo.cpp
+++ b/libs/ui/DynamicDisplayInfo.cpp
@@ -18,11 +18,6 @@
#include <cstdint>
-#include <ui/FlattenableHelpers.h>
-
-#define RETURN_IF_ERROR(op) \
- if (const status_t status = (op); status != OK) return status;
-
namespace android::ui {
std::optional<ui::DisplayMode> DynamicDisplayInfo::getActiveDisplayMode() const {
@@ -34,42 +29,4 @@
return {};
}
-size_t DynamicDisplayInfo::getFlattenedSize() const {
- return FlattenableHelpers::getFlattenedSize(supportedDisplayModes) +
- FlattenableHelpers::getFlattenedSize(activeDisplayModeId) +
- FlattenableHelpers::getFlattenedSize(supportedColorModes) +
- FlattenableHelpers::getFlattenedSize(activeColorMode) +
- FlattenableHelpers::getFlattenedSize(hdrCapabilities) +
- FlattenableHelpers::getFlattenedSize(autoLowLatencyModeSupported) +
- FlattenableHelpers::getFlattenedSize(gameContentTypeSupported) +
- FlattenableHelpers::getFlattenedSize(preferredBootDisplayMode);
-}
-
-status_t DynamicDisplayInfo::flatten(void* buffer, size_t size) const {
- if (size < getFlattenedSize()) {
- return NO_MEMORY;
- }
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, supportedDisplayModes));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, activeDisplayModeId));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, supportedColorModes));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, activeColorMode));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, hdrCapabilities));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, autoLowLatencyModeSupported));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, gameContentTypeSupported));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, preferredBootDisplayMode));
- return OK;
-}
-
-status_t DynamicDisplayInfo::unflatten(const void* buffer, size_t size) {
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &supportedDisplayModes));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &activeDisplayModeId));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &supportedColorModes));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &activeColorMode));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &hdrCapabilities));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &autoLowLatencyModeSupported));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &gameContentTypeSupported));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &preferredBootDisplayMode));
- return OK;
-}
-
} // namespace android::ui
diff --git a/libs/ui/HdrCapabilities.cpp b/libs/ui/HdrCapabilities.cpp
deleted file mode 100644
index aec2fac..0000000
--- a/libs/ui/HdrCapabilities.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <ui/HdrCapabilities.h>
-
-namespace android {
-
-#if defined(__clang__)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wundefined-reinterpret-cast"
-#endif
-
-size_t HdrCapabilities::getFlattenedSize() const {
- return sizeof(mMaxLuminance) +
- sizeof(mMaxAverageLuminance) +
- sizeof(mMinLuminance) +
- sizeof(int32_t) +
- mSupportedHdrTypes.size() * sizeof(ui::Hdr);
-}
-
-status_t HdrCapabilities::flatten(void* buffer, size_t size) const {
-
- if (size < getFlattenedSize()) {
- return NO_MEMORY;
- }
-
- int32_t* const buf = static_cast<int32_t*>(buffer);
- reinterpret_cast<float&>(buf[0]) = mMaxLuminance;
- reinterpret_cast<float&>(buf[1]) = mMaxAverageLuminance;
- reinterpret_cast<float&>(buf[2]) = mMinLuminance;
- buf[3] = static_cast<int32_t>(mSupportedHdrTypes.size());
- for (size_t i = 0, c = mSupportedHdrTypes.size(); i < c; ++i) {
- buf[4 + i] = static_cast<int32_t>(mSupportedHdrTypes[i]);
- }
- return NO_ERROR;
-}
-
-status_t HdrCapabilities::unflatten(void const* buffer, size_t size) {
-
- size_t minSize = sizeof(mMaxLuminance) +
- sizeof(mMaxAverageLuminance) +
- sizeof(mMinLuminance) +
- sizeof(int32_t);
-
- if (size < minSize) {
- return NO_MEMORY;
- }
-
- int32_t const * const buf = static_cast<int32_t const *>(buffer);
- const size_t itemCount = size_t(buf[3]);
-
- // check the buffer is large enough
- if (size < minSize + itemCount * sizeof(int32_t)) {
- return BAD_VALUE;
- }
-
- mMaxLuminance = reinterpret_cast<float const&>(buf[0]);
- mMaxAverageLuminance = reinterpret_cast<float const&>(buf[1]);
- mMinLuminance = reinterpret_cast<float const&>(buf[2]);
- if (itemCount) {
- mSupportedHdrTypes.resize(itemCount);
- for (size_t i = 0; i < itemCount; ++i) {
- mSupportedHdrTypes[i] = static_cast<ui::Hdr>(buf[4 + i]);
- }
- }
- return NO_ERROR;
-}
-
-#if defined(__clang__)
-#pragma clang diagnostic pop
-#endif
-
-} // namespace android
diff --git a/libs/ui/StaticDisplayInfo.cpp b/libs/ui/StaticDisplayInfo.cpp
deleted file mode 100644
index 03d15e4..0000000
--- a/libs/ui/StaticDisplayInfo.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <ui/StaticDisplayInfo.h>
-
-#include <cstdint>
-
-#include <ui/FlattenableHelpers.h>
-
-#define RETURN_IF_ERROR(op) \
- if (const status_t status = (op); status != OK) return status;
-
-namespace android::ui {
-
-size_t StaticDisplayInfo::getFlattenedSize() const {
- return FlattenableHelpers::getFlattenedSize(connectionType) +
- FlattenableHelpers::getFlattenedSize(density) +
- FlattenableHelpers::getFlattenedSize(secure) +
- FlattenableHelpers::getFlattenedSize(deviceProductInfo) +
- FlattenableHelpers::getFlattenedSize(installOrientation);
-}
-
-status_t StaticDisplayInfo::flatten(void* buffer, size_t size) const {
- if (size < getFlattenedSize()) {
- return NO_MEMORY;
- }
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, connectionType));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, density));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, secure));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, deviceProductInfo));
- RETURN_IF_ERROR(FlattenableHelpers::flatten(&buffer, &size, installOrientation));
- return OK;
-}
-
-status_t StaticDisplayInfo::unflatten(void const* buffer, size_t size) {
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &connectionType));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &density));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &secure));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &deviceProductInfo));
- RETURN_IF_ERROR(FlattenableHelpers::unflatten(&buffer, &size, &installOrientation));
- return OK;
-}
-
-} // namespace android::ui
diff --git a/libs/ui/include/ui/DeviceProductInfo.h b/libs/ui/include/ui/DeviceProductInfo.h
index 807a5d9..879e46f 100644
--- a/libs/ui/include/ui/DeviceProductInfo.h
+++ b/libs/ui/include/ui/DeviceProductInfo.h
@@ -24,8 +24,6 @@
#include <variant>
#include <vector>
-#include <utils/Flattenable.h>
-
namespace android {
// NUL-terminated plug and play ID.
@@ -34,7 +32,7 @@
// Product-specific information about the display or the directly connected device on the
// display chain. For example, if the display is transitively connected, this field may contain
// product information about the intermediate device.
-struct DeviceProductInfo : LightFlattenable<DeviceProductInfo> {
+struct DeviceProductInfo {
struct ModelYear {
uint32_t year;
};
@@ -64,11 +62,6 @@
// For example, for HDMI connected device this will be the physical address.
std::vector<uint8_t> relativeAddress;
- bool isFixedSize() const { return false; }
- size_t getFlattenedSize() const;
- status_t flatten(void* buffer, size_t size) const;
- status_t unflatten(void const* buffer, size_t size);
-
void dump(std::string& result) const;
};
diff --git a/libs/ui/include/ui/DisplayMode.h b/libs/ui/include/ui/DisplayMode.h
index 56f68e7..a2791a6 100644
--- a/libs/ui/include/ui/DisplayMode.h
+++ b/libs/ui/include/ui/DisplayMode.h
@@ -29,7 +29,7 @@
using DisplayModeId = int32_t;
// Mode supported by physical display.
-struct DisplayMode : LightFlattenable<DisplayMode> {
+struct DisplayMode {
DisplayModeId id;
ui::Size resolution;
float xDpi = 0;
@@ -40,11 +40,6 @@
nsecs_t sfVsyncOffset = 0;
nsecs_t presentationDeadline = 0;
int32_t group = -1;
-
- bool isFixedSize() const { return false; }
- size_t getFlattenedSize() const;
- status_t flatten(void* buffer, size_t size) const;
- status_t unflatten(const void* buffer, size_t size);
};
} // namespace android::ui
diff --git a/libs/ui/include/ui/DynamicDisplayInfo.h b/libs/ui/include/ui/DynamicDisplayInfo.h
index ce75a65..8c9fe4c 100644
--- a/libs/ui/include/ui/DynamicDisplayInfo.h
+++ b/libs/ui/include/ui/DynamicDisplayInfo.h
@@ -24,12 +24,11 @@
#include <ui/GraphicTypes.h>
#include <ui/HdrCapabilities.h>
-#include <utils/Flattenable.h>
namespace android::ui {
// Information about a physical display which may change on hotplug reconnect.
-struct DynamicDisplayInfo : LightFlattenable<DynamicDisplayInfo> {
+struct DynamicDisplayInfo {
std::vector<ui::DisplayMode> supportedDisplayModes;
// This struct is going to be serialized over binder, so
@@ -53,11 +52,6 @@
ui::DisplayModeId preferredBootDisplayMode;
std::optional<ui::DisplayMode> getActiveDisplayMode() const;
-
- bool isFixedSize() const { return false; }
- size_t getFlattenedSize() const;
- status_t flatten(void* buffer, size_t size) const;
- status_t unflatten(const void* buffer, size_t size);
};
} // namespace android::ui
diff --git a/libs/ui/include/ui/HdrCapabilities.h b/libs/ui/include/ui/HdrCapabilities.h
index 813adde..ae54223 100644
--- a/libs/ui/include/ui/HdrCapabilities.h
+++ b/libs/ui/include/ui/HdrCapabilities.h
@@ -22,12 +22,10 @@
#include <vector>
#include <ui/GraphicTypes.h>
-#include <utils/Flattenable.h>
namespace android {
-class HdrCapabilities : public LightFlattenable<HdrCapabilities>
-{
+class HdrCapabilities {
public:
HdrCapabilities(const std::vector<ui::Hdr>& types,
float maxLuminance, float maxAverageLuminance, float minLuminance)
@@ -49,12 +47,6 @@
float getDesiredMaxAverageLuminance() const { return mMaxAverageLuminance; }
float getDesiredMinLuminance() const { return mMinLuminance; }
- // Flattenable protocol
- bool isFixedSize() const { return false; }
- size_t getFlattenedSize() const;
- status_t flatten(void* buffer, size_t size) const;
- status_t unflatten(void const* buffer, size_t size);
-
private:
std::vector<ui::Hdr> mSupportedHdrTypes;
float mMaxLuminance;
diff --git a/libs/ui/include/ui/StaticDisplayInfo.h b/libs/ui/include/ui/StaticDisplayInfo.h
index cc7c869..566e417 100644
--- a/libs/ui/include/ui/StaticDisplayInfo.h
+++ b/libs/ui/include/ui/StaticDisplayInfo.h
@@ -20,24 +20,18 @@
#include <ui/DeviceProductInfo.h>
#include <ui/Rotation.h>
-#include <utils/Flattenable.h>
namespace android::ui {
enum class DisplayConnectionType { Internal, External };
// Immutable information about physical display.
-struct StaticDisplayInfo : LightFlattenable<StaticDisplayInfo> {
+struct StaticDisplayInfo {
DisplayConnectionType connectionType = DisplayConnectionType::Internal;
float density = 0.f;
bool secure = false;
std::optional<DeviceProductInfo> deviceProductInfo;
Rotation installOrientation = ROTATION_0;
-
- bool isFixedSize() const { return false; }
- size_t getFlattenedSize() const;
- status_t flatten(void* buffer, size_t size) const;
- status_t unflatten(void const* buffer, size_t size);
};
} // namespace android::ui
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 76fd7f0..dd14bcf 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -207,7 +207,8 @@
ATRACE_CALL();
const nsecs_t openTime = systemTime();
- if (should_unload_system_driver(cnx)) {
+ if (!android::GraphicsEnv::getInstance().angleIsSystemDriver() &&
+ should_unload_system_driver(cnx)) {
unload_system_driver(cnx);
}
@@ -216,8 +217,13 @@
return cnx->dso;
}
- // Firstly, try to load ANGLE driver.
- driver_t* hnd = attempt_to_load_angle(cnx);
+ // Firstly, try to load ANGLE driver, unless we know that we shouldn't.
+ bool shouldForceLegacyDriver = android::GraphicsEnv::getInstance().shouldForceLegacyDriver();
+ driver_t* hnd = nullptr;
+ if (!shouldForceLegacyDriver) {
+ hnd = attempt_to_load_angle(cnx);
+ }
+
if (!hnd) {
// Secondly, try to load from driver apk.
hnd = attempt_to_load_updated_driver(cnx);
@@ -230,21 +236,29 @@
LOG_ALWAYS_FATAL("couldn't find an OpenGL ES implementation from %s",
android::GraphicsEnv::getInstance().getDriverPath().c_str());
}
- // Finally, try to load system driver, start by searching for the library name appended by
- // the system properties of the GLES userspace driver in both locations.
- // i.e.:
- // libGLES_${prop}.so, or:
- // libEGL_${prop}.so, libGLESv1_CM_${prop}.so, libGLESv2_${prop}.so
- for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
- auto prop = base::GetProperty(key, "");
- if (prop.empty()) {
- continue;
- }
- hnd = attempt_to_load_system_driver(cnx, prop.c_str(), true);
- if (hnd) {
- break;
- } else if (strcmp(key, DRIVER_SUFFIX_PROPERTY) == 0) {
- failToLoadFromDriverSuffixProperty = true;
+ // Finally, try to load system driver. If ANGLE is the system driver
+ // (i.e. we are forcing the legacy system driver instead of ANGLE), use
+ // the driver suffix that was passed down from above.
+ if (shouldForceLegacyDriver) {
+ std::string suffix = android::GraphicsEnv::getInstance().getLegacySuffix();
+ hnd = attempt_to_load_system_driver(cnx, suffix.c_str(), true);
+ } else {
+ // Start by searching for the library name appended by the system
+ // properties of the GLES userspace driver in both locations.
+ // i.e.:
+ // libGLES_${prop}.so, or:
+ // libEGL_${prop}.so, libGLESv1_CM_${prop}.so, libGLESv2_${prop}.so
+ for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
+ auto prop = base::GetProperty(key, "");
+ if (prop.empty()) {
+ continue;
+ }
+ hnd = attempt_to_load_system_driver(cnx, prop.c_str(), true);
+ if (hnd) {
+ break;
+ } else if (strcmp(key, DRIVER_SUFFIX_PROPERTY) == 0) {
+ failToLoadFromDriverSuffixProperty = true;
+ }
}
}
}
diff --git a/services/inputflinger/InputClassifier.cpp b/services/inputflinger/InputClassifier.cpp
index 8ce2f35..21695c3 100644
--- a/services/inputflinger/InputClassifier.cpp
+++ b/services/inputflinger/InputClassifier.cpp
@@ -331,20 +331,9 @@
enqueueEvent(std::make_unique<NotifyDeviceResetArgs>(args));
}
-const char* MotionClassifier::getServiceStatus() REQUIRES(mLock) {
- if (!mService) {
- return "null";
- }
-
- if (AIBinder_ping(mService->asBinder().get()) == STATUS_OK) {
- return "running";
- }
- return "not responding";
-}
-
void MotionClassifier::dump(std::string& dump) {
std::scoped_lock lock(mLock);
- dump += StringPrintf(INDENT2 "mService status: %s\n", getServiceStatus());
+ dump += StringPrintf(INDENT2 "mService connected: %s\n", mService ? "true" : "false");
dump += StringPrintf(INDENT2 "mEvents: %zu element(s) (max=%zu)\n",
mEvents.size(), MAX_EVENTS);
dump += INDENT2 "mClassifications, mLastDownTimes:\n";
@@ -365,6 +354,18 @@
}
}
+void MotionClassifier::monitor() {
+ std::scoped_lock lock(mLock);
+ if (mService) {
+ // Ping the HAL service to ensure it is alive and not blocked.
+ const binder_status_t status = AIBinder_ping(mService->asBinder().get());
+ if (status != STATUS_OK) {
+ ALOGW("IInputProcessor HAL is not responding; binder ping result: %s",
+ AStatus_getDescription(AStatus_fromStatus(status)));
+ }
+ }
+}
+
// --- InputClassifier ---
InputClassifier::InputClassifier(InputListenerInterface& listener) : mQueuedListener(listener) {}
@@ -504,6 +505,7 @@
void InputClassifier::monitor() {
std::scoped_lock lock(mLock);
+ if (mMotionClassifier) mMotionClassifier->monitor();
}
InputClassifier::~InputClassifier() {
diff --git a/services/inputflinger/InputClassifier.h b/services/inputflinger/InputClassifier.h
index 56cf760..9b31a3c 100644
--- a/services/inputflinger/InputClassifier.h
+++ b/services/inputflinger/InputClassifier.h
@@ -78,9 +78,14 @@
virtual void reset(const NotifyDeviceResetArgs& args) = 0;
/**
- * Dump the state of the motion classifier
+ * Dump the state of the motion classifier.
*/
virtual void dump(std::string& dump) = 0;
+
+ /**
+ * Called by the heartbeat to ensure the HAL is still processing normally.
+ */
+ virtual void monitor() = 0;
};
/**
@@ -96,7 +101,7 @@
*/
virtual void dump(std::string& dump) = 0;
- /* Called by the heatbeat to ensures that the classifier has not deadlocked. */
+ /** Called by the heartbeat to ensure that the classifier has not deadlocked. */
virtual void monitor() = 0;
InputClassifierInterface() { }
@@ -155,13 +160,14 @@
virtual void reset(const NotifyDeviceResetArgs& args) override;
virtual void dump(std::string& dump) override;
+ virtual void monitor() override;
private:
friend class MotionClassifierTest; // to create MotionClassifier with a test HAL implementation
explicit MotionClassifier(
std::shared_ptr<aidl::android::hardware::input::processor::IInputProcessor> service);
- // The events that need to be sent to the HAL.
+ /** The events that need to be sent to the HAL. */
BlockingQueue<ClassifierEvent> mEvents;
/**
* Add an event to the queue mEvents.
diff --git a/services/inputflinger/TEST_MAPPING b/services/inputflinger/TEST_MAPPING
index b4b617e..f673a28 100644
--- a/services/inputflinger/TEST_MAPPING
+++ b/services/inputflinger/TEST_MAPPING
@@ -45,6 +45,101 @@
]
},
{
+ "name": "CtsWidgetTestCases",
+ "options": [
+ {
+ "include-filter": "android.widget.cts.NumberPickerTest"
+ }
+ ]
+ },
+ {
+ "name": "FrameworksCoreTests",
+ "options": [
+ {
+ "include-filter": "android.view.VerifiedKeyEventTest",
+ "include-filter": "android.view.VerifiedMotionEventTest"
+ }
+ ]
+ },
+ {
+ "name": "FrameworksServicesTests",
+ "options": [
+ {
+ "include-filter": "com.android.server.input"
+ }
+ ]
+ },
+ {
+ "name": "CtsSecurityTestCases",
+ "options": [
+ {
+ "include-filter": "android.security.cts.MotionEventTest"
+ }
+ ]
+ },
+ {
+ "name": "CtsSecurityBulletinHostTestCases",
+ "options": [
+ {
+ "include-filter": "android.security.cts.Poc19_03#testPocBug_115739809"
+ }
+ ]
+ }
+ ],
+ "hwasan-postsubmit": [
+ {
+ "name": "CtsWindowManagerDeviceTestCases",
+ "options": [
+ {
+ "include-filter": "android.server.wm.WindowInputTests"
+ }
+ ]
+ },
+ {
+ "name": "libinput_tests"
+ },
+ {
+ "name": "inputflinger_tests"
+ },
+ {
+ "name": "libpalmrejection_test"
+ },
+ {
+ "name": "InputTests"
+ },
+ {
+ "name": "libinputservice_test"
+ },
+ {
+ "name": "CtsHardwareTestCases",
+ "options": [
+ {
+ "include-filter": "android.hardware.input.cts.tests"
+ }
+ ]
+ },
+ {
+ "name": "CtsInputTestCases"
+ },
+ {
+ "name": "CtsViewTestCases",
+ "options": [
+ {
+ "include-filter": "android.view.cts.MotionEventTest",
+ "include-filter": "android.view.cts.PointerCaptureTest",
+ "include-filter": "android.view.cts.VerifyInputEventTest"
+ }
+ ]
+ },
+ {
+ "name": "CtsWidgetTestCases",
+ "options": [
+ {
+ "include-filter": "android.widget.cts.NumberPickerTest"
+ }
+ ]
+ },
+ {
"name": "FrameworksCoreTests",
"options": [
{
diff --git a/services/inputflinger/UnwantedInteractionBlocker.cpp b/services/inputflinger/UnwantedInteractionBlocker.cpp
index f57ff33..3ee60a9 100644
--- a/services/inputflinger/UnwantedInteractionBlocker.cpp
+++ b/services/inputflinger/UnwantedInteractionBlocker.cpp
@@ -512,6 +512,15 @@
return out;
}
+class AndroidPalmRejectionModel : public ::ui::OneDeviceTrainNeuralStylusPalmDetectionFilterModel {
+public:
+ AndroidPalmRejectionModel()
+ : ::ui::OneDeviceTrainNeuralStylusPalmDetectionFilterModel(/*default version*/ "",
+ std::vector<float>()) {
+ config_.resample_touch = true;
+ }
+};
+
PalmRejector::PalmRejector(const AndroidPalmFilterDeviceInfo& info,
std::unique_ptr<::ui::PalmDetectionFilter> filter)
: mSharedPalmState(std::make_unique<::ui::SharedPalmDetectionFilterState>()),
@@ -523,8 +532,7 @@
return;
}
std::unique_ptr<::ui::NeuralStylusPalmDetectionFilterModel> model =
- std::make_unique<::ui::OneDeviceTrainNeuralStylusPalmDetectionFilterModel>(
- std::vector<float>());
+ std::make_unique<AndroidPalmRejectionModel>();
mPalmDetectionFilter =
std::make_unique<::ui::NeuralStylusPalmDetectionFilter>(mDeviceInfo, std::move(model),
mSharedPalmState.get());
diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
index a2e60c4..c9ea068 100644
--- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
+++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
@@ -82,8 +82,6 @@
void notifyVibratorState(int32_t deviceId, bool isOn) override {}
- void notifyUntrustedTouch(const std::string& obscuringPackage) override {}
-
void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
*outConfig = mConfig;
}
@@ -114,6 +112,8 @@
void notifyDropWindow(const sp<IBinder>&, float x, float y) override {}
+ bool isPerDisplayTouchModeEnabled() override { return false; }
+
InputDispatcherConfiguration mConfig;
};
diff --git a/services/inputflinger/dispatcher/CancelationOptions.h b/services/inputflinger/dispatcher/CancelationOptions.h
index 99e2108..fec5f83 100644
--- a/services/inputflinger/dispatcher/CancelationOptions.h
+++ b/services/inputflinger/dispatcher/CancelationOptions.h
@@ -17,9 +17,11 @@
#ifndef _UI_INPUT_INPUTDISPATCHER_CANCELLATIONOPTIONS_H
#define _UI_INPUT_INPUTDISPATCHER_CANCELLATIONOPTIONS_H
+#include <utils/BitSet.h>
#include <optional>
-namespace android::inputdispatcher {
+namespace android {
+namespace inputdispatcher {
/* Specifies which events are to be canceled and why. */
struct CancelationOptions {
@@ -45,9 +47,13 @@
// The specific display id of events to cancel, or nullopt to cancel events on any display.
std::optional<int32_t> displayId = std::nullopt;
+ // The specific pointers to cancel, or nullopt to cancel all pointer events
+ std::optional<BitSet32> pointerIds = std::nullopt;
+
CancelationOptions(Mode mode, const char* reason) : mode(mode), reason(reason) {}
};
-} // namespace android::inputdispatcher
+} // namespace inputdispatcher
+} // namespace android
#endif // _UI_INPUT_INPUTDISPATCHER_CANCELLATIONOPTIONS_H
diff --git a/services/inputflinger/dispatcher/FocusResolver.cpp b/services/inputflinger/dispatcher/FocusResolver.cpp
index a02b3e8..4da846b 100644
--- a/services/inputflinger/dispatcher/FocusResolver.cpp
+++ b/services/inputflinger/dispatcher/FocusResolver.cpp
@@ -13,24 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-#define LOG_TAG "FocusResolver"
+#define LOG_TAG "InputDispatcher"
#define ATRACE_TAG ATRACE_TAG_INPUT
#define INDENT " "
#define INDENT2 " "
-// Log debug messages about input focus tracking.
-static constexpr bool DEBUG_FOCUS = false;
-
#include <inttypes.h>
#include <android-base/stringprintf.h>
#include <binder/Binder.h>
#include <ftl/enum.h>
#include <gui/WindowInfo.h>
-#include <log/log.h>
+#include "DebugConfig.h"
#include "FocusResolver.h"
using android::gui::FocusRequest;
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 5e9427a..bd55216 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -56,7 +56,6 @@
using android::gui::TouchOcclusionMode;
using android::gui::WindowInfo;
using android::gui::WindowInfoHandle;
-using android::os::BlockUntrustedTouchesMode;
using android::os::IInputConstants;
using android::os::InputEventInjectionResult;
using android::os::InputEventInjectionSync;
@@ -554,7 +553,8 @@
mWindowTokenWithPointerCapture(nullptr),
mStaleEventTimeout(staleEventTimeout),
mLatencyAggregator(),
- mLatencyTracker(&mLatencyAggregator) {
+ mLatencyTracker(&mLatencyAggregator),
+ kPerDisplayTouchModeEnabled(mPolicy->isPerDisplayTouchModeEnabled()) {
mLooper = new Looper(false);
mReporter = createInputReporter();
@@ -1658,6 +1658,13 @@
InputEventInjectionResult injectionResult;
if (isPointerEvent) {
// Pointer event. (eg. touchscreen)
+
+ if (mDragState &&
+ (entry->action & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_POINTER_DOWN) {
+ // If drag and drop ongoing and pointer down occur: pilfer drag window pointers
+ pilferPointersLocked(mDragState->dragWindow->getToken());
+ }
+
injectionResult =
findTouchedWindowTargetsLocked(currentTime, *entry, inputTargets, nextWakeupTime,
&conflictingPointerActions);
@@ -1866,6 +1873,17 @@
return false;
}
+static std::optional<nsecs_t> getDownTime(const EventEntry& eventEntry) {
+ if (eventEntry.type == EventEntry::Type::KEY) {
+ const KeyEntry& keyEntry = static_cast<const KeyEntry&>(eventEntry);
+ return keyEntry.downTime;
+ } else if (eventEntry.type == EventEntry::Type::MOTION) {
+ const MotionEntry& motionEntry = static_cast<const MotionEntry&>(eventEntry);
+ return motionEntry.downTime;
+ }
+ return std::nullopt;
+}
+
InputEventInjectionResult InputDispatcher::findFocusedWindowTargetsLocked(
nsecs_t currentTime, const EventEntry& entry, std::vector<InputTarget>& inputTargets,
nsecs_t* nextWakeupTime) {
@@ -1955,7 +1973,7 @@
// Success! Output targets.
addWindowTargetLocked(focusedWindowHandle,
InputTarget::FLAG_FOREGROUND | InputTarget::FLAG_DISPATCH_AS_IS,
- BitSet32(0), inputTargets);
+ BitSet32(0), getDownTime(entry), inputTargets);
// Done.
return InputEventInjectionResult::SUCCEEDED;
@@ -2152,23 +2170,17 @@
}
// Drop events that can't be trusted due to occlusion
- if (mBlockUntrustedTouchesMode != BlockUntrustedTouchesMode::DISABLED) {
- TouchOcclusionInfo occlusionInfo =
- computeTouchOcclusionInfoLocked(windowHandle, x, y);
- if (!isTouchTrustedLocked(occlusionInfo)) {
- if (DEBUG_TOUCH_OCCLUSION) {
- ALOGD("Stack of obscuring windows during untrusted touch (%d, %d):", x, y);
- for (const auto& log : occlusionInfo.debugInfo) {
- ALOGD("%s", log.c_str());
- }
- }
- sendUntrustedTouchCommandLocked(occlusionInfo.obscuringPackage);
- if (mBlockUntrustedTouchesMode == BlockUntrustedTouchesMode::BLOCK) {
- ALOGW("Dropping untrusted touch event due to %s/%d",
- occlusionInfo.obscuringPackage.c_str(), occlusionInfo.obscuringUid);
- continue;
+ TouchOcclusionInfo occlusionInfo = computeTouchOcclusionInfoLocked(windowHandle, x, y);
+ if (!isTouchTrustedLocked(occlusionInfo)) {
+ if (DEBUG_TOUCH_OCCLUSION) {
+ ALOGD("Stack of obscuring windows during untrusted touch (%d, %d):", x, y);
+ for (const auto& log : occlusionInfo.debugInfo) {
+ ALOGD("%s", log.c_str());
}
}
+ ALOGW("Dropping untrusted touch event due to %s/%d",
+ occlusionInfo.obscuringPackage.c_str(), occlusionInfo.obscuringUid);
+ continue;
}
// Drop touch events if requested by input feature
@@ -2200,8 +2212,18 @@
pointerIds.markBit(pointerId);
}
- tempTouchState.addOrUpdateWindow(windowHandle, targetFlags, pointerIds);
+ tempTouchState.addOrUpdateWindow(windowHandle, targetFlags, pointerIds,
+ entry.eventTime);
}
+
+ // If any existing window is pilfering pointers from newly added window, remove it
+ BitSet32 canceledPointers = BitSet32(0);
+ for (const TouchedWindow& window : tempTouchState.windows) {
+ if (window.isPilferingPointers) {
+ canceledPointers |= window.pointerIds;
+ }
+ }
+ tempTouchState.cancelPointersForNonPilferingWindows(canceledPointers);
} else {
/* Case 2: Pointer move, up, cancel or non-splittable pointer down. */
@@ -2278,7 +2300,8 @@
if (isSplit) {
pointerIds.markBit(entry.pointerProperties[0].id);
}
- tempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds);
+ tempTouchState.addOrUpdateWindow(newTouchedWindowHandle, targetFlags, pointerIds,
+ entry.eventTime);
}
}
}
@@ -2395,7 +2418,7 @@
InputTarget::
FLAG_WINDOW_IS_PARTIALLY_OBSCURED |
InputTarget::FLAG_DISPATCH_AS_IS,
- BitSet32(0));
+ BitSet32(0), entry.eventTime);
}
}
}
@@ -2406,7 +2429,8 @@
for (const TouchedWindow& touchedWindow : tempTouchState.windows) {
addWindowTargetLocked(touchedWindow.windowHandle, touchedWindow.targetFlags,
- touchedWindow.pointerIds, inputTargets);
+ touchedWindow.pointerIds, touchedWindow.firstDownTimeInTarget,
+ inputTargets);
}
// Drop the outside or hover touch windows since we will not care about them
@@ -2591,6 +2615,7 @@
void InputDispatcher::addWindowTargetLocked(const sp<WindowInfoHandle>& windowHandle,
int32_t targetFlags, BitSet32 pointerIds,
+ std::optional<nsecs_t> firstDownTimeInTarget,
std::vector<InputTarget>& inputTargets) {
std::vector<InputTarget>::iterator it =
std::find_if(inputTargets.begin(), inputTargets.end(),
@@ -2612,6 +2637,7 @@
inputTarget.inputChannel = inputChannel;
inputTarget.flags = targetFlags;
inputTarget.globalScaleFactor = windowInfo->globalScaleFactor;
+ inputTarget.firstDownTimeInTarget = firstDownTimeInTarget;
const auto& displayInfoIt = mDisplayInfos.find(windowInfo->displayId);
if (displayInfoIt != mDisplayInfos.end()) {
inputTarget.displayTransform = displayInfoIt->second.transform;
@@ -2637,6 +2663,8 @@
InputTarget target;
target.inputChannel = monitor.inputChannel;
target.flags = InputTarget::FLAG_DISPATCH_AS_IS;
+ // target.firstDownTimeInTarget is not set for global monitors. It is only required in split
+ // touch and global monitoring works as intended even without setting firstDownTimeInTarget
if (const auto& it = mDisplayInfos.find(displayId); it != mDisplayInfos.end()) {
target.displayTransform = it->second.transform;
}
@@ -2921,8 +2949,12 @@
const MotionEntry& originalMotionEntry = static_cast<const MotionEntry&>(*eventEntry);
if (inputTarget.pointerIds.count() != originalMotionEntry.pointerCount) {
+ LOG_ALWAYS_FATAL_IF(!inputTarget.firstDownTimeInTarget.has_value(),
+ "Splitting motion events requires a down time to be set for the "
+ "target");
std::unique_ptr<MotionEntry> splitMotionEntry =
- splitMotionEvent(originalMotionEntry, inputTarget.pointerIds);
+ splitMotionEvent(originalMotionEntry, inputTarget.pointerIds,
+ inputTarget.firstDownTimeInTarget.value());
if (!splitMotionEntry) {
return; // split event was dropped
}
@@ -3678,15 +3710,13 @@
}
void InputDispatcher::synthesizePointerDownEventsForConnectionLocked(
- const sp<Connection>& connection) {
+ const nsecs_t downTime, const sp<Connection>& connection) {
if (connection->status == Connection::Status::BROKEN) {
return;
}
- nsecs_t currentTime = now();
-
std::vector<std::unique_ptr<EventEntry>> downEvents =
- connection->inputState.synthesizePointerDownEvents(currentTime);
+ connection->inputState.synthesizePointerDownEvents(downTime);
if (downEvents.empty()) {
return;
@@ -3734,11 +3764,11 @@
InputTarget::FLAG_DISPATCH_AS_IS);
}
- startDispatchCycleLocked(currentTime, connection);
+ startDispatchCycleLocked(downTime, connection);
}
std::unique_ptr<MotionEntry> InputDispatcher::splitMotionEvent(
- const MotionEntry& originalMotionEntry, BitSet32 pointerIds) {
+ const MotionEntry& originalMotionEntry, BitSet32 pointerIds, nsecs_t splitDownTime) {
ALOG_ASSERT(pointerIds.value != 0);
uint32_t splitPointerIndexMap[MAX_POINTERS];
@@ -3806,6 +3836,13 @@
}
}
+ if (action == AMOTION_EVENT_ACTION_DOWN) {
+ LOG_ALWAYS_FATAL_IF(splitDownTime != originalMotionEntry.eventTime,
+ "Split motion event has mismatching downTime and eventTime for "
+ "ACTION_DOWN, motionEntry=%s, splitDownTime=%" PRId64 "ms",
+ originalMotionEntry.getDescription().c_str(), ns2ms(splitDownTime));
+ }
+
int32_t newId = mIdGenerator.nextId();
if (ATRACE_ENABLED()) {
std::string message = StringPrintf("Split MotionEvent(id=0x%" PRIx32
@@ -3826,9 +3863,9 @@
originalMotionEntry.xPrecision,
originalMotionEntry.yPrecision,
originalMotionEntry.xCursorPosition,
- originalMotionEntry.yCursorPosition,
- originalMotionEntry.downTime, splitPointerCount,
- splitPointerProperties, splitPointerCoords);
+ originalMotionEntry.yCursorPosition, splitDownTime,
+ splitPointerCount, splitPointerProperties,
+ splitPointerCoords);
if (originalMotionEntry.injectionState) {
splitMotionEntry->injectionState = originalMotionEntry.injectionState;
@@ -4951,8 +4988,8 @@
mLooper->wake();
}
-bool InputDispatcher::setInTouchMode(bool inTouchMode, int32_t pid, int32_t uid,
- bool hasPermission) {
+bool InputDispatcher::setInTouchMode(bool inTouchMode, int32_t pid, int32_t uid, bool hasPermission,
+ int32_t displayId) {
bool needWake = false;
{
std::scoped_lock lock(mLock);
@@ -4961,8 +4998,9 @@
}
if (DEBUG_TOUCH_MODE) {
ALOGD("Request to change touch mode from %s to %s (calling pid=%d, uid=%d, "
- "hasPermission=%s)",
- toString(mInTouchMode), toString(inTouchMode), pid, uid, toString(hasPermission));
+ "hasPermission=%s, target displayId=%d, perDisplayTouchModeEnabled=%s)",
+ toString(mInTouchMode), toString(inTouchMode), pid, uid, toString(hasPermission),
+ displayId, toString(kPerDisplayTouchModeEnabled));
}
if (!hasPermission) {
if (!focusedWindowIsOwnedByLocked(pid, uid) &&
@@ -4974,7 +5012,7 @@
}
}
- // TODO(b/198499018): Store touch mode per display.
+ // TODO(b/198499018): Store touch mode per display (kPerDisplayTouchModeEnabled)
mInTouchMode = inTouchMode;
auto entry = std::make_unique<TouchModeEntry>(mIdGenerator.nextId(), now(), inTouchMode);
@@ -5015,11 +5053,6 @@
mMaximumObscuringOpacityForTouch = opacity;
}
-void InputDispatcher::setBlockUntrustedTouchesMode(BlockUntrustedTouchesMode mode) {
- std::scoped_lock lock(mLock);
- mBlockUntrustedTouchesMode = mode;
-}
-
std::pair<TouchState*, TouchedWindow*> InputDispatcher::findTouchStateAndWindowLocked(
const sp<IBinder>& token) {
for (auto& [displayId, state] : mTouchStatesByDisplay) {
@@ -5070,12 +5103,13 @@
state->removeWindowByToken(fromToken);
// Add new window.
+ nsecs_t downTimeInTarget = now();
int32_t newTargetFlags =
oldTargetFlags & (InputTarget::FLAG_SPLIT | InputTarget::FLAG_DISPATCH_AS_IS);
if (canReceiveForegroundTouches(*toWindowHandle->getInfo())) {
newTargetFlags |= InputTarget::FLAG_FOREGROUND;
}
- state->addOrUpdateWindow(toWindowHandle, newTargetFlags, pointerIds);
+ state->addOrUpdateWindow(toWindowHandle, newTargetFlags, pointerIds, downTimeInTarget);
// Store the dragging window.
if (isDragDrop) {
@@ -5099,7 +5133,7 @@
options(CancelationOptions::CANCEL_POINTER_EVENTS,
"transferring touch focus from this window to another window");
synthesizeCancelationEventsForConnectionLocked(fromConnection, options);
- synthesizePointerDownEventsForConnectionLocked(toConnection);
+ synthesizePointerDownEventsForConnectionLocked(downTimeInTarget, toConnection);
}
if (DEBUG_FOCUS) {
@@ -5249,10 +5283,12 @@
dump += INDENT3 "Windows:\n";
for (size_t i = 0; i < state.windows.size(); i++) {
const TouchedWindow& touchedWindow = state.windows[i];
- dump += StringPrintf(INDENT4
- "%zu: name='%s', pointerIds=0x%0x, targetFlags=0x%x\n",
+ dump += StringPrintf(INDENT4 "%zu: name='%s', pointerIds=0x%0x, "
+ "targetFlags=0x%x, firstDownTimeInTarget=%" PRId64
+ "ms\n",
i, touchedWindow.windowHandle->getName().c_str(),
- touchedWindow.pointerIds.value, touchedWindow.targetFlags);
+ touchedWindow.pointerIds.value, touchedWindow.targetFlags,
+ ns2ms(touchedWindow.firstDownTimeInTarget.value_or(0)));
}
} else {
dump += INDENT3 "Windows: <none>\n";
@@ -5578,7 +5614,10 @@
status_t InputDispatcher::pilferPointers(const sp<IBinder>& token) {
std::scoped_lock _l(mLock);
+ return pilferPointersLocked(token);
+}
+status_t InputDispatcher::pilferPointersLocked(const sp<IBinder>& token) {
const std::shared_ptr<InputChannel> requestingChannel = getInputChannelLocked(token);
if (!requestingChannel) {
ALOGW("Attempted to pilfer pointers from an un-registered channel or invalid token");
@@ -5593,16 +5632,20 @@
}
TouchState& state = *statePtr;
-
+ TouchedWindow& window = *windowPtr;
// Send cancel events to all the input channels we're stealing from.
CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS,
"input channel stole pointer stream");
options.deviceId = state.deviceId;
options.displayId = state.displayId;
+ if (state.split) {
+ // If split pointers then selectively cancel pointers otherwise cancel all pointers
+ options.pointerIds = window.pointerIds;
+ }
std::string canceledWindows;
- for (const TouchedWindow& window : state.windows) {
+ for (const TouchedWindow& w : state.windows) {
const std::shared_ptr<InputChannel> channel =
- getInputChannelLocked(window.windowHandle->getToken());
+ getInputChannelLocked(w.windowHandle->getToken());
if (channel != nullptr && channel->getConnectionToken() != token) {
synthesizeCancelationEventsForInputChannelLocked(channel, options);
canceledWindows += canceledWindows.empty() ? "[" : ", ";
@@ -5614,8 +5657,14 @@
canceledWindows.c_str());
// Prevent the gesture from being sent to any other windows.
- state.filterWindowsExcept(token);
- state.preventNewTargets = true;
+ // This only blocks relevant pointers to be sent to other windows
+ window.isPilferingPointers = true;
+
+ if (state.split) {
+ state.cancelPointersForWindowsExcept(window.pointerIds, token);
+ } else {
+ state.filterWindowsExcept(token);
+ }
return OK;
}
@@ -5787,14 +5836,6 @@
postCommandLocked(std::move(command));
}
-void InputDispatcher::sendUntrustedTouchCommandLocked(const std::string& obscuringPackage) {
- auto command = [this, obscuringPackage]() REQUIRES(mLock) {
- scoped_unlock unlock(mLock);
- mPolicy->notifyUntrustedTouch(obscuringPackage);
- };
- postCommandLocked(std::move(command));
-}
-
void InputDispatcher::onAnrLocked(const sp<Connection>& connection) {
if (connection == nullptr) {
LOG_ALWAYS_FATAL("Caller must check for nullness");
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index ed89ed0..be619ae 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -119,9 +119,9 @@
void setFocusedDisplay(int32_t displayId) override;
void setInputDispatchMode(bool enabled, bool frozen) override;
void setInputFilterEnabled(bool enabled) override;
- bool setInTouchMode(bool inTouchMode, int32_t pid, int32_t uid, bool hasPermission) override;
+ bool setInTouchMode(bool inTouchMode, int32_t pid, int32_t uid, bool hasPermission,
+ int32_t displayId) override;
void setMaximumObscuringOpacityForTouch(float opacity) override;
- void setBlockUntrustedTouchesMode(android::os::BlockUntrustedTouchesMode mode) override;
bool transferTouchFocus(const sp<IBinder>& fromToken, const sp<IBinder>& toToken,
bool isDragDrop = false) override;
@@ -256,6 +256,8 @@
void removeConnectionLocked(const sp<Connection>& connection) REQUIRES(mLock);
+ status_t pilferPointersLocked(const sp<IBinder>& token) REQUIRES(mLock);
+
template <typename T>
struct StrongPointerHash {
std::size_t operator()(const sp<T>& b) const { return std::hash<T*>{}(b.get()); }
@@ -344,7 +346,6 @@
bool mInputFilterEnabled GUARDED_BY(mLock);
bool mInTouchMode GUARDED_BY(mLock);
float mMaximumObscuringOpacityForTouch GUARDED_BY(mLock);
- android::os::BlockUntrustedTouchesMode mBlockUntrustedTouchesMode GUARDED_BY(mLock);
class DispatcherWindowListener : public gui::WindowInfosListener {
public:
@@ -550,6 +551,7 @@
void addWindowTargetLocked(const sp<android::gui::WindowInfoHandle>& windowHandle,
int32_t targetFlags, BitSet32 pointerIds,
+ std::optional<nsecs_t> firstDownTimeInTarget,
std::vector<InputTarget>& inputTargets) REQUIRES(mLock);
void addGlobalMonitoringTargetsLocked(std::vector<InputTarget>& inputTargets, int32_t displayId)
REQUIRES(mLock);
@@ -621,12 +623,14 @@
const CancelationOptions& options)
REQUIRES(mLock);
- void synthesizePointerDownEventsForConnectionLocked(const sp<Connection>& connection)
+ void synthesizePointerDownEventsForConnectionLocked(const nsecs_t downTime,
+ const sp<Connection>& connection)
REQUIRES(mLock);
- // Splitting motion events across windows.
+ // Splitting motion events across windows. When splitting motion event for a target,
+ // splitDownTime refers to the time of first 'down' event on that particular target
std::unique_ptr<MotionEntry> splitMotionEvent(const MotionEntry& originalMotionEntry,
- BitSet32 pointerIds);
+ BitSet32 pointerIds, nsecs_t splitDownTime);
// Reset and drop everything the dispatcher is doing.
void resetAndDropEverythingLocked(const char* reason) REQUIRES(mLock);
@@ -652,7 +656,6 @@
void sendFocusChangedCommandLocked(const sp<IBinder>& oldToken, const sp<IBinder>& newToken)
REQUIRES(mLock);
void sendDropWindowCommandLocked(const sp<IBinder>& token, float x, float y) REQUIRES(mLock);
- void sendUntrustedTouchCommandLocked(const std::string& obscuringPackage) REQUIRES(mLock);
void onAnrLocked(const sp<Connection>& connection) REQUIRES(mLock);
void onAnrLocked(std::shared_ptr<InputApplicationHandle> application) REQUIRES(mLock);
void updateLastAnrStateLocked(const sp<android::gui::WindowInfoHandle>& window,
@@ -683,6 +686,9 @@
bool focusedWindowIsOwnedByLocked(int32_t pid, int32_t uid) REQUIRES(mLock);
bool recentWindowsAreOwnedByLocked(int32_t pid, int32_t uid) REQUIRES(mLock);
+ // Per display touch mode enabled
+ const bool kPerDisplayTouchModeEnabled;
+
sp<InputReporterInterface> mReporter;
};
diff --git a/services/inputflinger/dispatcher/InputState.cpp b/services/inputflinger/dispatcher/InputState.cpp
index f46a8bc..047c628 100644
--- a/services/inputflinger/dispatcher/InputState.cpp
+++ b/services/inputflinger/dispatcher/InputState.cpp
@@ -286,19 +286,30 @@
for (const MotionMemento& memento : mMotionMementos) {
if (shouldCancelMotion(memento, options)) {
- const int32_t action = memento.hovering ? AMOTION_EVENT_ACTION_HOVER_EXIT
- : AMOTION_EVENT_ACTION_CANCEL;
- events.push_back(
- std::make_unique<MotionEntry>(mIdGenerator.nextId(), currentTime,
- memento.deviceId, memento.source,
- memento.displayId, memento.policyFlags, action,
- 0 /*actionButton*/, memento.flags, AMETA_NONE,
- 0 /*buttonState*/, MotionClassification::NONE,
- AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
- memento.yPrecision, memento.xCursorPosition,
- memento.yCursorPosition, memento.downTime,
- memento.pointerCount, memento.pointerProperties,
- memento.pointerCoords));
+ if (options.pointerIds == std::nullopt) {
+ const int32_t action = memento.hovering ? AMOTION_EVENT_ACTION_HOVER_EXIT
+ : AMOTION_EVENT_ACTION_CANCEL;
+ events.push_back(
+ std::make_unique<MotionEntry>(mIdGenerator.nextId(), currentTime,
+ memento.deviceId, memento.source,
+ memento.displayId, memento.policyFlags,
+ action, 0 /*actionButton*/, memento.flags,
+ AMETA_NONE, 0 /*buttonState*/,
+ MotionClassification::NONE,
+ AMOTION_EVENT_EDGE_FLAG_NONE,
+ memento.xPrecision, memento.yPrecision,
+ memento.xCursorPosition,
+ memento.yCursorPosition, memento.downTime,
+ memento.pointerCount,
+ memento.pointerProperties,
+ memento.pointerCoords));
+ } else {
+ std::vector<std::unique_ptr<MotionEntry>> pointerCancelEvents =
+ synthesizeCancelationEventsForPointers(memento, options.pointerIds.value(),
+ currentTime);
+ events.insert(events.end(), std::make_move_iterator(pointerCancelEvents.begin()),
+ std::make_move_iterator(pointerCancelEvents.end()));
+ }
}
}
return events;
@@ -359,6 +370,73 @@
return events;
}
+std::vector<std::unique_ptr<MotionEntry>> InputState::synthesizeCancelationEventsForPointers(
+ const MotionMemento& memento, const BitSet32 pointerIds, nsecs_t currentTime) {
+ std::vector<std::unique_ptr<MotionEntry>> events;
+ std::vector<uint32_t> canceledPointerIndices;
+ std::vector<PointerProperties> pointerProperties(MAX_POINTERS);
+ std::vector<PointerCoords> pointerCoords(MAX_POINTERS);
+ for (uint32_t pointerIdx = 0; pointerIdx < memento.pointerCount; pointerIdx++) {
+ uint32_t pointerId = uint32_t(memento.pointerProperties[pointerIdx].id);
+ pointerProperties[pointerIdx].copyFrom(memento.pointerProperties[pointerIdx]);
+ pointerCoords[pointerIdx].copyFrom(memento.pointerCoords[pointerIdx]);
+ if (pointerIds.hasBit(pointerId)) {
+ canceledPointerIndices.push_back(pointerIdx);
+ }
+ }
+
+ if (canceledPointerIndices.size() == memento.pointerCount) {
+ const int32_t action =
+ memento.hovering ? AMOTION_EVENT_ACTION_HOVER_EXIT : AMOTION_EVENT_ACTION_CANCEL;
+ events.push_back(
+ std::make_unique<MotionEntry>(mIdGenerator.nextId(), currentTime, memento.deviceId,
+ memento.source, memento.displayId,
+ memento.policyFlags, action, 0 /*actionButton*/,
+ memento.flags, AMETA_NONE, 0 /*buttonState*/,
+ MotionClassification::NONE,
+ AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
+ memento.yPrecision, memento.xCursorPosition,
+ memento.yCursorPosition, memento.downTime,
+ memento.pointerCount, memento.pointerProperties,
+ memento.pointerCoords));
+ } else {
+ // If we aren't canceling all pointers, we need to generated ACTION_POINTER_UP with
+ // FLAG_CANCELED for each of the canceled pointers. For each event, we must remove the
+ // previously canceled pointers from PointerProperties and PointerCoords, and update
+ // pointerCount appropriately. For convenience, sort the canceled pointer indices so that we
+ // can just slide the remaining pointers to the beginning of the array when a pointer is
+ // canceled.
+ std::sort(canceledPointerIndices.begin(), canceledPointerIndices.end(),
+ std::greater<uint32_t>());
+
+ uint32_t pointerCount = memento.pointerCount;
+ for (const uint32_t pointerIdx : canceledPointerIndices) {
+ const int32_t action = pointerCount == 1 ? AMOTION_EVENT_ACTION_CANCEL
+ : AMOTION_EVENT_ACTION_POINTER_UP |
+ (pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+ events.push_back(
+ std::make_unique<MotionEntry>(mIdGenerator.nextId(), currentTime,
+ memento.deviceId, memento.source,
+ memento.displayId, memento.policyFlags, action,
+ 0 /*actionButton*/,
+ memento.flags | AMOTION_EVENT_FLAG_CANCELED,
+ AMETA_NONE, 0 /*buttonState*/,
+ MotionClassification::NONE,
+ AMOTION_EVENT_EDGE_FLAG_NONE, memento.xPrecision,
+ memento.yPrecision, memento.xCursorPosition,
+ memento.yCursorPosition, memento.downTime,
+ pointerCount, pointerProperties.data(),
+ pointerCoords.data()));
+
+ // Cleanup pointer information
+ pointerProperties.erase(pointerProperties.begin() + pointerIdx);
+ pointerCoords.erase(pointerCoords.begin() + pointerIdx);
+ pointerCount--;
+ }
+ }
+ return events;
+}
+
void InputState::clear() {
mKeyMementos.clear();
mMotionMementos.clear();
diff --git a/services/inputflinger/dispatcher/InputState.h b/services/inputflinger/dispatcher/InputState.h
index 74ae21f..77a6db1 100644
--- a/services/inputflinger/dispatcher/InputState.h
+++ b/services/inputflinger/dispatcher/InputState.h
@@ -22,7 +22,8 @@
#include <utils/Timers.h>
-namespace android::inputdispatcher {
+namespace android {
+namespace inputdispatcher {
static constexpr int32_t INVALID_POINTER_INDEX = -1;
@@ -125,8 +126,13 @@
static bool shouldCancelKey(const KeyMemento& memento, const CancelationOptions& options);
static bool shouldCancelMotion(const MotionMemento& memento, const CancelationOptions& options);
+
+ // Synthesizes pointer cancel events for a particular set of pointers.
+ std::vector<std::unique_ptr<MotionEntry>> synthesizeCancelationEventsForPointers(
+ const MotionMemento& memento, const BitSet32 pointerIds, nsecs_t currentTime);
};
-} // namespace android::inputdispatcher
+} // namespace inputdispatcher
+} // namespace android
#endif // _UI_INPUT_INPUTDISPATCHER_INPUTSTATE_H
diff --git a/services/inputflinger/dispatcher/InputTarget.h b/services/inputflinger/dispatcher/InputTarget.h
index 0725389..ac20dab 100644
--- a/services/inputflinger/dispatcher/InputTarget.h
+++ b/services/inputflinger/dispatcher/InputTarget.h
@@ -106,6 +106,9 @@
// The subset of pointer ids to include in motion events dispatched to this input target
// if FLAG_SPLIT is set.
BitSet32 pointerIds;
+ // Event time for the first motion event (ACTION_DOWN) dispatched to this input target if
+ // FLAG_SPLIT is set.
+ std::optional<nsecs_t> firstDownTimeInTarget;
// The data is stored by the pointerId. Use the bit position of pointerIds to look up
// Transform per pointerId.
ui::Transform pointerTransforms[MAX_POINTERS];
diff --git a/services/inputflinger/dispatcher/TouchState.cpp b/services/inputflinger/dispatcher/TouchState.cpp
index 61e78cc..cf0c38a 100644
--- a/services/inputflinger/dispatcher/TouchState.cpp
+++ b/services/inputflinger/dispatcher/TouchState.cpp
@@ -30,7 +30,7 @@
}
void TouchState::addOrUpdateWindow(const sp<WindowInfoHandle>& windowHandle, int32_t targetFlags,
- BitSet32 pointerIds) {
+ BitSet32 pointerIds, std::optional<nsecs_t> eventTime) {
if (targetFlags & InputTarget::FLAG_SPLIT) {
split = true;
}
@@ -42,17 +42,22 @@
if (targetFlags & InputTarget::FLAG_DISPATCH_AS_SLIPPERY_EXIT) {
touchedWindow.targetFlags &= ~InputTarget::FLAG_DISPATCH_AS_IS;
}
+ // For cases like hover enter/exit or DISPATCH_AS_OUTSIDE a touch window might not have
+ // downTime set initially. Need to update existing window when an pointer is down for
+ // the window.
touchedWindow.pointerIds.value |= pointerIds.value;
+ if (!touchedWindow.firstDownTimeInTarget.has_value()) {
+ touchedWindow.firstDownTimeInTarget = eventTime;
+ }
return;
}
}
- if (preventNewTargets) return; // Don't add new TouchedWindows.
-
TouchedWindow touchedWindow;
touchedWindow.windowHandle = windowHandle;
touchedWindow.targetFlags = targetFlags;
touchedWindow.pointerIds = pointerIds;
+ touchedWindow.firstDownTimeInTarget = eventTime;
windows.push_back(touchedWindow);
}
@@ -79,6 +84,27 @@
}
}
+void TouchState::cancelPointersForWindowsExcept(const BitSet32 pointerIds,
+ const sp<IBinder>& token) {
+ if (pointerIds.isEmpty()) return;
+ std::for_each(windows.begin(), windows.end(), [&pointerIds, &token](TouchedWindow& w) {
+ if (w.windowHandle->getToken() != token) {
+ w.pointerIds &= BitSet32(~pointerIds.value);
+ }
+ });
+ std::erase_if(windows, [](const TouchedWindow& w) { return w.pointerIds.isEmpty(); });
+}
+
+void TouchState::cancelPointersForNonPilferingWindows(const BitSet32 pointerIds) {
+ if (pointerIds.isEmpty()) return;
+ std::for_each(windows.begin(), windows.end(), [&pointerIds](TouchedWindow& w) {
+ if (!w.isPilferingPointers) {
+ w.pointerIds &= BitSet32(~pointerIds.value);
+ }
+ });
+ std::erase_if(windows, [](const TouchedWindow& w) { return w.pointerIds.isEmpty(); });
+}
+
void TouchState::filterWindowsExcept(const sp<IBinder>& token) {
std::erase_if(windows,
[&token](const TouchedWindow& w) { return w.windowHandle->getToken() != token; });
diff --git a/services/inputflinger/dispatcher/TouchState.h b/services/inputflinger/dispatcher/TouchState.h
index 9efb280..1fb51e1 100644
--- a/services/inputflinger/dispatcher/TouchState.h
+++ b/services/inputflinger/dispatcher/TouchState.h
@@ -31,7 +31,6 @@
struct TouchState {
bool down = false;
bool split = false;
- bool preventNewTargets = false;
// id of the device that is currently down, others are rejected
int32_t deviceId = -1;
@@ -48,10 +47,18 @@
void reset();
void addOrUpdateWindow(const sp<android::gui::WindowInfoHandle>& windowHandle,
- int32_t targetFlags, BitSet32 pointerIds);
+ int32_t targetFlags, BitSet32 pointerIds,
+ std::optional<nsecs_t> eventTime = std::nullopt);
void removeWindowByToken(const sp<IBinder>& token);
void filterNonAsIsTouchWindows();
void filterWindowsExcept(const sp<IBinder>& token);
+
+ // Cancel pointers for current set of windows except the window with particular binder token.
+ void cancelPointersForWindowsExcept(const BitSet32 pointerIds, const sp<IBinder>& token);
+ // Cancel pointers for current set of non-pilfering windows i.e. windows with isPilferingWindow
+ // set to false.
+ void cancelPointersForNonPilferingWindows(const BitSet32 pointerIds);
+
sp<android::gui::WindowInfoHandle> getFirstForegroundWindowHandle() const;
bool isSlippery() const;
sp<android::gui::WindowInfoHandle> getWallpaperWindow() const;
diff --git a/services/inputflinger/dispatcher/TouchedWindow.h b/services/inputflinger/dispatcher/TouchedWindow.h
index 4c31ec3..0962d0c 100644
--- a/services/inputflinger/dispatcher/TouchedWindow.h
+++ b/services/inputflinger/dispatcher/TouchedWindow.h
@@ -30,6 +30,10 @@
sp<gui::WindowInfoHandle> windowHandle;
int32_t targetFlags;
BitSet32 pointerIds; // zero unless target flag FLAG_SPLIT is set
+ bool isPilferingPointers = false;
+ // Time at which the first action down occurred on this window.
+ // NOTE: This is not initialized in case of HOVER entry/exit and DISPATCH_AS_OUTSIDE scenario.
+ std::optional<nsecs_t> firstDownTimeInTarget;
};
} // namespace inputdispatcher
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
index 67fed8b..32b3ddb 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherInterface.h
@@ -20,7 +20,7 @@
#include <InputListener.h>
#include <android-base/result.h>
#include <android/gui/FocusRequest.h>
-#include <android/os/BlockUntrustedTouchesMode.h>
+
#include <android/os/InputEventInjectionResult.h>
#include <android/os/InputEventInjectionSync.h>
#include <gui/InputApplication.h>
@@ -132,7 +132,8 @@
*
* Returns true when changing touch mode state.
*/
- virtual bool setInTouchMode(bool inTouchMode, int32_t pid, int32_t uid, bool hasPermission) = 0;
+ virtual bool setInTouchMode(bool inTouchMode, int32_t pid, int32_t uid, bool hasPermission,
+ int32_t displayId) = 0;
/**
* Sets the maximum allowed obscuring opacity by UID to propagate touches.
@@ -142,13 +143,6 @@
*/
virtual void setMaximumObscuringOpacityForTouch(float opacity) = 0;
- /**
- * Sets the mode of the block untrusted touches feature.
- *
- * TODO(b/169067926): Clean-up feature modes.
- */
- virtual void setBlockUntrustedTouchesMode(android::os::BlockUntrustedTouchesMode mode) = 0;
-
/* Transfers touch focus from one window to another window.
*
* Returns true on success. False if the window did not actually have touch focus.
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
index 575b3d7..7c299b2 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
@@ -75,9 +75,6 @@
InputDeviceSensorAccuracy accuracy) = 0;
virtual void notifyVibratorState(int32_t deviceId, bool isOn) = 0;
- /* Notifies the system that an untrusted touch occurred. */
- virtual void notifyUntrustedTouch(const std::string& obscuringPackage) = 0;
-
/* Gets the input dispatcher configuration. */
virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) = 0;
@@ -140,6 +137,9 @@
/* Notifies the policy that the drag window has moved over to another window */
virtual void notifyDropWindow(const sp<IBinder>& token, float x, float y) = 0;
+
+ /* If touch mode is enabled per display or global */
+ virtual bool isPerDisplayTouchModeEnabled() = 0;
};
} // namespace android
diff --git a/services/inputflinger/host/InputDriver.cpp b/services/inputflinger/host/InputDriver.cpp
index 2ebdbcf..97d57e4 100644
--- a/services/inputflinger/host/InputDriver.cpp
+++ b/services/inputflinger/host/InputDriver.cpp
@@ -240,19 +240,16 @@
return nullptr;
}
-input_property_t* InputDriver::inputGetDeviceProperty(input_property_map_t* map,
- const char* key) {
- String8 keyString(key);
+input_property_t* InputDriver::inputGetDeviceProperty(input_property_map_t* map, const char* key) {
if (map != nullptr) {
- if (map->propertyMap->hasProperty(keyString)) {
- auto prop = new input_property_t();
- if (!map->propertyMap->tryGetProperty(keyString, prop->value)) {
- delete prop;
- return nullptr;
- }
- prop->key = keyString;
- return prop;
+ std::string value;
+ auto prop = std::make_unique<input_property_t>();
+ if (!map->propertyMap->tryGetProperty(key, value)) {
+ return nullptr;
}
+ prop->key = key;
+ prop->value = value.c_str();
+ return prop.release();
}
return nullptr;
}
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index 41ecef3..77c9142 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -95,7 +95,7 @@
/* Determine whether physical keys exist for the given framework-domain key codes. */
virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
- size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) = 0;
+ const std::vector<int32_t>& keyCodes, uint8_t* outFlags) = 0;
/* Requests that a reconfiguration of all input devices.
* The changes flag is a bitfield that indicates what has changed and whether
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index 669d2e1..a17d2c0 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -502,7 +502,7 @@
bool EventHub::Device::isExternalDeviceLocked() {
if (configuration) {
bool value;
- if (configuration->tryGetProperty(String8("device.internal"), value)) {
+ if (configuration->tryGetProperty("device.internal", value)) {
return !value;
}
}
@@ -512,7 +512,7 @@
bool EventHub::Device::deviceHasMicLocked() {
if (configuration) {
bool value;
- if (configuration->tryGetProperty(String8("audio.mic"), value)) {
+ if (configuration->tryGetProperty("audio.mic", value)) {
return value;
}
}
@@ -687,6 +687,7 @@
LOG_ALWAYS_FATAL_IF(mEpollFd < 0, "Could not create epoll instance: %s", strerror(errno));
mINotifyFd = inotify_init1(IN_CLOEXEC);
+ LOG_ALWAYS_FATAL_IF(mINotifyFd < 0, "Could not create inotify instance: %s", strerror(errno));
std::error_code errorCode;
bool isDeviceInotifyAdded = false;
@@ -952,20 +953,20 @@
return -1;
}
-bool EventHub::markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
+bool EventHub::markSupportedKeyCodes(int32_t deviceId, const std::vector<int32_t>& keyCodes,
uint8_t* outFlags) const {
std::scoped_lock _l(mLock);
Device* device = getDeviceLocked(deviceId);
if (device != nullptr && device->keyMap.haveKeyLayout()) {
- for (size_t codeIndex = 0; codeIndex < numCodes; codeIndex++) {
+ for (size_t codeIndex = 0; codeIndex < keyCodes.size(); codeIndex++) {
std::vector<int32_t> scanCodes =
device->keyMap.keyLayoutMap->findScanCodesForKey(keyCodes[codeIndex]);
// check the possible scan codes identified by the layout map against the
// map of codes actually emitted by the driver
- for (size_t sc = 0; sc < scanCodes.size(); sc++) {
- if (device->keyBitmask.test(scanCodes[sc])) {
+ for (const int32_t scanCode : scanCodes) {
+ if (device->keyBitmask.test(scanCode)) {
outFlags[codeIndex] = 1;
break;
}
@@ -1723,7 +1724,10 @@
// before closing the devices.
if (mPendingINotify && mPendingEventIndex >= mPendingEventCount) {
mPendingINotify = false;
- readNotifyLocked();
+ const auto res = readNotifyLocked();
+ if (!res.ok()) {
+ ALOGW("Failed to read from inotify: %s", res.error().message().c_str());
+ }
deviceChanged = true;
}
@@ -2072,10 +2076,9 @@
}
// See if this is a rotary encoder type device.
- String8 deviceType = String8();
- if (device->configuration &&
- device->configuration->tryGetProperty(String8("device.type"), deviceType)) {
- if (!deviceType.compare(String8("rotaryEncoder"))) {
+ std::string deviceType;
+ if (device->configuration && device->configuration->tryGetProperty("device.type", deviceType)) {
+ if (deviceType == "rotaryEncoder") {
device->classes |= InputDeviceClass::ROTARY_ENCODER;
}
}
@@ -2413,53 +2416,56 @@
mDevices.erase(device.id);
}
-status_t EventHub::readNotifyLocked() {
- int res;
- char event_buf[512];
- int event_size;
- int event_pos = 0;
- struct inotify_event* event;
+base::Result<void> EventHub::readNotifyLocked() {
+ static constexpr auto EVENT_SIZE = static_cast<ssize_t>(sizeof(inotify_event));
+ uint8_t eventBuffer[512];
+ ssize_t sizeRead;
ALOGV("EventHub::readNotify nfd: %d\n", mINotifyFd);
- res = read(mINotifyFd, event_buf, sizeof(event_buf));
- if (res < (int)sizeof(*event)) {
- if (errno == EINTR) return 0;
- ALOGW("could not get event, %s\n", strerror(errno));
- return -1;
- }
+ do {
+ sizeRead = read(mINotifyFd, eventBuffer, sizeof(eventBuffer));
+ } while (sizeRead < 0 && errno == EINTR);
- while (res >= (int)sizeof(*event)) {
- event = (struct inotify_event*)(event_buf + event_pos);
- if (event->len) {
- if (event->wd == mDeviceInputWd) {
- std::string filename = std::string(DEVICE_INPUT_PATH) + "/" + event->name;
- if (event->mask & IN_CREATE) {
- openDeviceLocked(filename);
- } else {
- ALOGI("Removing device '%s' due to inotify event\n", filename.c_str());
- closeDeviceByPathLocked(filename);
- }
- } else if (event->wd == mDeviceWd) {
- if (isV4lTouchNode(event->name)) {
- std::string filename = std::string(DEVICE_PATH) + "/" + event->name;
- if (event->mask & IN_CREATE) {
- openVideoDeviceLocked(filename);
- } else {
- ALOGI("Removing video device '%s' due to inotify event", filename.c_str());
- closeVideoDeviceByPathLocked(filename);
- }
- } else if (strcmp(event->name, "input") == 0 && event->mask & IN_CREATE) {
- addDeviceInputInotify();
- }
- } else {
- LOG_ALWAYS_FATAL("Unexpected inotify event, wd = %i", event->wd);
- }
- }
- event_size = sizeof(*event) + event->len;
- res -= event_size;
- event_pos += event_size;
+ if (sizeRead < EVENT_SIZE) return Errorf("could not get event, %s", strerror(errno));
+
+ for (ssize_t eventPos = 0; sizeRead >= EVENT_SIZE;) {
+ const inotify_event* event;
+ event = (const inotify_event*)(eventBuffer + eventPos);
+ if (event->len == 0) continue;
+
+ handleNotifyEventLocked(*event);
+
+ const ssize_t eventSize = EVENT_SIZE + event->len;
+ sizeRead -= eventSize;
+ eventPos += eventSize;
}
- return 0;
+ return {};
+}
+
+void EventHub::handleNotifyEventLocked(const inotify_event& event) {
+ if (event.wd == mDeviceInputWd) {
+ std::string filename = std::string(DEVICE_INPUT_PATH) + "/" + event.name;
+ if (event.mask & IN_CREATE) {
+ openDeviceLocked(filename);
+ } else {
+ ALOGI("Removing device '%s' due to inotify event\n", filename.c_str());
+ closeDeviceByPathLocked(filename);
+ }
+ } else if (event.wd == mDeviceWd) {
+ if (isV4lTouchNode(event.name)) {
+ std::string filename = std::string(DEVICE_PATH) + "/" + event.name;
+ if (event.mask & IN_CREATE) {
+ openVideoDeviceLocked(filename);
+ } else {
+ ALOGI("Removing video device '%s' due to inotify event", filename.c_str());
+ closeVideoDeviceByPathLocked(filename);
+ }
+ } else if (strcmp(event.name, "input") == 0 && event.mask & IN_CREATE) {
+ addDeviceInputInotify();
+ }
+ } else {
+ LOG_ALWAYS_FATAL("Unexpected inotify event, wd = %i", event.wd);
+ }
}
status_t EventHub::scanDirLocked(const std::string& dirname) {
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index ba5083b..b67777f 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -465,12 +465,12 @@
return result;
}
-bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) {
+bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, const std::vector<int32_t>& keyCodes,
+ uint8_t* outFlags) {
bool result = false;
- for_each_mapper([&result, sourceMask, numCodes, keyCodes, outFlags](InputMapper& mapper) {
+ for_each_mapper([&result, sourceMask, keyCodes, outFlags](InputMapper& mapper) {
if (sourcesMatchMask(mapper.getSources(), sourceMask)) {
- result |= mapper.markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
+ result |= mapper.markSupportedKeyCodes(sourceMask, keyCodes, outFlags);
}
});
return result;
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 9c5a129..79901f0 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -561,28 +561,28 @@
device->updateMetaState(AKEYCODE_CAPS_LOCK);
}
-bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) {
+bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
+ const std::vector<int32_t>& keyCodes, uint8_t* outFlags) {
std::scoped_lock _l(mLock);
- memset(outFlags, 0, numCodes);
- return markSupportedKeyCodesLocked(deviceId, sourceMask, numCodes, keyCodes, outFlags);
+ memset(outFlags, 0, keyCodes.size());
+ return markSupportedKeyCodesLocked(deviceId, sourceMask, keyCodes, outFlags);
}
bool InputReader::markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask,
- size_t numCodes, const int32_t* keyCodes,
+ const std::vector<int32_t>& keyCodes,
uint8_t* outFlags) {
bool result = false;
if (deviceId >= 0) {
InputDevice* device = findInputDeviceLocked(deviceId);
if (device && !device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
- result = device->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
+ result = device->markSupportedKeyCodes(sourceMask, keyCodes, outFlags);
}
} else {
for (auto& devicePair : mDevices) {
std::shared_ptr<InputDevice>& device = devicePair.second;
if (!device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
- result |= device->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
+ result |= device->markSupportedKeyCodes(sourceMask, keyCodes, outFlags);
}
}
}
diff --git a/services/inputflinger/reader/Macros.h b/services/inputflinger/reader/Macros.h
index d837689..1bbf386 100644
--- a/services/inputflinger/reader/Macros.h
+++ b/services/inputflinger/reader/Macros.h
@@ -20,27 +20,65 @@
#define LOG_TAG "InputReader"
//#define LOG_NDEBUG 0
+#include <log/log.h>
+#include <log/log_event_list.h>
-// Log debug messages for each raw event received from the EventHub.
-static constexpr bool DEBUG_RAW_EVENTS = false;
+namespace android {
+/**
+ * Log debug messages for each raw event received from the EventHub.
+ * Enable this via "adb shell setprop log.tag.InputReaderRawEvents DEBUG" (requires restart)
+ */
+const bool DEBUG_RAW_EVENTS =
+ __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "RawEvents", ANDROID_LOG_INFO);
-// Log debug messages about virtual key processing.
-static constexpr bool DEBUG_VIRTUAL_KEYS = false;
+/**
+ * Log debug messages about virtual key processing.
+ * Enable this via "adb shell setprop log.tag.InputReaderVirtualKeys DEBUG" (requires restart)
+ */
+const bool DEBUG_VIRTUAL_KEYS =
+ __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "VirtualKeys", ANDROID_LOG_INFO);
-// Log debug messages about pointers.
-static constexpr bool DEBUG_POINTERS = false;
+/**
+ * Log debug messages about pointers.
+ * Enable this via "adb shell setprop log.tag.InputReaderPointers DEBUG" (requires restart)
+ */
+const bool DEBUG_POINTERS =
+ __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "Pointers", ANDROID_LOG_INFO);
-// Log debug messages about pointer assignment calculations.
-static constexpr bool DEBUG_POINTER_ASSIGNMENT = false;
+/**
+ * Log debug messages about pointer assignment calculations.
+ * Enable this via "adb shell setprop log.tag.InputReaderPointerAssignment DEBUG" (requires restart)
+ */
+const bool DEBUG_POINTER_ASSIGNMENT =
+ __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "PointerAssignment", ANDROID_LOG_INFO);
+/**
+ * Log debug messages about gesture detection.
+ * Enable this via "adb shell setprop log.tag.InputReaderGestures DEBUG" (requires restart)
+ */
+const bool DEBUG_GESTURES =
+ __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "Gestures", ANDROID_LOG_INFO);
-// Log debug messages about gesture detection.
-static constexpr bool DEBUG_GESTURES = false;
+/**
+ * Log debug messages about the vibrator.
+ * Enable this via "adb shell setprop log.tag.InputReaderVibrator DEBUG" (requires restart)
+ */
+const bool DEBUG_VIBRATOR =
+ __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "Vibrator", ANDROID_LOG_INFO);
-// Log debug messages about the vibrator.
-static constexpr bool DEBUG_VIBRATOR = false;
+/**
+ * Log debug messages about fusing stylus data.
+ * Enable this via "adb shell setprop log.tag.InputReaderStylusFusion DEBUG" (requires restart)
+ */
+const bool DEBUG_STYLUS_FUSION =
+ __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "StylusFusion", ANDROID_LOG_INFO);
-// Log debug messages about fusing stylus data.
-static constexpr bool DEBUG_STYLUS_FUSION = false;
+/**
+ * Log detailed debug messages about input device lights.
+ * Enable this via "adb shell setprop log.tag.InputReaderLightDetails DEBUG" (requires restart)
+ */
+const bool DEBUG_LIGHT_DETAILS =
+ __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG "LightDetails", ANDROID_LOG_INFO);
+} // namespace android
#define INDENT " "
#define INDENT2 " "
diff --git a/services/inputflinger/reader/controller/PeripheralController.cpp b/services/inputflinger/reader/controller/PeripheralController.cpp
index a693496..7673174 100644
--- a/services/inputflinger/reader/controller/PeripheralController.cpp
+++ b/services/inputflinger/reader/controller/PeripheralController.cpp
@@ -22,9 +22,6 @@
#include "../Macros.h"
#include "PeripheralController.h"
-// Log detailed debug messages about input device lights.
-static constexpr bool DEBUG_LIGHT_DETAILS = false;
-
namespace android {
static inline int32_t getAlpha(int32_t color) {
diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h
index 130c556..79188aa 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/reader/include/EventHub.h
@@ -36,7 +36,6 @@
#include <sys/epoll.h>
#include <utils/BitSet.h>
#include <utils/Errors.h>
-#include <utils/KeyedVector.h>
#include <utils/List.h>
#include <utils/Log.h>
#include <utils/Mutex.h>
@@ -44,6 +43,8 @@
#include "TouchVideoDevice.h"
#include "VibrationElement.h"
+struct inotify_event;
+
namespace android {
/* Number of colors : {red, green, blue} */
@@ -311,7 +312,7 @@
/*
* Examine key input devices for specific framework keycode support
*/
- virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
+ virtual bool markSupportedKeyCodes(int32_t deviceId, const std::vector<int32_t>& keyCodes,
uint8_t* outFlags) const = 0;
virtual bool hasScanCode(int32_t deviceId, int32_t scanCode) const = 0;
@@ -488,7 +489,7 @@
status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis,
int32_t* outValue) const override final;
- bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
+ 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;
@@ -648,7 +649,8 @@
status_t scanDirLocked(const std::string& dirname) REQUIRES(mLock);
status_t scanVideoDirLocked(const std::string& dirname) REQUIRES(mLock);
void scanDevicesLocked() REQUIRES(mLock);
- status_t readNotifyLocked() REQUIRES(mLock);
+ base::Result<void> readNotifyLocked() REQUIRES(mLock);
+ void handleNotifyEventLocked(const inotify_event&) REQUIRES(mLock);
Device* getDeviceByDescriptorLocked(const std::string& descriptor) const REQUIRES(mLock);
Device* getDeviceLocked(int32_t deviceId) const REQUIRES(mLock);
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index 728020e..51872ac 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -88,7 +88,7 @@
int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
int32_t getKeyCodeForKeyLocation(int32_t locationKeyCode) const;
- bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes, const int32_t* keyCodes,
+ bool markSupportedKeyCodes(uint32_t sourceMask, const std::vector<int32_t>& keyCodes,
uint8_t* outFlags);
void vibrate(const VibrationSequence& sequence, ssize_t repeat, int32_t token);
void cancelVibrate(int32_t token);
@@ -324,9 +324,9 @@
inline status_t getAbsoluteAxisValue(int32_t code, int32_t* outValue) const {
return mEventHub->getAbsoluteAxisValue(mId, code, outValue);
}
- inline bool markSupportedKeyCodes(size_t numCodes, const int32_t* keyCodes,
+ inline bool markSupportedKeyCodes(const std::vector<int32_t>& keyCodes,
uint8_t* outFlags) const {
- return mEventHub->markSupportedKeyCodes(mId, numCodes, keyCodes, outFlags);
+ return mEventHub->markSupportedKeyCodes(mId, keyCodes, outFlags);
}
inline bool hasScanCode(int32_t scanCode) const {
return mEventHub->hasScanCode(mId, scanCode);
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index daeaa1d..ae41e01 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -73,7 +73,7 @@
void toggleCapsLockState(int32_t deviceId) override;
- bool hasKeys(int32_t deviceId, uint32_t sourceMask, size_t numCodes, const int32_t* keyCodes,
+ bool hasKeys(int32_t deviceId, uint32_t sourceMask, const std::vector<int32_t>& keyCodes,
uint8_t* outFlags) override;
void requestRefreshConfiguration(uint32_t changes) override;
@@ -237,8 +237,9 @@
typedef int32_t (InputDevice::*GetStateFunc)(uint32_t sourceMask, int32_t code);
int32_t getStateLocked(int32_t deviceId, uint32_t sourceMask, int32_t code,
GetStateFunc getStateFunc) REQUIRES(mLock);
- bool markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) REQUIRES(mLock);
+ bool markSupportedKeyCodesLocked(int32_t deviceId, uint32_t sourceMask,
+ const std::vector<int32_t>& keyCodes, uint8_t* outFlags)
+ REQUIRES(mLock);
// find an InputDevice from an InputDevice id
InputDevice* findInputDeviceLocked(int32_t deviceId) const REQUIRES(mLock);
diff --git a/services/inputflinger/reader/mapper/CursorInputMapper.cpp b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
index 91dc619..baa6007 100644
--- a/services/inputflinger/reader/mapper/CursorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/CursorInputMapper.cpp
@@ -225,18 +225,17 @@
void CursorInputMapper::configureParameters() {
mParameters.mode = Parameters::Mode::POINTER;
- String8 cursorModeString;
- if (getDeviceContext().getConfiguration().tryGetProperty(String8("cursor.mode"),
- cursorModeString)) {
+ std::string cursorModeString;
+ if (getDeviceContext().getConfiguration().tryGetProperty("cursor.mode", cursorModeString)) {
if (cursorModeString == "navigation") {
mParameters.mode = Parameters::Mode::NAVIGATION;
} else if (cursorModeString != "pointer" && cursorModeString != "default") {
- ALOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
+ ALOGW("Invalid value for cursor.mode: '%s'", cursorModeString.c_str());
}
}
mParameters.orientationAware = false;
- getDeviceContext().getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
+ getDeviceContext().getConfiguration().tryGetProperty("cursor.orientationAware",
mParameters.orientationAware);
mParameters.hasAssociatedDisplay = false;
diff --git a/services/inputflinger/reader/mapper/InputMapper.cpp b/services/inputflinger/reader/mapper/InputMapper.cpp
index 7b185e0..75cebf3 100644
--- a/services/inputflinger/reader/mapper/InputMapper.cpp
+++ b/services/inputflinger/reader/mapper/InputMapper.cpp
@@ -55,8 +55,8 @@
return AKEYCODE_UNKNOWN;
}
-bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) {
+bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, const std::vector<int32_t>& keyCodes,
+ uint8_t* outFlags) {
return false;
}
diff --git a/services/inputflinger/reader/mapper/InputMapper.h b/services/inputflinger/reader/mapper/InputMapper.h
index fce6409..7858728 100644
--- a/services/inputflinger/reader/mapper/InputMapper.h
+++ b/services/inputflinger/reader/mapper/InputMapper.h
@@ -64,8 +64,8 @@
virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
virtual int32_t getKeyCodeForKeyLocation(int32_t locationKeyCode) const;
- virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags);
+ virtual bool markSupportedKeyCodes(uint32_t sourceMask, const std::vector<int32_t>& keyCodes,
+ uint8_t* outFlags);
virtual void vibrate(const VibrationSequence& sequence, ssize_t repeat, int32_t token);
virtual void cancelVibrate(int32_t token);
virtual bool isVibrating();
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
index 2ac8178..6a406d2 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
@@ -160,7 +160,7 @@
static void mapStemKey(int32_t keyCode, const PropertyMap& config, char const* property) {
int32_t mapped = 0;
- if (config.tryGetProperty(String8(property), mapped) && mapped > 0) {
+ if (config.tryGetProperty(property, mapped) && mapped > 0) {
for (size_t i = 0; i < stemKeyRotationMapSize; i++) {
if (stemKeyRotationMap[i][0] == keyCode) {
stemKeyRotationMap[i][1] = mapped;
@@ -173,7 +173,7 @@
void KeyboardInputMapper::configureParameters() {
mParameters.orientationAware = false;
const PropertyMap& config = getDeviceContext().getConfiguration();
- config.tryGetProperty(String8("keyboard.orientationAware"), mParameters.orientationAware);
+ config.tryGetProperty("keyboard.orientationAware", mParameters.orientationAware);
if (mParameters.orientationAware) {
mapStemKey(AKEYCODE_STEM_PRIMARY, config, "keyboard.rotated.stem_primary");
@@ -183,10 +183,10 @@
}
mParameters.handlesKeyRepeat = false;
- config.tryGetProperty(String8("keyboard.handlesKeyRepeat"), mParameters.handlesKeyRepeat);
+ config.tryGetProperty("keyboard.handlesKeyRepeat", mParameters.handlesKeyRepeat);
mParameters.doNotWakeByDefault = false;
- config.tryGetProperty(String8("keyboard.doNotWakeByDefault"), mParameters.doNotWakeByDefault);
+ config.tryGetProperty("keyboard.doNotWakeByDefault", mParameters.doNotWakeByDefault);
}
void KeyboardInputMapper::dumpParameters(std::string& dump) {
@@ -379,9 +379,10 @@
return getDeviceContext().getKeyCodeForKeyLocation(locationKeyCode);
}
-bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) {
- return getDeviceContext().markSupportedKeyCodes(numCodes, keyCodes, outFlags);
+bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask,
+ const std::vector<int32_t>& keyCodes,
+ uint8_t* outFlags) {
+ return getDeviceContext().markSupportedKeyCodes(keyCodes, outFlags);
}
int32_t KeyboardInputMapper::getMetaState() {
@@ -433,13 +434,12 @@
mMetaState |= getContext()->getLedMetaState();
constexpr int32_t META_NUM = 3;
- const std::array<int32_t, META_NUM> keyCodes = {AKEYCODE_CAPS_LOCK, AKEYCODE_NUM_LOCK,
- AKEYCODE_SCROLL_LOCK};
+ const std::vector<int32_t> keyCodes{AKEYCODE_CAPS_LOCK, AKEYCODE_NUM_LOCK,
+ AKEYCODE_SCROLL_LOCK};
const std::array<int32_t, META_NUM> metaCodes = {AMETA_CAPS_LOCK_ON, AMETA_NUM_LOCK_ON,
AMETA_SCROLL_LOCK_ON};
std::array<uint8_t, META_NUM> flags = {0, 0, 0};
- bool hasKeyLayout =
- getDeviceContext().markSupportedKeyCodes(META_NUM, keyCodes.data(), flags.data());
+ bool hasKeyLayout = getDeviceContext().markSupportedKeyCodes(keyCodes, flags.data());
// If the device doesn't have the physical meta key it shouldn't generate the corresponding
// meta state.
if (hasKeyLayout) {
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.h b/services/inputflinger/reader/mapper/KeyboardInputMapper.h
index 3787696..0a55def 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.h
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.h
@@ -36,8 +36,8 @@
virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode) override;
virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode) override;
- virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) override;
+ virtual bool markSupportedKeyCodes(uint32_t sourceMask, const std::vector<int32_t>& keyCodes,
+ uint8_t* outFlags) override;
virtual int32_t getKeyCodeForKeyLocation(int32_t locationKeyCode) const override;
virtual int32_t getMetaState() override;
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
index 41a8426..8f5dc9b 100644
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.cpp
@@ -31,23 +31,15 @@
MultiTouchMotionAccumulator::MultiTouchMotionAccumulator()
: mCurrentSlot(-1),
- mSlots(nullptr),
- mSlotCount(0),
mUsingSlotsProtocol(false),
mHaveStylus(false) {}
-MultiTouchMotionAccumulator::~MultiTouchMotionAccumulator() {
- delete[] mSlots;
-}
-
void MultiTouchMotionAccumulator::configure(InputDeviceContext& deviceContext, size_t slotCount,
bool usingSlotsProtocol) {
- mSlotCount = slotCount;
mUsingSlotsProtocol = usingSlotsProtocol;
mHaveStylus = deviceContext.hasAbsoluteAxis(ABS_MT_TOOL_TYPE);
- delete[] mSlots;
- mSlots = new Slot[slotCount];
+ mSlots = std::vector<Slot>(slotCount);
}
void MultiTouchMotionAccumulator::reset(InputDeviceContext& deviceContext) {
@@ -76,10 +68,8 @@
}
void MultiTouchMotionAccumulator::clearSlots(int32_t initialSlot) {
- if (mSlots) {
- for (size_t i = 0; i < mSlotCount; i++) {
- mSlots[i].clear();
- }
+ for (Slot& slot : mSlots) {
+ slot.clear();
}
mCurrentSlot = initialSlot;
}
@@ -96,68 +86,68 @@
mCurrentSlot = 0;
}
- if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) {
+ if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlots.size()) {
if (DEBUG_POINTERS) {
if (newSlot) {
ALOGW("MultiTouch device emitted invalid slot index %d but it "
"should be between 0 and %zd; ignoring this slot.",
- mCurrentSlot, mSlotCount - 1);
+ mCurrentSlot, mSlots.size() - 1);
}
}
} else {
- Slot* slot = &mSlots[mCurrentSlot];
+ Slot& slot = mSlots[mCurrentSlot];
// If mUsingSlotsProtocol is true, it means the raw pointer has axis info of
// ABS_MT_TRACKING_ID and ABS_MT_SLOT, so driver should send a valid trackingId while
// updating the slot.
if (!mUsingSlotsProtocol) {
- slot->mInUse = true;
+ slot.mInUse = true;
}
switch (rawEvent->code) {
case ABS_MT_POSITION_X:
- slot->mAbsMTPositionX = rawEvent->value;
- warnIfNotInUse(*rawEvent, *slot);
+ slot.mAbsMTPositionX = rawEvent->value;
+ warnIfNotInUse(*rawEvent, slot);
break;
case ABS_MT_POSITION_Y:
- slot->mAbsMTPositionY = rawEvent->value;
- warnIfNotInUse(*rawEvent, *slot);
+ slot.mAbsMTPositionY = rawEvent->value;
+ warnIfNotInUse(*rawEvent, slot);
break;
case ABS_MT_TOUCH_MAJOR:
- slot->mAbsMTTouchMajor = rawEvent->value;
+ slot.mAbsMTTouchMajor = rawEvent->value;
break;
case ABS_MT_TOUCH_MINOR:
- slot->mAbsMTTouchMinor = rawEvent->value;
- slot->mHaveAbsMTTouchMinor = true;
+ slot.mAbsMTTouchMinor = rawEvent->value;
+ slot.mHaveAbsMTTouchMinor = true;
break;
case ABS_MT_WIDTH_MAJOR:
- slot->mAbsMTWidthMajor = rawEvent->value;
+ slot.mAbsMTWidthMajor = rawEvent->value;
break;
case ABS_MT_WIDTH_MINOR:
- slot->mAbsMTWidthMinor = rawEvent->value;
- slot->mHaveAbsMTWidthMinor = true;
+ slot.mAbsMTWidthMinor = rawEvent->value;
+ slot.mHaveAbsMTWidthMinor = true;
break;
case ABS_MT_ORIENTATION:
- slot->mAbsMTOrientation = rawEvent->value;
+ slot.mAbsMTOrientation = rawEvent->value;
break;
case ABS_MT_TRACKING_ID:
if (mUsingSlotsProtocol && rawEvent->value < 0) {
// The slot is no longer in use but it retains its previous contents,
// which may be reused for subsequent touches.
- slot->mInUse = false;
+ slot.mInUse = false;
} else {
- slot->mInUse = true;
- slot->mAbsMTTrackingId = rawEvent->value;
+ slot.mInUse = true;
+ slot.mAbsMTTrackingId = rawEvent->value;
}
break;
case ABS_MT_PRESSURE:
- slot->mAbsMTPressure = rawEvent->value;
+ slot.mAbsMTPressure = rawEvent->value;
break;
case ABS_MT_DISTANCE:
- slot->mAbsMTDistance = rawEvent->value;
+ slot.mAbsMTDistance = rawEvent->value;
break;
case ABS_MT_TOOL_TYPE:
- slot->mAbsMTToolType = rawEvent->value;
- slot->mHaveAbsMTToolType = true;
+ slot.mAbsMTToolType = rawEvent->value;
+ slot.mHaveAbsMTToolType = true;
break;
}
}
@@ -186,28 +176,6 @@
// --- MultiTouchMotionAccumulator::Slot ---
-MultiTouchMotionAccumulator::Slot::Slot() {
- clear();
-}
-
-void MultiTouchMotionAccumulator::Slot::clear() {
- mInUse = false;
- mHaveAbsMTTouchMinor = false;
- mHaveAbsMTWidthMinor = false;
- mHaveAbsMTToolType = false;
- mAbsMTPositionX = 0;
- mAbsMTPositionY = 0;
- mAbsMTTouchMajor = 0;
- mAbsMTTouchMinor = 0;
- mAbsMTWidthMajor = 0;
- mAbsMTWidthMinor = 0;
- mAbsMTOrientation = 0;
- mAbsMTTrackingId = -1;
- mAbsMTPressure = 0;
- mAbsMTDistance = 0;
- mAbsMTToolType = 0;
-}
-
int32_t MultiTouchMotionAccumulator::Slot::getToolType() const {
if (mHaveAbsMTToolType) {
switch (mAbsMTToolType) {
@@ -264,14 +232,14 @@
mHavePointerIds = true;
for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
- const MultiTouchMotionAccumulator::Slot* inSlot =
+ const MultiTouchMotionAccumulator::Slot& inSlot =
mMultiTouchMotionAccumulator.getSlot(inIndex);
- if (!inSlot->isInUse()) {
+ if (!inSlot.isInUse()) {
continue;
}
- if (inSlot->getToolType() == AMOTION_EVENT_TOOL_TYPE_PALM) {
- std::optional<int32_t> id = getActiveBitId(*inSlot);
+ if (inSlot.getToolType() == AMOTION_EVENT_TOOL_TYPE_PALM) {
+ std::optional<int32_t> id = getActiveBitId(inSlot);
if (id) {
outState->rawPointerData.canceledIdBits.markBit(id.value());
}
@@ -292,19 +260,19 @@
}
RawPointerData::Pointer& outPointer = outState->rawPointerData.pointers[outCount];
- outPointer.x = inSlot->getX();
- outPointer.y = inSlot->getY();
- outPointer.pressure = inSlot->getPressure();
- outPointer.touchMajor = inSlot->getTouchMajor();
- outPointer.touchMinor = inSlot->getTouchMinor();
- outPointer.toolMajor = inSlot->getToolMajor();
- outPointer.toolMinor = inSlot->getToolMinor();
- outPointer.orientation = inSlot->getOrientation();
- outPointer.distance = inSlot->getDistance();
+ outPointer.x = inSlot.getX();
+ outPointer.y = inSlot.getY();
+ outPointer.pressure = inSlot.getPressure();
+ outPointer.touchMajor = inSlot.getTouchMajor();
+ outPointer.touchMinor = inSlot.getTouchMinor();
+ outPointer.toolMajor = inSlot.getToolMajor();
+ outPointer.toolMinor = inSlot.getToolMinor();
+ outPointer.orientation = inSlot.getOrientation();
+ outPointer.distance = inSlot.getDistance();
outPointer.tiltX = 0;
outPointer.tiltY = 0;
- outPointer.toolType = inSlot->getToolType();
+ outPointer.toolType = inSlot.getToolType();
if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
outPointer.toolType = mTouchButtonAccumulator.getToolType();
if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
@@ -318,12 +286,12 @@
bool isHovering = mTouchButtonAccumulator.getToolType() != AMOTION_EVENT_TOOL_TYPE_MOUSE &&
(mTouchButtonAccumulator.isHovering() ||
- (mRawPointerAxes.pressure.valid && inSlot->getPressure() <= 0));
+ (mRawPointerAxes.pressure.valid && inSlot.getPressure() <= 0));
outPointer.isHovering = isHovering;
// Assign pointer id using tracking id if available.
if (mHavePointerIds) {
- int32_t trackingId = inSlot->getTrackingId();
+ int32_t trackingId = inSlot.getTrackingId();
int32_t id = -1;
if (trackingId >= 0) {
for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty();) {
diff --git a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
index b7c3457..fe8af5d 100644
--- a/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/MultiTouchInputMapper.h
@@ -46,29 +46,27 @@
private:
friend class MultiTouchMotionAccumulator;
- bool mInUse;
- bool mHaveAbsMTTouchMinor;
- bool mHaveAbsMTWidthMinor;
- bool mHaveAbsMTToolType;
+ bool mInUse = false;
+ bool mHaveAbsMTTouchMinor = false;
+ bool mHaveAbsMTWidthMinor = false;
+ bool mHaveAbsMTToolType = false;
- int32_t mAbsMTPositionX;
- int32_t mAbsMTPositionY;
- int32_t mAbsMTTouchMajor;
- int32_t mAbsMTTouchMinor;
- int32_t mAbsMTWidthMajor;
- int32_t mAbsMTWidthMinor;
- int32_t mAbsMTOrientation;
- int32_t mAbsMTTrackingId;
- int32_t mAbsMTPressure;
- int32_t mAbsMTDistance;
- int32_t mAbsMTToolType;
+ int32_t mAbsMTPositionX = 0;
+ int32_t mAbsMTPositionY = 0;
+ int32_t mAbsMTTouchMajor = 0;
+ int32_t mAbsMTTouchMinor = 0;
+ int32_t mAbsMTWidthMajor = 0;
+ int32_t mAbsMTWidthMinor = 0;
+ int32_t mAbsMTOrientation = 0;
+ int32_t mAbsMTTrackingId = -1;
+ int32_t mAbsMTPressure = 0;
+ int32_t mAbsMTDistance = 0;
+ int32_t mAbsMTToolType = 0;
- Slot();
- void clear();
+ void clear() { *this = Slot(); }
};
MultiTouchMotionAccumulator();
- ~MultiTouchMotionAccumulator();
void configure(InputDeviceContext& deviceContext, size_t slotCount, bool usingSlotsProtocol);
void reset(InputDeviceContext& deviceContext);
@@ -76,13 +74,15 @@
void finishSync();
bool hasStylus() const;
- inline size_t getSlotCount() const { return mSlotCount; }
- inline const Slot* getSlot(size_t index) const { return &mSlots[index]; }
+ inline size_t getSlotCount() const { return mSlots.size(); }
+ inline const Slot& getSlot(size_t index) const {
+ LOG_ALWAYS_FATAL_IF(index < 0 || index >= mSlots.size(), "Invalid index: %zu", index);
+ return mSlots[index];
+ }
private:
int32_t mCurrentSlot;
- Slot* mSlots;
- size_t mSlotCount;
+ std::vector<Slot> mSlots;
bool mUsingSlotsProtocol;
bool mHaveStylus;
diff --git a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
index eca25f6..05973f7 100644
--- a/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/RotaryEncoderInputMapper.cpp
@@ -40,10 +40,10 @@
if (mRotaryEncoderScrollAccumulator.haveRelativeVWheel()) {
float res = 0.0f;
- if (!getDeviceContext().getConfiguration().tryGetProperty(String8("device.res"), res)) {
+ if (!getDeviceContext().getConfiguration().tryGetProperty("device.res", res)) {
ALOGW("Rotary Encoder device configuration file didn't specify resolution!\n");
}
- if (!getDeviceContext().getConfiguration().tryGetProperty(String8("device.scalingFactor"),
+ if (!getDeviceContext().getConfiguration().tryGetProperty("device.scalingFactor",
mScalingFactor)) {
ALOGW("Rotary Encoder device configuration file didn't specify scaling factor,"
"default to 1.0!\n");
diff --git a/services/inputflinger/reader/mapper/SensorInputMapper.cpp b/services/inputflinger/reader/mapper/SensorInputMapper.cpp
index b01c2bc..573f99c 100644
--- a/services/inputflinger/reader/mapper/SensorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/SensorInputMapper.cpp
@@ -64,7 +64,7 @@
template <typename T>
bool SensorInputMapper::tryGetProperty(std::string keyName, T& outValue) {
const auto& config = getDeviceContext().getConfiguration();
- return config.tryGetProperty(String8(keyName.c_str()), outValue);
+ return config.tryGetProperty(keyName, outValue);
}
void SensorInputMapper::parseSensorConfiguration(InputDeviceSensorType sensorType, int32_t absCode,
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index 2acbb0a..895a347 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -42,6 +42,8 @@
// data.
static constexpr nsecs_t STYLUS_DATA_LATENCY = ms2ns(10);
+// Minimum width between two pointers to determine a gesture as freeform gesture in mm
+static const float MIN_FREEFORM_GESTURE_WIDTH_IN_MILLIMETER = 30;
// --- Static Definitions ---
template <typename T>
@@ -415,15 +417,15 @@
? Parameters::GestureMode::SINGLE_TOUCH
: Parameters::GestureMode::MULTI_TOUCH;
- String8 gestureModeString;
- if (getDeviceContext().getConfiguration().tryGetProperty(String8("touch.gestureMode"),
+ std::string gestureModeString;
+ if (getDeviceContext().getConfiguration().tryGetProperty("touch.gestureMode",
gestureModeString)) {
if (gestureModeString == "single-touch") {
mParameters.gestureMode = Parameters::GestureMode::SINGLE_TOUCH;
} else if (gestureModeString == "multi-touch") {
mParameters.gestureMode = Parameters::GestureMode::MULTI_TOUCH;
} else if (gestureModeString != "default") {
- ALOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString.string());
+ ALOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString.c_str());
}
}
@@ -445,8 +447,8 @@
mParameters.hasButtonUnderPad = getDeviceContext().hasInputProperty(INPUT_PROP_BUTTONPAD);
- String8 deviceTypeString;
- if (getDeviceContext().getConfiguration().tryGetProperty(String8("touch.deviceType"),
+ std::string deviceTypeString;
+ if (getDeviceContext().getConfiguration().tryGetProperty("touch.deviceType",
deviceTypeString)) {
if (deviceTypeString == "touchScreen") {
mParameters.deviceType = Parameters::DeviceType::TOUCH_SCREEN;
@@ -457,17 +459,17 @@
} else if (deviceTypeString == "pointer") {
mParameters.deviceType = Parameters::DeviceType::POINTER;
} else if (deviceTypeString != "default") {
- ALOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
+ ALOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.c_str());
}
}
mParameters.orientationAware = mParameters.deviceType == Parameters::DeviceType::TOUCH_SCREEN;
- getDeviceContext().getConfiguration().tryGetProperty(String8("touch.orientationAware"),
+ getDeviceContext().getConfiguration().tryGetProperty("touch.orientationAware",
mParameters.orientationAware);
mParameters.orientation = Parameters::Orientation::ORIENTATION_0;
- String8 orientationString;
- if (getDeviceContext().getConfiguration().tryGetProperty(String8("touch.orientation"),
+ std::string orientationString;
+ if (getDeviceContext().getConfiguration().tryGetProperty("touch.orientation",
orientationString)) {
if (mParameters.deviceType != Parameters::DeviceType::TOUCH_SCREEN) {
ALOGW("The configuration 'touch.orientation' is only supported for touchscreens.");
@@ -478,7 +480,7 @@
} else if (orientationString == "ORIENTATION_270") {
mParameters.orientation = Parameters::Orientation::ORIENTATION_270;
} else if (orientationString != "ORIENTATION_0") {
- ALOGW("Invalid value for touch.orientation: '%s'", orientationString.string());
+ ALOGW("Invalid value for touch.orientation: '%s'", orientationString.c_str());
}
}
@@ -490,8 +492,8 @@
mParameters.hasAssociatedDisplay = true;
if (mParameters.deviceType == Parameters::DeviceType::TOUCH_SCREEN) {
mParameters.associatedDisplayIsExternal = getDeviceContext().isExternal();
- String8 uniqueDisplayId;
- getDeviceContext().getConfiguration().tryGetProperty(String8("touch.displayId"),
+ std::string uniqueDisplayId;
+ getDeviceContext().getConfiguration().tryGetProperty("touch.displayId",
uniqueDisplayId);
mParameters.uniqueDisplayId = uniqueDisplayId.c_str();
}
@@ -504,7 +506,7 @@
// Normally we don't do this for internal touch screens to prevent them from waking
// up in your pocket but you can enable it using the input device configuration.
mParameters.wake = getDeviceContext().isExternal();
- getDeviceContext().getConfiguration().tryGetProperty(String8("touch.wake"), mParameters.wake);
+ getDeviceContext().getConfiguration().tryGetProperty("touch.wake", mParameters.wake);
}
void TouchInputMapper::dumpParameters(std::string& dump) {
@@ -936,6 +938,11 @@
// Raw width and height in the natural orientation.
const int32_t rawWidth = mRawPointerAxes.getRawWidth();
const int32_t rawHeight = mRawPointerAxes.getRawHeight();
+ const int32_t rawXResolution = mRawPointerAxes.x.resolution;
+ const int32_t rawYResolution = mRawPointerAxes.y.resolution;
+ // Calculate the mean resolution when both x and y resolution are set, otherwise set it to 0.
+ const float rawMeanResolution =
+ (rawXResolution > 0 && rawYResolution > 0) ? (rawXResolution + rawYResolution) / 2 : 0;
const bool viewportChanged = mViewport != *newViewport;
bool skipViewportUpdate = false;
@@ -1094,10 +1101,14 @@
mConfig.pointerGestureZoomSpeedRatio * displayDiagonal / rawDiagonal;
mPointerYZoomScale = mPointerXZoomScale;
- // Max width between pointers to detect a swipe gesture is more than some fraction
- // of the diagonal axis of the touch pad. Touches that are wider than this are
- // translated into freeform gestures.
- mPointerGestureMaxSwipeWidth = mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal;
+ // Calculate the min freeform gesture width. It will be 0 when the resolution of any
+ // axis is non positive value.
+ const float minFreeformGestureWidth =
+ rawMeanResolution * MIN_FREEFORM_GESTURE_WIDTH_IN_MILLIMETER;
+
+ mPointerGestureMaxSwipeWidth =
+ std::max(mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal,
+ minFreeformGestureWidth);
// Abort current pointer usages because the state has changed.
const nsecs_t readTime = when; // synthetic event
@@ -1192,8 +1203,8 @@
// Size
out.sizeCalibration = Calibration::SizeCalibration::DEFAULT;
- String8 sizeCalibrationString;
- if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
+ std::string sizeCalibrationString;
+ if (in.tryGetProperty("touch.size.calibration", sizeCalibrationString)) {
if (sizeCalibrationString == "none") {
out.sizeCalibration = Calibration::SizeCalibration::NONE;
} else if (sizeCalibrationString == "geometric") {
@@ -1205,18 +1216,18 @@
} else if (sizeCalibrationString == "area") {
out.sizeCalibration = Calibration::SizeCalibration::AREA;
} else if (sizeCalibrationString != "default") {
- ALOGW("Invalid value for touch.size.calibration: '%s'", sizeCalibrationString.string());
+ ALOGW("Invalid value for touch.size.calibration: '%s'", sizeCalibrationString.c_str());
}
}
- out.haveSizeScale = in.tryGetProperty(String8("touch.size.scale"), out.sizeScale);
- out.haveSizeBias = in.tryGetProperty(String8("touch.size.bias"), out.sizeBias);
- out.haveSizeIsSummed = in.tryGetProperty(String8("touch.size.isSummed"), out.sizeIsSummed);
+ out.haveSizeScale = in.tryGetProperty("touch.size.scale", out.sizeScale);
+ out.haveSizeBias = in.tryGetProperty("touch.size.bias", out.sizeBias);
+ out.haveSizeIsSummed = in.tryGetProperty("touch.size.isSummed", out.sizeIsSummed);
// Pressure
out.pressureCalibration = Calibration::PressureCalibration::DEFAULT;
- String8 pressureCalibrationString;
- if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
+ std::string pressureCalibrationString;
+ if (in.tryGetProperty("touch.pressure.calibration", pressureCalibrationString)) {
if (pressureCalibrationString == "none") {
out.pressureCalibration = Calibration::PressureCalibration::NONE;
} else if (pressureCalibrationString == "physical") {
@@ -1225,16 +1236,16 @@
out.pressureCalibration = Calibration::PressureCalibration::AMPLITUDE;
} else if (pressureCalibrationString != "default") {
ALOGW("Invalid value for touch.pressure.calibration: '%s'",
- pressureCalibrationString.string());
+ pressureCalibrationString.c_str());
}
}
- out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"), out.pressureScale);
+ out.havePressureScale = in.tryGetProperty("touch.pressure.scale", out.pressureScale);
// Orientation
out.orientationCalibration = Calibration::OrientationCalibration::DEFAULT;
- String8 orientationCalibrationString;
- if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
+ std::string orientationCalibrationString;
+ if (in.tryGetProperty("touch.orientation.calibration", orientationCalibrationString)) {
if (orientationCalibrationString == "none") {
out.orientationCalibration = Calibration::OrientationCalibration::NONE;
} else if (orientationCalibrationString == "interpolated") {
@@ -1243,36 +1254,36 @@
out.orientationCalibration = Calibration::OrientationCalibration::VECTOR;
} else if (orientationCalibrationString != "default") {
ALOGW("Invalid value for touch.orientation.calibration: '%s'",
- orientationCalibrationString.string());
+ orientationCalibrationString.c_str());
}
}
// Distance
out.distanceCalibration = Calibration::DistanceCalibration::DEFAULT;
- String8 distanceCalibrationString;
- if (in.tryGetProperty(String8("touch.distance.calibration"), distanceCalibrationString)) {
+ std::string distanceCalibrationString;
+ if (in.tryGetProperty("touch.distance.calibration", distanceCalibrationString)) {
if (distanceCalibrationString == "none") {
out.distanceCalibration = Calibration::DistanceCalibration::NONE;
} else if (distanceCalibrationString == "scaled") {
out.distanceCalibration = Calibration::DistanceCalibration::SCALED;
} else if (distanceCalibrationString != "default") {
ALOGW("Invalid value for touch.distance.calibration: '%s'",
- distanceCalibrationString.string());
+ distanceCalibrationString.c_str());
}
}
- out.haveDistanceScale = in.tryGetProperty(String8("touch.distance.scale"), out.distanceScale);
+ out.haveDistanceScale = in.tryGetProperty("touch.distance.scale", out.distanceScale);
out.coverageCalibration = Calibration::CoverageCalibration::DEFAULT;
- String8 coverageCalibrationString;
- if (in.tryGetProperty(String8("touch.coverage.calibration"), coverageCalibrationString)) {
+ std::string coverageCalibrationString;
+ if (in.tryGetProperty("touch.coverage.calibration", coverageCalibrationString)) {
if (coverageCalibrationString == "none") {
out.coverageCalibration = Calibration::CoverageCalibration::NONE;
} else if (coverageCalibrationString == "box") {
out.coverageCalibration = Calibration::CoverageCalibration::BOX;
} else if (coverageCalibrationString != "default") {
ALOGW("Invalid value for touch.coverage.calibration: '%s'",
- coverageCalibrationString.string());
+ coverageCalibrationString.c_str());
}
}
}
@@ -4025,10 +4036,11 @@
return AKEY_STATE_UNKNOWN;
}
-bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
- const int32_t* keyCodes, uint8_t* outFlags) {
+bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask,
+ const std::vector<int32_t>& keyCodes,
+ uint8_t* outFlags) {
for (const VirtualKey& virtualKey : mVirtualKeys) {
- for (size_t i = 0; i < numCodes; i++) {
+ for (size_t i = 0; i < keyCodes.size(); i++) {
if (virtualKey.keyCode == keyCodes[i]) {
outFlags[i] = 1;
}
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h
index c948f56..3042be6 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -147,7 +147,7 @@
int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode) override;
int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode) override;
- bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes, const int32_t* keyCodes,
+ bool markSupportedKeyCodes(uint32_t sourceMask, const std::vector<int32_t>& keyCodes,
uint8_t* outFlags) override;
void cancelTouch(nsecs_t when, nsecs_t readTime) override;
@@ -527,7 +527,9 @@
float mPointerXZoomScale;
float mPointerYZoomScale;
- // The maximum swipe width.
+ // The maximum swipe width between pointers to detect a swipe gesture
+ // in the number of pixels.Touches that are wider than this are translated
+ // into freeform gestures.
float mPointerGestureMaxSwipeWidth;
struct PointerDistanceHeapElement {
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index df43071..8a2dea5 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -58,6 +58,8 @@
AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
static constexpr int32_t POINTER_2_DOWN =
AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
+static constexpr int32_t POINTER_3_DOWN =
+ AMOTION_EVENT_ACTION_POINTER_DOWN | (3 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
static constexpr int32_t POINTER_1_UP =
AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
@@ -412,7 +414,6 @@
void notifyFocusChanged(const sp<IBinder>&, const sp<IBinder>&) override {}
- void notifyUntrustedTouch(const std::string& obscuringPackage) override {}
void notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
const std::vector<float>& values) override {}
@@ -499,6 +500,11 @@
verify(*mFilteredEvent);
mFilteredEvent = nullptr;
}
+
+ bool isPerDisplayTouchModeEnabled() {
+ // TODO(b/198499018): Make this a regular property once per display touch mode is enabled
+ return false;
+ }
};
// --- InputDispatcherTest ---
@@ -1942,6 +1948,77 @@
window2->consumeMotionDown();
}
+/**
+ * When splitting touch events the downTime should be adjusted such that the downTime corresponds
+ * to the event time of the first ACTION_DOWN sent to the particular window.
+ */
+TEST_F(InputDispatcherTest, SplitTouchesSendCorrectActionDownTime) {
+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
+ sp<FakeWindowHandle> window1 =
+ new FakeWindowHandle(application, mDispatcher, "Window1", DISPLAY_ID);
+ window1->setTouchableRegion(Region{{0, 0, 100, 100}});
+ sp<FakeWindowHandle> window2 =
+ new FakeWindowHandle(application, mDispatcher, "Window2", DISPLAY_ID);
+ window2->setTouchableRegion(Region{{100, 0, 200, 100}});
+
+ mDispatcher->setInputWindows({{DISPLAY_ID, {window1, window2}}});
+
+ NotifyMotionArgs args;
+ // Touch down on the first window
+ mDispatcher->notifyMotion(&(args = generateTouchArgs(AMOTION_EVENT_ACTION_DOWN, {{50, 50}})));
+
+ mDispatcher->waitForIdle();
+ InputEvent* inputEvent1 = window1->consume();
+ window2->assertNoEvents();
+ MotionEvent& motionEvent1 = static_cast<MotionEvent&>(*inputEvent1);
+ nsecs_t downTimeForWindow1 = motionEvent1.getDownTime();
+ ASSERT_EQ(motionEvent1.getDownTime(), motionEvent1.getEventTime());
+
+ // Now touch down on the window with another pointer
+ mDispatcher->notifyMotion(&(args = generateTouchArgs(POINTER_1_DOWN, {{50, 50}, {150, 50}})));
+ mDispatcher->waitForIdle();
+ InputEvent* inputEvent2 = window2->consume();
+ MotionEvent& motionEvent2 = static_cast<MotionEvent&>(*inputEvent2);
+ nsecs_t downTimeForWindow2 = motionEvent2.getDownTime();
+ ASSERT_NE(downTimeForWindow1, downTimeForWindow2);
+ ASSERT_EQ(motionEvent2.getDownTime(), motionEvent2.getEventTime());
+
+ // Now move the pointer on the second window
+ mDispatcher->notifyMotion(
+ &(args = generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{50, 50}, {151, 51}})));
+ mDispatcher->waitForIdle();
+ InputEvent* inputEvent3 = window2->consume();
+ MotionEvent& motionEvent3 = static_cast<MotionEvent&>(*inputEvent3);
+ ASSERT_EQ(motionEvent3.getDownTime(), downTimeForWindow2);
+
+ // Now add new touch down on the second window
+ mDispatcher->notifyMotion(
+ &(args = generateTouchArgs(POINTER_2_DOWN, {{50, 50}, {151, 51}, {150, 50}})));
+ mDispatcher->waitForIdle();
+ InputEvent* inputEvent4 = window2->consume();
+ MotionEvent& motionEvent4 = static_cast<MotionEvent&>(*inputEvent4);
+ ASSERT_EQ(motionEvent4.getDownTime(), downTimeForWindow2);
+
+ // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
+ window1->consumeMotionMove();
+ window1->assertNoEvents();
+
+ // Now move the pointer on the first window
+ mDispatcher->notifyMotion(
+ &(args = generateTouchArgs(AMOTION_EVENT_ACTION_MOVE, {{51, 51}, {151, 51}})));
+ mDispatcher->waitForIdle();
+ InputEvent* inputEvent5 = window1->consume();
+ MotionEvent& motionEvent5 = static_cast<MotionEvent&>(*inputEvent5);
+ ASSERT_EQ(motionEvent5.getDownTime(), downTimeForWindow1);
+
+ mDispatcher->notifyMotion(&(
+ args = generateTouchArgs(POINTER_3_DOWN, {{51, 51}, {151, 51}, {150, 50}, {50, 50}})));
+ mDispatcher->waitForIdle();
+ InputEvent* inputEvent6 = window1->consume();
+ MotionEvent& motionEvent6 = static_cast<MotionEvent&>(*inputEvent6);
+ ASSERT_EQ(motionEvent6.getDownTime(), downTimeForWindow1);
+}
+
TEST_F(InputDispatcherTest, HoverMoveEnterMouseClickAndHoverMoveExit) {
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
sp<FakeWindowHandle> windowLeft =
@@ -3221,7 +3298,7 @@
SCOPED_TRACE("Disable touch mode");
mDispatcher->setInTouchMode(false, windowInfo.ownerPid, windowInfo.ownerUid,
- /* hasPermission */ true);
+ true /*hasPermission*/, ADISPLAY_ID_DEFAULT);
window->consumeTouchModeEvent(false);
window->setFocusable(true);
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
@@ -3235,7 +3312,7 @@
SCOPED_TRACE("Enable touch mode again");
mDispatcher->setInTouchMode(true, windowInfo.ownerPid, windowInfo.ownerUid,
- /* hasPermission */ true);
+ true /*hasPermission*/, ADISPLAY_ID_DEFAULT);
window->consumeTouchModeEvent(true);
window->setFocusable(true);
mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
@@ -5715,7 +5792,6 @@
virtual void SetUp() override {
InputDispatcherTest::SetUp();
mTouchWindow = getWindow(TOUCHED_APP_UID, "Touched");
- mDispatcher->setBlockUntrustedTouchesMode(android::os::BlockUntrustedTouchesMode::BLOCK);
mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
}
@@ -6096,6 +6172,7 @@
sp<FakeWindowHandle> mWindow;
sp<FakeWindowHandle> mSecondWindow;
sp<FakeWindowHandle> mDragWindow;
+ sp<FakeWindowHandle> mSpyWindow;
void SetUp() override {
InputDispatcherTest::SetUp();
@@ -6106,8 +6183,13 @@
mSecondWindow = new FakeWindowHandle(mApp, mDispatcher, "TestWindow2", ADISPLAY_ID_DEFAULT);
mSecondWindow->setFrame(Rect(100, 0, 200, 100));
+ mSpyWindow = new FakeWindowHandle(mApp, mDispatcher, "SpyWindow", ADISPLAY_ID_DEFAULT);
+ mSpyWindow->setSpy(true);
+ mSpyWindow->setTrustedOverlay(true);
+ mSpyWindow->setFrame(Rect(0, 0, 200, 100));
+
mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, mApp);
- mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mWindow, mSecondWindow}}});
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mSpyWindow, mWindow, mSecondWindow}}});
}
void injectDown() {
@@ -6118,6 +6200,8 @@
// Window should receive motion event.
mWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+ // Spy window should also receive motion event
+ mSpyWindow->consumeMotionDown(ADISPLAY_ID_DEFAULT);
}
// Start performing drag, we will create a drag window and transfer touch to it.
@@ -6130,8 +6214,9 @@
// The drag window covers the entire display
mDragWindow = new FakeWindowHandle(mApp, mDispatcher, "DragWindow", ADISPLAY_ID_DEFAULT);
+ mDragWindow->setTouchableRegion(Region{{0, 0, 0, 0}});
mDispatcher->setInputWindows(
- {{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});
+ {{ADISPLAY_ID_DEFAULT, {mDragWindow, mSpyWindow, mWindow, mSecondWindow}}});
// Transfer touch focus to the drag window
bool transferred =
@@ -6209,6 +6294,30 @@
mSecondWindow->assertNoEvents();
}
+TEST_F(InputDispatcherDragTests, DragEnterAndPointerDownPilfersPointers) {
+ performDrag();
+
+ // No cancel event after drag start
+ mSpyWindow->assertNoEvents();
+
+ const MotionEvent secondFingerDownEvent =
+ MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
+ .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
+ .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(60).y(60))
+ .build();
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
+ InputEventInjectionSync::WAIT_FOR_RESULT))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+
+ // Receives cancel for first pointer after next pointer down
+ mSpyWindow->consumeMotionCancel();
+ mSpyWindow->consumeMotionDown();
+
+ mSpyWindow->assertNoEvents();
+}
+
TEST_F(InputDispatcherDragTests, DragAndDrop) {
performDrag();
@@ -6611,14 +6720,15 @@
// Set initial touch mode to InputDispatcher::kDefaultInTouchMode.
if (mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, WINDOW_PID,
- WINDOW_UID, /* hasPermission */ true)) {
+ WINDOW_UID, true /*hasPermission*/, ADISPLAY_ID_DEFAULT)) {
mWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
mSecondWindow->consumeTouchModeEvent(InputDispatcher::kDefaultInTouchMode);
}
}
void changeAndVerifyTouchMode(bool inTouchMode, int32_t pid, int32_t uid, bool hasPermission) {
- ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission));
+ ASSERT_TRUE(mDispatcher->setInTouchMode(inTouchMode, pid, uid, hasPermission,
+ ADISPLAY_ID_DEFAULT));
mWindow->consumeTouchModeEvent(inTouchMode);
mSecondWindow->consumeTouchModeEvent(inTouchMode);
}
@@ -6627,7 +6737,7 @@
TEST_F(InputDispatcherTouchModeChangedTests, FocusedWindowCanChangeTouchMode) {
const WindowInfo& windowInfo = *mWindow->getInfo();
changeAndVerifyTouchMode(!InputDispatcher::kDefaultInTouchMode, windowInfo.ownerPid,
- windowInfo.ownerUid, /* hasPermission */ false);
+ windowInfo.ownerUid, false /*hasPermission*/);
}
TEST_F(InputDispatcherTouchModeChangedTests, NonFocusedWindowOwnerCannotChangeTouchMode) {
@@ -6636,7 +6746,8 @@
int32_t ownerUid = windowInfo.ownerUid;
mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode, ownerPid,
- ownerUid, /* hasPermission */ false));
+ ownerUid, false /*hasPermission*/,
+ ADISPLAY_ID_DEFAULT));
mWindow->assertNoEvents();
mSecondWindow->assertNoEvents();
}
@@ -6647,14 +6758,14 @@
int32_t ownerUid = windowInfo.ownerUid;
mWindow->setOwnerInfo(/* pid */ -1, /* uid */ -1);
changeAndVerifyTouchMode(!InputDispatcher::kDefaultInTouchMode, ownerPid, ownerUid,
- /* hasPermission */ true);
+ true /*hasPermission*/);
}
TEST_F(InputDispatcherTouchModeChangedTests, EventIsNotGeneratedIfNotChangingTouchMode) {
const WindowInfo& windowInfo = *mWindow->getInfo();
ASSERT_FALSE(mDispatcher->setInTouchMode(InputDispatcher::kDefaultInTouchMode,
windowInfo.ownerPid, windowInfo.ownerUid,
- /* hasPermission */ true));
+ true /*hasPermission*/, ADISPLAY_ID_DEFAULT));
mWindow->assertNoEvents();
mSecondWindow->assertNoEvents();
}
@@ -6673,7 +6784,7 @@
const WindowInfo& windowInfo = *mWindow->getInfo();
ASSERT_TRUE(mDispatcher->setInTouchMode(!InputDispatcher::kDefaultInTouchMode,
windowInfo.ownerPid, windowInfo.ownerUid,
- /* hasPermission= */ false));
+ false /*hasPermission*/, ADISPLAY_ID_DEFAULT));
}
class InputDispatcherSpyWindowTest : public InputDispatcherTest {
@@ -6862,123 +6973,6 @@
}
/**
- * A spy window can pilfer pointers. When this happens, touch gestures that are currently sent to
- * any other windows - including other spy windows - will also be cancelled.
- */
-TEST_F(InputDispatcherSpyWindowTest, PilferPointers) {
- auto window = createForeground();
- auto spy1 = createSpy();
- auto spy2 = createSpy();
- mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window}}});
-
- ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
- injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
- << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
- window->consumeMotionDown();
- spy1->consumeMotionDown();
- spy2->consumeMotionDown();
-
- // Pilfer pointers from the second spy window.
- EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
- spy2->assertNoEvents();
- spy1->consumeMotionCancel();
- window->consumeMotionCancel();
-
- // The rest of the gesture should only be sent to the second spy window.
- ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
- injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
- ADISPLAY_ID_DEFAULT))
- << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
- spy2->consumeMotionMove();
- spy1->assertNoEvents();
- window->assertNoEvents();
-}
-
-/**
- * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
- * in the middle of the gesture.
- */
-TEST_F(InputDispatcherSpyWindowTest, CanPilferAfterWindowIsRemovedMidStream) {
- auto window = createForeground();
- auto spy = createSpy();
- mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
-
- ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
- injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
- << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
- window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
- spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
-
- window->releaseChannel();
-
- EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
-
- ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
- injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
- << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
- spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
-}
-
-/**
- * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
- * the spy, but not to any other windows.
- */
-TEST_F(InputDispatcherSpyWindowTest, ContinuesToReceiveGestureAfterPilfer) {
- auto spy = createSpy();
- auto window = createForeground();
-
- mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
-
- // First finger down on the window and the spy.
- ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
- injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
- {100, 200}))
- << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
- spy->consumeMotionDown();
- window->consumeMotionDown();
-
- // Spy window pilfers the pointers.
- EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
- window->consumeMotionCancel();
-
- // Second finger down on the window and spy, but the window should not receive the pointer down.
- const MotionEvent secondFingerDownEvent =
- MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
- .displayId(ADISPLAY_ID_DEFAULT)
- .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
- .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
- .x(100)
- .y(200))
- .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
- .build();
- ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
- injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
- InputEventInjectionSync::WAIT_FOR_RESULT))
- << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-
- spy->consumeMotionPointerDown(1 /*pointerIndex*/);
-
- // Third finger goes down outside all windows, so injection should fail.
- const MotionEvent thirdFingerDownEvent =
- MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
- .displayId(ADISPLAY_ID_DEFAULT)
- .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
- .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
- .x(100)
- .y(200))
- .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
- .pointer(PointerBuilder(/* id */ 2, AMOTION_EVENT_TOOL_TYPE_FINGER).x(-5).y(-5))
- .build();
- ASSERT_EQ(InputEventInjectionResult::FAILED,
- injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
- InputEventInjectionSync::WAIT_FOR_RESULT))
- << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
-
- spy->assertNoEvents();
- window->assertNoEvents();
-}
-
-/**
* Even when a spy window spans over multiple foreground windows, the spy should receive all
* pointers that are down within its bounds.
*/
@@ -7112,6 +7106,277 @@
spy->assertNoEvents();
}
+using InputDispatcherPilferPointersTest = InputDispatcherSpyWindowTest;
+
+/**
+ * A spy window can pilfer pointers. When this happens, touch gestures used by the spy window that
+ * are currently sent to any other windows - including other spy windows - will also be cancelled.
+ */
+TEST_F(InputDispatcherPilferPointersTest, PilferPointers) {
+ auto window = createForeground();
+ auto spy1 = createSpy();
+ auto spy2 = createSpy();
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy1, spy2, window}}});
+
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ window->consumeMotionDown();
+ spy1->consumeMotionDown();
+ spy2->consumeMotionDown();
+
+ // Pilfer pointers from the second spy window.
+ EXPECT_EQ(OK, mDispatcher->pilferPointers(spy2->getToken()));
+ spy2->assertNoEvents();
+ spy1->consumeMotionCancel();
+ window->consumeMotionCancel();
+
+ // The rest of the gesture should only be sent to the second spy window.
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ spy2->consumeMotionMove();
+ spy1->assertNoEvents();
+ window->assertNoEvents();
+}
+
+/**
+ * A spy window can pilfer pointers for a gesture even after the foreground window has been removed
+ * in the middle of the gesture.
+ */
+TEST_F(InputDispatcherPilferPointersTest, CanPilferAfterWindowIsRemovedMidStream) {
+ auto window = createForeground();
+ auto spy = createSpy();
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
+
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+ spy->consumeMotionDown(ADISPLAY_ID_DEFAULT);
+
+ window->releaseChannel();
+
+ EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
+
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ spy->consumeMotionUp(ADISPLAY_ID_DEFAULT);
+}
+
+/**
+ * After a spy window pilfers pointers, new pointers that go down in its bounds should be sent to
+ * the spy, but not to any other windows.
+ */
+TEST_F(InputDispatcherPilferPointersTest, ContinuesToReceiveGestureAfterPilfer) {
+ auto spy = createSpy();
+ auto window = createForeground();
+
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
+
+ // First finger down on the window and the spy.
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {100, 200}))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ spy->consumeMotionDown();
+ window->consumeMotionDown();
+
+ // Spy window pilfers the pointers.
+ EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
+ window->consumeMotionCancel();
+
+ // Second finger down on the window and spy, but the window should not receive the pointer down.
+ const MotionEvent secondFingerDownEvent =
+ MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .displayId(ADISPLAY_ID_DEFAULT)
+ .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
+ .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
+ .x(100)
+ .y(200))
+ .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
+ .build();
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
+ InputEventInjectionSync::WAIT_FOR_RESULT))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+
+ spy->consumeMotionPointerDown(1 /*pointerIndex*/);
+
+ // Third finger goes down outside all windows, so injection should fail.
+ const MotionEvent thirdFingerDownEvent =
+ MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .displayId(ADISPLAY_ID_DEFAULT)
+ .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
+ .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
+ .x(100)
+ .y(200))
+ .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
+ .pointer(PointerBuilder(/* id */ 2, AMOTION_EVENT_TOOL_TYPE_FINGER).x(-5).y(-5))
+ .build();
+ ASSERT_EQ(InputEventInjectionResult::FAILED,
+ injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
+ InputEventInjectionSync::WAIT_FOR_RESULT))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+
+ spy->assertNoEvents();
+ window->assertNoEvents();
+}
+
+/**
+ * After a spy window pilfers pointers, only the pointers used by the spy should be canceled
+ */
+TEST_F(InputDispatcherPilferPointersTest, PartiallyPilferRequiredPointers) {
+ auto spy = createSpy();
+ spy->setFrame(Rect(0, 0, 100, 100));
+ auto window = createForeground();
+ window->setFrame(Rect(0, 0, 200, 200));
+
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
+
+ // First finger down on the window only
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {150, 150}))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ window->consumeMotionDown();
+
+ // Second finger down on the spy and window
+ const MotionEvent secondFingerDownEvent =
+ MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .displayId(ADISPLAY_ID_DEFAULT)
+ .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
+ .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
+ .x(150)
+ .y(150))
+ .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
+ .build();
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
+ InputEventInjectionSync::WAIT_FOR_RESULT))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ spy->consumeMotionDown();
+ window->consumeMotionPointerDown(1);
+
+ // Third finger down on the spy and window
+ const MotionEvent thirdFingerDownEvent =
+ MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .displayId(ADISPLAY_ID_DEFAULT)
+ .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
+ .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)
+ .x(150)
+ .y(150))
+ .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
+ .pointer(PointerBuilder(/* id */ 2, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
+ .build();
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(mDispatcher, thirdFingerDownEvent, INJECT_EVENT_TIMEOUT,
+ InputEventInjectionSync::WAIT_FOR_RESULT))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ spy->consumeMotionPointerDown(1);
+ window->consumeMotionPointerDown(2);
+
+ // Spy window pilfers the pointers.
+ EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
+ window->consumeMotionPointerUp(/* idx */ 2, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
+ window->consumeMotionPointerUp(/* idx */ 1, ADISPLAY_ID_DEFAULT, AMOTION_EVENT_FLAG_CANCELED);
+
+ spy->assertNoEvents();
+ window->assertNoEvents();
+}
+
+/**
+ * After a spy window pilfers pointers, all pilfered pointers that have already been dispatched to
+ * other windows should be canceled. If this results in the cancellation of all pointers for some
+ * window, then that window should receive ACTION_CANCEL.
+ */
+TEST_F(InputDispatcherPilferPointersTest, PilferAllRequiredPointers) {
+ auto spy = createSpy();
+ spy->setFrame(Rect(0, 0, 100, 100));
+ auto window = createForeground();
+ window->setFrame(Rect(0, 0, 200, 200));
+
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
+
+ // First finger down on both spy and window
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {10, 10}))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ window->consumeMotionDown();
+ spy->consumeMotionDown();
+
+ // Second finger down on the spy and window
+ const MotionEvent secondFingerDownEvent =
+ MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .displayId(ADISPLAY_ID_DEFAULT)
+ .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
+ .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
+ .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER).x(50).y(50))
+ .build();
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
+ InputEventInjectionSync::WAIT_FOR_RESULT))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ spy->consumeMotionPointerDown(1);
+ window->consumeMotionPointerDown(1);
+
+ // Spy window pilfers the pointers.
+ EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
+ window->consumeMotionCancel();
+
+ spy->assertNoEvents();
+ window->assertNoEvents();
+}
+
+/**
+ * After a spy window pilfers pointers, new pointers that are not touching the spy window can still
+ * be sent to other windows
+ */
+TEST_F(InputDispatcherPilferPointersTest, CanReceivePointersAfterPilfer) {
+ auto spy = createSpy();
+ spy->setFrame(Rect(0, 0, 100, 100));
+ auto window = createForeground();
+ window->setFrame(Rect(0, 0, 200, 200));
+
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {spy, window}}});
+
+ // First finger down on both window and spy
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
+ {10, 10}))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ window->consumeMotionDown();
+ spy->consumeMotionDown();
+
+ // Spy window pilfers the pointers.
+ EXPECT_EQ(OK, mDispatcher->pilferPointers(spy->getToken()));
+ window->consumeMotionCancel();
+
+ // Second finger down on the window only
+ const MotionEvent secondFingerDownEvent =
+ MotionEventBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
+ .displayId(ADISPLAY_ID_DEFAULT)
+ .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
+ .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER).x(10).y(10))
+ .pointer(PointerBuilder(/* id */ 1, AMOTION_EVENT_TOOL_TYPE_FINGER)
+ .x(150)
+ .y(150))
+ .build();
+ ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
+ injectMotionEvent(mDispatcher, secondFingerDownEvent, INJECT_EVENT_TIMEOUT,
+ InputEventInjectionSync::WAIT_FOR_RESULT))
+ << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
+ window->consumeMotionDown();
+ window->assertNoEvents();
+
+ // TODO(b/232530217): do not send the unnecessary MOVE event and delete the next line
+ spy->consumeMotionMove();
+ spy->assertNoEvents();
+}
+
class InputDispatcherStylusInterceptorTest : public InputDispatcherTest {
public:
std::pair<sp<FakeWindowHandle>, sp<FakeWindowHandle>> setupStylusOverlayScenario() {
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 0b8eb26..67fcc40 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -373,8 +373,12 @@
mConfig.defaultPointerDisplayId = pointerDisplayId;
}
+ void setPointerGestureEnabled(bool enabled) { mConfig.pointerGesturesEnabled = enabled; }
+
float getPointerGestureMovementSpeedRatio() { return mConfig.pointerGestureMovementSpeedRatio; }
+ float getPointerGestureZoomSpeedRatio() { return mConfig.pointerGestureZoomSpeedRatio; }
+
void setVelocityControlParams(const VelocityControlParameters& params) {
mConfig.pointerVelocityControlParameters = params;
mConfig.wheelVelocityControlParameters = params;
@@ -546,7 +550,7 @@
enqueueEvent(ARBITRARY_TIME, READ_TIME, 0, EventHubInterface::FINISHED_DEVICE_SCAN, 0, 0);
}
- void addConfigurationProperty(int32_t deviceId, const String8& key, const String8& value) {
+ void addConfigurationProperty(int32_t deviceId, const char* key, const char* value) {
Device* device = getDevice(deviceId);
device->configuration.addProperty(key, value);
}
@@ -887,13 +891,13 @@
}
// Return true if the device has non-empty key layout.
- bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
+ bool markSupportedKeyCodes(int32_t deviceId, const std::vector<int32_t>& keyCodes,
uint8_t* outFlags) const override {
bool result = false;
Device* device = getDevice(deviceId);
if (device) {
result = device->keysByScanCode.size() > 0 || device->keysByUsageCode.size() > 0;
- for (size_t i = 0; i < numCodes; i++) {
+ for (size_t i = 0; i < keyCodes.size(); i++) {
for (size_t j = 0; j < device->keysByScanCode.size(); j++) {
if (keyCodes[i] == device->keysByScanCode.valueAt(j).keyCode) {
outFlags[i] = 1;
@@ -1209,9 +1213,9 @@
}
// Return true if the device has non-empty key layout.
- bool markSupportedKeyCodes(uint32_t, size_t numCodes, const int32_t* keyCodes,
+ bool markSupportedKeyCodes(uint32_t, const std::vector<int32_t>& keyCodes,
uint8_t* outFlags) override {
- for (size_t i = 0; i < numCodes; i++) {
+ for (size_t i = 0; i < keyCodes.size(); i++) {
for (size_t j = 0; j < mSupportedKeyCodes.size(); j++) {
if (keyCodes[i] == mSupportedKeyCodes[j]) {
outFlags[i] = 1;
@@ -1855,34 +1859,37 @@
mapper.addSupportedKeyCode(AKEYCODE_A);
mapper.addSupportedKeyCode(AKEYCODE_B);
- const int32_t keyCodes[4] = { AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2 };
+ const std::vector<int32_t> keyCodes{AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2};
uint8_t flags[4] = { 0, 0, 0, 1 };
- ASSERT_FALSE(mReader->hasKeys(0, AINPUT_SOURCE_ANY, 4, keyCodes, flags))
+ ASSERT_FALSE(mReader->hasKeys(0, AINPUT_SOURCE_ANY, keyCodes, flags))
<< "Should return false when device id is >= 0 but unknown.";
ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
flags[3] = 1;
- ASSERT_FALSE(mReader->hasKeys(deviceId, AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
+ ASSERT_FALSE(mReader->hasKeys(deviceId, AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
<< "Should return false when device id is valid but the sources are not supported by "
"the device.";
ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
flags[3] = 1;
- ASSERT_TRUE(mReader->hasKeys(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, 4,
+ ASSERT_TRUE(mReader->hasKeys(deviceId, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL,
keyCodes, flags))
<< "Should return value provided by mapper when device id is valid and the device "
"supports some of the sources.";
ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
flags[3] = 1;
- ASSERT_FALSE(mReader->hasKeys(-1, AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
- << "Should return false when the device id is < 0 but the sources are not supported by any device.";
+ ASSERT_FALSE(mReader->hasKeys(-1, AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
+ << "Should return false when the device id is < 0 but the sources are not supported by "
+ "any device.";
ASSERT_TRUE(!flags[0] && !flags[1] && !flags[2] && !flags[3]);
flags[3] = 1;
- ASSERT_TRUE(mReader->hasKeys(-1, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
- << "Should return value provided by mapper when device id is < 0 and one of the devices supports some of the sources.";
+ ASSERT_TRUE(
+ mReader->hasKeys(-1, AINPUT_SOURCE_KEYBOARD | AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
+ << "Should return value provided by mapper when device id is < 0 and one of the "
+ "devices supports some of the sources.";
ASSERT_TRUE(flags[0] && flags[1] && !flags[2] && !flags[3]);
}
@@ -2718,9 +2725,9 @@
ASSERT_EQ(AKEY_STATE_UNKNOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 0))
<< "Ignored device should return unknown switch state.";
- const int32_t keyCodes[2] = { AKEYCODE_A, AKEYCODE_B };
+ const std::vector<int32_t> keyCodes{AKEYCODE_A, AKEYCODE_B};
uint8_t flags[2] = { 0, 1 };
- ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, 2, keyCodes, flags))
+ ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, keyCodes, flags))
<< "Ignored device should never mark any key codes.";
ASSERT_EQ(0, flags[0]) << "Flag for unsupported key should be unchanged.";
ASSERT_EQ(1, flags[1]) << "Flag for unsupported key should be unchanged.";
@@ -2728,7 +2735,7 @@
TEST_F(InputDeviceTest, WhenMappersAreRegistered_DeviceIsNotIgnoredAndForwardsRequestsToMappers) {
// Configuration.
- mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, String8("key"), String8("value"));
+ mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, "key", "value");
FakeInputMapper& mapper1 =
mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, AINPUT_SOURCE_KEYBOARD);
@@ -2749,10 +2756,10 @@
InputReaderConfiguration config;
mDevice->configure(ARBITRARY_TIME, &config, 0);
- String8 propertyValue;
- ASSERT_TRUE(mDevice->getConfiguration().tryGetProperty(String8("key"), propertyValue))
+ std::string propertyValue;
+ ASSERT_TRUE(mDevice->getConfiguration().tryGetProperty("key", propertyValue))
<< "Device should have read configuration during configuration phase.";
- ASSERT_STREQ("value", propertyValue.string());
+ ASSERT_EQ("value", propertyValue);
ASSERT_NO_FATAL_FAILURE(mapper1.assertConfigureWasCalled());
ASSERT_NO_FATAL_FAILURE(mapper2.assertConfigureWasCalled());
@@ -2795,16 +2802,16 @@
ASSERT_EQ(AKEY_STATE_DOWN, mDevice->getSwitchState(AINPUT_SOURCE_KEYBOARD, 4))
<< "Should query mapper when source is supported.";
- const int32_t keyCodes[4] = { AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2 };
+ const std::vector<int32_t> keyCodes{AKEYCODE_A, AKEYCODE_B, AKEYCODE_1, AKEYCODE_2};
uint8_t flags[4] = { 0, 0, 0, 1 };
- ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_TRACKBALL, 4, keyCodes, flags))
+ ASSERT_FALSE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_TRACKBALL, keyCodes, flags))
<< "Should do nothing when source is unsupported.";
ASSERT_EQ(0, flags[0]) << "Flag should be unchanged when source is unsupported.";
ASSERT_EQ(0, flags[1]) << "Flag should be unchanged when source is unsupported.";
ASSERT_EQ(0, flags[2]) << "Flag should be unchanged when source is unsupported.";
ASSERT_EQ(1, flags[3]) << "Flag should be unchanged when source is unsupported.";
- ASSERT_TRUE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, 4, keyCodes, flags))
+ ASSERT_TRUE(mDevice->markSupportedKeyCodes(AINPUT_SOURCE_KEYBOARD, keyCodes, flags))
<< "Should query mapper when source is supported.";
ASSERT_EQ(1, flags[0]) << "Flag for supported key should be set.";
ASSERT_EQ(1, flags[1]) << "Flag for supported key should be set.";
@@ -2950,7 +2957,7 @@
}
void addConfigurationProperty(const char* key, const char* value) {
- mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, String8(key), String8(value));
+ mFakeEventHub->addConfigurationProperty(EVENTHUB_ID, key, value);
}
void configureDevice(uint32_t changes) {
@@ -3726,9 +3733,8 @@
mFakeEventHub->addKey(EVENTHUB_ID, KEY_A, 0, AKEYCODE_A, 0);
- const int32_t keyCodes[2] = { AKEYCODE_A, AKEYCODE_B };
uint8_t flags[2] = { 0, 0 };
- ASSERT_TRUE(mapper.markSupportedKeyCodes(AINPUT_SOURCE_ANY, 1, keyCodes, flags));
+ ASSERT_TRUE(mapper.markSupportedKeyCodes(AINPUT_SOURCE_ANY, {AKEYCODE_A, AKEYCODE_B}, flags));
ASSERT_TRUE(flags[0]);
ASSERT_FALSE(flags[1]);
}
@@ -5405,9 +5411,9 @@
prepareVirtualKeys();
SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
- const int32_t keys[2] = { AKEYCODE_HOME, AKEYCODE_A };
uint8_t flags[2] = { 0, 0 };
- ASSERT_TRUE(mapper.markSupportedKeyCodes(AINPUT_SOURCE_ANY, 2, keys, flags));
+ ASSERT_TRUE(
+ mapper.markSupportedKeyCodes(AINPUT_SOURCE_ANY, {AKEYCODE_HOME, AKEYCODE_A}, flags));
ASSERT_TRUE(flags[0]);
ASSERT_FALSE(flags[1]);
}
@@ -9462,6 +9468,258 @@
ASSERT_EQ(AINPUT_SOURCE_TOUCHPAD, mapper.getSources());
}
+class MultiTouchPointerModeTest : public MultiTouchInputMapperTest {
+protected:
+ float mPointerMovementScale;
+ float mPointerXZoomScale;
+ void preparePointerMode(int xAxisResolution, int yAxisResolution) {
+ addConfigurationProperty("touch.deviceType", "pointer");
+ std::shared_ptr<FakePointerController> fakePointerController =
+ std::make_shared<FakePointerController>();
+ fakePointerController->setBounds(0, 0, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - 1);
+ fakePointerController->setPosition(0, 0);
+ fakePointerController->setButtonState(0);
+ prepareDisplay(DISPLAY_ORIENTATION_0);
+
+ prepareAxes(POSITION);
+ prepareAbsoluteAxisResolution(xAxisResolution, yAxisResolution);
+ // In order to enable swipe and freeform gesture in pointer mode, pointer capture
+ // needs to be disabled, and the pointer gesture needs to be enabled.
+ mFakePolicy->setPointerCapture(false);
+ mFakePolicy->setPointerGestureEnabled(true);
+ mFakePolicy->setPointerController(fakePointerController);
+
+ float rawDiagonal = hypotf(RAW_X_MAX - RAW_X_MIN, RAW_Y_MAX - RAW_Y_MIN);
+ float displayDiagonal = hypotf(DISPLAY_WIDTH, DISPLAY_HEIGHT);
+ mPointerMovementScale =
+ mFakePolicy->getPointerGestureMovementSpeedRatio() * displayDiagonal / rawDiagonal;
+ mPointerXZoomScale =
+ mFakePolicy->getPointerGestureZoomSpeedRatio() * displayDiagonal / rawDiagonal;
+ }
+
+ void prepareAbsoluteAxisResolution(int xAxisResolution, int yAxisResolution) {
+ mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_X, RAW_X_MIN, RAW_X_MAX,
+ /*flat*/ 0,
+ /*fuzz*/ 0, /*resolution*/ xAxisResolution);
+ mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_MT_POSITION_Y, RAW_Y_MIN, RAW_Y_MAX,
+ /*flat*/ 0,
+ /*fuzz*/ 0, /*resolution*/ yAxisResolution);
+ }
+};
+
+/**
+ * Two fingers down on a pointer mode touch pad. The width
+ * of the two finger is larger than 1/4 of the touch pack diagnal length. However, it
+ * is smaller than the fixed min physical length 30mm. Two fingers' distance must
+ * be greater than the both value to be freeform gesture, so that after two
+ * fingers start to move downwards, the gesture should be swipe.
+ */
+TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthSwipe) {
+ // The min freeform gesture width is 25units/mm x 30mm = 750
+ // which is greater than fraction of the diagnal length of the touchpad (349).
+ // Thus, MaxSwipWidth is 750.
+ preparePointerMode(25 /*xResolution*/, 25 /*yResolution*/);
+ MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ NotifyMotionArgs motionArgs;
+
+ // Two fingers down at once.
+ // The two fingers are 450 units apart, expects the current gesture to be PRESS
+ // Pointer's initial position is used the [0,0] coordinate.
+ int32_t x1 = 100, y1 = 125, x2 = 550, y2 = 125;
+
+ processId(mapper, FIRST_TRACKING_ID);
+ processPosition(mapper, x1, y1);
+ processMTSync(mapper);
+ processId(mapper, SECOND_TRACKING_ID);
+ processPosition(mapper, x2, y2);
+ processMTSync(mapper);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ 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_NO_FATAL_FAILURE(
+ assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
+
+ // It should be recognized as a SWIPE gesture when two fingers start to move down,
+ // that there should be 1 pointer.
+ int32_t movingDistance = 200;
+ y1 += movingDistance;
+ y2 += movingDistance;
+
+ processId(mapper, FIRST_TRACKING_ID);
+ processPosition(mapper, x1, y1);
+ processMTSync(mapper);
+ processId(mapper, SECOND_TRACKING_ID);
+ processPosition(mapper, x2, y2);
+ processMTSync(mapper);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ 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_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], 0,
+ movingDistance * mPointerMovementScale, 1, 0, 0, 0,
+ 0, 0, 0, 0));
+}
+
+/**
+ * Two fingers down on a pointer mode touch pad. The width of the two finger is larger
+ * than the minimum freeform gesture width, 30mm. However, it is smaller than 1/4 of
+ * the touch pack diagnal length. Two fingers' distance must be greater than the both
+ * value to be freeform gesture, so that after two fingers start to move downwards,
+ * the gesture should be swipe.
+ */
+TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthLowResolutionSwipe) {
+ // The min freeform gesture width is 5units/mm x 30mm = 150
+ // which is greater than fraction of the diagnal length of the touchpad (349).
+ // Thus, MaxSwipWidth is the fraction of the diagnal length, 349.
+ preparePointerMode(5 /*xResolution*/, 5 /*yResolution*/);
+ MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+ NotifyMotionArgs motionArgs;
+
+ // Two fingers down at once.
+ // The two fingers are 250 units apart, expects the current gesture to be PRESS
+ // Pointer's initial position is used the [0,0] coordinate.
+ int32_t x1 = 100, y1 = 125, x2 = 350, y2 = 125;
+
+ processId(mapper, FIRST_TRACKING_ID);
+ processPosition(mapper, x1, y1);
+ processMTSync(mapper);
+ processId(mapper, SECOND_TRACKING_ID);
+ processPosition(mapper, x2, y2);
+ processMTSync(mapper);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ 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_NO_FATAL_FAILURE(
+ assertPointerCoords(motionArgs.pointerCoords[0], 0, 0, 1, 0, 0, 0, 0, 0, 0, 0));
+
+ // It should be recognized as a SWIPE gesture when two fingers start to move down,
+ // and there should be 1 pointer.
+ int32_t movingDistance = 200;
+ y1 += movingDistance;
+ y2 += movingDistance;
+
+ processId(mapper, FIRST_TRACKING_ID);
+ processPosition(mapper, x1, y1);
+ processMTSync(mapper);
+ processId(mapper, SECOND_TRACKING_ID);
+ processPosition(mapper, x2, y2);
+ processMTSync(mapper);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(1U, motionArgs.pointerCount);
+ ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
+ // 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,
+ 0, 0, 0, 0));
+}
+
+/**
+ * Touch the touch pad with two fingers with a distance wider than the minimum freeform
+ * gesture width and 1/4 of the diagnal length of the touchpad. Expect to receive
+ * freeform gestures after two fingers start to move downwards.
+ */
+TEST_F(MultiTouchPointerModeTest, PointerGestureMaxSwipeWidthFreeform) {
+ preparePointerMode(25 /*xResolution*/, 25 /*yResolution*/);
+ MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+
+ NotifyMotionArgs motionArgs;
+
+ // Two fingers down at once. Wider than the max swipe width.
+ // The gesture is expected to be PRESS, then transformed to FREEFORM
+ int32_t x1 = 100, y1 = 125, x2 = 900, y2 = 125;
+
+ processId(mapper, FIRST_TRACKING_ID);
+ processPosition(mapper, x1, y1);
+ processMTSync(mapper);
+ processId(mapper, SECOND_TRACKING_ID);
+ processPosition(mapper, x2, y2);
+ processMTSync(mapper);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(1U, motionArgs.pointerCount);
+ ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
+ // 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));
+
+ int32_t movingDistance = 200;
+
+ // Move two fingers down, expect a cancel event because gesture is changing to freeform,
+ // then two down events for two pointers.
+ y1 += movingDistance;
+ y2 += movingDistance;
+
+ processId(mapper, FIRST_TRACKING_ID);
+ processPosition(mapper, x1, y1);
+ processMTSync(mapper);
+ processId(mapper, SECOND_TRACKING_ID);
+ processPosition(mapper, x2, y2);
+ processMTSync(mapper);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ // The previous PRESS gesture is cancelled, because it is transformed to freeform
+ ASSERT_EQ(1U, motionArgs.pointerCount);
+ ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
+ ASSERT_EQ(1U, motionArgs.pointerCount);
+ 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(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);
+ // 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;
+ float cookedX2 = (x2 - x1) / 2 * mPointerXZoomScale;
+ // When pointers move, the new coordinates equal to the initial coordinates plus
+ // scaled moving distance.
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], cookedX1,
+ movingDistance * mPointerMovementScale, 1, 0, 0, 0,
+ 0, 0, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], cookedX2,
+ movingDistance * mPointerMovementScale, 1, 0, 0, 0,
+ 0, 0, 0, 0));
+
+ // Move two fingers down again, expect one MOVE motion event.
+ y1 += movingDistance;
+ y2 += movingDistance;
+
+ processId(mapper, FIRST_TRACKING_ID);
+ processPosition(mapper, x1, y1);
+ processMTSync(mapper);
+ processId(mapper, SECOND_TRACKING_ID);
+ processPosition(mapper, x2, y2);
+ processMTSync(mapper);
+ processSync(mapper);
+
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
+ 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_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[0], cookedX1,
+ movingDistance * 2 * mPointerMovementScale, 1, 0, 0,
+ 0, 0, 0, 0, 0));
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(motionArgs.pointerCoords[1], cookedX2,
+ movingDistance * 2 * mPointerMovementScale, 1, 0, 0,
+ 0, 0, 0, 0, 0));
+}
+
// --- JoystickInputMapperTest ---
class JoystickInputMapperTest : public InputMapperTest {
diff --git a/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp b/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp
index 0062f42..7f14b94 100644
--- a/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp
+++ b/services/inputflinger/tests/UnwantedInteractionBlocker_test.cpp
@@ -47,6 +47,10 @@
constexpr int UP = AMOTION_EVENT_ACTION_UP;
constexpr int CANCEL = AMOTION_EVENT_ACTION_CANCEL;
+static nsecs_t toNs(std::chrono::nanoseconds duration) {
+ return duration.count();
+}
+
struct PointerData {
float x;
float y;
@@ -630,41 +634,41 @@
*/
TEST_F(PalmRejectorTest, TwoPointersAreCanceled) {
std::vector<NotifyMotionArgs> argsList;
- constexpr nsecs_t downTime = 255955749837000;
+ const nsecs_t downTime = toNs(0ms);
mPalmRejector->processMotion(
generateMotionArgs(downTime, downTime, DOWN, {{1342.0, 613.0, 79.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955759313000, MOVE, {{1406.0, 650.0, 52.0}}));
+ generateMotionArgs(downTime, toNs(8ms), MOVE, {{1406.0, 650.0, 52.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955766361000, MOVE, {{1429.0, 672.0, 46.0}}));
+ generateMotionArgs(downTime, toNs(16ms), MOVE, {{1429.0, 672.0, 46.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955775989000, MOVE, {{1417.0, 685.0, 41.0}}));
+ generateMotionArgs(downTime, toNs(24ms), MOVE, {{1417.0, 685.0, 41.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955775989000, POINTER_1_DOWN,
+ generateMotionArgs(downTime, toNs(32ms), POINTER_1_DOWN,
{{1417.0, 685.0, 41.0}, {1062.0, 697.0, 10.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955783039000, MOVE,
+ generateMotionArgs(downTime, toNs(40ms), MOVE,
{{1414.0, 702.0, 41.0}, {1059.0, 731.0, 12.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955792536000, MOVE,
+ generateMotionArgs(downTime, toNs(48ms), MOVE,
{{1415.0, 719.0, 44.0}, {1060.0, 760.0, 11.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955799474000, MOVE,
+ generateMotionArgs(downTime, toNs(56ms), MOVE,
{{1421.0, 733.0, 42.0}, {1065.0, 769.0, 13.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955809177000, MOVE,
+ generateMotionArgs(downTime, toNs(64ms), MOVE,
{{1426.0, 742.0, 43.0}, {1068.0, 771.0, 13.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955816131000, MOVE,
+ generateMotionArgs(downTime, toNs(72ms), MOVE,
{{1430.0, 748.0, 45.0}, {1069.0, 772.0, 13.0}}));
argsList = mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955825907000, MOVE,
+ generateMotionArgs(downTime, toNs(80ms), MOVE,
{{1432.0, 750.0, 44.0}, {1069.0, 772.0, 13.0}}));
ASSERT_EQ(1u, argsList.size());
ASSERT_EQ(0 /* No FLAG_CANCELED */, argsList[0].flags);
argsList = mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955832736000, MOVE,
+ generateMotionArgs(downTime, toNs(88ms), MOVE,
{{1433.0, 751.0, 44.0}, {1070.0, 771.0, 13.0}}));
ASSERT_EQ(2u, argsList.size());
ASSERT_EQ(POINTER_0_UP, argsList[0].action);
@@ -674,94 +678,94 @@
ASSERT_EQ(0, argsList[1].flags);
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955842432000, MOVE,
+ generateMotionArgs(downTime, toNs(96ms), MOVE,
{{1433.0, 751.0, 42.0}, {1071.0, 770.0, 13.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955849380000, MOVE,
+ generateMotionArgs(downTime, toNs(104ms), MOVE,
{{1433.0, 751.0, 45.0}, {1072.0, 769.0, 13.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955859046000, MOVE,
+ generateMotionArgs(downTime, toNs(112ms), MOVE,
{{1433.0, 751.0, 43.0}, {1072.0, 768.0, 13.0}}));
argsList = mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955869823000, MOVE,
+ generateMotionArgs(downTime, toNs(120ms), MOVE,
{{1433.0, 751.0, 45.0}, {1072.0, 767.0, 13.0}}));
ASSERT_EQ(1u, argsList.size());
ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, argsList[0].action);
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955875641000, MOVE,
+ generateMotionArgs(downTime, toNs(128ms), MOVE,
{{1433.0, 751.0, 43.0}, {1072.0, 766.0, 13.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955882693000, MOVE,
+ generateMotionArgs(downTime, toNs(136ms), MOVE,
{{1433.0, 750.0, 44.0}, {1072.0, 765.0, 13.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955892324000, MOVE,
+ generateMotionArgs(downTime, toNs(144ms), MOVE,
{{1433.0, 750.0, 42.0}, {1072.0, 763.0, 14.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955899425000, MOVE,
+ generateMotionArgs(downTime, toNs(152ms), MOVE,
{{1434.0, 750.0, 44.0}, {1073.0, 761.0, 14.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955909400000, MOVE,
+ generateMotionArgs(downTime, toNs(160ms), MOVE,
{{1435.0, 750.0, 43.0}, {1073.0, 759.0, 15.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955915885000, MOVE,
+ generateMotionArgs(downTime, toNs(168ms), MOVE,
{{1436.0, 750.0, 45.0}, {1074.0, 757.0, 15.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955925607000, MOVE,
+ generateMotionArgs(downTime, toNs(176ms), MOVE,
{{1436.0, 750.0, 44.0}, {1074.0, 755.0, 15.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955932580000, MOVE,
+ generateMotionArgs(downTime, toNs(184ms), MOVE,
{{1436.0, 750.0, 45.0}, {1074.0, 753.0, 15.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955942231000, MOVE,
+ generateMotionArgs(downTime, toNs(192ms), MOVE,
{{1436.0, 749.0, 44.0}, {1074.0, 751.0, 15.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955949204000, MOVE,
+ generateMotionArgs(downTime, toNs(200ms), MOVE,
{{1435.0, 748.0, 45.0}, {1074.0, 749.0, 15.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955959103000, MOVE,
+ generateMotionArgs(downTime, toNs(208ms), MOVE,
{{1434.0, 746.0, 44.0}, {1074.0, 747.0, 14.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955965884000, MOVE,
+ generateMotionArgs(downTime, toNs(216ms), MOVE,
{{1433.0, 744.0, 44.0}, {1075.0, 745.0, 14.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955975649000, MOVE,
+ generateMotionArgs(downTime, toNs(224ms), MOVE,
{{1431.0, 741.0, 43.0}, {1075.0, 742.0, 13.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955982537000, MOVE,
+ generateMotionArgs(downTime, toNs(232ms), MOVE,
{{1428.0, 738.0, 43.0}, {1076.0, 739.0, 12.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955992284000, MOVE,
+ generateMotionArgs(downTime, toNs(240ms), MOVE,
{{1400.0, 726.0, 54.0}, {1076.0, 739.0, 13.0}}));
argsList = mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955999348000, POINTER_1_UP,
+ generateMotionArgs(downTime, toNs(248ms), POINTER_1_UP,
{{1362.0, 716.0, 55.0}, {1076.0, 739.0, 13.0}}));
ASSERT_TRUE(argsList.empty());
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255955999348000, MOVE, {{1362.0, 716.0, 55.0}}));
+ generateMotionArgs(downTime, toNs(256ms), MOVE, {{1362.0, 716.0, 55.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255956008885000, MOVE, {{1347.0, 707.0, 54.0}}));
+ generateMotionArgs(downTime, toNs(264ms), MOVE, {{1347.0, 707.0, 54.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255956015791000, MOVE, {{1340.0, 698.0, 54.0}}));
+ generateMotionArgs(downTime, toNs(272ms), MOVE, {{1340.0, 698.0, 54.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255956025804000, MOVE, {{1338.0, 694.0, 55.0}}));
+ generateMotionArgs(downTime, toNs(280ms), MOVE, {{1338.0, 694.0, 55.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255956032314000, MOVE, {{1336.0, 690.0, 53.0}}));
+ generateMotionArgs(downTime, toNs(288ms), MOVE, {{1336.0, 690.0, 53.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255956042329000, MOVE, {{1334.0, 685.0, 47.0}}));
+ generateMotionArgs(downTime, toNs(296ms), MOVE, {{1334.0, 685.0, 47.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255956048979000, MOVE, {{1333.0, 679.0, 46.0}}));
+ generateMotionArgs(downTime, toNs(304ms), MOVE, {{1333.0, 679.0, 46.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255956058813000, MOVE, {{1332.0, 672.0, 45.0}}));
+ generateMotionArgs(downTime, toNs(312ms), MOVE, {{1332.0, 672.0, 45.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255956065592000, MOVE, {{1333.0, 666.0, 40.0}}));
+ generateMotionArgs(downTime, toNs(320ms), MOVE, {{1333.0, 666.0, 40.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255956075276000, MOVE, {{1336.0, 661.0, 24.0}}));
+ generateMotionArgs(downTime, toNs(328ms), MOVE, {{1336.0, 661.0, 24.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255956082198000, MOVE, {{1338.0, 656.0, 16.0}}));
+ generateMotionArgs(downTime, toNs(336ms), MOVE, {{1338.0, 656.0, 16.0}}));
mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255956092059000, MOVE, {{1341.0, 649.0, 1.0}}));
+ generateMotionArgs(downTime, toNs(344ms), MOVE, {{1341.0, 649.0, 1.0}}));
argsList = mPalmRejector->processMotion(
- generateMotionArgs(downTime, 255956098764000, UP, {{1341.0, 649.0, 1.0}}));
+ generateMotionArgs(downTime, toNs(352ms), UP, {{1341.0, 649.0, 1.0}}));
ASSERT_TRUE(argsList.empty());
}
diff --git a/services/stats/Android.bp b/services/stats/Android.bp
index 7fea616..7d358e1 100644
--- a/services/stats/Android.bp
+++ b/services/stats/Android.bp
@@ -13,10 +13,13 @@
"StatsAidl.cpp",
"StatsHal.cpp",
],
- cflags: ["-Wall", "-Werror"],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
shared_libs: [
"android.frameworks.stats@1.0",
- "android.frameworks.stats-V1-ndk",
+ "android.frameworks.stats-V2-ndk",
"libbinder_ndk",
"libhidlbase",
"liblog",
@@ -29,10 +32,12 @@
],
export_shared_lib_headers: [
"android.frameworks.stats@1.0",
- "android.frameworks.stats-V1-ndk",
+ "android.frameworks.stats-V2-ndk",
],
local_include_dirs: [
"include/stats",
],
- vintf_fragments: ["android.frameworks.stats@1.0-service.xml"]
+ vintf_fragments: [
+ "android.frameworks.stats-service.xml",
+ ],
}
diff --git a/services/stats/StatsAidl.cpp b/services/stats/StatsAidl.cpp
index a3b68f1..8d6a9bd 100644
--- a/services/stats/StatsAidl.cpp
+++ b/services/stats/StatsAidl.cpp
@@ -62,6 +62,10 @@
AStatsEvent_writeString(event,
atomValue.get<VendorAtomValue::stringValue>().c_str());
break;
+ case VendorAtomValue::boolValue:
+ AStatsEvent_writeBool(event,
+ atomValue.get<VendorAtomValue::boolValue>());
+ break;
}
}
AStatsEvent_build(event);
diff --git a/services/stats/android.frameworks.stats@1.0-service.xml b/services/stats/android.frameworks.stats-service.xml
similarity index 93%
rename from services/stats/android.frameworks.stats@1.0-service.xml
rename to services/stats/android.frameworks.stats-service.xml
index c564b7b..7e2635e 100644
--- a/services/stats/android.frameworks.stats@1.0-service.xml
+++ b/services/stats/android.frameworks.stats-service.xml
@@ -11,7 +11,7 @@
<hal format="aidl">
<name>android.frameworks.stats</name>
- <version>1</version>
+ <version>2</version>
<fqname>IStats/default</fqname>
</hal>
</manifest>
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index cbb95f9..eb17995 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -142,8 +142,6 @@
srcs: [
"BackgroundExecutor.cpp",
"BufferLayer.cpp",
- "BufferLayerConsumer.cpp",
- "BufferQueueLayer.cpp",
"BufferStateLayer.cpp",
"ClientCache.cpp",
"Client.cpp",
@@ -169,10 +167,8 @@
"WindowInfosListenerInvoker.cpp",
"Layer.cpp",
"LayerProtoHelper.cpp",
- "LayerRejecter.cpp",
"LayerRenderArea.cpp",
"LayerVector.cpp",
- "MonitoredProducer.cpp",
"NativeWindowSurface.cpp",
"RefreshRateOverlay.cpp",
"RegionSamplingThread.cpp",
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index d9c89cd..dd918c5 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -37,6 +37,7 @@
#include <gui/GLConsumer.h>
#include <gui/LayerDebugInfo.h>
#include <gui/Surface.h>
+#include <gui/TraceUtils.h>
#include <renderengine/RenderEngine.h>
#include <ui/DebugUtils.h>
#include <utils/Errors.h>
@@ -53,7 +54,6 @@
#include "Colorizer.h"
#include "DisplayDevice.h"
#include "FrameTracer/FrameTracer.h"
-#include "LayerRejecter.h"
#include "TimeStats/TimeStats.h"
namespace android {
@@ -457,7 +457,8 @@
bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
nsecs_t expectedPresentTime) {
- ATRACE_CALL();
+ ATRACE_FORMAT_INSTANT("latchBuffer %s - %" PRIu64, getDebugName(),
+ getDrawingState().frameNumber);
bool refreshRequired = latchSidebandStream(recomputeVisibleRegions);
@@ -738,10 +739,14 @@
}
void BufferLayer::getDrawingTransformMatrix(bool filteringEnabled, float outMatrix[16]) {
- GLConsumer::computeTransformMatrix(outMatrix,
- mBufferInfo.mBuffer ? mBufferInfo.mBuffer->getBuffer()
- : nullptr,
- mBufferInfo.mCrop, mBufferInfo.mTransform, filteringEnabled);
+ sp<GraphicBuffer> buffer = getBuffer();
+ if (!buffer) {
+ ALOGE("Buffer should not be null!");
+ return;
+ }
+ GLConsumer::computeTransformMatrix(outMatrix, buffer->getWidth(), buffer->getHeight(),
+ buffer->getPixelFormat(), mBufferInfo.mCrop,
+ mBufferInfo.mTransform, filteringEnabled);
}
void BufferLayer::setInitialValuesForClone(const sp<Layer>& clonedFrom) {
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index 4c70eb5..7cc67a2 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -20,7 +20,7 @@
#include <cstdint>
#include <list>
-#include <gui/ISurfaceComposerClient.h>
+#include <android/gui/ISurfaceComposerClient.h>
#include <gui/LayerState.h>
#include <renderengine/Image.h>
#include <renderengine/Mesh.h>
@@ -34,14 +34,12 @@
#include <utils/String8.h>
#include <utils/Timers.h>
-#include "BufferLayerConsumer.h"
#include "Client.h"
#include "DisplayHardware/HWComposer.h"
#include "FrameTimeline.h"
#include "FrameTracker.h"
#include "Layer.h"
#include "LayerVector.h"
-#include "MonitoredProducer.h"
#include "SurfaceFlinger.h"
namespace android {
diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp
deleted file mode 100644
index 7361a4f..0000000
--- a/services/surfaceflinger/BufferLayerConsumer.cpp
+++ /dev/null
@@ -1,500 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-
-#undef LOG_TAG
-#define LOG_TAG "BufferLayerConsumer"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-//#define LOG_NDEBUG 0
-
-#include "BufferLayerConsumer.h"
-#include "Layer.h"
-#include "Scheduler/VsyncController.h"
-
-#include <inttypes.h>
-
-#include <cutils/compiler.h>
-
-#include <hardware/hardware.h>
-
-#include <math/mat4.h>
-
-#include <gui/BufferItem.h>
-#include <gui/GLConsumer.h>
-#include <gui/ISurfaceComposer.h>
-#include <gui/SurfaceComposerClient.h>
-#include <private/gui/ComposerService.h>
-#include <renderengine/RenderEngine.h>
-#include <renderengine/impl/ExternalTexture.h>
-#include <utils/Log.h>
-#include <utils/String8.h>
-#include <utils/Trace.h>
-
-namespace android {
-
-// Macros for including the BufferLayerConsumer name in log messages
-#define BLC_LOGV(x, ...) ALOGV("[%s] " x, mName.string(), ##__VA_ARGS__)
-#define BLC_LOGD(x, ...) ALOGD("[%s] " x, mName.string(), ##__VA_ARGS__)
-//#define BLC_LOGI(x, ...) ALOGI("[%s] " x, mName.string(), ##__VA_ARGS__)
-#define BLC_LOGW(x, ...) ALOGW("[%s] " x, mName.string(), ##__VA_ARGS__)
-#define BLC_LOGE(x, ...) ALOGE("[%s] " x, mName.string(), ##__VA_ARGS__)
-
-static const mat4 mtxIdentity;
-
-BufferLayerConsumer::BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq,
- renderengine::RenderEngine& engine, uint32_t tex,
- Layer* layer)
- : ConsumerBase(bq, false),
- mCurrentCrop(Rect::EMPTY_RECT),
- mCurrentTransform(0),
- mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
- mCurrentFence(Fence::NO_FENCE),
- mCurrentTimestamp(0),
- mCurrentDataSpace(ui::Dataspace::UNKNOWN),
- mCurrentFrameNumber(0),
- mCurrentTransformToDisplayInverse(false),
- mCurrentSurfaceDamage(),
- mCurrentApi(0),
- mDefaultWidth(1),
- mDefaultHeight(1),
- mFilteringEnabled(true),
- mRE(engine),
- mTexName(tex),
- mLayer(layer),
- mCurrentTexture(BufferQueue::INVALID_BUFFER_SLOT) {
- BLC_LOGV("BufferLayerConsumer");
-
- memcpy(mCurrentTransformMatrix, mtxIdentity.asArray(), sizeof(mCurrentTransformMatrix));
-
- mConsumer->setConsumerUsageBits(DEFAULT_USAGE_FLAGS);
-}
-
-status_t BufferLayerConsumer::setDefaultBufferSize(uint32_t w, uint32_t h) {
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- BLC_LOGE("setDefaultBufferSize: BufferLayerConsumer is abandoned!");
- return NO_INIT;
- }
- mDefaultWidth = w;
- mDefaultHeight = h;
- return mConsumer->setDefaultBufferSize(w, h);
-}
-
-void BufferLayerConsumer::setContentsChangedListener(const wp<ContentsChangedListener>& listener) {
- setFrameAvailableListener(listener);
- Mutex::Autolock lock(mMutex);
- mContentsChangedListener = listener;
-}
-
-status_t BufferLayerConsumer::updateTexImage(BufferRejecter* rejecter, nsecs_t expectedPresentTime,
- bool* autoRefresh, bool* queuedBuffer,
- uint64_t maxFrameNumber) {
- ATRACE_CALL();
- BLC_LOGV("updateTexImage");
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- BLC_LOGE("updateTexImage: BufferLayerConsumer is abandoned!");
- return NO_INIT;
- }
-
- BufferItem item;
-
- // Acquire the next buffer.
- // In asynchronous mode the list is guaranteed to be one buffer
- // deep, while in synchronous mode we use the oldest buffer.
- status_t err = acquireBufferLocked(&item, expectedPresentTime, maxFrameNumber);
- if (err != NO_ERROR) {
- if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
- err = NO_ERROR;
- } else if (err == BufferQueue::PRESENT_LATER) {
- // return the error, without logging
- } else {
- BLC_LOGE("updateTexImage: acquire failed: %s (%d)", strerror(-err), err);
- }
- return err;
- }
-
- if (autoRefresh) {
- *autoRefresh = item.mAutoRefresh;
- }
-
- if (queuedBuffer) {
- *queuedBuffer = item.mQueuedBuffer;
- }
-
- // We call the rejecter here, in case the caller has a reason to
- // not accept this buffer. This is used by SurfaceFlinger to
- // reject buffers which have the wrong size
- int slot = item.mSlot;
- if (rejecter && rejecter->reject(mSlots[slot].mGraphicBuffer, item)) {
- releaseBufferLocked(slot, mSlots[slot].mGraphicBuffer);
- return BUFFER_REJECTED;
- }
-
- // Release the previous buffer.
- err = updateAndReleaseLocked(item, &mPendingRelease);
- if (err != NO_ERROR) {
- return err;
- }
- return err;
-}
-
-void BufferLayerConsumer::setReleaseFence(const sp<Fence>& fence) {
- if (!fence->isValid()) {
- return;
- }
-
- auto slot = mPendingRelease.isPending ? mPendingRelease.currentTexture : mCurrentTexture;
- if (slot == BufferQueue::INVALID_BUFFER_SLOT) {
- return;
- }
-
- auto buffer = mPendingRelease.isPending ? mPendingRelease.graphicBuffer
- : mCurrentTextureBuffer->getBuffer();
- auto err = addReleaseFence(slot, buffer, fence);
- if (err != OK) {
- BLC_LOGE("setReleaseFence: failed to add the fence: %s (%d)", strerror(-err), err);
- }
-}
-
-bool BufferLayerConsumer::releasePendingBuffer() {
- if (!mPendingRelease.isPending) {
- BLC_LOGV("Pending buffer already released");
- return false;
- }
- BLC_LOGV("Releasing pending buffer");
- Mutex::Autolock lock(mMutex);
- status_t result =
- releaseBufferLocked(mPendingRelease.currentTexture, mPendingRelease.graphicBuffer);
- if (result < NO_ERROR) {
- BLC_LOGE("releasePendingBuffer failed: %s (%d)", strerror(-result), result);
- }
- mPendingRelease = PendingRelease();
- return true;
-}
-
-sp<Fence> BufferLayerConsumer::getPrevFinalReleaseFence() const {
- Mutex::Autolock lock(mMutex);
- return ConsumerBase::mPrevFinalReleaseFence;
-}
-
-status_t BufferLayerConsumer::acquireBufferLocked(BufferItem* item, nsecs_t presentWhen,
- uint64_t maxFrameNumber) {
- status_t err = ConsumerBase::acquireBufferLocked(item, presentWhen, maxFrameNumber);
- if (err != NO_ERROR) {
- return err;
- }
-
- // If item->mGraphicBuffer is not null, this buffer has not been acquired
- // before, so we need to clean up old references.
- if (item->mGraphicBuffer != nullptr) {
- std::lock_guard<std::mutex> lock(mImagesMutex);
- if (mImages[item->mSlot] == nullptr || mImages[item->mSlot]->getBuffer() == nullptr ||
- mImages[item->mSlot]->getBuffer()->getId() != item->mGraphicBuffer->getId()) {
- mImages[item->mSlot] = std::make_shared<
- renderengine::impl::ExternalTexture>(item->mGraphicBuffer, mRE,
- renderengine::impl::ExternalTexture::
- Usage::READABLE);
- }
- }
-
- return NO_ERROR;
-}
-
-status_t BufferLayerConsumer::updateAndReleaseLocked(const BufferItem& item,
- PendingRelease* pendingRelease) {
- status_t err = NO_ERROR;
-
- int slot = item.mSlot;
-
- BLC_LOGV("updateAndRelease: (slot=%d buf=%p) -> (slot=%d buf=%p)", mCurrentTexture,
- (mCurrentTextureBuffer != nullptr && mCurrentTextureBuffer->getBuffer() != nullptr)
- ? mCurrentTextureBuffer->getBuffer()->handle
- : 0,
- slot, mSlots[slot].mGraphicBuffer->handle);
-
- // Hang onto the pointer so that it isn't freed in the call to
- // releaseBufferLocked() if we're in shared buffer mode and both buffers are
- // the same.
-
- std::shared_ptr<renderengine::ExternalTexture> nextTextureBuffer;
- {
- std::lock_guard<std::mutex> lock(mImagesMutex);
- nextTextureBuffer = mImages[slot];
- }
-
- // release old buffer
- if (mCurrentTexture != BufferQueue::INVALID_BUFFER_SLOT) {
- if (pendingRelease == nullptr) {
- status_t status =
- releaseBufferLocked(mCurrentTexture, mCurrentTextureBuffer->getBuffer());
- if (status < NO_ERROR) {
- BLC_LOGE("updateAndRelease: failed to release buffer: %s (%d)", strerror(-status),
- status);
- err = status;
- // keep going, with error raised [?]
- }
- } else {
- pendingRelease->currentTexture = mCurrentTexture;
- pendingRelease->graphicBuffer = mCurrentTextureBuffer->getBuffer();
- pendingRelease->isPending = true;
- }
- }
-
- // Update the BufferLayerConsumer state.
- mCurrentTexture = slot;
- mCurrentTextureBuffer = nextTextureBuffer;
- mCurrentCrop = item.mCrop;
- mCurrentTransform = item.mTransform;
- mCurrentScalingMode = item.mScalingMode;
- mCurrentTimestamp = item.mTimestamp;
- mCurrentDataSpace = static_cast<ui::Dataspace>(item.mDataSpace);
- mCurrentHdrMetadata = item.mHdrMetadata;
- mCurrentFence = item.mFence;
- mCurrentFenceTime = item.mFenceTime;
- mCurrentFrameNumber = item.mFrameNumber;
- mCurrentTransformToDisplayInverse = item.mTransformToDisplayInverse;
- mCurrentSurfaceDamage = item.mSurfaceDamage;
- mCurrentApi = item.mApi;
-
- computeCurrentTransformMatrixLocked();
-
- return err;
-}
-
-void BufferLayerConsumer::getTransformMatrix(float mtx[16]) {
- Mutex::Autolock lock(mMutex);
- memcpy(mtx, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
-}
-
-void BufferLayerConsumer::setFilteringEnabled(bool enabled) {
- Mutex::Autolock lock(mMutex);
- if (mAbandoned) {
- BLC_LOGE("setFilteringEnabled: BufferLayerConsumer is abandoned!");
- return;
- }
- bool needsRecompute = mFilteringEnabled != enabled;
- mFilteringEnabled = enabled;
-
- if (needsRecompute && mCurrentTextureBuffer == nullptr) {
- BLC_LOGD("setFilteringEnabled called with mCurrentTextureBuffer == nullptr");
- }
-
- if (needsRecompute && mCurrentTextureBuffer != nullptr) {
- computeCurrentTransformMatrixLocked();
- }
-}
-
-void BufferLayerConsumer::computeCurrentTransformMatrixLocked() {
- BLC_LOGV("computeCurrentTransformMatrixLocked");
- if (mCurrentTextureBuffer == nullptr || mCurrentTextureBuffer->getBuffer() == nullptr) {
- BLC_LOGD("computeCurrentTransformMatrixLocked: "
- "mCurrentTextureBuffer is nullptr");
- }
- GLConsumer::computeTransformMatrix(mCurrentTransformMatrix,
- mCurrentTextureBuffer == nullptr
- ? nullptr
- : mCurrentTextureBuffer->getBuffer(),
- getCurrentCropLocked(), mCurrentTransform,
- mFilteringEnabled);
-}
-
-nsecs_t BufferLayerConsumer::getTimestamp() {
- BLC_LOGV("getTimestamp");
- Mutex::Autolock lock(mMutex);
- return mCurrentTimestamp;
-}
-
-ui::Dataspace BufferLayerConsumer::getCurrentDataSpace() {
- BLC_LOGV("getCurrentDataSpace");
- Mutex::Autolock lock(mMutex);
- return mCurrentDataSpace;
-}
-
-const HdrMetadata& BufferLayerConsumer::getCurrentHdrMetadata() const {
- BLC_LOGV("getCurrentHdrMetadata");
- Mutex::Autolock lock(mMutex);
- return mCurrentHdrMetadata;
-}
-
-uint64_t BufferLayerConsumer::getFrameNumber() {
- BLC_LOGV("getFrameNumber");
- Mutex::Autolock lock(mMutex);
- return mCurrentFrameNumber;
-}
-
-bool BufferLayerConsumer::getTransformToDisplayInverse() const {
- Mutex::Autolock lock(mMutex);
- return mCurrentTransformToDisplayInverse;
-}
-
-const Region& BufferLayerConsumer::getSurfaceDamage() const {
- return mCurrentSurfaceDamage;
-}
-
-void BufferLayerConsumer::mergeSurfaceDamage(const Region& damage) {
- if (damage.bounds() == Rect::INVALID_RECT ||
- mCurrentSurfaceDamage.bounds() == Rect::INVALID_RECT) {
- mCurrentSurfaceDamage = Region::INVALID_REGION;
- } else {
- mCurrentSurfaceDamage |= damage;
- }
-}
-
-int BufferLayerConsumer::getCurrentApi() const {
- Mutex::Autolock lock(mMutex);
- return mCurrentApi;
-}
-
-std::shared_ptr<renderengine::ExternalTexture> BufferLayerConsumer::getCurrentBuffer(
- int* outSlot, sp<Fence>* outFence) const {
- Mutex::Autolock lock(mMutex);
-
- if (outSlot != nullptr) {
- *outSlot = mCurrentTexture;
- }
-
- if (outFence != nullptr) {
- *outFence = mCurrentFence;
- }
-
- return mCurrentTextureBuffer == nullptr ? nullptr : mCurrentTextureBuffer;
-}
-
-Rect BufferLayerConsumer::getCurrentCrop() const {
- Mutex::Autolock lock(mMutex);
- return getCurrentCropLocked();
-}
-
-Rect BufferLayerConsumer::getCurrentCropLocked() const {
- uint32_t width = mDefaultWidth;
- uint32_t height = mDefaultHeight;
- // If the buffer comes with a rotated bit for 90 (or 270) degrees, switch width/height in order
- // to scale and crop correctly.
- if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
- width = mDefaultHeight;
- height = mDefaultWidth;
- }
-
- return (mCurrentScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP)
- ? GLConsumer::scaleDownCrop(mCurrentCrop, width, height)
- : mCurrentCrop;
-}
-
-uint32_t BufferLayerConsumer::getCurrentTransform() const {
- Mutex::Autolock lock(mMutex);
- return mCurrentTransform;
-}
-
-uint32_t BufferLayerConsumer::getCurrentScalingMode() const {
- Mutex::Autolock lock(mMutex);
- return mCurrentScalingMode;
-}
-
-sp<Fence> BufferLayerConsumer::getCurrentFence() const {
- Mutex::Autolock lock(mMutex);
- return mCurrentFence;
-}
-
-std::shared_ptr<FenceTime> BufferLayerConsumer::getCurrentFenceTime() const {
- Mutex::Autolock lock(mMutex);
- return mCurrentFenceTime;
-}
-
-void BufferLayerConsumer::freeBufferLocked(int slotIndex) {
- BLC_LOGV("freeBufferLocked: slotIndex=%d", slotIndex);
- std::lock_guard<std::mutex> lock(mImagesMutex);
- if (slotIndex == mCurrentTexture) {
- mCurrentTexture = BufferQueue::INVALID_BUFFER_SLOT;
- }
- mImages[slotIndex] = nullptr;
- ConsumerBase::freeBufferLocked(slotIndex);
-}
-
-void BufferLayerConsumer::onDisconnect() {
- Mutex::Autolock lock(mMutex);
-
- if (mAbandoned) {
- // Nothing to do if we're already abandoned.
- return;
- }
-
- mLayer->onDisconnect();
-}
-
-void BufferLayerConsumer::onSidebandStreamChanged() {
- [[maybe_unused]] FrameAvailableListener* unsafeFrameAvailableListener = nullptr;
- {
- Mutex::Autolock lock(mFrameAvailableMutex);
- unsafeFrameAvailableListener = mFrameAvailableListener.unsafe_get();
- }
- sp<ContentsChangedListener> listener;
- { // scope for the lock
- Mutex::Autolock lock(mMutex);
- ALOG_ASSERT(unsafeFrameAvailableListener == mContentsChangedListener.unsafe_get());
- listener = mContentsChangedListener.promote();
- }
-
- if (listener != nullptr) {
- listener->onSidebandStreamChanged();
- }
-}
-
-void BufferLayerConsumer::onBufferAvailable(const BufferItem& item) {
- if (item.mGraphicBuffer != nullptr && item.mSlot != BufferQueue::INVALID_BUFFER_SLOT) {
- std::lock_guard<std::mutex> lock(mImagesMutex);
- const std::shared_ptr<renderengine::ExternalTexture>& oldImage = mImages[item.mSlot];
- if (oldImage == nullptr || oldImage->getBuffer() == nullptr ||
- oldImage->getBuffer()->getId() != item.mGraphicBuffer->getId()) {
- mImages[item.mSlot] = std::make_shared<
- renderengine::impl::ExternalTexture>(item.mGraphicBuffer, mRE,
- renderengine::impl::ExternalTexture::
- Usage::READABLE);
- }
- }
-}
-
-void BufferLayerConsumer::abandonLocked() {
- BLC_LOGV("abandonLocked");
- mCurrentTextureBuffer = nullptr;
- for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
- std::lock_guard<std::mutex> lock(mImagesMutex);
- mImages[i] = nullptr;
- }
- ConsumerBase::abandonLocked();
-}
-
-status_t BufferLayerConsumer::setConsumerUsageBits(uint64_t usage) {
- return ConsumerBase::setConsumerUsageBits(usage | DEFAULT_USAGE_FLAGS);
-}
-
-void BufferLayerConsumer::dumpLocked(String8& result, const char* prefix) const {
- result.appendFormat("%smTexName=%d mCurrentTexture=%d\n"
- "%smCurrentCrop=[%d,%d,%d,%d] mCurrentTransform=%#x\n",
- prefix, mTexName, mCurrentTexture, prefix, mCurrentCrop.left,
- mCurrentCrop.top, mCurrentCrop.right, mCurrentCrop.bottom,
- mCurrentTransform);
-
- ConsumerBase::dumpLocked(result, prefix);
-}
-}; // namespace android
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/BufferLayerConsumer.h b/services/surfaceflinger/BufferLayerConsumer.h
deleted file mode 100644
index 23ad2a3..0000000
--- a/services/surfaceflinger/BufferLayerConsumer.h
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_BUFFERLAYERCONSUMER_H
-#define ANDROID_BUFFERLAYERCONSUMER_H
-
-#include <android-base/thread_annotations.h>
-#include <gui/BufferQueueDefs.h>
-#include <gui/ConsumerBase.h>
-#include <gui/HdrMetadata.h>
-#include <renderengine/ExternalTexture.h>
-#include <ui/FenceTime.h>
-#include <ui/GraphicBuffer.h>
-#include <ui/GraphicTypes.h>
-#include <ui/Region.h>
-#include <utils/String8.h>
-#include <utils/Vector.h>
-#include <utils/threads.h>
-
-namespace android {
-// ----------------------------------------------------------------------------
-
-class Layer;
-class String8;
-
-namespace renderengine {
-class RenderEngine;
-} // namespace renderengine
-
-/*
- * BufferLayerConsumer consumes buffers of graphics data from a BufferQueue,
- * and makes them available to RenderEngine as a texture.
- *
- * A typical usage pattern is to call updateTexImage() when a new frame is
- * desired. If a new frame is available, the frame is latched. If not, the
- * previous contents are retained. The texture is attached and updated after
- * bindTextureImage() is called.
- *
- * All calls to updateTexImage must be made with RenderEngine being current.
- * The texture is attached to the TEXTURE_EXTERNAL texture target.
- */
-class BufferLayerConsumer : public ConsumerBase {
-public:
- static const status_t BUFFER_REJECTED = UNKNOWN_ERROR + 8;
-
- class BufferRejecter {
- friend class BufferLayerConsumer;
- virtual bool reject(const sp<GraphicBuffer>& buf, const BufferItem& item) = 0;
-
- protected:
- virtual ~BufferRejecter() {}
- };
-
- struct ContentsChangedListener : public FrameAvailableListener {
- virtual void onSidebandStreamChanged() = 0;
- };
-
- // BufferLayerConsumer constructs a new BufferLayerConsumer object. The
- // tex parameter indicates the name of the RenderEngine texture to which
- // images are to be streamed.
- BufferLayerConsumer(const sp<IGraphicBufferConsumer>& bq, renderengine::RenderEngine& engine,
- uint32_t tex, Layer* layer);
-
- // Sets the contents changed listener. This should be used instead of
- // ConsumerBase::setFrameAvailableListener().
- void setContentsChangedListener(const wp<ContentsChangedListener>& listener);
-
- // updateTexImage acquires the most recently queued buffer, and sets the
- // image contents of the target texture to it.
- //
- // This call may only be made while RenderEngine is current.
- //
- // This calls doFenceWait to ensure proper synchronization unless native
- // fence is supported.
- //
- // Unlike the GLConsumer version, this version takes a functor that may be
- // used to reject the newly acquired buffer. It also does not bind the
- // RenderEngine texture until bindTextureImage is called.
- status_t updateTexImage(BufferRejecter* rejecter, nsecs_t expectedPresentTime,
- bool* autoRefresh, bool* queuedBuffer, uint64_t maxFrameNumber);
-
- // setReleaseFence stores a fence that will signal when the current buffer
- // is no longer being read. This fence will be returned to the producer
- // when the current buffer is released by updateTexImage(). Multiple
- // fences can be set for a given buffer; they will be merged into a single
- // union fence.
- void setReleaseFence(const sp<Fence>& fence);
-
- bool releasePendingBuffer();
-
- sp<Fence> getPrevFinalReleaseFence() const;
-
- // See GLConsumer::getTransformMatrix.
- void getTransformMatrix(float mtx[16]);
-
- // getTimestamp retrieves the timestamp associated with the texture image
- // set by the most recent call to updateTexImage.
- //
- // The timestamp is in nanoseconds, and is monotonically increasing. Its
- // other semantics (zero point, etc) are source-dependent and should be
- // documented by the source.
- int64_t getTimestamp();
-
- // getDataSpace retrieves the DataSpace associated with the texture image
- // set by the most recent call to updateTexImage.
- ui::Dataspace getCurrentDataSpace();
-
- // getCurrentHdrMetadata retrieves the HDR metadata associated with the
- // texture image set by the most recent call to updateTexImage.
- const HdrMetadata& getCurrentHdrMetadata() const;
-
- // getFrameNumber retrieves the frame number associated with the texture
- // image set by the most recent call to updateTexImage.
- //
- // The frame number is an incrementing counter set to 0 at the creation of
- // the BufferQueue associated with this consumer.
- uint64_t getFrameNumber();
-
- bool getTransformToDisplayInverse() const;
-
- // must be called from SF main thread
- const Region& getSurfaceDamage() const;
-
- // Merge the given damage region into the current damage region value.
- void mergeSurfaceDamage(const Region& damage);
-
- // getCurrentApi retrieves the API which queues the current buffer.
- int getCurrentApi() const;
-
- // See GLConsumer::setDefaultBufferSize.
- status_t setDefaultBufferSize(uint32_t width, uint32_t height);
-
- // setFilteringEnabled sets whether the transform matrix should be computed
- // for use with bilinear filtering.
- void setFilteringEnabled(bool enabled);
-
- // getCurrentBuffer returns the buffer associated with the current image.
- // When outSlot is not nullptr, the current buffer slot index is also
- // returned. Simiarly, when outFence is not nullptr, the current output
- // fence is returned.
- std::shared_ptr<renderengine::ExternalTexture> getCurrentBuffer(
- int* outSlot = nullptr, sp<Fence>* outFence = nullptr) const;
-
- // getCurrentCrop returns the cropping rectangle of the current buffer.
- Rect getCurrentCrop() const;
-
- // getCurrentTransform returns the transform of the current buffer.
- uint32_t getCurrentTransform() const;
-
- // getCurrentScalingMode returns the scaling mode of the current buffer.
- uint32_t getCurrentScalingMode() const;
-
- // getCurrentFence returns the fence indicating when the current buffer is
- // ready to be read from.
- sp<Fence> getCurrentFence() const;
-
- // getCurrentFence returns the FenceTime indicating when the current
- // buffer is ready to be read from.
- std::shared_ptr<FenceTime> getCurrentFenceTime() const;
-
- // setConsumerUsageBits overrides the ConsumerBase method to OR
- // DEFAULT_USAGE_FLAGS to usage.
- status_t setConsumerUsageBits(uint64_t usage);
- void onBufferAvailable(const BufferItem& item) EXCLUDES(mImagesMutex);
-
-protected:
- // abandonLocked overrides the ConsumerBase method to clear
- // mCurrentTextureImage in addition to the ConsumerBase behavior.
- virtual void abandonLocked() EXCLUDES(mImagesMutex);
-
- // dumpLocked overrides the ConsumerBase method to dump BufferLayerConsumer-
- // specific info in addition to the ConsumerBase behavior.
- virtual void dumpLocked(String8& result, const char* prefix) const;
-
- // See ConsumerBase::acquireBufferLocked
- virtual status_t acquireBufferLocked(BufferItem* item, nsecs_t presentWhen,
- uint64_t maxFrameNumber = 0) override
- EXCLUDES(mImagesMutex);
-
- bool canUseImageCrop(const Rect& crop) const;
-
- struct PendingRelease {
- PendingRelease() : isPending(false), currentTexture(-1), graphicBuffer() {}
-
- bool isPending;
- int currentTexture;
- sp<GraphicBuffer> graphicBuffer;
- };
-
- // This releases the buffer in the slot referenced by mCurrentTexture,
- // then updates state to refer to the BufferItem, which must be a
- // newly-acquired buffer. If pendingRelease is not null, the parameters
- // which would have been passed to releaseBufferLocked upon the successful
- // completion of the method will instead be returned to the caller, so that
- // it may call releaseBufferLocked itself later.
- status_t updateAndReleaseLocked(const BufferItem& item,
- PendingRelease* pendingRelease = nullptr)
- EXCLUDES(mImagesMutex);
-
-private:
- // Utility class for managing GraphicBuffer references into renderengine
- class Image {
- public:
- Image(const sp<GraphicBuffer>& graphicBuffer, renderengine::RenderEngine& engine);
- virtual ~Image();
- const sp<GraphicBuffer>& graphicBuffer() { return mGraphicBuffer; }
-
- private:
- // mGraphicBuffer is the buffer that was used to create this image.
- sp<GraphicBuffer> mGraphicBuffer;
- // Back-reference into renderengine to initiate cleanup.
- renderengine::RenderEngine& mRE;
- DISALLOW_COPY_AND_ASSIGN(Image);
- };
-
- // freeBufferLocked frees up the given buffer slot. If the slot has been
- // initialized this will release the reference to the GraphicBuffer in
- // that slot. Otherwise it has no effect.
- //
- // This method must be called with mMutex locked.
- virtual void freeBufferLocked(int slotIndex) EXCLUDES(mImagesMutex);
-
- // IConsumerListener interface
- void onDisconnect() override;
- void onSidebandStreamChanged() override;
- void addAndGetFrameTimestamps(const NewFrameEventsEntry*, FrameEventHistoryDelta*) override {}
-
- // computeCurrentTransformMatrixLocked computes the transform matrix for the
- // current texture. It uses mCurrentTransform and the current GraphicBuffer
- // to compute this matrix and stores it in mCurrentTransformMatrix.
- // mCurrentTextureImage must not be nullptr.
- void computeCurrentTransformMatrixLocked();
-
- // getCurrentCropLocked returns the cropping rectangle of the current buffer.
- Rect getCurrentCropLocked() const;
-
- // The default consumer usage flags that BufferLayerConsumer always sets on its
- // BufferQueue instance; these will be OR:d with any additional flags passed
- // from the BufferLayerConsumer user. In particular, BufferLayerConsumer will always
- // consume buffers as hardware textures.
- static const uint64_t DEFAULT_USAGE_FLAGS = GraphicBuffer::USAGE_HW_TEXTURE;
-
- // mCurrentTextureBuffer is the buffer containing the current texture. It's
- // possible that this buffer is not associated with any buffer slot, so we
- // must track it separately in order to support the getCurrentBuffer method.
- std::shared_ptr<renderengine::ExternalTexture> mCurrentTextureBuffer;
-
- // mCurrentCrop is the crop rectangle that applies to the current texture.
- // It gets set each time updateTexImage is called.
- Rect mCurrentCrop;
-
- // mCurrentTransform is the transform identifier for the current texture. It
- // gets set each time updateTexImage is called.
- uint32_t mCurrentTransform;
-
- // mCurrentScalingMode is the scaling mode for the current texture. It gets
- // set each time updateTexImage is called.
- uint32_t mCurrentScalingMode;
-
- // mCurrentFence is the fence received from BufferQueue in updateTexImage.
- sp<Fence> mCurrentFence;
-
- // The FenceTime wrapper around mCurrentFence.
- std::shared_ptr<FenceTime> mCurrentFenceTime{FenceTime::NO_FENCE};
-
- // mCurrentTransformMatrix is the transform matrix for the current texture.
- // It gets computed by computeTransformMatrix each time updateTexImage is
- // called.
- float mCurrentTransformMatrix[16];
-
- // mCurrentTimestamp is the timestamp for the current texture. It
- // gets set each time updateTexImage is called.
- int64_t mCurrentTimestamp;
-
- // mCurrentDataSpace is the dataspace for the current texture. It
- // gets set each time updateTexImage is called.
- ui::Dataspace mCurrentDataSpace;
-
- // mCurrentHdrMetadata is the HDR metadata for the current texture. It
- // gets set each time updateTexImage is called.
- HdrMetadata mCurrentHdrMetadata;
-
- // mCurrentFrameNumber is the frame counter for the current texture.
- // It gets set each time updateTexImage is called.
- uint64_t mCurrentFrameNumber;
-
- // Indicates this buffer must be transformed by the inverse transform of the screen
- // it is displayed onto. This is applied after BufferLayerConsumer::mCurrentTransform.
- // This must be set/read from SurfaceFlinger's main thread.
- bool mCurrentTransformToDisplayInverse;
-
- // The portion of this surface that has changed since the previous frame
- Region mCurrentSurfaceDamage;
-
- int mCurrentApi;
-
- uint32_t mDefaultWidth, mDefaultHeight;
-
- // mFilteringEnabled indicates whether the transform matrix is computed for
- // use with bilinear filtering. It defaults to true and is changed by
- // setFilteringEnabled().
- bool mFilteringEnabled;
-
- renderengine::RenderEngine& mRE;
-
- // mTexName is the name of the RenderEngine texture to which streamed
- // images will be bound when bindTexImage is called. It is set at
- // construction time.
- const uint32_t mTexName;
-
- // The layer for this BufferLayerConsumer. Always check mAbandoned before accessing.
- Layer* mLayer GUARDED_BY(mMutex);
-
- wp<ContentsChangedListener> mContentsChangedListener;
-
- // mCurrentTexture is the buffer slot index of the buffer that is currently
- // bound to the RenderEngine texture. It is initialized to INVALID_BUFFER_SLOT,
- // indicating that no buffer slot is currently bound to the texture. Note,
- // however, that a value of INVALID_BUFFER_SLOT does not necessarily mean
- // that no buffer is bound to the texture. A call to setBufferCount will
- // reset mCurrentTexture to INVALID_BUFFER_SLOT.
- int mCurrentTexture;
-
- // Shadow buffer cache for cleaning up renderengine references.
- std::shared_ptr<renderengine::ExternalTexture>
- mImages[BufferQueueDefs::NUM_BUFFER_SLOTS] GUARDED_BY(mImagesMutex);
-
- // Separate mutex guarding the shadow buffer cache.
- // mImagesMutex can be manipulated with binder threads (e.g. onBuffersAllocated)
- // which is contentious enough that we can't just use mMutex.
- mutable std::mutex mImagesMutex;
-
- // A release that is pending on the receipt of a new release fence from
- // presentDisplay
- PendingRelease mPendingRelease;
-};
-
-// ----------------------------------------------------------------------------
-}; // namespace android
-
-#endif // ANDROID_BUFFERLAYERCONSUMER_H
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
deleted file mode 100644
index bee4de3..0000000
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ /dev/null
@@ -1,575 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-
-#undef LOG_TAG
-#define LOG_TAG "BufferQueueLayer"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-#include "BufferQueueLayer.h"
-
-#include <compositionengine/LayerFECompositionState.h>
-#include <gui/BufferQueueConsumer.h>
-#include <system/window.h>
-
-#include "LayerRejecter.h"
-#include "SurfaceInterceptor.h"
-
-#include "FrameTracer/FrameTracer.h"
-#include "Scheduler/LayerHistory.h"
-#include "TimeStats/TimeStats.h"
-
-namespace android {
-using PresentState = frametimeline::SurfaceFrame::PresentState;
-
-BufferQueueLayer::BufferQueueLayer(const LayerCreationArgs& args) : BufferLayer(args) {}
-
-BufferQueueLayer::~BufferQueueLayer() {
- mContentsChangedListener->abandon();
- mConsumer->abandon();
-}
-
-// -----------------------------------------------------------------------
-// Interface implementation for Layer
-// -----------------------------------------------------------------------
-
-void BufferQueueLayer::onLayerDisplayed(ftl::SharedFuture<FenceResult> futureFenceResult) {
- const sp<Fence> releaseFence = futureFenceResult.get().value_or(Fence::NO_FENCE);
- mConsumer->setReleaseFence(releaseFence);
-
- // Prevent tracing the same release multiple times.
- if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) {
- mFlinger->mFrameTracer->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber,
- std::make_shared<FenceTime>(releaseFence),
- FrameTracer::FrameEvent::RELEASE_FENCE);
- mPreviousReleasedFrameNumber = mPreviousFrameNumber;
- }
-}
-
-void BufferQueueLayer::setTransformHint(ui::Transform::RotationFlags displayTransformHint) {
- BufferLayer::setTransformHint(displayTransformHint);
- mConsumer->setTransformHint(mTransformHint);
-}
-
-void BufferQueueLayer::releasePendingBuffer(nsecs_t) {
- if (!mConsumer->releasePendingBuffer()) {
- return;
- }
-}
-
-void BufferQueueLayer::setDefaultBufferSize(uint32_t w, uint32_t h) {
- mConsumer->setDefaultBufferSize(w, h);
-}
-
-int32_t BufferQueueLayer::getQueuedFrameCount() const {
- return mQueuedFrames;
-}
-
-bool BufferQueueLayer::isBufferDue(nsecs_t expectedPresentTime) const {
- Mutex::Autolock lock(mQueueItemLock);
-
- const int64_t addedTime = mQueueItems[0].item.mTimestamp;
-
- // Ignore timestamps more than a second in the future
- const bool isPlausible = addedTime < (expectedPresentTime + s2ns(1));
- ALOGW_IF(!isPlausible,
- "[%s] Timestamp %" PRId64 " seems implausible "
- "relative to expectedPresent %" PRId64,
- getDebugName(), addedTime, expectedPresentTime);
-
- if (!isPlausible) {
- mFlinger->mTimeStats->incrementBadDesiredPresent(getSequence());
- }
-
- const bool isDue = addedTime < expectedPresentTime;
- return isDue || !isPlausible;
-}
-
-// -----------------------------------------------------------------------
-// Interface implementation for BufferLayer
-// -----------------------------------------------------------------------
-
-bool BufferQueueLayer::fenceHasSignaled() const {
- Mutex::Autolock lock(mQueueItemLock);
-
- if (SurfaceFlinger::enableLatchUnsignaledConfig != LatchUnsignaledConfig::Disabled) {
- return true;
- }
-
- if (!hasFrameUpdate()) {
- return true;
- }
-
- if (mQueueItems[0].item.mIsDroppable) {
- // Even though this buffer's fence may not have signaled yet, it could
- // be replaced by another buffer before it has a chance to, which means
- // that it's possible to get into a situation where a buffer is never
- // able to be latched. To avoid this, grab this buffer anyway.
- return true;
- }
- const bool fenceSignaled =
- mQueueItems[0].item.mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING;
- if (!fenceSignaled) {
- mFlinger->mTimeStats->incrementLatchSkipped(getSequence(),
- TimeStats::LatchSkipReason::LateAcquire);
- }
-
- return fenceSignaled;
-}
-
-bool BufferQueueLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const {
- Mutex::Autolock lock(mQueueItemLock);
-
- if (!hasFrameUpdate() || isRemovedFromCurrentState()) {
- return true;
- }
-
- return mQueueItems[0].item.mTimestamp <= expectedPresentTime;
-}
-
-bool BufferQueueLayer::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();
-
- bool sidebandStreamChanged = true;
- if (mSidebandStreamChanged.compare_exchange_strong(sidebandStreamChanged, false)) {
- // mSidebandStreamChanged was changed to false
- mSidebandStream = mConsumer->getSidebandStream();
- auto* layerCompositionState = editCompositionState();
- layerCompositionState->sidebandStream = mSidebandStream;
- if (layerCompositionState->sidebandStream != nullptr) {
- setTransactionFlags(eTransactionNeeded);
- mFlinger->setTransactionFlags(eTraversalNeeded);
- }
- recomputeVisibleRegions = true;
-
- return true;
- }
- return false;
-}
-
-bool BufferQueueLayer::hasFrameUpdate() const {
- return mQueuedFrames > 0;
-}
-
-status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
- nsecs_t expectedPresentTime) {
- // This boolean is used to make sure that SurfaceFlinger's shadow copy
- // of the buffer queue isn't modified when the buffer queue is returning
- // BufferItem's that weren't actually queued. This can happen in shared
- // buffer mode.
- bool queuedBuffer = false;
- const int32_t layerId = getSequence();
- LayerRejecter r(mDrawingState, getDrawingState(), recomputeVisibleRegions,
- getProducerStickyTransform() != 0, mName,
- getTransformToDisplayInverse());
-
- if (isRemovedFromCurrentState()) {
- expectedPresentTime = 0;
- }
-
- // updateTexImage() below might drop the some buffers at the head of the queue if there is a
- // buffer behind them which is timely to be presented. However this buffer may not be signaled
- // yet. The code below makes sure that this wouldn't happen by setting maxFrameNumber to the
- // last buffer that was signaled.
- uint64_t lastSignaledFrameNumber = mLastFrameNumberReceived;
- {
- Mutex::Autolock lock(mQueueItemLock);
- for (size_t i = 0; i < mQueueItems.size(); i++) {
- bool fenceSignaled =
- mQueueItems[i].item.mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING;
- if (!fenceSignaled) {
- break;
- }
- lastSignaledFrameNumber = mQueueItems[i].item.mFrameNumber;
- }
- }
- const uint64_t maxFrameNumberToAcquire =
- std::min(mLastFrameNumberReceived.load(), lastSignaledFrameNumber);
-
- bool autoRefresh;
- status_t updateResult = mConsumer->updateTexImage(&r, expectedPresentTime, &autoRefresh,
- &queuedBuffer, maxFrameNumberToAcquire);
- mDrawingState.autoRefresh = autoRefresh;
- if (updateResult == BufferQueue::PRESENT_LATER) {
- // Producer doesn't want buffer to be displayed yet. Signal a
- // layer update so we check again at the next opportunity.
- mFlinger->onLayerUpdate();
- return BAD_VALUE;
- } else if (updateResult == BufferLayerConsumer::BUFFER_REJECTED) {
- // If the buffer has been rejected, remove it from the shadow queue
- // and return early
- if (queuedBuffer) {
- Mutex::Autolock lock(mQueueItemLock);
- if (mQueuedFrames > 0) {
- mConsumer->mergeSurfaceDamage(mQueueItems[0].item.mSurfaceDamage);
- mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].item.mFrameNumber);
- if (mQueueItems[0].surfaceFrame) {
- addSurfaceFrameDroppedForBuffer(mQueueItems[0].surfaceFrame);
- }
- mQueueItems.erase(mQueueItems.begin());
- mQueuedFrames--;
- }
- }
- return BAD_VALUE;
- } else if (updateResult != NO_ERROR || mUpdateTexImageFailed) {
- // This can occur if something goes wrong when trying to create the
- // EGLImage for this buffer. If this happens, the buffer has already
- // been released, so we need to clean up the queue and bug out
- // early.
- if (queuedBuffer) {
- Mutex::Autolock lock(mQueueItemLock);
- for (auto& [item, surfaceFrame] : mQueueItems) {
- if (surfaceFrame) {
- addSurfaceFrameDroppedForBuffer(surfaceFrame);
- }
- }
- mQueueItems.clear();
- mQueuedFrames = 0;
- mFlinger->mTimeStats->onDestroy(layerId);
- mFlinger->mFrameTracer->onDestroy(layerId);
- }
-
- // Once we have hit this state, the shadow queue may no longer
- // correctly reflect the incoming BufferQueue's contents, so even if
- // updateTexImage starts working, the only safe course of action is
- // to continue to ignore updates.
- mUpdateTexImageFailed = true;
-
- return BAD_VALUE;
- }
-
- bool more_frames_pending = false;
- if (queuedBuffer) {
- // Autolock scope
- auto currentFrameNumber = mConsumer->getFrameNumber();
-
- Mutex::Autolock lock(mQueueItemLock);
-
- // Remove any stale buffers that have been dropped during
- // updateTexImage
- while (mQueuedFrames > 0 && mQueueItems[0].item.mFrameNumber != currentFrameNumber) {
- mConsumer->mergeSurfaceDamage(mQueueItems[0].item.mSurfaceDamage);
- mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].item.mFrameNumber);
- if (mQueueItems[0].surfaceFrame) {
- addSurfaceFrameDroppedForBuffer(mQueueItems[0].surfaceFrame);
- }
- mQueueItems.erase(mQueueItems.begin());
- mQueuedFrames--;
- }
-
- uint64_t bufferID = mQueueItems[0].item.mGraphicBuffer->getId();
- mFlinger->mTimeStats->setLatchTime(layerId, currentFrameNumber, latchTime);
- mFlinger->mFrameTracer->traceTimestamp(layerId, bufferID, currentFrameNumber, latchTime,
- FrameTracer::FrameEvent::LATCH);
-
- if (mQueueItems[0].surfaceFrame) {
- addSurfaceFramePresentedForBuffer(mQueueItems[0].surfaceFrame,
- mQueueItems[0].item.mFenceTime->getSignalTime(),
- latchTime);
- }
- mQueueItems.erase(mQueueItems.begin());
- more_frames_pending = (mQueuedFrames.fetch_sub(1) > 1);
- }
-
- // Decrement the queued-frames count. Signal another event if we
- // have more frames pending.
- if ((queuedBuffer && more_frames_pending) || mDrawingState.autoRefresh) {
- mFlinger->onLayerUpdate();
- }
-
- return NO_ERROR;
-}
-
-status_t BufferQueueLayer::updateActiveBuffer() {
- // update the active buffer
- mPreviousBufferId = getCurrentBufferId();
- mBufferInfo.mBuffer =
- mConsumer->getCurrentBuffer(&mBufferInfo.mBufferSlot, &mBufferInfo.mFence);
-
- if (mBufferInfo.mBuffer == nullptr) {
- // this can only happen if the very first buffer was rejected.
- return BAD_VALUE;
- }
- return NO_ERROR;
-}
-
-status_t BufferQueueLayer::updateFrameNumber() {
- mPreviousFrameNumber = mCurrentFrameNumber;
- mCurrentFrameNumber = mConsumer->getFrameNumber();
- return NO_ERROR;
-}
-
-void BufferQueueLayer::setFrameTimelineInfoForBuffer(const FrameTimelineInfo& frameTimelineInfo) {
- mFrameTimelineInfo = frameTimelineInfo;
-}
-
-// -----------------------------------------------------------------------
-// Interface implementation for BufferLayerConsumer::ContentsChangedListener
-// -----------------------------------------------------------------------
-
-void BufferQueueLayer::onFrameDequeued(const uint64_t bufferId) {
- const int32_t layerId = getSequence();
- mFlinger->mFrameTracer->traceNewLayer(layerId, getName().c_str());
- mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER,
- systemTime(), FrameTracer::FrameEvent::DEQUEUE);
-}
-
-void BufferQueueLayer::onFrameDetached(const uint64_t bufferId) {
- const int32_t layerId = getSequence();
- mFlinger->mFrameTracer->traceNewLayer(layerId, getName().c_str());
- mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER,
- systemTime(), FrameTracer::FrameEvent::DETACH);
-}
-
-void BufferQueueLayer::onFrameCancelled(const uint64_t bufferId) {
- const int32_t layerId = getSequence();
- mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER,
- systemTime(), FrameTracer::FrameEvent::CANCEL);
-}
-
-void BufferQueueLayer::onFrameAvailable(const BufferItem& item) {
- const int32_t layerId = getSequence();
- const uint64_t bufferId = item.mGraphicBuffer->getId();
- mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, item.mFrameNumber, systemTime(),
- FrameTracer::FrameEvent::QUEUE);
- mFlinger->mFrameTracer->traceFence(layerId, bufferId, item.mFrameNumber,
- std::make_shared<FenceTime>(item.mFence),
- FrameTracer::FrameEvent::ACQUIRE_FENCE);
-
- ATRACE_CALL();
- // Add this buffer from our internal queue tracker
- { // Autolock scope
- const nsecs_t presentTime = item.mIsAutoTimestamp ? 0 : item.mTimestamp;
-
- using LayerUpdateType = scheduler::LayerHistory::LayerUpdateType;
- mFlinger->mScheduler->recordLayerHistory(this, presentTime, LayerUpdateType::Buffer);
-
- Mutex::Autolock lock(mQueueItemLock);
- // Reset the frame number tracker when we receive the first buffer after
- // a frame number reset
- if (item.mFrameNumber == 1) {
- mLastFrameNumberReceived = 0;
- }
-
- // Ensure that callbacks are handled in order
- while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
- status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500));
- if (result != NO_ERROR) {
- ALOGE("[%s] Timed out waiting on callback", getDebugName());
- break;
- }
- }
-
- auto surfaceFrame = createSurfaceFrameForBuffer(mFrameTimelineInfo, systemTime(), mName);
-
- mQueueItems.push_back({item, surfaceFrame});
- mQueuedFrames++;
-
- // Wake up any pending callbacks
- mLastFrameNumberReceived = item.mFrameNumber;
- mQueueItemCondition.broadcast();
- }
-
- mFlinger->mInterceptor->saveBufferUpdate(layerId, item.mGraphicBuffer->getWidth(),
- item.mGraphicBuffer->getHeight(), item.mFrameNumber);
-
- mFlinger->onLayerUpdate();
- mConsumer->onBufferAvailable(item);
-}
-
-void BufferQueueLayer::onFrameReplaced(const BufferItem& item) {
- ATRACE_CALL();
- { // Autolock scope
- Mutex::Autolock lock(mQueueItemLock);
-
- // Ensure that callbacks are handled in order
- while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
- status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500));
- if (result != NO_ERROR) {
- ALOGE("[%s] Timed out waiting on callback", getDebugName());
- break;
- }
- }
-
- if (!hasFrameUpdate()) {
- ALOGE("Can't replace a frame on an empty queue");
- return;
- }
-
- auto surfaceFrame = createSurfaceFrameForBuffer(mFrameTimelineInfo, systemTime(), mName);
- mQueueItems[mQueueItems.size() - 1].item = item;
- mQueueItems[mQueueItems.size() - 1].surfaceFrame = std::move(surfaceFrame);
-
- // Wake up any pending callbacks
- mLastFrameNumberReceived = item.mFrameNumber;
- mQueueItemCondition.broadcast();
- }
-
- const int32_t layerId = getSequence();
- const uint64_t bufferId = item.mGraphicBuffer->getId();
- mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, item.mFrameNumber, systemTime(),
- FrameTracer::FrameEvent::QUEUE);
- mFlinger->mFrameTracer->traceFence(layerId, bufferId, item.mFrameNumber,
- std::make_shared<FenceTime>(item.mFence),
- FrameTracer::FrameEvent::ACQUIRE_FENCE);
- mConsumer->onBufferAvailable(item);
-}
-
-void BufferQueueLayer::onSidebandStreamChanged() {
- bool sidebandStreamChanged = false;
- if (mSidebandStreamChanged.compare_exchange_strong(sidebandStreamChanged, true)) {
- // mSidebandStreamChanged was changed to true
- mFlinger->onLayerUpdate();
- }
-}
-
-// -----------------------------------------------------------------------
-
-void BufferQueueLayer::onFirstRef() {
- BufferLayer::onFirstRef();
-
- // Creates a custom BufferQueue for SurfaceFlingerConsumer to use
- sp<IGraphicBufferProducer> producer;
- sp<IGraphicBufferConsumer> consumer;
- mFlinger->getFactory().createBufferQueue(&producer, &consumer, true);
- mProducer = mFlinger->getFactory().createMonitoredProducer(producer, mFlinger, this);
- mConsumer =
- mFlinger->getFactory().createBufferLayerConsumer(consumer, mFlinger->getRenderEngine(),
- mTextureName, this);
- mConsumer->setConsumerUsageBits(getEffectiveUsage(0));
-
- mContentsChangedListener = new ContentsChangedListener(this);
- mConsumer->setContentsChangedListener(mContentsChangedListener);
- mConsumer->setName(String8(mName.data(), mName.size()));
-
- mProducer->setMaxDequeuedBufferCount(2);
-}
-
-status_t BufferQueueLayer::setDefaultBufferProperties(uint32_t w, uint32_t h, PixelFormat format) {
- // never allow a surface larger than what our underlying GL implementation
- // can handle.
- if (mFlinger->exceedsMaxRenderTargetSize(w, h)) {
- ALOGE("dimensions too large %" PRIu32 " x %" PRIu32, w, h);
- return BAD_VALUE;
- }
-
- setDefaultBufferSize(w, h);
- mConsumer->setDefaultBufferFormat(format);
- mConsumer->setConsumerUsageBits(getEffectiveUsage(0));
-
- return NO_ERROR;
-}
-
-sp<IGraphicBufferProducer> BufferQueueLayer::getProducer() const {
- return mProducer;
-}
-
-uint32_t BufferQueueLayer::getProducerStickyTransform() const {
- int producerStickyTransform = 0;
- int ret = mProducer->query(NATIVE_WINDOW_STICKY_TRANSFORM, &producerStickyTransform);
- if (ret != OK) {
- ALOGW("%s: Error %s (%d) while querying window sticky transform.", __FUNCTION__,
- strerror(-ret), ret);
- return 0;
- }
- return static_cast<uint32_t>(producerStickyTransform);
-}
-
-void BufferQueueLayer::gatherBufferInfo() {
- BufferLayer::gatherBufferInfo();
-
- mBufferInfo.mDesiredPresentTime = mConsumer->getTimestamp();
- mBufferInfo.mFenceTime = mConsumer->getCurrentFenceTime();
- mBufferInfo.mFence = mConsumer->getCurrentFence();
- mBufferInfo.mTransform = mConsumer->getCurrentTransform();
- mBufferInfo.mDataspace = translateDataspace(mConsumer->getCurrentDataSpace());
- mBufferInfo.mCrop = mConsumer->getCurrentCrop();
- mBufferInfo.mScaleMode = mConsumer->getCurrentScalingMode();
- mBufferInfo.mSurfaceDamage = mConsumer->getSurfaceDamage();
- mBufferInfo.mHdrMetadata = mConsumer->getCurrentHdrMetadata();
- mBufferInfo.mApi = mConsumer->getCurrentApi();
- mBufferInfo.mTransformToDisplayInverse = mConsumer->getTransformToDisplayInverse();
-}
-
-sp<Layer> BufferQueueLayer::createClone() {
- LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, LayerMetadata());
- args.textureName = mTextureName;
- sp<BufferQueueLayer> layer = mFlinger->getFactory().createBufferQueueLayer(args);
- layer->setInitialValuesForClone(this);
-
- return layer;
-}
-
-// -----------------------------------------------------------------------
-// Interface implementation for BufferLayerConsumer::ContentsChangedListener
-// -----------------------------------------------------------------------
-
-void BufferQueueLayer::ContentsChangedListener::onFrameAvailable(const BufferItem& item) {
- Mutex::Autolock lock(mMutex);
- if (mBufferQueueLayer != nullptr) {
- mBufferQueueLayer->onFrameAvailable(item);
- }
-}
-
-void BufferQueueLayer::ContentsChangedListener::onFrameReplaced(const BufferItem& item) {
- Mutex::Autolock lock(mMutex);
- if (mBufferQueueLayer != nullptr) {
- mBufferQueueLayer->onFrameReplaced(item);
- }
-}
-
-void BufferQueueLayer::ContentsChangedListener::onSidebandStreamChanged() {
- Mutex::Autolock lock(mMutex);
- if (mBufferQueueLayer != nullptr) {
- mBufferQueueLayer->onSidebandStreamChanged();
- }
-}
-
-void BufferQueueLayer::ContentsChangedListener::onFrameDequeued(const uint64_t bufferId) {
- Mutex::Autolock lock(mMutex);
- if (mBufferQueueLayer != nullptr) {
- mBufferQueueLayer->onFrameDequeued(bufferId);
- }
-}
-
-void BufferQueueLayer::ContentsChangedListener::onFrameDetached(const uint64_t bufferId) {
- Mutex::Autolock lock(mMutex);
- if (mBufferQueueLayer != nullptr) {
- mBufferQueueLayer->onFrameDetached(bufferId);
- }
-}
-
-void BufferQueueLayer::ContentsChangedListener::onFrameCancelled(const uint64_t bufferId) {
- Mutex::Autolock lock(mMutex);
- if (mBufferQueueLayer != nullptr) {
- mBufferQueueLayer->onFrameCancelled(bufferId);
- }
-}
-
-void BufferQueueLayer::ContentsChangedListener::abandon() {
- Mutex::Autolock lock(mMutex);
- mBufferQueueLayer = nullptr;
-}
-
-// -----------------------------------------------------------------------
-
-} // namespace android
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
deleted file mode 100644
index e1c80d5..0000000
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include "BufferLayer.h"
-
-#include <utils/String8.h>
-
-namespace android {
-
-namespace frametimeline {
-class SurfaceFrame;
-}
-
-/*
- * A new BufferQueue and a new BufferLayerConsumer are created when the
- * BufferLayer is first referenced.
- *
- * This also implements onFrameAvailable(), which notifies SurfaceFlinger
- * that new data has arrived.
- */
-class BufferQueueLayer : public BufferLayer {
-public:
- // Only call while mStateLock is held
- explicit BufferQueueLayer(const LayerCreationArgs&);
- ~BufferQueueLayer() override;
-
- // Implements Layer.
- const char* getType() const override { return "BufferQueueLayer"; }
-
- void onLayerDisplayed(ftl::SharedFuture<FenceResult>) override;
-
- // If a buffer was replaced this frame, release the former buffer
- void releasePendingBuffer(nsecs_t dequeueReadyTime) override;
-
- void setDefaultBufferSize(uint32_t w, uint32_t h) override;
-
- int32_t getQueuedFrameCount() const override;
-
- // Returns true if the next buffer should be presented at the expected present time
- bool isBufferDue(nsecs_t expectedPresentTime) const override;
-
- // Implements BufferLayer.
- bool fenceHasSignaled() const override;
- bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const override;
-
- status_t setDefaultBufferProperties(uint32_t w, uint32_t h, PixelFormat format);
- sp<IGraphicBufferProducer> getProducer() const;
-
- void setSizeForTest(uint32_t w, uint32_t h) {
- mDrawingState.active_legacy.w = w;
- mDrawingState.active_legacy.h = h;
- }
-
-protected:
- void gatherBufferInfo() override;
-
- // -----------------------------------------------------------------------
- // Interface implementation for BufferLayerConsumer::ContentsChangedListener
- // -----------------------------------------------------------------------
- class ContentsChangedListener : public BufferLayerConsumer::ContentsChangedListener {
- public:
- ContentsChangedListener(BufferQueueLayer* bufferQueueLayer)
- : mBufferQueueLayer(bufferQueueLayer) {}
- void abandon();
-
- protected:
- void onFrameAvailable(const BufferItem& item) override;
- void onFrameReplaced(const BufferItem& item) override;
- void onSidebandStreamChanged() override;
- void onFrameDequeued(const uint64_t bufferId) override;
- void onFrameDetached(const uint64_t bufferId) override;
- void onFrameCancelled(const uint64_t bufferId) override;
-
- private:
- BufferQueueLayer* mBufferQueueLayer = nullptr;
- Mutex mMutex;
- };
-
-private:
-
- bool latchSidebandStream(bool& recomputeVisibleRegions) override;
- void setTransformHint(ui::Transform::RotationFlags displayTransformHint) override;
-
- bool hasFrameUpdate() const override;
-
- status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime,
- nsecs_t expectedPresentTime) override;
-
- status_t updateActiveBuffer() override;
- status_t updateFrameNumber() override;
- void setFrameTimelineInfoForBuffer(const FrameTimelineInfo& frameTimelineInfo) override;
-
- sp<Layer> createClone() override;
-
- void onFirstRef() override;
-
- void onFrameAvailable(const BufferItem& item);
- void onFrameReplaced(const BufferItem& item);
- void onSidebandStreamChanged();
- void onFrameDequeued(const uint64_t bufferId);
- void onFrameDetached(const uint64_t bufferId);
- void onFrameCancelled(const uint64_t bufferId);
-
- // Temporary - Used only for LEGACY camera mode.
- uint32_t getProducerStickyTransform() const;
-
- sp<BufferLayerConsumer> mConsumer;
- sp<IGraphicBufferProducer> mProducer;
-
- bool mUpdateTexImageFailed{false};
-
- uint64_t mPreviousBufferId = 0;
- uint64_t mPreviousReleasedFrameNumber = 0;
-
- // Local copy of the queued contents of the incoming BufferQueue
- mutable Mutex mQueueItemLock;
- Condition mQueueItemCondition;
-
- struct BufferData {
- BufferData(BufferItem item, std::shared_ptr<frametimeline::SurfaceFrame> surfaceFrame)
- : item(item), surfaceFrame(surfaceFrame) {}
- BufferItem item;
- std::shared_ptr<frametimeline::SurfaceFrame> surfaceFrame;
- };
- std::vector<BufferData> mQueueItems;
- std::atomic<uint64_t> mLastFrameNumberReceived{0};
-
- // thread-safe
- std::atomic<int32_t> mQueuedFrames{0};
-
- sp<ContentsChangedListener> mContentsChangedListener;
-
- // The last vsync info received on this layer. This will be used when we get
- // a buffer to correlate the buffer with the vsync id. Can only be accessed
- // with the SF state lock held.
- FrameTimelineInfo mFrameTimelineInfo;
-};
-
-} // namespace android
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 3875f15..574e2f5 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -30,6 +30,7 @@
#include <renderengine/Image.h>
#include "TunnelModeEnabledReporter.h"
+#include <gui/TraceUtils.h>
#include "EffectLayer.h"
#include "FrameTracer/FrameTracer.h"
#include "TimeStats/TimeStats.h"
@@ -39,19 +40,20 @@
namespace android {
using PresentState = frametimeline::SurfaceFrame::PresentState;
-namespace {
-void callReleaseBufferCallback(const sp<ITransactionCompletedListener>& listener,
- const sp<GraphicBuffer>& buffer, uint64_t framenumber,
- const sp<Fence>& releaseFence,
- uint32_t currentMaxAcquiredBufferCount) {
+
+void BufferStateLayer::callReleaseBufferCallback(const sp<ITransactionCompletedListener>& listener,
+ const sp<GraphicBuffer>& buffer,
+ uint64_t framenumber,
+ const sp<Fence>& releaseFence,
+ uint32_t currentMaxAcquiredBufferCount) {
if (!listener) {
return;
}
+ ATRACE_FORMAT_INSTANT("callReleaseBufferCallback %s - %" PRIu64, getDebugName(), framenumber);
listener->onReleaseBuffer({buffer->getId(), framenumber},
releaseFence ? releaseFence : Fence::NO_FENCE,
currentMaxAcquiredBufferCount);
}
-} // namespace
BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args)
: BufferLayer(args), mHwcSlotGenerator(new HwcSlotGenerator()) {
@@ -145,6 +147,8 @@
handle->dequeueReadyTime = dequeueReadyTime;
handle->currentMaxAcquiredBufferCount =
mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(mOwnerUid);
+ ATRACE_FORMAT_INSTANT("releasePendingBuffer %s - %" PRIu64, getDebugName(),
+ handle->previousReleaseCallbackId.framenumber);
}
for (auto& handle : mDrawingState.callbackHandles) {
@@ -853,7 +857,15 @@
}
const Rect layerSize{getBounds()};
- return layerSize.width() != bufferWidth || layerSize.height() != bufferHeight;
+ int32_t layerWidth = layerSize.getWidth();
+ int32_t layerHeight = layerSize.getHeight();
+
+ // Align the layer orientation with the buffer before comparism
+ if (mTransformHint & ui::Transform::ROT_90) {
+ std::swap(layerWidth, layerHeight);
+ }
+
+ return layerWidth != bufferWidth || layerHeight != bufferHeight;
}
void BufferStateLayer::decrementPendingBufferCount() {
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 3f0dbe4..bf98a27 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -135,6 +135,11 @@
bool simpleBufferUpdate(const layer_state_t& s) const override;
+ void callReleaseBufferCallback(const sp<ITransactionCompletedListener>& listener,
+ const sp<GraphicBuffer>& buffer, uint64_t framenumber,
+ const sp<Fence>& releaseFence,
+ uint32_t currentMaxAcquiredBufferCount);
+
ReleaseCallbackId mPreviousReleaseCallbackId = ReleaseCallbackId::INVALID_ID;
uint64_t mPreviousReleasedFrameNumber = 0;
diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp
index 6d7b732..b27055d 100644
--- a/services/surfaceflinger/Client.cpp
+++ b/services/surfaceflinger/Client.cpp
@@ -21,12 +21,16 @@
#include <private/android_filesystem_config.h>
+#include <gui/AidlStatusUtil.h>
+
#include "Client.h"
#include "Layer.h"
#include "SurfaceFlinger.h"
namespace android {
+using gui::aidl_utils::binderStatusFromStatusT;
+
// ---------------------------------------------------------------------------
const String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER");
@@ -72,52 +76,74 @@
return lbc;
}
-status_t Client::createSurface(const String8& name, uint32_t /* w */, uint32_t /* h */,
- PixelFormat /* format */, uint32_t flags,
- const sp<IBinder>& parentHandle, LayerMetadata metadata,
- sp<IBinder>* outHandle, sp<IGraphicBufferProducer>* /* gbp */,
- int32_t* outLayerId, uint32_t* outTransformHint) {
+binder::Status Client::createSurface(const std::string& name, int32_t flags,
+ const sp<IBinder>& parent, const gui::LayerMetadata& metadata,
+ gui::CreateSurfaceResult* outResult) {
// We rely on createLayer to check permissions.
- LayerCreationArgs args(mFlinger.get(), this, name.c_str(), flags, std::move(metadata));
- return mFlinger->createLayer(args, outHandle, parentHandle, outLayerId, nullptr,
- outTransformHint);
+ sp<IBinder> handle;
+ int32_t layerId;
+ uint32_t transformHint;
+ LayerCreationArgs args(mFlinger.get(), this, name.c_str(), static_cast<uint32_t>(flags),
+ std::move(metadata));
+ const status_t status =
+ mFlinger->createLayer(args, &handle, parent, &layerId, nullptr, &transformHint);
+ if (status == NO_ERROR) {
+ outResult->handle = handle;
+ outResult->layerId = layerId;
+ outResult->transformHint = static_cast<int32_t>(transformHint);
+ }
+ return binderStatusFromStatusT(status);
}
-status_t Client::createWithSurfaceParent(const String8& /* name */, uint32_t /* w */,
- uint32_t /* h */, PixelFormat /* format */,
- uint32_t /* flags */,
- const sp<IGraphicBufferProducer>& /* parent */,
- LayerMetadata /* metadata */, sp<IBinder>* /* handle */,
- sp<IGraphicBufferProducer>* /* gbp */,
- int32_t* /* outLayerId */,
- uint32_t* /* outTransformHint */) {
- // This api does not make sense with blast since SF no longer tracks IGBP. This api should be
- // removed.
- return BAD_VALUE;
-}
-
-status_t Client::mirrorSurface(const sp<IBinder>& mirrorFromHandle, sp<IBinder>* outHandle,
- int32_t* outLayerId) {
- LayerCreationArgs args(mFlinger.get(), this, "MirrorRoot", 0 /* flags */, LayerMetadata());
- return mFlinger->mirrorLayer(args, mirrorFromHandle, outHandle, outLayerId);
-}
-
-status_t Client::clearLayerFrameStats(const sp<IBinder>& handle) const {
+binder::Status Client::clearLayerFrameStats(const sp<IBinder>& handle) {
+ status_t status;
sp<Layer> layer = getLayerUser(handle);
if (layer == nullptr) {
- return NAME_NOT_FOUND;
+ status = NAME_NOT_FOUND;
+ } else {
+ layer->clearFrameStats();
+ status = NO_ERROR;
}
- layer->clearFrameStats();
- return NO_ERROR;
+ return binderStatusFromStatusT(status);
}
-status_t Client::getLayerFrameStats(const sp<IBinder>& handle, FrameStats* outStats) const {
+binder::Status Client::getLayerFrameStats(const sp<IBinder>& handle, gui::FrameStats* outStats) {
+ status_t status;
sp<Layer> layer = getLayerUser(handle);
if (layer == nullptr) {
- return NAME_NOT_FOUND;
+ status = NAME_NOT_FOUND;
+ } else {
+ FrameStats stats;
+ layer->getFrameStats(&stats);
+ outStats->refreshPeriodNano = stats.refreshPeriodNano;
+ outStats->desiredPresentTimesNano.reserve(stats.desiredPresentTimesNano.size());
+ for (const auto& t : stats.desiredPresentTimesNano) {
+ outStats->desiredPresentTimesNano.push_back(t);
+ }
+ outStats->actualPresentTimesNano.reserve(stats.actualPresentTimesNano.size());
+ for (const auto& t : stats.actualPresentTimesNano) {
+ outStats->actualPresentTimesNano.push_back(t);
+ }
+ outStats->frameReadyTimesNano.reserve(stats.frameReadyTimesNano.size());
+ for (const auto& t : stats.frameReadyTimesNano) {
+ outStats->frameReadyTimesNano.push_back(t);
+ }
+ status = NO_ERROR;
}
- layer->getFrameStats(outStats);
- return NO_ERROR;
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status Client::mirrorSurface(const sp<IBinder>& mirrorFromHandle,
+ gui::MirrorSurfaceResult* outResult) {
+ sp<IBinder> handle;
+ int32_t layerId;
+ LayerCreationArgs args(mFlinger.get(), this, "MirrorRoot", 0 /* flags */, gui::LayerMetadata());
+ status_t status = mFlinger->mirrorLayer(args, mirrorFromHandle, &handle, &layerId);
+ if (status == NO_ERROR) {
+ outResult->handle = handle;
+ outResult->layerId = layerId;
+ }
+ return binderStatusFromStatusT(status);
}
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h
index 15cd763..4720d5c 100644
--- a/services/surfaceflinger/Client.h
+++ b/services/surfaceflinger/Client.h
@@ -24,15 +24,14 @@
#include <utils/KeyedVector.h>
#include <utils/Mutex.h>
-#include <gui/ISurfaceComposerClient.h>
+#include <android/gui/BnSurfaceComposerClient.h>
namespace android {
class Layer;
class SurfaceFlinger;
-class Client : public BnSurfaceComposerClient
-{
+class Client : public gui::BnSurfaceComposerClient {
public:
explicit Client(const sp<SurfaceFlinger>& flinger);
~Client() = default;
@@ -47,25 +46,18 @@
private:
// ISurfaceComposerClient interface
- virtual status_t createSurface(const String8& name, uint32_t w, uint32_t h, PixelFormat format,
- uint32_t flags, const sp<IBinder>& parent,
- LayerMetadata metadata, sp<IBinder>* handle,
- sp<IGraphicBufferProducer>* gbp, int32_t* outLayerId,
- uint32_t* outTransformHint = nullptr);
- virtual status_t createWithSurfaceParent(const String8& name, uint32_t w, uint32_t h,
- PixelFormat format, uint32_t flags,
- const sp<IGraphicBufferProducer>& parent,
- LayerMetadata metadata, sp<IBinder>* handle,
- sp<IGraphicBufferProducer>* gbp, int32_t* outLayerId,
- uint32_t* outTransformHint = nullptr);
+ binder::Status createSurface(const std::string& name, int32_t flags, const sp<IBinder>& parent,
+ const gui::LayerMetadata& metadata,
+ gui::CreateSurfaceResult* outResult) override;
- status_t mirrorSurface(const sp<IBinder>& mirrorFromHandle, sp<IBinder>* handle,
- int32_t* outLayerId);
+ binder::Status clearLayerFrameStats(const sp<IBinder>& handle) override;
- virtual status_t clearLayerFrameStats(const sp<IBinder>& handle) const;
+ binder::Status getLayerFrameStats(const sp<IBinder>& handle,
+ gui::FrameStats* outStats) override;
- virtual status_t getLayerFrameStats(const sp<IBinder>& handle, FrameStats* outStats) const;
+ binder::Status mirrorSurface(const sp<IBinder>& mirrorFromHandle,
+ gui::MirrorSurfaceResult* outResult) override;
// constant
sp<SurfaceFlinger> mFlinger;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
index f201751..f861fc9 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h
@@ -32,6 +32,11 @@
using Layers = std::vector<sp<compositionengine::LayerFE>>;
using Outputs = std::vector<std::shared_ptr<compositionengine::Output>>;
+struct BorderRenderInfo {
+ float width = 0;
+ half4 color;
+ std::vector<int32_t> layerIds;
+};
/**
* A parameter object for refreshing a set of outputs
*/
@@ -90,6 +95,8 @@
// If set, a frame has been scheduled for that time.
std::optional<std::chrono::steady_clock::time_point> scheduledFrameTime;
+
+ std::vector<BorderRenderInfo> borderInfoList;
};
} // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
index df721cd..fc8dd8b 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -154,6 +154,7 @@
private:
void dirtyEntireOutput();
+ void updateCompositionStateForBorder(const compositionengine::CompositionRefreshArgs&);
compositionengine::OutputLayer* findLayerRequestingBackgroundComposition() const;
void finishPrepareFrame();
ui::Dataspace getBestDataspace(ui::Dataspace*, bool*) const;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
index 7709b96..c291652 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h
@@ -33,6 +33,7 @@
#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
#include <compositionengine/ProjectionSpace.h>
+#include <renderengine/BorderRenderInfo.h>
#include <ui/LayerStack.h>
#include <ui/Rect.h>
#include <ui/Region.h>
@@ -164,6 +165,8 @@
bool treat170mAsSrgb = false;
+ std::vector<renderengine::BorderRenderInfo> borderInfoList;
+
uint64_t lastOutputLayerHash = 0;
uint64_t outputLayerHash = 0;
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 070b285..aea6798 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -586,8 +586,29 @@
// Remove the transparent area from the visible region
if (!layerFEState->isOpaque) {
if (tr.preserveRects()) {
- // transform the transparent region
- transparentRegion = tr.transform(layerFEState->transparentRegionHint);
+ // Clip the transparent region to geomLayerBounds first
+ // The transparent region may be influenced by applications, for
+ // instance, by overriding ViewGroup#gatherTransparentRegion with a
+ // custom view. Once the layer stack -> display mapping is known, we
+ // must guard against very wrong inputs to prevent underflow or
+ // overflow errors. We do this here by constraining the transparent
+ // region to be within the pre-transform layer bounds, since the
+ // layer bounds are expected to play nicely with the full
+ // transform.
+ const Region clippedTransparentRegionHint =
+ layerFEState->transparentRegionHint.intersect(
+ Rect(layerFEState->geomLayerBounds));
+
+ if (clippedTransparentRegionHint.isEmpty()) {
+ if (!layerFEState->transparentRegionHint.isEmpty()) {
+ ALOGD("Layer: %s had an out of bounds transparent region",
+ layerFE->getDebugName());
+ layerFEState->transparentRegionHint.dump("transparentRegionHint");
+ }
+ transparentRegion.clear();
+ } else {
+ transparentRegion = tr.transform(clippedTransparentRegionHint);
+ }
} else {
// transformation too complex, can't do the
// transparent region optimization.
@@ -733,6 +754,44 @@
forceClientComposition = false;
}
}
+
+ updateCompositionStateForBorder(refreshArgs);
+}
+
+void Output::updateCompositionStateForBorder(
+ const compositionengine::CompositionRefreshArgs& refreshArgs) {
+ std::unordered_map<int32_t, const Region*> layerVisibleRegionMap;
+ // Store a map of layerId to their computed visible region.
+ for (auto* layer : getOutputLayersOrderedByZ()) {
+ int layerId = (layer->getLayerFE()).getSequence();
+ layerVisibleRegionMap[layerId] = &((layer->getState()).visibleRegion);
+ }
+ OutputCompositionState& outputCompositionState = editState();
+ outputCompositionState.borderInfoList.clear();
+ bool clientComposeTopLayer = false;
+ for (const auto& borderInfo : refreshArgs.borderInfoList) {
+ renderengine::BorderRenderInfo info;
+ for (const auto& id : borderInfo.layerIds) {
+ info.combinedRegion.orSelf(*(layerVisibleRegionMap[id]));
+ }
+
+ if (!info.combinedRegion.isEmpty()) {
+ info.width = borderInfo.width;
+ info.color = borderInfo.color;
+ outputCompositionState.borderInfoList.emplace_back(std::move(info));
+ clientComposeTopLayer = true;
+ }
+ }
+
+ // In this situation we must client compose the top layer instead of using hwc
+ // because we want to draw the border above all else.
+ // This could potentially cause a bit of a performance regression if the top
+ // layer would have been rendered using hwc originally.
+ // TODO(b/227656283): Measure system's performance before enabling the border feature
+ if (clientComposeTopLayer) {
+ auto topLayer = getOutputLayerOrderedByZByIndex(getOutputLayerCount() - 1);
+ (topLayer->editState()).forceClientComposition = true;
+ }
}
void Output::planComposition() {
@@ -1199,6 +1258,13 @@
// Compute the global color transform matrix.
clientCompositionDisplay.colorTransform = outputState.colorTransformMatrix;
+ for (auto& info : outputState.borderInfoList) {
+ renderengine::BorderRenderInfo borderInfo;
+ borderInfo.width = info.width;
+ borderInfo.color = info.color;
+ borderInfo.combinedRegion = info.combinedRegion;
+ clientCompositionDisplay.borderInfoList.emplace_back(std::move(borderInfo));
+ }
clientCompositionDisplay.deviceHandlesColorTransform =
outputState.usesDeviceComposition || getSkipColorTransform();
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp
index 948c0c9..c512a1e 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputCompositionState.cpp
@@ -62,14 +62,18 @@
dumpVal(out, "sdrWhitePointNits", sdrWhitePointNits);
dumpVal(out, "clientTargetBrightness", clientTargetBrightness);
dumpVal(out, "displayBrightness", displayBrightness);
-
out.append("\n ");
dumpVal(out, "compositionStrategyPredictionState", ftl::enum_string(strategyPrediction));
+ out.append("\n ");
out.append("\n ");
dumpVal(out, "treate170mAsSrgb", treat170mAsSrgb);
- out += '\n';
+ out.append("\n");
+ for (const auto& borderRenderInfo : borderInfoList) {
+ dumpVal(out, "borderRegion", borderRenderInfo.combinedRegion);
+ }
+ out.append("\n");
}
} // namespace android::compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 505f94e..cf12890 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -1505,6 +1505,8 @@
static const Region kTransparentRegionHint;
static const Region kTransparentRegionHintTwo;
static const Region kTransparentRegionHintTwo90Rotation;
+ static const Region kTransparentRegionHintNegative;
+ static const Region kTransparentRegionHintNegativeIntersectsBounds;
StrictMock<OutputPartialMock> mOutput;
LayerFESet mGeomSnapshots;
@@ -1528,6 +1530,10 @@
Region(Rect(25, 20, 50, 75));
const Region OutputEnsureOutputLayerIfVisibleTest::kTransparentRegionHintTwo90Rotation =
Region(Rect(125, 25, 180, 50));
+const Region OutputEnsureOutputLayerIfVisibleTest::kTransparentRegionHintNegative =
+ Region(Rect(INT32_MIN, INT32_MIN, INT32_MIN + 100, INT32_MIN + 200));
+const Region OutputEnsureOutputLayerIfVisibleTest::kTransparentRegionHintNegativeIntersectsBounds =
+ Region(Rect(INT32_MIN, INT32_MIN, 100, 100));
TEST_F(OutputEnsureOutputLayerIfVisibleTest, performsGeomLatchBeforeCheckingIfLayerIncluded) {
EXPECT_CALL(mOutput, includesLayer(sp<LayerFE>(mLayer.layerFE))).WillOnce(Return(false));
@@ -1997,6 +2003,41 @@
RegionEq(kTransparentRegionHintTwo90Rotation));
}
+TEST_F(OutputEnsureOutputLayerIfVisibleTest, transparentRegionExcludesOutputLayer) {
+ mLayer.layerFEState.isOpaque = false;
+ mLayer.layerFEState.contentDirty = true;
+ mLayer.layerFEState.geomLayerBounds = kFullBoundsNoRotation.bounds().toFloatRect();
+ mLayer.layerFEState.transparentRegionHint = kFullBoundsNoRotation;
+
+ EXPECT_CALL(mOutput, ensureOutputLayer(_, _)).Times(0);
+}
+
+TEST_F(OutputEnsureOutputLayerIfVisibleTest, transparentRegionIgnoredWhenOutsideBounds) {
+ mLayer.layerFEState.isOpaque = false;
+ mLayer.layerFEState.contentDirty = true;
+ mLayer.layerFEState.geomLayerBounds = kFullBoundsNoRotation.bounds().toFloatRect();
+ mLayer.layerFEState.transparentRegionHint = kTransparentRegionHintNegative;
+
+ EXPECT_CALL(mOutput, ensureOutputLayer(_, _)).Times(0);
+}
+
+TEST_F(OutputEnsureOutputLayerIfVisibleTest, transparentRegionClipsWhenOutsideBounds) {
+ mLayer.layerFEState.isOpaque = false;
+ mLayer.layerFEState.contentDirty = true;
+ mLayer.layerFEState.compositionType =
+ aidl::android::hardware::graphics::composer3::Composition::DISPLAY_DECORATION;
+ mLayer.layerFEState.transparentRegionHint = kTransparentRegionHintNegativeIntersectsBounds;
+
+ EXPECT_CALL(mOutput, getOutputLayerCount()).WillOnce(Return(0u));
+ EXPECT_CALL(mOutput, ensureOutputLayer(Eq(std::nullopt), Eq(mLayer.layerFE)))
+ .WillOnce(Return(&mLayer.outputLayer));
+ ensureOutputLayerIfVisible();
+
+ // Check that the blocking region clips an out-of-bounds transparent region.
+ EXPECT_THAT(mLayer.outputLayerState.outputSpaceBlockingRegionHint,
+ RegionEq(kTransparentRegionHint));
+}
+
/*
* Output::present()
*/
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 24aef9b..486eaf8 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -88,7 +88,7 @@
virtual hal::HWDisplayId getId() const = 0;
virtual bool isConnected() const = 0;
- virtual void setConnected(bool connected) = 0; // For use by Device only
+ virtual void setConnected(bool connected) = 0; // For use by HWComposer only
virtual bool hasCapability(
aidl::android::hardware::graphics::composer3::DisplayCapability) const = 0;
virtual bool isVsyncPeriodSwitchSupported() const = 0;
@@ -253,7 +253,7 @@
// Other Display methods
hal::HWDisplayId getId() const override { return mId; }
bool isConnected() const override { return mIsConnected; }
- void setConnected(bool connected) override; // For use by Device only
+ void setConnected(bool connected) override;
bool hasCapability(aidl::android::hardware::graphics::composer3::DisplayCapability)
const override EXCLUDES(mDisplayCapabilitiesMutex);
bool isVsyncPeriodSwitchSupported() const override;
@@ -271,7 +271,7 @@
// Member variables
- // These are references to data owned by HWC2::Device, which will outlive
+ // These are references to data owned by HWComposer, which will outlive
// this HWC2::Display, so these references are guaranteed to be valid for
// the lifetime of this object.
android::Hwc2::Composer& mComposer;
@@ -383,7 +383,7 @@
hal::Error setBlockingRegion(const android::Region& region) override;
private:
- // These are references to data owned by HWC2::Device, which will outlive
+ // These are references to data owned by HWComposer, which will outlive
// this HWC2::Layer, so these references are guaranteed to be valid for
// the lifetime of this object.
android::Hwc2::Composer& mComposer;
diff --git a/services/surfaceflinger/FpsReporter.cpp b/services/surfaceflinger/FpsReporter.cpp
index e12835f..c89c9ff 100644
--- a/services/surfaceflinger/FpsReporter.cpp
+++ b/services/surfaceflinger/FpsReporter.cpp
@@ -56,8 +56,8 @@
mFlinger.mCurrentState.traverse([&](Layer* layer) {
auto& currentState = layer->getDrawingState();
- if (currentState.metadata.has(METADATA_TASK_ID)) {
- int32_t taskId = currentState.metadata.getInt32(METADATA_TASK_ID, 0);
+ if (currentState.metadata.has(gui::METADATA_TASK_ID)) {
+ int32_t taskId = currentState.metadata.getInt32(gui::METADATA_TASK_ID, 0);
if (seenTasks.count(taskId) == 0) {
// localListeners is expected to be tiny
for (TrackedListener& listener : localListeners) {
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
index 66beff2..3e69b5c 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
@@ -289,7 +289,7 @@
minTime = std::min(minTime, actuals.endTime);
}
if (actuals.presentTime != 0) {
- minTime = std::min(minTime, actuals.endTime);
+ minTime = std::min(minTime, actuals.presentTime);
}
return minTime;
}
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 38662bd..cabadb7 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -70,8 +70,6 @@
#include "FrameTimeline.h"
#include "FrameTracer/FrameTracer.h"
#include "LayerProtoHelper.h"
-#include "LayerRejecter.h"
-#include "MonitoredProducer.h"
#include "SurfaceFlinger.h"
#include "TimeStats/TimeStats.h"
#include "TunnelModeEnabledReporter.h"
@@ -86,6 +84,8 @@
using namespace ftl::flag_operators;
using base::StringAppendF;
+using gui::GameMode;
+using gui::LayerMetadata;
using gui::WindowInfo;
using PresentState = frametimeline::SurfaceFrame::PresentState;
@@ -97,8 +97,10 @@
mFlinger(args.flinger),
mName(base::StringPrintf("%s#%d", args.name.c_str(), sequence)),
mClientRef(args.client),
- mWindowType(static_cast<WindowInfo::Type>(args.metadata.getInt32(METADATA_WINDOW_TYPE, 0))),
- mLayerCreationFlags(args.flags) {
+ mWindowType(static_cast<WindowInfo::Type>(
+ args.metadata.getInt32(gui::METADATA_WINDOW_TYPE, 0))),
+ mLayerCreationFlags(args.flags),
+ mBorderEnabled(false) {
uint32_t layerFlags = 0;
if (args.flags & ISurfaceComposerClient::eHidden) layerFlags |= layer_state_t::eLayerHidden;
if (args.flags & ISurfaceComposerClient::eOpaque) layerFlags |= layer_state_t::eLayerOpaque;
@@ -144,6 +146,7 @@
mDrawingState.isTrustedOverlay = false;
mDrawingState.dropInputMode = gui::DropInputMode::NONE;
mDrawingState.dimmingEnabled = true;
+ mDrawingState.defaultFrameRateCompatibility = FrameRateCompatibility::Default;
if (args.flags & ISurfaceComposerClient::eNoColorFill) {
// Set an invalid color so there is no color fill.
@@ -151,17 +154,17 @@
mDrawingState.color.g = -1.0_hf;
mDrawingState.color.b = -1.0_hf;
}
- CompositorTiming compositorTiming;
- args.flinger->getCompositorTiming(&compositorTiming);
- mFrameTracker.setDisplayRefreshPeriod(compositorTiming.interval);
+
+ mFrameTracker.setDisplayRefreshPeriod(
+ args.flinger->mScheduler->getVsyncPeriodFromRefreshRateConfigs());
mCallingPid = args.callingPid;
mCallingUid = args.callingUid;
if (mCallingUid == AID_GRAPHICS || mCallingUid == AID_SYSTEM) {
// If the system didn't send an ownerUid, use the callingUid for the ownerUid.
- mOwnerUid = args.metadata.getInt32(METADATA_OWNER_UID, mCallingUid);
- mOwnerPid = args.metadata.getInt32(METADATA_OWNER_PID, mCallingPid);
+ mOwnerUid = args.metadata.getInt32(gui::METADATA_OWNER_UID, mCallingUid);
+ mOwnerPid = args.metadata.getInt32(gui::METADATA_OWNER_PID, mCallingPid);
} else {
// A create layer request from a non system request cannot specify the owner uid
mOwnerUid = mCallingUid;
@@ -405,7 +408,7 @@
const auto& drawingState{getDrawingState()};
const auto alpha = static_cast<float>(getAlpha());
const bool opaque = isOpaque(drawingState);
- const bool usesRoundedCorners = getRoundedCornerState().radius != 0.f;
+ const bool usesRoundedCorners = hasRoundedCorners();
auto blendMode = Hwc2::IComposerClient::BlendMode::NONE;
if (!opaque || alpha != 1.0f) {
@@ -481,7 +484,7 @@
compositionState->hasProtectedContent = isProtected();
compositionState->dimmingEnabled = isDimmingEnabled();
- const bool usesRoundedCorners = getRoundedCornerState().radius != 0.f;
+ const bool usesRoundedCorners = hasRoundedCorners();
compositionState->isOpaque =
isOpaque(drawingState) && !usesRoundedCorners && getAlpha() == 1.0_hf;
@@ -720,7 +723,7 @@
if (s.sequence != mLastCommittedTxSequence) {
// invalidate and recompute the visible regions if needed
- mLastCommittedTxSequence = s.sequence;
+ mLastCommittedTxSequence = s.sequence;
flags |= eVisibleRegion;
this->contentDirty = true;
@@ -728,6 +731,10 @@
mNeedsFiltering = getActiveTransform(s).needsBilinearFiltering();
}
+ if (!mPotentialCursor && (flags & Layer::eVisibleRegion)) {
+ mFlinger->mUpdateInputInfo = true;
+ }
+
commitTransaction(mDrawingState);
return flags;
@@ -878,7 +885,7 @@
if (mDrawingState.isTrustedOverlay == isTrustedOverlay) return false;
mDrawingState.isTrustedOverlay = isTrustedOverlay;
mDrawingState.modified = true;
- mFlinger->mInputInfoChanged = true;
+ mFlinger->mUpdateInputInfo = true;
setTransactionFlags(eTransactionNeeded);
return true;
}
@@ -975,6 +982,13 @@
return true;
}
bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix) {
+ if (matrix.dsdx == mDrawingState.transform.dsdx() &&
+ matrix.dtdy == mDrawingState.transform.dtdy() &&
+ matrix.dtdx == mDrawingState.transform.dtdx() &&
+ matrix.dsdy == mDrawingState.transform.dsdy()) {
+ return false;
+ }
+
ui::Transform t;
t.set(matrix.dsdx, matrix.dtdy, matrix.dtdx, matrix.dsdy);
@@ -1086,6 +1100,19 @@
return Layer::PRIORITY_UNSET;
}
+bool Layer::setDefaultFrameRateCompatibility(FrameRateCompatibility compatibility) {
+ if (mDrawingState.defaultFrameRateCompatibility == compatibility) return false;
+ mDrawingState.defaultFrameRateCompatibility = compatibility;
+ mDrawingState.modified = true;
+ mFlinger->mScheduler->setDefaultFrameRateCompatibility(this);
+ setTransactionFlags(eTransactionNeeded);
+ return true;
+}
+
+scheduler::LayerInfo::FrameRateCompatibility Layer::getDefaultFrameRateCompatibility() const {
+ return mDrawingState.defaultFrameRateCompatibility;
+}
+
bool Layer::isLayerFocusedBasedOnPriority(int32_t priority) {
return priority == PRIORITY_FOCUSED_WITH_MODE || priority == PRIORITY_FOCUSED_WITHOUT_MODE;
};
@@ -1150,6 +1177,28 @@
return StretchEffect{};
}
+bool Layer::enableBorder(bool shouldEnable, float width, const half4& color) {
+ if (mBorderEnabled == shouldEnable && mBorderWidth == width && mBorderColor == color) {
+ return false;
+ }
+ mBorderEnabled = shouldEnable;
+ mBorderWidth = width;
+ mBorderColor = color;
+ return true;
+}
+
+bool Layer::isBorderEnabled() {
+ return mBorderEnabled;
+}
+
+float Layer::getBorderWidth() {
+ return mBorderWidth;
+}
+
+const half4& Layer::getBorderColor() {
+ return mBorderColor;
+}
+
bool Layer::propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool* transactionNeeded) {
// The frame rate for layer tree is this layer's frame rate if present, or the parent frame rate
const auto frameRate = [&] {
@@ -1398,10 +1447,10 @@
// ----------------------------------------------------------------------------
// TODO(marissaw): add new layer state info to layer debugging
-LayerDebugInfo Layer::getLayerDebugInfo(const DisplayDevice* display) const {
+gui::LayerDebugInfo Layer::getLayerDebugInfo(const DisplayDevice* display) const {
using namespace std::string_literals;
- LayerDebugInfo info;
+ gui::LayerDebugInfo info;
const State& ds = getDrawingState();
info.mName = getName();
sp<Layer> parent = mDrawingParent.promote();
@@ -1550,8 +1599,9 @@
void Layer::setGameModeForTree(GameMode gameMode) {
const auto& currentState = getDrawingState();
- if (currentState.metadata.has(METADATA_GAME_MODE)) {
- gameMode = static_cast<GameMode>(currentState.metadata.getInt32(METADATA_GAME_MODE, 0));
+ if (currentState.metadata.has(gui::METADATA_GAME_MODE)) {
+ gameMode =
+ static_cast<GameMode>(currentState.metadata.getInt32(gui::METADATA_GAME_MODE, 0));
}
setGameMode(gameMode);
for (const sp<Layer>& child : mCurrentChildren) {
@@ -1916,27 +1966,22 @@
const auto& parent = mDrawingParent.promote();
if (parent != nullptr) {
parentSettings = parent->getRoundedCornerState();
- if (parentSettings.radius > 0) {
+ if (parentSettings.hasRoundedCorners()) {
ui::Transform t = getActiveTransform(getDrawingState());
t = t.inverse();
parentSettings.cropRect = t.transform(parentSettings.cropRect);
- // The rounded corners shader only accepts 1 corner radius for performance reasons,
- // but a transform matrix can define horizontal and vertical scales.
- // Let's take the average between both of them and pass into the shader, practically we
- // never do this type of transformation on windows anyway.
- auto scaleX = sqrtf(t[0][0] * t[0][0] + t[0][1] * t[0][1]);
- auto scaleY = sqrtf(t[1][0] * t[1][0] + t[1][1] * t[1][1]);
- parentSettings.radius *= (scaleX + scaleY) / 2.0f;
+ parentSettings.radius.x *= t.getScaleX();
+ parentSettings.radius.y *= t.getScaleY();
}
}
// Get layer settings
Rect layerCropRect = getCroppedBufferSize(getDrawingState());
- const float radius = getDrawingState().cornerRadius;
+ const vec2 radius(getDrawingState().cornerRadius, getDrawingState().cornerRadius);
RoundedCornerState layerSettings(layerCropRect.toFloatRect(), radius);
- const bool layerSettingsValid = layerSettings.radius > 0 && layerCropRect.isValid();
+ const bool layerSettingsValid = layerSettings.hasRoundedCorners() && layerCropRect.isValid();
- if (layerSettingsValid && parentSettings.radius > 0) {
+ if (layerSettingsValid && parentSettings.hasRoundedCorners()) {
// If the parent and the layer have rounded corner settings, use the parent settings if the
// parent crop is entirely inside the layer crop.
// This has limitations and cause rendering artifacts. See b/200300845 for correct fix.
@@ -1950,7 +1995,7 @@
}
} else if (layerSettingsValid) {
return layerSettings;
- } else if (parentSettings.radius > 0) {
+ } else if (parentSettings.hasRoundedCorners()) {
return parentSettings;
}
return {};
@@ -2026,7 +2071,7 @@
mDrawingState.inputInfo = info;
mDrawingState.touchableRegionCrop = fromHandle(info.touchableRegionCropHandle.promote());
mDrawingState.modified = true;
- mFlinger->mInputInfoChanged = true;
+ mFlinger->mUpdateInputInfo = true;
setTransactionFlags(eTransactionNeeded);
}
@@ -2071,7 +2116,8 @@
layerInfo->set_effective_scaling_mode(getEffectiveScalingMode());
layerInfo->set_requested_corner_radius(getDrawingState().cornerRadius);
- layerInfo->set_corner_radius(getRoundedCornerState().radius);
+ layerInfo->set_corner_radius(
+ (getRoundedCornerState().radius.x + getRoundedCornerState().radius.y) / 2.0);
layerInfo->set_background_blur_radius(getBackgroundBlurRadius());
layerInfo->set_is_trusted_overlay(isTrustedOverlay());
LayerProtoHelper::writeToProtoDeprecated(transform, layerInfo->mutable_transform());
@@ -2425,7 +2471,7 @@
// If the layer is a clone, we need to crop the input region to cloned root to prevent
// touches from going outside the cloned area.
if (isClone()) {
- info.isClone = true;
+ info.inputConfig |= WindowInfo::InputConfig::CLONE;
if (const sp<Layer> clonedRoot = getClonedRoot()) {
const Rect rect = displayTransform.transform(Rect{clonedRoot->mScreenBounds});
info.touchableRegion = info.touchableRegion.intersect(rect);
@@ -2605,6 +2651,8 @@
return FrameRateCompatibility::ExactOrMultiple;
case ANATIVEWINDOW_FRAME_RATE_EXACT:
return FrameRateCompatibility::Exact;
+ case ANATIVEWINDOW_FRAME_RATE_MIN:
+ return FrameRateCompatibility::Min;
case ANATIVEWINDOW_FRAME_RATE_NO_VOTE:
return FrameRateCompatibility::NoVote;
default:
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 24abad9..b809c8a 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -17,8 +17,8 @@
#pragma once
#include <android/gui/DropInputMode.h>
+#include <android/gui/ISurfaceComposerClient.h>
#include <gui/BufferQueue.h>
-#include <gui/ISurfaceComposerClient.h>
#include <gui/LayerState.h>
#include <gui/WindowInfo.h>
#include <layerproto/LayerProtoHeader.h>
@@ -53,7 +53,6 @@
#include "DisplayHardware/HWComposer.h"
#include "FrameTracker.h"
#include "LayerVector.h"
-#include "MonitoredProducer.h"
#include "RenderArea.h"
#include "Scheduler/LayerInfo.h"
#include "SurfaceFlinger.h"
@@ -69,13 +68,16 @@
class DisplayDevice;
class GraphicBuffer;
class SurfaceFlinger;
-class LayerDebugInfo;
namespace compositionengine {
class OutputLayer;
struct LayerFECompositionState;
}
+namespace gui {
+class LayerDebugInfo;
+}
+
namespace impl {
class SurfaceInterceptor;
}
@@ -134,13 +136,14 @@
struct RoundedCornerState {
RoundedCornerState() = default;
- RoundedCornerState(FloatRect cropRect, float radius)
+ RoundedCornerState(const FloatRect& cropRect, const vec2& radius)
: cropRect(cropRect), radius(radius) {}
// Rounded rectangle in local layer coordinate space.
FloatRect cropRect = FloatRect();
// Radius of the rounded rectangle.
- float radius = 0.0f;
+ vec2 radius;
+ bool hasRoundedCorners() const { return radius.x > 0.0f && radius.y > 0.0f; }
};
using FrameRate = scheduler::LayerInfo::FrameRate;
@@ -232,6 +235,9 @@
// Priority of the layer assigned by Window Manager.
int32_t frameRateSelectionPriority;
+ // Default frame rate compatibility used to set the layer refresh rate votetype.
+ FrameRateCompatibility defaultFrameRateCompatibility;
+
FrameRate frameRate;
// The combined frame rate of parents / children of this layer
@@ -435,6 +441,7 @@
virtual bool setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace);
virtual bool setColorSpaceAgnostic(const bool agnostic);
virtual bool setDimmingEnabled(const bool dimmingEnabled);
+ virtual bool setDefaultFrameRateCompatibility(FrameRateCompatibility compatibility);
virtual bool setFrameRateSelectionPriority(int32_t priority);
virtual bool setFixedTransformHint(ui::Transform::RotationFlags fixedTransformHint);
virtual void setAutoRefresh(bool /* autoRefresh */) {}
@@ -443,6 +450,9 @@
// If the variable is not set on the layer, it traverses up the tree to inherit the frame
// rate priority from its parent.
virtual int32_t getFrameRateSelectionPriority() const;
+ //
+ virtual FrameRateCompatibility getDefaultFrameRateCompatibility() const;
+ //
virtual ui::Dataspace getDataSpace() const { return ui::Dataspace::UNKNOWN; }
virtual sp<compositionengine::LayerFE> getCompositionEngineLayerFE() const;
@@ -596,7 +606,7 @@
// corner crop does not intersect with its own rounded corner crop.
virtual RoundedCornerState getRoundedCornerState() const;
- bool hasRoundedCorners() const override { return getRoundedCornerState().radius > .0f; }
+ bool hasRoundedCorners() const override { return getRoundedCornerState().hasRoundedCorners(); }
virtual PixelFormat getPixelFormat() const { return PIXEL_FORMAT_NONE; }
/**
@@ -735,7 +745,7 @@
inline const State& getDrawingState() const { return mDrawingState; }
inline State& getDrawingState() { return mDrawingState; }
- LayerDebugInfo getLayerDebugInfo(const DisplayDevice*) const;
+ gui::LayerDebugInfo getLayerDebugInfo(const DisplayDevice*) const;
void miniDump(std::string& result, const DisplayDevice&) const;
void dumpFrameStats(std::string& result) const;
@@ -885,6 +895,10 @@
bool setStretchEffect(const StretchEffect& effect);
StretchEffect getStretchEffect() const;
+ bool enableBorder(bool shouldEnable, float width, const half4& color);
+ bool isBorderEnabled();
+ float getBorderWidth();
+ const half4& getBorderColor();
virtual bool setBufferCrop(const Rect& /* bufferCrop */) { return false; }
virtual bool setDestinationFrame(const Rect& /* destinationFrame */) { return false; }
@@ -1126,7 +1140,12 @@
bool mIsAtRoot = false;
uint32_t mLayerCreationFlags;
+
bool findInHierarchy(const sp<Layer>&);
+
+ bool mBorderEnabled = false;
+ float mBorderWidth;
+ half4 mBorderColor;
};
std::ostream& operator<<(std::ostream& stream, const Layer::FrameRate& rate);
diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp
deleted file mode 100644
index 1c0263b..0000000
--- a/services/surfaceflinger/LayerRejecter.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-
-#include "LayerRejecter.h"
-
-#include <gui/BufferItem.h>
-#include <system/window.h>
-
-#define DEBUG_RESIZE 0
-
-namespace android {
-
-LayerRejecter::LayerRejecter(Layer::State& front, Layer::State& current,
- bool& recomputeVisibleRegions, bool stickySet, const std::string& name,
- bool transformToDisplayInverse)
- : mFront(front),
- mCurrent(current),
- mRecomputeVisibleRegions(recomputeVisibleRegions),
- mStickyTransformSet(stickySet),
- mName(name),
- mTransformToDisplayInverse(transformToDisplayInverse) {}
-
-bool LayerRejecter::reject(const sp<GraphicBuffer>& buf, const BufferItem& item) {
- if (buf == nullptr) {
- return false;
- }
-
- uint32_t bufWidth = buf->getWidth();
- uint32_t bufHeight = buf->getHeight();
-
- // check that we received a buffer of the right size
- // (Take the buffer's orientation into account)
- if (item.mTransform & ui::Transform::ROT_90) {
- std::swap(bufWidth, bufHeight);
- }
-
- if (mTransformToDisplayInverse) {
- uint32_t invTransform = DisplayDevice::getPrimaryDisplayRotationFlags();
- if (invTransform & ui::Transform::ROT_90) {
- std::swap(bufWidth, bufHeight);
- }
- }
-
- int actualScalingMode = item.mScalingMode;
- bool isFixedSize = actualScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
- if (mFront.active_legacy != mFront.requested_legacy) {
- if (isFixedSize ||
- (bufWidth == mFront.requested_legacy.w && bufHeight == mFront.requested_legacy.h)) {
- // Here we pretend the transaction happened by updating the
- // current and drawing states. Drawing state is only accessed
- // in this thread, no need to have it locked
- mFront.active_legacy = mFront.requested_legacy;
-
- // We also need to update the current state so that
- // we don't end-up overwriting the drawing state with
- // this stale current state during the next transaction
- //
- // NOTE: We don't need to hold the transaction lock here
- // because State::active_legacy is only accessed from this thread.
- mCurrent.active_legacy = mFront.active_legacy;
- mCurrent.modified = true;
-
- // recompute visible region
- mRecomputeVisibleRegions = true;
-
- if (mFront.crop != mFront.requestedCrop) {
- mFront.crop = mFront.requestedCrop;
- mCurrent.crop = mFront.requestedCrop;
- mRecomputeVisibleRegions = true;
- }
- }
-
- ALOGD_IF(DEBUG_RESIZE,
- "[%s] latchBuffer/reject: buffer (%ux%u, tr=%02x), scalingMode=%d\n"
- " drawing={ active_legacy ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} "
- "(%4d,%4d) "
- "}\n"
- " requested_legacy={ wh={%4u,%4u} }}\n",
- mName.c_str(), bufWidth, bufHeight, item.mTransform, item.mScalingMode,
- mFront.active_legacy.w, mFront.active_legacy.h, mFront.crop.left, mFront.crop.top,
- mFront.crop.right, mFront.crop.bottom, mFront.crop.getWidth(),
- mFront.crop.getHeight(), mFront.requested_legacy.w, mFront.requested_legacy.h);
- }
-
- if (!isFixedSize && !mStickyTransformSet) {
- if (mFront.active_legacy.w != bufWidth || mFront.active_legacy.h != bufHeight) {
- // reject this buffer
- ALOGE("[%s] rejecting buffer: "
- "bufWidth=%d, bufHeight=%d, front.active_legacy.{w=%d, h=%d}",
- mName.c_str(), bufWidth, bufHeight, mFront.active_legacy.w,
- mFront.active_legacy.h);
- return true;
- }
- }
-
- // if the transparent region has changed (this test is
- // conservative, but that's fine, worst case we're doing
- // a bit of extra work), we latch the new one and we
- // trigger a visible-region recompute.
- //
- // We latch the transparent region here, instead of above where we latch
- // the rest of the geometry because it is only content but not necessarily
- // resize dependent.
- if (!mFront.activeTransparentRegion_legacy.hasSameRects(
- mFront.requestedTransparentRegion_legacy)) {
- mFront.activeTransparentRegion_legacy = mFront.requestedTransparentRegion_legacy;
-
- // We also need to update the current state so that
- // we don't end-up overwriting the drawing state with
- // this stale current state during the next transaction
- //
- // NOTE: We don't need to hold the transaction lock here
- // because State::active_legacy is only accessed from this thread.
- mCurrent.activeTransparentRegion_legacy = mFront.activeTransparentRegion_legacy;
-
- // recompute visible region
- mRecomputeVisibleRegions = true;
- }
-
- return false;
-}
-
-} // namespace android
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/LayerRejecter.h b/services/surfaceflinger/LayerRejecter.h
deleted file mode 100644
index 4981f45..0000000
--- a/services/surfaceflinger/LayerRejecter.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2007 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 "Layer.h"
-#include "BufferLayerConsumer.h"
-
-namespace android {
-
-class LayerRejecter : public BufferLayerConsumer::BufferRejecter {
-public:
- LayerRejecter(Layer::State& front, Layer::State& current, bool& recomputeVisibleRegions,
- bool stickySet, const std::string& name,
- bool transformToDisplayInverse);
-
- virtual bool reject(const sp<GraphicBuffer>&, const BufferItem&);
-
-private:
- Layer::State& mFront;
- Layer::State& mCurrent;
- bool& mRecomputeVisibleRegions;
- const bool mStickyTransformSet;
- const std::string& mName;
- const bool mTransformToDisplayInverse;
-};
-
-} // namespace android
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
deleted file mode 100644
index df76f50..0000000
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright 2014 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.
- */
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-
-#include "MonitoredProducer.h"
-#include "Layer.h"
-#include "SurfaceFlinger.h"
-
-#include "Scheduler/MessageQueue.h"
-
-namespace android {
-
-MonitoredProducer::MonitoredProducer(const sp<IGraphicBufferProducer>& producer,
- const sp<SurfaceFlinger>& flinger,
- const wp<Layer>& layer) :
- mProducer(producer),
- mFlinger(flinger),
- mLayer(layer) {}
-
-MonitoredProducer::~MonitoredProducer() {}
-
-status_t MonitoredProducer::requestBuffer(int slot, sp<GraphicBuffer>* buf) {
- return mProducer->requestBuffer(slot, buf);
-}
-
-status_t MonitoredProducer::setMaxDequeuedBufferCount(
- int maxDequeuedBuffers) {
- return mProducer->setMaxDequeuedBufferCount(maxDequeuedBuffers);
-}
-
-status_t MonitoredProducer::setAsyncMode(bool async) {
- return mProducer->setAsyncMode(async);
-}
-
-status_t MonitoredProducer::dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h,
- PixelFormat format, uint64_t usage,
- uint64_t* outBufferAge,
- FrameEventHistoryDelta* outTimestamps) {
- return mProducer->dequeueBuffer(slot, fence, w, h, format, usage, outBufferAge, outTimestamps);
-}
-
-status_t MonitoredProducer::detachBuffer(int slot) {
- return mProducer->detachBuffer(slot);
-}
-
-status_t MonitoredProducer::detachNextBuffer(sp<GraphicBuffer>* outBuffer,
- sp<Fence>* outFence) {
- return mProducer->detachNextBuffer(outBuffer, outFence);
-}
-
-status_t MonitoredProducer::attachBuffer(int* outSlot,
- const sp<GraphicBuffer>& buffer) {
- return mProducer->attachBuffer(outSlot, buffer);
-}
-
-status_t MonitoredProducer::queueBuffer(int slot, const QueueBufferInput& input,
- QueueBufferOutput* output) {
- return mProducer->queueBuffer(slot, input, output);
-}
-
-status_t MonitoredProducer::cancelBuffer(int slot, const sp<Fence>& fence) {
- return mProducer->cancelBuffer(slot, fence);
-}
-
-int MonitoredProducer::query(int what, int* value) {
- return mProducer->query(what, value);
-}
-
-status_t MonitoredProducer::connect(const sp<IProducerListener>& listener,
- int api, bool producerControlledByApp, QueueBufferOutput* output) {
- return mProducer->connect(listener, api, producerControlledByApp, output);
-}
-
-status_t MonitoredProducer::disconnect(int api, DisconnectMode mode) {
- return mProducer->disconnect(api, mode);
-}
-
-status_t MonitoredProducer::setSidebandStream(const sp<NativeHandle>& stream) {
- return mProducer->setSidebandStream(stream);
-}
-
-void MonitoredProducer::allocateBuffers(uint32_t width, uint32_t height,
- PixelFormat format, uint64_t usage) {
- mProducer->allocateBuffers(width, height, format, usage);
-}
-
-status_t MonitoredProducer::allowAllocation(bool allow) {
- return mProducer->allowAllocation(allow);
-}
-
-status_t MonitoredProducer::setGenerationNumber(uint32_t generationNumber) {
- return mProducer->setGenerationNumber(generationNumber);
-}
-
-String8 MonitoredProducer::getConsumerName() const {
- return mProducer->getConsumerName();
-}
-
-status_t MonitoredProducer::setSharedBufferMode(bool sharedBufferMode) {
- return mProducer->setSharedBufferMode(sharedBufferMode);
-}
-
-status_t MonitoredProducer::setAutoRefresh(bool autoRefresh) {
- return mProducer->setAutoRefresh(autoRefresh);
-}
-
-status_t MonitoredProducer::setDequeueTimeout(nsecs_t timeout) {
- return mProducer->setDequeueTimeout(timeout);
-}
-
-status_t MonitoredProducer::setLegacyBufferDrop(bool drop) {
- return mProducer->setLegacyBufferDrop(drop);
-}
-
-status_t MonitoredProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
- sp<Fence>* outFence, float outTransformMatrix[16]) {
- return mProducer->getLastQueuedBuffer(outBuffer, outFence,
- outTransformMatrix);
-}
-
-status_t MonitoredProducer::getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence,
- Rect* outRect, uint32_t* outTransform) {
- return mProducer->getLastQueuedBuffer(outBuffer, outFence, outRect, outTransform);
-}
-
-void MonitoredProducer::getFrameTimestamps(FrameEventHistoryDelta* outDelta) {
- mProducer->getFrameTimestamps(outDelta);
-}
-
-status_t MonitoredProducer::getUniqueId(uint64_t* outId) const {
- return mProducer->getUniqueId(outId);
-}
-
-status_t MonitoredProducer::getConsumerUsage(uint64_t* outUsage) const {
- return mProducer->getConsumerUsage(outUsage);
-}
-
-status_t MonitoredProducer::setAutoPrerotation(bool autoPrerotation) {
- return mProducer->setAutoPrerotation(autoPrerotation);
-}
-
-IBinder* MonitoredProducer::onAsBinder() {
- return this;
-}
-
-sp<Layer> MonitoredProducer::getLayer() const {
- return mLayer.promote();
-}
-
-// ---------------------------------------------------------------------------
-}; // namespace android
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h
deleted file mode 100644
index 3778277..0000000
--- a/services/surfaceflinger/MonitoredProducer.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_MONITORED_PRODUCER_H
-#define ANDROID_MONITORED_PRODUCER_H
-
-#include <gui/IGraphicBufferProducer.h>
-
-namespace android {
-
-class IProducerListener;
-class NativeHandle;
-class SurfaceFlinger;
-class Layer;
-
-// MonitoredProducer wraps an IGraphicBufferProducer so that SurfaceFlinger will
-// be notified upon its destruction
-class MonitoredProducer : public BnGraphicBufferProducer {
-public:
- MonitoredProducer(const sp<IGraphicBufferProducer>& producer,
- const sp<SurfaceFlinger>& flinger,
- const wp<Layer>& layer);
- virtual ~MonitoredProducer();
-
- // From IGraphicBufferProducer
- virtual status_t requestBuffer(int slot, sp<GraphicBuffer>* buf);
- virtual status_t setMaxDequeuedBufferCount(int maxDequeuedBuffers);
- virtual status_t setAsyncMode(bool async);
- virtual status_t dequeueBuffer(int* slot, sp<Fence>* fence, uint32_t w, uint32_t h,
- PixelFormat format, uint64_t usage, uint64_t* outBufferAge,
- FrameEventHistoryDelta* outTimestamps);
- virtual status_t detachBuffer(int slot);
- virtual status_t detachNextBuffer(sp<GraphicBuffer>* outBuffer,
- sp<Fence>* outFence);
- virtual status_t attachBuffer(int* outSlot,
- const sp<GraphicBuffer>& buffer);
- virtual status_t queueBuffer(int slot, const QueueBufferInput& input,
- QueueBufferOutput* output);
- virtual status_t cancelBuffer(int slot, const sp<Fence>& fence);
- virtual int query(int what, int* value);
- virtual status_t connect(const sp<IProducerListener>& token, int api,
- bool producerControlledByApp, QueueBufferOutput* output);
- virtual status_t disconnect(int api, DisconnectMode mode);
- virtual status_t setSidebandStream(const sp<NativeHandle>& stream);
- virtual void allocateBuffers(uint32_t width, uint32_t height,
- PixelFormat format, uint64_t usage);
- virtual status_t allowAllocation(bool allow);
- virtual status_t setGenerationNumber(uint32_t generationNumber);
- virtual String8 getConsumerName() const override;
- virtual status_t setDequeueTimeout(nsecs_t timeout) override;
- virtual status_t setLegacyBufferDrop(bool drop) override;
- virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
- sp<Fence>* outFence, float outTransformMatrix[16]) override;
- virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence,
- Rect* outRect, uint32_t* outTransform) override;
- virtual IBinder* onAsBinder();
- virtual status_t setSharedBufferMode(bool sharedBufferMode) override;
- virtual status_t setAutoRefresh(bool autoRefresh) override;
- virtual void getFrameTimestamps(FrameEventHistoryDelta *outDelta) override;
- virtual status_t getUniqueId(uint64_t* outId) const override;
- virtual status_t getConsumerUsage(uint64_t* outUsage) const override;
- virtual status_t setAutoPrerotation(bool autoPrerotation) override;
-
- // The Layer which created this producer, and on which queued Buffer's will be displayed.
- sp<Layer> getLayer() const;
-
-private:
- sp<IGraphicBufferProducer> mProducer;
- sp<SurfaceFlinger> mFlinger;
- // The Layer which created this producer, and on which queued Buffer's will be displayed.
- wp<Layer> mLayer;
-};
-
-}; // namespace android
-
-#endif // ANDROID_MONITORED_PRODUCER_H
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index 639ba5a..d152ab2 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -157,9 +157,9 @@
} // namespace
-EventThreadConnection::EventThreadConnection(
- EventThread* eventThread, uid_t callingUid, ResyncCallback resyncCallback,
- ISurfaceComposer::EventRegistrationFlags eventRegistration)
+EventThreadConnection::EventThreadConnection(EventThread* eventThread, uid_t callingUid,
+ ResyncCallback resyncCallback,
+ EventRegistrationFlags eventRegistration)
: resyncCallback(std::move(resyncCallback)),
mOwnerUid(callingUid),
mEventRegistration(eventRegistration),
@@ -288,8 +288,7 @@
}
sp<EventThreadConnection> EventThread::createEventConnection(
- ResyncCallback resyncCallback,
- ISurfaceComposer::EventRegistrationFlags eventRegistration) const {
+ ResyncCallback resyncCallback, EventRegistrationFlags eventRegistration) const {
return new EventThreadConnection(const_cast<EventThread*>(this),
IPCThreadState::self()->getCallingUid(),
std::move(resyncCallback), eventRegistration);
@@ -553,7 +552,7 @@
case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE: {
return connection->mEventRegistration.test(
- ISurfaceComposer::EventRegistration::modeChanged);
+ gui::ISurfaceComposer::EventRegistration::modeChanged);
}
case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
@@ -586,7 +585,7 @@
[[fallthrough]];
case DisplayEventReceiver::DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH:
return connection->mEventRegistration.test(
- ISurfaceComposer::EventRegistration::frameRateOverride);
+ gui::ISurfaceComposer::EventRegistration::frameRateOverride);
default:
return false;
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index adb96fd..d85d140 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -92,7 +92,7 @@
class EventThreadConnection : public gui::BnDisplayEventConnection {
public:
EventThreadConnection(EventThread*, uid_t callingUid, ResyncCallback,
- ISurfaceComposer::EventRegistrationFlags eventRegistration = {});
+ EventRegistrationFlags eventRegistration = {});
virtual ~EventThreadConnection();
virtual status_t postEvent(const DisplayEventReceiver::Event& event);
@@ -107,7 +107,7 @@
VSyncRequest vsyncRequest = VSyncRequest::None;
const uid_t mOwnerUid;
- const ISurfaceComposer::EventRegistrationFlags mEventRegistration;
+ const EventRegistrationFlags mEventRegistration;
private:
virtual void onFirstRef();
@@ -123,8 +123,7 @@
virtual ~EventThread();
virtual sp<EventThreadConnection> createEventConnection(
- ResyncCallback,
- ISurfaceComposer::EventRegistrationFlags eventRegistration = {}) const = 0;
+ ResyncCallback, EventRegistrationFlags eventRegistration = {}) const = 0;
// called before the screen is turned off from main thread
virtual void onScreenReleased() = 0;
@@ -171,8 +170,7 @@
~EventThread();
sp<EventThreadConnection> createEventConnection(
- ResyncCallback,
- ISurfaceComposer::EventRegistrationFlags eventRegistration = {}) const override;
+ ResyncCallback, EventRegistrationFlags eventRegistration = {}) const override;
status_t registerDisplayEventConnection(const sp<EventThreadConnection>& connection) override;
void setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& connection) override;
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index 5f64efa..ae111c3 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -72,6 +72,20 @@
ALOGD("%s: %s @ %d Hz", __FUNCTION__, info.getName().c_str(), fps);
}
+
+LayerHistory::LayerVoteType getVoteType(LayerInfo::FrameRateCompatibility compatibility,
+ bool contentDetectionEnabled) {
+ LayerHistory::LayerVoteType voteType;
+ if (!contentDetectionEnabled || compatibility == LayerInfo::FrameRateCompatibility::NoVote) {
+ voteType = LayerHistory::LayerVoteType::NoVote;
+ } else if (compatibility == LayerInfo::FrameRateCompatibility::Min) {
+ voteType = LayerHistory::LayerVoteType::Min;
+ } else {
+ voteType = LayerHistory::LayerVoteType::Heuristic;
+ }
+ return voteType;
+}
+
} // namespace
LayerHistory::LayerHistory()
@@ -81,10 +95,12 @@
LayerHistory::~LayerHistory() = default;
-void LayerHistory::registerLayer(Layer* layer, LayerVoteType type) {
+void LayerHistory::registerLayer(Layer* layer, bool contentDetectionEnabled) {
std::lock_guard lock(mLock);
LOG_ALWAYS_FATAL_IF(findLayer(layer->getSequence()).first != LayerStatus::NotFound,
"%s already registered", layer->getName().c_str());
+ LayerVoteType type =
+ getVoteType(layer->getDefaultFrameRateCompatibility(), contentDetectionEnabled);
auto info = std::make_unique<LayerInfo>(layer->getName(), layer->getOwnerUid(), type);
// The layer can be placed on either map, it is assumed that partitionLayers() will be called
@@ -132,6 +148,22 @@
}
}
+void LayerHistory::setDefaultFrameRateCompatibility(Layer* layer, bool contentDetectionEnabled) {
+ std::lock_guard lock(mLock);
+ auto id = layer->getSequence();
+
+ auto [found, layerPair] = findLayer(id);
+ if (found == LayerStatus::NotFound) {
+ // Offscreen layer
+ ALOGV("%s: %s not registered", __func__, layer->getName().c_str());
+ return;
+ }
+
+ const auto& info = layerPair->second;
+ info->setDefaultLayerVote(
+ getVoteType(layer->getDefaultFrameRateCompatibility(), contentDetectionEnabled));
+}
+
auto LayerHistory::summarize(const RefreshRateConfigs& configs, nsecs_t now) -> Summary {
Summary summary;
@@ -203,6 +235,8 @@
switch (frameRate.type) {
case Layer::FrameRateCompatibility::Default:
return LayerVoteType::ExplicitDefault;
+ case Layer::FrameRateCompatibility::Min:
+ return LayerVoteType::Min;
case Layer::FrameRateCompatibility::ExactOrMultiple:
return LayerVoteType::ExplicitExactOrMultiple;
case Layer::FrameRateCompatibility::NoVote:
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h
index 7b6096f..12bec8d 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.h
+++ b/services/surfaceflinger/Scheduler/LayerHistory.h
@@ -45,7 +45,7 @@
~LayerHistory();
// Layers are unregistered when the weak reference expires.
- void registerLayer(Layer*, LayerVoteType type);
+ void registerLayer(Layer*, bool contentDetectionEnabled);
// Sets the display size. Client is responsible for synchronization.
void setDisplayArea(uint32_t displayArea) { mDisplayArea = displayArea; }
@@ -63,6 +63,10 @@
// Marks the layer as active, and records the given state to its history.
void record(Layer*, nsecs_t presentTime, nsecs_t now, LayerUpdateType updateType);
+ // Updates the default frame rate compatibility which takes effect when the app
+ // does not set a preference for refresh rate.
+ void setDefaultFrameRateCompatibility(Layer*, bool contentDetectionEnabled);
+
using Summary = std::vector<RefreshRateConfigs::LayerRequirement>;
// Rebuilds sets of active/inactive layers, and accumulates stats for active layers.
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h
index 8a3b0b9..28cb24a 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.h
+++ b/services/surfaceflinger/Scheduler/LayerInfo.h
@@ -74,6 +74,8 @@
enum class FrameRateCompatibility {
Default, // Layer didn't specify any specific handling strategy
+ Min, // Layer needs the minimum frame rate.
+
Exact, // Layer needs the exact frame rate.
ExactOrMultiple, // Layer needs the exact frame rate (or a multiple of it) to present the
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 727cb08..a3d4e8d 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -28,7 +28,6 @@
#include <ftl/fake_guard.h>
#include <gui/WindowInfo.h>
#include <system/window.h>
-#include <ui/DisplayStatInfo.h>
#include <utils/Timers.h>
#include <utils/Trace.h>
@@ -172,8 +171,7 @@
impl::EventThread::GetVsyncPeriodFunction Scheduler::makeGetVsyncPeriodFunction() const {
return [this](uid_t uid) {
const Fps refreshRate = holdRefreshRateConfigs()->getActiveMode()->getFps();
- const auto currentPeriod =
- mVsyncSchedule->getTracker().currentPeriod() ?: refreshRate.getPeriodNsecs();
+ const nsecs_t currentPeriod = mVsyncSchedule->period().ns() ?: refreshRate.getPeriodNsecs();
const auto frameRate = getFrameRateOverride(uid);
if (!frameRate.has_value()) {
@@ -214,12 +212,12 @@
}
sp<EventThreadConnection> Scheduler::createConnectionInternal(
- EventThread* eventThread, ISurfaceComposer::EventRegistrationFlags eventRegistration) {
+ EventThread* eventThread, EventRegistrationFlags eventRegistration) {
return eventThread->createEventConnection([&] { resync(); }, eventRegistration);
}
sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
- ConnectionHandle handle, ISurfaceComposer::EventRegistrationFlags eventRegistration) {
+ ConnectionHandle handle, EventRegistrationFlags eventRegistration) {
std::lock_guard<std::mutex> lock(mConnectionsLock);
RETURN_IF_INVALID_HANDLE(handle, nullptr);
return createConnectionInternal(mConnections[handle].thread.get(), eventRegistration);
@@ -361,12 +359,6 @@
thread->setDuration(workDuration, readyDuration);
}
-DisplayStatInfo Scheduler::getDisplayStatInfo(nsecs_t now) {
- const auto vsyncTime = mVsyncSchedule->getTracker().nextAnticipatedVSyncTimeFrom(now);
- const auto vsyncPeriod = mVsyncSchedule->getTracker().currentPeriod();
- return DisplayStatInfo{.vsyncTime = vsyncTime, .vsyncPeriod = vsyncPeriod};
-}
-
ConnectionHandle Scheduler::enableVSyncInjection(bool enable) {
if (mInjectVSyncs == enable) {
return {};
@@ -497,24 +489,10 @@
}
void Scheduler::registerLayer(Layer* layer) {
- using WindowType = gui::WindowInfo::Type;
-
- scheduler::LayerHistory::LayerVoteType voteType;
-
- if (!mFeatures.test(Feature::kContentDetection) ||
- layer->getWindowType() == WindowType::STATUS_BAR) {
- voteType = scheduler::LayerHistory::LayerVoteType::NoVote;
- } else if (layer->getWindowType() == WindowType::WALLPAPER) {
- // Running Wallpaper at Min is considered as part of content detection.
- voteType = scheduler::LayerHistory::LayerVoteType::Min;
- } else {
- voteType = scheduler::LayerHistory::LayerVoteType::Heuristic;
- }
-
// If the content detection feature is off, we still keep the layer history,
// since we use it for other features (like Frame Rate API), so layers
// still need to be registered.
- mLayerHistory.registerLayer(layer, voteType);
+ mLayerHistory.registerLayer(layer, mFeatures.test(Feature::kContentDetection));
}
void Scheduler::deregisterLayer(Layer* layer) {
@@ -535,6 +513,11 @@
mLayerHistory.setModeChangePending(pending);
}
+void Scheduler::setDefaultFrameRateCompatibility(Layer* layer) {
+ mLayerHistory.setDefaultFrameRateCompatibility(layer,
+ mFeatures.test(Feature::kContentDetection));
+}
+
void Scheduler::chooseRefreshRateForContent() {
const auto configs = holdRefreshRateConfigs();
if (!configs->canSwitch()) return;
@@ -776,11 +759,4 @@
mFrameRateOverrideMappings.setPreferredRefreshRateForUid(frameRateOverride);
}
-std::chrono::steady_clock::time_point Scheduler::getPreviousVsyncFrom(
- nsecs_t expectedPresentTime) const {
- const auto presentTime = std::chrono::nanoseconds(expectedPresentTime);
- const auto vsyncPeriod = std::chrono::nanoseconds(mVsyncSchedule->getTracker().currentPeriod());
- return std::chrono::steady_clock::time_point(presentTime - vsyncPeriod);
-}
-
} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index a8043bf..f800eeb 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -33,6 +33,7 @@
#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
#include <scheduler/Features.h>
+#include <scheduler/Time.h>
#include "EventThread.h"
#include "FrameRateOverrideMappings.h"
@@ -131,7 +132,7 @@
impl::EventThread::InterceptVSyncsCallback);
sp<IDisplayEventConnection> createDisplayEventConnection(
- ConnectionHandle, ISurfaceComposer::EventRegistrationFlags eventRegistration = {});
+ ConnectionHandle, EventRegistrationFlags eventRegistration = {});
sp<EventThreadConnection> getEventConnection(ConnectionHandle);
@@ -148,8 +149,6 @@
void setDuration(ConnectionHandle, std::chrono::nanoseconds workDuration,
std::chrono::nanoseconds readyDuration);
- DisplayStatInfo getDisplayStatInfo(nsecs_t now);
-
// Returns injector handle if injection has toggled, or an invalid handle otherwise.
ConnectionHandle enableVSyncInjection(bool enable);
// Returns false if injection is disabled.
@@ -176,6 +175,7 @@
void recordLayerHistory(Layer*, nsecs_t presentTime, LayerHistory::LayerUpdateType updateType)
EXCLUDES(mRefreshRateConfigsLock);
void setModeChangePending(bool pending);
+ void setDefaultFrameRateCompatibility(Layer*);
void deregisterLayer(Layer*);
// Detects content using layer history, and selects a matching refresh rate.
@@ -188,14 +188,12 @@
void setDisplayPowerMode(hal::PowerMode powerMode);
- VSyncDispatch& getVsyncDispatch() { return mVsyncSchedule->getDispatch(); }
+ VsyncSchedule& getVsyncSchedule() { return *mVsyncSchedule; }
// Returns true if a given vsync timestamp is considered valid vsync
// for a given uid
bool isVsyncValid(nsecs_t expectedVsyncTimestamp, uid_t uid) const;
- std::chrono::steady_clock::time_point getPreviousVsyncFrom(nsecs_t expectedPresentTime) const;
-
void dump(std::string&) const;
void dump(ConnectionHandle, std::string&) const;
void dumpVsync(std::string&) const;
@@ -248,7 +246,7 @@
// Create a connection on the given EventThread.
ConnectionHandle createConnection(std::unique_ptr<EventThread>);
sp<EventThreadConnection> createConnectionInternal(
- EventThread*, ISurfaceComposer::EventRegistrationFlags eventRegistration = {});
+ EventThread*, EventRegistrationFlags eventRegistration = {});
// Update feature state machine to given state when corresponding timer resets or expires.
void kernelIdleTimerCallback(TimerState) EXCLUDES(mRefreshRateConfigsLock);
diff --git a/services/surfaceflinger/Scheduler/VsyncSchedule.cpp b/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
index 3a918a1..95bc31f 100644
--- a/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
+++ b/services/surfaceflinger/Scheduler/VsyncSchedule.cpp
@@ -68,6 +68,14 @@
VsyncSchedule::VsyncSchedule(VsyncSchedule&&) = default;
VsyncSchedule::~VsyncSchedule() = default;
+Period VsyncSchedule::period() const {
+ return Period::fromNs(mTracker->currentPeriod());
+}
+
+TimePoint VsyncSchedule::vsyncDeadlineAfter(TimePoint timePoint) const {
+ return TimePoint::fromNs(mTracker->nextAnticipatedVSyncTimeFrom(timePoint.ns()));
+}
+
void VsyncSchedule::dump(std::string& out) const {
out.append("VsyncController:\n");
mController->dump(out);
diff --git a/services/surfaceflinger/Scheduler/VsyncSchedule.h b/services/surfaceflinger/Scheduler/VsyncSchedule.h
index 0d9b114..8c17409 100644
--- a/services/surfaceflinger/Scheduler/VsyncSchedule.h
+++ b/services/surfaceflinger/Scheduler/VsyncSchedule.h
@@ -20,6 +20,7 @@
#include <string>
#include <scheduler/Features.h>
+#include <scheduler/Time.h>
namespace android::scheduler {
@@ -38,6 +39,9 @@
VsyncSchedule(VsyncSchedule&&);
~VsyncSchedule();
+ Period period() const;
+ TimePoint vsyncDeadlineAfter(TimePoint) const;
+
// TODO(b/185535769): Hide behind API.
const VsyncTracker& getTracker() const { return *mTracker; }
VsyncTracker& getTracker() { return *mTracker; }
diff --git a/services/surfaceflinger/Scheduler/include/scheduler/Time.h b/services/surfaceflinger/Scheduler/include/scheduler/Time.h
new file mode 100644
index 0000000..6fa548e
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/include/scheduler/Time.h
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <chrono>
+
+#include <utils/Timers.h>
+
+namespace android {
+namespace scheduler {
+
+// TODO(b/185535769): Pull Clock.h to libscheduler to reuse this.
+using SchedulerClock = std::chrono::high_resolution_clock;
+static_assert(SchedulerClock::is_steady);
+
+} // namespace scheduler
+
+struct Duration;
+
+struct TimePoint : scheduler::SchedulerClock::time_point {
+ explicit TimePoint(const Duration&);
+
+ // Implicit conversion from std::chrono counterpart.
+ constexpr TimePoint(scheduler::SchedulerClock::time_point p)
+ : scheduler::SchedulerClock::time_point(p) {}
+
+ static TimePoint fromNs(nsecs_t);
+
+ nsecs_t ns() const;
+};
+
+struct Duration : TimePoint::duration {
+ // Implicit conversion from std::chrono counterpart.
+ constexpr Duration(TimePoint::duration d) : TimePoint::duration(d) {}
+
+ static Duration fromNs(nsecs_t ns) { return {std::chrono::nanoseconds(ns)}; }
+
+ nsecs_t ns() const { return std::chrono::nanoseconds(*this).count(); }
+};
+
+using Period = Duration;
+
+inline TimePoint::TimePoint(const Duration& d) : scheduler::SchedulerClock::time_point(d) {}
+
+inline TimePoint TimePoint::fromNs(nsecs_t ns) {
+ return TimePoint(Duration::fromNs(ns));
+}
+
+inline nsecs_t TimePoint::ns() const {
+ return Duration(time_since_epoch()).ns();
+}
+
+} // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 6e74eef..2beb946 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -30,6 +30,7 @@
#include <android-base/strings.h>
#include <android/configuration.h>
#include <android/gui/IDisplayEventConnection.h>
+#include <android/gui/StaticDisplayInfo.h>
#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
#include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
#include <android/hardware/configstore/1.1/types.h>
@@ -55,6 +56,7 @@
#include <ftl/fake_guard.h>
#include <ftl/future.h>
#include <ftl/small_map.h>
+#include <gui/AidlStatusUtil.h>
#include <gui/BufferQueue.h>
#include <gui/DebugEGLImageTracker.h>
#include <gui/IProducerListener.h>
@@ -104,7 +106,6 @@
#include <ui/DisplayIdentification.h>
#include "BackgroundExecutor.h"
#include "BufferLayer.h"
-#include "BufferQueueLayer.h"
#include "BufferStateLayer.h"
#include "Client.h"
#include "Colorizer.h"
@@ -128,7 +129,6 @@
#include "LayerProtoHelper.h"
#include "LayerRenderArea.h"
#include "LayerVector.h"
-#include "MonitoredProducer.h"
#include "MutexUtils.h"
#include "NativeWindowSurface.h"
#include "RefreshRateOverlay.h"
@@ -154,6 +154,10 @@
#define NO_THREAD_SAFETY_ANALYSIS \
_Pragma("GCC error \"Prefer <ftl/fake_guard.h> or MutexUtils.h helpers.\"")
+// To enable layer borders in the system, change the below flag to true.
+#undef DOES_CONTAIN_BORDER
+#define DOES_CONTAIN_BORDER false
+
namespace android {
using namespace std::string_literals;
@@ -170,9 +174,12 @@
using base::StringAppendF;
using gui::DisplayInfo;
+using gui::GameMode;
using gui::IDisplayEventConnection;
using gui::IWindowInfosListener;
+using gui::LayerMetadata;
using gui::WindowInfo;
+using gui::aidl_utils::binderStatusFromStatusT;
using ui::ColorMode;
using ui::Dataspace;
using ui::DisplayPrimaries;
@@ -273,6 +280,8 @@
const char* KERNEL_IDLE_TIMER_PROP = "graphics.display.kernel_idle_timer.enabled";
+static const int MAX_TRACING_MEMORY = 1024 * 1024 * 1024; // 1GB
+
// ---------------------------------------------------------------------------
int64_t SurfaceFlinger::dispSyncPresentTimeOffset;
bool SurfaceFlinger::useHwcForRgbToYuv;
@@ -331,7 +340,7 @@
mInternalDisplayDensity(getDensityFromProperty("ro.sf.lcd_density", true)),
mEmulatedDisplayDensity(getDensityFromProperty("qemu.sf.lcd_density", false)),
mPowerAdvisor(std::make_unique<Hwc2::impl::PowerAdvisor>(*this)),
- mWindowInfosListenerInvoker(sp<WindowInfosListenerInvoker>::make(*this)) {
+ mWindowInfosListenerInvoker(sp<WindowInfosListenerInvoker>::make()) {
ALOGI("Using HWComposer service: %s", mHwcServiceName.c_str());
}
@@ -402,7 +411,7 @@
property_get("ro.sf.blurs_are_expensive", value, "0");
mBlursAreExpensive = atoi(value);
- const size_t defaultListSize = ISurfaceComposer::MAX_LAYERS;
+ const size_t defaultListSize = MAX_LAYERS;
auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize));
mMaxGraphicBufferProducerListSize = (listSize > 0) ? size_t(listSize) : defaultListSize;
mGraphicBufferProducerListSizeLogThreshold =
@@ -483,11 +492,6 @@
mScheduler->run();
}
-sp<ISurfaceComposerClient> SurfaceFlinger::createConnection() {
- const sp<Client> client = new Client(this);
- return client->initCheck() == NO_ERROR ? client : nullptr;
-}
-
sp<IBinder> SurfaceFlinger::createDisplay(const String8& displayName, bool secure) {
// onTransact already checks for some permissions, but adding an additional check here.
// This is to ensure that only system and graphics can request to create a secure
@@ -881,17 +885,6 @@
// ----------------------------------------------------------------------------
-bool SurfaceFlinger::authenticateSurfaceTexture(
- const sp<IGraphicBufferProducer>& bufferProducer) const {
- Mutex::Autolock _l(mStateLock);
- return authenticateSurfaceTextureLocked(bufferProducer);
-}
-
-bool SurfaceFlinger::authenticateSurfaceTextureLocked(
- const sp<IGraphicBufferProducer>& /* bufferProducer */) const {
- return false;
-}
-
status_t SurfaceFlinger::getSupportedFrameTimestamps(
std::vector<FrameEvent>* outSupported) const {
*outSupported = {
@@ -1061,12 +1054,14 @@
return NO_ERROR;
}
-status_t SurfaceFlinger::getDisplayStats(const sp<IBinder>&, DisplayStatInfo* stats) {
- if (!stats) {
+status_t SurfaceFlinger::getDisplayStats(const sp<IBinder>&, DisplayStatInfo* outStats) {
+ if (!outStats) {
return BAD_VALUE;
}
- *stats = mScheduler->getDisplayStatInfo(systemTime());
+ const auto& schedule = mScheduler->getVsyncSchedule();
+ outStats->vsyncTime = schedule.vsyncDeadlineAfter(scheduler::SchedulerClock::now()).ns();
+ outStats->vsyncPeriod = schedule.period().ns();
return NO_ERROR;
}
@@ -1575,15 +1570,13 @@
status_t SurfaceFlinger::injectVSync(nsecs_t when) {
Mutex::Autolock lock(mStateLock);
- const DisplayStatInfo stats = mScheduler->getDisplayStatInfo(when);
- const auto expectedPresent = calculateExpectedPresentTime(stats);
- return mScheduler->injectVSync(when, /*expectedVSyncTime=*/expectedPresent,
- /*deadlineTimestamp=*/expectedPresent)
- ? NO_ERROR
- : BAD_VALUE;
+ const nsecs_t expectedPresentTime = calculateExpectedPresentTime(when).ns();
+ const nsecs_t deadlineTimestamp = expectedPresentTime;
+ return mScheduler->injectVSync(when, expectedPresentTime, deadlineTimestamp) ? NO_ERROR
+ : BAD_VALUE;
}
-status_t SurfaceFlinger::getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) {
+status_t SurfaceFlinger::getLayerDebugInfo(std::vector<gui::LayerDebugInfo>* outLayers) {
outLayers->clear();
auto future = mScheduler->schedule([=] {
const auto display = FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked());
@@ -1815,10 +1808,11 @@
// ----------------------------------------------------------------------------
sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
- ISurfaceComposer::VsyncSource vsyncSource,
- ISurfaceComposer::EventRegistrationFlags eventRegistration) {
+ gui::ISurfaceComposer::VsyncSource vsyncSource, EventRegistrationFlags eventRegistration) {
const auto& handle =
- vsyncSource == eVsyncSourceSurfaceFlinger ? mSfConnectionHandle : mAppConnectionHandle;
+ vsyncSource == gui::ISurfaceComposer::VsyncSource::eVsyncSourceSurfaceFlinger
+ ? mSfConnectionHandle
+ : mAppConnectionHandle;
return mScheduler->createDisplayEventConnection(handle, eventRegistration);
}
@@ -1891,11 +1885,6 @@
}
}
-void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) {
- std::lock_guard<std::mutex> lock(getBE().mCompositorTimingLock);
- *compositorTiming = getBE().mCompositorTiming;
-}
-
void SurfaceFlinger::onComposerHalHotplug(hal::HWDisplayId hwcDisplayId,
hal::Connection connection) {
const bool connected = connection == hal::Connection::CONNECTED;
@@ -1956,18 +1945,15 @@
}));
}
-SurfaceFlinger::FenceWithFenceTime SurfaceFlinger::previousFrameFence() {
- const auto now = systemTime();
- const auto vsyncPeriod = mScheduler->getDisplayStatInfo(now).vsyncPeriod;
- const bool expectedPresentTimeIsTheNextVsync = mExpectedPresentTime - now <= vsyncPeriod;
- return expectedPresentTimeIsTheNextVsync ? mPreviousPresentFences[0]
- : mPreviousPresentFences[1];
+auto SurfaceFlinger::getPreviousPresentFence(nsecs_t frameTime, Period vsyncPeriod)
+ -> const FenceTimePtr& {
+ const bool isTwoVsyncsAhead = mExpectedPresentTime - frameTime > vsyncPeriod.ns();
+ const size_t i = static_cast<size_t>(isTwoVsyncsAhead);
+ return mPreviousPresentFences[i].fenceTime;
}
-bool SurfaceFlinger::previousFramePending(int graceTimeMs) {
+bool SurfaceFlinger::isFencePending(const FenceTimePtr& fence, int graceTimeMs) {
ATRACE_CALL();
- const std::shared_ptr<FenceTime>& fence = previousFrameFence().fenceTime;
-
if (fence == FenceTime::NO_FENCE) {
return false;
}
@@ -1978,37 +1964,32 @@
return status == -ETIME;
}
-nsecs_t SurfaceFlinger::previousFramePresentTime() {
- const std::shared_ptr<FenceTime>& fence = previousFrameFence().fenceTime;
+TimePoint SurfaceFlinger::calculateExpectedPresentTime(nsecs_t frameTime) const {
+ const auto& schedule = mScheduler->getVsyncSchedule();
- if (fence == FenceTime::NO_FENCE) {
- return Fence::SIGNAL_TIME_INVALID;
+ const TimePoint vsyncDeadline = schedule.vsyncDeadlineAfter(TimePoint::fromNs(frameTime));
+ if (mVsyncModulator->getVsyncConfig().sfOffset > 0) {
+ return vsyncDeadline;
}
- return fence->getSignalTime();
-}
-
-nsecs_t SurfaceFlinger::calculateExpectedPresentTime(DisplayStatInfo stats) const {
- // Inflate the expected present time if we're targetting the next vsync.
- return mVsyncModulator->getVsyncConfig().sfOffset > 0 ? stats.vsyncTime
- : stats.vsyncTime + stats.vsyncPeriod;
+ // Inflate the expected present time if we're targeting the next vsync.
+ return vsyncDeadline + schedule.period();
}
bool SurfaceFlinger::commit(nsecs_t frameTime, int64_t vsyncId, nsecs_t expectedVsyncTime)
FTL_FAKE_GUARD(kMainThreadContext) {
- // calculate the expected present time once and use the cached
- // value throughout this frame to make sure all layers are
- // seeing this same value.
- if (expectedVsyncTime >= frameTime) {
- mExpectedPresentTime = expectedVsyncTime;
- } else {
- const DisplayStatInfo stats = mScheduler->getDisplayStatInfo(frameTime);
- mExpectedPresentTime = calculateExpectedPresentTime(stats);
- }
-
+ // The expectedVsyncTime, which was predicted when this frame was scheduled, is normally in the
+ // future relative to frameTime, but may not be for delayed frames. Adjust mExpectedPresentTime
+ // accordingly, but not mScheduledPresentTime.
const nsecs_t lastScheduledPresentTime = mScheduledPresentTime;
mScheduledPresentTime = expectedVsyncTime;
+ // Calculate the expected present time once and use the cached value throughout this frame to
+ // make sure all layers are seeing this same value.
+ mExpectedPresentTime = expectedVsyncTime >= frameTime
+ ? expectedVsyncTime
+ : calculateExpectedPresentTime(frameTime).ns();
+
const auto vsyncIn = [&] {
if (!ATRACE_ENABLED()) return 0.f;
return (mExpectedPresentTime - systemTime()) / 1e6f;
@@ -2016,6 +1997,9 @@
ATRACE_FORMAT("%s %" PRId64 " vsyncIn %.2fms%s", __func__, vsyncId, vsyncIn,
mExpectedPresentTime == expectedVsyncTime ? "" : " (adjusted)");
+ const Period vsyncPeriod = mScheduler->getVsyncSchedule().period();
+ const FenceTimePtr& previousPresentFence = getPreviousPresentFence(frameTime, vsyncPeriod);
+
// When Backpressure propagation is enabled we want to give a small grace period
// for the present fence to fire instead of just giving up on this frame to handle cases
// where present fence is just about to get signaled.
@@ -2024,7 +2008,8 @@
// Pending frames may trigger backpressure propagation.
const TracedOrdinal<bool> framePending = {"PrevFramePending",
- previousFramePending(graceTimeForPresentFenceMs)};
+ isFencePending(previousPresentFence,
+ graceTimeForPresentFenceMs)};
// Frame missed counts for metrics tracking.
// A frame is missed if the prior frame is still pending. If no longer pending,
@@ -2034,9 +2019,8 @@
// Add some slop to correct for drift. This should generally be
// smaller than a typical frame duration, but should not be so small
// that it reports reasonable drift as a missed frame.
- const DisplayStatInfo stats = mScheduler->getDisplayStatInfo(systemTime());
- const nsecs_t frameMissedSlop = stats.vsyncPeriod / 2;
- const nsecs_t previousPresentTime = previousFramePresentTime();
+ const nsecs_t frameMissedSlop = vsyncPeriod.ns() / 2;
+ const nsecs_t previousPresentTime = previousPresentFence->getSignalTime();
const TracedOrdinal<bool> frameMissed = {"PrevFrameMissed",
framePending ||
(previousPresentTime >= 0 &&
@@ -2060,6 +2044,11 @@
mGpuFrameMissedCount++;
}
+ if (mTracingEnabledChanged) {
+ mLayerTracingEnabled = mLayerTracing.isEnabled();
+ mTracingEnabledChanged = false;
+ }
+
// If we are in the middle of a mode change and the fence hasn't
// fired yet just wait for the next commit.
if (mSetActiveModePending) {
@@ -2108,11 +2097,6 @@
}
}
- if (mTracingEnabledChanged) {
- mLayerTracingEnabled = mLayerTracing.isEnabled();
- mTracingEnabledChanged = false;
- }
-
if (mRefreshRateOverlaySpinner) {
Mutex::Autolock lock(mStateLock);
if (const auto display = getDefaultDisplayDeviceLocked()) {
@@ -2123,11 +2107,11 @@
// Composite if transactions were committed, or if requested by HWC.
bool mustComposite = mMustComposite.exchange(false);
{
- mFrameTimeline->setSfWakeUp(vsyncId, frameTime, Fps::fromPeriodNsecs(stats.vsyncPeriod));
+ mFrameTimeline->setSfWakeUp(vsyncId, frameTime, Fps::fromPeriodNsecs(vsyncPeriod.ns()));
bool needsTraversal = false;
if (clearTransactionFlags(eTransactionFlushNeeded)) {
- needsTraversal |= commitCreatedLayers();
+ needsTraversal |= commitCreatedLayers(vsyncId);
needsTraversal |= flushTransactionQueues(vsyncId);
}
@@ -2172,8 +2156,9 @@
if (mLayerTracingEnabled && !mLayerTracing.flagIsSet(LayerTracing::TRACE_COMPOSITION)) {
// This will block and tracing should only be enabled for debugging.
- mLayerTracing.notify(mVisibleRegionsDirty, frameTime);
+ mLayerTracing.notify(mVisibleRegionsDirty, frameTime, vsyncId);
}
+ mLastCommittedVsyncId = vsyncId;
persistDisplayBrightness(mustComposite);
@@ -2197,6 +2182,22 @@
if (auto layerFE = layer->getCompositionEngineLayerFE())
refreshArgs.layers.push_back(layerFE);
});
+
+ if (DOES_CONTAIN_BORDER) {
+ refreshArgs.borderInfoList.clear();
+ mDrawingState.traverse([&refreshArgs](Layer* layer) {
+ if (layer->isBorderEnabled()) {
+ compositionengine::BorderRenderInfo info;
+ info.width = layer->getBorderWidth();
+ info.color = layer->getBorderColor();
+ layer->traverse(LayerVector::StateSet::Drawing, [&info](Layer* ilayer) {
+ info.layerIds.push_back(ilayer->getSequence());
+ });
+ refreshArgs.borderInfoList.emplace_back(std::move(info));
+ }
+ });
+ }
+
refreshArgs.layersWithQueuedFrames.reserve(mLayersWithQueuedFrames.size());
for (auto layer : mLayersWithQueuedFrames) {
if (auto layerFE = layer->getCompositionEngineLayerFE())
@@ -2227,7 +2228,9 @@
}
const auto expectedPresentTime = mExpectedPresentTime.load();
- const auto prevVsyncTime = mScheduler->getPreviousVsyncFrom(expectedPresentTime);
+ const auto prevVsyncTime =
+ TimePoint::fromNs(expectedPresentTime) - mScheduler->getVsyncSchedule().period();
+
const auto hwcMinWorkDuration = mVsyncConfiguration->getCurrentConfigs().hwcMinWorkDuration;
refreshArgs.earliestPresentTime = prevVsyncTime - hwcMinWorkDuration;
refreshArgs.previousPresentFence = mPreviousPresentFences[0].fenceTime;
@@ -2284,7 +2287,7 @@
mLayersWithQueuedFrames.clear();
if (mLayerTracingEnabled && mLayerTracing.flagIsSet(LayerTracing::TRACE_COMPOSITION)) {
// This will block and should only be used for debugging.
- mLayerTracing.notify(mVisibleRegionsDirty, frameTime);
+ mLayerTracing.notify(mVisibleRegionsDirty, frameTime, vsyncId);
}
mVisibleRegionsWereDirtyThisFrame = mVisibleRegionsDirty; // Cache value for use in post-comp
@@ -2314,11 +2317,11 @@
mLayersPendingRefresh.clear();
}
-void SurfaceFlinger::updateCompositorTiming(const DisplayStatInfo& stats, nsecs_t compositeTime,
- std::shared_ptr<FenceTime>& presentFenceTime) {
+nsecs_t SurfaceFlinger::trackPresentLatency(nsecs_t compositeTime,
+ std::shared_ptr<FenceTime> presentFenceTime) {
// Update queue of past composite+present times and determine the
// most recently known composite to present latency.
- getBE().mCompositePresentTimes.push({compositeTime, presentFenceTime});
+ getBE().mCompositePresentTimes.push({compositeTime, std::move(presentFenceTime)});
nsecs_t compositeToPresentLatency = -1;
while (!getBE().mCompositePresentTimes.empty()) {
SurfaceFlingerBE::CompositePresentTime& cpt = getBE().mCompositePresentTimes.front();
@@ -2337,41 +2340,7 @@
getBE().mCompositePresentTimes.pop();
}
- setCompositorTimingSnapped(stats, compositeToPresentLatency);
-}
-
-void SurfaceFlinger::setCompositorTimingSnapped(const DisplayStatInfo& stats,
- nsecs_t compositeToPresentLatency) {
- // Avoid division by 0 by defaulting to 60Hz
- const auto vsyncPeriod = stats.vsyncPeriod ?: (60_Hz).getPeriodNsecs();
-
- // Integer division and modulo round toward 0 not -inf, so we need to
- // treat negative and positive offsets differently.
- nsecs_t idealLatency = (mVsyncConfiguration->getCurrentConfigs().late.sfOffset > 0)
- ? (vsyncPeriod -
- (mVsyncConfiguration->getCurrentConfigs().late.sfOffset % vsyncPeriod))
- : ((-mVsyncConfiguration->getCurrentConfigs().late.sfOffset) % vsyncPeriod);
-
- // Just in case mVsyncConfiguration->getCurrentConfigs().late.sf == -vsyncInterval.
- if (idealLatency <= 0) {
- idealLatency = vsyncPeriod;
- }
-
- // Snap the latency to a value that removes scheduling jitter from the
- // composition and present times, which often have >1ms of jitter.
- // Reducing jitter is important if an app attempts to extrapolate
- // something (such as user input) to an accurate diasplay time.
- // Snapping also allows an app to precisely calculate
- // mVsyncConfiguration->getCurrentConfigs().late.sf with (presentLatency % interval).
- const nsecs_t bias = vsyncPeriod / 2;
- const int64_t extraVsyncs = ((compositeToPresentLatency - idealLatency + bias) / vsyncPeriod);
- const nsecs_t snappedCompositeToPresentLatency =
- (extraVsyncs > 0) ? idealLatency + (extraVsyncs * vsyncPeriod) : idealLatency;
-
- std::lock_guard<std::mutex> lock(getBE().mCompositorTimingLock);
- getBE().mCompositorTiming.deadline = stats.vsyncTime - idealLatency;
- getBE().mCompositorTiming.interval = vsyncPeriod;
- getBE().mCompositorTiming.presentLatency = snappedCompositeToPresentLatency;
+ return compositeToPresentLatency;
}
bool SurfaceFlinger::isHdrLayer(Layer* layer) const {
@@ -2458,18 +2427,20 @@
mFrameTimeline->setSfPresent(/* sfPresentTime */ now, mPreviousPresentFences[0].fenceTime,
glCompositionDoneFenceTime);
- const DisplayStatInfo stats = mScheduler->getDisplayStatInfo(now);
-
// We use the CompositionEngine::getLastFrameRefreshTimestamp() which might
// be sampled a little later than when we started doing work for this frame,
- // but that should be okay since updateCompositorTiming has snapping logic.
- updateCompositorTiming(stats, mCompositionEngine->getLastFrameRefreshTimestamp(),
- mPreviousPresentFences[0].fenceTime);
- CompositorTiming compositorTiming;
- {
- std::lock_guard<std::mutex> lock(getBE().mCompositorTimingLock);
- compositorTiming = getBE().mCompositorTiming;
- }
+ // but that should be okay since CompositorTiming has snapping logic.
+ const nsecs_t compositeTime = mCompositionEngine->getLastFrameRefreshTimestamp();
+ const nsecs_t presentLatency =
+ trackPresentLatency(compositeTime, mPreviousPresentFences[0].fenceTime);
+
+ const auto& schedule = mScheduler->getVsyncSchedule();
+ const TimePoint vsyncDeadline = schedule.vsyncDeadlineAfter(TimePoint::fromNs(now));
+ const Period vsyncPeriod = schedule.period();
+ const nsecs_t vsyncPhase = mVsyncConfiguration->getCurrentConfigs().late.sfOffset;
+
+ const CompositorTiming compositorTiming(vsyncDeadline.ns(), vsyncPeriod.ns(), vsyncPhase,
+ presentLatency);
for (const auto& layer: mLayersWithQueuedFrames) {
layer->onPostComposition(display, glCompositionDoneFenceTime,
@@ -2581,7 +2552,7 @@
mHasPoweredOff = false;
} else {
nsecs_t elapsedTime = currentTime - getBE().mLastSwapTime;
- size_t numPeriods = static_cast<size_t>(elapsedTime / stats.vsyncPeriod);
+ const size_t numPeriods = static_cast<size_t>(elapsedTime / vsyncPeriod.ns());
if (numPeriods < SurfaceFlingerBE::NUM_BUCKETS - 1) {
getBE().mFrameBuckets[numPeriods] += elapsedTime;
} else {
@@ -3103,6 +3074,7 @@
const KeyedVector<wp<IBinder>, DisplayDeviceState>& draw(mDrawingState.displays);
if (!curr.isIdenticalTo(draw)) {
mVisibleRegionsDirty = true;
+ mUpdateInputInfo = true;
// find the displays that were removed
// (ie: in drawing state but not in current state)
@@ -3147,6 +3119,7 @@
if (mSomeChildrenChanged) {
mVisibleRegionsDirty = true;
mSomeChildrenChanged = false;
+ mUpdateInputInfo = true;
}
// Update transform hint.
@@ -3188,7 +3161,7 @@
}
}
- if (!hintDisplay) {
+ if (!hintDisplay && mDisplays.size() > 0) {
// NOTE: TEMPORARY FIX ONLY. Real fix should cause layers to
// redraw after transform hint changes. See bug 8508397.
@@ -3198,7 +3171,11 @@
hintDisplay = getDefaultDisplayDeviceLocked();
}
- layer->updateTransformHint(hintDisplay->getTransformHint());
+ if (hintDisplay) {
+ layer->updateTransformHint(hintDisplay->getTransformHint());
+ } else {
+ ALOGW("Ignoring transform hint update for %s", layer->getDebugName());
+ }
});
}
@@ -3206,6 +3183,7 @@
mLayersAdded = false;
// Layers have been added.
mVisibleRegionsDirty = true;
+ mUpdateInputInfo = true;
}
// some layers might have been removed, so
@@ -3213,6 +3191,7 @@
if (mLayersRemoved) {
mLayersRemoved = false;
mVisibleRegionsDirty = true;
+ mUpdateInputInfo = true;
mDrawingState.traverseInZOrder([&](Layer* layer) {
if (mLayersPendingRemoval.indexOf(layer) >= 0) {
// this layer is not visible anymore
@@ -3237,14 +3216,14 @@
std::vector<WindowInfo> windowInfos;
std::vector<DisplayInfo> displayInfos;
bool updateWindowInfo = false;
- if (mVisibleRegionsDirty || mInputInfoChanged) {
- mInputInfoChanged = false;
+ if (mUpdateInputInfo) {
+ mUpdateInputInfo = false;
updateWindowInfo = true;
buildWindowInfos(windowInfos, displayInfos);
- }
- if (!updateWindowInfo && mInputWindowCommands.empty()) {
+ } else if (mInputWindowCommands.empty()) {
return;
}
+
BackgroundExecutor::getInstance().sendCallbacks({[updateWindowInfo,
windowInfos = std::move(windowInfos),
displayInfos = std::move(displayInfos),
@@ -3253,12 +3232,17 @@
inputFlinger = mInputFlinger, this]() {
ATRACE_NAME("BackgroundExecutor::updateInputFlinger");
if (updateWindowInfo) {
- mWindowInfosListenerInvoker->windowInfosChanged(windowInfos, displayInfos,
- inputWindowCommands.syncInputWindows);
- } else if (inputWindowCommands.syncInputWindows) {
- // If the caller requested to sync input windows, but there are no
- // changes to input windows, notify immediately.
- windowInfosReported();
+ mWindowInfosListenerInvoker
+ ->windowInfosChanged(windowInfos, displayInfos,
+ inputWindowCommands.windowInfosReportedListeners);
+ } else {
+ // If there are listeners but no changes to input windows, call the listeners
+ // immediately.
+ for (const auto& listener : inputWindowCommands.windowInfosReportedListeners) {
+ if (IInterface::asBinder(listener)->isBinderAlive()) {
+ listener->onWindowInfosReported();
+ }
+ }
}
for (const auto& focusRequest : inputWindowCommands.focusRequests) {
inputFlinger->setFocusedWindow(focusRequest);
@@ -3445,8 +3429,8 @@
mInterceptor->saveVSyncEvent(timestamp);
});
- mScheduler->initVsync(mScheduler->getVsyncDispatch(), *mFrameTimeline->getTokenManager(),
- configs.late.sfWorkDuration);
+ mScheduler->initVsync(mScheduler->getVsyncSchedule().getDispatch(),
+ *mFrameTimeline->getTokenManager(), configs.late.sfWorkDuration);
mRegionSamplingThread =
new RegionSamplingThread(*this, RegionSamplingThread::EnvironmentTimingTunables());
@@ -3638,9 +3622,9 @@
status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<IBinder>& handle,
const sp<Layer>& layer, const wp<Layer>& parent,
bool addToRoot, uint32_t* outTransformHint) {
- if (mNumLayers >= ISurfaceComposer::MAX_LAYERS) {
+ if (mNumLayers >= MAX_LAYERS) {
ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers.load(),
- ISurfaceComposer::MAX_LAYERS);
+ MAX_LAYERS);
static_cast<void>(mScheduler->schedule([=] {
ALOGE("Dumping random sampling of on-screen layers: ");
mDrawingState.traverse([&](Layer *layer) {
@@ -3916,10 +3900,10 @@
bool SurfaceFlinger::frameIsEarly(nsecs_t expectedPresentTime, int64_t vsyncId) const {
// The amount of time SF can delay a frame if it is considered early based
// on the VsyncModulator::VsyncConfig::appWorkDuration
- constexpr static std::chrono::nanoseconds kEarlyLatchMaxThreshold = 100ms;
+ constexpr std::chrono::nanoseconds kEarlyLatchMaxThreshold = 100ms;
- const auto currentVsyncPeriod = mScheduler->getDisplayStatInfo(systemTime()).vsyncPeriod;
- const auto earlyLatchVsyncThreshold = currentVsyncPeriod / 2;
+ const nsecs_t currentVsyncPeriod = mScheduler->getVsyncSchedule().period().ns();
+ const nsecs_t earlyLatchVsyncThreshold = currentVsyncPeriod / 2;
const auto prediction = mFrameTimeline->getTokenManager()->getPredictionsForToken(vsyncId);
if (!prediction.has_value()) {
@@ -4081,11 +4065,9 @@
Mutex::Autolock lock(mQueueLock);
// Generate a CountDownLatch pending state if this is a synchronous transaction.
- if ((state.flags & eSynchronous) || state.inputWindowCommands.syncInputWindows) {
- state.transactionCommittedSignal = std::make_shared<CountDownLatch>(
- (state.inputWindowCommands.syncInputWindows
- ? (CountDownLatch::eSyncInputWindows | CountDownLatch::eSyncTransaction)
- : CountDownLatch::eSyncTransaction));
+ if (state.flags & eSynchronous) {
+ state.transactionCommittedSignal =
+ std::make_shared<CountDownLatch>(CountDownLatch::eSyncTransaction);
}
mTransactionQueue.emplace_back(state);
@@ -4467,6 +4449,11 @@
if (what & layer_state_t::eBlurRegionsChanged) {
if (layer->setBlurRegions(s.blurRegions)) flags |= eTraversalNeeded;
}
+ if (what & layer_state_t::eRenderBorderChanged) {
+ if (layer->enableBorder(s.borderEnabled, s.borderWidth, s.borderColor)) {
+ flags |= eTraversalNeeded;
+ }
+ }
if (what & layer_state_t::eLayerStackChanged) {
ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
// We only allow setting layer stacks for top level layers,
@@ -4518,9 +4505,10 @@
}
std::optional<nsecs_t> dequeueBufferTimestamp;
if (what & layer_state_t::eMetadataChanged) {
- dequeueBufferTimestamp = s.metadata.getInt64(METADATA_DEQUEUE_TIME);
+ dequeueBufferTimestamp = s.metadata.getInt64(gui::METADATA_DEQUEUE_TIME);
- if (const int32_t gameMode = s.metadata.getInt32(METADATA_GAME_MODE, -1); gameMode != -1) {
+ if (const int32_t gameMode = s.metadata.getInt32(gui::METADATA_GAME_MODE, -1);
+ gameMode != -1) {
// The transaction will be received on the Task layer and needs to be applied to all
// child layers. Child layers that are added at a later point will obtain the game mode
// info through addChild().
@@ -4537,6 +4525,14 @@
if (what & layer_state_t::eShadowRadiusChanged) {
if (layer->setShadowRadius(s.shadowRadius)) flags |= eTraversalNeeded;
}
+ if (what & layer_state_t::eDefaultFrameRateCompatibilityChanged) {
+ const auto compatibility =
+ Layer::FrameRate::convertCompatibility(s.defaultFrameRateCompatibility);
+
+ if (layer->setDefaultFrameRateCompatibility(compatibility)) {
+ flags |= eTraversalNeeded;
+ }
+ }
if (what & layer_state_t::eFrameRateSelectionPriority) {
if (layer->setFrameRateSelectionPriority(s.frameRateSelectionPriority)) {
flags |= eTraversalNeeded;
@@ -4587,7 +4583,7 @@
if (what & layer_state_t::eDropInputModeChanged) {
if (layer->setDropInputMode(s.dropInputMode)) {
flags |= eTraversalNeeded;
- mInputInfoChanged = true;
+ mUpdateInputInfo = true;
}
}
// This has to happen after we reparent children because when we reparent to null we remove
@@ -4736,42 +4732,6 @@
return result;
}
-status_t SurfaceFlinger::createBufferQueueLayer(LayerCreationArgs& args, PixelFormat& format,
- sp<IBinder>* handle,
- sp<IGraphicBufferProducer>* gbp,
- sp<Layer>* outLayer) {
- // initialize the surfaces
- switch (format) {
- case PIXEL_FORMAT_TRANSPARENT:
- case PIXEL_FORMAT_TRANSLUCENT:
- format = PIXEL_FORMAT_RGBA_8888;
- break;
- case PIXEL_FORMAT_OPAQUE:
- format = PIXEL_FORMAT_RGBX_8888;
- break;
- }
-
- sp<BufferQueueLayer> layer;
- args.textureName = getNewTexture();
- {
- // Grab the SF state lock during this since it's the only safe way to access
- // RenderEngine when creating a BufferLayerConsumer
- // TODO: Check if this lock is still needed here
- Mutex::Autolock lock(mStateLock);
- layer = getFactory().createBufferQueueLayer(args);
- }
-
- status_t err = layer->setDefaultBufferProperties(0, 0, format);
- if (err == NO_ERROR) {
- *handle = layer->getHandle();
- *gbp = layer->getProducer();
- *outLayer = layer;
- }
-
- ALOGE_IF(err, "createBufferQueueLayer() failed (%s)", strerror(-err));
- return err;
-}
-
status_t SurfaceFlinger::createBufferStateLayer(LayerCreationArgs& args, sp<IBinder>* handle,
sp<Layer>* outLayer) {
args.textureName = getNewTexture();
@@ -4846,10 +4806,6 @@
const nsecs_t vsyncPeriod = display->refreshRateConfigs().getActiveMode()->getVsyncPeriod();
mAnimFrameTracker.setDisplayRefreshPeriod(vsyncPeriod);
mActiveDisplayTransformHint = display->getTransformHint();
- // Use phase of 0 since phase is not known.
- // Use latency of 0, which will snap to the ideal latency.
- DisplayStatInfo stats{0 /* vsyncTime */, vsyncPeriod};
- setCompositorTimingSnapped(stats, 0);
}
void SurfaceFlinger::initializeDisplays() {
@@ -4930,6 +4886,9 @@
// Update display while dozing
getHwComposer().setPowerMode(displayId, mode);
if (isDisplayActiveLocked(display) && currentMode == hal::PowerMode::DOZE_SUSPEND) {
+ ALOGI("Force repainting for DOZE_SUSPEND -> DOZE or ON.");
+ mVisibleRegionsDirty = true;
+ scheduleRepaint();
mScheduler->onScreenAcquired(mAppConnectionHandle);
mScheduler->resyncToHardwareVsync(true, refreshRate);
}
@@ -5525,29 +5484,11 @@
#pragma clang diagnostic push
#pragma clang diagnostic error "-Wswitch-enum"
switch (static_cast<ISurfaceComposerTag>(code)) {
- case ENABLE_VSYNC_INJECTIONS:
- case INJECT_VSYNC:
- if (!hasMockHwc()) return PERMISSION_DENIED;
- [[fallthrough]];
// These methods should at minimum make sure that the client requested
// access to SF.
- case BOOT_FINISHED:
- case CLEAR_ANIMATION_FRAME_STATS:
- case GET_ANIMATION_FRAME_STATS:
- case OVERRIDE_HDR_TYPES:
case GET_HDR_CAPABILITIES:
- case SET_DESIRED_DISPLAY_MODE_SPECS:
- case GET_DESIRED_DISPLAY_MODE_SPECS:
- case SET_ACTIVE_COLOR_MODE:
- case SET_BOOT_DISPLAY_MODE:
case GET_AUTO_LOW_LATENCY_MODE_SUPPORT:
case GET_GAME_CONTENT_TYPE_SUPPORT:
- case GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES:
- case SET_DISPLAY_CONTENT_SAMPLING_ENABLED:
- case GET_DISPLAYED_CONTENT_SAMPLE:
- case ADD_TUNNEL_MODE_ENABLED_LISTENER:
- case REMOVE_TUNNEL_MODE_ENABLED_LISTENER:
- case SET_GLOBAL_SHADOW_SETTINGS:
case ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN: {
// OVERRIDE_HDR_TYPES is used by CTS tests, which acquire the necessary
// permission dynamically. Don't use the permission cache for this check.
@@ -5560,100 +5501,38 @@
}
return OK;
}
- case GET_LAYER_DEBUG_INFO: {
- IPCThreadState* ipc = IPCThreadState::self();
- const int pid = ipc->getCallingPid();
- const int uid = ipc->getCallingUid();
- if ((uid != AID_SHELL) && !PermissionCache::checkPermission(sDump, pid, uid)) {
- ALOGE("Layer debug info permission denied for pid=%d, uid=%d", pid, uid);
- return PERMISSION_DENIED;
- }
- return OK;
- }
- // Used by apps to hook Choreographer to SurfaceFlinger.
- case CREATE_DISPLAY_EVENT_CONNECTION:
// The following calls are currently used by clients that do not
// request necessary permissions. However, they do not expose any secret
// information, so it is OK to pass them.
- case AUTHENTICATE_SURFACE:
case GET_ACTIVE_COLOR_MODE:
case GET_ACTIVE_DISPLAY_MODE:
case GET_DISPLAY_COLOR_MODES:
- case GET_DISPLAY_NATIVE_PRIMARIES:
- case GET_STATIC_DISPLAY_INFO:
- case GET_DYNAMIC_DISPLAY_INFO:
case GET_DISPLAY_MODES:
- case GET_SUPPORTED_FRAME_TIMESTAMPS:
// Calling setTransactionState is safe, because you need to have been
// granted a reference to Client* and Handle* to do anything with it.
- case SET_TRANSACTION_STATE:
- case CREATE_CONNECTION:
- case GET_COLOR_MANAGEMENT:
- case GET_COMPOSITION_PREFERENCE:
- case GET_PROTECTED_CONTENT_SUPPORT:
- // setFrameRate() is deliberately available for apps to call without any
- // special permissions.
- case SET_FRAME_RATE:
- case GET_DISPLAY_DECORATION_SUPPORT:
- case SET_FRAME_TIMELINE_INFO:
- case GET_GPU_CONTEXT_PRIORITY:
- case GET_MAX_ACQUIRED_BUFFER_COUNT: {
+ case SET_TRANSACTION_STATE: {
// This is not sensitive information, so should not require permission control.
return OK;
}
- case ADD_FPS_LISTENER:
- case REMOVE_FPS_LISTENER:
- case ADD_REGION_SAMPLING_LISTENER:
- case REMOVE_REGION_SAMPLING_LISTENER: {
- // codes that require permission check
- IPCThreadState* ipc = IPCThreadState::self();
- const int pid = ipc->getCallingPid();
- const int uid = ipc->getCallingUid();
- if ((uid != AID_GRAPHICS) &&
- !PermissionCache::checkPermission(sReadFramebuffer, pid, uid)) {
- ALOGE("Permission Denial: can't read framebuffer pid=%d, uid=%d", pid, uid);
- return PERMISSION_DENIED;
- }
- return OK;
- }
- case ADD_TRANSACTION_TRACE_LISTENER: {
- IPCThreadState* ipc = IPCThreadState::self();
- const int uid = ipc->getCallingUid();
- if (uid == AID_ROOT || uid == AID_GRAPHICS || uid == AID_SYSTEM || uid == AID_SHELL) {
- return OK;
- }
- return PERMISSION_DENIED;
- }
- case SET_OVERRIDE_FRAME_RATE: {
- const int uid = IPCThreadState::self()->getCallingUid();
- if (uid == AID_ROOT || uid == AID_SYSTEM) {
- return OK;
- }
- return PERMISSION_DENIED;
- }
- case ON_PULL_ATOM: {
- const int uid = IPCThreadState::self()->getCallingUid();
- if (uid == AID_SYSTEM) {
- return OK;
- }
- return PERMISSION_DENIED;
- }
- case ADD_WINDOW_INFOS_LISTENER:
- case REMOVE_WINDOW_INFOS_LISTENER: {
- const int uid = IPCThreadState::self()->getCallingUid();
- if (uid == AID_SYSTEM || uid == AID_GRAPHICS) {
- return OK;
- }
- return PERMISSION_DENIED;
- }
+ case BOOT_FINISHED:
+ // Used by apps to hook Choreographer to SurfaceFlinger.
+ case CREATE_DISPLAY_EVENT_CONNECTION:
+ case CREATE_CONNECTION:
case CREATE_DISPLAY:
case DESTROY_DISPLAY:
case GET_PRIMARY_PHYSICAL_DISPLAY_ID:
case GET_PHYSICAL_DISPLAY_IDS:
case GET_PHYSICAL_DISPLAY_TOKEN:
+ case AUTHENTICATE_SURFACE:
case SET_POWER_MODE:
+ case GET_SUPPORTED_FRAME_TIMESTAMPS:
case GET_DISPLAY_STATE:
case GET_DISPLAY_STATS:
+ case GET_STATIC_DISPLAY_INFO:
+ case GET_DYNAMIC_DISPLAY_INFO:
+ case GET_DISPLAY_NATIVE_PRIMARIES:
+ case SET_ACTIVE_COLOR_MODE:
+ case SET_BOOT_DISPLAY_MODE:
case CLEAR_BOOT_DISPLAY_MODE:
case GET_BOOT_DISPLAY_MODE_SUPPORT:
case SET_AUTO_LOW_LATENCY_MODE:
@@ -5661,12 +5540,43 @@
case CAPTURE_LAYERS:
case CAPTURE_DISPLAY:
case CAPTURE_DISPLAY_BY_ID:
+ case CLEAR_ANIMATION_FRAME_STATS:
+ case GET_ANIMATION_FRAME_STATS:
+ case OVERRIDE_HDR_TYPES:
+ case ON_PULL_ATOM:
+ case ENABLE_VSYNC_INJECTIONS:
+ case INJECT_VSYNC:
+ case GET_LAYER_DEBUG_INFO:
+ case GET_COLOR_MANAGEMENT:
+ case GET_COMPOSITION_PREFERENCE:
+ case GET_DISPLAYED_CONTENT_SAMPLING_ATTRIBUTES:
+ case SET_DISPLAY_CONTENT_SAMPLING_ENABLED:
+ case GET_DISPLAYED_CONTENT_SAMPLE:
+ case GET_PROTECTED_CONTENT_SUPPORT:
case IS_WIDE_COLOR_DISPLAY:
+ case ADD_REGION_SAMPLING_LISTENER:
+ case REMOVE_REGION_SAMPLING_LISTENER:
+ case ADD_FPS_LISTENER:
+ case REMOVE_FPS_LISTENER:
+ case ADD_TUNNEL_MODE_ENABLED_LISTENER:
+ case REMOVE_TUNNEL_MODE_ENABLED_LISTENER:
+ case ADD_WINDOW_INFOS_LISTENER:
+ case REMOVE_WINDOW_INFOS_LISTENER:
+ case SET_DESIRED_DISPLAY_MODE_SPECS:
+ case GET_DESIRED_DISPLAY_MODE_SPECS:
case GET_DISPLAY_BRIGHTNESS_SUPPORT:
case SET_DISPLAY_BRIGHTNESS:
case ADD_HDR_LAYER_INFO_LISTENER:
case REMOVE_HDR_LAYER_INFO_LISTENER:
case NOTIFY_POWER_BOOST:
+ case SET_GLOBAL_SHADOW_SETTINGS:
+ case GET_DISPLAY_DECORATION_SUPPORT:
+ case SET_FRAME_RATE:
+ case SET_OVERRIDE_FRAME_RATE:
+ case SET_FRAME_TIMELINE_INFO:
+ case ADD_TRANSACTION_TRACE_LISTENER:
+ case GET_GPU_CONTEXT_PRIORITY:
+ case GET_MAX_ACQUIRED_BUFFER_COUNT:
LOG_FATAL("Deprecated opcode: %d, migrated to AIDL", code);
return PERMISSION_DENIED;
}
@@ -5878,7 +5788,8 @@
(fixedStartingTime) ? fixedStartingTime : systemTime();
mScheduler
->schedule([&]() FTL_FAKE_GUARD(mStateLock) {
- mLayerTracing.notify("start", startingTime);
+ mLayerTracing.notify(true /* visibleRegionDirty */,
+ startingTime, mLastCommittedVsyncId);
})
.wait();
}
@@ -6676,24 +6587,21 @@
});
if (captureListener) {
- // TODO: The future returned by std::async blocks the main thread. Return a chain of
- // futures to the Binder thread instead.
- std::async([=]() mutable {
- ATRACE_NAME("captureListener is nonnull!");
- auto fenceResult = renderFuture.get();
- // TODO(b/232535621): Change ScreenCaptureResults to store a FenceResult.
- captureResults.result = fenceStatus(fenceResult);
- captureResults.fence = std::move(fenceResult).value_or(Fence::NO_FENCE);
- captureListener->onScreenCaptureCompleted(captureResults);
- });
+ // Defer blocking on renderFuture back to the Binder thread.
+ return ftl::Future(std::move(renderFuture))
+ .then([captureListener, captureResults = std::move(captureResults)](
+ FenceResult fenceResult) mutable -> FenceResult {
+ // TODO(b/232535621): Change ScreenCaptureResults to store a FenceResult.
+ captureResults.result = fenceStatus(fenceResult);
+ captureResults.fence = std::move(fenceResult).value_or(Fence::NO_FENCE);
+ captureListener->onScreenCaptureCompleted(captureResults);
+ return base::unexpected(NO_ERROR);
+ })
+ .share();
}
return renderFuture;
});
- if (captureListener) {
- return ftl::yield<FenceResult>(base::unexpected(NO_ERROR)).share();
- }
-
// Flatten nested futures.
auto chain = ftl::Future(std::move(future)).then([](ftl::SharedFuture<FenceResult> future) {
return future;
@@ -6861,11 +6769,6 @@
return future;
}
-void SurfaceFlinger::windowInfosReported() {
- Mutex::Autolock _l(mStateLock);
- signalSynchronousTransactions(CountDownLatch::eSyncInputWindows);
-}
-
// ---------------------------------------------------------------------------
void SurfaceFlinger::State::traverse(const LayerVector::Visitor& visitor) const {
@@ -7098,45 +7001,12 @@
// on the work to remove the table in that bug rather than adding more to
// it.
static const std::unordered_map<std::string, uint32_t> genericLayerMetadataKeyMap{
- {"org.chromium.arc.V1_0.TaskId", METADATA_TASK_ID},
- {"org.chromium.arc.V1_0.CursorInfo", METADATA_MOUSE_CURSOR},
+ {"org.chromium.arc.V1_0.TaskId", gui::METADATA_TASK_ID},
+ {"org.chromium.arc.V1_0.CursorInfo", gui::METADATA_MOUSE_CURSOR},
};
return genericLayerMetadataKeyMap;
}
-status_t SurfaceFlinger::setFrameRate(const sp<IGraphicBufferProducer>& surface, float frameRate,
- int8_t compatibility, int8_t changeFrameRateStrategy) {
- if (!ValidateFrameRate(frameRate, compatibility, changeFrameRateStrategy,
- "SurfaceFlinger::setFrameRate")) {
- return BAD_VALUE;
- }
-
- static_cast<void>(mScheduler->schedule([=] {
- Mutex::Autolock lock(mStateLock);
- if (authenticateSurfaceTextureLocked(surface)) {
- sp<Layer> layer = (static_cast<MonitoredProducer*>(surface.get()))->getLayer();
- if (layer == nullptr) {
- ALOGE("Attempt to set frame rate on a layer that no longer exists");
- return BAD_VALUE;
- }
- const auto strategy =
- Layer::FrameRate::convertChangeFrameRateStrategy(changeFrameRateStrategy);
- if (layer->setFrameRate(
- Layer::FrameRate(Fps::fromValue(frameRate),
- Layer::FrameRate::convertCompatibility(compatibility),
- strategy))) {
- setTransactionFlags(eTraversalNeeded);
- }
- } else {
- ALOGE("Attempt to set frame rate on an unrecognized IGraphicBufferProducer");
- return BAD_VALUE;
- }
- return NO_ERROR;
- }));
-
- return NO_ERROR;
-}
-
status_t SurfaceFlinger::setOverrideFrameRate(uid_t uid, float frameRate) {
PhysicalDisplayId displayId = [&]() {
Mutex::Autolock lock(mStateLock);
@@ -7148,24 +7018,6 @@
return NO_ERROR;
}
-status_t SurfaceFlinger::setFrameTimelineInfo(const sp<IGraphicBufferProducer>& surface,
- const FrameTimelineInfo& frameTimelineInfo) {
- Mutex::Autolock lock(mStateLock);
- if (!authenticateSurfaceTextureLocked(surface)) {
- ALOGE("Attempt to set frame timeline info on an unrecognized IGraphicBufferProducer");
- return BAD_VALUE;
- }
-
- sp<Layer> layer = (static_cast<MonitoredProducer*>(surface.get()))->getLayer();
- if (layer == nullptr) {
- ALOGE("Attempt to set frame timeline info on a layer that no longer exists");
- return BAD_VALUE;
- }
-
- layer->setFrameTimelineInfoForBuffer(frameTimelineInfo);
- return NO_ERROR;
-}
-
void SurfaceFlinger::enableRefreshRateOverlay(bool enable) {
for (const auto& [ignored, display] : mDisplays) {
if (display->isInternal()) {
@@ -7185,7 +7037,7 @@
return NO_ERROR;
}
-int SurfaceFlinger::getGPUContextPriority() {
+int SurfaceFlinger::getGpuContextPriority() {
return getRenderEngine().getContextPriority();
}
@@ -7231,7 +7083,7 @@
return calculateMaxAcquiredBufferCount(refreshRate, presentLatency);
}
-void SurfaceFlinger::handleLayerCreatedLocked(const LayerCreatedState& state) {
+void SurfaceFlinger::handleLayerCreatedLocked(const LayerCreatedState& state, int64_t vsyncId) {
sp<Layer> layer = state.layer.promote();
if (!layer) {
ALOGD("Layer was destroyed soon after creation %p", state.layer.unsafe_get());
@@ -7261,7 +7113,9 @@
}
layer->updateTransformHint(mActiveDisplayTransformHint);
-
+ if (mTransactionTracing) {
+ mTransactionTracing->onLayerAddedToDrawingState(layer->getSequence(), vsyncId);
+ }
mInterceptor->saveSurfaceCreation(layer);
}
@@ -7345,7 +7199,7 @@
return buffer;
}
-bool SurfaceFlinger::commitCreatedLayers() {
+bool SurfaceFlinger::commitCreatedLayers(int64_t vsyncId) {
std::vector<LayerCreatedState> createdLayers;
{
std::scoped_lock<std::mutex> lock(mCreatedLayersLock);
@@ -7358,7 +7212,7 @@
Mutex::Autolock _l(mStateLock);
for (const auto& createdLayer : createdLayers) {
- handleLayerCreatedLocked(createdLayer);
+ handleLayerCreatedLocked(createdLayer, vsyncId);
}
createdLayers.clear();
mLayersAdded = true;
@@ -7367,24 +7221,58 @@
// gui::ISurfaceComposer
+binder::Status SurfaceComposerAIDL::bootFinished() {
+ status_t status = checkAccessPermission();
+ if (status != OK) {
+ return binderStatusFromStatusT(status);
+ }
+ mFlinger->bootFinished();
+ return binder::Status::ok();
+}
+
+binder::Status SurfaceComposerAIDL::createDisplayEventConnection(
+ VsyncSource vsyncSource, EventRegistration eventRegistration,
+ sp<IDisplayEventConnection>* outConnection) {
+ sp<IDisplayEventConnection> conn =
+ mFlinger->createDisplayEventConnection(vsyncSource, eventRegistration);
+ if (conn == nullptr) {
+ *outConnection = nullptr;
+ return binderStatusFromStatusT(BAD_VALUE);
+ } else {
+ *outConnection = conn;
+ return binder::Status::ok();
+ }
+}
+
+binder::Status SurfaceComposerAIDL::createConnection(sp<gui::ISurfaceComposerClient>* outClient) {
+ const sp<Client> client = new Client(mFlinger);
+ if (client->initCheck() == NO_ERROR) {
+ *outClient = client;
+ return binder::Status::ok();
+ } else {
+ *outClient = nullptr;
+ return binderStatusFromStatusT(BAD_VALUE);
+ }
+}
+
binder::Status SurfaceComposerAIDL::createDisplay(const std::string& displayName, bool secure,
sp<IBinder>* outDisplay) {
status_t status = checkAccessPermission();
- if (status == OK) {
- String8 displayName8 = String8::format("%s", displayName.c_str());
- *outDisplay = mFlinger->createDisplay(displayName8, secure);
- return binder::Status::ok();
+ if (status != OK) {
+ return binderStatusFromStatusT(status);
}
- return binder::Status::fromStatusT(status);
+ String8 displayName8 = String8::format("%s", displayName.c_str());
+ *outDisplay = mFlinger->createDisplay(displayName8, secure);
+ return binder::Status::ok();
}
binder::Status SurfaceComposerAIDL::destroyDisplay(const sp<IBinder>& display) {
status_t status = checkAccessPermission();
- if (status == OK) {
- mFlinger->destroyDisplay(display);
- return binder::Status::ok();
+ if (status != OK) {
+ return binderStatusFromStatusT(status);
}
- return binder::Status::fromStatusT(status);
+ mFlinger->destroyDisplay(display);
+ return binder::Status::ok();
}
binder::Status SurfaceComposerAIDL::getPhysicalDisplayIds(std::vector<int64_t>* outDisplayIds) {
@@ -7401,7 +7289,7 @@
binder::Status SurfaceComposerAIDL::getPrimaryPhysicalDisplayId(int64_t* outDisplayId) {
status_t status = checkAccessPermission();
if (status != OK) {
- return binder::Status::fromStatusT(status);
+ return binderStatusFromStatusT(status);
}
PhysicalDisplayId id;
@@ -7409,7 +7297,7 @@
if (status == NO_ERROR) {
*outDisplayId = id.value;
}
- return binder::Status::fromStatusT(status);
+ return binderStatusFromStatusT(status);
}
binder::Status SurfaceComposerAIDL::getPhysicalDisplayToken(int64_t displayId,
@@ -7421,12 +7309,25 @@
binder::Status SurfaceComposerAIDL::setPowerMode(const sp<IBinder>& display, int mode) {
status_t status = checkAccessPermission();
- if (status != OK) return binder::Status::fromStatusT(status);
-
+ if (status != OK) {
+ return binderStatusFromStatusT(status);
+ }
mFlinger->setPowerMode(display, mode);
return binder::Status::ok();
}
+binder::Status SurfaceComposerAIDL::getSupportedFrameTimestamps(
+ std::vector<FrameEvent>* outSupported) {
+ status_t status;
+ if (!outSupported) {
+ status = UNEXPECTED_NULL;
+ } else {
+ outSupported->clear();
+ status = mFlinger->getSupportedFrameTimestamps(outSupported);
+ }
+ return binderStatusFromStatusT(status);
+}
+
binder::Status SurfaceComposerAIDL::getDisplayStats(const sp<IBinder>& display,
gui::DisplayStatInfo* outStatInfo) {
DisplayStatInfo statInfo;
@@ -7435,7 +7336,7 @@
outStatInfo->vsyncTime = static_cast<long>(statInfo.vsyncTime);
outStatInfo->vsyncPeriod = static_cast<long>(statInfo.vsyncPeriod);
}
- return binder::Status::fromStatusT(status);
+ return binderStatusFromStatusT(status);
}
binder::Status SurfaceComposerAIDL::getDisplayState(const sp<IBinder>& display,
@@ -7448,37 +7349,175 @@
outState->layerStackSpaceRect.width = state.layerStackSpaceRect.width;
outState->layerStackSpaceRect.height = state.layerStackSpaceRect.height;
}
- return binder::Status::fromStatusT(status);
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::getStaticDisplayInfo(const sp<IBinder>& display,
+ gui::StaticDisplayInfo* outInfo) {
+ using Tag = gui::DeviceProductInfo::ManufactureOrModelDate::Tag;
+ ui::StaticDisplayInfo info;
+ status_t status = mFlinger->getStaticDisplayInfo(display, &info);
+ if (status == NO_ERROR) {
+ // convert ui::StaticDisplayInfo to gui::StaticDisplayInfo
+ outInfo->connectionType = static_cast<gui::DisplayConnectionType>(info.connectionType);
+ outInfo->density = info.density;
+ outInfo->secure = info.secure;
+ outInfo->installOrientation = static_cast<gui::Rotation>(info.installOrientation);
+
+ gui::DeviceProductInfo dinfo;
+ std::optional<DeviceProductInfo> dpi = info.deviceProductInfo;
+ dinfo.name = std::move(dpi->name);
+ dinfo.manufacturerPnpId =
+ std::vector<uint8_t>(dpi->manufacturerPnpId.begin(), dpi->manufacturerPnpId.end());
+ dinfo.productId = dpi->productId;
+ dinfo.relativeAddress =
+ std::vector<uint8_t>(dpi->relativeAddress.begin(), dpi->relativeAddress.end());
+ if (const auto* model =
+ std::get_if<DeviceProductInfo::ModelYear>(&dpi->manufactureOrModelDate)) {
+ gui::DeviceProductInfo::ModelYear modelYear;
+ modelYear.year = model->year;
+ dinfo.manufactureOrModelDate.set<Tag::modelYear>(modelYear);
+ } else if (const auto* manufacture = std::get_if<DeviceProductInfo::ManufactureYear>(
+ &dpi->manufactureOrModelDate)) {
+ gui::DeviceProductInfo::ManufactureYear date;
+ date.modelYear.year = manufacture->year;
+ dinfo.manufactureOrModelDate.set<Tag::manufactureYear>(date);
+ } else if (const auto* manufacture = std::get_if<DeviceProductInfo::ManufactureWeekAndYear>(
+ &dpi->manufactureOrModelDate)) {
+ gui::DeviceProductInfo::ManufactureWeekAndYear date;
+ date.manufactureYear.modelYear.year = manufacture->year;
+ date.week = manufacture->week;
+ dinfo.manufactureOrModelDate.set<Tag::manufactureWeekAndYear>(date);
+ }
+
+ outInfo->deviceProductInfo = dinfo;
+ }
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::getDynamicDisplayInfo(const sp<IBinder>& display,
+ gui::DynamicDisplayInfo* outInfo) {
+ ui::DynamicDisplayInfo info;
+ status_t status = mFlinger->getDynamicDisplayInfo(display, &info);
+ if (status == NO_ERROR) {
+ // convert ui::DynamicDisplayInfo to gui::DynamicDisplayInfo
+ outInfo->supportedDisplayModes.clear();
+ outInfo->supportedDisplayModes.reserve(info.supportedDisplayModes.size());
+ for (const auto& mode : info.supportedDisplayModes) {
+ gui::DisplayMode outMode;
+ outMode.id = mode.id;
+ outMode.resolution.width = mode.resolution.width;
+ outMode.resolution.height = mode.resolution.height;
+ outMode.xDpi = mode.xDpi;
+ outMode.yDpi = mode.yDpi;
+ outMode.refreshRate = mode.refreshRate;
+ outMode.appVsyncOffset = mode.appVsyncOffset;
+ outMode.sfVsyncOffset = mode.sfVsyncOffset;
+ outMode.presentationDeadline = mode.presentationDeadline;
+ outMode.group = mode.group;
+ outInfo->supportedDisplayModes.push_back(outMode);
+ }
+
+ outInfo->activeDisplayModeId = info.activeDisplayModeId;
+
+ outInfo->supportedColorModes.clear();
+ outInfo->supportedColorModes.reserve(info.supportedColorModes.size());
+ for (const auto& cmode : info.supportedColorModes) {
+ outInfo->supportedColorModes.push_back(static_cast<int32_t>(cmode));
+ }
+
+ outInfo->activeColorMode = static_cast<int32_t>(info.activeColorMode);
+
+ gui::HdrCapabilities& hdrCapabilities = outInfo->hdrCapabilities;
+ hdrCapabilities.supportedHdrTypes.clear();
+ hdrCapabilities.supportedHdrTypes.reserve(
+ info.hdrCapabilities.getSupportedHdrTypes().size());
+ for (const auto& hdr : info.hdrCapabilities.getSupportedHdrTypes()) {
+ hdrCapabilities.supportedHdrTypes.push_back(static_cast<int32_t>(hdr));
+ }
+ hdrCapabilities.maxLuminance = info.hdrCapabilities.getDesiredMaxLuminance();
+ hdrCapabilities.maxAverageLuminance = info.hdrCapabilities.getDesiredMaxAverageLuminance();
+ hdrCapabilities.minLuminance = info.hdrCapabilities.getDesiredMinLuminance();
+
+ outInfo->autoLowLatencyModeSupported = info.autoLowLatencyModeSupported;
+ outInfo->gameContentTypeSupported = info.gameContentTypeSupported;
+ outInfo->preferredBootDisplayMode = info.preferredBootDisplayMode;
+ }
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::getDisplayNativePrimaries(const sp<IBinder>& display,
+ gui::DisplayPrimaries* outPrimaries) {
+ ui::DisplayPrimaries primaries;
+ status_t status = mFlinger->getDisplayNativePrimaries(display, primaries);
+ if (status == NO_ERROR) {
+ outPrimaries->red.X = primaries.red.X;
+ outPrimaries->red.Y = primaries.red.Y;
+ outPrimaries->red.Z = primaries.red.Z;
+
+ outPrimaries->green.X = primaries.green.X;
+ outPrimaries->green.Y = primaries.green.Y;
+ outPrimaries->green.Z = primaries.green.Z;
+
+ outPrimaries->blue.X = primaries.blue.X;
+ outPrimaries->blue.Y = primaries.blue.Y;
+ outPrimaries->blue.Z = primaries.blue.Z;
+
+ outPrimaries->white.X = primaries.white.X;
+ outPrimaries->white.Y = primaries.white.Y;
+ outPrimaries->white.Z = primaries.white.Z;
+ }
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::setActiveColorMode(const sp<IBinder>& display, int colorMode) {
+ status_t status = checkAccessPermission();
+ if (status == OK) {
+ status = mFlinger->setActiveColorMode(display, static_cast<ui::ColorMode>(colorMode));
+ }
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::setBootDisplayMode(const sp<IBinder>& display,
+ int displayModeId) {
+ status_t status = checkAccessPermission();
+ if (status == OK) {
+ status = mFlinger->setBootDisplayMode(display,
+ static_cast<ui::DisplayModeId>(displayModeId));
+ }
+ return binderStatusFromStatusT(status);
}
binder::Status SurfaceComposerAIDL::clearBootDisplayMode(const sp<IBinder>& display) {
status_t status = checkAccessPermission();
- if (status != OK) return binder::Status::fromStatusT(status);
-
- status = mFlinger->clearBootDisplayMode(display);
- return binder::Status::fromStatusT(status);
+ if (status == OK) {
+ status = mFlinger->clearBootDisplayMode(display);
+ }
+ return binderStatusFromStatusT(status);
}
binder::Status SurfaceComposerAIDL::getBootDisplayModeSupport(bool* outMode) {
status_t status = checkAccessPermission();
- if (status != OK) return binder::Status::fromStatusT(status);
-
- status = mFlinger->getBootDisplayModeSupport(outMode);
- return binder::Status::fromStatusT(status);
+ if (status == OK) {
+ status = mFlinger->getBootDisplayModeSupport(outMode);
+ }
+ return binderStatusFromStatusT(status);
}
binder::Status SurfaceComposerAIDL::setAutoLowLatencyMode(const sp<IBinder>& display, bool on) {
status_t status = checkAccessPermission();
- if (status != OK) return binder::Status::fromStatusT(status);
-
+ if (status != OK) {
+ return binderStatusFromStatusT(status);
+ }
mFlinger->setAutoLowLatencyMode(display, on);
return binder::Status::ok();
}
binder::Status SurfaceComposerAIDL::setGameContentType(const sp<IBinder>& display, bool on) {
status_t status = checkAccessPermission();
- if (status != OK) return binder::Status::fromStatusT(status);
-
+ if (status != OK) {
+ return binderStatusFromStatusT(status);
+ }
mFlinger->setGameContentType(display, on);
return binder::Status::ok();
}
@@ -7486,7 +7525,7 @@
binder::Status SurfaceComposerAIDL::captureDisplay(
const DisplayCaptureArgs& args, const sp<IScreenCaptureListener>& captureListener) {
status_t status = mFlinger->captureDisplay(args, captureListener);
- return binder::Status::fromStatusT(status);
+ return binderStatusFromStatusT(status);
}
binder::Status SurfaceComposerAIDL::captureDisplayById(
@@ -7500,60 +7539,465 @@
} else {
status = PERMISSION_DENIED;
}
- return binder::Status::fromStatusT(status);
+ return binderStatusFromStatusT(status);
}
binder::Status SurfaceComposerAIDL::captureLayers(
const LayerCaptureArgs& args, const sp<IScreenCaptureListener>& captureListener) {
status_t status = mFlinger->captureLayers(args, captureListener);
- return binder::Status::fromStatusT(status);
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::clearAnimationFrameStats() {
+ status_t status = checkAccessPermission();
+ if (status == OK) {
+ status = mFlinger->clearAnimationFrameStats();
+ }
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::getAnimationFrameStats(gui::FrameStats* outStats) {
+ status_t status = checkAccessPermission();
+ if (status != OK) {
+ return binderStatusFromStatusT(status);
+ }
+
+ FrameStats stats;
+ status = mFlinger->getAnimationFrameStats(&stats);
+ if (status == NO_ERROR) {
+ outStats->refreshPeriodNano = stats.refreshPeriodNano;
+ outStats->desiredPresentTimesNano.reserve(stats.desiredPresentTimesNano.size());
+ for (const auto& t : stats.desiredPresentTimesNano) {
+ outStats->desiredPresentTimesNano.push_back(t);
+ }
+ outStats->actualPresentTimesNano.reserve(stats.actualPresentTimesNano.size());
+ for (const auto& t : stats.actualPresentTimesNano) {
+ outStats->actualPresentTimesNano.push_back(t);
+ }
+ outStats->frameReadyTimesNano.reserve(stats.frameReadyTimesNano.size());
+ for (const auto& t : stats.frameReadyTimesNano) {
+ outStats->frameReadyTimesNano.push_back(t);
+ }
+ }
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::overrideHdrTypes(const sp<IBinder>& display,
+ const std::vector<int32_t>& hdrTypes) {
+ // overrideHdrTypes is used by CTS tests, which acquire the necessary
+ // permission dynamically. Don't use the permission cache for this check.
+ status_t status = checkAccessPermission(false);
+ if (status != OK) {
+ return binderStatusFromStatusT(status);
+ }
+
+ std::vector<ui::Hdr> hdrTypesVector;
+ for (int32_t i : hdrTypes) {
+ hdrTypesVector.push_back(static_cast<ui::Hdr>(i));
+ }
+ status = mFlinger->overrideHdrTypes(display, hdrTypesVector);
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::onPullAtom(int32_t atomId, gui::PullAtomData* outPullData) {
+ status_t status;
+ const int uid = IPCThreadState::self()->getCallingUid();
+ if (uid != AID_SYSTEM) {
+ status = PERMISSION_DENIED;
+ } else {
+ status = mFlinger->onPullAtom(atomId, &outPullData->data, &outPullData->success);
+ }
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::enableVSyncInjections(bool enable) {
+ if (!mFlinger->hasMockHwc()) {
+ return binderStatusFromStatusT(PERMISSION_DENIED);
+ }
+
+ status_t status = checkAccessPermission();
+ if (status == OK) {
+ status = mFlinger->enableVSyncInjections(enable);
+ }
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::injectVSync(int64_t when) {
+ if (!mFlinger->hasMockHwc()) {
+ return binderStatusFromStatusT(PERMISSION_DENIED);
+ }
+
+ status_t status = checkAccessPermission();
+ if (status == OK) {
+ status = mFlinger->injectVSync(when);
+ }
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::getLayerDebugInfo(std::vector<gui::LayerDebugInfo>* outLayers) {
+ if (!outLayers) {
+ return binderStatusFromStatusT(UNEXPECTED_NULL);
+ }
+
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int pid = ipc->getCallingPid();
+ const int uid = ipc->getCallingUid();
+ if ((uid != AID_SHELL) && !PermissionCache::checkPermission(sDump, pid, uid)) {
+ ALOGE("Layer debug info permission denied for pid=%d, uid=%d", pid, uid);
+ return binderStatusFromStatusT(PERMISSION_DENIED);
+ }
+ status_t status = mFlinger->getLayerDebugInfo(outLayers);
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::getColorManagement(bool* outGetColorManagement) {
+ status_t status = mFlinger->getColorManagement(outGetColorManagement);
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::getCompositionPreference(gui::CompositionPreference* outPref) {
+ ui::Dataspace dataspace;
+ ui::PixelFormat pixelFormat;
+ ui::Dataspace wideColorGamutDataspace;
+ ui::PixelFormat wideColorGamutPixelFormat;
+ status_t status =
+ mFlinger->getCompositionPreference(&dataspace, &pixelFormat, &wideColorGamutDataspace,
+ &wideColorGamutPixelFormat);
+ if (status == NO_ERROR) {
+ outPref->defaultDataspace = static_cast<int32_t>(dataspace);
+ outPref->defaultPixelFormat = static_cast<int32_t>(pixelFormat);
+ outPref->wideColorGamutDataspace = static_cast<int32_t>(wideColorGamutDataspace);
+ outPref->wideColorGamutPixelFormat = static_cast<int32_t>(wideColorGamutPixelFormat);
+ }
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::getDisplayedContentSamplingAttributes(
+ const sp<IBinder>& display, gui::ContentSamplingAttributes* outAttrs) {
+ status_t status = checkAccessPermission();
+ if (status != OK) {
+ return binderStatusFromStatusT(status);
+ }
+
+ ui::PixelFormat format;
+ ui::Dataspace dataspace;
+ uint8_t componentMask;
+ status = mFlinger->getDisplayedContentSamplingAttributes(display, &format, &dataspace,
+ &componentMask);
+ if (status == NO_ERROR) {
+ outAttrs->format = static_cast<int32_t>(format);
+ outAttrs->dataspace = static_cast<int32_t>(dataspace);
+ outAttrs->componentMask = static_cast<int8_t>(componentMask);
+ }
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::setDisplayContentSamplingEnabled(const sp<IBinder>& display,
+ bool enable,
+ int8_t componentMask,
+ int64_t maxFrames) {
+ status_t status = checkAccessPermission();
+ if (status == OK) {
+ status = mFlinger->setDisplayContentSamplingEnabled(display, enable,
+ static_cast<uint8_t>(componentMask),
+ static_cast<uint64_t>(maxFrames));
+ }
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::getDisplayedContentSample(const sp<IBinder>& display,
+ int64_t maxFrames, int64_t timestamp,
+ gui::DisplayedFrameStats* outStats) {
+ if (!outStats) {
+ return binderStatusFromStatusT(BAD_VALUE);
+ }
+
+ status_t status = checkAccessPermission();
+ if (status != OK) {
+ return binderStatusFromStatusT(status);
+ }
+
+ DisplayedFrameStats stats;
+ status = mFlinger->getDisplayedContentSample(display, static_cast<uint64_t>(maxFrames),
+ static_cast<uint64_t>(timestamp), &stats);
+ if (status == NO_ERROR) {
+ // convert from ui::DisplayedFrameStats to gui::DisplayedFrameStats
+ outStats->numFrames = static_cast<int64_t>(stats.numFrames);
+ outStats->component_0_sample.reserve(stats.component_0_sample.size());
+ for (const auto& s : stats.component_0_sample) {
+ outStats->component_0_sample.push_back(static_cast<int64_t>(s));
+ }
+ outStats->component_1_sample.reserve(stats.component_1_sample.size());
+ for (const auto& s : stats.component_1_sample) {
+ outStats->component_1_sample.push_back(static_cast<int64_t>(s));
+ }
+ outStats->component_2_sample.reserve(stats.component_2_sample.size());
+ for (const auto& s : stats.component_2_sample) {
+ outStats->component_2_sample.push_back(static_cast<int64_t>(s));
+ }
+ outStats->component_3_sample.reserve(stats.component_3_sample.size());
+ for (const auto& s : stats.component_3_sample) {
+ outStats->component_3_sample.push_back(static_cast<int64_t>(s));
+ }
+ }
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::getProtectedContentSupport(bool* outSupported) {
+ status_t status = mFlinger->getProtectedContentSupport(outSupported);
+ return binderStatusFromStatusT(status);
}
binder::Status SurfaceComposerAIDL::isWideColorDisplay(const sp<IBinder>& token,
bool* outIsWideColorDisplay) {
status_t status = mFlinger->isWideColorDisplay(token, outIsWideColorDisplay);
- return binder::Status::fromStatusT(status);
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::addRegionSamplingListener(
+ const gui::ARect& samplingArea, const sp<IBinder>& stopLayerHandle,
+ const sp<gui::IRegionSamplingListener>& listener) {
+ status_t status = checkReadFrameBufferPermission();
+ if (status != OK) {
+ return binderStatusFromStatusT(status);
+ }
+ android::Rect rect;
+ rect.left = samplingArea.left;
+ rect.top = samplingArea.top;
+ rect.right = samplingArea.right;
+ rect.bottom = samplingArea.bottom;
+ status = mFlinger->addRegionSamplingListener(rect, stopLayerHandle, listener);
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::removeRegionSamplingListener(
+ const sp<gui::IRegionSamplingListener>& listener) {
+ status_t status = checkReadFrameBufferPermission();
+ if (status == OK) {
+ status = mFlinger->removeRegionSamplingListener(listener);
+ }
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::addFpsListener(int32_t taskId,
+ const sp<gui::IFpsListener>& listener) {
+ status_t status = checkReadFrameBufferPermission();
+ if (status == OK) {
+ status = mFlinger->addFpsListener(taskId, listener);
+ }
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::removeFpsListener(const sp<gui::IFpsListener>& listener) {
+ status_t status = checkReadFrameBufferPermission();
+ if (status == OK) {
+ status = mFlinger->removeFpsListener(listener);
+ }
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::addTunnelModeEnabledListener(
+ const sp<gui::ITunnelModeEnabledListener>& listener) {
+ status_t status = checkAccessPermission();
+ if (status == OK) {
+ status = mFlinger->addTunnelModeEnabledListener(listener);
+ }
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::removeTunnelModeEnabledListener(
+ const sp<gui::ITunnelModeEnabledListener>& listener) {
+ status_t status = checkAccessPermission();
+ if (status == OK) {
+ status = mFlinger->removeTunnelModeEnabledListener(listener);
+ }
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::setDesiredDisplayModeSpecs(
+ const sp<IBinder>& displayToken, int32_t defaultMode, bool allowGroupSwitching,
+ float primaryRefreshRateMin, float primaryRefreshRateMax, float appRequestRefreshRateMin,
+ float appRequestRefreshRateMax) {
+ status_t status = checkAccessPermission();
+ if (status == OK) {
+ status = mFlinger->setDesiredDisplayModeSpecs(displayToken,
+ static_cast<ui::DisplayModeId>(defaultMode),
+ allowGroupSwitching, primaryRefreshRateMin,
+ primaryRefreshRateMax,
+ appRequestRefreshRateMin,
+ appRequestRefreshRateMax);
+ }
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::getDesiredDisplayModeSpecs(const sp<IBinder>& displayToken,
+ gui::DisplayModeSpecs* outSpecs) {
+ if (!outSpecs) {
+ return binderStatusFromStatusT(BAD_VALUE);
+ }
+
+ status_t status = checkAccessPermission();
+ if (status != OK) {
+ return binderStatusFromStatusT(status);
+ }
+
+ ui::DisplayModeId displayModeId;
+ bool allowGroupSwitching;
+ float primaryRefreshRateMin;
+ float primaryRefreshRateMax;
+ float appRequestRefreshRateMin;
+ float appRequestRefreshRateMax;
+ status = mFlinger->getDesiredDisplayModeSpecs(displayToken, &displayModeId,
+ &allowGroupSwitching, &primaryRefreshRateMin,
+ &primaryRefreshRateMax, &appRequestRefreshRateMin,
+ &appRequestRefreshRateMax);
+ if (status == NO_ERROR) {
+ outSpecs->defaultMode = displayModeId;
+ outSpecs->allowGroupSwitching = allowGroupSwitching;
+ outSpecs->primaryRefreshRateMin = primaryRefreshRateMin;
+ outSpecs->primaryRefreshRateMax = primaryRefreshRateMax;
+ outSpecs->appRequestRefreshRateMin = appRequestRefreshRateMin;
+ outSpecs->appRequestRefreshRateMax = appRequestRefreshRateMax;
+ }
+
+ return binderStatusFromStatusT(status);
}
binder::Status SurfaceComposerAIDL::getDisplayBrightnessSupport(const sp<IBinder>& displayToken,
bool* outSupport) {
status_t status = mFlinger->getDisplayBrightnessSupport(displayToken, outSupport);
- return binder::Status::fromStatusT(status);
+ return binderStatusFromStatusT(status);
}
binder::Status SurfaceComposerAIDL::setDisplayBrightness(const sp<IBinder>& displayToken,
const gui::DisplayBrightness& brightness) {
status_t status = checkControlDisplayBrightnessPermission();
- if (status != OK) return binder::Status::fromStatusT(status);
-
- status = mFlinger->setDisplayBrightness(displayToken, brightness);
- return binder::Status::fromStatusT(status);
+ if (status == OK) {
+ status = mFlinger->setDisplayBrightness(displayToken, brightness);
+ }
+ return binderStatusFromStatusT(status);
}
binder::Status SurfaceComposerAIDL::addHdrLayerInfoListener(
const sp<IBinder>& displayToken, const sp<gui::IHdrLayerInfoListener>& listener) {
status_t status = checkControlDisplayBrightnessPermission();
- if (status != OK) return binder::Status::fromStatusT(status);
-
- status = mFlinger->addHdrLayerInfoListener(displayToken, listener);
- return binder::Status::fromStatusT(status);
+ if (status == OK) {
+ status = mFlinger->addHdrLayerInfoListener(displayToken, listener);
+ }
+ return binderStatusFromStatusT(status);
}
binder::Status SurfaceComposerAIDL::removeHdrLayerInfoListener(
const sp<IBinder>& displayToken, const sp<gui::IHdrLayerInfoListener>& listener) {
status_t status = checkControlDisplayBrightnessPermission();
- if (status != OK) return binder::Status::fromStatusT(status);
-
- status = mFlinger->removeHdrLayerInfoListener(displayToken, listener);
- return binder::Status::fromStatusT(status);
+ if (status == OK) {
+ status = mFlinger->removeHdrLayerInfoListener(displayToken, listener);
+ }
+ return binderStatusFromStatusT(status);
}
binder::Status SurfaceComposerAIDL::notifyPowerBoost(int boostId) {
status_t status = checkAccessPermission();
- if (status != OK) return binder::Status::fromStatusT(status);
+ if (status == OK) {
+ status = mFlinger->notifyPowerBoost(boostId);
+ }
+ return binderStatusFromStatusT(status);
+}
- status = mFlinger->notifyPowerBoost(boostId);
- return binder::Status::fromStatusT(status);
+binder::Status SurfaceComposerAIDL::setGlobalShadowSettings(const gui::Color& ambientColor,
+ const gui::Color& spotColor,
+ float lightPosY, float lightPosZ,
+ float lightRadius) {
+ status_t status = checkAccessPermission();
+ if (status != OK) {
+ return binderStatusFromStatusT(status);
+ }
+
+ half4 ambientColorHalf = {ambientColor.r, ambientColor.g, ambientColor.b, ambientColor.a};
+ half4 spotColorHalf = {spotColor.r, spotColor.g, spotColor.b, spotColor.a};
+ status = mFlinger->setGlobalShadowSettings(ambientColorHalf, spotColorHalf, lightPosY,
+ lightPosZ, lightRadius);
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::getDisplayDecorationSupport(
+ const sp<IBinder>& displayToken, std::optional<gui::DisplayDecorationSupport>* outSupport) {
+ std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport> support;
+ status_t status = mFlinger->getDisplayDecorationSupport(displayToken, &support);
+ if (status != NO_ERROR) {
+ ALOGE("getDisplayDecorationSupport failed with error %d", status);
+ return binderStatusFromStatusT(status);
+ }
+
+ if (!support || !support.has_value()) {
+ outSupport->reset();
+ } else {
+ outSupport->emplace();
+ outSupport->value().format = static_cast<int32_t>(support->format);
+ outSupport->value().alphaInterpretation =
+ static_cast<int32_t>(support->alphaInterpretation);
+ }
+
+ return binder::Status::ok();
+}
+
+binder::Status SurfaceComposerAIDL::setOverrideFrameRate(int32_t uid, float frameRate) {
+ status_t status;
+ const int c_uid = IPCThreadState::self()->getCallingUid();
+ if (c_uid == AID_ROOT || c_uid == AID_SYSTEM) {
+ status = mFlinger->setOverrideFrameRate(uid, frameRate);
+ } else {
+ ALOGE("setOverrideFrameRate() permission denied for uid: %d", c_uid);
+ status = PERMISSION_DENIED;
+ }
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::addTransactionTraceListener(
+ const sp<gui::ITransactionTraceListener>& listener) {
+ status_t status;
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int uid = ipc->getCallingUid();
+ if (uid == AID_ROOT || uid == AID_GRAPHICS || uid == AID_SYSTEM || uid == AID_SHELL) {
+ status = mFlinger->addTransactionTraceListener(listener);
+ } else {
+ status = PERMISSION_DENIED;
+ }
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::getGpuContextPriority(int32_t* outPriority) {
+ *outPriority = mFlinger->getGpuContextPriority();
+ return binder::Status::ok();
+}
+
+binder::Status SurfaceComposerAIDL::getMaxAcquiredBufferCount(int32_t* buffers) {
+ status_t status = mFlinger->getMaxAcquiredBufferCount(buffers);
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::addWindowInfosListener(
+ const sp<gui::IWindowInfosListener>& windowInfosListener) {
+ status_t status;
+ const int uid = IPCThreadState::self()->getCallingUid();
+ if (uid == AID_SYSTEM || uid == AID_GRAPHICS) {
+ status = mFlinger->addWindowInfosListener(windowInfosListener);
+ } else {
+ status = PERMISSION_DENIED;
+ }
+ return binderStatusFromStatusT(status);
+}
+
+binder::Status SurfaceComposerAIDL::removeWindowInfosListener(
+ const sp<gui::IWindowInfosListener>& windowInfosListener) {
+ status_t status;
+ const int uid = IPCThreadState::self()->getCallingUid();
+ if (uid == AID_SYSTEM || uid == AID_GRAPHICS) {
+ status = mFlinger->removeWindowInfosListener(windowInfosListener);
+ } else {
+ status = PERMISSION_DENIED;
+ }
+ return binderStatusFromStatusT(status);
}
status_t SurfaceComposerAIDL::checkAccessPermission(bool usePermissionCache) {
@@ -7578,6 +8022,17 @@
return OK;
}
+status_t SurfaceComposerAIDL::checkReadFrameBufferPermission() {
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int pid = ipc->getCallingPid();
+ const int uid = ipc->getCallingUid();
+ if ((uid != AID_GRAPHICS) && !PermissionCache::checkPermission(sReadFramebuffer, pid, uid)) {
+ ALOGE("Permission Denial: can't read framebuffer pid=%d, uid=%d", pid, uid);
+ return PERMISSION_DENIED;
+ }
+ return OK;
+}
+
} // namespace android
#if defined(__gl_h_)
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 83134a2..7d23c3c 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -25,15 +25,17 @@
#include <android/gui/BnSurfaceComposer.h>
#include <android/gui/DisplayStatInfo.h>
#include <android/gui/DisplayState.h>
+#include <android/gui/ISurfaceComposerClient.h>
#include <cutils/atomic.h>
#include <cutils/compiler.h>
#include <ftl/future.h>
#include <ftl/small_map.h>
#include <gui/BufferQueue.h>
+#include <gui/CompositorTiming.h>
#include <gui/FrameTimestamps.h>
#include <gui/ISurfaceComposer.h>
-#include <gui/ISurfaceComposerClient.h>
#include <gui/ITransactionCompletedListener.h>
+#include <gui/LayerDebugInfo.h>
#include <gui/LayerState.h>
#include <layerproto/LayerProtoHeader.h>
#include <math/mat4.h>
@@ -167,10 +169,6 @@
using DisplayColorSetting = compositionengine::OutputColorSetting;
struct SurfaceFlingerBE {
- // protected by mCompositorTimingLock;
- mutable std::mutex mCompositorTimingLock;
- CompositorTiming mCompositorTiming;
-
// Only accessed from the main thread.
struct CompositePresentTime {
nsecs_t composite = -1;
@@ -309,9 +307,6 @@
renderengine::RenderEngine& getRenderEngine() const;
- bool authenticateSurfaceTextureLocked(
- const sp<IGraphicBufferProducer>& bufferProducer) const;
-
void onLayerFirstRef(Layer*);
void onLayerDestroyed(Layer*);
void onLayerUpdate();
@@ -335,7 +330,6 @@
// If set, disables reusing client composition buffers. This can be set by
// debug.sf.disable_client_composition_cache
bool mDisableClientCompositionCache = false;
- void windowInfosReported();
// Disables expensive rendering for all displays
// This is scheduled on the main thread
@@ -375,13 +369,11 @@
private:
friend class BufferLayer;
- friend class BufferQueueLayer;
friend class BufferStateLayer;
friend class Client;
friend class FpsReporter;
friend class TunnelModeEnabledReporter;
friend class Layer;
- friend class MonitoredProducer;
friend class RefreshRateOverlay;
friend class RegionSamplingThread;
friend class LayerRenderArea;
@@ -519,10 +511,11 @@
}
}
- static const int MAX_TRACING_MEMORY = 100 * 1024 * 1024; // 100MB
// Maximum allowed number of display frames that can be set through backdoor
static const int MAX_ALLOWED_DISPLAY_FRAMES = 2048;
+ static const size_t MAX_LAYERS = 4096;
+
// Implements IBinder.
status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override;
status_t dump(int fd, const Vector<String16>& args) override { return priorityDump(fd, args); }
@@ -530,7 +523,6 @@
EXCLUDES(mStateLock);
// Implements ISurfaceComposer
- sp<ISurfaceComposerClient> createConnection() override;
sp<IBinder> createDisplay(const String8& displayName, bool secure);
void destroyDisplay(const sp<IBinder>& displayToken);
std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const EXCLUDES(mStateLock) {
@@ -549,13 +541,12 @@
const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
const std::vector<ListenerCallbacks>& listenerCallbacks,
uint64_t transactionId) override;
- void bootFinished() override;
- bool authenticateSurfaceTexture(
- const sp<IGraphicBufferProducer>& bufferProducer) const override;
- status_t getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported) const override;
+ void bootFinished();
+ virtual status_t getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported) const;
sp<IDisplayEventConnection> createDisplayEventConnection(
- ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp,
- ISurfaceComposer::EventRegistrationFlags eventRegistration = {}) override;
+ gui::ISurfaceComposer::VsyncSource vsyncSource =
+ gui::ISurfaceComposer::VsyncSource::eVsyncSourceApp,
+ EventRegistrationFlags eventRegistration = {});
status_t captureDisplay(const DisplayCaptureArgs&, const sp<IScreenCaptureListener>&);
status_t captureDisplay(DisplayId, const sp<IScreenCaptureListener>&);
@@ -565,62 +556,58 @@
status_t getDisplayState(const sp<IBinder>& displayToken, ui::DisplayState*)
EXCLUDES(mStateLock);
status_t getStaticDisplayInfo(const sp<IBinder>& displayToken, ui::StaticDisplayInfo*)
- EXCLUDES(mStateLock) override;
+ EXCLUDES(mStateLock);
status_t getDynamicDisplayInfo(const sp<IBinder>& displayToken, ui::DynamicDisplayInfo*)
- EXCLUDES(mStateLock) override;
- status_t getDisplayNativePrimaries(const sp<IBinder>& displayToken,
- ui::DisplayPrimaries&) override;
- status_t setActiveColorMode(const sp<IBinder>& displayToken, ui::ColorMode colorMode) override;
+ EXCLUDES(mStateLock);
+ status_t getDisplayNativePrimaries(const sp<IBinder>& displayToken, ui::DisplayPrimaries&);
+ status_t setActiveColorMode(const sp<IBinder>& displayToken, ui::ColorMode colorMode);
status_t getBootDisplayModeSupport(bool* outSupport) const;
- status_t setBootDisplayMode(const sp<IBinder>& displayToken, ui::DisplayModeId id) override;
+ status_t setBootDisplayMode(const sp<IBinder>& displayToken, ui::DisplayModeId id);
status_t clearBootDisplayMode(const sp<IBinder>& displayToken);
void setAutoLowLatencyMode(const sp<IBinder>& displayToken, bool on);
void setGameContentType(const sp<IBinder>& displayToken, bool on);
void setPowerMode(const sp<IBinder>& displayToken, int mode);
- status_t clearAnimationFrameStats() override;
- status_t getAnimationFrameStats(FrameStats* outStats) const override;
+ status_t clearAnimationFrameStats();
+ status_t getAnimationFrameStats(FrameStats* outStats) const;
status_t overrideHdrTypes(const sp<IBinder>& displayToken,
- const std::vector<ui::Hdr>& hdrTypes) override;
- status_t onPullAtom(const int32_t atomId, std::string* pulledData, bool* success) override;
- status_t enableVSyncInjections(bool enable) override;
- status_t injectVSync(nsecs_t when) override;
- status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) override;
- status_t getColorManagement(bool* outGetColorManagement) const override;
+ const std::vector<ui::Hdr>& hdrTypes);
+ status_t onPullAtom(const int32_t atomId, std::string* pulledData, bool* success);
+ status_t enableVSyncInjections(bool enable);
+ status_t injectVSync(nsecs_t when);
+ status_t getLayerDebugInfo(std::vector<gui::LayerDebugInfo>* outLayers);
+ status_t getColorManagement(bool* outGetColorManagement) const;
status_t getCompositionPreference(ui::Dataspace* outDataspace, ui::PixelFormat* outPixelFormat,
ui::Dataspace* outWideColorGamutDataspace,
- ui::PixelFormat* outWideColorGamutPixelFormat) const override;
+ ui::PixelFormat* outWideColorGamutPixelFormat) const;
status_t getDisplayedContentSamplingAttributes(const sp<IBinder>& displayToken,
ui::PixelFormat* outFormat,
ui::Dataspace* outDataspace,
- uint8_t* outComponentMask) const override;
+ uint8_t* outComponentMask) const;
status_t setDisplayContentSamplingEnabled(const sp<IBinder>& displayToken, bool enable,
- uint8_t componentMask, uint64_t maxFrames) override;
+ uint8_t componentMask, uint64_t maxFrames);
status_t getDisplayedContentSample(const sp<IBinder>& displayToken, uint64_t maxFrames,
- uint64_t timestamp,
- DisplayedFrameStats* outStats) const override;
- status_t getProtectedContentSupport(bool* outSupported) const override;
+ uint64_t timestamp, DisplayedFrameStats* outStats) const;
+ status_t getProtectedContentSupport(bool* outSupported) const;
status_t isWideColorDisplay(const sp<IBinder>& displayToken, bool* outIsWideColorDisplay) const;
status_t addRegionSamplingListener(const Rect& samplingArea, const sp<IBinder>& stopLayerHandle,
- const sp<IRegionSamplingListener>& listener) override;
- status_t removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener) override;
- status_t addFpsListener(int32_t taskId, const sp<gui::IFpsListener>& listener) override;
- status_t removeFpsListener(const sp<gui::IFpsListener>& listener) override;
- status_t addTunnelModeEnabledListener(
- const sp<gui::ITunnelModeEnabledListener>& listener) override;
- status_t removeTunnelModeEnabledListener(
- const sp<gui::ITunnelModeEnabledListener>& listener) override;
+ const sp<IRegionSamplingListener>& listener);
+ status_t removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener);
+ status_t addFpsListener(int32_t taskId, const sp<gui::IFpsListener>& listener);
+ status_t removeFpsListener(const sp<gui::IFpsListener>& listener);
+ status_t addTunnelModeEnabledListener(const sp<gui::ITunnelModeEnabledListener>& listener);
+ status_t removeTunnelModeEnabledListener(const sp<gui::ITunnelModeEnabledListener>& listener);
status_t setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken,
ui::DisplayModeId displayModeId, bool allowGroupSwitching,
float primaryRefreshRateMin, float primaryRefreshRateMax,
float appRequestRefreshRateMin,
- float appRequestRefreshRateMax) override;
+ float appRequestRefreshRateMax);
status_t getDesiredDisplayModeSpecs(const sp<IBinder>& displayToken,
ui::DisplayModeId* outDefaultMode,
bool* outAllowGroupSwitching,
float* outPrimaryRefreshRateMin,
float* outPrimaryRefreshRateMax,
float* outAppRequestRefreshRateMin,
- float* outAppRequestRefreshRateMax) override;
+ float* outAppRequestRefreshRateMax);
status_t getDisplayBrightnessSupport(const sp<IBinder>& displayToken, bool* outSupport) const;
status_t setDisplayBrightness(const sp<IBinder>& displayToken,
const gui::DisplayBrightness& brightness);
@@ -630,30 +617,28 @@
const sp<gui::IHdrLayerInfoListener>& listener);
status_t notifyPowerBoost(int32_t boostId);
status_t setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor,
- float lightPosY, float lightPosZ, float lightRadius) override;
+ float lightPosY, float lightPosZ, float lightRadius);
status_t getDisplayDecorationSupport(
const sp<IBinder>& displayToken,
std::optional<aidl::android::hardware::graphics::common::DisplayDecorationSupport>*
- outSupport) const override;
+ outSupport) const;
status_t setFrameRate(const sp<IGraphicBufferProducer>& surface, float frameRate,
- int8_t compatibility, int8_t changeFrameRateStrategy) override;
+ int8_t compatibility, int8_t changeFrameRateStrategy);
status_t setFrameTimelineInfo(const sp<IGraphicBufferProducer>& surface,
- const FrameTimelineInfo& frameTimelineInfo) override;
+ const gui::FrameTimelineInfo& frameTimelineInfo);
- status_t setOverrideFrameRate(uid_t uid, float frameRate) override;
+ status_t setOverrideFrameRate(uid_t uid, float frameRate);
- status_t addTransactionTraceListener(
- const sp<gui::ITransactionTraceListener>& listener) override;
+ status_t addTransactionTraceListener(const sp<gui::ITransactionTraceListener>& listener);
- int getGPUContextPriority() override;
+ int getGpuContextPriority();
- status_t getMaxAcquiredBufferCount(int* buffers) const override;
+ status_t getMaxAcquiredBufferCount(int* buffers) const;
- status_t addWindowInfosListener(
- const sp<gui::IWindowInfosListener>& windowInfosListener) const override;
+ status_t addWindowInfosListener(const sp<gui::IWindowInfosListener>& windowInfosListener) const;
status_t removeWindowInfosListener(
- const sp<gui::IWindowInfosListener>& windowInfosListener) const override;
+ const sp<gui::IWindowInfosListener>& windowInfosListener) const;
// Implements IBinder::DeathRecipient.
void binderDied(const wp<IBinder>& who) override;
@@ -832,10 +817,6 @@
const sp<Layer>& parentLayer = nullptr,
uint32_t* outTransformHint = nullptr);
- status_t createBufferQueueLayer(LayerCreationArgs& args, PixelFormat& format,
- sp<IBinder>* outHandle, sp<IGraphicBufferProducer>* outGbp,
- sp<Layer>* outLayer);
-
status_t createBufferStateLayer(LayerCreationArgs& args, sp<IBinder>* outHandle,
sp<Layer>* outLayer);
@@ -973,11 +954,9 @@
* Compositing
*/
void postComposition();
- void getCompositorTiming(CompositorTiming* compositorTiming);
- void updateCompositorTiming(const DisplayStatInfo& stats, nsecs_t compositeTime,
- std::shared_ptr<FenceTime>& presentFenceTime);
- void setCompositorTimingSnapped(const DisplayStatInfo& stats,
- nsecs_t compositeToPresentLatency);
+
+ // Returns the composite-to-present latency of the latest presented frame.
+ nsecs_t trackPresentLatency(nsecs_t compositeTime, std::shared_ptr<FenceTime> presentFenceTime);
void postFrame() REQUIRES(kMainThreadContext);
@@ -1012,31 +991,17 @@
getHwComposer().setVsyncEnabled(id, enabled);
}
- struct FenceWithFenceTime {
- sp<Fence> fence = Fence::NO_FENCE;
- std::shared_ptr<FenceTime> fenceTime = FenceTime::NO_FENCE;
- };
+ using FenceTimePtr = std::shared_ptr<FenceTime>;
- // Gets the fence for the previous frame.
- // Must be called on the main thread.
- FenceWithFenceTime previousFrameFence();
+ const FenceTimePtr& getPreviousPresentFence(nsecs_t frameTime, Period)
+ REQUIRES(kMainThreadContext);
- // Whether the previous frame has not yet been presented to the display.
- // If graceTimeMs is positive, this method waits for at most the provided
- // grace period before reporting if the frame missed.
- // Must be called on the main thread.
- bool previousFramePending(int graceTimeMs = 0);
-
- // Returns the previous time that the frame was presented. If the frame has
- // not been presented yet, then returns Fence::SIGNAL_TIME_PENDING. If there
- // is no pending frame, then returns Fence::SIGNAL_TIME_INVALID.
- // Must be called on the main thread.
- nsecs_t previousFramePresentTime();
+ // Blocks the thread waiting for up to graceTimeMs in case the fence is about to signal.
+ static bool isFencePending(const FenceTimePtr&, int graceTimeMs);
// Calculates the expected present time for this frame. For negative offsets, performs a
// correction using the predicted vsync for the next frame instead.
-
- nsecs_t calculateExpectedPresentTime(DisplayStatInfo) const;
+ TimePoint calculateExpectedPresentTime(nsecs_t frameTime) const;
/*
* Display identification
@@ -1178,7 +1143,7 @@
float mGlobalSaturationFactor = 1.0f;
mat4 mClientColorMatrix;
- size_t mMaxGraphicBufferProducerListSize = ISurfaceComposer::MAX_LAYERS;
+ size_t mMaxGraphicBufferProducerListSize = MAX_LAYERS;
// If there are more GraphicBufferProducers tracked by SurfaceFlinger than
// this threshold, then begin logging.
size_t mGraphicBufferProducerListSizeLogThreshold =
@@ -1212,7 +1177,7 @@
// Set during transaction application stage to track if the input info or children
// for a layer has changed.
// TODO: Also move visibleRegions over to a boolean system.
- bool mInputInfoChanged = false;
+ bool mUpdateInputInfo = false;
bool mSomeChildrenChanged;
bool mSomeDataspaceChanged = false;
bool mForceTransactionDisplayChange = false;
@@ -1224,7 +1189,7 @@
std::unordered_set<sp<Layer>, SpHash<Layer>> mLayersWithQueuedFrames;
// Tracks layers that need to update a display's dirty region.
std::vector<sp<Layer>> mLayersPendingRefresh;
- std::array<FenceWithFenceTime, 2> mPreviousPresentFences;
+
// True if in the previous frame at least one layer was composed via the GPU.
bool mHadClientComposition = false;
// True if in the previous frame at least one layer was composed via HW Composer.
@@ -1275,6 +1240,8 @@
const std::unique_ptr<FrameTracer> mFrameTracer;
const std::unique_ptr<frametimeline::FrameTimeline> mFrameTimeline;
+ int64_t mLastCommittedVsyncId = -1;
+
// If blurs should be enabled on this device.
bool mSupportsBlur = false;
// If blurs are considered expensive and should require high GPU frequency.
@@ -1359,6 +1326,12 @@
std::unique_ptr<scheduler::RefreshRateStats> mRefreshRateStats;
+ struct FenceWithFenceTime {
+ sp<Fence> fence = Fence::NO_FENCE;
+ FenceTimePtr fenceTime = FenceTime::NO_FENCE;
+ };
+ std::array<FenceWithFenceTime, 2> mPreviousPresentFences;
+
std::atomic<nsecs_t> mExpectedPresentTime = 0;
nsecs_t mScheduledPresentTime = 0;
hal::Vsync mHWCVsyncPendingState = hal::Vsync::DISABLE;
@@ -1414,8 +1387,9 @@
// A temporay pool that store the created layers and will be added to current state in main
// thread.
std::vector<LayerCreatedState> mCreatedLayers GUARDED_BY(mCreatedLayersLock);
- bool commitCreatedLayers();
- void handleLayerCreatedLocked(const LayerCreatedState& state) REQUIRES(mStateLock);
+ bool commitCreatedLayers(int64_t vsyncId);
+ void handleLayerCreatedLocked(const LayerCreatedState& state, int64_t vsyncId)
+ REQUIRES(mStateLock);
std::atomic<ui::Transform::RotationFlags> mActiveDisplayTransformHint;
@@ -1449,8 +1423,13 @@
class SurfaceComposerAIDL : public gui::BnSurfaceComposer {
public:
- SurfaceComposerAIDL(sp<SurfaceFlinger> sf) { mFlinger = sf; }
+ SurfaceComposerAIDL(sp<SurfaceFlinger> sf) : mFlinger(std::move(sf)) {}
+ binder::Status bootFinished() override;
+ binder::Status createDisplayEventConnection(
+ VsyncSource vsyncSource, EventRegistration eventRegistration,
+ sp<gui::IDisplayEventConnection>* outConnection) override;
+ binder::Status createConnection(sp<gui::ISurfaceComposerClient>* outClient) override;
binder::Status createDisplay(const std::string& displayName, bool secure,
sp<IBinder>* outDisplay) override;
binder::Status destroyDisplay(const sp<IBinder>& display) override;
@@ -1458,10 +1437,19 @@
binder::Status getPrimaryPhysicalDisplayId(int64_t* outDisplayId) override;
binder::Status getPhysicalDisplayToken(int64_t displayId, sp<IBinder>* outDisplay) override;
binder::Status setPowerMode(const sp<IBinder>& display, int mode) override;
+ binder::Status getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported) override;
binder::Status getDisplayStats(const sp<IBinder>& display,
gui::DisplayStatInfo* outStatInfo) override;
binder::Status getDisplayState(const sp<IBinder>& display,
gui::DisplayState* outState) override;
+ binder::Status getStaticDisplayInfo(const sp<IBinder>& display,
+ gui::StaticDisplayInfo* outInfo) override;
+ binder::Status getDynamicDisplayInfo(const sp<IBinder>& display,
+ gui::DynamicDisplayInfo* outInfo) override;
+ binder::Status getDisplayNativePrimaries(const sp<IBinder>& display,
+ gui::DisplayPrimaries* outPrimaries) override;
+ binder::Status setActiveColorMode(const sp<IBinder>& display, int colorMode) override;
+ binder::Status setBootDisplayMode(const sp<IBinder>& display, int displayModeId) override;
binder::Status clearBootDisplayMode(const sp<IBinder>& display) override;
binder::Status getBootDisplayModeSupport(bool* outMode) override;
binder::Status setAutoLowLatencyMode(const sp<IBinder>& display, bool on) override;
@@ -1471,8 +1459,45 @@
binder::Status captureDisplayById(int64_t, const sp<IScreenCaptureListener>&) override;
binder::Status captureLayers(const LayerCaptureArgs&,
const sp<IScreenCaptureListener>&) override;
+ binder::Status clearAnimationFrameStats() override;
+ binder::Status getAnimationFrameStats(gui::FrameStats* outStats) override;
+ binder::Status overrideHdrTypes(const sp<IBinder>& display,
+ const std::vector<int32_t>& hdrTypes) override;
+ binder::Status onPullAtom(int32_t atomId, gui::PullAtomData* outPullData) override;
+ binder::Status enableVSyncInjections(bool enable) override;
+ binder::Status injectVSync(int64_t when) override;
+ binder::Status getLayerDebugInfo(std::vector<gui::LayerDebugInfo>* outLayers) override;
+ binder::Status getColorManagement(bool* outGetColorManagement) override;
+ binder::Status getCompositionPreference(gui::CompositionPreference* outPref) override;
+ binder::Status getDisplayedContentSamplingAttributes(
+ const sp<IBinder>& display, gui::ContentSamplingAttributes* outAttrs) override;
+ binder::Status setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
+ int8_t componentMask,
+ int64_t maxFrames) override;
+ binder::Status getDisplayedContentSample(const sp<IBinder>& display, int64_t maxFrames,
+ int64_t timestamp,
+ gui::DisplayedFrameStats* outStats) override;
+ binder::Status getProtectedContentSupport(bool* outSupporte) override;
binder::Status isWideColorDisplay(const sp<IBinder>& token,
bool* outIsWideColorDisplay) override;
+ binder::Status addRegionSamplingListener(
+ const gui::ARect& samplingArea, const sp<IBinder>& stopLayerHandle,
+ const sp<gui::IRegionSamplingListener>& listener) override;
+ binder::Status removeRegionSamplingListener(
+ const sp<gui::IRegionSamplingListener>& listener) override;
+ binder::Status addFpsListener(int32_t taskId, const sp<gui::IFpsListener>& listener) override;
+ binder::Status removeFpsListener(const sp<gui::IFpsListener>& listener) override;
+ binder::Status addTunnelModeEnabledListener(
+ const sp<gui::ITunnelModeEnabledListener>& listener) override;
+ binder::Status removeTunnelModeEnabledListener(
+ const sp<gui::ITunnelModeEnabledListener>& listener) override;
+ binder::Status setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, int32_t defaultMode,
+ bool allowGroupSwitching, float primaryRefreshRateMin,
+ float primaryRefreshRateMax,
+ float appRequestRefreshRateMin,
+ float appRequestRefreshRateMax) override;
+ binder::Status getDesiredDisplayModeSpecs(const sp<IBinder>& displayToken,
+ gui::DisplayModeSpecs* outSpecs) override;
binder::Status getDisplayBrightnessSupport(const sp<IBinder>& displayToken,
bool* outSupport) override;
binder::Status setDisplayBrightness(const sp<IBinder>& displayToken,
@@ -1483,11 +1508,27 @@
const sp<IBinder>& displayToken,
const sp<gui::IHdrLayerInfoListener>& listener) override;
binder::Status notifyPowerBoost(int boostId) override;
+ binder::Status setGlobalShadowSettings(const gui::Color& ambientColor,
+ const gui::Color& spotColor, float lightPosY,
+ float lightPosZ, float lightRadius) override;
+ binder::Status getDisplayDecorationSupport(
+ const sp<IBinder>& displayToken,
+ std::optional<gui::DisplayDecorationSupport>* outSupport) override;
+ binder::Status setOverrideFrameRate(int32_t uid, float frameRate) override;
+ binder::Status addTransactionTraceListener(
+ const sp<gui::ITransactionTraceListener>& listener) override;
+ binder::Status getGpuContextPriority(int32_t* outPriority) override;
+ binder::Status getMaxAcquiredBufferCount(int32_t* buffers) override;
+ binder::Status addWindowInfosListener(
+ const sp<gui::IWindowInfosListener>& windowInfosListener) override;
+ binder::Status removeWindowInfosListener(
+ const sp<gui::IWindowInfosListener>& windowInfosListener) override;
private:
static const constexpr bool kUsePermissionCache = true;
status_t checkAccessPermission(bool usePermissionCache = kUsePermissionCache);
status_t checkControlDisplayBrightnessPermission();
+ status_t checkReadFrameBufferPermission();
private:
sp<SurfaceFlinger> mFlinger;
diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
index b81b445..2399a39 100644
--- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
+++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp
@@ -22,15 +22,12 @@
#include <cutils/properties.h>
#include <ui/GraphicBuffer.h>
-#include "BufferLayerConsumer.h"
-#include "BufferQueueLayer.h"
#include "BufferStateLayer.h"
#include "ContainerLayer.h"
#include "DisplayDevice.h"
#include "EffectLayer.h"
#include "FrameTracer/FrameTracer.h"
#include "Layer.h"
-#include "MonitoredProducer.h"
#include "NativeWindowSurface.h"
#include "StartPropertySetThread.h"
#include "SurfaceFlingerDefaultFactory.h"
@@ -84,18 +81,6 @@
BufferQueue::createBufferQueue(outProducer, outConsumer, consumerIsSurfaceFlinger);
}
-sp<IGraphicBufferProducer> DefaultFactory::createMonitoredProducer(
- const sp<IGraphicBufferProducer>& producer, const sp<SurfaceFlinger>& flinger,
- const wp<Layer>& layer) {
- return new MonitoredProducer(producer, flinger, layer);
-}
-
-sp<BufferLayerConsumer> DefaultFactory::createBufferLayerConsumer(
- const sp<IGraphicBufferConsumer>& consumer, renderengine::RenderEngine& renderEngine,
- uint32_t textureName, Layer* layer) {
- return new BufferLayerConsumer(consumer, renderEngine, textureName, layer);
-}
-
std::unique_ptr<surfaceflinger::NativeWindowSurface> DefaultFactory::createNativeWindowSurface(
const sp<IGraphicBufferProducer>& producer) {
return surfaceflinger::impl::createNativeWindowSurface(producer);
@@ -109,10 +94,6 @@
return new ContainerLayer(args);
}
-sp<BufferQueueLayer> DefaultFactory::createBufferQueueLayer(const LayerCreationArgs& args) {
- return new BufferQueueLayer(args);
-}
-
sp<BufferStateLayer> DefaultFactory::createBufferStateLayer(const LayerCreationArgs& args) {
return new BufferStateLayer(args);
}
diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.h b/services/surfaceflinger/SurfaceFlingerDefaultFactory.h
index 501629d..4000e09 100644
--- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.h
+++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.h
@@ -38,16 +38,9 @@
void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer,
bool consumerIsSurfaceFlinger) override;
- sp<IGraphicBufferProducer> createMonitoredProducer(const sp<IGraphicBufferProducer>&,
- const sp<SurfaceFlinger>&,
- const wp<Layer>&) override;
- sp<BufferLayerConsumer> createBufferLayerConsumer(const sp<IGraphicBufferConsumer>&,
- renderengine::RenderEngine&, uint32_t tex,
- Layer*) override;
std::unique_ptr<surfaceflinger::NativeWindowSurface> createNativeWindowSurface(
const sp<IGraphicBufferProducer>&) override;
std::unique_ptr<compositionengine::CompositionEngine> createCompositionEngine() override;
- sp<BufferQueueLayer> createBufferQueueLayer(const LayerCreationArgs& args) override;
sp<BufferStateLayer> createBufferStateLayer(const LayerCreationArgs& args) override;
sp<EffectLayer> createEffectLayer(const LayerCreationArgs& args) override;
sp<ContainerLayer> createContainerLayer(const LayerCreationArgs& args) override;
diff --git a/services/surfaceflinger/SurfaceFlingerFactory.h b/services/surfaceflinger/SurfaceFlingerFactory.h
index 6153e8e..77a75c4 100644
--- a/services/surfaceflinger/SurfaceFlingerFactory.h
+++ b/services/surfaceflinger/SurfaceFlingerFactory.h
@@ -30,7 +30,6 @@
typedef int32_t PixelFormat;
-class BufferQueueLayer;
class BufferLayerConsumer;
class BufferStateLayer;
class ContainerLayer;
@@ -86,19 +85,12 @@
virtual void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
sp<IGraphicBufferConsumer>* outConsumer,
bool consumerIsSurfaceFlinger) = 0;
- virtual sp<IGraphicBufferProducer> createMonitoredProducer(const sp<IGraphicBufferProducer>&,
- const sp<SurfaceFlinger>&,
- const wp<Layer>&) = 0;
- virtual sp<BufferLayerConsumer> createBufferLayerConsumer(const sp<IGraphicBufferConsumer>&,
- renderengine::RenderEngine&,
- uint32_t tex, Layer*) = 0;
virtual std::unique_ptr<surfaceflinger::NativeWindowSurface> createNativeWindowSurface(
const sp<IGraphicBufferProducer>&) = 0;
virtual std::unique_ptr<compositionengine::CompositionEngine> createCompositionEngine() = 0;
- virtual sp<BufferQueueLayer> createBufferQueueLayer(const LayerCreationArgs& args) = 0;
virtual sp<BufferStateLayer> createBufferStateLayer(const LayerCreationArgs& args) = 0;
virtual sp<EffectLayer> createEffectLayer(const LayerCreationArgs& args) = 0;
virtual sp<ContainerLayer> createContainerLayer(const LayerCreationArgs& args) = 0;
diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h
index 7a159b8..61d7c22 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.h
+++ b/services/surfaceflinger/TimeStats/TimeStats.h
@@ -34,6 +34,8 @@
#include <scheduler/Fps.h>
+using android::gui::GameMode;
+using android::gui::LayerMetadata;
using namespace android::surfaceflinger;
namespace android {
diff --git a/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h
index 237ae8d..60aa810 100644
--- a/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h
+++ b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h
@@ -24,6 +24,9 @@
#include <unordered_map>
#include <vector>
+using android::gui::GameMode;
+using android::gui::LayerMetadata;
+
namespace android {
namespace surfaceflinger {
diff --git a/services/surfaceflinger/Tracing/LayerTracing.cpp b/services/surfaceflinger/Tracing/LayerTracing.cpp
index 49554c7..afa3e50 100644
--- a/services/surfaceflinger/Tracing/LayerTracing.cpp
+++ b/services/surfaceflinger/Tracing/LayerTracing.cpp
@@ -98,7 +98,7 @@
mBuffer->dump(result);
}
-void LayerTracing::notify(bool visibleRegionDirty, int64_t time) {
+void LayerTracing::notify(bool visibleRegionDirty, int64_t time, int64_t vsyncId) {
std::scoped_lock lock(mTraceLock);
if (!mEnabled) {
return;
@@ -129,6 +129,7 @@
entry.set_excludes_composition_state(true);
}
mFlinger.dumpDisplayProto(entry);
+ entry.set_vsync_id(vsyncId);
mBuffer->emplace(std::move(entry));
}
diff --git a/services/surfaceflinger/Tracing/LayerTracing.h b/services/surfaceflinger/Tracing/LayerTracing.h
index 88a19ec..e73dac6 100644
--- a/services/surfaceflinger/Tracing/LayerTracing.h
+++ b/services/surfaceflinger/Tracing/LayerTracing.h
@@ -47,7 +47,7 @@
bool isEnabled() const;
status_t writeToFile();
LayersTraceFileProto createTraceFileProto() const;
- void notify(bool visibleRegionDirty, int64_t time);
+ void notify(bool visibleRegionDirty, int64_t time, int64_t vsyncId);
enum : uint32_t {
TRACE_INPUT = 1 << 1,
diff --git a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
index a73eccf..65918f6 100644
--- a/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
+++ b/services/surfaceflinger/Tracing/TransactionProtoParser.cpp
@@ -15,6 +15,7 @@
*/
#include <gui/SurfaceComposerClient.h>
+#include <ui/Fence.h>
#include <ui/Rect.h>
#include "LayerProtoHelper.h"
@@ -458,7 +459,7 @@
layer.parentSurfaceControlForChild =
new SurfaceControl(SurfaceComposerClient::getDefault(),
mMapper->getLayerHandle(static_cast<int32_t>(layerId)),
- nullptr, static_cast<int32_t>(layerId));
+ static_cast<int32_t>(layerId));
}
}
if (proto.what() & layer_state_t::eRelativeLayerChanged) {
@@ -469,7 +470,7 @@
layer.relativeLayerSurfaceControl =
new SurfaceControl(SurfaceComposerClient::getDefault(),
mMapper->getLayerHandle(static_cast<int32_t>(layerId)),
- nullptr, static_cast<int32_t>(layerId));
+ static_cast<int32_t>(layerId));
}
layer.z = proto.z();
}
@@ -497,8 +498,13 @@
inputInfo.replaceTouchableRegionWithCrop =
windowInfoProto.replace_touchable_region_with_crop();
int64_t layerId = windowInfoProto.crop_layer_id();
- inputInfo.touchableRegionCropHandle =
- mMapper->getLayerHandle(static_cast<int32_t>(layerId));
+ if (layerId != -1) {
+ inputInfo.touchableRegionCropHandle =
+ mMapper->getLayerHandle(static_cast<int32_t>(layerId));
+ } else {
+ inputInfo.touchableRegionCropHandle = nullptr;
+ }
+
layer.windowInfoHandle = sp<gui::WindowInfoHandle>::make(inputInfo);
}
if (proto.what() & layer_state_t::eBackgroundColorChanged) {
diff --git a/services/surfaceflinger/Tracing/TransactionTracing.cpp b/services/surfaceflinger/Tracing/TransactionTracing.cpp
index 6381758..af0594e 100644
--- a/services/surfaceflinger/Tracing/TransactionTracing.cpp
+++ b/services/surfaceflinger/Tracing/TransactionTracing.cpp
@@ -152,17 +152,33 @@
mTransactionQueue.push(state);
}
-void TransactionTracing::addCommittedTransactions(std::vector<TransactionState>& transactions,
- int64_t vsyncId) {
+TransactionTracing::CommittedTransactions&
+TransactionTracing::findOrCreateCommittedTransactionRecord(int64_t vsyncId) {
+ for (auto& pendingTransaction : mPendingTransactions) {
+ if (pendingTransaction.vsyncId == vsyncId) {
+ return pendingTransaction;
+ }
+ }
+
CommittedTransactions committedTransactions;
committedTransactions.vsyncId = vsyncId;
committedTransactions.timestamp = systemTime();
+ mPendingTransactions.emplace_back(committedTransactions);
+ return mPendingTransactions.back();
+}
+
+void TransactionTracing::onLayerAddedToDrawingState(int layerId, int64_t vsyncId) {
+ CommittedTransactions& committedTransactions = findOrCreateCommittedTransactionRecord(vsyncId);
+ committedTransactions.createdLayerIds.emplace_back(layerId);
+}
+
+void TransactionTracing::addCommittedTransactions(std::vector<TransactionState>& transactions,
+ int64_t vsyncId) {
+ CommittedTransactions& committedTransactions = findOrCreateCommittedTransactionRecord(vsyncId);
committedTransactions.transactionIds.reserve(transactions.size());
for (const auto& transaction : transactions) {
committedTransactions.transactionIds.emplace_back(transaction.id);
}
-
- mPendingTransactions.emplace_back(committedTransactions);
tryPushToTracingThread();
}
@@ -235,15 +251,24 @@
for (const CommittedTransactions& entry : committedTransactions) {
entryProto.set_elapsed_realtime_nanos(entry.timestamp);
entryProto.set_vsync_id(entry.vsyncId);
- entryProto.mutable_added_layers()->Reserve(static_cast<int32_t>(mCreatedLayers.size()));
- for (auto& newLayer : mCreatedLayers) {
- entryProto.mutable_added_layers()->Add(std::move(newLayer));
+ entryProto.mutable_added_layers()->Reserve(
+ static_cast<int32_t>(entry.createdLayerIds.size()));
+
+ for (const int32_t& id : entry.createdLayerIds) {
+ auto it = mCreatedLayers.find(id);
+ if (it != mCreatedLayers.end()) {
+ entryProto.mutable_added_layers()->Add(std::move(it->second));
+ mCreatedLayers.erase(it);
+ } else {
+ ALOGW("Could not created layer with id %d", id);
+ }
}
+
entryProto.mutable_removed_layers()->Reserve(static_cast<int32_t>(removedLayers.size()));
for (auto& removedLayer : removedLayers) {
entryProto.mutable_removed_layers()->Add(removedLayer);
+ mCreatedLayers.erase(removedLayer);
}
- mCreatedLayers.clear();
entryProto.mutable_transactions()->Reserve(
static_cast<int32_t>(entry.transactionIds.size()));
for (const uint64_t& id : entry.transactionIds) {
@@ -256,6 +281,14 @@
}
}
+ entryProto.mutable_removed_layer_handles()->Reserve(
+ static_cast<int32_t>(mRemovedLayerHandles.size()));
+ for (auto& [handle, layerId] : mRemovedLayerHandles) {
+ entryProto.mutable_removed_layer_handles()->Add(layerId);
+ mLayerHandles.erase(handle);
+ }
+ mRemovedLayerHandles.clear();
+
std::string serializedProto;
entryProto.SerializeToString(&serializedProto);
entryProto.Clear();
@@ -263,13 +296,6 @@
removedEntries.reserve(removedEntries.size() + entries.size());
removedEntries.insert(removedEntries.end(), std::make_move_iterator(entries.begin()),
std::make_move_iterator(entries.end()));
-
- entryProto.mutable_removed_layer_handles()->Reserve(
- static_cast<int32_t>(mRemovedLayerHandles.size()));
- for (auto& handle : mRemovedLayerHandles) {
- entryProto.mutable_removed_layer_handles()->Add(handle);
- }
- mRemovedLayerHandles.clear();
}
proto::TransactionTraceEntry removedEntryProto;
@@ -304,7 +330,7 @@
ALOGW("Duplicate handles found. %p", layerHandle);
}
mLayerHandles[layerHandle] = layerId;
- mCreatedLayers.push_back(mProtoParser.toProto(args));
+ mCreatedLayers[layerId] = mProtoParser.toProto(args);
}
void TransactionTracing::onMirrorLayerAdded(BBinder* layerHandle, int layerId,
@@ -315,7 +341,7 @@
ALOGW("Duplicate handles found. %p", layerHandle);
}
mLayerHandles[layerHandle] = layerId;
- mCreatedLayers.emplace_back(mProtoParser.toProto(args));
+ mCreatedLayers[layerId] = mProtoParser.toProto(args);
}
void TransactionTracing::onLayerRemoved(int32_t layerId) {
@@ -330,9 +356,7 @@
ALOGW("handle not found. %p", layerHandle);
return;
}
-
- mRemovedLayerHandles.push_back(it->second);
- mLayerHandles.erase(it);
+ mRemovedLayerHandles.emplace_back(layerHandle, it->second);
}
void TransactionTracing::tryPushToTracingThread() {
@@ -376,10 +400,15 @@
}
}
+ for (const int32_t removedLayerHandleId : removedEntry.removed_layer_handles()) {
+ mRemovedLayerHandlesAtStart.insert(removedLayerHandleId);
+ }
+
// Clean up stale starting states since the layer has been removed and the buffer does not
// contain any references to the layer.
for (const int32_t removedLayerId : removedEntry.removed_layers()) {
mStartingStates.erase(removedLayerId);
+ mRemovedLayerHandlesAtStart.erase(removedLayerId);
}
}
@@ -401,6 +430,12 @@
transactionProto.set_vsync_id(0);
transactionProto.set_post_time(mStartingTimestamp);
entryProto->mutable_transactions()->Add(std::move(transactionProto));
+
+ entryProto->mutable_removed_layer_handles()->Reserve(
+ static_cast<int32_t>(mRemovedLayerHandlesAtStart.size()));
+ for (const int32_t removedLayerHandleId : mRemovedLayerHandlesAtStart) {
+ entryProto->mutable_removed_layer_handles()->Add(removedLayerHandleId);
+ }
}
proto::TransactionTraceFile TransactionTracing::writeToProto() {
diff --git a/services/surfaceflinger/Tracing/TransactionTracing.h b/services/surfaceflinger/Tracing/TransactionTracing.h
index 4c291f9..ae01d3c 100644
--- a/services/surfaceflinger/Tracing/TransactionTracing.h
+++ b/services/surfaceflinger/Tracing/TransactionTracing.h
@@ -64,6 +64,7 @@
int mirrorFromId);
void onLayerRemoved(int layerId);
void onHandleRemoved(BBinder* layerHandle);
+ void onLayerAddedToDrawingState(int layerId, int64_t vsyncId);
void dump(std::string&) const;
static constexpr auto CONTINUOUS_TRACING_BUFFER_SIZE = 512 * 1024;
static constexpr auto ACTIVE_TRACING_BUFFER_SIZE = 100 * 1024 * 1024;
@@ -81,11 +82,13 @@
GUARDED_BY(mTraceLock);
LocklessStack<proto::TransactionState> mTransactionQueue;
nsecs_t mStartingTimestamp GUARDED_BY(mTraceLock);
- std::vector<proto::LayerCreationArgs> mCreatedLayers GUARDED_BY(mTraceLock);
+ std::unordered_map<int, proto::LayerCreationArgs> mCreatedLayers GUARDED_BY(mTraceLock);
std::unordered_map<BBinder* /* layerHandle */, int32_t /* layerId */> mLayerHandles
GUARDED_BY(mTraceLock);
- std::vector<int32_t /* layerId */> mRemovedLayerHandles GUARDED_BY(mTraceLock);
+ std::vector<std::pair<BBinder* /* layerHandle */, int32_t /* layerId */>> mRemovedLayerHandles
+ GUARDED_BY(mTraceLock);
std::map<int32_t /* layerId */, TracingLayerState> mStartingStates GUARDED_BY(mTraceLock);
+ std::set<int32_t /* layerId */> mRemovedLayerHandlesAtStart GUARDED_BY(mTraceLock);
TransactionProtoParser mProtoParser GUARDED_BY(mTraceLock);
// Parses the transaction to proto without holding any tracing locks so we can generate proto
// in the binder thread without any contention.
@@ -100,6 +103,7 @@
std::condition_variable mTransactionsAddedToBufferCv;
struct CommittedTransactions {
std::vector<uint64_t> transactionIds;
+ std::vector<int32_t> createdLayerIds;
int64_t vsyncId;
int64_t timestamp;
};
@@ -117,7 +121,7 @@
void tryPushToTracingThread() EXCLUDES(mMainThreadLock);
void addStartingStateToProtoLocked(proto::TransactionTraceFile& proto) REQUIRES(mTraceLock);
void updateStartingStateLocked(const proto::TransactionTraceEntry& entry) REQUIRES(mTraceLock);
-
+ CommittedTransactions& findOrCreateCommittedTransactionRecord(int64_t vsyncId);
// TEST
// Wait until all the committed transactions for the specified vsync id are added to the buffer.
void flush(int64_t vsyncId) EXCLUDES(mMainThreadLock);
diff --git a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
index cf44eff..c4b1b0f 100644
--- a/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
+++ b/services/surfaceflinger/Tracing/tools/LayerTraceGenerator.cpp
@@ -16,6 +16,7 @@
#undef LOG_TAG
#define LOG_TAG "LayerTraceGenerator"
+//#define LOG_NDEBUG 0
#include <TestableSurfaceFlinger.h>
#include <Tracing/TransactionProtoParser.h>
@@ -70,19 +71,6 @@
sp<IGraphicBufferConsumer>* /* outConsumer */,
bool /* consumerIsSurfaceFlinger */) override {}
- sp<IGraphicBufferProducer> createMonitoredProducer(
- const sp<IGraphicBufferProducer>& /* producer */,
- const sp<SurfaceFlinger>& /* flinger */, const wp<Layer>& /* layer */) override {
- return nullptr;
- }
-
- sp<BufferLayerConsumer> createBufferLayerConsumer(
- const sp<IGraphicBufferConsumer>& /* consumer */,
- renderengine::RenderEngine& /* renderEngine */, uint32_t /* textureName */,
- Layer* /* layer */) override {
- return nullptr;
- }
-
std::unique_ptr<surfaceflinger::NativeWindowSurface> createNativeWindowSurface(
const sp<IGraphicBufferProducer>& /* producer */) override {
return nullptr;
@@ -104,10 +92,6 @@
return new EffectLayer(args);
}
- sp<BufferQueueLayer> createBufferQueueLayer(const LayerCreationArgs&) override {
- return nullptr;
- }
-
std::unique_ptr<FrameTracer> createFrameTracer() override {
return std::make_unique<testing::NiceMock<mock::FrameTracer>>();
}
@@ -142,6 +126,14 @@
transact(1033, data, &reply, 0 /* flags */);
}
+ void setLayerTraceSize(int32_t sizeInKb) {
+ Parcel data;
+ Parcel reply;
+ data.writeInterfaceToken(String16("android.ui.ISurfaceComposer"));
+ data.writeInt32(sizeInKb);
+ transact(1029, data, &reply, 0 /* flags */);
+ }
+
void startLayerTracing(int64_t traceStartTime) {
Parcel data;
Parcel reply;
@@ -181,6 +173,7 @@
bool LayerTraceGenerator::generate(const proto::TransactionTraceFile& traceFile,
const char* outputLayersTracePath) {
if (traceFile.entry_size() == 0) {
+ ALOGD("Trace file is empty");
return false;
}
@@ -205,6 +198,7 @@
mFlinger.mutableMaxRenderTargetSize() = 16384;
flinger->setLayerTracingFlags(LayerTracing::TRACE_INPUT | LayerTracing::TRACE_BUFFERS);
+ flinger->setLayerTraceSize(512 * 1024); // 512MB buffer size
flinger->startLayerTracing(traceFile.entry(0).elapsed_realtime_nanos());
std::unique_ptr<TraceGenFlingerDataMapper> mapper =
std::make_unique<TraceGenFlingerDataMapper>();
@@ -217,9 +211,10 @@
for (int i = 0; i < traceFile.entry_size(); i++) {
proto::TransactionTraceEntry entry = traceFile.entry(i);
ALOGV(" Entry %04d/%04d for time=%" PRId64 " vsyncid=%" PRId64
- " layers +%d -%d transactions=%d",
+ " layers +%d -%d handles -%d transactions=%d",
i, traceFile.entry_size(), entry.elapsed_realtime_nanos(), entry.vsync_id(),
- entry.added_layers_size(), entry.removed_layers_size(), entry.transactions_size());
+ entry.added_layers_size(), entry.removed_layers_size(),
+ entry.removed_layer_handles_size(), entry.transactions_size());
for (int j = 0; j < entry.added_layers_size(); j++) {
// create layers
@@ -238,7 +233,7 @@
(dataMapper->mLayerHandles.find(tracingArgs.parentId) ==
dataMapper->mLayerHandles.end())) {
args.addToRoot = false;
- } else {
+ } else if (tracingArgs.parentId != -1) {
parentHandle = dataMapper->getLayerHandle(tracingArgs.parentId);
}
mFlinger.createLayer(args, &outHandle, parentHandle, &outLayerId,
@@ -265,13 +260,13 @@
transaction.listenerCallbacks, transaction.id);
}
- for (int j = 0; j < entry.removed_layer_handles_size(); j++) {
- dataMapper->mLayerHandles.erase(entry.removed_layer_handles(j));
- }
-
frameTime = entry.elapsed_realtime_nanos();
vsyncId = entry.vsync_id();
mFlinger.commit(frameTime, vsyncId);
+
+ for (int j = 0; j < entry.removed_layer_handles_size(); j++) {
+ dataMapper->mLayerHandles.erase(entry.removed_layer_handles(j));
+ }
}
flinger->stopLayerTracing(outputLayersTracePath);
diff --git a/services/surfaceflinger/TransactionState.h b/services/surfaceflinger/TransactionState.h
index 900d566..bbfeac1 100644
--- a/services/surfaceflinger/TransactionState.h
+++ b/services/surfaceflinger/TransactionState.h
@@ -106,7 +106,6 @@
public:
enum {
eSyncTransaction = 1 << 0,
- eSyncInputWindows = 1 << 1,
};
explicit CountDownLatch(uint32_t flags) : mFlags(flags) {}
diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.cpp b/services/surfaceflinger/WindowInfosListenerInvoker.cpp
index 30b9d8f..cc33001 100644
--- a/services/surfaceflinger/WindowInfosListenerInvoker.cpp
+++ b/services/surfaceflinger/WindowInfosListenerInvoker.cpp
@@ -26,21 +26,39 @@
using gui::IWindowInfosListener;
using gui::WindowInfo;
-struct WindowInfosListenerInvoker::WindowInfosReportedListener
- : gui::BnWindowInfosReportedListener {
- explicit WindowInfosReportedListener(WindowInfosListenerInvoker& invoker) : mInvoker(invoker) {}
+struct WindowInfosListenerInvoker::WindowInfosReportedListener : gui::BnWindowInfosReportedListener,
+ DeathRecipient {
+ explicit WindowInfosReportedListener(
+ size_t callbackCount,
+ const std::unordered_set<sp<gui::IWindowInfosReportedListener>,
+ SpHash<gui::IWindowInfosReportedListener>>&
+ windowInfosReportedListeners)
+ : mCallbacksPending(callbackCount),
+ mWindowInfosReportedListeners(windowInfosReportedListeners) {}
binder::Status onWindowInfosReported() override {
- mInvoker.windowInfosReported();
+ // TODO(b/222421815) There could potentially be callbacks that we don't need to wait for
+ // before calling the WindowInfosReportedListeners coming from InputWindowCommands. Filter
+ // the list of callbacks down to those from system server.
+ if (--mCallbacksPending == 0) {
+ for (const auto& listener : mWindowInfosReportedListeners) {
+ sp<IBinder> asBinder = IInterface::asBinder(listener);
+ if (asBinder->isBinderAlive()) {
+ listener->onWindowInfosReported();
+ }
+ }
+ }
return binder::Status::ok();
}
- WindowInfosListenerInvoker& mInvoker;
-};
+ void binderDied(const wp<IBinder>&) { onWindowInfosReported(); }
-WindowInfosListenerInvoker::WindowInfosListenerInvoker(SurfaceFlinger& flinger)
- : mFlinger(flinger),
- mWindowInfosReportedListener(sp<WindowInfosReportedListener>::make(*this)) {}
+private:
+ std::atomic<size_t> mCallbacksPending;
+ std::unordered_set<sp<gui::IWindowInfosReportedListener>,
+ SpHash<gui::IWindowInfosReportedListener>>
+ mWindowInfosReportedListeners;
+};
void WindowInfosListenerInvoker::addWindowInfosListener(sp<IWindowInfosListener> listener) {
sp<IBinder> asBinder = IInterface::asBinder(listener);
@@ -64,9 +82,11 @@
mWindowInfosListeners.erase(who);
}
-void WindowInfosListenerInvoker::windowInfosChanged(const std::vector<WindowInfo>& windowInfos,
- const std::vector<DisplayInfo>& displayInfos,
- bool shouldSync) {
+void WindowInfosListenerInvoker::windowInfosChanged(
+ const std::vector<WindowInfo>& windowInfos, const std::vector<DisplayInfo>& displayInfos,
+ const std::unordered_set<sp<gui::IWindowInfosReportedListener>,
+ SpHash<gui::IWindowInfosReportedListener>>&
+ windowInfosReportedListeners) {
ftl::SmallVector<const sp<IWindowInfosListener>, kStaticCapacity> windowInfosListeners;
{
std::scoped_lock lock(mListenersMutex);
@@ -75,18 +95,25 @@
}
}
- mCallbacksPending = windowInfosListeners.size();
-
+ auto windowInfosReportedListener = windowInfosReportedListeners.empty()
+ ? nullptr
+ : sp<WindowInfosReportedListener>::make(windowInfosListeners.size(),
+ windowInfosReportedListeners);
for (const auto& listener : windowInfosListeners) {
- listener->onWindowInfosChanged(windowInfos, displayInfos,
- shouldSync ? mWindowInfosReportedListener : nullptr);
- }
-}
+ sp<IBinder> asBinder = IInterface::asBinder(listener);
-void WindowInfosListenerInvoker::windowInfosReported() {
- mCallbacksPending--;
- if (mCallbacksPending == 0) {
- mFlinger.windowInfosReported();
+ // linkToDeath is used here to ensure that the windowInfosReportedListeners
+ // are called even if one of the windowInfosListeners dies before
+ // calling onWindowInfosReported.
+ if (windowInfosReportedListener) {
+ asBinder->linkToDeath(windowInfosReportedListener);
+ }
+
+ auto status = listener->onWindowInfosChanged(windowInfos, displayInfos,
+ windowInfosReportedListener);
+ if (!status.isOk()) {
+ windowInfosReportedListener->onWindowInfosReported();
+ }
}
}
diff --git a/services/surfaceflinger/WindowInfosListenerInvoker.h b/services/surfaceflinger/WindowInfosListenerInvoker.h
index d8d8d0f..a1d66a1 100644
--- a/services/surfaceflinger/WindowInfosListenerInvoker.h
+++ b/services/surfaceflinger/WindowInfosListenerInvoker.h
@@ -29,22 +29,21 @@
class WindowInfosListenerInvoker : public IBinder::DeathRecipient {
public:
- explicit WindowInfosListenerInvoker(SurfaceFlinger&);
-
void addWindowInfosListener(sp<gui::IWindowInfosListener>);
void removeWindowInfosListener(const sp<gui::IWindowInfosListener>& windowInfosListener);
void windowInfosChanged(const std::vector<gui::WindowInfo>&,
- const std::vector<gui::DisplayInfo>&, bool shouldSync);
+ const std::vector<gui::DisplayInfo>&,
+ const std::unordered_set<sp<gui::IWindowInfosReportedListener>,
+ SpHash<gui::IWindowInfosReportedListener>>&
+ windowInfosReportedListeners);
protected:
void binderDied(const wp<IBinder>& who) override;
private:
struct WindowInfosReportedListener;
- void windowInfosReported();
- SurfaceFlinger& mFlinger;
std::mutex mListenersMutex;
static constexpr size_t kStaticCapacity = 3;
@@ -52,7 +51,6 @@
mWindowInfosListeners GUARDED_BY(mListenersMutex);
sp<gui::IWindowInfosReportedListener> mWindowInfosReportedListener;
- std::atomic<size_t> mCallbacksPending{0};
};
} // namespace android
diff --git a/services/surfaceflinger/fuzzer/Android.bp b/services/surfaceflinger/fuzzer/Android.bp
index b0b6bf1..7350e09 100644
--- a/services/surfaceflinger/fuzzer/Android.bp
+++ b/services/surfaceflinger/fuzzer/Android.bp
@@ -127,3 +127,13 @@
"surfaceflinger_layer_fuzzer.cpp",
],
}
+
+cc_fuzz {
+ name: "surfaceflinger_frametracer_fuzzer",
+ defaults: [
+ "surfaceflinger_fuzz_defaults",
+ ],
+ srcs: [
+ "surfaceflinger_frametracer_fuzzer.cpp",
+ ],
+}
diff --git a/services/surfaceflinger/fuzzer/README.md b/services/surfaceflinger/fuzzer/README.md
index 78a7596..7a5f229 100644
--- a/services/surfaceflinger/fuzzer/README.md
+++ b/services/surfaceflinger/fuzzer/README.md
@@ -4,6 +4,7 @@
+ [DisplayHardware](#DisplayHardware)
+ [Scheduler](#Scheduler)
+ [Layer](#Layer)
++ [FrameTracer](#FrameTracer)
# <a name="SurfaceFlinger"></a> Fuzzer for SurfaceFlinger
@@ -93,3 +94,16 @@
$ adb sync data
$ adb shell /data/fuzz/arm64/surfaceflinger_layer_fuzzer/surfaceflinger_layer_fuzzer
```
+
+# <a name="FrameTracer"></a> Fuzzer for FrameTracer
+
+#### Steps to run
+1. Build the fuzzer
+```
+ $ mm -j$(nproc) surfaceflinger_frametracer_fuzzer
+```
+2. To run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/surfaceflinger_frametracer_fuzzer/surfaceflinger_frametracer_fuzzer
+```
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_frametracer_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_frametracer_fuzzer.cpp
new file mode 100644
index 0000000..a22a778
--- /dev/null
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_frametracer_fuzzer.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <FrameTracer/FrameTracer.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <perfetto/trace/trace.pb.h>
+
+namespace android::fuzz {
+
+using namespace google::protobuf;
+
+constexpr size_t kMaxStringSize = 100;
+constexpr size_t kMinLayerIds = 1;
+constexpr size_t kMaxLayerIds = 10;
+constexpr int32_t kConfigDuration = 500;
+constexpr int32_t kBufferSize = 1024;
+constexpr int32_t kTimeOffset = 100000;
+
+class FrameTracerFuzzer {
+public:
+ FrameTracerFuzzer(const uint8_t* data, size_t size) : mFdp(data, size) {
+ // Fuzzer is single-threaded, so no need to be thread-safe.
+ static bool wasInitialized = false;
+ if (!wasInitialized) {
+ perfetto::TracingInitArgs args;
+ args.backends = perfetto::kInProcessBackend;
+ perfetto::Tracing::Initialize(args);
+ wasInitialized = true;
+ }
+ mFrameTracer = std::make_unique<android::FrameTracer>();
+ }
+ ~FrameTracerFuzzer() { mFrameTracer.reset(); }
+ void process();
+
+private:
+ std::unique_ptr<perfetto::TracingSession> getTracingSessionForTest();
+ void traceTimestamp();
+ std::vector<int32_t> generateLayerIds(size_t numLayerIds);
+ void traceTimestamp(std::vector<int32_t> layerIds, size_t numLayerIds);
+ void traceFence(std::vector<int32_t> layerIds, size_t numLayerIds);
+ std::unique_ptr<android::FrameTracer> mFrameTracer = nullptr;
+ FuzzedDataProvider mFdp;
+ android::FenceToFenceTimeMap mFenceFactory;
+};
+
+std::unique_ptr<perfetto::TracingSession> FrameTracerFuzzer::getTracingSessionForTest() {
+ perfetto::TraceConfig cfg;
+ cfg.set_duration_ms(kConfigDuration);
+ cfg.add_buffers()->set_size_kb(kBufferSize);
+ auto* dsCfg = cfg.add_data_sources()->mutable_config();
+ dsCfg->set_name(android::FrameTracer::kFrameTracerDataSource);
+
+ auto tracingSession = perfetto::Tracing::NewTrace(perfetto::kInProcessBackend);
+ tracingSession->Setup(cfg);
+ return tracingSession;
+}
+
+std::vector<int32_t> FrameTracerFuzzer::generateLayerIds(size_t numLayerIds) {
+ std::vector<int32_t> layerIds;
+ for (size_t i = 0; i < numLayerIds; ++i) {
+ layerIds.push_back(mFdp.ConsumeIntegral<int32_t>());
+ }
+ return layerIds;
+}
+
+void FrameTracerFuzzer::traceTimestamp(std::vector<int32_t> layerIds, size_t numLayerIds) {
+ int32_t layerId = layerIds.at(mFdp.ConsumeIntegralInRange<size_t>(0, numLayerIds - 1));
+ mFrameTracer->traceTimestamp(layerId, mFdp.ConsumeIntegral<uint64_t>() /*bufferID*/,
+ mFdp.ConsumeIntegral<uint64_t>() /*frameNumber*/,
+ mFdp.ConsumeIntegral<nsecs_t>() /*timestamp*/,
+ android::FrameTracer::FrameEvent::UNSPECIFIED,
+ mFdp.ConsumeIntegral<nsecs_t>() /*duration*/);
+}
+
+void FrameTracerFuzzer::traceFence(std::vector<int32_t> layerIds, size_t numLayerIds) {
+ const nsecs_t signalTime = systemTime();
+ const nsecs_t startTime = signalTime + kTimeOffset;
+ auto fence = mFenceFactory.createFenceTimeForTest(android::Fence::NO_FENCE);
+ mFenceFactory.signalAllForTest(android::Fence::NO_FENCE, signalTime);
+ int32_t layerId = layerIds.at(mFdp.ConsumeIntegralInRange<size_t>(0, numLayerIds - 1));
+ mFrameTracer->traceFence(layerId, mFdp.ConsumeIntegral<uint64_t>() /*bufferID*/,
+ mFdp.ConsumeIntegral<uint64_t>() /*frameNumber*/, fence,
+ android::FrameTracer::FrameEvent::ACQUIRE_FENCE, startTime);
+}
+
+void FrameTracerFuzzer::process() {
+ mFrameTracer->registerDataSource();
+
+ auto tracingSession = getTracingSessionForTest();
+ tracingSession->StartBlocking();
+
+ size_t numLayerIds = mFdp.ConsumeIntegralInRange<size_t>(kMinLayerIds, kMaxLayerIds);
+ std::vector<int32_t> layerIds = generateLayerIds(numLayerIds);
+
+ for (auto it = layerIds.begin(); it != layerIds.end(); ++it) {
+ mFrameTracer->traceNewLayer(*it /*layerId*/,
+ mFdp.ConsumeRandomLengthString(kMaxStringSize) /*layerName*/);
+ }
+
+ traceTimestamp(layerIds, numLayerIds);
+ traceFence(layerIds, numLayerIds);
+
+ mFenceFactory.signalAllForTest(android::Fence::NO_FENCE, systemTime());
+
+ tracingSession->StopBlocking();
+
+ for (auto it = layerIds.begin(); it != layerIds.end(); ++it) {
+ mFrameTracer->onDestroy(*it);
+ }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ FrameTracerFuzzer frameTracerFuzzer(data, size);
+ frameTracerFuzzer.process();
+ return 0;
+}
+
+} // namespace android::fuzz
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp
index f25043c..8e60247 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzer.cpp
@@ -151,7 +151,6 @@
sp<IBinder> handle = defaultServiceManager()->checkService(
String16(mFdp.ConsumeRandomLengthString().c_str()));
mFlinger->fromHandle(handle);
- mFlinger->windowInfosReported();
mFlinger->disableExpensiveRendering();
}
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h
index 867a198..3338da0 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 "BufferQueueLayer.h"
#include "BufferStateLayer.h"
#include "ContainerLayer.h"
#include "DisplayDevice.h"
@@ -334,18 +333,6 @@
mCreateBufferQueue(outProducer, outConsumer, consumerIsSurfaceFlinger);
}
- sp<IGraphicBufferProducer> createMonitoredProducer(const sp<IGraphicBufferProducer> &producer,
- const sp<SurfaceFlinger> &flinger,
- const wp<Layer> &layer) override {
- return new MonitoredProducer(producer, flinger, layer);
- }
-
- sp<BufferLayerConsumer> createBufferLayerConsumer(const sp<IGraphicBufferConsumer> &consumer,
- renderengine::RenderEngine &renderEngine,
- uint32_t textureName, Layer *layer) override {
- return new BufferLayerConsumer(consumer, renderEngine, textureName, layer);
- }
-
std::unique_ptr<surfaceflinger::NativeWindowSurface> createNativeWindowSurface(
const sp<IGraphicBufferProducer> &producer) override {
if (!mCreateNativeWindowSurface) return nullptr;
@@ -356,10 +343,6 @@
return compositionengine::impl::createCompositionEngine();
}
- sp<BufferQueueLayer> createBufferQueueLayer(const LayerCreationArgs &) override {
- return nullptr;
- }
-
sp<BufferStateLayer> createBufferStateLayer(const LayerCreationArgs &) override {
return nullptr;
}
@@ -540,19 +523,9 @@
mFlinger->setVsyncConfig(vsyncConfig, fdp->ConsumeIntegral<nsecs_t>());
}
- void updateCompositorTiming(FuzzedDataProvider *fdp) {
- std::shared_ptr<FenceTime> presentFenceTime = FenceTime::NO_FENCE;
- mFlinger->updateCompositorTiming({}, fdp->ConsumeIntegral<nsecs_t>(), presentFenceTime);
- }
-
- void getCompositorTiming() {
- CompositorTiming compositorTiming;
- mFlinger->getCompositorTiming(&compositorTiming);
- }
-
sp<IBinder> fuzzBoot(FuzzedDataProvider *fdp) {
mFlinger->callingThreadHasUnscopedSurfaceFlingerAccess(fdp->ConsumeBool());
- mFlinger->createConnection();
+ const sp<Client> client = new Client(mFlinger);
DisplayIdGenerator<HalVirtualDisplayId> kGenerator;
HalVirtualDisplayId halVirtualDisplayId = kGenerator.generateId().value();
@@ -585,7 +558,6 @@
sp<IBinder> display = fuzzBoot(&mFdp);
sp<IGraphicBufferProducer> bufferProducer = sp<mock::GraphicBufferProducer>::make();
- mFlinger->authenticateSurfaceTexture(bufferProducer.get());
mFlinger->createDisplayEventConnection();
@@ -645,11 +617,8 @@
mFlinger->postComposition();
- getCompositorTiming();
+ mFlinger->trackPresentLatency(mFdp.ConsumeIntegral<nsecs_t>(), FenceTime::NO_FENCE);
- updateCompositorTiming(&mFdp);
-
- mFlinger->setCompositorTimingSnapped({}, mFdp.ConsumeIntegral<nsecs_t>());
FTL_FAKE_GUARD(kMainThreadContext, mFlinger->postFrame());
mFlinger->calculateExpectedPresentTime({});
@@ -779,7 +748,7 @@
return mFlinger->onTransact(code, data, reply, flags);
}
- auto getGPUContextPriority() { return mFlinger->getGPUContextPriority(); }
+ auto getGpuContextPriority() { return mFlinger->getGpuContextPriority(); }
auto calculateMaxAcquiredBufferCount(Fps refreshRate,
std::chrono::nanoseconds presentLatency) const {
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp
index 34cf906..4d90b1e 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_layer_fuzzer.cpp
@@ -18,9 +18,7 @@
#include <Client.h>
#include <DisplayDevice.h>
#include <EffectLayer.h>
-#include <LayerRejecter.h>
#include <LayerRenderArea.h>
-#include <MonitoredProducer.h>
#include <ftl/future.h>
#include <fuzzer/FuzzedDataProvider.h>
#include <gui/IProducerListener.h>
@@ -59,8 +57,10 @@
}
FrameTimelineInfo LayerFuzzer::getFuzzedFrameTimelineInfo() {
- return FrameTimelineInfo{.vsyncId = mFdp.ConsumeIntegral<int64_t>(),
- .inputEventId = mFdp.ConsumeIntegral<int32_t>()};
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = mFdp.ConsumeIntegral<int64_t>();
+ ftInfo.inputEventId = mFdp.ConsumeIntegral<int32_t>();
+ return ftInfo;
}
LayerCreationArgs LayerFuzzer::createLayerCreationArgs(TestableSurfaceFlinger* flinger,
@@ -115,17 +115,18 @@
sp<Fence> fence = sp<Fence>::make();
const std::shared_ptr<FenceTime> fenceTime = std::make_shared<FenceTime>(fence);
- const CompositorTiming compositor = {mFdp.ConsumeIntegral<int64_t>(),
- mFdp.ConsumeIntegral<int64_t>(),
- mFdp.ConsumeIntegral<int64_t>()};
+ const CompositorTiming compositorTiming(mFdp.ConsumeIntegral<int64_t>(),
+ mFdp.ConsumeIntegral<int64_t>(),
+ mFdp.ConsumeIntegral<int64_t>(),
+ mFdp.ConsumeIntegral<int64_t>());
layer->onLayerDisplayed(ftl::yield<FenceResult>(fence).share());
layer->onLayerDisplayed(
ftl::yield<FenceResult>(base::unexpected(mFdp.ConsumeIntegral<status_t>())).share());
layer->releasePendingBuffer(mFdp.ConsumeIntegral<int64_t>());
- layer->finalizeFrameEventHistory(fenceTime, compositor);
- layer->onPostComposition(nullptr, fenceTime, fenceTime, compositor);
+ layer->finalizeFrameEventHistory(fenceTime, compositorTiming);
+ layer->onPostComposition(nullptr, fenceTime, fenceTime, compositorTiming);
layer->isBufferDue(mFdp.ConsumeIntegral<int64_t>());
layer->setTransform(mFdp.ConsumeIntegral<uint32_t>());
diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
index da60a69..1a91a69 100644
--- a/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
+++ b/services/surfaceflinger/fuzzer/surfaceflinger_scheduler_fuzzer.cpp
@@ -319,7 +319,7 @@
LayerCreationArgs args(flinger.flinger(), client,
mFdp.ConsumeRandomLengthString(kRandomStringLength) /*name*/,
mFdp.ConsumeIntegral<uint16_t>() /*layerFlags*/, LayerMetadata());
- sp<Layer> layer = new BufferQueueLayer(args);
+ sp<Layer> layer = new BufferStateLayer(args);
layer->setFrameRateSelectionPriority(mFdp.ConsumeIntegral<int16_t>());
}
diff --git a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
index 52503ba..cdc2706 100644
--- a/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
+++ b/services/surfaceflinger/layerproto/include/layerproto/LayerProtoParser.h
@@ -24,6 +24,8 @@
#include <unordered_map>
#include <vector>
+using android::gui::LayerMetadata;
+
namespace android {
namespace surfaceflinger {
diff --git a/services/surfaceflinger/layerproto/layerstrace.proto b/services/surfaceflinger/layerproto/layerstrace.proto
index 13647b6..7def024 100644
--- a/services/surfaceflinger/layerproto/layerstrace.proto
+++ b/services/surfaceflinger/layerproto/layerstrace.proto
@@ -40,7 +40,7 @@
repeated LayersTraceProto entry = 2;
}
-/* one window manager trace entry. */
+/* one layers trace entry. */
message LayersTraceProto {
/* required: elapsed realtime in nanos since boot of when this entry was logged */
optional sfixed64 elapsed_realtime_nanos = 1;
@@ -60,4 +60,6 @@
optional uint32 missed_entries = 6;
repeated DisplayProto displays = 7;
+
+ optional int64 vsync_id = 8;
}
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index ceddf27..276431e 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -34,6 +34,7 @@
"DisplayConfigs_test.cpp",
"DisplayEventReceiver_test.cpp",
"EffectLayer_test.cpp",
+ "LayerBorder_test.cpp",
"InvalidHandles_test.cpp",
"LayerCallback_test.cpp",
"LayerRenderTypeTransaction_test.cpp",
diff --git a/services/surfaceflinger/tests/BootDisplayMode_test.cpp b/services/surfaceflinger/tests/BootDisplayMode_test.cpp
index d70908e..432e227 100644
--- a/services/surfaceflinger/tests/BootDisplayMode_test.cpp
+++ b/services/surfaceflinger/tests/BootDisplayMode_test.cpp
@@ -18,6 +18,7 @@
#include <gtest/gtest.h>
+#include <gui/AidlStatusUtil.h>
#include <gui/SurfaceComposerClient.h>
#include <private/gui/ComposerService.h>
#include <private/gui/ComposerServiceAIDL.h>
@@ -25,15 +26,17 @@
namespace android {
+using gui::aidl_utils::statusTFromBinderStatus;
+
TEST(BootDisplayModeTest, setBootDisplayMode) {
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- sp<gui::ISurfaceComposer> sf_aidl(ComposerServiceAIDL::getComposerService());
+ sp<gui::ISurfaceComposer> sf(ComposerServiceAIDL::getComposerService());
auto displayToken = SurfaceComposerClient::getInternalDisplayToken();
bool bootModeSupport = false;
- binder::Status status = sf_aidl->getBootDisplayModeSupport(&bootModeSupport);
- ASSERT_NO_FATAL_FAILURE(status.transactionError());
+ binder::Status status = sf->getBootDisplayModeSupport(&bootModeSupport);
+ ASSERT_NO_FATAL_FAILURE(statusTFromBinderStatus(status));
if (bootModeSupport) {
- ASSERT_EQ(NO_ERROR, sf->setBootDisplayMode(displayToken, 0));
+ status = sf->setBootDisplayMode(displayToken, 0);
+ ASSERT_EQ(NO_ERROR, statusTFromBinderStatus(status));
}
}
@@ -42,10 +45,10 @@
auto displayToken = SurfaceComposerClient::getInternalDisplayToken();
bool bootModeSupport = false;
binder::Status status = sf->getBootDisplayModeSupport(&bootModeSupport);
- ASSERT_NO_FATAL_FAILURE(status.transactionError());
+ ASSERT_NO_FATAL_FAILURE(statusTFromBinderStatus(status));
if (bootModeSupport) {
status = sf->clearBootDisplayMode(displayToken);
- ASSERT_EQ(NO_ERROR, status.transactionError());
+ ASSERT_EQ(NO_ERROR, statusTFromBinderStatus(status));
}
}
diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp
index d33bc10..8a443b8 100644
--- a/services/surfaceflinger/tests/Credentials_test.cpp
+++ b/services/surfaceflinger/tests/Credentials_test.cpp
@@ -18,13 +18,14 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wconversion"
+#include <android/gui/ISurfaceComposer.h>
#include <gtest/gtest.h>
-#include <gui/ISurfaceComposer.h>
+#include <gui/AidlStatusUtil.h>
#include <gui/LayerDebugInfo.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <private/android_filesystem_config.h>
-#include <private/gui/ComposerService.h>
+#include <private/gui/ComposerServiceAIDL.h>
#include <ui/DisplayMode.h>
#include <ui/DynamicDisplayInfo.h>
#include <utils/String8.h>
@@ -34,6 +35,8 @@
namespace android {
using Transaction = SurfaceComposerClient::Transaction;
+using gui::LayerDebugInfo;
+using gui::aidl_utils::statusTFromBinderStatus;
using ui::ColorMode;
namespace {
@@ -307,23 +310,26 @@
*/
TEST_F(CredentialsTest, GetLayerDebugInfo) {
setupBackgroundSurface();
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+ sp<gui::ISurfaceComposer> sf(ComposerServiceAIDL::getComposerService());
// Historically, only root and shell can access the getLayerDebugInfo which
// is called when we call dumpsys. I don't see a reason why we should change this.
std::vector<LayerDebugInfo> outLayers;
// Check with root.
seteuid(AID_ROOT);
- ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
+ binder::Status status = sf->getLayerDebugInfo(&outLayers);
+ ASSERT_EQ(NO_ERROR, statusTFromBinderStatus(status));
// Check as a shell.
seteuid(AID_SHELL);
- ASSERT_EQ(NO_ERROR, sf->getLayerDebugInfo(&outLayers));
+ status = sf->getLayerDebugInfo(&outLayers);
+ ASSERT_EQ(NO_ERROR, statusTFromBinderStatus(status));
// Check as anyone else.
seteuid(AID_ROOT);
seteuid(AID_BIN);
- ASSERT_EQ(PERMISSION_DENIED, sf->getLayerDebugInfo(&outLayers));
+ status = sf->getLayerDebugInfo(&outLayers);
+ ASSERT_EQ(PERMISSION_DENIED, statusTFromBinderStatus(status));
}
TEST_F(CredentialsTest, IsWideColorDisplayBasicCorrectness) {
diff --git a/services/surfaceflinger/tests/DisplayEventReceiver_test.cpp b/services/surfaceflinger/tests/DisplayEventReceiver_test.cpp
index 0e54664..0df7e2f 100644
--- a/services/surfaceflinger/tests/DisplayEventReceiver_test.cpp
+++ b/services/surfaceflinger/tests/DisplayEventReceiver_test.cpp
@@ -36,7 +36,8 @@
EXPECT_GT(vsyncEventData.frameTimelines[0].deadlineTimestamp, now)
<< "Deadline timestamp should be greater than frame time";
for (size_t i = 0; i < VsyncEventData::kFrameTimelinesLength; i++) {
- EXPECT_NE(FrameTimelineInfo::INVALID_VSYNC_ID, vsyncEventData.frameTimelines[i].vsyncId);
+ EXPECT_NE(gui::FrameTimelineInfo::INVALID_VSYNC_ID,
+ vsyncEventData.frameTimelines[i].vsyncId);
EXPECT_GT(vsyncEventData.frameTimelines[i].expectedPresentationTime,
vsyncEventData.frameTimelines[i].deadlineTimestamp)
<< "Expected vsync timestamp should be greater than deadline";
@@ -51,4 +52,4 @@
}
}
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/surfaceflinger/tests/InvalidHandles_test.cpp b/services/surfaceflinger/tests/InvalidHandles_test.cpp
index d192a2d..023133f 100644
--- a/services/surfaceflinger/tests/InvalidHandles_test.cpp
+++ b/services/surfaceflinger/tests/InvalidHandles_test.cpp
@@ -48,7 +48,7 @@
}
sp<SurfaceControl> makeNotSurfaceControl() {
- return new SurfaceControl(mScc, new NotALayer(), nullptr, true);
+ return new SurfaceControl(mScc, new NotALayer(), 1);
}
};
@@ -64,4 +64,4 @@
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion"
\ No newline at end of file
+#pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/tests/LayerBorder_test.cpp b/services/surfaceflinger/tests/LayerBorder_test.cpp
new file mode 100644
index 0000000..f80c705
--- /dev/null
+++ b/services/surfaceflinger/tests/LayerBorder_test.cpp
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+// TODO: Amend all tests when screenshots become fully reworked for borders
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wconversion"
+
+#include <chrono> // std::chrono::seconds
+#include <thread> // std::this_thread::sleep_for
+#include "LayerTransactionTest.h"
+
+namespace android {
+
+class LayerBorderTest : public LayerTransactionTest {
+protected:
+ virtual void SetUp() {
+ LayerTransactionTest::SetUp();
+ ASSERT_EQ(NO_ERROR, mClient->initCheck());
+
+ toHalf3 = ColorTransformHelper::toHalf3;
+ toHalf4 = ColorTransformHelper::toHalf4;
+
+ const auto display = SurfaceComposerClient::getInternalDisplayToken();
+ ASSERT_FALSE(display == nullptr);
+ mColorOrange = toHalf4({255, 140, 0, 255});
+ mParentLayer = createColorLayer("Parent layer", Color::RED);
+
+ mContainerLayer = mClient->createSurface(String8("Container Layer"), 0 /* width */,
+ 0 /* height */, PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceContainer |
+ ISurfaceComposerClient::eNoColorFill,
+ mParentLayer->getHandle());
+ EXPECT_NE(nullptr, mContainerLayer.get()) << "failed to create container layer";
+
+ mEffectLayer1 = mClient->createSurface(String8("Effect Layer"), 0 /* width */,
+ 0 /* height */, PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceEffect |
+ ISurfaceComposerClient::eNoColorFill,
+ mContainerLayer->getHandle());
+ EXPECT_NE(nullptr, mEffectLayer1.get()) << "failed to create effect layer 1";
+
+ mEffectLayer2 = mClient->createSurface(String8("Effect Layer"), 0 /* width */,
+ 0 /* height */, PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceEffect |
+ ISurfaceComposerClient::eNoColorFill,
+ mContainerLayer->getHandle());
+
+ EXPECT_NE(nullptr, mEffectLayer2.get()) << "failed to create effect layer 2";
+
+ asTransaction([&](Transaction& t) {
+ t.setDisplayLayerStack(display, ui::DEFAULT_LAYER_STACK);
+ t.setLayer(mParentLayer, INT32_MAX - 20).show(mParentLayer);
+ t.setFlags(mParentLayer, layer_state_t::eLayerOpaque, layer_state_t::eLayerOpaque);
+
+ t.setColor(mEffectLayer1, toHalf3(Color::BLUE));
+
+ t.setColor(mEffectLayer2, toHalf3(Color::GREEN));
+ });
+ }
+
+ virtual void TearDown() {
+ // Uncomment the line right below when running any of the tests
+ // std::this_thread::sleep_for (std::chrono::seconds(30));
+ LayerTransactionTest::TearDown();
+ mParentLayer = 0;
+ }
+
+ std::function<half3(Color)> toHalf3;
+ std::function<half4(Color)> toHalf4;
+ sp<SurfaceControl> mParentLayer, mContainerLayer, mEffectLayer1, mEffectLayer2;
+ half4 mColorOrange;
+};
+
+TEST_F(LayerBorderTest, OverlappingVisibleRegions) {
+ asTransaction([&](Transaction& t) {
+ t.setCrop(mEffectLayer1, Rect(0, 0, 400, 400));
+ t.setCrop(mEffectLayer2, Rect(200, 200, 600, 600));
+
+ t.enableBorder(mContainerLayer, true, 20, mColorOrange);
+ t.show(mEffectLayer1);
+ t.show(mEffectLayer2);
+ t.show(mContainerLayer);
+ });
+}
+
+TEST_F(LayerBorderTest, PartiallyCoveredVisibleRegion) {
+ asTransaction([&](Transaction& t) {
+ t.setCrop(mEffectLayer1, Rect(0, 0, 400, 400));
+ t.setCrop(mEffectLayer2, Rect(200, 200, 600, 600));
+
+ t.enableBorder(mEffectLayer1, true, 20, mColorOrange);
+ t.show(mEffectLayer1);
+ t.show(mEffectLayer2);
+ t.show(mContainerLayer);
+ });
+}
+
+TEST_F(LayerBorderTest, NonOverlappingVisibleRegion) {
+ asTransaction([&](Transaction& t) {
+ t.setCrop(mEffectLayer1, Rect(0, 0, 200, 200));
+ t.setCrop(mEffectLayer2, Rect(400, 400, 600, 600));
+
+ t.enableBorder(mContainerLayer, true, 20, mColorOrange);
+ t.show(mEffectLayer1);
+ t.show(mEffectLayer2);
+ t.show(mContainerLayer);
+ });
+}
+
+TEST_F(LayerBorderTest, EmptyVisibleRegion) {
+ asTransaction([&](Transaction& t) {
+ t.setCrop(mEffectLayer1, Rect(200, 200, 400, 400));
+ t.setCrop(mEffectLayer2, Rect(0, 0, 600, 600));
+
+ t.enableBorder(mEffectLayer1, true, 20, mColorOrange);
+ t.show(mEffectLayer1);
+ t.show(mEffectLayer2);
+ t.show(mContainerLayer);
+ });
+}
+
+TEST_F(LayerBorderTest, ZOrderAdjustment) {
+ asTransaction([&](Transaction& t) {
+ t.setCrop(mEffectLayer1, Rect(0, 0, 400, 400));
+ t.setCrop(mEffectLayer2, Rect(200, 200, 600, 600));
+ t.setLayer(mParentLayer, 10);
+ t.setLayer(mEffectLayer1, 30);
+ t.setLayer(mEffectLayer2, 20);
+
+ t.enableBorder(mEffectLayer1, true, 20, mColorOrange);
+ t.show(mEffectLayer1);
+ t.show(mEffectLayer2);
+ t.show(mContainerLayer);
+ });
+}
+
+TEST_F(LayerBorderTest, GrandChildHierarchy) {
+ sp<SurfaceControl> containerLayer2 =
+ mClient->createSurface(String8("Container Layer"), 0 /* width */, 0 /* height */,
+ PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceContainer |
+ ISurfaceComposerClient::eNoColorFill,
+ mContainerLayer->getHandle());
+ EXPECT_NE(nullptr, containerLayer2.get()) << "failed to create container layer 2";
+
+ sp<SurfaceControl> effectLayer3 =
+ mClient->createSurface(String8("Effect Layer"), 0 /* width */, 0 /* height */,
+ PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceEffect |
+ ISurfaceComposerClient::eNoColorFill,
+ containerLayer2->getHandle());
+
+ asTransaction([&](Transaction& t) {
+ t.setCrop(mEffectLayer1, Rect(0, 0, 400, 400));
+ t.setCrop(mEffectLayer2, Rect(200, 200, 600, 600));
+ t.setCrop(effectLayer3, Rect(400, 400, 800, 800));
+ t.setColor(effectLayer3, toHalf3(Color::BLUE));
+
+ t.enableBorder(mContainerLayer, true, 20, mColorOrange);
+ t.show(mEffectLayer1);
+ t.show(mEffectLayer2);
+ t.show(effectLayer3);
+ t.show(mContainerLayer);
+ });
+}
+
+TEST_F(LayerBorderTest, TransparentAlpha) {
+ asTransaction([&](Transaction& t) {
+ t.setCrop(mEffectLayer1, Rect(0, 0, 400, 400));
+ t.setCrop(mEffectLayer2, Rect(200, 200, 600, 600));
+ t.setAlpha(mEffectLayer1, 0.0f);
+
+ t.enableBorder(mContainerLayer, true, 20, mColorOrange);
+ t.show(mEffectLayer1);
+ t.show(mEffectLayer2);
+ t.show(mContainerLayer);
+ });
+}
+
+TEST_F(LayerBorderTest, SemiTransparentAlpha) {
+ asTransaction([&](Transaction& t) {
+ t.setCrop(mEffectLayer1, Rect(0, 0, 400, 400));
+ t.setCrop(mEffectLayer2, Rect(200, 200, 600, 600));
+ t.setAlpha(mEffectLayer2, 0.5f);
+
+ t.enableBorder(mEffectLayer2, true, 20, mColorOrange);
+ t.show(mEffectLayer1);
+ t.show(mEffectLayer2);
+ t.show(mContainerLayer);
+ });
+}
+
+TEST_F(LayerBorderTest, InvisibleLayers) {
+ asTransaction([&](Transaction& t) {
+ t.setCrop(mEffectLayer1, Rect(0, 0, 400, 400));
+ t.setCrop(mEffectLayer2, Rect(200, 200, 600, 600));
+
+ t.enableBorder(mContainerLayer, true, 20, mColorOrange);
+ t.hide(mEffectLayer2);
+ t.show(mContainerLayer);
+ });
+}
+
+TEST_F(LayerBorderTest, BufferStateLayer) {
+ asTransaction([&](Transaction& t) {
+ t.hide(mEffectLayer1);
+ t.hide(mEffectLayer2);
+ t.show(mContainerLayer);
+
+ sp<SurfaceControl> bufferStateLayer =
+ mClient->createSurface(String8("BufferState"), 0 /* width */, 0 /* height */,
+ PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceBufferState,
+ mContainerLayer->getHandle());
+
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(400, 400, PIXEL_FORMAT_RGBA_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY | BufferUsage::GPU_TEXTURE,
+ "test");
+ 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.enableBorder(mContainerLayer, true, 20, mColorOrange);
+ });
+}
+
+TEST_F(LayerBorderTest, CustomWidth) {
+ asTransaction([&](Transaction& t) {
+ t.setCrop(mEffectLayer1, Rect(0, 0, 400, 400));
+ t.setCrop(mEffectLayer2, Rect(200, 200, 600, 600));
+
+ t.enableBorder(mContainerLayer, true, 50, mColorOrange);
+ t.show(mEffectLayer1);
+ t.show(mEffectLayer2);
+ t.show(mContainerLayer);
+ });
+}
+
+TEST_F(LayerBorderTest, CustomColor) {
+ asTransaction([&](Transaction& t) {
+ t.setCrop(mEffectLayer1, Rect(0, 0, 400, 400));
+ t.setCrop(mEffectLayer2, Rect(200, 200, 600, 600));
+
+ t.enableBorder(mContainerLayer, true, 20, toHalf4({255, 0, 255, 255}));
+ t.show(mEffectLayer1);
+ t.show(mEffectLayer2);
+ t.show(mContainerLayer);
+ });
+}
+
+TEST_F(LayerBorderTest, CustomWidthAndColorAndOpacity) {
+ asTransaction([&](Transaction& t) {
+ t.setCrop(mEffectLayer1, Rect(0, 0, 200, 200));
+ t.setCrop(mEffectLayer2, Rect(400, 400, 600, 600));
+
+ t.enableBorder(mContainerLayer, true, 40, toHalf4({255, 255, 0, 128}));
+ t.show(mEffectLayer1);
+ t.show(mEffectLayer2);
+ t.show(mContainerLayer);
+ });
+}
+
+} // namespace android
+
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/tests/LayerCallback_test.cpp b/services/surfaceflinger/tests/LayerCallback_test.cpp
index 219db8c..c8df0a0 100644
--- a/services/surfaceflinger/tests/LayerCallback_test.cpp
+++ b/services/surfaceflinger/tests/LayerCallback_test.cpp
@@ -1050,7 +1050,10 @@
}
const Vsync vsync = waitForNextVsync();
- transaction.setFrameTimelineInfo({vsync.vsyncId, 0});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = vsync.vsyncId;
+ ftInfo.inputEventId = 0;
+ transaction.setFrameTimelineInfo(ftInfo);
transaction.apply();
ExpectedResult expected;
diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h
index 6bd7920..b46db65 100644
--- a/services/surfaceflinger/tests/LayerTransactionTest.h
+++ b/services/surfaceflinger/tests/LayerTransactionTest.h
@@ -23,9 +23,11 @@
#include <cutils/properties.h>
#include <gtest/gtest.h>
+#include <gui/AidlStatusUtil.h>
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
#include <private/gui/ComposerService.h>
+#include <private/gui/ComposerServiceAIDL.h>
#include <ui/DisplayMode.h>
#include "BufferGenerator.h"
@@ -44,8 +46,9 @@
ASSERT_NO_FATAL_FAILURE(SetUpDisplay());
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- ASSERT_NO_FATAL_FAILURE(sf->getColorManagement(&mColorManagementUsed));
+ sp<gui::ISurfaceComposer> sf(ComposerServiceAIDL::getComposerService());
+ binder::Status status = sf->getColorManagement(&mColorManagementUsed);
+ ASSERT_NO_FATAL_FAILURE(gui::aidl_utils::statusTFromBinderStatus(status));
mCaptureArgs.displayToken = mDisplay;
}
diff --git a/services/surfaceflinger/tests/SetFrameRateOverride_test.cpp b/services/surfaceflinger/tests/SetFrameRateOverride_test.cpp
index 4efec77..e43ef95 100644
--- a/services/surfaceflinger/tests/SetFrameRateOverride_test.cpp
+++ b/services/surfaceflinger/tests/SetFrameRateOverride_test.cpp
@@ -14,9 +14,9 @@
* limitations under the License.
*/
+#include <android/gui/ISurfaceComposer.h>
#include <gtest/gtest.h>
#include <gui/DisplayEventReceiver.h>
-#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
#include <sys/epoll.h>
#include <algorithm>
@@ -24,12 +24,14 @@
namespace android {
namespace {
using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride;
+using gui::ISurfaceComposer;
class SetFrameRateOverrideTest : public ::testing::Test {
protected:
void SetUp() override {
- const ISurfaceComposer::VsyncSource vsyncSource = ISurfaceComposer::eVsyncSourceApp;
- const ISurfaceComposer::EventRegistrationFlags eventRegistration = {
+ const ISurfaceComposer::VsyncSource vsyncSource =
+ ISurfaceComposer::VsyncSource::eVsyncSourceApp;
+ const EventRegistrationFlags eventRegistration = {
ISurfaceComposer::EventRegistration::frameRateOverride};
mDisplayEventReceiver =
diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp
index b38032d..f824fdf 100644
--- a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp
+++ b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp
@@ -86,7 +86,9 @@
class DelayedEventGenerator {
public:
explicit DelayedEventGenerator(std::function<void()> onTimerExpired)
- : mOnTimerExpired(onTimerExpired), mThread([this]() { loop(); }) {}
+ : mOnTimerExpired(onTimerExpired) {
+ mThread = std::thread([this]() { loop(); });
+ }
~DelayedEventGenerator() {
ALOGI("DelayedEventGenerator exiting.");
diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
index b3b4ec1..00845d7 100644
--- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
+++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
@@ -29,6 +29,7 @@
#include "MockComposerHal.h"
#include <binder/Parcel.h>
+#include <gui/AidlStatusUtil.h>
#include <gui/DisplayEventReceiver.h>
#include <gui/ISurfaceComposer.h>
#include <gui/LayerDebugInfo.h>
@@ -43,6 +44,7 @@
#include <hwbinder/ProcessState.h>
#include <log/log.h>
#include <private/gui/ComposerService.h>
+#include <private/gui/ComposerServiceAIDL.h>
#include <ui/DisplayMode.h>
#include <ui/DynamicDisplayInfo.h>
#include <utils/Looper.h>
@@ -243,8 +245,9 @@
mComposerClient = new SurfaceComposerClient;
ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
- mReceiver.reset(new DisplayEventReceiver(ISurfaceComposer::eVsyncSourceApp,
- ISurfaceComposer::EventRegistration::modeChanged));
+ mReceiver.reset(
+ new DisplayEventReceiver(gui::ISurfaceComposer::VsyncSource::eVsyncSourceApp,
+ gui::ISurfaceComposer::EventRegistration::modeChanged));
mLooper = new Looper(false);
mLooper->addFd(mReceiver->getFd(), 0, ALOOPER_EVENT_INPUT, processDisplayEvents, this);
}
@@ -992,7 +995,7 @@
// Tests that VSYNC injection can be safely toggled while invalidating.
TEST_F(DisplayTest_2_1, VsyncInjection) {
- const auto flinger = ComposerService::getComposerService();
+ const auto flinger = ComposerServiceAIDL::getComposerService();
bool enable = true;
for (int i = 0; i < 100; i++) {
@@ -1238,9 +1241,10 @@
sFakeComposer->clearFrames();
ASSERT_EQ(0, sFakeComposer->getFrameCount());
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- std::vector<LayerDebugInfo> layers;
- status_t result = sf->getLayerDebugInfo(&layers);
+ sp<gui::ISurfaceComposer> sf(ComposerServiceAIDL::getComposerService());
+ std::vector<gui::LayerDebugInfo> layers;
+ binder::Status status = sf->getLayerDebugInfo(&layers);
+ status_t result = gui::aidl_utils::statusTFromBinderStatus(status);
if (result != NO_ERROR) {
ALOGE("Failed to get layers %s %d", strerror(-result), result);
} else {
diff --git a/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp b/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp
index ac4354c..0e214af 100644
--- a/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp
+++ b/services/surfaceflinger/tests/tracing/TransactionTraceTestSuite.cpp
@@ -83,6 +83,37 @@
std::vector<std::filesystem::path> TransactionTraceTestSuite::sTransactionTraces{};
+struct LayerInfo {
+ int id;
+ std::string name;
+ int parent;
+ int z;
+ uint64_t curr_frame;
+ float x;
+ float y;
+};
+
+bool operator==(const LayerInfo& lh, const LayerInfo& rh) {
+ return std::make_tuple(lh.id, lh.name, lh.parent, lh.z, lh.curr_frame) ==
+ std::make_tuple(rh.id, rh.name, rh.parent, rh.z, rh.curr_frame);
+}
+
+bool compareById(const LayerInfo& a, const LayerInfo& b) {
+ return a.id < b.id;
+}
+
+inline void PrintTo(const LayerInfo& info, ::std::ostream* os) {
+ *os << "Layer [" << info.id << "] name=" << info.name << " parent=" << info.parent
+ << " z=" << info.z << " curr_frame=" << info.curr_frame << " x=" << info.x
+ << " y=" << info.y;
+}
+
+struct find_id : std::unary_function<LayerInfo, bool> {
+ int id;
+ find_id(int id) : id(id) {}
+ bool operator()(LayerInfo const& m) const { return m.id == id; }
+};
+
TEST_P(TransactionTraceTestSuite, validateEndState) {
ASSERT_GT(mActualLayersTraceProto.entry_size(), 0);
ASSERT_GT(mExpectedLayersTraceProto.entry_size(), 0);
@@ -92,19 +123,64 @@
auto actualLastEntry = mActualLayersTraceProto.entry(mActualLayersTraceProto.entry_size() - 1);
EXPECT_EQ(expectedLastEntry.layers().layers_size(), actualLastEntry.layers().layers_size());
- for (int i = 0;
- i < expectedLastEntry.layers().layers_size() && i < actualLastEntry.layers().layers_size();
- i++) {
- auto expectedLayer = expectedLastEntry.layers().layers(i);
- auto actualLayer = actualLastEntry.layers().layers(i);
- EXPECT_EQ(expectedLayer.id(), actualLayer.id());
- EXPECT_EQ(expectedLayer.name(), actualLayer.name());
- EXPECT_EQ(expectedLayer.parent(), actualLayer.parent());
- EXPECT_EQ(expectedLayer.z(), actualLayer.z());
- EXPECT_EQ(expectedLayer.curr_frame(), actualLayer.curr_frame());
- ALOGV("Validating %s[%d] parent=%d z=%d frame=%" PRIu64, expectedLayer.name().c_str(),
- expectedLayer.id(), expectedLayer.parent(), expectedLayer.z(),
- expectedLayer.curr_frame());
+
+ std::vector<LayerInfo> expectedLayers;
+ expectedLayers.reserve(static_cast<size_t>(expectedLastEntry.layers().layers_size()));
+ for (int i = 0; i < expectedLastEntry.layers().layers_size(); i++) {
+ auto layer = expectedLastEntry.layers().layers(i);
+ expectedLayers.push_back({layer.id(), layer.name(), layer.parent(), layer.z(),
+ layer.curr_frame(),
+ layer.has_position() ? layer.position().x() : -1,
+ layer.has_position() ? layer.position().y() : -1});
+ }
+ std::sort(expectedLayers.begin(), expectedLayers.end(), compareById);
+
+ std::vector<LayerInfo> actualLayers;
+ actualLayers.reserve(static_cast<size_t>(actualLastEntry.layers().layers_size()));
+ for (int i = 0; i < actualLastEntry.layers().layers_size(); i++) {
+ auto layer = actualLastEntry.layers().layers(i);
+ actualLayers.push_back({layer.id(), layer.name(), layer.parent(), layer.z(),
+ layer.curr_frame(),
+ layer.has_position() ? layer.position().x() : -1,
+ layer.has_position() ? layer.position().y() : -1});
+ }
+ std::sort(actualLayers.begin(), actualLayers.end(), compareById);
+
+ size_t i = 0;
+ for (; i < actualLayers.size() && i < expectedLayers.size(); i++) {
+ auto it = std::find_if(actualLayers.begin(), actualLayers.end(),
+ find_id(expectedLayers[i].id));
+ EXPECT_NE(it, actualLayers.end());
+ EXPECT_EQ(expectedLayers[i], *it);
+ ALOGV("Validating %s[%d] parent=%d z=%d frame=%" PRIu64, expectedLayers[i].name.c_str(),
+ expectedLayers[i].id, expectedLayers[i].parent, expectedLayers[i].z,
+ expectedLayers[i].curr_frame);
+ }
+
+ EXPECT_EQ(expectedLayers.size(), actualLayers.size());
+
+ if (i < actualLayers.size()) {
+ for (size_t j = 0; j < actualLayers.size(); j++) {
+ if (std::find_if(expectedLayers.begin(), expectedLayers.end(),
+ find_id(actualLayers[j].id)) == expectedLayers.end()) {
+ ALOGD("actualLayers [%d]:%s parent=%d z=%d frame=%" PRIu64, actualLayers[j].id,
+ actualLayers[j].name.c_str(), actualLayers[j].parent, actualLayers[j].z,
+ actualLayers[j].curr_frame);
+ }
+ }
+ FAIL();
+ }
+
+ if (i < expectedLayers.size()) {
+ for (size_t j = 0; j < expectedLayers.size(); j++) {
+ if (std::find_if(actualLayers.begin(), actualLayers.end(),
+ find_id(expectedLayers[j].id)) == actualLayers.end()) {
+ ALOGD("expectedLayers [%d]:%s parent=%d z=%d frame=%" PRIu64, expectedLayers[j].id,
+ expectedLayers[j].name.c_str(), expectedLayers[j].parent, expectedLayers[j].z,
+ expectedLayers[j].curr_frame);
+ }
+ }
+ FAIL();
}
}
diff --git a/services/surfaceflinger/tests/tracing/testdata/layers_trace_nodisplayfound.winscope b/services/surfaceflinger/tests/tracing/testdata/layers_trace_nodisplayfound.winscope
new file mode 100644
index 0000000..16a91ee
--- /dev/null
+++ b/services/surfaceflinger/tests/tracing/testdata/layers_trace_nodisplayfound.winscope
Binary files differ
diff --git a/services/surfaceflinger/tests/tracing/testdata/transactions_trace_nodisplayfound.winscope b/services/surfaceflinger/tests/tracing/testdata/transactions_trace_nodisplayfound.winscope
new file mode 100644
index 0000000..cd62ab8
--- /dev/null
+++ b/services/surfaceflinger/tests/tracing/testdata/transactions_trace_nodisplayfound.winscope
Binary files differ
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index bbfedc7..f6ebfe5 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -37,7 +37,6 @@
#include <system/window.h>
#include <utils/String8.h>
-#include "BufferQueueLayer.h"
#include "ContainerLayer.h"
#include "DisplayRenderArea.h"
#include "EffectLayer.h"
@@ -492,65 +491,31 @@
static constexpr IComposerClient::BlendMode BLENDMODE =
IComposerClient::BlendMode::PREMULTIPLIED;
- static void enqueueBuffer(CompositionTest*, sp<BufferQueueLayer> layer) {
- auto producer = layer->getProducer();
-
- IGraphicBufferProducer::QueueBufferOutput qbo;
- status_t result = producer->connect(nullptr, NATIVE_WINDOW_API_EGL, false, &qbo);
- if (result != NO_ERROR) {
- ALOGE("Failed to connect() (%d)", result);
- return;
- }
-
- int slot;
- sp<Fence> fence;
- result = producer->dequeueBuffer(&slot, &fence, LayerProperties::WIDTH,
- LayerProperties::HEIGHT, LayerProperties::FORMAT,
- LayerProperties::USAGE, nullptr, nullptr);
- if (result != IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) {
- ALOGE("Failed to dequeueBuffer() (%d)", result);
- return;
- }
-
- sp<GraphicBuffer> buffer;
- result = producer->requestBuffer(slot, &buffer);
- if (result != NO_ERROR) {
- ALOGE("Failed to requestBuffer() (%d)", result);
- return;
- }
-
- IGraphicBufferProducer::QueueBufferInput qbi(systemTime(), false /* isAutoTimestamp */,
- LayerProperties::DATASPACE,
- Rect(LayerProperties::WIDTH,
- LayerProperties::HEIGHT),
- LayerProperties::SCALING_MODE,
- LayerProperties::TRANSFORM, Fence::NO_FENCE);
- result = producer->queueBuffer(slot, qbi, &qbo);
- if (result != NO_ERROR) {
- ALOGE("Failed to queueBuffer (%d)", result);
- return;
- }
- }
-
- static void setupLatchedBuffer(CompositionTest* test, sp<BufferQueueLayer> layer) {
- // TODO: Eliminate the complexity of actually creating a buffer
- layer->setSizeForTest(LayerProperties::WIDTH, LayerProperties::HEIGHT);
- status_t err =
- layer->setDefaultBufferProperties(LayerProperties::WIDTH, LayerProperties::HEIGHT,
- LayerProperties::FORMAT);
- ASSERT_EQ(NO_ERROR, err);
+ static void setupLatchedBuffer(CompositionTest* test, sp<BufferStateLayer> layer) {
Mock::VerifyAndClear(test->mRenderEngine);
- EXPECT_CALL(*test->mFlinger.scheduler(), scheduleFrame()).Times(1);
- enqueueBuffer(test, layer);
- Mock::VerifyAndClearExpectations(test->mFlinger.scheduler());
+ const auto buffer = std::make_shared<
+ renderengine::mock::FakeExternalTexture>(LayerProperties::WIDTH,
+ LayerProperties::HEIGHT,
+ DEFAULT_TEXTURE_ID,
+ LayerProperties::FORMAT,
+ LayerProperties::USAGE |
+ GraphicBuffer::USAGE_HW_TEXTURE);
+
+ auto& layerDrawingState = test->mFlinger.mutableLayerDrawingState(layer);
+ layerDrawingState.crop = Rect(0, 0, LayerProperties::HEIGHT, LayerProperties::WIDTH);
+ layerDrawingState.buffer = buffer;
+ layerDrawingState.acquireFence = Fence::NO_FENCE;
+ layerDrawingState.dataspace = ui::Dataspace::UNKNOWN;
+ layer->setSurfaceDamageRegion(
+ Region(Rect(LayerProperties::HEIGHT, LayerProperties::WIDTH)));
bool ignoredRecomputeVisibleRegions;
layer->latchBuffer(ignoredRecomputeVisibleRegions, 0, 0);
Mock::VerifyAndClear(test->mRenderEngine);
}
- static void setupLayerState(CompositionTest* test, sp<BufferQueueLayer> layer) {
+ static void setupLayerState(CompositionTest* test, sp<BufferStateLayer> layer) {
setupLatchedBuffer(test, layer);
}
@@ -664,7 +629,8 @@
EXPECT_EQ(false, layer.source.buffer.isY410BT2020);
EXPECT_EQ(true, layer.source.buffer.usePremultipliedAlpha);
EXPECT_EQ(false, layer.source.buffer.isOpaque);
- EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius);
+ EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius.x);
+ EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius.y);
EXPECT_EQ(ui::Dataspace::UNKNOWN, layer.sourceDataspace);
EXPECT_EQ(LayerProperties::COLOR[3], layer.alpha);
return resultFuture;
@@ -714,7 +680,8 @@
EXPECT_EQ(half3(LayerProperties::COLOR[0], LayerProperties::COLOR[1],
LayerProperties::COLOR[2]),
layer.source.solidColor);
- EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius);
+ EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius.x);
+ EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius.y);
EXPECT_EQ(ui::Dataspace::UNKNOWN, layer.sourceDataspace);
EXPECT_EQ(LayerProperties::COLOR[3], layer.alpha);
return resultFuture;
@@ -736,7 +703,7 @@
using Base = BaseLayerProperties<SidebandLayerProperties>;
static constexpr IComposerClient::BlendMode BLENDMODE = IComposerClient::BlendMode::NONE;
- static void setupLayerState(CompositionTest* test, sp<BufferQueueLayer> layer) {
+ static void setupLayerState(CompositionTest* test, sp<BufferStateLayer> layer) {
sp<NativeHandle> stream =
NativeHandle::create(reinterpret_cast<native_handle_t*>(DEFAULT_SIDEBAND_STREAM),
false);
@@ -792,7 +759,8 @@
const renderengine::LayerSettings layer = layerSettings.back();
EXPECT_THAT(layer.source.buffer.buffer, IsNull());
EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), layer.source.solidColor);
- EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius);
+ EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius.x);
+ EXPECT_EQ(0.0, layer.geometry.roundedCornersRadius.y);
EXPECT_EQ(ui::Dataspace::UNKNOWN, layer.sourceDataspace);
EXPECT_EQ(1.0f, layer.alpha);
return resultFuture;
@@ -818,14 +786,14 @@
struct CursorLayerProperties : public BaseLayerProperties<CursorLayerProperties> {
using Base = BaseLayerProperties<CursorLayerProperties>;
- static void setupLayerState(CompositionTest* test, sp<BufferQueueLayer> layer) {
+ static void setupLayerState(CompositionTest* test, sp<BufferStateLayer> layer) {
Base::setupLayerState(test, layer);
test->mFlinger.setLayerPotentialCursor(layer, true);
}
};
struct NoLayerVariant {
- using FlingerLayerType = sp<BufferQueueLayer>;
+ using FlingerLayerType = sp<BufferStateLayer>;
static FlingerLayerType createLayer(CompositionTest*) { return FlingerLayerType(); }
static void injectLayer(CompositionTest*, FlingerLayerType) {}
@@ -932,17 +900,17 @@
template <typename LayerProperties>
struct BufferLayerVariant : public BaseLayerVariant<LayerProperties> {
using Base = BaseLayerVariant<LayerProperties>;
- using FlingerLayerType = sp<BufferQueueLayer>;
+ using FlingerLayerType = sp<BufferStateLayer>;
static FlingerLayerType createLayer(CompositionTest* test) {
test->mFlinger.mutableTexturePool().push_back(DEFAULT_TEXTURE_ID);
FlingerLayerType layer =
- Base::template createLayerWithFactory<BufferQueueLayer>(test, [test]() {
+ Base::template createLayerWithFactory<BufferStateLayer>(test, [test]() {
LayerCreationArgs args(test->mFlinger.flinger(), sp<Client>(), "test-layer",
LayerProperties::LAYER_FLAGS, LayerMetadata());
args.textureName = test->mFlinger.mutableTexturePool().back();
- return new BufferQueueLayer(args);
+ return new BufferStateLayer(args);
});
LayerProperties::setupLayerState(test, layer);
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index c033af8..7ee04b0 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -72,7 +72,7 @@
public:
MockEventThreadConnection(impl::EventThread* eventThread, uid_t callingUid,
ResyncCallback&& resyncCallback,
- ISurfaceComposer::EventRegistrationFlags eventRegistration)
+ EventRegistrationFlags eventRegistration)
: EventThreadConnection(eventThread, callingUid, std::move(resyncCallback),
eventRegistration) {}
MOCK_METHOD1(postEvent, status_t(const DisplayEventReceiver::Event& event));
@@ -85,10 +85,9 @@
~EventThreadTest() override;
void createThread(std::unique_ptr<VSyncSource>);
- sp<MockEventThreadConnection> createConnection(
- ConnectionEventRecorder& recorder,
- ISurfaceComposer::EventRegistrationFlags eventRegistration = {},
- uid_t ownerUid = mConnectionUid);
+ sp<MockEventThreadConnection> createConnection(ConnectionEventRecorder& recorder,
+ EventRegistrationFlags eventRegistration = {},
+ uid_t ownerUid = mConnectionUid);
void expectVSyncSetEnabledCallReceived(bool expectedState);
void expectVSyncSetDurationCallReceived(std::chrono::nanoseconds expectedDuration,
@@ -149,11 +148,12 @@
.WillRepeatedly(Invoke(mVSyncSetDurationCallRecorder.getInvocable()));
createThread(std::move(vsyncSource));
- mConnection = createConnection(mConnectionEventCallRecorder,
- ISurfaceComposer::EventRegistration::modeChanged |
- ISurfaceComposer::EventRegistration::frameRateOverride);
+ mConnection =
+ createConnection(mConnectionEventCallRecorder,
+ gui::ISurfaceComposer::EventRegistration::modeChanged |
+ gui::ISurfaceComposer::EventRegistration::frameRateOverride);
mThrottledConnection = createConnection(mThrottledConnectionEventCallRecorder,
- ISurfaceComposer::EventRegistration::modeChanged,
+ gui::ISurfaceComposer::EventRegistration::modeChanged,
mThrottledConnectionUid);
// A display must be connected for VSYNC events to be delivered.
@@ -190,8 +190,8 @@
}
sp<EventThreadTest::MockEventThreadConnection> EventThreadTest::createConnection(
- ConnectionEventRecorder& recorder,
- ISurfaceComposer::EventRegistrationFlags eventRegistration, uid_t ownerUid) {
+ ConnectionEventRecorder& recorder, EventRegistrationFlags eventRegistration,
+ uid_t ownerUid) {
sp<MockEventThreadConnection> connection =
new MockEventThreadConnection(mThread.get(), ownerUid,
mResyncCallRecorder.getInvocable(), eventRegistration);
diff --git a/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp b/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp
index bb1f432..3a9b805 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 "BufferQueueLayer.h"
#include "BufferStateLayer.h"
#include "EffectLayer.h"
#include "FpsReporter.h"
@@ -51,6 +50,7 @@
using android::Hwc2::IComposerClient;
using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector;
+using gui::LayerMetadata;
struct TestableFpsListener : public gui::BnFpsListener {
TestableFpsListener() {}
@@ -153,7 +153,7 @@
mParent = createBufferStateLayer();
constexpr int32_t kTaskId = 12;
LayerMetadata targetMetadata;
- targetMetadata.setInt32(METADATA_TASK_ID, kTaskId);
+ targetMetadata.setInt32(gui::METADATA_TASK_ID, kTaskId);
mTarget = createBufferStateLayer(targetMetadata);
mChild = createBufferStateLayer();
mGrandChild = createBufferStateLayer();
@@ -188,7 +188,7 @@
TEST_F(FpsReporterTest, rateLimits) {
const constexpr int32_t kTaskId = 12;
LayerMetadata targetMetadata;
- targetMetadata.setInt32(METADATA_TASK_ID, kTaskId);
+ targetMetadata.setInt32(gui::METADATA_TASK_ID, kTaskId);
mTarget = createBufferStateLayer(targetMetadata);
mFlinger.mutableCurrentState().layersSortedByZ.add(mTarget);
diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
index f1efa92..756db8a 100644
--- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
+++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
@@ -217,9 +217,12 @@
TEST_F(FrameTimelineTest, createSurfaceFrameForToken_expiredToken) {
int64_t token1 = mTokenManager->generateTokenForPredictions({0, 0, 0});
flushTokens();
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = token1;
+ ftInfo.inputEventId = sInputEventId;
auto surfaceFrame =
- mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne,
- sLayerIdOne, sLayerNameOne, sLayerNameOne,
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
/*isBuffer*/ true, sGameMode);
EXPECT_EQ(surfaceFrame->getPredictionState(), PredictionState::Expired);
@@ -227,9 +230,12 @@
TEST_F(FrameTimelineTest, createSurfaceFrameForToken_validToken) {
int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = token1;
+ ftInfo.inputEventId = sInputEventId;
auto surfaceFrame =
- mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne,
- sLayerIdOne, sLayerNameOne, sLayerNameOne,
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
/*isBuffer*/ true, sGameMode);
EXPECT_EQ(surfaceFrame->getPredictionState(), PredictionState::Valid);
@@ -239,9 +245,12 @@
TEST_F(FrameTimelineTest, createSurfaceFrameForToken_validInputEventId) {
int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
constexpr int32_t inputEventId = 1;
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = token1;
+ ftInfo.inputEventId = inputEventId;
auto surfaceFrame =
- mFrameTimeline->createSurfaceFrameForToken({token1, inputEventId}, sPidOne, sUidOne,
- sLayerIdOne, sLayerNameOne, sLayerNameOne,
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
/*isBuffer*/ true, sGameMode);
EXPECT_EQ(inputEventId, surfaceFrame->getInputEventId());
@@ -250,9 +259,12 @@
TEST_F(FrameTimelineTest, presentFenceSignaled_droppedFramesNotUpdated) {
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = token1;
+ ftInfo.inputEventId = sInputEventId;
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne,
- sLayerIdOne, sLayerNameOne, sLayerNameOne,
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
/*isBuffer*/ true, sGameMode);
// Set up the display frame
@@ -278,14 +290,17 @@
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 30});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = surfaceFrameToken1;
+ ftInfo.inputEventId = sInputEventId;
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
- sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
auto surfaceFrame2 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
- sUidOne, sLayerIdTwo, sLayerNameTwo,
- sLayerNameTwo, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdTwo,
+ sLayerNameTwo, sLayerNameTwo,
+ /*isBuffer*/ true, sGameMode);
mFrameTimeline->setSfWakeUp(sfToken1, 22, Fps::fromPeriodNsecs(11));
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame1);
@@ -324,9 +339,11 @@
{10 + frameTimeFactor, 20 + frameTimeFactor, 30 + frameTimeFactor});
int64_t sfToken = mTokenManager->generateTokenForPredictions(
{22 + frameTimeFactor, 26 + frameTimeFactor, 30 + frameTimeFactor});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = surfaceFrameToken;
+ ftInfo.inputEventId = sInputEventId;
auto surfaceFrame =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId},
- sPidOne, sUidOne, sLayerIdOne,
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
sLayerNameOne, sLayerNameOne,
/*isBuffer*/ true, sGameMode);
mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor, Fps::fromPeriodNsecs(11));
@@ -347,10 +364,13 @@
{10 + frameTimeFactor, 20 + frameTimeFactor, 30 + frameTimeFactor});
int64_t sfToken = mTokenManager->generateTokenForPredictions(
{22 + frameTimeFactor, 26 + frameTimeFactor, 30 + frameTimeFactor});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = surfaceFrameToken;
+ ftInfo.inputEventId = sInputEventId;
auto surfaceFrame =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, sPidOne,
- sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor, Fps::fromPeriodNsecs(11));
surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame);
@@ -442,11 +462,14 @@
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({10, 20, 60});
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({52, 60, 60});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = surfaceFrameToken1;
+ ftInfo.inputEventId = sInputEventId;
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
- sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate);
surfaceFrame1->setAcquireFenceTime(20);
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -470,11 +493,14 @@
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t surfaceFrameToken1 = -1;
int64_t sfToken1 = -1;
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = surfaceFrameToken1;
+ ftInfo.inputEventId = sInputEventId;
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
- sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate);
surfaceFrame1->setAcquireFenceTime(20);
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -495,11 +521,14 @@
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({10, 20, 60});
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({52, 60, 60});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = surfaceFrameToken1;
+ ftInfo.inputEventId = sInputEventId;
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
- sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate);
surfaceFrame1->setAcquireFenceTime(20);
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -521,11 +550,14 @@
auto gpuFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({10, 20, 60});
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({52, 60, 60});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = surfaceFrameToken1;
+ ftInfo.inputEventId = sInputEventId;
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
- sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate);
surfaceFrame1->setAcquireFenceTime(20);
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -546,11 +578,14 @@
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({10, 20, 60});
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({52, 60, 60});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = surfaceFrameToken1;
+ ftInfo.inputEventId = sInputEventId;
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
- sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate);
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
surfaceFrame1->setAcquireFenceTime(20);
@@ -570,11 +605,14 @@
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({10, 20, 60});
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({82, 90, 90});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = surfaceFrameToken1;
+ ftInfo.inputEventId = sInputEventId;
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
- sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
surfaceFrame1->setAcquireFenceTime(45);
mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate);
@@ -596,11 +634,14 @@
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({40, 60, 92});
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({52, 60, 60});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = surfaceFrameToken1;
+ ftInfo.inputEventId = sInputEventId;
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
- sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
surfaceFrame1->setAcquireFenceTime(50);
mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate);
@@ -622,11 +663,14 @@
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({30, 40, 60});
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({52, 60, 60});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = surfaceFrameToken1;
+ ftInfo.inputEventId = sInputEventId;
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
- sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
surfaceFrame1->setAcquireFenceTime(40);
mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate);
@@ -648,11 +692,14 @@
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({30, 40, 58});
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({82, 90, 90});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = surfaceFrameToken1;
+ ftInfo.inputEventId = sInputEventId;
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
- sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
surfaceFrame1->setAcquireFenceTime(40);
mFrameTimeline->setSfWakeUp(sfToken1, 82, refreshRate);
@@ -676,11 +723,14 @@
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({10, 20, 60});
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({82, 90, 90});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = surfaceFrameToken1;
+ ftInfo.inputEventId = sInputEventId;
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
- sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
surfaceFrame1->setAcquireFenceTime(45);
mFrameTimeline->setSfWakeUp(sfToken1, 52, refreshRate);
@@ -706,11 +756,14 @@
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({10, 20, 60});
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({82, 90, 90});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = surfaceFrameToken1;
+ ftInfo.inputEventId = sInputEventId;
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
- sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
surfaceFrame1->setAcquireFenceTime(45);
// Trigger a prediction expiry
flushTokens();
@@ -744,9 +797,12 @@
auto tracingSession = getTracingSessionForTest();
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = token1;
+ ftInfo.inputEventId = sInputEventId;
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne,
- sLayerIdOne, sLayerNameOne, sLayerNameOne,
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
/*isBuffer*/ true, sGameMode);
// Set up the display frame
@@ -771,9 +827,12 @@
tracingSession->StartBlocking();
int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
int64_t token2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = token1;
+ ftInfo.inputEventId = sInputEventId;
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne,
- sLayerIdOne, sLayerNameOne, sLayerNameOne,
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
/*isBuffer*/ true, sGameMode);
// Set up the display frame
@@ -1133,14 +1192,18 @@
int64_t surfaceFrameToken = mTokenManager->generateTokenForPredictions({10, 25, 40});
int64_t displayFrameToken1 = mTokenManager->generateTokenForPredictions({30, 35, 40});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = surfaceFrameToken;
+ ftInfo.inputEventId = sInputEventId;
+
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, sPidOne,
- sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
auto surfaceFrame2 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, sPidOne,
- sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
surfaceFrame1->setActualQueueTime(10);
surfaceFrame1->setDropTime(15);
@@ -1293,10 +1356,13 @@
// Flush the token so that it would expire
flushTokens();
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = surfaceFrameToken;
+ ftInfo.inputEventId = 0;
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, /*inputEventId*/ 0},
- sPidOne, sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
surfaceFrame1->setActualQueueTime(appEndTime);
surfaceFrame1->setAcquireFenceTime(appEndTime);
@@ -1369,10 +1435,13 @@
// Flush the token so that it would expire
flushTokens();
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = surfaceFrameToken;
+ ftInfo.inputEventId = 0;
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, /*inputEventId*/ 0},
- sPidOne, sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
constexpr nsecs_t sfStartTime = std::chrono::nanoseconds(22ms).count();
constexpr nsecs_t sfEndTime = std::chrono::nanoseconds(30ms).count();
@@ -1438,10 +1507,13 @@
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t surfaceFrameToken = mTokenManager->generateTokenForPredictions({10, 20, 30});
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 30, 30});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = surfaceFrameToken;
+ ftInfo.inputEventId = sInputEventId;
auto surfaceFrame =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, sPidOne,
- sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
mFrameTimeline->setSfWakeUp(sfToken1, 22, Fps::fromPeriodNsecs(11));
surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame);
@@ -1654,10 +1726,13 @@
int64_t sfToken2 = mTokenManager->generateTokenForPredictions({52, 60, 70});
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({5, 16, 40});
int64_t surfaceFrameToken2 = mTokenManager->generateTokenForPredictions({25, 36, 70});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = surfaceFrameToken1;
+ ftInfo.inputEventId = sInputEventId;
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
- sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
surfaceFrame1->setAcquireFenceTime(16);
mFrameTimeline->setSfWakeUp(sfToken1, 22, Fps::fromPeriodNsecs(11));
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1674,10 +1749,13 @@
// Trigger a flush by finalizing the next DisplayFrame
auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+ FrameTimelineInfo ftInfo2;
+ ftInfo2.vsyncId = surfaceFrameToken2;
+ ftInfo2.inputEventId = sInputEventId;
auto surfaceFrame2 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne,
- sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo2, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
surfaceFrame2->setAcquireFenceTime(36);
mFrameTimeline->setSfWakeUp(sfToken2, 52, Fps::fromPeriodNsecs(11));
surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1734,10 +1812,13 @@
int64_t sfToken2 = mTokenManager->generateTokenForPredictions({52, 60, 70});
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({5, 16, 40});
int64_t surfaceFrameToken2 = mTokenManager->generateTokenForPredictions({25, 36, 70});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = surfaceFrameToken1;
+ ftInfo.inputEventId = sInputEventId;
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
- sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
surfaceFrame1->setAcquireFenceTime(16);
mFrameTimeline->setSfWakeUp(sfToken1, 22, Fps::fromPeriodNsecs(11));
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1754,10 +1835,13 @@
// Trigger a flush by finalizing the next DisplayFrame
auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+ FrameTimelineInfo ftInfo2;
+ ftInfo2.vsyncId = surfaceFrameToken2;
+ ftInfo2.inputEventId = sInputEventId;
auto surfaceFrame2 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne,
- sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo2, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
surfaceFrame2->setAcquireFenceTime(36);
mFrameTimeline->setSfWakeUp(sfToken2, 52, Fps::fromPeriodNsecs(11));
surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1813,10 +1897,13 @@
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({42, 50, 50});
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({5, 26, 60});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = surfaceFrameToken1;
+ ftInfo.inputEventId = sInputEventId;
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
- sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
surfaceFrame1->setAcquireFenceTime(40);
mFrameTimeline->setSfWakeUp(sfToken1, 42, Fps::fromPeriodNsecs(11));
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1857,10 +1944,13 @@
int64_t sfToken2 = mTokenManager->generateTokenForPredictions({42, 50, 50});
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({5, 16, 30});
int64_t surfaceFrameToken2 = mTokenManager->generateTokenForPredictions({25, 36, 50});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = surfaceFrameToken1;
+ ftInfo.inputEventId = sInputEventId;
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
- sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
surfaceFrame1->setAcquireFenceTime(26);
mFrameTimeline->setSfWakeUp(sfToken1, 32, Fps::fromPeriodNsecs(11));
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1877,10 +1967,13 @@
// Trigger a flush by finalizing the next DisplayFrame
auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+ FrameTimelineInfo ftInfo2;
+ ftInfo2.vsyncId = surfaceFrameToken2;
+ ftInfo2.inputEventId = sInputEventId;
auto surfaceFrame2 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne,
- sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo2, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
surfaceFrame2->setAcquireFenceTime(40);
mFrameTimeline->setSfWakeUp(sfToken2, 43, Fps::fromPeriodNsecs(11));
surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1932,10 +2025,13 @@
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({52, 60, 60});
int64_t sfToken2 = mTokenManager->generateTokenForPredictions({112, 120, 120});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = surfaceFrameToken1;
+ ftInfo.inputEventId = sInputEventId;
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
- sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
surfaceFrame1->setAcquireFenceTime(50);
mFrameTimeline->setSfWakeUp(sfToken1, 52, Fps::fromPeriodNsecs(30));
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1952,10 +2048,13 @@
// Trigger a flush by finalizing the next DisplayFrame
auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+ FrameTimelineInfo ftInfo2;
+ ftInfo2.vsyncId = surfaceFrameToken2;
+ ftInfo2.inputEventId = sInputEventId;
auto surfaceFrame2 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne,
- sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo2, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
surfaceFrame2->setAcquireFenceTime(84);
mFrameTimeline->setSfWakeUp(sfToken2, 112, Fps::fromPeriodNsecs(30));
surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented, 54);
@@ -2010,10 +2109,13 @@
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({52, 60, 60});
int64_t sfToken2 = mTokenManager->generateTokenForPredictions({82, 90, 90});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = surfaceFrameToken1;
+ ftInfo.inputEventId = sInputEventId;
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
- sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
surfaceFrame1->setAcquireFenceTime(50);
mFrameTimeline->setSfWakeUp(sfToken1, 52, Fps::fromPeriodNsecs(30));
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -2030,10 +2132,13 @@
// Trigger a flush by finalizing the next DisplayFrame
auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+ FrameTimelineInfo ftInfo2;
+ ftInfo2.vsyncId = surfaceFrameToken2;
+ ftInfo2.inputEventId = sInputEventId;
auto surfaceFrame2 =
- mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne,
- sUidOne, sLayerIdOne, sLayerNameOne,
- sLayerNameOne, /*isBuffer*/ true, sGameMode);
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo2, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
surfaceFrame2->setAcquireFenceTime(80);
mFrameTimeline->setSfWakeUp(sfToken2, 82, Fps::fromPeriodNsecs(30));
// Setting previous latch time to 54, adjusted deadline will be 54 + vsyncTime(30) = 84
@@ -2237,4 +2342,38 @@
EXPECT_EQ(mFrameTimeline->computeFps({sLayerIdOne}), 5.0f);
}
+TEST_F(FrameTimelineTest, getMinTime) {
+ // Use SurfaceFrame::getBaseTime to test the getMinTime.
+ FrameTimelineInfo ftInfo;
+
+ // Valid prediction state test.
+ ftInfo.vsyncId = 0L;
+ mTokenManager->generateTokenForPredictions({10});
+ auto surfaceFrame =
+ mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
+ ASSERT_EQ(surfaceFrame->getBaseTime(), 10);
+
+ // Test prediction state which is not valid.
+ ftInfo.vsyncId = FrameTimelineInfo::INVALID_VSYNC_ID;
+ surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(ftInfo, sPidOne, sUidOne, sLayerIdOne,
+ sLayerNameOne, sLayerNameOne,
+ /*isBuffer*/ true, sGameMode);
+ // Start time test.
+ surfaceFrame->setActualStartTime(200);
+ ASSERT_EQ(surfaceFrame->getBaseTime(), 200);
+
+ // End time test.
+ surfaceFrame->setAcquireFenceTime(100);
+ ASSERT_EQ(surfaceFrame->getBaseTime(), 100);
+
+ // Present time test.
+ auto presentFence = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+ surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented);
+ mFrameTimeline->addSurfaceFrame(surfaceFrame);
+ presentFence->signalForTest(std::chrono::nanoseconds(50ns).count());
+ mFrameTimeline->setSfPresent(50, presentFence);
+ ASSERT_EQ(surfaceFrame->getBaseTime(), 50);
+}
} // namespace android::frametimeline
diff --git a/services/surfaceflinger/tests/unittests/GameModeTest.cpp b/services/surfaceflinger/tests/unittests/GameModeTest.cpp
index 981ca1d..b79909a 100644
--- a/services/surfaceflinger/tests/unittests/GameModeTest.cpp
+++ b/services/surfaceflinger/tests/unittests/GameModeTest.cpp
@@ -34,6 +34,8 @@
using testing::Mock;
using testing::Return;
using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector;
+using gui::GameMode;
+using gui::LayerMetadata;
class GameModeTest : public testing::Test {
public:
@@ -92,7 +94,7 @@
// Mocks the behavior of applying a transaction from WMShell
void setGameModeMetadata(sp<Layer> layer, GameMode gameMode) {
- mLayerMetadata.setInt32(METADATA_GAME_MODE, static_cast<int32_t>(gameMode));
+ mLayerMetadata.setInt32(gui::METADATA_GAME_MODE, static_cast<int32_t>(gameMode));
layer->setMetadata(mLayerMetadata);
layer->setGameModeForTree(gameMode);
}
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
index 17511cd..972198c 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
@@ -141,6 +141,54 @@
namespace {
+TEST_F(LayerHistoryTest, singleLayerNoVoteDefaultCompatibility) {
+ const auto layer = createLayer();
+ EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true));
+ EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate()));
+ EXPECT_CALL(*layer, getDefaultFrameRateCompatibility())
+ .WillOnce(Return(LayerInfo::FrameRateCompatibility::NoVote));
+
+ EXPECT_EQ(1, layerCount());
+ EXPECT_EQ(0, activeLayerCount());
+
+ nsecs_t time = systemTime();
+
+ // No layers returned if no layers are active.
+ EXPECT_TRUE(summarizeLayerHistory(time).empty());
+ EXPECT_EQ(0, activeLayerCount());
+
+ history().record(layer.get(), 0, time, LayerHistory::LayerUpdateType::Buffer);
+ history().setDefaultFrameRateCompatibility(layer.get(), true /* contentDetectionEnabled */);
+
+ EXPECT_TRUE(summarizeLayerHistory(time).empty());
+ EXPECT_EQ(1, activeLayerCount());
+}
+
+TEST_F(LayerHistoryTest, singleLayerMinVoteDefaultCompatibility) {
+ const auto layer = createLayer();
+ EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true));
+ EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate()));
+ EXPECT_CALL(*layer, getDefaultFrameRateCompatibility())
+ .WillOnce(Return(LayerInfo::FrameRateCompatibility::Min));
+
+ EXPECT_EQ(1, layerCount());
+ EXPECT_EQ(0, activeLayerCount());
+
+ nsecs_t time = systemTime();
+
+ EXPECT_TRUE(summarizeLayerHistory(time).empty());
+ EXPECT_EQ(0, activeLayerCount());
+
+ history().record(layer.get(), 0, time, LayerHistory::LayerUpdateType::Buffer);
+ history().setDefaultFrameRateCompatibility(layer.get(), true /* contentDetectionEnabled */);
+
+ auto summary = summarizeLayerHistory(time);
+ ASSERT_EQ(1, summarizeLayerHistory(time).size());
+
+ EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote);
+ EXPECT_EQ(1, activeLayerCount());
+}
+
TEST_F(LayerHistoryTest, oneLayer) {
const auto layer = createLayer();
EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true));
diff --git a/services/surfaceflinger/tests/unittests/LayerMetadataTest.cpp b/services/surfaceflinger/tests/unittests/LayerMetadataTest.cpp
index 373fd74..e6e02c1 100644
--- a/services/surfaceflinger/tests/unittests/LayerMetadataTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerMetadataTest.cpp
@@ -27,6 +27,8 @@
#include <gui/LayerMetadata.h>
#include <log/log.h>
+using android::gui::LayerMetadata;
+
namespace android {
namespace {
@@ -113,4 +115,4 @@
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wextra"
\ No newline at end of file
+#pragma clang diagnostic pop // ignored "-Wextra"
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_OnInitializeDisplaysTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_OnInitializeDisplaysTest.cpp
index 37cf05e..3d576f4 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_OnInitializeDisplaysTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_OnInitializeDisplaysTest.cpp
@@ -85,12 +85,6 @@
// The display transaction needed flag should be set.
EXPECT_TRUE(hasTransactionFlagSet(eDisplayTransactionNeeded));
-
- // The compositor timing should be set to default values
- const auto& compositorTiming = mFlinger.getCompositorTiming();
- EXPECT_EQ(-DEFAULT_VSYNC_PERIOD, compositorTiming.deadline);
- EXPECT_EQ(DEFAULT_VSYNC_PERIOD, compositorTiming.interval);
- EXPECT_EQ(DEFAULT_VSYNC_PERIOD, compositorTiming.presentLatency);
}
} // namespace
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index b70fdcd..60285f9 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -29,7 +29,6 @@
#include <compositionengine/mock/DisplaySurface.h>
#include <gui/ScreenCaptureResults.h>
-#include "BufferQueueLayer.h"
#include "BufferStateLayer.h"
#include "ContainerLayer.h"
#include "DisplayDevice.h"
@@ -112,18 +111,6 @@
mCreateBufferQueue(outProducer, outConsumer, consumerIsSurfaceFlinger);
}
- sp<IGraphicBufferProducer> createMonitoredProducer(const sp<IGraphicBufferProducer>& producer,
- const sp<SurfaceFlinger>& flinger,
- const wp<Layer>& layer) override {
- return new MonitoredProducer(producer, flinger, layer);
- }
-
- sp<BufferLayerConsumer> createBufferLayerConsumer(const sp<IGraphicBufferConsumer>& consumer,
- renderengine::RenderEngine& renderEngine,
- uint32_t textureName, Layer* layer) override {
- return new BufferLayerConsumer(consumer, renderEngine, textureName, layer);
- }
-
std::unique_ptr<surfaceflinger::NativeWindowSurface> createNativeWindowSurface(
const sp<IGraphicBufferProducer>& producer) override {
if (!mCreateNativeWindowSurface) return nullptr;
@@ -134,10 +121,6 @@
return compositionengine::impl::createCompositionEngine();
}
- sp<BufferQueueLayer> createBufferQueueLayer(const LayerCreationArgs&) override {
- return nullptr;
- }
-
sp<BufferStateLayer> createBufferStateLayer(const LayerCreationArgs&) override {
return nullptr;
}
@@ -460,7 +443,7 @@
return mFlinger->onTransact(code, data, reply, flags);
}
- auto getGPUContextPriority() { return mFlinger->getGPUContextPriority(); }
+ auto getGpuContextPriority() { return mFlinger->getGpuContextPriority(); }
auto calculateMaxAcquiredBufferCount(Fps refreshRate,
std::chrono::nanoseconds presentLatency) const {
@@ -506,8 +489,6 @@
}
auto& getCompositionEngine() const { return mFlinger->getCompositionEngine(); }
- const auto& getCompositorTiming() const { return mFlinger->getBE().mCompositorTiming; }
-
mock::FrameTracer* getFrameTracer() const {
return static_cast<mock::FrameTracer*>(mFlinger->mFrameTracer.get());
}
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index ded7531..84f1170 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -107,22 +107,20 @@
EXPECT_EQ(info.desiredPresentTime, state.desiredPresentTime);
}
- void setupSingle(TransactionInfo& transaction, uint32_t flags, bool syncInputWindows,
- int64_t desiredPresentTime, bool isAutoTimestamp,
- const FrameTimelineInfo& frameTimelineInfo) {
+ void setupSingle(TransactionInfo& transaction, uint32_t flags, int64_t desiredPresentTime,
+ bool isAutoTimestamp, const FrameTimelineInfo& frameTimelineInfo) {
mTransactionNumber++;
transaction.flags |= flags; // ISurfaceComposer::eSynchronous;
- transaction.inputWindowCommands.syncInputWindows = syncInputWindows;
transaction.desiredPresentTime = desiredPresentTime;
transaction.isAutoTimestamp = isAutoTimestamp;
transaction.frameTimelineInfo = frameTimelineInfo;
}
- void NotPlacedOnTransactionQueue(uint32_t flags, bool syncInputWindows) {
+ void NotPlacedOnTransactionQueue(uint32_t flags) {
ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
TransactionInfo transaction;
- setupSingle(transaction, flags, syncInputWindows,
+ setupSingle(transaction, flags,
/*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true,
FrameTimelineInfo{});
nsecs_t applicationTime = systemTime();
@@ -133,12 +131,10 @@
transaction.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
transaction.id);
- // If transaction is synchronous or syncs input windows, SF
- // applyTransactionState should time out (5s) wating for SF to commit
- // the transaction or to receive a signal that syncInputWindows has
- // completed. If this is animation, it should not time out waiting.
+ // If transaction is synchronous, SF applyTransactionState should time out (5s) wating for
+ // SF to commit the transaction. If this is animation, it should not time out waiting.
nsecs_t returnedTime = systemTime();
- if (flags & ISurfaceComposer::eSynchronous || syncInputWindows) {
+ if (flags & ISurfaceComposer::eSynchronous) {
EXPECT_GE(returnedTime, applicationTime + mFlinger.getAnimationTransactionTimeout());
} else {
EXPECT_LE(returnedTime, applicationTime + mFlinger.getAnimationTransactionTimeout());
@@ -148,7 +144,7 @@
EXPECT_EQ(1u, transactionQueue.size());
}
- void PlaceOnTransactionQueue(uint32_t flags, bool syncInputWindows) {
+ void PlaceOnTransactionQueue(uint32_t flags) {
ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
@@ -156,8 +152,8 @@
// but afterwards it will look like the desired present time has passed
nsecs_t time = systemTime();
TransactionInfo transaction;
- setupSingle(transaction, flags, syncInputWindows,
- /*desiredPresentTime*/ time + s2ns(1), false, FrameTimelineInfo{});
+ setupSingle(transaction, flags, /*desiredPresentTime*/ time + s2ns(1), false,
+ FrameTimelineInfo{});
nsecs_t applicationSentTime = systemTime();
mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states,
transaction.displays, transaction.flags,
@@ -167,7 +163,7 @@
transaction.id);
nsecs_t returnedTime = systemTime();
- if ((flags & ISurfaceComposer::eSynchronous) || syncInputWindows) {
+ if (flags & ISurfaceComposer::eSynchronous) {
EXPECT_GE(systemTime(),
applicationSentTime + mFlinger.getAnimationTransactionTimeout());
} else {
@@ -179,25 +175,21 @@
EXPECT_EQ(1u, transactionQueue.size());
}
- void BlockedByPriorTransaction(uint32_t flags, bool syncInputWindows) {
+ void BlockedByPriorTransaction(uint32_t flags) {
ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
nsecs_t time = systemTime();
- if (!syncInputWindows) {
- EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(2);
- } else {
- EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
- }
+ EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(2);
+
// transaction that should go on the pending thread
TransactionInfo transactionA;
- setupSingle(transactionA, /*flags*/ 0, /*syncInputWindows*/ false,
- /*desiredPresentTime*/ time + s2ns(1), false, FrameTimelineInfo{});
+ setupSingle(transactionA, /*flags*/ 0, /*desiredPresentTime*/ time + s2ns(1), false,
+ FrameTimelineInfo{});
// transaction that would not have gone on the pending thread if not
// blocked
TransactionInfo transactionB;
- setupSingle(transactionB, flags, syncInputWindows,
- /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true,
- FrameTimelineInfo{});
+ setupSingle(transactionB, flags, /*desiredPresentTime*/ systemTime(),
+ /*isAutoTimestamp*/ true, FrameTimelineInfo{});
nsecs_t applicationSentTime = systemTime();
mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states,
@@ -226,8 +218,7 @@
// if this is an animation, this thread should be blocked for 5s
// in setTransactionState waiting for transactionA to flush. Otherwise,
// the transaction should be placed on the pending queue
- if (flags & (ISurfaceComposer::eSynchronous) ||
- syncInputWindows) {
+ if (flags & ISurfaceComposer::eSynchronous) {
EXPECT_GE(systemTime(),
applicationSentTime + mFlinger.getAnimationTransactionTimeout());
} else {
@@ -253,8 +244,8 @@
EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1);
TransactionInfo transactionA; // transaction to go on pending queue
- setupSingle(transactionA, /*flags*/ 0, /*syncInputWindows*/ false,
- /*desiredPresentTime*/ s2ns(1), false, FrameTimelineInfo{});
+ setupSingle(transactionA, /*flags*/ 0, /*desiredPresentTime*/ s2ns(1), false,
+ FrameTimelineInfo{});
mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states,
transactionA.displays, transactionA.flags, transactionA.applyToken,
transactionA.inputWindowCommands, transactionA.desiredPresentTime,
@@ -285,31 +276,23 @@
}
TEST_F(TransactionApplicationTest, NotPlacedOnTransactionQueue_Synchronous) {
- NotPlacedOnTransactionQueue(ISurfaceComposer::eSynchronous, /*syncInputWindows*/ false);
+ NotPlacedOnTransactionQueue(ISurfaceComposer::eSynchronous);
}
TEST_F(TransactionApplicationTest, NotPlacedOnTransactionQueue_SyncInputWindows) {
- NotPlacedOnTransactionQueue(/*flags*/ 0, /*syncInputWindows*/ true);
+ NotPlacedOnTransactionQueue(/*flags*/ 0);
}
TEST_F(TransactionApplicationTest, PlaceOnTransactionQueue_Synchronous) {
- PlaceOnTransactionQueue(ISurfaceComposer::eSynchronous, /*syncInputWindows*/ false);
+ PlaceOnTransactionQueue(ISurfaceComposer::eSynchronous);
}
TEST_F(TransactionApplicationTest, PlaceOnTransactionQueue_SyncInputWindows) {
- PlaceOnTransactionQueue(/*flags*/ 0, /*syncInputWindows*/ true);
+ PlaceOnTransactionQueue(/*flags*/ 0);
}
TEST_F(TransactionApplicationTest, BlockWithPriorTransaction_Synchronous) {
- BlockedByPriorTransaction(ISurfaceComposer::eSynchronous, /*syncInputWindows*/ false);
-}
-
-TEST_F(TransactionApplicationTest, BlockWithPriorTransaction_Animation) {
- BlockedByPriorTransaction(ISurfaceComposer::eSynchronous, /*syncInputWindows*/ false);
-}
-
-TEST_F(TransactionApplicationTest, BlockWithPriorTransaction_SyncInputWindows) {
- BlockedByPriorTransaction(/*flags*/ 0, /*syncInputWindows*/ true);
+ BlockedByPriorTransaction(ISurfaceComposer::eSynchronous);
}
TEST_F(TransactionApplicationTest, FromHandle) {
@@ -359,13 +342,11 @@
const std::vector<ComposerState>& states) {
TransactionInfo transaction;
const uint32_t kFlags = ISurfaceComposer::eSynchronous;
- const bool kSyncInputWindows = false;
const nsecs_t kDesiredPresentTime = systemTime();
const bool kIsAutoTimestamp = true;
const auto kFrameTimelineInfo = FrameTimelineInfo{};
- setupSingle(transaction, kFlags, kSyncInputWindows, kDesiredPresentTime, kIsAutoTimestamp,
- kFrameTimelineInfo);
+ setupSingle(transaction, kFlags, kDesiredPresentTime, kIsAutoTimestamp, kFrameTimelineInfo);
transaction.applyToken = applyToken;
for (const auto& state : states) {
transaction.states.push_back(state);
diff --git a/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp b/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp
index f5e3b77..669fa3a 100644
--- a/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionProtoParserTest.cpp
@@ -49,8 +49,7 @@
ComposerState s;
if (i == 1) {
layer.parentSurfaceControlForChild =
- new SurfaceControl(SurfaceComposerClient::getDefault(), layerHandle, nullptr,
- 42);
+ new SurfaceControl(SurfaceComposerClient::getDefault(), layerHandle, 42);
}
s.state = layer;
t1.states.add(s);
diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
index 5bb4c92..6d58303 100644
--- a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
@@ -100,8 +100,10 @@
void PresentedSurfaceFrameForBufferlessTransaction() {
sp<BufferStateLayer> layer = createBufferStateLayer();
- layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0},
- 10);
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = 1;
+ ftInfo.inputEventId = 0;
+ layer->setFrameTimelineVsyncForBufferlessTransaction(ftInfo, 10);
EXPECT_EQ(1u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
ASSERT_TRUE(layer->mDrawingState.bufferSurfaceFrameTX == nullptr);
const auto surfaceFrame = layer->mDrawingState.bufferlessSurfaceFramesTX.at(/*token*/ 1);
@@ -125,8 +127,10 @@
1ULL /* bufferId */,
HAL_PIXEL_FORMAT_RGBA_8888,
0ULL /*usage*/);
- layer->setBuffer(externalTexture, bufferData, 10, 20, false, std::nullopt,
- {/*vsyncId*/ 1, /*inputEventId*/ 0});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = 1;
+ ftInfo.inputEventId = 0;
+ layer->setBuffer(externalTexture, bufferData, 10, 20, false, std::nullopt, ftInfo);
acquireFence->signalForTest(12);
commitTransaction(layer.get());
@@ -159,8 +163,10 @@
1ULL /* bufferId */,
HAL_PIXEL_FORMAT_RGBA_8888,
0ULL /*usage*/);
- layer->setBuffer(externalTexture1, bufferData, 10, 20, false, std::nullopt,
- {/*vsyncId*/ 1, /*inputEventId*/ 0});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = 1;
+ ftInfo.inputEventId = 0;
+ layer->setBuffer(externalTexture1, bufferData, 10, 20, false, std::nullopt, ftInfo);
EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
const auto droppedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX;
@@ -177,8 +183,7 @@
2ULL /* bufferId */,
HAL_PIXEL_FORMAT_RGBA_8888,
0ULL /*usage*/);
- layer->setBuffer(externalTexture2, bufferData, 10, 20, false, std::nullopt,
- {/*vsyncId*/ 1, /*inputEventId*/ 0});
+ layer->setBuffer(externalTexture2, bufferData, 10, 20, false, std::nullopt, ftInfo);
nsecs_t end = systemTime();
acquireFence2->signalForTest(12);
@@ -204,9 +209,11 @@
void BufferlessSurfaceFramePromotedToBufferSurfaceFrame() {
sp<BufferStateLayer> layer = createBufferStateLayer();
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = 1;
+ ftInfo.inputEventId = 0;
- layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0},
- 10);
+ layer->setFrameTimelineVsyncForBufferlessTransaction(ftInfo, 10);
EXPECT_EQ(1u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
ASSERT_EQ(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
@@ -223,8 +230,7 @@
1ULL /* bufferId */,
HAL_PIXEL_FORMAT_RGBA_8888,
0ULL /*usage*/);
- layer->setBuffer(externalTexture, bufferData, 10, 20, false, std::nullopt,
- {/*vsyncId*/ 1, /*inputEventId*/ 0});
+ layer->setBuffer(externalTexture, bufferData, 10, 20, false, std::nullopt, ftInfo);
acquireFence->signalForTest(12);
EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
@@ -257,28 +263,33 @@
1ULL /* bufferId */,
HAL_PIXEL_FORMAT_RGBA_8888,
0ULL /*usage*/);
- layer->setBuffer(externalTexture, bufferData, 10, 20, false, std::nullopt,
- {/*vsyncId*/ 1, /*inputEventId*/ 0});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = 1;
+ ftInfo.inputEventId = 0;
+ layer->setBuffer(externalTexture, bufferData, 10, 20, false, std::nullopt, ftInfo);
EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
- layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0},
- 10);
+ layer->setFrameTimelineVsyncForBufferlessTransaction(ftInfo, 10);
EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
}
void MultipleSurfaceFramesPresentedTogether() {
sp<BufferStateLayer> layer = createBufferStateLayer();
- layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0},
- 10);
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = 1;
+ ftInfo.inputEventId = 0;
+ layer->setFrameTimelineVsyncForBufferlessTransaction(ftInfo, 10);
EXPECT_EQ(1u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
ASSERT_EQ(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
const auto bufferlessSurfaceFrame1 =
layer->mDrawingState.bufferlessSurfaceFramesTX.at(/*token*/ 1);
- layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 4, /*inputEventId*/ 0},
- 10);
+ FrameTimelineInfo ftInfo2;
+ ftInfo2.vsyncId = 4;
+ ftInfo2.inputEventId = 0;
+ layer->setFrameTimelineVsyncForBufferlessTransaction(ftInfo2, 10);
EXPECT_EQ(2u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
ASSERT_EQ(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
const auto bufferlessSurfaceFrame2 = layer->mDrawingState.bufferlessSurfaceFramesTX[4];
@@ -295,8 +306,10 @@
1ULL /* bufferId */,
HAL_PIXEL_FORMAT_RGBA_8888,
0ULL /*usage*/);
- layer->setBuffer(externalTexture, bufferData, 10, 20, false, std::nullopt,
- {/*vsyncId*/ 3, /*inputEventId*/ 0});
+ FrameTimelineInfo ftInfo3;
+ ftInfo3.vsyncId = 3;
+ ftInfo3.inputEventId = 0;
+ layer->setBuffer(externalTexture, bufferData, 10, 20, false, std::nullopt, ftInfo3);
EXPECT_EQ(2u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
const auto bufferSurfaceFrameTX = layer->mDrawingState.bufferSurfaceFrameTX;
@@ -339,8 +352,10 @@
1ULL /* bufferId */,
HAL_PIXEL_FORMAT_RGBA_8888,
0ULL /*usage*/);
- layer->setBuffer(externalTexture1, bufferData, 10, 20, false, std::nullopt,
- {/*vsyncId*/ 1, /*inputEventId*/ 0});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = 1;
+ ftInfo.inputEventId = 0;
+ layer->setBuffer(externalTexture1, bufferData, 10, 20, false, std::nullopt, ftInfo);
ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
const auto droppedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX;
@@ -355,8 +370,7 @@
1ULL /* bufferId */,
HAL_PIXEL_FORMAT_RGBA_8888,
0ULL /*usage*/);
- layer->setBuffer(externalTexture2, bufferData, 10, 20, false, std::nullopt,
- {/*vsyncId*/ 1, /*inputEventId*/ 0});
+ layer->setBuffer(externalTexture2, bufferData, 10, 20, false, std::nullopt, ftInfo);
acquireFence2->signalForTest(12);
ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
@@ -391,8 +405,10 @@
1ULL /* bufferId */,
HAL_PIXEL_FORMAT_RGBA_8888,
0ULL /*usage*/);
- layer->setBuffer(externalTexture1, bufferData, 10, 20, false, std::nullopt,
- {/*vsyncId*/ 1, /*inputEventId*/ 0});
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = 1;
+ ftInfo.inputEventId = 0;
+ layer->setBuffer(externalTexture1, bufferData, 10, 20, false, std::nullopt, ftInfo);
EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
const auto droppedSurfaceFrame1 = layer->mDrawingState.bufferSurfaceFrameTX;
@@ -409,8 +425,10 @@
1ULL /* bufferId */,
HAL_PIXEL_FORMAT_RGBA_8888,
0ULL /*usage*/);
- layer->setBuffer(externalTexture2, bufferData, 10, 20, false, std::nullopt,
- {/*vsyncId*/ FrameTimelineInfo::INVALID_VSYNC_ID, /*inputEventId*/ 0});
+ FrameTimelineInfo ftInfoInv;
+ ftInfoInv.vsyncId = FrameTimelineInfo::INVALID_VSYNC_ID;
+ ftInfoInv.inputEventId = 0;
+ layer->setBuffer(externalTexture2, bufferData, 10, 20, false, std::nullopt, ftInfoInv);
auto dropEndTime1 = systemTime();
EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
@@ -428,8 +446,10 @@
1ULL /* bufferId */,
HAL_PIXEL_FORMAT_RGBA_8888,
0ULL /*usage*/);
- layer->setBuffer(externalTexture3, bufferData, 10, 20, false, std::nullopt,
- {/*vsyncId*/ 2, /*inputEventId*/ 0});
+ FrameTimelineInfo ftInfo2;
+ ftInfo2.vsyncId = 2;
+ ftInfo2.inputEventId = 0;
+ layer->setBuffer(externalTexture3, bufferData, 10, 20, false, std::nullopt, ftInfo2);
auto dropEndTime2 = systemTime();
acquireFence3->signalForTest(12);
@@ -476,11 +496,14 @@
1ULL /* bufferId */,
HAL_PIXEL_FORMAT_RGBA_8888,
0ULL /*usage*/);
- layer->setBuffer(externalTexture, bufferData, 10, 20, false, std::nullopt,
- {/*vsyncId*/ 1, /*inputEventId*/ 0});
- layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 2,
- /*inputEventId*/ 0},
- 10);
+ FrameTimelineInfo ftInfo;
+ ftInfo.vsyncId = 1;
+ ftInfo.inputEventId = 0;
+ layer->setBuffer(externalTexture, bufferData, 10, 20, false, std::nullopt, ftInfo);
+ FrameTimelineInfo ftInfo2;
+ ftInfo2.vsyncId = 2;
+ ftInfo2.inputEventId = 0;
+ layer->setFrameTimelineVsyncForBufferlessTransaction(ftInfo2, 10);
ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
EXPECT_EQ(1u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
auto& bufferlessSurfaceFrame =
diff --git a/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp b/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp
index 61b72a0..8ec918d 100644
--- a/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionTracingTest.cpp
@@ -127,6 +127,8 @@
std::vector<TransactionState> transactions;
transactions.emplace_back(transaction);
VSYNC_ID_FIRST_LAYER_CHANGE = ++mVsyncId;
+ mTracing.onLayerAddedToDrawingState(mParentLayerId, VSYNC_ID_FIRST_LAYER_CHANGE);
+ mTracing.onLayerAddedToDrawingState(mChildLayerId, VSYNC_ID_FIRST_LAYER_CHANGE);
mTracing.addCommittedTransactions(transactions, VSYNC_ID_FIRST_LAYER_CHANGE);
flush(VSYNC_ID_FIRST_LAYER_CHANGE);
}
@@ -238,6 +240,8 @@
const sp<IBinder> fakeMirrorLayerHandle = new BBinder();
mTracing.onMirrorLayerAdded(fakeMirrorLayerHandle->localBinder(), mMirrorLayerId, "Mirror",
mLayerId);
+ mTracing.onLayerAddedToDrawingState(mLayerId, mVsyncId);
+ mTracing.onLayerAddedToDrawingState(mMirrorLayerId, mVsyncId);
// add some layer transaction
{
@@ -257,7 +261,7 @@
std::vector<TransactionState> transactions;
transactions.emplace_back(transaction);
- mTracing.addCommittedTransactions(transactions, ++mVsyncId);
+ mTracing.addCommittedTransactions(transactions, mVsyncId);
flush(mVsyncId);
}
}
diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
index c5ca86a..d30dc42 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
@@ -28,8 +28,7 @@
~EventThread() override;
MOCK_CONST_METHOD2(createEventConnection,
- sp<EventThreadConnection>(ResyncCallback,
- ISurfaceComposer::EventRegistrationFlags));
+ sp<EventThreadConnection>(ResyncCallback, EventRegistrationFlags));
MOCK_METHOD0(onScreenReleased, void());
MOCK_METHOD0(onScreenAcquired, void());
MOCK_METHOD2(onHotplugReceived, void(PhysicalDisplayId, bool));
diff --git a/services/surfaceflinger/tests/unittests/mock/MockLayer.h b/services/surfaceflinger/tests/unittests/mock/MockLayer.h
index 0840a2f..d086d79 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockLayer.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockLayer.h
@@ -25,7 +25,10 @@
class MockLayer : public Layer {
public:
MockLayer(SurfaceFlinger* flinger, std::string name)
- : Layer(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));
+ }
explicit MockLayer(SurfaceFlinger* flinger) : MockLayer(flinger, "TestLayer") {}
MOCK_CONST_METHOD0(getType, const char*());
@@ -33,6 +36,8 @@
MOCK_CONST_METHOD0(isVisible, bool());
MOCK_METHOD0(createClone, sp<Layer>());
MOCK_CONST_METHOD0(getFrameRateForLayerTree, FrameRate());
+ MOCK_CONST_METHOD0(getDefaultFrameRateCompatibility,
+ scheduler::LayerInfo::FrameRateCompatibility());
MOCK_CONST_METHOD0(getOwnerUid, uid_t());
MOCK_CONST_METHOD0(getDataSpace, ui::Dataspace());
};
diff --git a/services/surfaceflinger/tests/utils/ColorUtils.h b/services/surfaceflinger/tests/utils/ColorUtils.h
index 07916b6..38c422a 100644
--- a/services/surfaceflinger/tests/utils/ColorUtils.h
+++ b/services/surfaceflinger/tests/utils/ColorUtils.h
@@ -33,6 +33,10 @@
static const Color WHITE;
static const Color BLACK;
static const Color TRANSPARENT;
+
+ half3 toHalf3() { return half3{r / 255.0f, g / 255.0f, b / 255.0f}; }
+
+ half4 toHalf4() { return half4{r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f}; }
};
const Color Color::RED{255, 0, 0, 255};
@@ -81,6 +85,14 @@
}
color = ret;
}
+
+ static half3 toHalf3(const Color& color) {
+ return half3{color.r / 255.0f, color.g / 255.0f, color.b / 255.0f};
+ }
+
+ static half4 toHalf4(const Color& color) {
+ return half4{color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, color.a / 255.0f};
+ }
};
} // namespace
} // namespace android
diff --git a/services/surfaceflinger/tests/utils/ScreenshotUtils.h b/services/surfaceflinger/tests/utils/ScreenshotUtils.h
index f879430..6ada549 100644
--- a/services/surfaceflinger/tests/utils/ScreenshotUtils.h
+++ b/services/surfaceflinger/tests/utils/ScreenshotUtils.h
@@ -15,6 +15,7 @@
*/
#pragma once
+#include <gui/AidlStatusUtil.h>
#include <gui/SyncScreenCaptureListener.h>
#include <private/gui/ComposerServiceAIDL.h>
#include <ui/Rect.h>
@@ -24,6 +25,8 @@
namespace android {
+using gui::aidl_utils::statusTFromBinderStatus;
+
namespace {
// A ScreenCapture is a screenshot from SurfaceFlinger that can be used to check
@@ -38,9 +41,9 @@
captureArgs.dataspace = ui::Dataspace::V0_SRGB;
const sp<SyncScreenCaptureListener> captureListener = new SyncScreenCaptureListener();
binder::Status status = sf->captureDisplay(captureArgs, captureListener);
-
- if (status.transactionError() != NO_ERROR) {
- return status.transactionError();
+ status_t err = statusTFromBinderStatus(status);
+ if (err != NO_ERROR) {
+ return err;
}
captureResults = captureListener->waitForResults();
return captureResults.result;
@@ -72,8 +75,9 @@
captureArgs.dataspace = ui::Dataspace::V0_SRGB;
const sp<SyncScreenCaptureListener> captureListener = new SyncScreenCaptureListener();
binder::Status status = sf->captureLayers(captureArgs, captureListener);
- if (status.transactionError() != NO_ERROR) {
- return status.transactionError();
+ status_t err = statusTFromBinderStatus(status);
+ if (err != NO_ERROR) {
+ return err;
}
captureResults = captureListener->waitForResults();
return captureResults.result;
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 48d6fd0..eb669c0 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -763,7 +763,11 @@
// We must support R8G8B8A8
std::vector<VkSurfaceFormatKHR> all_formats = {
{VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
- {VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR}};
+ {VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR},
+ // Also allow to use PASS_THROUGH + HAL_DATASPACE_ARBITRARY
+ {VK_FORMAT_R8G8B8A8_UNORM, VK_COLOR_SPACE_PASS_THROUGH_EXT},
+ {VK_FORMAT_R8G8B8A8_SRGB, VK_COLOR_SPACE_PASS_THROUGH_EXT},
+ };
if (colorspace_ext) {
all_formats.emplace_back(VkSurfaceFormatKHR{
@@ -1843,6 +1847,11 @@
if (swapchain_result != VK_SUCCESS) {
OrphanSwapchain(device, &swapchain);
}
+ // Android will only return VK_SUBOPTIMAL_KHR for vkQueuePresentKHR,
+ // and only when the window's transform/rotation changes. Extent
+ // changes will not cause VK_SUBOPTIMAL_KHR because of the
+ // application issues that were caused when the following transform
+ // change was added.
int window_transform_hint;
err = window->query(window, NATIVE_WINDOW_TRANSFORM_HINT,
&window_transform_hint);