Merge "Revert "DisplayEventDispatcher: optimize binder calls"" into sc-dev
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp
index 80d14ac..34e9a85 100644
--- a/cmds/dumpstate/Android.bp
+++ b/cmds/dumpstate/Android.bp
@@ -112,6 +112,7 @@
],
required: [
"atrace",
+ "dmabuf_dump",
"ip",
"iptables",
"librank",
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 4a4a510..990aa53 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1846,10 +1846,8 @@
RunCommand("IOTOP", {"iotop", "-n", "1", "-m", "100"});
// Gather shared memory buffer info if the product implements it
- struct stat st;
- if (!stat("/product/bin/dmabuf_dump", &st)) {
- RunCommand("Dmabuf dump", {"/product/bin/dmabuf_dump"});
- }
+ RunCommand("Dmabuf dump", {"dmabuf_dump"});
+ RunCommand("Dmabuf per-buffer/per-exporter/per-device stats", {"dmabuf_dump", "-b"});
DumpFile("PSI cpu", "/proc/pressure/cpu");
DumpFile("PSI memory", "/proc/pressure/memory");
diff --git a/cmds/flatland/GLHelper.cpp b/cmds/flatland/GLHelper.cpp
index 3a3df08..01f7d30 100644
--- a/cmds/flatland/GLHelper.cpp
+++ b/cmds/flatland/GLHelper.cpp
@@ -19,7 +19,7 @@
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <gui/SurfaceComposerClient.h>
-#include <ui/DisplayConfig.h>
+#include <ui/DisplayMode.h>
namespace android {
@@ -227,15 +227,15 @@
return false;
}
- DisplayConfig config;
- status_t err = mSurfaceComposerClient->getActiveDisplayConfig(dpy, &config);
+ ui::DisplayMode mode;
+ status_t err = mSurfaceComposerClient->getActiveDisplayMode(dpy, &mode);
if (err != NO_ERROR) {
- fprintf(stderr, "SurfaceComposer::getActiveDisplayConfig failed: %#x\n", err);
+ fprintf(stderr, "SurfaceComposer::getActiveDisplayMode failed: %#x\n", err);
return false;
}
- float scaleX = static_cast<float>(config.resolution.getWidth()) / w;
- float scaleY = static_cast<float>(config.resolution.getHeight()) / h;
+ float scaleX = static_cast<float>(mode.resolution.getWidth()) / w;
+ float scaleY = static_cast<float>(mode.resolution.getHeight()) / h;
*scale = scaleX < scaleY ? scaleX : scaleY;
return true;
diff --git a/cmds/idlcli/Android.bp b/cmds/idlcli/Android.bp
index 643b3ca..72ffc94 100644
--- a/cmds/idlcli/Android.bp
+++ b/cmds/idlcli/Android.bp
@@ -15,7 +15,7 @@
cc_defaults {
name: "idlcli-defaults",
shared_libs: [
- "android.hardware.vibrator-unstable-ndk_platform",
+ "android.hardware.vibrator-V2-ndk_platform",
"android.hardware.vibrator@1.0",
"android.hardware.vibrator@1.1",
"android.hardware.vibrator@1.2",
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index 96875d5..cbe857a 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -38,6 +38,9 @@
"libutils",
"server_configurable_flags",
],
+ export_shared_lib_headers: [
+ "libbinder",
+ ],
product_variables: {
arc: {
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 65fc46e..4dfd1d0 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -1130,23 +1130,6 @@
return true;
}
-// Updates the access times of out_oat_path based on those from apk_path.
-void update_out_oat_access_times(const char* apk_path, const char* out_oat_path) {
- struct stat input_stat;
- memset(&input_stat, 0, sizeof(input_stat));
- if (stat(apk_path, &input_stat) != 0) {
- PLOG(ERROR) << "Could not stat " << apk_path << " during dexopt";
- return;
- }
-
- struct utimbuf ut;
- ut.actime = input_stat.st_atime;
- ut.modtime = input_stat.st_mtime;
- if (utime(out_oat_path, &ut) != 0) {
- PLOG(WARNING) << "Could not update access times for " << apk_path << " during dexopt";
- }
-}
-
// Runs (execv) dexoptanalyzer on the given arguments.
// The analyzer will check if the dex_file needs to be (re)compiled to match the compiler_filter.
// If this is for a profile guided compilation, profile_was_updated will tell whether or not
@@ -1843,8 +1826,6 @@
}
}
- update_out_oat_access_times(dex_path, out_oat.path().c_str());
-
// We've been successful, don't delete output.
out_oat.DisableCleanup();
out_vdex.DisableCleanup();
diff --git a/cmds/lshal/DebugCommand.cpp b/cmds/lshal/DebugCommand.cpp
index 72958bd..ccf1ab1 100644
--- a/cmds/lshal/DebugCommand.cpp
+++ b/cmds/lshal/DebugCommand.cpp
@@ -28,7 +28,7 @@
}
std::string DebugCommand::getSimpleDescription() const {
- return "Debug a specified HAL.";
+ return "Debug a specified HIDL HAL.";
}
Status DebugCommand::parseArgs(const Arg &arg) {
@@ -78,7 +78,7 @@
"debug:\n"
" lshal debug [-E] <interface> [options [options [...]]] \n"
" Print debug information of a specified interface.\n"
- " -E: excludes debug output if HAL is actually a subclass.\n"
+ " -E: excludes debug output if HIDL HAL is actually a subclass.\n"
" <interface>: Format is `android.hardware.foo@1.0::IFoo/default`.\n"
" If instance name is missing `default` is used.\n"
" options: space separated options to IBase::debug.\n";
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
index 22268ac..d5110f6 100644
--- a/cmds/lshal/ListCommand.cpp
+++ b/cmds/lshal/ListCommand.cpp
@@ -81,7 +81,7 @@
return "list";
}
std::string ListCommand::getSimpleDescription() const {
- return "List HALs.";
+ return "List HIDL HALs.";
}
std::string ListCommand::parseCmdline(pid_t pid) const {
@@ -295,21 +295,21 @@
}
mServicesTable.setDescription(
- "| All binderized services (registered with hwservicemanager)");
+ "| All HIDL binderized services (registered with hwservicemanager)");
mPassthroughRefTable.setDescription(
- "| All interfaces that getService() has ever returned as a passthrough interface;\n"
+ "| All HIDL interfaces getService() has ever returned as a passthrough interface;\n"
"| PIDs / processes shown below might be inaccurate because the process\n"
"| might have relinquished the interface or might have died.\n"
"| The Server / Server CMD column can be ignored.\n"
"| The Clients / Clients CMD column shows all process that have ever dlopen'ed \n"
"| the library and successfully fetched the passthrough implementation.");
mImplementationsTable.setDescription(
- "| All available passthrough implementations (all -impl.so files).\n"
+ "| All available HIDL passthrough implementations (all -impl.so files).\n"
"| These may return subclasses through their respective HIDL_FETCH_I* functions.");
mManifestHalsTable.setDescription(
- "| All HALs that are in VINTF manifest.");
+ "| All HIDL HALs that are in VINTF manifest.");
mLazyHalsTable.setDescription(
- "| All HALs that are declared in VINTF manifest:\n"
+ "| All HIDL HALs that are declared in VINTF manifest:\n"
"| - as hwbinder HALs but are not registered to hwservicemanager, and\n"
"| - as hwbinder/passthrough HALs with no implementation.");
}
@@ -903,11 +903,11 @@
thiz->mSelectedColumns.push_back(TableColumnType::VINTF);
return OK;
}, "print VINTF info. This column contains a comma-separated list of:\n"
- " - DM: if the HAL is in the device manifest\n"
- " - DC: if the HAL is in the device compatibility matrix\n"
- " - FM: if the HAL is in the framework manifest\n"
- " - FC: if the HAL is in the framework compatibility matrix\n"
- " - X: if the HAL is in none of the above lists"});
+ " - DM: if the HIDL HAL is in the device manifest\n"
+ " - DC: if the HIDL HAL is in the device compatibility matrix\n"
+ " - FM: if the HIDL HAL is in the framework manifest\n"
+ " - FC: if the HIDL HAL is in the framework compatibility matrix\n"
+ " - X: if the HIDL HAL is in none of the above lists"});
mOptions.push_back({'S', "service-status", no_argument, v++, [](ListCommand* thiz, const char*) {
thiz->mSelectedColumns.push_back(TableColumnType::SERVICE_STATUS);
return OK;
diff --git a/cmds/lshal/Lshal.cpp b/cmds/lshal/Lshal.cpp
index 99cb93a..bc99f4d 100644
--- a/cmds/lshal/Lshal.cpp
+++ b/cmds/lshal/Lshal.cpp
@@ -59,7 +59,8 @@
}
void Lshal::usage() {
- err() << "lshal: List and debug HALs." << std::endl << std::endl
+ err() << "lshal: List and debug HIDL HALs." << std::endl
+ << " (for AIDL HALs, see `dumpsys`)" << std::endl << std::endl
<< "commands:" << std::endl;
size_t nameMaxLength = 0;
diff --git a/cmds/lshal/WaitCommand.cpp b/cmds/lshal/WaitCommand.cpp
index 65b41b9..437a66a 100644
--- a/cmds/lshal/WaitCommand.cpp
+++ b/cmds/lshal/WaitCommand.cpp
@@ -29,7 +29,7 @@
}
std::string WaitCommand::getSimpleDescription() const {
- return "Wait for HAL to start if it is not already started.";
+ return "Wait for HIDL HAL to start if it is not already started.";
}
Status WaitCommand::parseArgs(const Arg &arg) {
diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto
index c6f656b..79aab82 100644
--- a/cmds/surfacereplayer/proto/src/trace.proto
+++ b/cmds/surfacereplayer/proto/src/trace.proto
@@ -50,11 +50,10 @@
CornerRadiusChange corner_radius = 16;
ReparentChange reparent = 17;
RelativeParentChange relative_parent = 18;
- DetachChildrenChange detach_children = 19;
- ReparentChildrenChange reparent_children = 20;
- BackgroundBlurRadiusChange background_blur_radius = 21;
- ShadowRadiusChange shadow_radius = 22;
- BlurRegionsChange blur_regions = 23;
+ ReparentChildrenChange reparent_children = 19;
+ BackgroundBlurRadiusChange background_blur_radius = 20;
+ ShadowRadiusChange shadow_radius = 21;
+ BlurRegionsChange blur_regions = 22;
}
}
@@ -200,10 +199,6 @@
required int32 z = 2;
}
-message DetachChildrenChange {
- required bool detach_children = 1;
-}
-
message ShadowRadiusChange {
required float radius = 1;
}
diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp
index 5849212..58d6582 100644
--- a/cmds/surfacereplayer/replayer/Replayer.cpp
+++ b/cmds/surfacereplayer/replayer/Replayer.cpp
@@ -417,9 +417,6 @@
case SurfaceChange::SurfaceChangeCase::kRelativeParent:
setRelativeParentChange(transaction, change.id(), change.relative_parent());
break;
- case SurfaceChange::SurfaceChangeCase::kDetachChildren:
- setDetachChildrenChange(transaction, change.id(), change.detach_children());
- break;
case SurfaceChange::SurfaceChangeCase::kShadowRadius:
setShadowRadiusChange(transaction, change.id(), change.shadow_radius());
break;
@@ -713,11 +710,6 @@
t.setRelativeLayer(mLayers[id], mLayers[c.relative_parent_id()], c.z());
}
-void Replayer::setDetachChildrenChange(SurfaceComposerClient::Transaction& t,
- layer_id id, const DetachChildrenChange& c) {
- t.detachChildren(mLayers[id]);
-}
-
void Replayer::setReparentChildrenChange(SurfaceComposerClient::Transaction& t,
layer_id id, const ReparentChildrenChange& c) {
if (mLayers.count(c.parent_id()) == 0 || mLayers[c.parent_id()] == nullptr) {
diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h
index a22262a..324d591 100644
--- a/cmds/surfacereplayer/replayer/Replayer.h
+++ b/cmds/surfacereplayer/replayer/Replayer.h
@@ -116,8 +116,6 @@
layer_id id, const ReparentChange& c);
void setRelativeParentChange(SurfaceComposerClient::Transaction& t,
layer_id id, const RelativeParentChange& c);
- void setDetachChildrenChange(SurfaceComposerClient::Transaction& t,
- layer_id id, const DetachChildrenChange& c);
void setReparentChildrenChange(SurfaceComposerClient::Transaction& t,
layer_id id, const ReparentChildrenChange& c);
void setShadowRadiusChange(SurfaceComposerClient::Transaction& t,
diff --git a/data/etc/android.hardware.keystore.limited_use_key.xml b/data/etc/android.hardware.keystore.limited_use_key.xml
new file mode 100644
index 0000000..5217086
--- /dev/null
+++ b/data/etc/android.hardware.keystore.limited_use_key.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- Feature for devices with KeyMint that can enforce limited use key
+ in hardware with any max usage count (including count equals to 1). -->
+<permissions>
+ <feature name="android.hardware.keystore.limited_use_key" />
+</permissions>
\ No newline at end of file
diff --git a/data/etc/android.hardware.keystore.single_use_key.xml b/data/etc/android.hardware.keystore.single_use_key.xml
new file mode 100644
index 0000000..40e80aa
--- /dev/null
+++ b/data/etc/android.hardware.keystore.single_use_key.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- Feature for devices with KeyMint that only can enforce limited use key
+ in hardware with max usage count equals to 1. -->
+<permissions>
+ <feature name="android.hardware.keystore.single_use_key" />
+</permissions>
\ No newline at end of file
diff --git a/data/etc/android.hardware.telephony.ims.singlereg.xml b/data/etc/android.hardware.telephony.ims.singlereg.xml
new file mode 100644
index 0000000..9a6cec0
--- /dev/null
+++ b/data/etc/android.hardware.telephony.ims.singlereg.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- Feature for devices that have an IMS service that supports all IMS
+ applications using a single IMS registration. -->
+<permissions>
+ <feature name="android.hardware.telephony.ims" />
+ <feature name="android.hardware.telephony.ims.singlereg" />
+</permissions>
diff --git a/data/etc/car_core_hardware.xml b/data/etc/car_core_hardware.xml
index cc0ee82..adfd6e2 100644
--- a/data/etc/car_core_hardware.xml
+++ b/data/etc/car_core_hardware.xml
@@ -47,6 +47,12 @@
<feature name="android.software.secure_lock_screen" />
<feature name="android.software.input_methods" />
+
+ <!-- Feature to support device admins -->
+ <!-- TODO(b/178412797): not fully supported yet, CTS tests are still
+ failing. -->
+ <feature name="android.software.device_admin" />
+
<!-- devices with GPS must include android.hardware.location.gps.xml -->
<!-- devices with an autofocus camera and/or flash must include either
android.hardware.camera.autofocus.xml or
diff --git a/include/OWNERS b/include/OWNERS
index db52850..c98e87a 100644
--- a/include/OWNERS
+++ b/include/OWNERS
@@ -1,3 +1,4 @@
+alecmouri@google.com
alexeykuzmin@google.com
dangittik@google.com
jreck@google.com
@@ -8,7 +9,6 @@
racarr@google.com
romainguy@android.com
santoscordon@google.com
-stoza@google.com
svv@google.com
# For multinetwork.h only.
diff --git a/include/android/bitmap.h b/include/android/bitmap.h
index d7f25e1..a70dffd 100644
--- a/include/android/bitmap.h
+++ b/include/android/bitmap.h
@@ -31,18 +31,8 @@
#include <stddef.h>
#include <jni.h>
-#ifndef __ANDROID__
- // Value copied from 'bionic/libc/include/android/api-level.h' which is not available on
- // non Android systems. It is set to 10000 which is same as __ANDROID_API_FUTURE__ value.
- #ifndef __ANDROID_API__
- #define __ANDROID_API__ 10000
- #endif
-
- // Value copied from 'bionic/libc/include/android/versioning.h' which is not available on
- // non Android systems
- #ifndef __INTRODUCED_IN
- #define __INTRODUCED_IN(api_level)
- #endif
+#if !defined(__INTRODUCED_IN)
+#define __INTRODUCED_IN(__api_level) /* nothing */
#endif
#ifdef __cplusplus
@@ -132,8 +122,6 @@
int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,
AndroidBitmapInfo* info);
-#if __ANDROID_API__ >= 30
-
/**
* Given a java bitmap object, return its {@link ADataSpace}.
*
@@ -145,8 +133,6 @@
*/
int32_t AndroidBitmap_getDataSpace(JNIEnv* env, jobject jbitmap) __INTRODUCED_IN(30);
-#endif // __ANDROID_API__ >= 30
-
/**
* Given a java bitmap object, attempt to lock the pixel address.
* Locking will ensure that the memory for the pixels will not move
@@ -216,8 +202,6 @@
const void* data,
size_t size) __INTRODUCED_IN(30);
-#if __ANDROID_API__ >= 30
-
/**
* Compress |pixels| as described by |info|.
*
@@ -269,8 +253,6 @@
int AndroidBitmap_getHardwareBuffer(JNIEnv* env, jobject bitmap,
AHardwareBuffer** outBuffer) __INTRODUCED_IN(30);
-#endif // __ANDROID_API__ >= 30
-
#ifdef __cplusplus
}
#endif
diff --git a/include/android/choreographer.h b/include/android/choreographer.h
index e9f559c..8039bb0 100644
--- a/include/android/choreographer.h
+++ b/include/android/choreographer.h
@@ -61,8 +61,6 @@
*/
typedef void (*AChoreographer_refreshRateCallback)(int64_t vsyncPeriodNanos, void* data);
-#if __ANDROID_API__ >= 24
-
/**
* Get the AChoreographer instance for the current thread. This must be called
* on an ALooper thread.
@@ -86,10 +84,6 @@
long delayMillis) __INTRODUCED_IN(24)
__DEPRECATED_IN(29);
-#endif /* __ANDROID_API__ >= 24 */
-
-#if __ANDROID_API__ >= 29
-
/**
* Power a callback to be run on the next frame. The data pointer provided will
* be passed to the callback function when it's called.
@@ -111,10 +105,6 @@
AChoreographer_frameCallback64 callback, void* data,
uint32_t delayMillis) __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
-
-#if __ANDROID_API__ >= 30
-
/**
* Registers a callback to be run when the display refresh rate changes. The
* data pointer provided will be passed to the callback function when it's
@@ -160,7 +150,6 @@
void AChoreographer_unregisterRefreshRateCallback(AChoreographer* choreographer,
AChoreographer_refreshRateCallback, void* data)
__INTRODUCED_IN(30);
-#endif /* __ANDROID_API__ >= 30 */
__END_DECLS
diff --git a/include/android/configuration.h b/include/android/configuration.h
index ccf3e59..88019ae 100644
--- a/include/android/configuration.h
+++ b/include/android/configuration.h
@@ -645,14 +645,12 @@
*/
void AConfiguration_setScreenLong(AConfiguration* config, int32_t screenLong);
-#if __ANDROID_API__ >= 30
/**
* Return the current ACONFIGURATION_SCREENROUND_* set in the configuration.
*
* Available since API level 30.
*/
int32_t AConfiguration_getScreenRound(AConfiguration* config) __INTRODUCED_IN(30);
-#endif
/**
* Set the current screen round in the configuration.
@@ -712,7 +710,6 @@
*/
void AConfiguration_setSmallestScreenWidthDp(AConfiguration* config, int32_t value);
-#if __ANDROID_API__ >= 17
/**
* Return the configuration's layout direction, or
* ACONFIGURATION_LAYOUTDIR_ANY if not set.
@@ -727,7 +724,6 @@
* Available since API level 17.
*/
void AConfiguration_setLayoutDirection(AConfiguration* config, int32_t value) __INTRODUCED_IN(17);
-#endif /* __ANDROID_API__ >= 17 */
/**
* Perform a diff between two configurations. Returns a bit mask of
diff --git a/include/android/font.h b/include/android/font.h
index 1618096..a172618 100644
--- a/include/android/font.h
+++ b/include/android/font.h
@@ -51,8 +51,6 @@
__BEGIN_DECLS
-#if __ANDROID_API__ >= 29
-
enum {
/** The minimum value fot the font weight value. */
AFONT_WEIGHT_MIN = 0,
@@ -297,8 +295,6 @@
float AFont_getAxisValue(const AFont* _Nonnull font, uint32_t axisIndex)
__INTRODUCED_IN(29);
-#endif // __ANDROID_API__ >= 29
-
__END_DECLS
#endif // ANDROID_FONT_H
diff --git a/include/android/font_matcher.h b/include/android/font_matcher.h
index d4bd892..49e478c 100644
--- a/include/android/font_matcher.h
+++ b/include/android/font_matcher.h
@@ -97,8 +97,6 @@
__BEGIN_DECLS
-#if __ANDROID_API__ >= 29
-
enum {
/** A family variant value for the system default variant. */
AFAMILY_VARIANT_DEFAULT = 0,
@@ -217,8 +215,6 @@
const uint32_t textLength,
uint32_t* _Nullable runLengthOut) __INTRODUCED_IN(29);
-#endif // __ANDROID_API__ >= 29
-
__END_DECLS
#endif // ANDROID_FONT_MATCHER_H
diff --git a/include/android/imagedecoder.h b/include/android/imagedecoder.h
index c7a8939..cac67d4 100644
--- a/include/android/imagedecoder.h
+++ b/include/android/imagedecoder.h
@@ -51,18 +51,8 @@
#include <android/rect.h>
#include <stdint.h>
-#ifndef __ANDROID__
- // Value copied from 'bionic/libc/include/android/api-level.h' which is not available on
- // non Android systems. It is set to 10000 which is same as __ANDROID_API_FUTURE__ value.
- #ifndef __ANDROID_API__
- #define __ANDROID_API__ 10000
- #endif
-
- // Value copied from 'bionic/libc/include/android/versioning.h' which is not available on
- // non Android systems
- #ifndef __INTRODUCED_IN
- #define __INTRODUCED_IN(api_level)
- #endif
+#if !defined(__INTRODUCED_IN)
+#define __INTRODUCED_IN(__api_level) /* nothing */
#endif
#ifdef __cplusplus
@@ -139,8 +129,6 @@
ANDROID_IMAGE_DECODER_INVALID_STATE = -11,
};
-#if __ANDROID_API__ >= 31
-
/**
* Return a constant string value representing the error code.
*
@@ -155,8 +143,6 @@
*/
const char* _Nullable AImageDecoder_resultToString(int)__INTRODUCED_IN(31);
-#endif // __ANDROID_API__ >= 31
-
struct AImageDecoder;
/**
@@ -179,8 +165,6 @@
*/
typedef struct AImageDecoder AImageDecoder;
-#if __ANDROID_API__ >= 30
-
/**
* Create a new {@link AImageDecoder} from an {@link AAsset}.
*
@@ -469,8 +453,6 @@
*/
int AImageDecoder_setCrop(AImageDecoder* _Nonnull decoder, ARect crop) __INTRODUCED_IN(30);
-#endif // __ANDROID_API__ >= 30
-
struct AImageDecoderHeaderInfo;
/**
* Opaque handle for representing information about the encoded image.
@@ -483,8 +465,6 @@
*/
typedef struct AImageDecoderHeaderInfo AImageDecoderHeaderInfo;
-#if __ANDROID_API__ >= 30
-
/**
* Return an opaque handle for reading header info.
*
@@ -672,10 +652,6 @@
void* _Nonnull pixels, size_t stride,
size_t size) __INTRODUCED_IN(30);
-#endif // __ANDROID_API__ >= 30
-
-#if __ANDROID_API__ >= 31
-
/**
* Return true iff the image is animated - i.e. has multiple frames.
*
@@ -690,8 +666,6 @@
bool AImageDecoder_isAnimated(AImageDecoder* _Nonnull decoder)
__INTRODUCED_IN(31);
-#endif // __ANDROID_API__ >= 31
-
enum {
/*
* Reported by {@link AImageDecoder_getRepeatCount} if the
@@ -702,8 +676,6 @@
ANDROID_IMAGE_DECODER_INFINITE = INT32_MAX,
};
-#if __ANDROID_API__ >= 31
-
/**
* Report how many times the animation should repeat.
*
@@ -793,8 +765,6 @@
int AImageDecoder_rewind(AImageDecoder* _Nonnull decoder)
__INTRODUCED_IN(31);
-#endif // __ANDROID_API__ >= 31
-
struct AImageDecoderFrameInfo;
/**
@@ -810,8 +780,6 @@
*/
typedef struct AImageDecoderFrameInfo AImageDecoderFrameInfo;
-#if __ANDROID_API__ >= 31
-
/**
* Create an uninitialized AImageDecoderFrameInfo.
*
@@ -922,8 +890,6 @@
bool AImageDecoderFrameInfo_hasAlphaWithinBounds(
const AImageDecoderFrameInfo* _Nonnull info) __INTRODUCED_IN(31);
-#endif // __ANDROID_API__ >= 31
-
/**
* How a frame is “disposed” before showing the next one.
*
@@ -947,8 +913,6 @@
ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS = 3,
};
-#if __ANDROID_API__ >= 31
-
/**
* Return how this frame is “disposed” before showing the next one.
*
@@ -969,8 +933,6 @@
int32_t AImageDecoderFrameInfo_getDisposeOp(
const AImageDecoderFrameInfo* _Nonnull info) __INTRODUCED_IN(31);
-#endif // __ANDROID_API__ >= 31
-
/**
* How a frame is blended with the previous frame.
*
@@ -989,8 +951,6 @@
ANDROID_IMAGE_DECODER_BLEND_OP_SRC_OVER = 2,
};
-#if __ANDROID_API__ >= 31
-
/**
* Return how this frame is blended with the previous frame.
*
@@ -1047,8 +1007,6 @@
__INTRODUCED_IN(31);
-#endif // __ANDROID_API__ >= 31
-
#ifdef __cplusplus
}
#endif
diff --git a/include/android/input.h b/include/android/input.h
index b5d399e..b70d424 100644
--- a/include/android/input.h
+++ b/include/android/input.h
@@ -856,8 +856,10 @@
AINPUT_SOURCE_TOUCH_NAVIGATION = 0x00200000 | AINPUT_SOURCE_CLASS_NONE,
/** joystick */
AINPUT_SOURCE_JOYSTICK = 0x01000000 | AINPUT_SOURCE_CLASS_JOYSTICK,
+ /** HDMI */
+ AINPUT_SOURCE_HDMI = 0x02000000 | AINPUT_SOURCE_CLASS_BUTTON,
/** sensor */
- AINPUT_SOURCE_SENSOR = 0x02000000 | AINPUT_SOURCE_CLASS_JOYSTICK,
+ AINPUT_SOURCE_SENSOR = 0x04000000 | AINPUT_SOURCE_UNKNOWN,
/** rotary encoder */
AINPUT_SOURCE_ROTARY_ENCODER = 0x00400000 | AINPUT_SOURCE_CLASS_NONE,
diff --git a/include/android/multinetwork.h b/include/android/multinetwork.h
index c6d1c94..424299d 100644
--- a/include/android/multinetwork.h
+++ b/include/android/multinetwork.h
@@ -60,8 +60,6 @@
* on failure with an appropriate errno value set.
*/
-#if __ANDROID_API__ >= 23
-
/**
* Set the network to be used by the given socket file descriptor.
*
@@ -111,10 +109,6 @@
const char *node, const char *service,
const struct addrinfo *hints, struct addrinfo **res) __INTRODUCED_IN(23);
-#endif /* __ANDROID_API__ >= 23 */
-
-#if __ANDROID_API__ >= 29
-
/**
* Possible values of the flags argument to android_res_nsend and android_res_nquery.
* Values are ORed together.
@@ -187,8 +181,6 @@
*/
void android_res_cancel(int nsend_fd) __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
-
__END_DECLS
#endif // ANDROID_MULTINETWORK_H
diff --git a/include/android/native_window_jni.h b/include/android/native_window_jni.h
index 3a77ffe..071ec79 100644
--- a/include/android/native_window_jni.h
+++ b/include/android/native_window_jni.h
@@ -44,7 +44,6 @@
*/
ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface);
-#if __ANDROID_API__ >= 26
/**
* Return a Java Surface object derived from the ANativeWindow, for interacting
* with it through Java code. The returned Java object acquires a reference on
@@ -55,7 +54,6 @@
* Available since API level 26.
*/
jobject ANativeWindow_toSurface(JNIEnv* env, ANativeWindow* window) __INTRODUCED_IN(26);
-#endif
#ifdef __cplusplus
};
diff --git a/include/android/sensor.h b/include/android/sensor.h
index eb40779..6447844 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -52,6 +52,13 @@
#include <math.h>
#include <stdint.h>
+#if !defined(__INTRODUCED_IN)
+#define __INTRODUCED_IN(__api_level) /* nothing */
+#endif
+#if !defined(__DEPRECATED_IN)
+#define __DEPRECATED_IN(__api_level) __attribute__((__deprecated__))
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -553,13 +560,8 @@
* ASensorManager* sensorManager = ASensorManager_getInstance();
*
*/
-#if __ANDROID_API__ >= 26
-__attribute__ ((deprecated)) ASensorManager* ASensorManager_getInstance();
-#else
-ASensorManager* ASensorManager_getInstance();
-#endif
+ASensorManager* ASensorManager_getInstance() __DEPRECATED_IN(26);
-#if __ANDROID_API__ >= 26
/**
* Get a reference to the sensor manager. ASensorManager is a singleton
* per package as different packages may have access to different sensors.
@@ -571,7 +573,6 @@
* Available since API level 26.
*/
ASensorManager* ASensorManager_getInstanceForPackage(const char* packageName) __INTRODUCED_IN(26);
-#endif
/**
* Returns the list of available sensors.
@@ -584,7 +585,6 @@
*/
ASensor const* ASensorManager_getDefaultSensor(ASensorManager* manager, int type);
-#if __ANDROID_API__ >= 21
/**
* Returns the default sensor with the given type and wakeUp properties or NULL if no sensor
* of this type and wakeUp properties exists.
@@ -592,7 +592,6 @@
* Available since API level 21.
*/
ASensor const* ASensorManager_getDefaultSensorEx(ASensorManager* manager, int type, bool wakeUp) __INTRODUCED_IN(21);
-#endif
/**
* Creates a new sensor event queue and associate it with a looper.
@@ -609,7 +608,6 @@
*/
int ASensorManager_destroyEventQueue(ASensorManager* manager, ASensorEventQueue* queue);
-#if __ANDROID_API__ >= 26
/**
* Create direct channel based on shared memory
*
@@ -706,7 +704,6 @@
*/
int ASensorManager_configureDirectReport(ASensorManager* manager,
ASensor const* sensor, int channelId, int rate) __INTRODUCED_IN(26);
-#endif /* __ANDROID_API__ >= 26 */
/*****************************************************************************/
@@ -795,7 +792,6 @@
*/
ssize_t ASensorEventQueue_getEvents(ASensorEventQueue* queue, ASensorEvent* events, size_t count);
-#if __ANDROID_API__ >= 29
/**
* Request that {@link ASENSOR_TYPE_ADDITIONAL_INFO} events to be delivered on
* the given {@link ASensorEventQueue}.
@@ -819,7 +815,6 @@
* \return 0 on success or a negative error code on failure
*/
int ASensorEventQueue_requestAdditionalInfoEvents(ASensorEventQueue* queue, bool enable) __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
/*****************************************************************************/
@@ -850,7 +845,6 @@
*/
int ASensor_getMinDelay(ASensor const* sensor);
-#if __ANDROID_API__ >= 21
/**
* Returns the maximum size of batches for this sensor. Batches will often be
* smaller, as the hardware fifo might be used for other sensors.
@@ -886,9 +880,7 @@
* Available since API level 21.
*/
bool ASensor_isWakeUpSensor(ASensor const* sensor) __INTRODUCED_IN(21);
-#endif /* __ANDROID_API__ >= 21 */
-#if __ANDROID_API__ >= 26
/**
* Test if sensor supports a certain type of direct channel.
*
@@ -914,9 +906,7 @@
* does not support direct report.
*/
int ASensor_getHighestDirectReportRateLevel(ASensor const* sensor) __INTRODUCED_IN(26);
-#endif /* __ANDROID_API__ >= 26 */
-#if __ANDROID_API__ >= 29
/**
* Returns the sensor's handle.
*
@@ -934,7 +924,6 @@
* Available since API level 29.
*/
int ASensor_getHandle(ASensor const* sensor) __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
#ifdef __cplusplus
};
diff --git a/include/android/sharedmem.h b/include/android/sharedmem.h
index 5f74682..7994aa9 100644
--- a/include/android/sharedmem.h
+++ b/include/android/sharedmem.h
@@ -50,8 +50,6 @@
extern "C" {
#endif
-#if __ANDROID_API__ >= 26
-
/**
* Create a shared memory region.
*
@@ -121,8 +119,6 @@
*/
int ASharedMemory_setProt(int fd, int prot) __INTRODUCED_IN(26);
-#endif // __ANDROID_API__ >= 26
-
#ifdef __cplusplus
};
#endif
diff --git a/include/android/sharedmem_jni.h b/include/android/sharedmem_jni.h
index 13e56e6..bbac785 100644
--- a/include/android/sharedmem_jni.h
+++ b/include/android/sharedmem_jni.h
@@ -52,8 +52,6 @@
extern "C" {
#endif
-#if __ANDROID_API__ >= 27
-
/**
* Returns a dup'd FD from the given Java android.os.SharedMemory object. The returned file
* descriptor has all the same properties & capabilities as the FD returned from
@@ -72,8 +70,6 @@
*/
int ASharedMemory_dupFromJava(JNIEnv* env, jobject sharedMemory) __INTRODUCED_IN(27);
-#endif // __ANDROID_API__ >= 27
-
#ifdef __cplusplus
};
#endif
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
index 7a74248..98fd875 100644
--- a/include/android/surface_control.h
+++ b/include/android/surface_control.h
@@ -35,8 +35,6 @@
__BEGIN_DECLS
-#if __ANDROID_API__ >= 29
-
struct ASurfaceControl;
/**
@@ -409,10 +407,6 @@
struct AHdrMetadata_cta861_3* metadata)
__INTRODUCED_IN(29);
-#endif // __ANDROID_API__ >= 29
-
-#if __ANDROID_API__ >= 30
-
/**
* Same as ASurfaceTransaction_setFrameRateWithSeamlessness(transaction, surface_control,
* frameRate, compatibility, true).
@@ -425,10 +419,6 @@
ASurfaceControl* surface_control, float frameRate,
int8_t compatibility) __INTRODUCED_IN(30);
-#endif // __ANDROID_API__ >= 30
-
-#if __ANDROID_API__ >= 31
-
/**
* Sets the intended frame rate for \a surface_control.
*
@@ -462,7 +452,6 @@
int8_t compatibility, bool shouldBeSeamless)
__INTRODUCED_IN(31);
-#endif // __ANDROID_API__ >= 31
__END_DECLS
#endif // ANDROID_SURFACE_CONTROL_H
diff --git a/include/android/surface_texture.h b/include/android/surface_texture.h
index dde7eaa..b227b32 100644
--- a/include/android/surface_texture.h
+++ b/include/android/surface_texture.h
@@ -59,8 +59,6 @@
*/
typedef struct ASurfaceTexture ASurfaceTexture;
-#if __ANDROID_API__ >= 28
-
/**
* Release the reference to the native ASurfaceTexture acquired with
* ASurfaceTexture_fromSurfaceTexture().
@@ -175,8 +173,6 @@
*/
int64_t ASurfaceTexture_getTimestamp(ASurfaceTexture* st) __INTRODUCED_IN(28);
-#endif /* __ANDROID_API__ >= 28 */
-
__END_DECLS
#endif /* ANDROID_NATIVE_SURFACE_TEXTURE_H */
diff --git a/include/android/surface_texture_jni.h b/include/android/surface_texture_jni.h
index 2266d54..e40686d 100644
--- a/include/android/surface_texture_jni.h
+++ b/include/android/surface_texture_jni.h
@@ -32,8 +32,6 @@
__BEGIN_DECLS
-#if __ANDROID_API__ >= 28
-
/**
* Get a reference to the native ASurfaceTexture from the corresponding java object.
*
@@ -52,8 +50,6 @@
*/
ASurfaceTexture* ASurfaceTexture_fromSurfaceTexture(JNIEnv* env, jobject surfacetexture) __INTRODUCED_IN(28);
-#endif
-
__END_DECLS
#endif /* ANDROID_NATIVE_SURFACE_TEXTURE_JNI_H */
diff --git a/include/android/system_fonts.h b/include/android/system_fonts.h
index 6fd7d2c..b0bbb95 100644
--- a/include/android/system_fonts.h
+++ b/include/android/system_fonts.h
@@ -87,8 +87,6 @@
__BEGIN_DECLS
-#if __ANDROID_API__ >= 29
-
/**
* ASystemFontIterator provides access to the system font configuration.
*
@@ -128,8 +126,6 @@
*/
AFont* _Nullable ASystemFontIterator_next(ASystemFontIterator* _Nonnull iterator) __INTRODUCED_IN(29);
-#endif // __ANDROID_API__ >= 29
-
__END_DECLS
#endif // ANDROID_SYSTEM_FONTS_H
diff --git a/include/android/trace.h b/include/android/trace.h
index dbad6f6..dcefffb 100644
--- a/include/android/trace.h
+++ b/include/android/trace.h
@@ -40,8 +40,6 @@
extern "C" {
#endif
-#if __ANDROID_API__ >= 23
-
/**
* Returns true if tracing is enabled. Use this to avoid expensive computation only necessary
* when tracing is enabled.
@@ -72,10 +70,6 @@
*/
void ATrace_endSection() __INTRODUCED_IN(23);
-#endif /* __ANDROID_API__ >= 23 */
-
-#if __ANDROID_API__ >= 29
-
/**
* Writes a trace message to indicate that a given section of code has
* begun. Must be followed by a call to {@link ATrace_endAsyncSection} with the same
@@ -112,8 +106,6 @@
*/
void ATrace_setCounter(const char* counterName, int64_t counterValue) __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
-
#ifdef __cplusplus
}
#endif
diff --git a/include/audiomanager/IAudioManager.h b/include/audiomanager/IAudioManager.h
index 7d1f38f..426e10c 100644
--- a/include/audiomanager/IAudioManager.h
+++ b/include/audiomanager/IAudioManager.h
@@ -39,6 +39,7 @@
TRACK_RECORDER = IBinder::FIRST_CALL_TRANSACTION + 4,
RECORDER_EVENT = IBinder::FIRST_CALL_TRANSACTION + 5,
RELEASE_RECORDER = IBinder::FIRST_CALL_TRANSACTION + 6,
+ PLAYER_SESSION_ID = IBinder::FIRST_CALL_TRANSACTION + 7,
};
DECLARE_META_INTERFACE(AudioManager)
@@ -46,7 +47,8 @@
// The parcels created by these methods must be kept in sync with the
// corresponding methods from IAudioService.aidl and objects it imports.
virtual audio_unique_id_t trackPlayer(player_type_t playerType, audio_usage_t usage,
- audio_content_type_t content, const sp<IBinder>& player) = 0;
+ audio_content_type_t content, const sp<IBinder>& player,
+ audio_session_t sessionId) = 0;
/*oneway*/ virtual status_t playerAttributes(audio_unique_id_t piid, audio_usage_t usage,
audio_content_type_t content)= 0;
/*oneway*/ virtual status_t playerEvent(audio_unique_id_t piid, player_state_t event,
@@ -55,6 +57,7 @@
virtual audio_unique_id_t trackRecorder(const sp<IBinder>& recorder) = 0;
/*oneway*/ virtual status_t recorderEvent(audio_unique_id_t riid, recorder_state_t event) = 0;
/*oneway*/ virtual status_t releaseRecorder(audio_unique_id_t riid) = 0;
+ /*oneway*/ virtual status_t playerSessionId(audio_unique_id_t piid, audio_session_t sessionId) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h
index 23692e9..2bd7bd2 100644
--- a/include/input/InputDevice.h
+++ b/include/input/InputDevice.h
@@ -213,6 +213,9 @@
inline void setVibrator(bool hasVibrator) { mHasVibrator = hasVibrator; }
inline bool hasVibrator() const { return mHasVibrator; }
+ inline void setHasBattery(bool hasBattery) { mHasBattery = hasBattery; }
+ inline bool hasBattery() const { return mHasBattery; }
+
inline void setButtonUnderPad(bool hasButton) { mHasButtonUnderPad = hasButton; }
inline bool hasButtonUnderPad() const { return mHasButtonUnderPad; }
@@ -239,6 +242,7 @@
int32_t mKeyboardType;
std::shared_ptr<KeyCharacterMap> mKeyCharacterMap;
bool mHasVibrator;
+ bool mHasBattery;
bool mHasButtonUnderPad;
bool mHasSensor;
diff --git a/libs/adbd_auth/include/adbd_auth.h b/libs/adbd_auth/include/adbd_auth.h
index 8f834df..1dcf540 100644
--- a/libs/adbd_auth/include/adbd_auth.h
+++ b/libs/adbd_auth/include/adbd_auth.h
@@ -26,7 +26,6 @@
#endif
__BEGIN_DECLS
-#if !defined(__ANDROID__) || __ANDROID_API__ >= 30
// The transport type of the device connection.
enum AdbTransportType : int32_t {
@@ -186,5 +185,4 @@
*/
bool adbd_auth_supports_feature(AdbdAuthFeature feature);
-#endif //!__ANDROID__ || __ANDROID_API__ >= 30
__END_DECLS
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 2c0cca1..b585ad2 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -22,14 +22,21 @@
header_libs: [
"libbase_headers",
+ "libbinder_headers_platform_shared",
"libcutils_headers",
"libutils_headers",
],
export_header_lib_headers: [
"libbase_headers",
+ "libbinder_headers_platform_shared",
"libcutils_headers",
"libutils_headers",
],
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media",
+ "com.android.media.swcodec",
+ ],
min_sdk_version: "29",
target: {
darwin: {
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index 5c34069..79a11d2 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -611,6 +611,12 @@
mPostWriteStrongDerefs.clear();
}
+void IPCThreadState::createTransactionReference(RefBase* ref)
+{
+ ref->incStrong(mProcess.get());
+ mPostWriteStrongDerefs.push(ref);
+}
+
void IPCThreadState::joinThreadPool(bool isMain)
{
LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());
diff --git a/libs/binder/IpPrefix.cpp b/libs/binder/IpPrefix.cpp
index 8d62266..4edc493 100644
--- a/libs/binder/IpPrefix.cpp
+++ b/libs/binder/IpPrefix.cpp
@@ -24,12 +24,10 @@
#include <log/log.h>
#include <utils/Errors.h>
-using android::BAD_TYPE;
using android::BAD_VALUE;
using android::NO_ERROR;
using android::Parcel;
using android::status_t;
-using android::UNEXPECTED_NULL;
namespace android {
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 440c98c..b9d00fe 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -2291,7 +2291,7 @@
ssize_t written = TEMP_FAILURE_RETRY(
::write(comm, &message, sizeof(message)));
- if (written == -1 || written != sizeof(message)) {
+ if (written != sizeof(message)) {
ALOGW("Failed to detach ParcelFileDescriptor written: %zd err: %s",
written, strerror(errno));
return BAD_TYPE;
diff --git a/libs/binder/PersistableBundle.cpp b/libs/binder/PersistableBundle.cpp
index c807cfe..406fee0 100644
--- a/libs/binder/PersistableBundle.cpp
+++ b/libs/binder/PersistableBundle.cpp
@@ -31,7 +31,6 @@
using android::BAD_VALUE;
using android::NO_ERROR;
using android::Parcel;
-using android::sp;
using android::status_t;
using android::UNEXPECTED_NULL;
diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h
index c8fb448..31f63c8 100644
--- a/libs/binder/include/binder/IBinder.h
+++ b/libs/binder/include/binder/IBinder.h
@@ -60,6 +60,15 @@
EXTENSION_TRANSACTION = B_PACK_CHARS('_', 'E', 'X', 'T'),
DEBUG_PID_TRANSACTION = B_PACK_CHARS('_', 'P', 'I', 'D'),
+ // See android.os.IBinder.TWEET_TRANSACTION
+ // Most importantly, messages can be anything not exceeding 130 UTF-8
+ // characters, and callees should exclaim "jolly good message old boy!"
+ TWEET_TRANSACTION = B_PACK_CHARS('_', 'T', 'W', 'T'),
+
+ // See android.os.IBinder.LIKE_TRANSACTION
+ // Improve binder self-esteem.
+ LIKE_TRANSACTION = B_PACK_CHARS('_', 'L', 'I', 'K'),
+
// Corresponds to TF_ONE_WAY -- an asynchronous call.
FLAG_ONEWAY = 0x00000001,
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index 0183324..23a0cb0 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -162,6 +162,12 @@
// This constant needs to be kept in sync with Binder.UNSET_WORKSOURCE from the Java
// side.
static const int32_t kUnsetWorkSource = -1;
+
+ // Create a temp reference until commands in queue flushed to driver
+ // Internal only.
+ // @internal
+ void createTransactionReference(RefBase* ref);
+
private:
IPCThreadState();
~IPCThreadState();
diff --git a/libs/binder/include/binder/ParcelRef.h b/libs/binder/include/binder/ParcelRef.h
new file mode 100644
index 0000000..497da2d
--- /dev/null
+++ b/libs/binder/include/binder/ParcelRef.h
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+
+#include <binder/Parcel.h>
+#include <utils/RefBase.h>
+
+// ---------------------------------------------------------------------------
+namespace android {
+
+/**
+ * internal use only
+ * @internal
+ */
+class ParcelRef : public Parcel, public RefBase
+{
+public:
+ static sp<ParcelRef> create() {
+ return new ParcelRef();
+ }
+
+private:
+ ParcelRef() = default;
+};
+
+} // namespace android
+
+// ---------------------------------------------------------------------------
\ No newline at end of file
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 82f3882..897c72a 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -129,6 +129,26 @@
],
}
+cc_library_headers {
+ name: "libbinder_headers_platform_shared",
+ export_include_dirs: ["include_cpp"],
+ vendor_available: true,
+ host_supported: true,
+ // TODO(b/153609531): remove when no longer needed.
+ native_bridge_supported: true,
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.media",
+ "com.android.media.swcodec",
+ ],
+ min_sdk_version: "29",
+}
+
ndk_headers {
name: "libbinder_ndk_headers",
from: "include_ndk/android",
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 454fbd0..3c90681 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -597,13 +597,6 @@
return STATUS_INVALID_OPERATION;
}
- if (!binder->isRemote()) {
- LOG(WARNING) << "A binder object at " << binder
- << " is being transacted on, however, this object is in the same process as "
- "its proxy. Transacting with this binder is expensive compared to just "
- "calling the corresponding functionality in the same process.";
- }
-
*in = new AParcel(binder);
status_t status = (*in)->get()->writeInterfaceToken(clazz->getInterfaceDescriptor());
binder_status_t ret = PruneStatusT(status);
diff --git a/libs/binder/ndk/include_cpp/android/binder_to_string.h b/libs/binder/ndk/include_cpp/android/binder_to_string.h
new file mode 100644
index 0000000..bd51b11
--- /dev/null
+++ b/libs/binder/ndk/include_cpp/android/binder_to_string.h
@@ -0,0 +1,184 @@
+/*
+ * 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.
+ */
+
+/**
+ * @addtogroup NdkBinder
+ * @{
+ */
+
+/**
+ * @file binder_to_string.h
+ * @brief Helper for parcelable.
+ */
+
+#pragma once
+
+#include <codecvt>
+#include <locale>
+#include <sstream>
+#include <string>
+#include <type_traits>
+
+#if __has_include(<android/binder_ibinder.h>)
+#include <android/binder_auto_utils.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_parcelable_utils.h>
+#define HAS_NDK_INTERFACE
+#else
+#include <binder/IBinder.h>
+#include <binder/IInterface.h>
+#include <binder/ParcelFileDescriptor.h>
+#include <binder/ParcelableHolder.h>
+#include <utils/String16.h>
+#include <utils/StrongPointer.h>
+#define HAS_CPP_INTERFACE
+#endif //_has_include
+
+namespace android {
+namespace internal {
+
+// ToString is a utility to generate string representation for various AIDL-supported types.
+template <typename _T>
+std::string ToString(const _T& t);
+
+namespace details {
+
+// Truthy if _T has toString() method.
+template <typename _T>
+class HasToStringMethod {
+ template <typename _U>
+ static auto _test(int) -> decltype(std::declval<_U>().toString(), std::true_type());
+ template <typename _U>
+ static std::false_type _test(...);
+
+ public:
+ enum { value = decltype(_test<_T>(0))::value };
+};
+
+// Truthy if _T has a overloaded toString(T)
+template <typename _T>
+class HasToStringFunction {
+ template <typename _U>
+ static auto _test(int) -> decltype(toString(std::declval<_U>()), std::true_type());
+ template <typename _U>
+ static std::false_type _test(...);
+
+ public:
+ enum { value = decltype(_test<_T>(0))::value };
+};
+
+// Truthy if _T is like a pointer
+template <typename _T>
+class IsPointerLike {
+ template <typename _U>
+ static auto _test(int) -> decltype(!std::declval<_U>(), *std::declval<_U>(), std::true_type());
+ template <typename _U>
+ static std::false_type _test(...);
+
+ public:
+ enum { value = decltype(_test<_T>(0))::value };
+};
+
+// Truthy if _T is like a container
+template <typename _T>
+class IsIterable {
+ template <typename _U>
+ static auto _test(int)
+ -> decltype(begin(std::declval<_U>()), end(std::declval<_U>()), std::true_type());
+ template <typename _U>
+ static std::false_type _test(...);
+
+ public:
+ enum { value = decltype(_test<_T>(0))::value };
+};
+
+template <typename _T>
+class ToEmptyString {
+ template <typename _U>
+ static std::enable_if_t<
+#ifdef HAS_NDK_INTERFACE
+ std::is_base_of_v<::ndk::ICInterface, _U> || std::is_same_v<::ndk::SpAIBinder, _U> ||
+ std::is_same_v<::ndk::ScopedFileDescriptor, _U> ||
+ std::is_same_v<::ndk::AParcelableHolder, _U>
+#else
+ std::is_base_of_v<IInterface, _U> || std::is_same_v<IBinder, _U> ||
+ std::is_same_v<os::ParcelFileDescriptor, _U> ||
+ std::is_same_v<os::ParcelableHolder, _U>
+#endif
+ ,
+ std::true_type>
+ _test(int);
+ template <typename _U>
+ static std::false_type _test(...);
+
+ public:
+ enum { value = decltype(_test<_T>(0))::value };
+};
+
+} // namespace details
+
+template <typename _T>
+std::string ToString(const _T& t) {
+ if constexpr (details::ToEmptyString<_T>::value) {
+ return "";
+ } else if constexpr (std::is_same_v<bool, _T>) {
+ return t ? "true" : "false";
+ } else if constexpr (std::is_same_v<char16_t, _T>) {
+ return std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>().to_bytes(t);
+ } else if constexpr (std::is_arithmetic_v<_T>) {
+ return std::to_string(t);
+ } else if constexpr (std::is_same_v<std::string, _T>) {
+ return t;
+#ifdef HAS_CPP_INTERFACE
+ } else if constexpr (std::is_same_v<String16, _T>) {
+ std::stringstream out;
+ out << t;
+ return out.str();
+#endif
+ } else if constexpr (details::HasToStringMethod<_T>::value) {
+ return t.toString();
+ } else if constexpr (details::HasToStringFunction<_T>::value) {
+ return toString(t);
+ } else if constexpr (details::IsIterable<_T>::value) {
+ std::stringstream out;
+ bool first = true;
+ out << "[";
+ for (const auto& e : t) {
+ if (first) {
+ first = false;
+ } else {
+ out << ", ";
+ }
+ // Use explicit type parameter in case deref of iterator has different type
+ // e.g. vector<bool>
+ out << ToString<typename _T::value_type>(e);
+ }
+ out << "]";
+ return out.str();
+ } else if constexpr (details::IsPointerLike<_T>::value) {
+ if (!t) return "(null)";
+ std::stringstream out;
+ out << ToString(*t);
+ return out.str();
+ } else {
+ return "{no toString() implemented}";
+ }
+}
+
+} // namespace internal
+} // namespace android
+
+/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index bb70588..a44c261 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -41,8 +41,6 @@
android platform host build, you must use libbinder_ndk_host_user.
#endif
-#if __ANDROID_API__ >= 29
-
typedef uint32_t binder_flags_t;
enum {
/**
@@ -567,10 +565,6 @@
*/
void AIBinder_DeathRecipient_delete(AIBinder_DeathRecipient* recipient) __INTRODUCED_IN(29);
-#endif //__ANDROID_API__ >= 29
-
-#if __ANDROID_API__ >= 30
-
/**
* Gets the extension registered with AIBinder_setExtension.
*
@@ -640,10 +634,6 @@
*/
binder_status_t AIBinder_setExtension(AIBinder* binder, AIBinder* ext) __INTRODUCED_IN(30);
-#endif //__ANDROID_API__ >= 30
-
-#if __ANDROID_API__ >= 31
-
/**
* Retrieve the class descriptor for the class.
*
@@ -728,8 +718,6 @@
*/
bool AIBinder_Weak_lt(const AIBinder_Weak* lhs, const AIBinder_Weak* rhs);
-#endif //__ANDROID_API__ >= 31
-
__END_DECLS
/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h b/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h
index cd1ff1f..6880d86 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder_jni.h
@@ -31,7 +31,6 @@
#include <jni.h>
__BEGIN_DECLS
-#if __ANDROID_API__ >= 29
/**
* Converts an android.os.IBinder object into an AIBinder* object.
@@ -67,7 +66,6 @@
__attribute__((warn_unused_result)) jobject AIBinder_toJavaBinder(JNIEnv* env, AIBinder* binder)
__INTRODUCED_IN(29);
-#endif //__ANDROID_API__ >= 29
__END_DECLS
/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h
index ab67017..527b151 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h
@@ -36,7 +36,6 @@
typedef struct AIBinder AIBinder;
__BEGIN_DECLS
-#if __ANDROID_API__ >= 29
/**
* This object represents a package of data that can be sent between processes. When transacting, an
@@ -1119,7 +1118,6 @@
// @END-PRIMITIVE-READ-WRITE
-#endif //__ANDROID_API__ >= 29
/**
* Reset the parcel to the initial status.
*
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel_jni.h b/libs/binder/ndk/include_ndk/android/binder_parcel_jni.h
index 65e1704..384d4f7 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel_jni.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel_jni.h
@@ -31,7 +31,6 @@
#include <jni.h>
__BEGIN_DECLS
-#if __ANDROID_API__ >= 30
/**
* Converts an android.os.Parcel object into an AParcel* object.
@@ -50,7 +49,6 @@
__attribute__((warn_unused_result)) AParcel* AParcel_fromJavaParcel(JNIEnv* env, jobject parcel)
__INTRODUCED_IN(30);
-#endif //__ANDROID_API__ >= 30
__END_DECLS
/** @} */
diff --git a/libs/binder/ndk/include_ndk/android/binder_status.h b/libs/binder/ndk/include_ndk/android/binder_status.h
index 3a55f94..05b25e7 100644
--- a/libs/binder/ndk/include_ndk/android/binder_status.h
+++ b/libs/binder/ndk/include_ndk/android/binder_status.h
@@ -31,7 +31,6 @@
#include <sys/cdefs.h>
__BEGIN_DECLS
-#if __ANDROID_API__ >= 29
enum {
STATUS_OK = 0,
@@ -275,7 +274,6 @@
*/
void AStatus_delete(AStatus* status) __INTRODUCED_IN(29);
-#endif //__ANDROID_API__ >= 29
__END_DECLS
/** @} */
diff --git a/libs/binder/rust/tests/serialization.rs b/libs/binder/rust/tests/serialization.rs
index 2ae13f4..2bf3d03 100644
--- a/libs/binder/rust/tests/serialization.rs
+++ b/libs/binder/rust/tests/serialization.rs
@@ -25,7 +25,6 @@
use binder::parcel::ParcelFileDescriptor;
use std::ffi::{c_void, CStr, CString};
-use std::panic::{self, AssertUnwindSafe};
use std::sync::Once;
#[allow(
@@ -73,22 +72,9 @@
impl ReadParcelTest for () {}
-fn on_transact(
- _service: &dyn ReadParcelTest,
- code: TransactionCode,
- parcel: &Parcel,
- reply: &mut Parcel,
-) -> Result<()> {
- panic::catch_unwind(AssertUnwindSafe(|| transact_inner(code, parcel, reply))).unwrap_or_else(
- |e| {
- eprintln!("Failure in Rust: {:?}", e.downcast_ref::<String>());
- Err(StatusCode::FAILED_TRANSACTION)
- },
- )
-}
-
#[allow(clippy::float_cmp)]
-fn transact_inner(code: TransactionCode, parcel: &Parcel, reply: &mut Parcel) -> Result<()> {
+fn on_transact(_service: &dyn ReadParcelTest, code: TransactionCode,
+ parcel: &Parcel, reply: &mut Parcel) -> Result<()> {
match code {
bindings::Transaction_TEST_BOOL => {
assert_eq!(parcel.read::<bool>()?, true);
@@ -296,7 +282,7 @@
))?;
}
bindings::Transaction_TEST_FAIL => {
- panic!("Testing expected failure");
+ return Err(StatusCode::FAILED_TRANSACTION)
}
_ => return Err(StatusCode::UNKNOWN_TRANSACTION),
}
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 988f7f3..259417a 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -220,3 +220,15 @@
test_suites: ["device-tests"],
require_root: true,
}
+
+cc_benchmark {
+ name: "binderParcelBenchmark",
+ defaults: ["binder_test_defaults"],
+ srcs: ["binderParcelBenchmark.cpp"],
+ shared_libs: [
+ "libbase",
+ "libbinder",
+ "liblog",
+ "libutils",
+ ],
+}
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index a5261e5..e2193fa 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -21,6 +21,7 @@
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
+#include <thread>
#include <gtest/gtest.h>
@@ -28,6 +29,7 @@
#include <binder/IBinder.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
+#include <binder/ParcelRef.h>
#include <private/binder/binder_module.h>
#include <linux/sched.h>
@@ -916,6 +918,36 @@
}
}
+TEST_F(BinderLibTest, ParcelAllocatedOnAnotherThread) {
+ sp<IBinder> server = addServer();
+ ASSERT_TRUE(server != nullptr);
+
+ Parcel data;
+ sp<ParcelRef> reply = ParcelRef::create();
+
+ // when we have a Parcel which is deleted on another thread, if it gets
+ // deleted, it will tell the kernel this, and it will drop strong references
+ // to binder, so that we can't BR_ACQUIRE would fail
+ IPCThreadState::self()->createTransactionReference(reply.get());
+ ASSERT_EQ(NO_ERROR, server->transact(BINDER_LIB_TEST_CREATE_BINDER_TRANSACTION,
+ data,
+ reply.get()));
+
+ // we have sp to binder, but it is not actually acquired by kernel, the
+ // transaction is sitting on an out buffer
+ sp<IBinder> binder = reply->readStrongBinder();
+
+ std::thread([&] {
+ // without the transaction reference, this would cause the Parcel to be
+ // deallocated before the first thread flushes BR_ACQUIRE
+ reply = nullptr;
+ IPCThreadState::self()->flushCommands();
+ }).join();
+
+ ASSERT_NE(nullptr, binder);
+ ASSERT_EQ(NO_ERROR, binder->pingBinder());
+}
+
TEST_F(BinderLibTest, CheckNoHeaderMappedInUser) {
status_t ret;
Parcel data, reply;
diff --git a/libs/binder/tests/binderParcelBenchmark.cpp b/libs/binder/tests/binderParcelBenchmark.cpp
new file mode 100644
index 0000000..ec69c36
--- /dev/null
+++ b/libs/binder/tests/binderParcelBenchmark.cpp
@@ -0,0 +1,172 @@
+/*
+ * 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.
+ */
+
+#include <binder/Parcel.h>
+#include <benchmark/benchmark.h>
+
+// Usage: atest binderParcelBenchmark
+
+// For static assert(false) we need a template version to avoid early failure.
+// See: https://stackoverflow.com/questions/51523965/template-dependent-false
+template <typename T>
+constexpr bool dependent_false_v = false;
+
+template <template <typename ...> class V, typename T, typename... Args>
+void writeVector(android::Parcel &p, const V<T, Args...> &v) {
+ if constexpr (std::is_same_v<T, bool>) {
+ p.writeBoolVector(v);
+ } else if constexpr (std::is_same_v<T, uint8_t>) {
+ p.writeByteVector(v);
+ } else if constexpr (std::is_same_v<T, char16_t>) {
+ p.writeCharVector(v);
+ } else if constexpr (std::is_same_v<T, int32_t>) {
+ p.writeInt32Vector(v);
+ } else if constexpr (std::is_same_v<T, int64_t>) {
+ p.writeInt64Vector(v);
+ } else {
+ static_assert(dependent_false_v<V<T>>);
+ }
+}
+
+template <template <typename ...> class V, typename T, typename... Args>
+void readVector(android::Parcel &p, V<T, Args...> *v) {
+ if constexpr (std::is_same_v<T, bool>) {
+ p.readBoolVector(v);
+ } else if constexpr (std::is_same_v<T, uint8_t>) {
+ p.readByteVector(v);
+ } else if constexpr (std::is_same_v<T, char16_t>) {
+ p.readCharVector(v);
+ } else if constexpr (std::is_same_v<T, int32_t>) {
+ p.readInt32Vector(v);
+ } else if constexpr (std::is_same_v<T, int64_t>) {
+ p.readInt64Vector(v);
+ } else {
+ static_assert(dependent_false_v<V<T>>);
+ }
+}
+
+// Construct a series of args { 1 << 0, 1 << 1, ..., 1 << 10 }
+static void VectorArgs(benchmark::internal::Benchmark* b) {
+ for (int i = 0; i < 10; ++i) {
+ b->Args({1 << i});
+ }
+}
+
+template <typename T>
+static void BM_ParcelVector(benchmark::State& state) {
+ const size_t elements = state.range(0);
+
+ std::vector<T> v1(elements);
+ std::vector<T> v2(elements);
+ android::Parcel p;
+ while (state.KeepRunning()) {
+ p.setDataPosition(0);
+ writeVector(p, v1);
+
+ p.setDataPosition(0);
+ readVector(p, &v2);
+
+ benchmark::DoNotOptimize(v2[0]);
+ benchmark::ClobberMemory();
+ }
+ state.SetComplexityN(elements);
+}
+
+/*
+ Parcel vector write than read.
+ The read and write vectors are fixed, no resizing required.
+
+ Results on Crosshatch Pixel 3XL
+
+ #BM_BoolVector/1 40 ns 40 ns 17261011
+ #BM_BoolVector/2 46 ns 46 ns 15029619
+ #BM_BoolVector/4 65 ns 64 ns 10888021
+ #BM_BoolVector/8 114 ns 114 ns 6130937
+ #BM_BoolVector/16 179 ns 179 ns 3902462
+ #BM_BoolVector/32 328 ns 327 ns 2138812
+ #BM_BoolVector/64 600 ns 598 ns 1169414
+ #BM_BoolVector/128 1168 ns 1165 ns 601281
+ #BM_BoolVector/256 2288 ns 2281 ns 305737
+ #BM_BoolVector/512 4535 ns 4521 ns 154668
+ #BM_ByteVector/1 53 ns 52 ns 13212196
+ #BM_ByteVector/2 53 ns 53 ns 13194050
+ #BM_ByteVector/4 50 ns 50 ns 13768037
+ #BM_ByteVector/8 50 ns 50 ns 13890210
+ #BM_ByteVector/16 50 ns 50 ns 13897305
+ #BM_ByteVector/32 51 ns 51 ns 13679862
+ #BM_ByteVector/64 54 ns 53 ns 12988544
+ #BM_ByteVector/128 64 ns 64 ns 10921227
+ #BM_ByteVector/256 82 ns 81 ns 8542549
+ #BM_ByteVector/512 118 ns 118 ns 5862931
+ #BM_CharVector/1 32 ns 32 ns 21783579
+ #BM_CharVector/2 38 ns 38 ns 18200971
+ #BM_CharVector/4 53 ns 53 ns 13111785
+ #BM_CharVector/8 80 ns 80 ns 8698331
+ #BM_CharVector/16 159 ns 159 ns 4390738
+ #BM_CharVector/32 263 ns 262 ns 2667310
+ #BM_CharVector/64 486 ns 485 ns 1441118
+ #BM_CharVector/128 937 ns 934 ns 749006
+ #BM_CharVector/256 1848 ns 1843 ns 379537
+ #BM_CharVector/512 3650 ns 3639 ns 191713
+ #BM_Int32Vector/1 31 ns 31 ns 22104147
+ #BM_Int32Vector/2 38 ns 38 ns 18075471
+ #BM_Int32Vector/4 53 ns 52 ns 13249969
+ #BM_Int32Vector/8 80 ns 80 ns 8719798
+ #BM_Int32Vector/16 161 ns 160 ns 4350096
+ #BM_Int32Vector/32 271 ns 270 ns 2591896
+ #BM_Int32Vector/64 499 ns 498 ns 1406201
+ #BM_Int32Vector/128 948 ns 945 ns 740052
+ #BM_Int32Vector/256 1855 ns 1849 ns 379127
+ #BM_Int32Vector/512 3665 ns 3653 ns 191533
+ #BM_Int64Vector/1 31 ns 31 ns 22388370
+ #BM_Int64Vector/2 38 ns 38 ns 18300347
+ #BM_Int64Vector/4 53 ns 53 ns 13137818
+ #BM_Int64Vector/8 81 ns 81 ns 8599613
+ #BM_Int64Vector/16 167 ns 166 ns 4195953
+ #BM_Int64Vector/32 280 ns 280 ns 2499271
+ #BM_Int64Vector/64 523 ns 522 ns 1341380
+ #BM_Int64Vector/128 991 ns 988 ns 707437
+ #BM_Int64Vector/256 1940 ns 1934 ns 361704
+ #BM_Int64Vector/512 3843 ns 3831 ns 183204
+*/
+
+static void BM_BoolVector(benchmark::State& state) {
+ BM_ParcelVector<bool>(state);
+}
+
+static void BM_ByteVector(benchmark::State& state) {
+ BM_ParcelVector<uint8_t>(state);
+}
+
+static void BM_CharVector(benchmark::State& state) {
+ BM_ParcelVector<char16_t>(state);
+}
+
+static void BM_Int32Vector(benchmark::State& state) {
+ BM_ParcelVector<int32_t>(state);
+}
+
+static void BM_Int64Vector(benchmark::State& state) {
+ BM_ParcelVector<int64_t>(state);
+}
+
+BENCHMARK(BM_BoolVector)->Apply(VectorArgs);
+BENCHMARK(BM_ByteVector)->Apply(VectorArgs);
+BENCHMARK(BM_CharVector)->Apply(VectorArgs);
+BENCHMARK(BM_Int32Vector)->Apply(VectorArgs);
+BENCHMARK(BM_Int64Vector)->Apply(VectorArgs);
+
+BENCHMARK_MAIN();
diff --git a/libs/cputimeinstate/cputimeinstate.cpp b/libs/cputimeinstate/cputimeinstate.cpp
index 462f0db..7e9bb7d 100644
--- a/libs/cputimeinstate/cputimeinstate.cpp
+++ b/libs/cputimeinstate/cputimeinstate.cpp
@@ -155,10 +155,14 @@
return true;
}
-static bool attachTracepointProgram(const std::string &eventType, const std::string &eventName) {
+static int retrieveProgramFd(const std::string &eventType, const std::string &eventName) {
std::string path = StringPrintf(BPF_FS_PATH "prog_time_in_state_tracepoint_%s_%s",
eventType.c_str(), eventName.c_str());
- int prog_fd = retrieveProgram(path.c_str());
+ return retrieveProgram(path.c_str());
+}
+
+static bool attachTracepointProgram(const std::string &eventType, const std::string &eventName) {
+ int prog_fd = retrieveProgramFd(eventType, eventName);
if (prog_fd < 0) return false;
return bpf_attach_tracepoint(prog_fd, eventType.c_str(), eventName.c_str()) >= 0;
}
@@ -174,6 +178,17 @@
return {};
}
+// Check if tracking is expected to work without activating it.
+bool isTrackingUidTimesSupported() {
+ auto freqs = getCpuFreqs();
+ if (!freqs || freqs->empty()) return false;
+ if (gTracking) return true;
+ if (retrieveProgramFd("sched", "sched_switch") < 0) return false;
+ if (retrieveProgramFd("power", "cpu_frequency") < 0) return false;
+ if (retrieveProgramFd("sched", "sched_process_free") < 0) return false;
+ return true;
+}
+
// Start tracking and aggregating data to be reported by getUidCpuFreqTimes and getUidsCpuFreqTimes.
// Returns true on success, false otherwise.
// Tracking is active only once a live process has successfully called this function; if the calling
diff --git a/libs/cputimeinstate/cputimeinstate.h b/libs/cputimeinstate/cputimeinstate.h
index 46de669..4145374 100644
--- a/libs/cputimeinstate/cputimeinstate.h
+++ b/libs/cputimeinstate/cputimeinstate.h
@@ -22,6 +22,7 @@
namespace android {
namespace bpf {
+bool isTrackingUidTimesSupported();
bool startTrackingUidTimes();
std::optional<std::vector<std::vector<uint64_t>>> getTotalCpuFreqTimes();
std::optional<std::vector<std::vector<uint64_t>>> getUidCpuFreqTimes(uint32_t uid);
diff --git a/libs/cputimeinstate/testtimeinstate.cpp b/libs/cputimeinstate/testtimeinstate.cpp
index d25b2e9..2112b10 100644
--- a/libs/cputimeinstate/testtimeinstate.cpp
+++ b/libs/cputimeinstate/testtimeinstate.cpp
@@ -40,6 +40,11 @@
using std::vector;
+TEST(TimeInStateTest, IsTrackingSupported) {
+ isTrackingUidTimesSupported();
+ SUCCEED();
+}
+
TEST(TimeInStateTest, TotalTimeInState) {
auto times = getTotalCpuFreqTimes();
ASSERT_TRUE(times.has_value());
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index 143fa13..8a82c2a 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -53,7 +53,6 @@
/* list of hal interface to dump containing process during native dumps */
static const char* hal_interfaces_to_dump[] {
- "android.hardware.audio@2.0::IDevicesFactory",
"android.hardware.audio@4.0::IDevicesFactory",
"android.hardware.audio@5.0::IDevicesFactory",
"android.hardware.audio@6.0::IDevicesFactory",
diff --git a/libs/gralloc/types/Android.bp b/libs/gralloc/types/Android.bp
index 243d7f1..dd0ae30 100644
--- a/libs/gralloc/types/Android.bp
+++ b/libs/gralloc/types/Android.bp
@@ -43,14 +43,14 @@
],
shared_libs: [
- "android.hardware.graphics.common-unstable-ndk_platform",
+ "android.hardware.graphics.common-V2-ndk_platform",
"android.hardware.graphics.mapper@4.0",
"libhidlbase",
"liblog",
],
export_shared_lib_headers: [
- "android.hardware.graphics.common-unstable-ndk_platform",
+ "android.hardware.graphics.common-V2-ndk_platform",
"android.hardware.graphics.mapper@4.0",
"libhidlbase",
],
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 38ae353..fa5044c 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -49,6 +49,7 @@
srcs: [
":framework_native_aidl",
+ ":inputconstants_aidl",
":libgui_aidl",
":libgui_bufferqueue_sources",
@@ -62,6 +63,7 @@
"DebugEGLImageTracker.cpp",
"DisplayEventDispatcher.cpp",
"DisplayEventReceiver.cpp",
+ "FrameTimelineInfo.cpp",
"GLConsumer.cpp",
"IConsumerListener.cpp",
"IDisplayEventConnection.cpp",
@@ -154,6 +156,7 @@
defaults: ["libgui_bufferqueue-defaults"],
srcs: [
+ ":inputconstants_aidl",
":libgui_aidl",
":libgui_bufferqueue_sources",
],
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 42d2895..1e6fc2b 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -133,8 +133,10 @@
if (enableTripleBuffering) {
mProducer->setMaxDequeuedBufferCount(2);
}
- mBufferItemConsumer =
- new BLASTBufferItemConsumer(mConsumer, GraphicBuffer::USAGE_HW_COMPOSER, 1, false);
+ mBufferItemConsumer = new BLASTBufferItemConsumer(mConsumer,
+ GraphicBuffer::USAGE_HW_COMPOSER |
+ GraphicBuffer::USAGE_HW_TEXTURE,
+ 1, false);
static int32_t id = 0;
auto consumerName = mName + "(BLAST Consumer)" + std::to_string(id);
id++;
@@ -142,7 +144,7 @@
mBufferItemConsumer->setFrameAvailableListener(this);
mBufferItemConsumer->setBufferFreedListener(this);
mBufferItemConsumer->setDefaultBufferSize(mSize.width, mSize.height);
- mBufferItemConsumer->setDefaultBufferFormat(format);
+ mBufferItemConsumer->setDefaultBufferFormat(convertBufferFormat(format));
mTransformHint = mSurfaceControl->getTransformHint();
mBufferItemConsumer->setTransformHint(mTransformHint);
@@ -175,7 +177,7 @@
std::unique_lock _lock{mMutex};
if (mFormat != format) {
mFormat = format;
- mBufferItemConsumer->setDefaultBufferFormat(format);
+ mBufferItemConsumer->setDefaultBufferFormat(convertBufferFormat(format));
}
SurfaceComposerClient::Transaction t;
@@ -370,9 +372,9 @@
}
t->setFrameNumber(mSurfaceControl, bufferItem.mFrameNumber);
- if (!mNextFrameTimelineVsyncIdQueue.empty()) {
- t->setFrameTimelineVsync(mSurfaceControl, mNextFrameTimelineVsyncIdQueue.front());
- mNextFrameTimelineVsyncIdQueue.pop();
+ if (!mNextFrameTimelineInfoQueue.empty()) {
+ t->setFrameTimelineInfo(mSurfaceControl, mNextFrameTimelineInfoQueue.front());
+ mNextFrameTimelineInfoQueue.pop();
}
if (mAutoRefresh != bufferItem.mAutoRefresh) {
@@ -534,8 +536,8 @@
return mBbq->setFrameRate(frameRate, compatibility, shouldBeSeamless);
}
- status_t setFrameTimelineVsync(int64_t frameTimelineVsyncId) override {
- return mBbq->setFrameTimelineVsync(frameTimelineVsyncId);
+ status_t setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo) override {
+ return mBbq->setFrameTimelineInfo(frameTimelineInfo);
}
};
@@ -549,9 +551,9 @@
return t.setFrameRate(mSurfaceControl, frameRate, compatibility, shouldBeSeamless).apply();
}
-status_t BLASTBufferQueue::setFrameTimelineVsync(int64_t frameTimelineVsyncId) {
+status_t BLASTBufferQueue::setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo) {
std::unique_lock _lock{mMutex};
- mNextFrameTimelineVsyncIdQueue.push(frameTimelineVsyncId);
+ mNextFrameTimelineInfoQueue.push(frameTimelineInfo);
return OK;
}
@@ -683,4 +685,18 @@
*outConsumer = consumer;
}
+PixelFormat BLASTBufferQueue::convertBufferFormat(PixelFormat& format) {
+ PixelFormat convertedFormat = format;
+ switch (format) {
+ case PIXEL_FORMAT_TRANSPARENT:
+ case PIXEL_FORMAT_TRANSLUCENT:
+ convertedFormat = PIXEL_FORMAT_RGBA_8888;
+ break;
+ case PIXEL_FORMAT_OPAQUE:
+ convertedFormat = PIXEL_FORMAT_RGBX_8888;
+ break;
+ }
+ return convertedFormat;
+}
+
} // namespace android
diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp
index c6c9a8f..9cd3f63 100644
--- a/libs/gui/DisplayEventDispatcher.cpp
+++ b/libs/gui/DisplayEventDispatcher.cpp
@@ -156,9 +156,9 @@
case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
dispatchHotplug(ev.header.timestamp, ev.header.displayId, ev.hotplug.connected);
break;
- case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED:
- dispatchConfigChanged(ev.header.timestamp, ev.header.displayId,
- ev.config.configId, ev.config.vsyncPeriod);
+ case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE:
+ dispatchModeChanged(ev.header.timestamp, ev.header.displayId,
+ ev.modeChange.modeId, ev.modeChange.vsyncPeriod);
break;
case DisplayEventReceiver::DISPLAY_EVENT_NULL:
dispatchNullEvent(ev.header.timestamp, ev.header.displayId);
diff --git a/libs/gui/FrameTimelineInfo.cpp b/libs/gui/FrameTimelineInfo.cpp
new file mode 100644
index 0000000..f400774
--- /dev/null
+++ b/libs/gui/FrameTimelineInfo.cpp
@@ -0,0 +1,62 @@
+/*
+ * 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 <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);
+ return NO_ERROR;
+}
+
+status_t FrameTimelineInfo::read(const Parcel& input) {
+ SAFE_PARCEL(input.readInt64, &vsyncId);
+ SAFE_PARCEL(input.readInt32, &inputEventId);
+ 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;
+ }
+ } else if (vsyncId == INVALID_VSYNC_ID) {
+ vsyncId = other.vsyncId;
+ inputEventId = other.inputEventId;
+ }
+}
+
+void FrameTimelineInfo::clear() {
+ vsyncId = INVALID_VSYNC_ID;
+ inputEventId = IInputConstants::INVALID_INPUT_EVENT_ID;
+}
+
+}; // namespace android
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index a8d6832..10d48a3 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -36,8 +36,8 @@
#include <system/graphics.h>
-#include <ui/DisplayConfig.h>
#include <ui/DisplayInfo.h>
+#include <ui/DisplayMode.h>
#include <ui/DisplayStatInfo.h>
#include <ui/DisplayState.h>
#include <ui/HdrCapabilities.h>
@@ -68,16 +68,19 @@
return interface_cast<ISurfaceComposerClient>(reply.readStrongBinder());
}
- virtual status_t setTransactionState(
- int64_t frameTimelineVsyncId, const Vector<ComposerState>& state,
- const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
- const InputWindowCommands& commands, int64_t desiredPresentTime, bool isAutoTimestamp,
- const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
- const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) {
+ status_t setTransactionState(const FrameTimelineInfo& frameTimelineInfo,
+ const Vector<ComposerState>& state,
+ const Vector<DisplayState>& displays, uint32_t flags,
+ const sp<IBinder>& applyToken, const InputWindowCommands& commands,
+ int64_t desiredPresentTime, bool isAutoTimestamp,
+ const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
+ const std::vector<ListenerCallbacks>& listenerCallbacks,
+ uint64_t transactionId) override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
- SAFE_PARCEL(data.writeInt64, frameTimelineVsyncId);
+ SAFE_PARCEL(frameTimelineInfo.write, data);
+
SAFE_PARCEL(data.writeUint32, static_cast<uint32_t>(state.size()));
for (const auto& s : state) {
SAFE_PARCEL(s.write, data);
@@ -108,15 +111,14 @@
return remote()->transact(BnSurfaceComposer::SET_TRANSACTION_STATE, data, &reply);
}
- virtual void bootFinished()
- {
+ void bootFinished() override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply);
}
- virtual status_t captureDisplay(const DisplayCaptureArgs& args,
- const sp<IScreenCaptureListener>& captureListener) {
+ status_t captureDisplay(const DisplayCaptureArgs& args,
+ const sp<IScreenCaptureListener>& captureListener) override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
SAFE_PARCEL(args.write, data);
@@ -125,8 +127,8 @@
return remote()->transact(BnSurfaceComposer::CAPTURE_DISPLAY, data, &reply);
}
- virtual status_t captureDisplay(uint64_t displayOrLayerStack,
- const sp<IScreenCaptureListener>& captureListener) {
+ status_t captureDisplay(uint64_t displayOrLayerStack,
+ const sp<IScreenCaptureListener>& captureListener) override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
SAFE_PARCEL(data.writeUint64, displayOrLayerStack);
@@ -135,8 +137,8 @@
return remote()->transact(BnSurfaceComposer::CAPTURE_DISPLAY_BY_ID, data, &reply);
}
- virtual status_t captureLayers(const LayerCaptureArgs& args,
- const sp<IScreenCaptureListener>& captureListener) {
+ status_t captureLayers(const LayerCaptureArgs& args,
+ const sp<IScreenCaptureListener>& captureListener) override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
SAFE_PARCEL(args.write, data);
@@ -145,9 +147,8 @@
return remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply);
}
- virtual bool authenticateSurfaceTexture(
- const sp<IGraphicBufferProducer>& bufferProducer) const
- {
+ bool authenticateSurfaceTexture(
+ const sp<IGraphicBufferProducer>& bufferProducer) const override {
Parcel data, reply;
int err = NO_ERROR;
err = data.writeInterfaceToken(
@@ -180,8 +181,7 @@
return result != 0;
}
- virtual status_t getSupportedFrameTimestamps(
- std::vector<FrameEvent>* outSupported) const {
+ status_t getSupportedFrameTimestamps(std::vector<FrameEvent>* outSupported) const override {
if (!outSupported) {
return UNEXPECTED_NULL;
}
@@ -224,8 +224,8 @@
return NO_ERROR;
}
- virtual sp<IDisplayEventConnection> createDisplayEventConnection(
- VsyncSource vsyncSource, EventRegistrationFlags eventRegistration) {
+ sp<IDisplayEventConnection> createDisplayEventConnection(
+ VsyncSource vsyncSource, EventRegistrationFlags eventRegistration) override {
Parcel data, reply;
sp<IDisplayEventConnection> result;
int err = data.writeInterfaceToken(
@@ -247,8 +247,7 @@
return result;
}
- virtual sp<IBinder> createDisplay(const String8& displayName, bool secure)
- {
+ sp<IBinder> createDisplay(const String8& displayName, bool secure) override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
status_t status = data.writeString8(displayName);
@@ -272,15 +271,14 @@
return display;
}
- virtual void destroyDisplay(const sp<IBinder>& display)
- {
+ void destroyDisplay(const sp<IBinder>& display) override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeStrongBinder(display);
remote()->transact(BnSurfaceComposer::DESTROY_DISPLAY, data, &reply);
}
- virtual std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const {
+ std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (remote()->transact(BnSurfaceComposer::GET_PHYSICAL_DISPLAY_IDS, data, &reply) ==
@@ -297,7 +295,7 @@
return {};
}
- virtual sp<IBinder> getPhysicalDisplayToken(PhysicalDisplayId displayId) const {
+ sp<IBinder> getPhysicalDisplayToken(PhysicalDisplayId displayId) const override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeUint64(displayId.value);
@@ -305,8 +303,7 @@
return reply.readStrongBinder();
}
- virtual void setPowerMode(const sp<IBinder>& display, int mode)
- {
+ void setPowerMode(const sp<IBinder>& display, int mode) override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeStrongBinder(display);
@@ -314,7 +311,7 @@
remote()->transact(BnSurfaceComposer::SET_POWER_MODE, data, &reply);
}
- virtual status_t getDisplayState(const sp<IBinder>& display, ui::DisplayState* state) {
+ status_t getDisplayState(const sp<IBinder>& display, ui::DisplayState* state) override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeStrongBinder(display);
@@ -326,7 +323,7 @@
return result;
}
- virtual status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info) {
+ status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo* info) override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeStrongBinder(display);
@@ -336,27 +333,25 @@
return reply.read(*info);
}
- virtual status_t getDisplayConfigs(const sp<IBinder>& display, Vector<DisplayConfig>* configs) {
+ status_t getDisplayModes(const sp<IBinder>& display, Vector<ui::DisplayMode>* modes) override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeStrongBinder(display);
- remote()->transact(BnSurfaceComposer::GET_DISPLAY_CONFIGS, data, &reply);
+ remote()->transact(BnSurfaceComposer::GET_DISPLAY_MODES, data, &reply);
const status_t result = reply.readInt32();
if (result == NO_ERROR) {
- const size_t numConfigs = reply.readUint32();
- configs->clear();
- configs->resize(numConfigs);
- for (size_t c = 0; c < numConfigs; ++c) {
- memcpy(&(configs->editItemAt(c)), reply.readInplace(sizeof(DisplayConfig)),
- sizeof(DisplayConfig));
+ const size_t numModes = reply.readUint32();
+ modes->clear();
+ modes->resize(numModes);
+ for (size_t i = 0; i < numModes; i++) {
+ memcpy(&(modes->editItemAt(i)), reply.readInplace(sizeof(ui::DisplayMode)),
+ sizeof(ui::DisplayMode));
}
}
return result;
}
- virtual status_t getDisplayStats(const sp<IBinder>& display,
- DisplayStatInfo* stats)
- {
+ status_t getDisplayStats(const sp<IBinder>& display, DisplayStatInfo* stats) override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeStrongBinder(display);
@@ -370,17 +365,16 @@
return result;
}
- virtual int getActiveConfig(const sp<IBinder>& display)
- {
+ int getActiveDisplayModeId(const sp<IBinder>& display) override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeStrongBinder(display);
- remote()->transact(BnSurfaceComposer::GET_ACTIVE_CONFIG, data, &reply);
+ remote()->transact(BnSurfaceComposer::GET_ACTIVE_DISPLAY_MODE, data, &reply);
return reply.readInt32();
}
- virtual status_t getDisplayColorModes(const sp<IBinder>& display,
- Vector<ColorMode>* outColorModes) {
+ status_t getDisplayColorModes(const sp<IBinder>& display,
+ Vector<ColorMode>* outColorModes) override {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
@@ -409,8 +403,8 @@
return result;
}
- virtual status_t getDisplayNativePrimaries(const sp<IBinder>& display,
- ui::DisplayPrimaries& primaries) {
+ 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) {
@@ -435,7 +429,7 @@
return result;
}
- virtual ColorMode getActiveColorMode(const sp<IBinder>& display) {
+ ColorMode getActiveColorMode(const sp<IBinder>& display) override {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
@@ -455,8 +449,7 @@
return static_cast<ColorMode>(reply.readInt32());
}
- virtual status_t setActiveColorMode(const sp<IBinder>& display,
- ColorMode colorMode) {
+ status_t setActiveColorMode(const sp<IBinder>& display, ColorMode colorMode) override {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
@@ -481,8 +474,8 @@
return static_cast<status_t>(reply.readInt32());
}
- virtual status_t getAutoLowLatencyModeSupport(const sp<IBinder>& display,
- bool* outSupport) const {
+ status_t getAutoLowLatencyModeSupport(const sp<IBinder>& display,
+ bool* outSupport) const override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
status_t result = data.writeStrongBinder(display);
@@ -499,7 +492,7 @@
return reply.readBool(outSupport);
}
- virtual void setAutoLowLatencyMode(const sp<IBinder>& display, bool on) {
+ void setAutoLowLatencyMode(const sp<IBinder>& display, bool on) override {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
@@ -524,7 +517,8 @@
}
}
- virtual status_t getGameContentTypeSupport(const sp<IBinder>& display, bool* outSupport) const {
+ status_t getGameContentTypeSupport(const sp<IBinder>& display,
+ bool* outSupport) const override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
status_t result = data.writeStrongBinder(display);
@@ -540,7 +534,7 @@
return reply.readBool(outSupport);
}
- virtual void setGameContentType(const sp<IBinder>& display, bool on) {
+ void setGameContentType(const sp<IBinder>& display, bool on) override {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
@@ -563,7 +557,7 @@
}
}
- virtual status_t clearAnimationFrameStats() {
+ status_t clearAnimationFrameStats() override {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
@@ -578,7 +572,7 @@
return reply.readInt32();
}
- virtual status_t getAnimationFrameStats(FrameStats* outStats) const {
+ status_t getAnimationFrameStats(FrameStats* outStats) const override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
remote()->transact(BnSurfaceComposer::GET_ANIMATION_FRAME_STATS, data, &reply);
@@ -586,8 +580,8 @@
return reply.readInt32();
}
- virtual status_t getHdrCapabilities(const sp<IBinder>& display,
- HdrCapabilities* outCapabilities) const {
+ status_t getHdrCapabilities(const sp<IBinder>& display,
+ HdrCapabilities* outCapabilities) const override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
status_t result = data.writeStrongBinder(display);
@@ -608,7 +602,7 @@
return result;
}
- virtual status_t enableVSyncInjections(bool enable) {
+ status_t enableVSyncInjections(bool enable) override {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
@@ -629,7 +623,7 @@
return result;
}
- virtual status_t injectVSync(nsecs_t when) {
+ status_t injectVSync(nsecs_t when) override {
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
@@ -650,7 +644,7 @@
return result;
}
- virtual status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) {
+ status_t getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) override {
if (!outLayers) {
return UNEXPECTED_NULL;
}
@@ -680,10 +674,10 @@
return reply.readParcelableVector(outLayers);
}
- virtual status_t getCompositionPreference(ui::Dataspace* defaultDataspace,
- ui::PixelFormat* defaultPixelFormat,
- ui::Dataspace* wideColorGamutDataspace,
- ui::PixelFormat* wideColorGamutPixelFormat) const {
+ 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) {
@@ -703,7 +697,7 @@
return error;
}
- virtual status_t getColorManagement(bool* outGetColorManagement) const {
+ status_t getColorManagement(bool* outGetColorManagement) const override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
remote()->transact(BnSurfaceComposer::GET_COLOR_MANAGEMENT, data, &reply);
@@ -715,10 +709,10 @@
return err;
}
- virtual status_t getDisplayedContentSamplingAttributes(const sp<IBinder>& display,
- ui::PixelFormat* outFormat,
- ui::Dataspace* outDataspace,
- uint8_t* outComponentMask) const {
+ 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());
@@ -752,8 +746,8 @@
return error;
}
- virtual status_t setDisplayContentSamplingEnabled(const sp<IBinder>& display, bool enable,
- uint8_t componentMask, uint64_t maxFrames) {
+ 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);
@@ -766,9 +760,9 @@
return result;
}
- virtual status_t getDisplayedContentSample(const sp<IBinder>& display, uint64_t maxFrames,
- uint64_t timestamp,
- DisplayedFrameStats* outStats) const {
+ 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;
@@ -805,7 +799,7 @@
return result;
}
- virtual status_t getProtectedContentSupport(bool* outSupported) const {
+ status_t getProtectedContentSupport(bool* outSupported) const override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
status_t error =
@@ -817,8 +811,8 @@
return error;
}
- virtual status_t isWideColorDisplay(const sp<IBinder>& token,
- bool* outIsWideColorDisplay) const {
+ status_t isWideColorDisplay(const sp<IBinder>& token,
+ bool* outIsWideColorDisplay) const override {
Parcel data, reply;
status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (error != NO_ERROR) {
@@ -837,9 +831,8 @@
return error;
}
- virtual status_t addRegionSamplingListener(const Rect& samplingArea,
- const sp<IBinder>& stopLayerHandle,
- const sp<IRegionSamplingListener>& listener) {
+ 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) {
@@ -868,7 +861,7 @@
return error;
}
- virtual status_t removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener) {
+ status_t removeRegionSamplingListener(const sp<IRegionSamplingListener>& listener) override {
Parcel data, reply;
status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (error != NO_ERROR) {
@@ -888,73 +881,70 @@
return error;
}
- virtual status_t setDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
- int32_t defaultConfig, bool allowGroupSwitching,
- float primaryRefreshRateMin,
- float primaryRefreshRateMax,
- float appRequestRefreshRateMin,
- float appRequestRefreshRateMax) {
+ status_t setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, size_t 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("setDesiredDisplayConfigSpecs: failed to writeInterfaceToken: %d", result);
+ ALOGE("setDesiredDisplayModeSpecs: failed to writeInterfaceToken: %d", result);
return result;
}
result = data.writeStrongBinder(displayToken);
if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayConfigSpecs: failed to write display token: %d", result);
+ ALOGE("setDesiredDisplayModeSpecs: failed to write display token: %d", result);
return result;
}
- result = data.writeInt32(defaultConfig);
+ result = data.writeInt32(defaultMode);
if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayConfigSpecs failed to write defaultConfig: %d", result);
+ ALOGE("setDesiredDisplayModeSpecs failed to write defaultMode: %d", result);
return result;
}
result = data.writeBool(allowGroupSwitching);
if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayConfigSpecs failed to write allowGroupSwitching: %d", result);
+ ALOGE("setDesiredDisplayModeSpecs failed to write allowGroupSwitching: %d", result);
return result;
}
result = data.writeFloat(primaryRefreshRateMin);
if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayConfigSpecs failed to write primaryRefreshRateMin: %d", result);
+ ALOGE("setDesiredDisplayModeSpecs failed to write primaryRefreshRateMin: %d", result);
return result;
}
result = data.writeFloat(primaryRefreshRateMax);
if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayConfigSpecs failed to write primaryRefreshRateMax: %d", result);
+ ALOGE("setDesiredDisplayModeSpecs failed to write primaryRefreshRateMax: %d", result);
return result;
}
result = data.writeFloat(appRequestRefreshRateMin);
if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayConfigSpecs failed to write appRequestRefreshRateMin: %d",
+ ALOGE("setDesiredDisplayModeSpecs failed to write appRequestRefreshRateMin: %d",
result);
return result;
}
result = data.writeFloat(appRequestRefreshRateMax);
if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayConfigSpecs failed to write appRequestRefreshRateMax: %d",
+ ALOGE("setDesiredDisplayModeSpecs failed to write appRequestRefreshRateMax: %d",
result);
return result;
}
- result = remote()->transact(BnSurfaceComposer::SET_DESIRED_DISPLAY_CONFIG_SPECS, data,
- &reply);
+ result =
+ remote()->transact(BnSurfaceComposer::SET_DESIRED_DISPLAY_MODE_SPECS, data, &reply);
if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayConfigSpecs failed to transact: %d", result);
+ ALOGE("setDesiredDisplayModeSpecs failed to transact: %d", result);
return result;
}
return reply.readInt32();
}
- virtual status_t getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
- int32_t* outDefaultConfig,
- bool* outAllowGroupSwitching,
- float* outPrimaryRefreshRateMin,
- float* outPrimaryRefreshRateMax,
- float* outAppRequestRefreshRateMin,
- float* outAppRequestRefreshRateMax) {
- if (!outDefaultConfig || !outAllowGroupSwitching || !outPrimaryRefreshRateMin ||
+ status_t getDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, size_t* outDefaultMode,
+ bool* outAllowGroupSwitching,
+ float* outPrimaryRefreshRateMin,
+ float* outPrimaryRefreshRateMax,
+ float* outAppRequestRefreshRateMin,
+ float* outAppRequestRefreshRateMax) override {
+ if (!outDefaultMode || !outAllowGroupSwitching || !outPrimaryRefreshRateMin ||
!outPrimaryRefreshRateMax || !outAppRequestRefreshRateMin ||
!outAppRequestRefreshRateMax) {
return BAD_VALUE;
@@ -962,57 +952,62 @@
Parcel data, reply;
status_t result = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayConfigSpecs failed to writeInterfaceToken: %d", result);
+ ALOGE("getDesiredDisplayModeSpecs failed to writeInterfaceToken: %d", result);
return result;
}
result = data.writeStrongBinder(displayToken);
if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayConfigSpecs failed to writeStrongBinder: %d", result);
+ ALOGE("getDesiredDisplayModeSpecs failed to writeStrongBinder: %d", result);
return result;
}
- result = remote()->transact(BnSurfaceComposer::GET_DESIRED_DISPLAY_CONFIG_SPECS, data,
- &reply);
+ result =
+ remote()->transact(BnSurfaceComposer::GET_DESIRED_DISPLAY_MODE_SPECS, data, &reply);
if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayConfigSpecs failed to transact: %d", result);
+ ALOGE("getDesiredDisplayModeSpecs failed to transact: %d", result);
return result;
}
- result = reply.readInt32(outDefaultConfig);
+ int32_t defaultMode;
+ result = reply.readInt32(&defaultMode);
if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayConfigSpecs failed to read defaultConfig: %d", result);
+ ALOGE("getDesiredDisplayModeSpecs 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;
+ }
+ *outDefaultMode = static_cast<size_t>(defaultMode);
+
result = reply.readBool(outAllowGroupSwitching);
if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayConfigSpecs failed to read allowGroupSwitching: %d", result);
+ ALOGE("getDesiredDisplayModeSpecs failed to read allowGroupSwitching: %d", result);
return result;
}
result = reply.readFloat(outPrimaryRefreshRateMin);
if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayConfigSpecs failed to read primaryRefreshRateMin: %d", result);
+ ALOGE("getDesiredDisplayModeSpecs failed to read primaryRefreshRateMin: %d", result);
return result;
}
result = reply.readFloat(outPrimaryRefreshRateMax);
if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayConfigSpecs failed to read primaryRefreshRateMax: %d", result);
+ ALOGE("getDesiredDisplayModeSpecs failed to read primaryRefreshRateMax: %d", result);
return result;
}
result = reply.readFloat(outAppRequestRefreshRateMin);
if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayConfigSpecs failed to read appRequestRefreshRateMin: %d",
- result);
+ ALOGE("getDesiredDisplayModeSpecs failed to read appRequestRefreshRateMin: %d", result);
return result;
}
result = reply.readFloat(outAppRequestRefreshRateMax);
if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayConfigSpecs failed to read appRequestRefreshRateMax: %d",
- result);
+ ALOGE("getDesiredDisplayModeSpecs failed to read appRequestRefreshRateMax: %d", result);
return result;
}
return reply.readInt32();
}
- virtual status_t getDisplayBrightnessSupport(const sp<IBinder>& displayToken,
- bool* outSupport) const {
+ status_t getDisplayBrightnessSupport(const sp<IBinder>& displayToken,
+ bool* outSupport) const override {
Parcel data, reply;
status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (error != NO_ERROR) {
@@ -1039,7 +1034,7 @@
return NO_ERROR;
}
- virtual status_t setDisplayBrightness(const sp<IBinder>& displayToken, float brightness) {
+ status_t setDisplayBrightness(const sp<IBinder>& displayToken, float brightness) override {
Parcel data, reply;
status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (error != NO_ERROR) {
@@ -1064,7 +1059,7 @@
return NO_ERROR;
}
- virtual status_t notifyPowerBoost(int32_t boostId) {
+ status_t notifyPowerBoost(int32_t boostId) override {
Parcel data, reply;
status_t error = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (error != NO_ERROR) {
@@ -1085,8 +1080,8 @@
return NO_ERROR;
}
- virtual status_t setGlobalShadowSettings(const half4& ambientColor, const half4& spotColor,
- float lightPosY, float lightPosZ, float lightRadius) {
+ 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) {
@@ -1114,8 +1109,8 @@
return NO_ERROR;
}
- virtual status_t setFrameRate(const sp<IGraphicBufferProducer>& surface, float frameRate,
- int8_t compatibility, bool shouldBeSeamless) {
+ status_t setFrameRate(const sp<IGraphicBufferProducer>& surface, float frameRate,
+ int8_t compatibility, bool shouldBeSeamless) override {
Parcel data, reply;
status_t err = data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
if (err != NO_ERROR) {
@@ -1156,7 +1151,7 @@
return reply.readInt32();
}
- virtual status_t acquireFrameRateFlexibilityToken(sp<IBinder>* outToken) {
+ status_t acquireFrameRateFlexibilityToken(sp<IBinder>* outToken) override {
if (!outToken) return BAD_VALUE;
Parcel data, reply;
@@ -1191,40 +1186,34 @@
return NO_ERROR;
}
- virtual status_t setFrameTimelineVsync(const sp<IGraphicBufferProducer>& surface,
- int64_t frameTimelineVsyncId) {
+ 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("setFrameTimelineVsync: failed writing interface token: %s (%d)", strerror(-err),
- -err);
+ 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("setFrameTimelineVsync: failed writing strong binder: %s (%d)", strerror(-err),
- -err);
+ ALOGE("%s: failed writing strong binder: %s (%d)", __func__, strerror(-err), -err);
return err;
}
- err = data.writeInt64(frameTimelineVsyncId);
- if (err != NO_ERROR) {
- ALOGE("setFrameTimelineVsync: failed writing int64_t: %s (%d)", strerror(-err), -err);
- return err;
- }
+ SAFE_PARCEL(frameTimelineInfo.write, data);
- err = remote()->transact(BnSurfaceComposer::SET_FRAME_TIMELINE_VSYNC, data, &reply);
+ err = remote()->transact(BnSurfaceComposer::SET_FRAME_TIMELINE_INFO, data, &reply);
if (err != NO_ERROR) {
- ALOGE("setFrameTimelineVsync: failed to transact: %s (%d)", strerror(-err), err);
+ ALOGE("%s: failed to transact: %s (%d)", __func__, strerror(-err), err);
return err;
}
return reply.readInt32();
}
- virtual status_t addTransactionTraceListener(
- const sp<gui::ITransactionTraceListener>& listener) {
+ 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));
@@ -1235,7 +1224,7 @@
/**
* Get priority of the RenderEngine in surface flinger.
*/
- virtual int getGPUContextPriority() {
+ int getGPUContextPriority() override {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
status_t err =
@@ -1269,8 +1258,9 @@
case SET_TRANSACTION_STATE: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
- int64_t frameTimelineVsyncId;
- SAFE_PARCEL(data.readInt64, &frameTimelineVsyncId);
+ FrameTimelineInfo frameTimelineInfo;
+ SAFE_PARCEL(frameTimelineInfo.read, data);
+
uint32_t count = 0;
SAFE_PARCEL_READ_SIZE(data.readUint32, &count, data.dataSize());
Vector<ComposerState> state;
@@ -1324,10 +1314,10 @@
uint64_t transactionId = -1;
SAFE_PARCEL(data.readUint64, &transactionId);
- return setTransactionState(frameTimelineVsyncId, state, displays, stateFlags,
- applyToken, inputWindowCommands, desiredPresentTime,
- isAutoTimestamp, uncachedBuffer, hasListenerCallbacks,
- listenerCallbacks, transactionId);
+ return setTransactionState(frameTimelineInfo, state, displays, stateFlags, applyToken,
+ inputWindowCommands, desiredPresentTime, isAutoTimestamp,
+ uncachedBuffer, hasListenerCallbacks, listenerCallbacks,
+ transactionId);
}
case BOOT_FINISHED: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
@@ -1443,17 +1433,17 @@
if (result != NO_ERROR) return result;
return reply->write(info);
}
- case GET_DISPLAY_CONFIGS: {
+ case GET_DISPLAY_MODES: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
- Vector<DisplayConfig> configs;
+ Vector<ui::DisplayMode> modes;
const sp<IBinder> display = data.readStrongBinder();
- const status_t result = getDisplayConfigs(display, &configs);
+ const status_t result = getDisplayModes(display, &modes);
reply->writeInt32(result);
if (result == NO_ERROR) {
- reply->writeUint32(static_cast<uint32_t>(configs.size()));
- for (size_t c = 0; c < configs.size(); ++c) {
- memcpy(reply->writeInplace(sizeof(DisplayConfig)), &configs[c],
- sizeof(DisplayConfig));
+ reply->writeUint32(static_cast<uint32_t>(modes.size()));
+ for (size_t i = 0; i < modes.size(); i++) {
+ memcpy(reply->writeInplace(sizeof(ui::DisplayMode)), &modes[i],
+ sizeof(ui::DisplayMode));
}
}
return NO_ERROR;
@@ -1470,10 +1460,10 @@
}
return NO_ERROR;
}
- case GET_ACTIVE_CONFIG: {
+ case GET_ACTIVE_DISPLAY_MODE: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
sp<IBinder> display = data.readStrongBinder();
- int id = getActiveConfig(display);
+ int id = getActiveDisplayModeId(display);
reply->writeInt32(id);
return NO_ERROR;
}
@@ -1857,56 +1847,59 @@
}
return removeRegionSamplingListener(listener);
}
- case SET_DESIRED_DISPLAY_CONFIG_SPECS: {
+ case SET_DESIRED_DISPLAY_MODE_SPECS: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
sp<IBinder> displayToken = data.readStrongBinder();
- int32_t defaultConfig;
- status_t result = data.readInt32(&defaultConfig);
+ int32_t defaultMode;
+ status_t result = data.readInt32(&defaultMode);
if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayConfigSpecs: failed to read defaultConfig: %d", result);
+ 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("setDesiredDisplayConfigSpecs: failed to read allowGroupSwitching: %d",
- result);
+ ALOGE("setDesiredDisplayModeSpecs: failed to read allowGroupSwitching: %d", result);
return result;
}
float primaryRefreshRateMin;
result = data.readFloat(&primaryRefreshRateMin);
if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayConfigSpecs: failed to read primaryRefreshRateMin: %d",
+ ALOGE("setDesiredDisplayModeSpecs: failed to read primaryRefreshRateMin: %d",
result);
return result;
}
float primaryRefreshRateMax;
result = data.readFloat(&primaryRefreshRateMax);
if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayConfigSpecs: failed to read primaryRefreshRateMax: %d",
+ ALOGE("setDesiredDisplayModeSpecs: failed to read primaryRefreshRateMax: %d",
result);
return result;
}
float appRequestRefreshRateMin;
result = data.readFloat(&appRequestRefreshRateMin);
if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayConfigSpecs: failed to read appRequestRefreshRateMin: %d",
+ ALOGE("setDesiredDisplayModeSpecs: failed to read appRequestRefreshRateMin: %d",
result);
return result;
}
float appRequestRefreshRateMax;
result = data.readFloat(&appRequestRefreshRateMax);
if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayConfigSpecs: failed to read appRequestRefreshRateMax: %d",
+ ALOGE("setDesiredDisplayModeSpecs: failed to read appRequestRefreshRateMax: %d",
result);
return result;
}
- result = setDesiredDisplayConfigSpecs(displayToken, defaultConfig, allowGroupSwitching,
- primaryRefreshRateMin, primaryRefreshRateMax,
- appRequestRefreshRateMin,
- appRequestRefreshRateMax);
+ result = setDesiredDisplayModeSpecs(displayToken, static_cast<size_t>(defaultMode),
+ allowGroupSwitching, primaryRefreshRateMin,
+ primaryRefreshRateMax, appRequestRefreshRateMin,
+ appRequestRefreshRateMax);
if (result != NO_ERROR) {
- ALOGE("setDesiredDisplayConfigSpecs: failed to call setDesiredDisplayConfigSpecs: "
+ ALOGE("setDesiredDisplayModeSpecs: failed to call setDesiredDisplayModeSpecs: "
"%d",
result);
return result;
@@ -1914,10 +1907,10 @@
reply->writeInt32(result);
return result;
}
- case GET_DESIRED_DISPLAY_CONFIG_SPECS: {
+ case GET_DESIRED_DISPLAY_MODE_SPECS: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
sp<IBinder> displayToken = data.readStrongBinder();
- int32_t defaultConfig;
+ size_t defaultMode;
bool allowGroupSwitching;
float primaryRefreshRateMin;
float primaryRefreshRateMax;
@@ -1925,49 +1918,49 @@
float appRequestRefreshRateMax;
status_t result =
- getDesiredDisplayConfigSpecs(displayToken, &defaultConfig, &allowGroupSwitching,
- &primaryRefreshRateMin, &primaryRefreshRateMax,
- &appRequestRefreshRateMin,
- &appRequestRefreshRateMax);
+ getDesiredDisplayModeSpecs(displayToken, &defaultMode, &allowGroupSwitching,
+ &primaryRefreshRateMin, &primaryRefreshRateMax,
+ &appRequestRefreshRateMin,
+ &appRequestRefreshRateMax);
if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayConfigSpecs: failed to get getDesiredDisplayConfigSpecs: "
+ ALOGE("getDesiredDisplayModeSpecs: failed to get getDesiredDisplayModeSpecs: "
"%d",
result);
return result;
}
- result = reply->writeInt32(defaultConfig);
+ result = reply->writeInt32(static_cast<int32_t>(defaultMode));
if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayConfigSpecs: failed to write defaultConfig: %d", result);
+ ALOGE("getDesiredDisplayModeSpecs: failed to write defaultMode: %d", result);
return result;
}
result = reply->writeBool(allowGroupSwitching);
if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayConfigSpecs: failed to write allowGroupSwitching: %d",
+ ALOGE("getDesiredDisplayModeSpecs: failed to write allowGroupSwitching: %d",
result);
return result;
}
result = reply->writeFloat(primaryRefreshRateMin);
if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayConfigSpecs: failed to write primaryRefreshRateMin: %d",
+ ALOGE("getDesiredDisplayModeSpecs: failed to write primaryRefreshRateMin: %d",
result);
return result;
}
result = reply->writeFloat(primaryRefreshRateMax);
if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayConfigSpecs: failed to write primaryRefreshRateMax: %d",
+ ALOGE("getDesiredDisplayModeSpecs: failed to write primaryRefreshRateMax: %d",
result);
return result;
}
result = reply->writeFloat(appRequestRefreshRateMin);
if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayConfigSpecs: failed to write appRequestRefreshRateMin: %d",
+ ALOGE("getDesiredDisplayModeSpecs: failed to write appRequestRefreshRateMin: %d",
result);
return result;
}
result = reply->writeFloat(appRequestRefreshRateMax);
if (result != NO_ERROR) {
- ALOGE("getDesiredDisplayConfigSpecs: failed to write appRequestRefreshRateMax: %d",
+ ALOGE("getDesiredDisplayModeSpecs: failed to write appRequestRefreshRateMax: %d",
result);
return result;
}
@@ -2078,30 +2071,26 @@
}
return NO_ERROR;
}
- case SET_FRAME_TIMELINE_VSYNC: {
+ case SET_FRAME_TIMELINE_INFO: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
sp<IBinder> binder;
status_t err = data.readStrongBinder(&binder);
if (err != NO_ERROR) {
- ALOGE("setFrameTimelineVsync: failed to read strong binder: %s (%d)",
- strerror(-err), -err);
+ ALOGE("setFrameTimelineInfo: failed to read strong binder: %s (%d)", strerror(-err),
+ -err);
return err;
}
sp<IGraphicBufferProducer> surface = interface_cast<IGraphicBufferProducer>(binder);
if (!surface) {
- ALOGE("setFrameTimelineVsync: failed to cast to IGraphicBufferProducer: %s (%d)",
+ ALOGE("setFrameTimelineInfo: failed to cast to IGraphicBufferProducer: %s (%d)",
strerror(-err), -err);
return err;
}
- int64_t frameTimelineVsyncId;
- err = data.readInt64(&frameTimelineVsyncId);
- if (err != NO_ERROR) {
- ALOGE("setFrameTimelineVsync: failed to read int64_t: %s (%d)", strerror(-err),
- -err);
- return err;
- }
- status_t result = setFrameTimelineVsync(surface, frameTimelineVsyncId);
+ FrameTimelineInfo frameTimelineInfo;
+ SAFE_PARCEL(frameTimelineInfo.read, data);
+
+ status_t result = setFrameTimelineInfo(surface, frameTimelineInfo);
reply->writeInt32(result);
return NO_ERROR;
}
diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp
index 1808571..0ded936 100644
--- a/libs/gui/ITransactionCompletedListener.cpp
+++ b/libs/gui/ITransactionCompletedListener.cpp
@@ -92,10 +92,8 @@
return err;
}
-JankData::JankData() :
- frameVsyncId(ISurfaceComposer::INVALID_VSYNC_ID),
- jankType(JankType::None) {
-}
+JankData::JankData()
+ : frameVsyncId(FrameTimelineInfo::INVALID_VSYNC_ID), jankType(JankType::None) {}
status_t JankData::writeToParcel(Parcel* output) const {
SAFE_PARCEL(output->writeInt64, frameVsyncId);
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 2946aae..fff3305 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -63,7 +63,7 @@
shouldBeSeamless(true),
fixedTransformHint(ui::Transform::ROT_INVALID),
frameNumber(0),
- frameTimelineVsyncId(ISurfaceComposer::INVALID_VSYNC_ID),
+ frameTimelineInfo(),
autoRefresh(false) {
matrix.dsdx = matrix.dtdy = 1.0f;
matrix.dsdy = matrix.dtdx = 0.0f;
@@ -151,7 +151,7 @@
SAFE_PARCEL(output.writeBool, shouldBeSeamless);
SAFE_PARCEL(output.writeUint32, fixedTransformHint);
SAFE_PARCEL(output.writeUint64, frameNumber);
- SAFE_PARCEL(output.writeInt64, frameTimelineVsyncId);
+ SAFE_PARCEL(frameTimelineInfo.write, output);
SAFE_PARCEL(output.writeBool, autoRefresh);
SAFE_PARCEL(output.writeUint32, blurRegions.size());
@@ -270,7 +270,7 @@
SAFE_PARCEL(input.readUint32, &tmpUint32);
fixedTransformHint = static_cast<ui::Transform::RotationFlags>(tmpUint32);
SAFE_PARCEL(input.readUint64, &frameNumber);
- SAFE_PARCEL(input.readInt64, &frameTimelineVsyncId);
+ SAFE_PARCEL(frameTimelineInfo.read, input);
SAFE_PARCEL(input.readBool, &autoRefresh);
uint32_t numRegions = 0;
@@ -426,9 +426,6 @@
what |= eReparentChildren;
reparentSurfaceControl = other.reparentSurfaceControl;
}
- if (other.what & eDetachChildren) {
- what |= eDetachChildren;
- }
if (other.what & eRelativeLayerChanged) {
what |= eRelativeLayerChanged;
what &= ~eLayerChanged;
@@ -537,15 +534,9 @@
what |= eFrameNumberChanged;
frameNumber = other.frameNumber;
}
- if (other.what & eFrameTimelineVsyncChanged) {
- // When merging vsync Ids we take the oldest valid one
- if (frameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID &&
- other.frameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID) {
- frameTimelineVsyncId = std::max(frameTimelineVsyncId, other.frameTimelineVsyncId);
- } else if (frameTimelineVsyncId == ISurfaceComposer::INVALID_VSYNC_ID) {
- frameTimelineVsyncId = other.frameTimelineVsyncId;
- }
- what |= eFrameTimelineVsyncChanged;
+ if (other.what & eFrameTimelineInfoChanged) {
+ what |= eFrameTimelineInfoChanged;
+ frameTimelineInfo.merge(other.frameTimelineInfo);
}
if (other.what & eAutoRefreshChanged) {
what |= eAutoRefreshChanged;
@@ -644,11 +635,13 @@
status_t CaptureArgs::write(Parcel& output) const {
SAFE_PARCEL(output.writeInt32, static_cast<int32_t>(pixelFormat));
SAFE_PARCEL(output.write, sourceCrop);
- SAFE_PARCEL(output.writeFloat, frameScale);
+ SAFE_PARCEL(output.writeFloat, frameScaleX);
+ SAFE_PARCEL(output.writeFloat, frameScaleY);
SAFE_PARCEL(output.writeBool, captureSecureLayers);
SAFE_PARCEL(output.writeInt32, uid);
SAFE_PARCEL(output.writeInt32, static_cast<int32_t>(dataspace));
SAFE_PARCEL(output.writeBool, allowProtected);
+ SAFE_PARCEL(output.writeBool, grayscale);
return NO_ERROR;
}
@@ -657,12 +650,14 @@
SAFE_PARCEL(input.readInt32, &value);
pixelFormat = static_cast<ui::PixelFormat>(value);
SAFE_PARCEL(input.read, sourceCrop);
- SAFE_PARCEL(input.readFloat, &frameScale);
+ SAFE_PARCEL(input.readFloat, &frameScaleX);
+ SAFE_PARCEL(input.readFloat, &frameScaleY);
SAFE_PARCEL(input.readBool, &captureSecureLayers);
SAFE_PARCEL(input.readInt32, &uid);
SAFE_PARCEL(input.readInt32, &value);
dataspace = static_cast<ui::Dataspace>(value);
SAFE_PARCEL(input.readBool, &allowProtected);
+ SAFE_PARCEL(input.readBool, &grayscale);
return NO_ERROR;
}
diff --git a/libs/gui/OWNERS b/libs/gui/OWNERS
index 1667fb0..45c958e 100644
--- a/libs/gui/OWNERS
+++ b/libs/gui/OWNERS
@@ -1,5 +1,4 @@
adyabr@google.com
-akrulec@google.com
alecmouri@google.com
chaviw@google.com
chrisforbes@google.com
@@ -7,7 +6,6 @@
lpy@google.com
mathias@google.com
racarr@google.com
-stoza@google.com
vishnun@google.com
per-file EndToEndNativeInputTest.cpp = svv@google.com
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index e82f0cc..59ad8d2 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -1496,8 +1496,8 @@
case NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER:
res = dispatchGetLastQueuedBuffer(args);
break;
- case NATIVE_WINDOW_SET_FRAME_TIMELINE_VSYNC:
- res = dispatchSetFrameTimelineVsync(args);
+ case NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO:
+ res = dispatchSetFrameTimelineInfo(args);
break;
default:
res = NAME_NOT_FOUND;
@@ -1806,12 +1806,13 @@
return result;
}
-int Surface::dispatchSetFrameTimelineVsync(va_list args) {
+int Surface::dispatchSetFrameTimelineInfo(va_list args) {
ATRACE_CALL();
auto frameTimelineVsyncId = static_cast<int64_t>(va_arg(args, int64_t));
+ auto inputEventId = static_cast<int32_t>(va_arg(args, int32_t));
- ALOGV("Surface::dispatchSetFrameTimelineVsync");
- return setFrameTimelineVsync(frameTimelineVsyncId);
+ ALOGV("Surface::%s", __func__);
+ return setFrameTimelineInfo({frameTimelineVsyncId, inputEventId});
}
bool Surface::transformToDisplayInverse() {
@@ -2579,9 +2580,8 @@
shouldBeSeamless);
}
-status_t Surface::setFrameTimelineVsync(int64_t frameTimelineVsyncId) {
- return composerService()->setFrameTimelineVsync(mGraphicBufferProducer,
- frameTimelineVsyncId);
+status_t Surface::setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo) {
+ return composerService()->setFrameTimelineInfo(mGraphicBufferProducer, frameTimelineInfo);
}
}; // namespace android
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 96c099b..4493a21 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -39,7 +39,7 @@
#include <gui/LayerState.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
-#include <ui/DisplayConfig.h>
+#include <ui/DisplayMode.h>
#ifndef NO_INPUT
#include <input/InputWindow.h>
@@ -396,7 +396,7 @@
mContainsBuffer(other.mContainsBuffer),
mDesiredPresentTime(other.mDesiredPresentTime),
mIsAutoTimestamp(other.mIsAutoTimestamp),
- mFrameTimelineVsyncId(other.mFrameTimelineVsyncId),
+ mFrameTimelineInfo(other.mFrameTimelineInfo),
mApplyToken(other.mApplyToken) {
mDisplayStates = other.mDisplayStates;
mComposerStates = other.mComposerStates;
@@ -427,7 +427,9 @@
const bool containsBuffer = parcel->readBool();
const int64_t desiredPresentTime = parcel->readInt64();
const bool isAutoTimestamp = parcel->readBool();
- const int64_t frameTimelineVsyncId = parcel->readInt64();
+ FrameTimelineInfo frameTimelineInfo;
+ SAFE_PARCEL(frameTimelineInfo.read, *parcel);
+
sp<IBinder> applyToken;
parcel->readNullableStrongBinder(&applyToken);
size_t count = static_cast<size_t>(parcel->readUint32());
@@ -502,7 +504,7 @@
mContainsBuffer = containsBuffer;
mDesiredPresentTime = desiredPresentTime;
mIsAutoTimestamp = isAutoTimestamp;
- mFrameTimelineVsyncId = frameTimelineVsyncId;
+ mFrameTimelineInfo = frameTimelineInfo;
mDisplayStates = displayStates;
mListenerCallbacks = listenerCallbacks;
mComposerStates = composerStates;
@@ -534,7 +536,7 @@
parcel->writeBool(mContainsBuffer);
parcel->writeInt64(mDesiredPresentTime);
parcel->writeBool(mIsAutoTimestamp);
- parcel->writeInt64(mFrameTimelineVsyncId);
+ SAFE_PARCEL(mFrameTimelineInfo.write, *parcel);
parcel->writeStrongBinder(mApplyToken);
parcel->writeUint32(static_cast<uint32_t>(mDisplayStates.size()));
for (auto const& displayState : mDisplayStates) {
@@ -613,13 +615,7 @@
mExplicitEarlyWakeupEnd = mExplicitEarlyWakeupEnd || other.mExplicitEarlyWakeupEnd;
mApplyToken = other.mApplyToken;
- // When merging vsync Ids we take the oldest one
- if (mFrameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID &&
- other.mFrameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID) {
- mFrameTimelineVsyncId = std::max(mFrameTimelineVsyncId, other.mFrameTimelineVsyncId);
- } else if (mFrameTimelineVsyncId == ISurfaceComposer::INVALID_VSYNC_ID) {
- mFrameTimelineVsyncId = other.mFrameTimelineVsyncId;
- }
+ mFrameTimelineInfo.merge(other.mFrameTimelineInfo);
other.clear();
return *this;
@@ -639,7 +635,7 @@
mExplicitEarlyWakeupEnd = false;
mDesiredPresentTime = 0;
mIsAutoTimestamp = true;
- mFrameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID;
+ mFrameTimelineInfo.clear();
mApplyToken = nullptr;
}
@@ -651,9 +647,8 @@
uncacheBuffer.id = cacheId;
sp<IBinder> applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance());
- sf->setTransactionState(ISurfaceComposer::INVALID_VSYNC_ID, {}, {}, 0, applyToken, {},
- systemTime(), true, uncacheBuffer, false, {},
- 0 /* Undefined transactionId */);
+ sf->setTransactionState(FrameTimelineInfo{}, {}, {}, 0, applyToken, {}, systemTime(), true,
+ uncacheBuffer, false, {}, 0 /* Undefined transactionId */);
}
void SurfaceComposerClient::Transaction::cacheBuffers() {
@@ -773,7 +768,7 @@
? mApplyToken
: IInterface::asBinder(TransactionCompletedListener::getIInstance());
- sf->setTransactionState(mFrameTimelineVsyncId, composerStates, displayStates, flags, applyToken,
+ sf->setTransactionState(mFrameTimelineInfo, composerStates, displayStates, flags, applyToken,
mInputWindowCommands, mDesiredPresentTime, mIsAutoTimestamp,
{} /*uncacheBuffer - only set in doUncacheBufferTransaction*/,
hasListenerCallbacks, listenerCallbacks, mId);
@@ -1391,19 +1386,6 @@
return *this;
}
-SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::detachChildren(
- const sp<SurfaceControl>& sc) {
- layer_state_t* s = getLayerState(sc);
- if (!s) {
- mStatus = BAD_INDEX;
- return *this;
- }
- s->what |= layer_state_t::eDetachChildren;
-
- registerSurfaceControlForCallback(sc);
- return *this;
-}
-
#ifndef NO_INPUT
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInputWindowInfo(
const sp<SurfaceControl>& sc,
@@ -1549,22 +1531,22 @@
return *this;
}
-SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameTimelineVsync(
- int64_t frameTimelineVsyncId) {
- mFrameTimelineVsyncId = frameTimelineVsyncId;
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameTimelineInfo(
+ const FrameTimelineInfo& frameTimelineInfo) {
+ mFrameTimelineInfo = frameTimelineInfo;
return *this;
}
-SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameTimelineVsync(
- const sp<SurfaceControl>& sc, int64_t frameTimelineVsyncId) {
+SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameTimelineInfo(
+ const sp<SurfaceControl>& sc, const FrameTimelineInfo& frameTimelineInfo) {
layer_state_t* s = getLayerState(sc);
if (!s) {
mStatus = BAD_INDEX;
return *this;
}
- s->what |= layer_state_t::eFrameTimelineVsyncChanged;
- s->frameTimelineVsyncId = frameTimelineVsyncId;
+ s->what |= layer_state_t::eFrameTimelineInfoChanged;
+ s->frameTimelineInfo = frameTimelineInfo;
return *this;
}
@@ -1820,52 +1802,51 @@
return ComposerService::getComposerService()->getDisplayInfo(display, info);
}
-status_t SurfaceComposerClient::getDisplayConfigs(const sp<IBinder>& display,
- Vector<DisplayConfig>* configs) {
- return ComposerService::getComposerService()->getDisplayConfigs(display, configs);
+status_t SurfaceComposerClient::getDisplayModes(const sp<IBinder>& display,
+ Vector<ui::DisplayMode>* modes) {
+ return ComposerService::getComposerService()->getDisplayModes(display, modes);
}
-status_t SurfaceComposerClient::getActiveDisplayConfig(const sp<IBinder>& display,
- DisplayConfig* config) {
- Vector<DisplayConfig> configs;
- status_t result = getDisplayConfigs(display, &configs);
+status_t SurfaceComposerClient::getActiveDisplayMode(const sp<IBinder>& display,
+ ui::DisplayMode* mode) {
+ Vector<ui::DisplayMode> modes;
+ status_t result = getDisplayModes(display, &modes);
if (result != NO_ERROR) {
return result;
}
- int activeId = getActiveConfig(display);
+ int activeId = getActiveDisplayModeId(display);
if (activeId < 0) {
- ALOGE("No active configuration found");
+ ALOGE("No active mode found");
return NAME_NOT_FOUND;
}
- *config = configs[static_cast<size_t>(activeId)];
+ *mode = modes[static_cast<size_t>(activeId)];
return NO_ERROR;
}
-int SurfaceComposerClient::getActiveConfig(const sp<IBinder>& display) {
- return ComposerService::getComposerService()->getActiveConfig(display);
+int SurfaceComposerClient::getActiveDisplayModeId(const sp<IBinder>& display) {
+ return ComposerService::getComposerService()->getActiveDisplayModeId(display);
}
-status_t SurfaceComposerClient::setDesiredDisplayConfigSpecs(
- const sp<IBinder>& displayToken, int32_t defaultConfig, bool allowGroupSwitching,
+status_t SurfaceComposerClient::setDesiredDisplayModeSpecs(
+ const sp<IBinder>& displayToken, size_t defaultMode, bool allowGroupSwitching,
float primaryRefreshRateMin, float primaryRefreshRateMax, float appRequestRefreshRateMin,
float appRequestRefreshRateMax) {
return ComposerService::getComposerService()
- ->setDesiredDisplayConfigSpecs(displayToken, defaultConfig, allowGroupSwitching,
- primaryRefreshRateMin, primaryRefreshRateMax,
- appRequestRefreshRateMin, appRequestRefreshRateMax);
+ ->setDesiredDisplayModeSpecs(displayToken, defaultMode, allowGroupSwitching,
+ primaryRefreshRateMin, primaryRefreshRateMax,
+ appRequestRefreshRateMin, appRequestRefreshRateMax);
}
-status_t SurfaceComposerClient::getDesiredDisplayConfigSpecs(
- const sp<IBinder>& displayToken, int32_t* outDefaultConfig, bool* outAllowGroupSwitching,
+status_t SurfaceComposerClient::getDesiredDisplayModeSpecs(
+ const sp<IBinder>& displayToken, size_t* outDefaultMode, bool* outAllowGroupSwitching,
float* outPrimaryRefreshRateMin, float* outPrimaryRefreshRateMax,
float* outAppRequestRefreshRateMin, float* outAppRequestRefreshRateMax) {
return ComposerService::getComposerService()
- ->getDesiredDisplayConfigSpecs(displayToken, outDefaultConfig, outAllowGroupSwitching,
- outPrimaryRefreshRateMin, outPrimaryRefreshRateMax,
- outAppRequestRefreshRateMin,
- outAppRequestRefreshRateMax);
+ ->getDesiredDisplayModeSpecs(displayToken, outDefaultMode, outAllowGroupSwitching,
+ outPrimaryRefreshRateMin, outPrimaryRefreshRateMax,
+ outAppRequestRefreshRateMin, outAppRequestRefreshRateMax);
}
status_t SurfaceComposerClient::getDisplayColorModes(const sp<IBinder>& display,
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index 7f69bc4..bccb71b 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -92,7 +92,7 @@
void flushShadowQueue() { mFlushShadowQueue = true; }
status_t setFrameRate(float frameRate, int8_t compatibility, bool shouldBeSeamless);
- status_t setFrameTimelineVsync(int64_t frameTimelineVsyncId);
+ status_t setFrameTimelineInfo(const FrameTimelineInfo& info);
virtual ~BLASTBufferQueue();
@@ -110,6 +110,7 @@
// Return true if we need to reject the buffer based on the scaling mode and the buffer size.
bool rejectBuffer(const BufferItem& item) REQUIRES(mMutex);
bool maxBuffersAcquired(bool includeExtraAcquire) const REQUIRES(mMutex);
+ static PixelFormat convertBufferFormat(PixelFormat& format);
std::string mName;
sp<SurfaceControl> mSurfaceControl;
@@ -156,7 +157,7 @@
// This is only relevant for shared buffer mode.
bool mAutoRefresh GUARDED_BY(mMutex) = false;
- std::queue<int64_t> mNextFrameTimelineVsyncIdQueue GUARDED_BY(mMutex);
+ std::queue<FrameTimelineInfo> mNextFrameTimelineInfoQueue GUARDED_BY(mMutex);
// Last acquired buffer's scaling mode. This is used to check if we should update the blast
// layer size immediately or wait until we get the next buffer. This will support scenarios
diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h
index 5587acf..d74c2ba 100644
--- a/libs/gui/include/gui/DisplayEventDispatcher.h
+++ b/libs/gui/include/gui/DisplayEventDispatcher.h
@@ -25,7 +25,7 @@
// The Vsync Id corresponsing to this vsync event. This will be used to
// populate ISurfaceComposer::setFrameTimelineVsync and
// SurfaceComposerClient::setFrameTimelineVsync
- int64_t id = ISurfaceComposer::INVALID_VSYNC_ID;
+ int64_t id = FrameTimelineInfo::INVALID_VSYNC_ID;
// The deadline in CLOCK_MONOTONIC that the app needs to complete its
// frame by (both on the CPU and the GPU)
@@ -60,8 +60,8 @@
VsyncEventData vsyncEventData) = 0;
virtual void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId,
bool connected) = 0;
- virtual void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId,
- int32_t configId, nsecs_t vsyncPeriod) = 0;
+ virtual void dispatchModeChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t modeId,
+ nsecs_t vsyncPeriod) = 0;
// AChoreographer-specific hook for processing null-events so that looper
// can be properly poked.
virtual void dispatchNullEvent(nsecs_t timestamp, PhysicalDisplayId displayId) = 0;
diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h
index 3191fc9..7179a20 100644
--- a/libs/gui/include/gui/DisplayEventReceiver.h
+++ b/libs/gui/include/gui/DisplayEventReceiver.h
@@ -52,7 +52,7 @@
enum {
DISPLAY_EVENT_VSYNC = fourcc('v', 's', 'y', 'n'),
DISPLAY_EVENT_HOTPLUG = fourcc('p', 'l', 'u', 'g'),
- DISPLAY_EVENT_CONFIG_CHANGED = fourcc('c', 'o', 'n', 'f'),
+ DISPLAY_EVENT_MODE_CHANGE = fourcc('m', 'o', 'd', 'e'),
DISPLAY_EVENT_NULL = fourcc('n', 'u', 'l', 'l'),
DISPLAY_EVENT_FRAME_RATE_OVERRIDE = fourcc('r', 'a', 't', 'e'),
DISPLAY_EVENT_FRAME_RATE_OVERRIDE_FLUSH = fourcc('f', 'l', 's', 'h'),
@@ -82,8 +82,8 @@
bool connected;
};
- struct Config {
- int32_t configId;
+ struct ModeChange {
+ int32_t modeId;
nsecs_t vsyncPeriod __attribute__((aligned(8)));
};
@@ -96,7 +96,7 @@
union {
VSync vsync;
Hotplug hotplug;
- Config config;
+ ModeChange modeChange;
FrameRateOverride frameRateOverride;
};
};
@@ -106,7 +106,7 @@
* DisplayEventReceiver creates and registers an event connection with
* SurfaceFlinger. VSync events are disabled by default. Call setVSyncRate
* or requestNextVsync to receive them.
- * To receive ConfigChanged and/or FrameRateOverrides events specify this in
+ * To receive ModeChanged and/or FrameRateOverrides events specify this in
* the constructor. Other events start being delivered immediately.
*/
explicit DisplayEventReceiver(
diff --git a/libs/gui/include/gui/FrameTimelineInfo.h b/libs/gui/include/gui/FrameTimelineInfo.h
new file mode 100644
index 0000000..3b4c009
--- /dev/null
+++ b/libs/gui/include/gui/FrameTimelineInfo.h
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#include <android/os/IInputConstants.h>
+#include <binder/Parcel.h>
+
+namespace android {
+
+struct FrameTimelineInfo {
+ // Needs to be in sync with android.graphics.FrameInfo.INVALID_VSYNC_ID in java
+ static constexpr int64_t INVALID_VSYNC_ID = -1;
+
+ // The vsync id that was used to start the transaction
+ int64_t vsyncId = INVALID_VSYNC_ID;
+
+ // The id of the input event that caused this buffer
+ int32_t inputEventId = android::os::IInputConstants::INVALID_INPUT_EVENT_ID;
+
+ status_t write(Parcel& output) const;
+ status_t read(const Parcel& input);
+
+ void merge(const FrameTimelineInfo& other);
+ void clear();
+};
+
+} // namespace android
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 86f3c60..6d1a3ab 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -24,6 +24,7 @@
#include <android/gui/IScreenCaptureListener.h>
#include <android/gui/ITransactionTraceListener.h>
+#include <gui/FrameTimelineInfo.h>
#include <gui/ITransactionCompletedListener.h>
#include <input/Flags.h>
@@ -53,7 +54,6 @@
struct client_cache_t;
struct ComposerState;
struct DisplayCaptureArgs;
-struct DisplayConfig;
struct DisplayInfo;
struct DisplayStatInfo;
struct DisplayState;
@@ -72,6 +72,7 @@
namespace ui {
+struct DisplayMode;
struct DisplayState;
} // namespace ui
@@ -111,15 +112,12 @@
};
enum class EventRegistration {
- configChanged = 1 << 0,
+ modeChanged = 1 << 0,
frameRateOverride = 1 << 1,
};
using EventRegistrationFlags = Flags<EventRegistration>;
- // Needs to be in sync with android.graphics.FrameInfo.INVALID_VSYNC_ID in java
- static constexpr int64_t INVALID_VSYNC_ID = -1;
-
/*
* Create a connection with SurfaceFlinger.
*/
@@ -164,7 +162,7 @@
/* open/close transactions. requires ACCESS_SURFACE_FLINGER permission */
virtual status_t setTransactionState(
- int64_t frameTimelineVsyncId, const Vector<ComposerState>& state,
+ const FrameTimelineInfo& frameTimelineInfo, const Vector<ComposerState>& state,
const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
@@ -209,15 +207,15 @@
virtual status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo*) = 0;
/**
- * Get configurations supported by given physical display.
+ * Get modes supported by given physical display.
*/
- virtual status_t getDisplayConfigs(const sp<IBinder>& display, Vector<DisplayConfig>*) = 0;
+ virtual status_t getDisplayModes(const sp<IBinder>& display, Vector<ui::DisplayMode>*) = 0;
/**
- * Get the index into configurations returned by getDisplayConfigs,
- * corresponding to the active configuration.
+ * Get the index into modes returned by getDisplayModes,
+ * corresponding to the active mode.
*/
- virtual int getActiveConfig(const sp<IBinder>& display) = 0;
+ virtual int getActiveDisplayModeId(const sp<IBinder>& display) = 0;
virtual status_t getDisplayColorModes(const sp<IBinder>& display,
Vector<ui::ColorMode>* outColorModes) = 0;
@@ -388,34 +386,31 @@
/* Sets the refresh rate boundaries for the display.
*
* The primary refresh rate range represents display manager's general guidance on the display
- * configs we'll consider when switching refresh rates. Unless we get an explicit signal from an
+ * 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 configs when switching
+ * 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.
*
- * defaultConfig is used to narrow the list of display configs SurfaceFlinger will consider
- * switching between. Only configs with a config group and resolution matching defaultConfig
- * will be considered for switching. The defaultConfig index corresponds to the list of configs
- * returned from getDisplayConfigs().
+ * 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 index corresponds to the list of modes
+ * returned from getDisplayModes().
*/
- virtual status_t setDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
- int32_t defaultConfig, bool allowGroupSwitching,
- float primaryRefreshRateMin,
- float primaryRefreshRateMax,
- float appRequestRefreshRateMin,
- float appRequestRefreshRateMax) = 0;
+ virtual status_t setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, size_t defaultMode,
+ bool allowGroupSwitching,
+ float primaryRefreshRateMin,
+ float primaryRefreshRateMax,
+ float appRequestRefreshRateMin,
+ float appRequestRefreshRateMax) = 0;
- virtual status_t getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
- int32_t* outDefaultConfig,
- bool* outAllowGroupSwitching,
- float* outPrimaryRefreshRateMin,
- float* outPrimaryRefreshRateMax,
- float* outAppRequestRefreshRateMin,
- float* outAppRequestRefreshRateMax) = 0;
+ virtual status_t getDesiredDisplayModeSpecs(
+ const sp<IBinder>& displayToken, size_t* outDefaultMode, bool* outAllowGroupSwitching,
+ float* outPrimaryRefreshRateMin, float* outPrimaryRefreshRateMax,
+ float* outAppRequestRefreshRateMin, float* outAppRequestRefreshRateMax) = 0;
/*
* Gets whether brightness operations are supported on a display.
*
@@ -494,11 +489,11 @@
virtual status_t acquireFrameRateFlexibilityToken(sp<IBinder>* outToken) = 0;
/*
- * Sets the frame timeline vsync id received from choreographer that corresponds to next
+ * Sets the frame timeline vsync info received from choreographer that corresponds to next
* buffer submitted on that surface.
*/
- virtual status_t setFrameTimelineVsync(const sp<IGraphicBufferProducer>& surface,
- int64_t frameTimelineVsyncId) = 0;
+ virtual status_t setFrameTimelineInfo(const sp<IGraphicBufferProducer>& surface,
+ const FrameTimelineInfo& frameTimelineInfo) = 0;
/*
* Adds a TransactionTraceListener to listen for transaction tracing state updates.
@@ -529,8 +524,8 @@
SET_TRANSACTION_STATE,
AUTHENTICATE_SURFACE,
GET_SUPPORTED_FRAME_TIMESTAMPS,
- GET_DISPLAY_CONFIGS,
- GET_ACTIVE_CONFIG,
+ GET_DISPLAY_MODES,
+ GET_ACTIVE_DISPLAY_MODE,
GET_DISPLAY_STATE,
CAPTURE_DISPLAY,
CAPTURE_LAYERS,
@@ -556,8 +551,8 @@
GET_PHYSICAL_DISPLAY_IDS,
ADD_REGION_SAMPLING_LISTENER,
REMOVE_REGION_SAMPLING_LISTENER,
- SET_DESIRED_DISPLAY_CONFIG_SPECS,
- GET_DESIRED_DISPLAY_CONFIG_SPECS,
+ SET_DESIRED_DISPLAY_MODE_SPECS,
+ GET_DESIRED_DISPLAY_MODE_SPECS,
GET_DISPLAY_BRIGHTNESS_SUPPORT,
SET_DISPLAY_BRIGHTNESS,
CAPTURE_DISPLAY_BY_ID,
@@ -569,7 +564,7 @@
SET_GAME_CONTENT_TYPE,
SET_FRAME_RATE,
ACQUIRE_FRAME_RATE_FLEXIBILITY_TOKEN,
- SET_FRAME_TIMELINE_VSYNC,
+ SET_FRAME_TIMELINE_INFO,
ADD_TRANSACTION_TRACE_LISTENER,
GET_GPU_CONTEXT_PRIORITY,
// Always append new enum to the end.
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index b1305c6..2f9a0c0 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -102,7 +102,7 @@
/* was ScalingModeChanged, now available 0x00000400, */
eShadowRadiusChanged = 0x00000800,
eReparentChildren = 0x00001000,
- eDetachChildren = 0x00002000,
+ /* was eDetachChildren, now available 0x00002000, */
eRelativeLayerChanged = 0x00004000,
eReparent = 0x00008000,
eColorChanged = 0x00010000,
@@ -132,7 +132,7 @@
eProducerDisconnect = 0x100'00000000,
eFixedTransformHintChanged = 0x200'00000000,
eFrameNumberChanged = 0x400'00000000,
- eFrameTimelineVsyncChanged = 0x800'00000000,
+ eFrameTimelineInfoChanged = 0x800'00000000,
eBlurRegionsChanged = 0x1000'00000000,
eAutoRefreshChanged = 0x2000'00000000,
};
@@ -238,7 +238,7 @@
// graphics producer.
uint64_t frameNumber;
- int64_t frameTimelineVsyncId;
+ FrameTimelineInfo frameTimelineInfo;
// Indicates that the consumer should acquire the next frame as soon as it
// can and not wait for a frame to become available. This is only relevant
@@ -328,7 +328,8 @@
ui::PixelFormat pixelFormat{ui::PixelFormat::RGBA_8888};
Rect sourceCrop;
- float frameScale{1};
+ float frameScaleX{1};
+ float frameScaleY{1};
bool captureSecureLayers{false};
int32_t uid{UNSET_UID};
// Force capture to be in a color space. If the value is ui::Dataspace::UNKNOWN, the captured
@@ -346,6 +347,8 @@
// the contents being accessed/captured by screenshot or unsecure display.
bool allowProtected = false;
+ bool grayscale = false;
+
virtual status_t write(Parcel& output) const;
virtual status_t read(const Parcel& input);
};
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 43b5dcd..b6b5c7c 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -18,6 +18,7 @@
#define ANDROID_GUI_SURFACE_H
#include <gui/BufferQueueDefs.h>
+#include <gui/FrameTimelineInfo.h>
#include <gui/HdrMetadata.h>
#include <gui/IGraphicBufferProducer.h>
#include <gui/IProducerListener.h>
@@ -187,7 +188,7 @@
status_t getConsumerUsage(uint64_t* outUsage) const;
virtual status_t setFrameRate(float frameRate, int8_t compatibility, bool shouldBeSeamless);
- virtual status_t setFrameTimelineVsync(int64_t frameTimelineVsyncId);
+ virtual status_t setFrameTimelineInfo(const FrameTimelineInfo& info);
protected:
virtual ~Surface();
@@ -273,7 +274,7 @@
int dispatchAddQueueInterceptor(va_list args);
int dispatchAddQueryInterceptor(va_list args);
int dispatchGetLastQueuedBuffer(va_list args);
- int dispatchSetFrameTimelineVsync(va_list args);
+ int dispatchSetFrameTimelineInfo(va_list args);
bool transformToDisplayInverse();
protected:
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 11db658..bd9f066 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -110,30 +110,29 @@
// Get immutable information about given physical display.
static status_t getDisplayInfo(const sp<IBinder>& display, DisplayInfo*);
- // Get configurations supported by given physical display.
- static status_t getDisplayConfigs(const sp<IBinder>& display, Vector<DisplayConfig>*);
+ // Get modes supported by given physical display.
+ static status_t getDisplayModes(const sp<IBinder>& display, Vector<ui::DisplayMode>*);
- // Get the ID of the active DisplayConfig, as getDisplayConfigs index.
- static int getActiveConfig(const sp<IBinder>& display);
+ // Get the ID of the active DisplayMode, as getDisplayModes index.
+ static int getActiveDisplayModeId(const sp<IBinder>& display);
- // Shorthand for getDisplayConfigs element at getActiveConfig index.
- static status_t getActiveDisplayConfig(const sp<IBinder>& display, DisplayConfig*);
+ // Shorthand for getDisplayModes element at getActiveDisplayModeId index.
+ static status_t getActiveDisplayMode(const sp<IBinder>& display, ui::DisplayMode*);
// Sets the refresh rate boundaries for the display.
- static status_t setDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
- int32_t defaultConfig, bool allowGroupSwitching,
- float primaryRefreshRateMin,
- float primaryRefreshRateMax,
- float appRequestRefreshRateMin,
- float appRequestRefreshRateMax);
+ static status_t setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, size_t defaultMode,
+ bool allowGroupSwitching,
+ float primaryRefreshRateMin,
+ float primaryRefreshRateMax,
+ float appRequestRefreshRateMin,
+ float appRequestRefreshRateMax);
// Gets the refresh rate boundaries for the display.
- static status_t getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
- int32_t* outDefaultConfig,
- bool* outAllowGroupSwitching,
- float* outPrimaryRefreshRateMin,
- float* outPrimaryRefreshRateMax,
- float* outAppRequestRefreshRateMin,
- float* outAppRequestRefreshRateMax);
+ static status_t getDesiredDisplayModeSpecs(const sp<IBinder>& displayToken,
+ size_t* outDefaultMode, bool* outAllowGroupSwitching,
+ float* outPrimaryRefreshRateMin,
+ float* outPrimaryRefreshRateMax,
+ float* outAppRequestRefreshRateMin,
+ float* outAppRequestRefreshRateMax);
// Gets the list of supported color modes for the given display
static status_t getDisplayColorModes(const sp<IBinder>& display,
@@ -385,8 +384,8 @@
int64_t mDesiredPresentTime = 0;
bool mIsAutoTimestamp = true;
- // The vsync Id provided by Choreographer.getVsyncId
- int64_t mFrameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID;
+ // The vsync id provided by Choreographer.getVsyncId and the input event id
+ FrameTimelineInfo mFrameTimelineInfo;
// If not null, transactions will be queued up using this token otherwise a common token
// per process will be used.
@@ -508,18 +507,6 @@
// Set the framenumber generated by the graphics producer to mimic BufferQueue behaviour.
Transaction& setFrameNumber(const sp<SurfaceControl>& sc, uint64_t frameNumber);
- // Detaches all child surfaces (and their children recursively)
- // from their SurfaceControl.
- // The child SurfaceControls will not throw exceptions or return errors,
- // but transactions will have no effect.
- // The child surfaces will continue to follow their parent surfaces,
- // and remain eligible for rendering, but their relative state will be
- // frozen. We use this in the WindowManager, in app shutdown/relaunch
- // scenarios, where the app would otherwise clean up its child Surfaces.
- // Sometimes the WindowManager needs to extend their lifetime slightly
- // in order to perform an exit animation or prevent flicker.
- Transaction& detachChildren(const sp<SurfaceControl>& sc);
-
#ifndef NO_INPUT
Transaction& setInputWindowInfo(const sp<SurfaceControl>& sc, const InputWindowInfo& info);
Transaction& setFocusedWindow(const FocusRequest& request);
@@ -546,11 +533,12 @@
Transaction& setFixedTransformHint(const sp<SurfaceControl>& sc, int32_t transformHint);
// Sets the frame timeline vsync id received from choreographer that corresponds
- // to the transaction.
- Transaction& setFrameTimelineVsync(int64_t frameTimelineVsyncId);
+ // to the transaction, and the input event id that identifies the input event that caused
+ // the current frame.
+ Transaction& setFrameTimelineInfo(const FrameTimelineInfo& frameTimelineInfo);
// Variant that only applies to a specific SurfaceControl.
- Transaction& setFrameTimelineVsync(const sp<SurfaceControl>& sc,
- int64_t frameTimelineVsyncId);
+ Transaction& setFrameTimelineInfo(const sp<SurfaceControl>& sc,
+ const FrameTimelineInfo& frameTimelineInfo);
// Indicates that the consumer should acquire the next frame as soon as it
// can and not wait for a frame to become available. This is only relevant
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
index 70e656d..5447b76 100644
--- a/libs/gui/tests/BLASTBufferQueue_test.cpp
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -28,7 +28,7 @@
#include <gui/SurfaceComposerClient.h>
#include <gui/SyncScreenCaptureListener.h>
#include <private/gui/ComposerService.h>
-#include <ui/DisplayConfig.h>
+#include <ui/DisplayMode.h>
#include <ui/GraphicBuffer.h>
#include <ui/GraphicTypes.h>
#include <ui/Transform.h>
@@ -107,9 +107,9 @@
t.apply();
t.clear();
- DisplayConfig config;
- ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(mDisplayToken, &config));
- const ui::Size& resolution = config.resolution;
+ ui::DisplayMode mode;
+ ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(mDisplayToken, &mode));
+ const ui::Size& resolution = mode.resolution;
mDisplayWidth = resolution.getWidth();
mDisplayHeight = resolution.getHeight();
diff --git a/libs/gui/tests/DisplayEventStructLayout_test.cpp b/libs/gui/tests/DisplayEventStructLayout_test.cpp
index c5093e2..7dbba31 100644
--- a/libs/gui/tests/DisplayEventStructLayout_test.cpp
+++ b/libs/gui/tests/DisplayEventStructLayout_test.cpp
@@ -25,7 +25,7 @@
TEST(DisplayEventStructLayoutTest, TestEventAlignment) {
CHECK_OFFSET(DisplayEventReceiver::Event, vsync, 24);
CHECK_OFFSET(DisplayEventReceiver::Event, hotplug, 24);
- CHECK_OFFSET(DisplayEventReceiver::Event, config, 24);
+ CHECK_OFFSET(DisplayEventReceiver::Event, modeChange, 24);
CHECK_OFFSET(DisplayEventReceiver::Event::Header, type, 0);
CHECK_OFFSET(DisplayEventReceiver::Event::Header, displayId, 8);
@@ -38,8 +38,8 @@
CHECK_OFFSET(DisplayEventReceiver::Event::Hotplug, connected, 0);
- CHECK_OFFSET(DisplayEventReceiver::Event::Config, configId, 0);
- CHECK_OFFSET(DisplayEventReceiver::Event::Config, vsyncPeriod, 8);
+ CHECK_OFFSET(DisplayEventReceiver::Event::ModeChange, modeId, 0);
+ CHECK_OFFSET(DisplayEventReceiver::Event::ModeChange, vsyncPeriod, 8);
CHECK_OFFSET(DisplayEventReceiver::Event::FrameRateOverride, uid, 0);
CHECK_OFFSET(DisplayEventReceiver::Event::FrameRateOverride, frameRateHz, 8);
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index 31cbbdc..d65a40b 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -41,7 +41,7 @@
#include <input/InputTransport.h>
#include <input/InputWindow.h>
-#include <ui/DisplayConfig.h>
+#include <ui/DisplayMode.h>
#include <ui/Rect.h>
#include <ui/Region.h>
@@ -272,13 +272,13 @@
const auto display = mComposerClient->getInternalDisplayToken();
ASSERT_NE(display, nullptr);
- DisplayConfig config;
- ASSERT_EQ(NO_ERROR, mComposerClient->getActiveDisplayConfig(display, &config));
+ ui::DisplayMode mode;
+ ASSERT_EQ(NO_ERROR, mComposerClient->getActiveDisplayMode(display, &mode));
// After a new buffer is queued, SurfaceFlinger is notified and will
// latch the new buffer on next vsync. Let's heuristically wait for 3
// vsyncs.
- mBufferPostDelay = static_cast<int32_t>(1e6 / config.refreshRate) * 3;
+ mBufferPostDelay = static_cast<int32_t>(1e6 / mode.refreshRate) * 3;
}
void TearDown() {
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 63db9a7..80e4c77 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -695,7 +695,7 @@
void destroyDisplay(const sp<IBinder>& /*display */) override {}
std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const override { return {}; }
sp<IBinder> getPhysicalDisplayToken(PhysicalDisplayId) const override { return nullptr; }
- status_t setTransactionState(int64_t /*frameTimelineVsyncId*/,
+ status_t setTransactionState(const FrameTimelineInfo& /*frameTimelineInfo*/,
const Vector<ComposerState>& /*state*/,
const Vector<DisplayState>& /*displays*/, uint32_t /*flags*/,
const sp<IBinder>& /*applyToken*/,
@@ -737,7 +737,7 @@
status_t getDisplayInfo(const sp<IBinder>& /*display*/, DisplayInfo*) override {
return NO_ERROR;
}
- status_t getDisplayConfigs(const sp<IBinder>& /*display*/, Vector<DisplayConfig>*) override {
+ status_t getDisplayModes(const sp<IBinder>& /*display*/, Vector<ui::DisplayMode>*) override {
return NO_ERROR;
}
status_t getDisplayState(const sp<IBinder>& /*display*/, ui::DisplayState*) override {
@@ -745,7 +745,7 @@
}
status_t getDisplayStats(const sp<IBinder>& /*display*/,
DisplayStatInfo* /*stats*/) override { return NO_ERROR; }
- int getActiveConfig(const sp<IBinder>& /*display*/) override { return 0; }
+ int getActiveDisplayModeId(const sp<IBinder>& /*display*/) override { return 0; }
status_t getDisplayColorModes(const sp<IBinder>& /*display*/,
Vector<ColorMode>* /*outColorModes*/) override {
return NO_ERROR;
@@ -843,21 +843,21 @@
const sp<IRegionSamplingListener>& /*listener*/) override {
return NO_ERROR;
}
- status_t setDesiredDisplayConfigSpecs(const sp<IBinder>& /*displayToken*/,
- int32_t /*defaultConfig*/, bool /*allowGroupSwitching*/,
- float /*primaryRefreshRateMin*/,
- float /*primaryRefreshRateMax*/,
- float /*appRequestRefreshRateMin*/,
- float /*appRequestRefreshRateMax*/) {
+ status_t setDesiredDisplayModeSpecs(const sp<IBinder>& /*displayToken*/, size_t /*defaultMode*/,
+ bool /*allowGroupSwitching*/,
+ float /*primaryRefreshRateMin*/,
+ float /*primaryRefreshRateMax*/,
+ float /*appRequestRefreshRateMin*/,
+ float /*appRequestRefreshRateMax*/) {
return NO_ERROR;
}
- status_t getDesiredDisplayConfigSpecs(const sp<IBinder>& /*displayToken*/,
- int32_t* /*outDefaultConfig*/,
- bool* /*outAllowGroupSwitching*/,
- float* /*outPrimaryRefreshRateMin*/,
- float* /*outPrimaryRefreshRateMax*/,
- float* /*outAppRequestRefreshRateMin*/,
- float* /*outAppRequestRefreshRateMax*/) override {
+ status_t getDesiredDisplayModeSpecs(const sp<IBinder>& /*displayToken*/,
+ size_t* /*outDefaultMode*/,
+ bool* /*outAllowGroupSwitching*/,
+ float* /*outPrimaryRefreshRateMin*/,
+ float* /*outPrimaryRefreshRateMax*/,
+ float* /*outAppRequestRefreshRateMin*/,
+ float* /*outAppRequestRefreshRateMax*/) override {
return NO_ERROR;
};
status_t notifyPowerBoost(int32_t /*boostId*/) override { return NO_ERROR; }
@@ -877,8 +877,8 @@
return NO_ERROR;
}
- status_t setFrameTimelineVsync(const sp<IGraphicBufferProducer>& /*surface*/,
- int64_t /*frameTimelineVsyncId*/) override {
+ status_t setFrameTimelineInfo(const sp<IGraphicBufferProducer>& /*surface*/,
+ const FrameTimelineInfo& /*frameTimelineInfo*/) override {
return NO_ERROR;
}
diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp
index 2ed441d..698cf6e 100644
--- a/libs/input/InputDevice.cpp
+++ b/libs/input/InputDevice.cpp
@@ -166,6 +166,7 @@
mKeyboardType(other.mKeyboardType),
mKeyCharacterMap(other.mKeyCharacterMap),
mHasVibrator(other.mHasVibrator),
+ mHasBattery(other.mHasBattery),
mHasButtonUnderPad(other.mHasButtonUnderPad),
mHasSensor(other.mHasSensor),
mMotionRanges(other.mMotionRanges),
@@ -187,6 +188,7 @@
mSources = 0;
mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE;
mHasVibrator = false;
+ mHasBattery = false;
mHasButtonUnderPad = false;
mHasSensor = false;
mMotionRanges.clear();
diff --git a/libs/input/android/os/IInputConstants.aidl b/libs/input/android/os/IInputConstants.aidl
index 6316b59..bce0ec8 100644
--- a/libs/input/android/os/IInputConstants.aidl
+++ b/libs/input/android/os/IInputConstants.aidl
@@ -28,4 +28,13 @@
* to identify apps that are using this flag.
*/
const long BLOCK_FLAG_SLIPPERY = 157929241;
+
+ // Indicate invalid battery capacity
+ const int INVALID_BATTERY_CAPACITY = -1;
+
+ /**
+ * Every input event has an id. This constant value is used when a valid input event id is not
+ * available.
+ */
+ const int INVALID_INPUT_EVENT_ID = 0;
}
diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp
index 6d91916..dc2dd29 100644
--- a/libs/nativedisplay/AChoreographer.cpp
+++ b/libs/nativedisplay/AChoreographer.cpp
@@ -21,7 +21,7 @@
#include <gui/DisplayEventDispatcher.h>
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
-#include <nativehelper/JNIHelp.h>
+#include <jni.h>
#include <private/android/choreographer.h>
#include <utils/Looper.h>
#include <utils/Timers.h>
@@ -138,8 +138,8 @@
void dispatchVsync(nsecs_t timestamp, PhysicalDisplayId displayId, uint32_t count,
VsyncEventData vsyncEventData) override;
void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override;
- void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t configId,
- nsecs_t vsyncPeriod) override;
+ void dispatchModeChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t modeId,
+ nsecs_t vsyncPeriod) override;
void dispatchNullEvent(nsecs_t, PhysicalDisplayId) override;
void dispatchFrameRateOverrides(nsecs_t timestamp, PhysicalDisplayId displayId,
std::vector<FrameRateOverride> overrides) override;
@@ -382,8 +382,8 @@
this, to_string(displayId).c_str(), toString(connected));
}
-void Choreographer::dispatchConfigChanged(nsecs_t, PhysicalDisplayId, int32_t, nsecs_t) {
- LOG_ALWAYS_FATAL("dispatchConfigChanged was called but was never registered");
+void Choreographer::dispatchModeChanged(nsecs_t, PhysicalDisplayId, int32_t, nsecs_t) {
+ LOG_ALWAYS_FATAL("dispatchModeChanged was called but was never registered");
}
void Choreographer::dispatchFrameRateOverrides(nsecs_t, PhysicalDisplayId,
diff --git a/libs/nativedisplay/ADisplay.cpp b/libs/nativedisplay/ADisplay.cpp
index 277635c..c595aa6 100644
--- a/libs/nativedisplay/ADisplay.cpp
+++ b/libs/nativedisplay/ADisplay.cpp
@@ -16,8 +16,8 @@
#include <apex/display.h>
#include <gui/SurfaceComposerClient.h>
-#include <ui/DisplayConfig.h>
#include <ui/DisplayInfo.h>
+#include <ui/DisplayMode.h>
#include <ui/GraphicTypes.h>
#include <ui/PixelFormat.h>
@@ -134,8 +134,8 @@
return NO_INIT;
}
- std::vector<DisplayConfigImpl> configsPerDisplay[size];
- int numConfigs = 0;
+ std::vector<DisplayConfigImpl> modesPerDisplay[size];
+ int numModes = 0;
for (int i = 0; i < size; ++i) {
const sp<IBinder> token = SurfaceComposerClient::getPhysicalDisplayToken(ids[i]);
@@ -145,23 +145,23 @@
return status;
}
- Vector<DisplayConfig> configs;
- if (const status_t status = SurfaceComposerClient::getDisplayConfigs(token, &configs);
+ Vector<ui::DisplayMode> modes;
+ if (const status_t status = SurfaceComposerClient::getDisplayModes(token, &modes);
status != OK) {
return status;
}
- if (configs.empty()) {
+ if (modes.empty()) {
return NO_INIT;
}
- numConfigs += configs.size();
- configsPerDisplay[i].reserve(configs.size());
- for (int j = 0; j < configs.size(); ++j) {
- const DisplayConfig& config = configs[j];
- configsPerDisplay[i].emplace_back(
- DisplayConfigImpl{config.resolution.getWidth(), config.resolution.getHeight(),
- info.density, config.refreshRate, config.sfVsyncOffset,
- config.appVsyncOffset});
+ numModes += modes.size();
+ modesPerDisplay[i].reserve(modes.size());
+ for (int j = 0; j < modes.size(); ++j) {
+ const ui::DisplayMode& mode = modes[j];
+ modesPerDisplay[i].emplace_back(
+ DisplayConfigImpl{mode.resolution.getWidth(), mode.resolution.getHeight(),
+ info.density, mode.refreshRate, mode.sfVsyncOffset,
+ mode.appVsyncOffset});
}
}
@@ -192,7 +192,7 @@
// contiguous block of DisplayConfigImpls specific to that display.
DisplayImpl** const impls = reinterpret_cast<DisplayImpl**>(
malloc((sizeof(DisplayImpl) + sizeof(DisplayImpl*)) * size +
- sizeof(DisplayConfigImpl) * numConfigs));
+ sizeof(DisplayConfigImpl) * numModes));
DisplayImpl* const displayData = reinterpret_cast<DisplayImpl*>(impls + size);
DisplayConfigImpl* configData = reinterpret_cast<DisplayConfigImpl*>(displayData + size);
@@ -200,7 +200,7 @@
const PhysicalDisplayId id = ids[i];
const ADisplayType type = (internalId == id) ? ADisplayType::DISPLAY_TYPE_INTERNAL
: ADisplayType::DISPLAY_TYPE_EXTERNAL;
- const std::vector<DisplayConfigImpl>& configs = configsPerDisplay[i];
+ const std::vector<DisplayConfigImpl>& configs = modesPerDisplay[i];
memcpy(configData, configs.data(), sizeof(DisplayConfigImpl) * configs.size());
displayData[i] = DisplayImpl{id,
@@ -257,7 +257,7 @@
CHECK_NOT_NULL(display);
sp<IBinder> token = getToken(display);
- const int index = SurfaceComposerClient::getActiveConfig(token);
+ const int index = SurfaceComposerClient::getActiveDisplayModeId(token);
if (index < 0) {
return index;
}
diff --git a/libs/nativedisplay/Android.bp b/libs/nativedisplay/Android.bp
index f56b3a2..6574ae6 100644
--- a/libs/nativedisplay/Android.bp
+++ b/libs/nativedisplay/Android.bp
@@ -53,15 +53,13 @@
"libcutils",
"libEGL",
"libGLESv2",
- "libnativehelper",
],
- export_shared_lib_headers: [
- "libnativehelper",
- ],
+ export_header_lib_headers: ["jni_headers"],
header_libs: [
+ "jni_headers",
"libnativedisplay_headers",
+ "libnativehelper_header_only",
],
-
}
diff --git a/libs/nativedisplay/include-private/private/android/choreographer.h b/libs/nativedisplay/include-private/private/android/choreographer.h
index d3a4a66..0f4fd45 100644
--- a/libs/nativedisplay/include-private/private/android/choreographer.h
+++ b/libs/nativedisplay/include-private/private/android/choreographer.h
@@ -18,7 +18,7 @@
#include <apex/choreographer.h>
#include <inttypes.h>
-#include <nativehelper/JNIHelp.h>
+#include <jni.h>
namespace android {
diff --git a/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h b/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
index f371667..85fe42f 100644
--- a/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
+++ b/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
@@ -19,7 +19,7 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
-#include <nativehelper/JNIHelp.h>
+#include <jni.h>
#include <system/graphics.h>
// This file provides a facade API on top of SurfaceTexture, which avoids using
diff --git a/libs/nativedisplay/surfacetexture/surface_texture.cpp b/libs/nativedisplay/surfacetexture/surface_texture.cpp
index ebe4484..c214ab7 100644
--- a/libs/nativedisplay/surfacetexture/surface_texture.cpp
+++ b/libs/nativedisplay/surfacetexture/surface_texture.cpp
@@ -29,8 +29,7 @@
#include <mutex>
#include <jni.h>
-#include <nativehelper/JNIHelp.h>
-#include <nativehelper/ScopedLocalRef.h>
+#include <nativehelper/scoped_local_ref.h>
struct ASurfaceTexture {
android::sp<android::SurfaceTexture> consumer;
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index 4fcca9e..20a1f74 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -334,8 +334,6 @@
// clang-format on
-#if __ANDROID_API__ >= 26
-
/**
* Allocates a buffer that matches the passed AHardwareBuffer_Desc.
*
@@ -478,10 +476,6 @@
AHardwareBuffer* _Nullable* _Nonnull outBuffer)
__INTRODUCED_IN(26);
-#endif // __ANDROID_API__ >= 26
-
-#if __ANDROID_API__ >= 29
-
/**
* Lock a potentially multi-planar AHardwareBuffer for direct CPU access.
*
@@ -551,10 +545,6 @@
int32_t* _Nonnull outBytesPerPixel,
int32_t* _Nonnull outBytesPerStride) __INTRODUCED_IN(29);
-#endif // __ANDROID_API__ >= 29
-
-#if __ANDROID_API__ >= 31
-
/**
* Get the system wide unique id for an AHardwareBuffer.
*
@@ -566,8 +556,6 @@
int AHardwareBuffer_getId(const AHardwareBuffer* _Nonnull buffer, uint64_t* _Nonnull outId)
__INTRODUCED_IN(31);
-#endif // __ANDROID_API__ >= 31
-
__END_DECLS
#endif // ANDROID_HARDWARE_BUFFER_H
diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h
index deea59b..285f2fb 100644
--- a/libs/nativewindow/include/android/native_window.h
+++ b/libs/nativewindow/include/android/native_window.h
@@ -186,8 +186,6 @@
*/
int32_t ANativeWindow_unlockAndPost(ANativeWindow* window);
-#if __ANDROID_API__ >= 26
-
/**
* Set a transform that will be applied to future buffers posted to the window.
*
@@ -198,10 +196,6 @@
*/
int32_t ANativeWindow_setBuffersTransform(ANativeWindow* window, int32_t transform) __INTRODUCED_IN(26);
-#endif // __ANDROID_API__ >= 26
-
-#if __ANDROID_API__ >= 28
-
/**
* All buffers queued after this call will be associated with the dataSpace
* parameter specified.
@@ -230,10 +224,6 @@
*/
int32_t ANativeWindow_getBuffersDataSpace(ANativeWindow* window) __INTRODUCED_IN(28);
-#endif // __ANDROID_API__ >= 28
-
-#if __ANDROID_API__ >= 30
-
/** Compatibility value for ANativeWindow_setFrameRate. */
enum ANativeWindow_FrameRateCompatibility {
/**
@@ -275,11 +265,7 @@
*
* Available since API level 30.
*/
-void ANativeWindow_tryAllocateBuffers(ANativeWindow* window);
-
-#endif // __ANDROID_API__ >= 30
-
-#if __ANDROID_API__ >= 31
+void ANativeWindow_tryAllocateBuffers(ANativeWindow* window) __INTRODUCED_IN(30);
/**
* Sets the intended frame rate for this window.
@@ -322,8 +308,6 @@
int32_t ANativeWindow_setFrameRateWithSeamlessness(ANativeWindow* window, float frameRate,
int8_t compatibility, bool shouldBeSeamless) __INTRODUCED_IN(31);
-#endif // __ANDROID_API__ >= 31
-
#ifdef __cplusplus
};
#endif
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index 82d2e66..ffe4412 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -255,7 +255,7 @@
NATIVE_WINDOW_ALLOCATE_BUFFERS = 45, /* private */
NATIVE_WINDOW_GET_LAST_QUEUED_BUFFER = 46, /* private */
NATIVE_WINDOW_SET_QUERY_INTERCEPTOR = 47, /* private */
- NATIVE_WINDOW_SET_FRAME_TIMELINE_VSYNC = 48, /* private */
+ NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO = 48, /* private */
// clang-format on
};
@@ -1023,10 +1023,11 @@
(int)compatibility, (int)shouldBeSeamless);
}
-static inline int native_window_set_frame_timeline_vsync(struct ANativeWindow* window,
- int64_t frameTimelineVsyncId) {
- return window->perform(window, NATIVE_WINDOW_SET_FRAME_TIMELINE_VSYNC,
- frameTimelineVsyncId);
+static inline int native_window_set_frame_timeline_info(struct ANativeWindow* window,
+ int64_t frameTimelineVsyncId,
+ int32_t inputEventId) {
+ return window->perform(window, NATIVE_WINDOW_SET_FRAME_TIMELINE_INFO,
+ frameTimelineVsyncId, inputEventId);
}
// ------------------------------------------------------------------------------------------------
diff --git a/libs/renderengine/OWNERS b/libs/renderengine/OWNERS
index b44456b..08cf2de 100644
--- a/libs/renderengine/OWNERS
+++ b/libs/renderengine/OWNERS
@@ -1,4 +1,3 @@
alecmouri@google.com
jreck@google.com
lpy@google.com
-stoza@google.com
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index 79505ba..dd26b17 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -33,9 +33,11 @@
#include <SkRegion.h>
#include <SkShadowUtils.h>
#include <SkSurface.h>
+#include <android-base/stringprintf.h>
#include <gl/GrGLInterface.h>
#include <sync/sync.h>
#include <ui/BlurRegion.h>
+#include <ui/DebugUtils.h>
#include <ui/GraphicBuffer.h>
#include <utils/Trace.h>
@@ -59,6 +61,8 @@
namespace renderengine {
namespace skia {
+using base::StringAppendF;
+
static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs, EGLint attribute,
EGLint wanted, EGLConfig* outConfig) {
EGLint numConfigs = -1, n = 0;
@@ -1075,6 +1079,53 @@
return value;
}
+void SkiaGLRenderEngine::dump(std::string& result) {
+ const gl::GLExtensions& extensions = gl::GLExtensions::getInstance();
+
+ StringAppendF(&result, "\n ------------RE-----------------\n");
+ StringAppendF(&result, "EGL implementation : %s\n", extensions.getEGLVersion());
+ StringAppendF(&result, "%s\n", extensions.getEGLExtensions());
+ StringAppendF(&result, "GLES: %s, %s, %s\n", extensions.getVendor(), extensions.getRenderer(),
+ extensions.getVersion());
+ StringAppendF(&result, "%s\n", extensions.getExtensions());
+ StringAppendF(&result, "RenderEngine supports protected context: %d\n",
+ supportsProtectedContent());
+ StringAppendF(&result, "RenderEngine is in protected context: %d\n", mInProtectedContext);
+
+ {
+ std::lock_guard<std::mutex> lock(mRenderingMutex);
+ StringAppendF(&result, "RenderEngine texture cache size: %zu\n", mTextureCache.size());
+ StringAppendF(&result, "Dumping buffer ids...\n");
+ // TODO(178539829): It would be nice to know which layer these are coming from and what
+ // the texture sizes are.
+ for (const auto& [id, unused] : mTextureCache) {
+ StringAppendF(&result, "- 0x%" PRIx64 "\n", id);
+ }
+ StringAppendF(&result, "\n");
+ StringAppendF(&result, "RenderEngine protected texture cache size: %zu\n",
+ mProtectedTextureCache.size());
+ StringAppendF(&result, "Dumping buffer ids...\n");
+ for (const auto& [id, unused] : mProtectedTextureCache) {
+ StringAppendF(&result, "- 0x%" PRIx64 "\n", id);
+ }
+ StringAppendF(&result, "\n");
+ StringAppendF(&result, "RenderEngine runtime effects: %zu\n", mRuntimeEffects.size());
+ for (const auto& [linearEffect, unused] : mRuntimeEffects) {
+ StringAppendF(&result, "- inputDataspace: %s\n",
+ dataspaceDetails(
+ static_cast<android_dataspace>(linearEffect.inputDataspace))
+ .c_str());
+ StringAppendF(&result, "- outputDataspace: %s\n",
+ dataspaceDetails(
+ static_cast<android_dataspace>(linearEffect.outputDataspace))
+ .c_str());
+ StringAppendF(&result, "undoPremultipliedAlpha: %s\n",
+ linearEffect.undoPremultipliedAlpha ? "true" : "false");
+ }
+ }
+ StringAppendF(&result, "\n");
+}
+
} // namespace skia
} // namespace renderengine
} // namespace android
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h
index 3294de8..810fc2a 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.h
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.h
@@ -63,7 +63,7 @@
bool useProtectedContext(bool useProtectedContext) override;
protected:
- void dump(std::string& /*result*/) override{};
+ void dump(std::string& result) override;
size_t getMaxTextureSize() const override;
size_t getMaxViewportDims() const override;
diff --git a/libs/renderengine/skia/debug/record.sh b/libs/renderengine/skia/debug/record.sh
new file mode 100755
index 0000000..bc406d9
--- /dev/null
+++ b/libs/renderengine/skia/debug/record.sh
@@ -0,0 +1,106 @@
+# This script captures MSKP files from RenderEngine in a connected device.
+# this only functions when RenderEngine uses the Skia backend.
+# it triggers code in SkiaCapture.cpp.
+
+# for a newly flashed device, perform first time steps with
+# record.sh rootandsetup
+
+# record all frames that RenderEngine handles over the span of 2 seconds.
+# record.sh 2000
+
+if [ -z "$1" ]; then
+ printf 'Usage:\n record.sh rootandsetup\n'
+ printf ' record.sh MILLISECONDS\n\n'
+ exit 1
+elif [ "$1" == "rootandsetup" ]; then
+ # first time use requires these changes
+ adb root
+ adb shell setenforce 0
+ adb shell setprop debug.renderengine.backend "skiagl"
+ adb shell stop
+ adb shell start
+ exit 1;
+fi
+
+# name of the newest file in /data/user/ before starting
+oldname=$(adb shell ls -cr /data/user/ | head -n 1)
+
+# record frames for some number of milliseconds.
+adb shell setprop debug.renderengine.capture_skia_ms $1
+
+# give the device time to both record, and starting writing the file.
+# Total time needed to write the file depends on how much data was recorded.
+# the loop at the end waits for this.
+sleep $(($1 / 1000 + 2));
+
+# There is no guarantee that at least one frame passed through renderengine during that time
+# but as far as I know it always at least writes a 0-byte file with a new name, unless it crashes
+# the process it is recording.
+# /data/user/re_skiacapture_56204430551705.mskp
+
+# list the files here from newest to oldest, keep only the name of the newest.
+name=$(adb shell ls -cr /data/user/ | head -n 1)
+remote_path=/data/user/$name
+
+if [[ $oldname = $name ]]; then
+ echo "No new file written, probably no RenderEngine activity during recording period."
+ exit 1
+fi
+
+# return the size of a file in bytes
+adb_filesize() {
+ adb shell "wc -c \"$1\"" 2> /dev/null | awk '{print $1}'
+}
+
+mskp_size=$(adb_filesize "/data/user/$name")
+if [[ $mskp_size = "0" ]]; then
+ echo "Empty file, probably no RenderEngine activity during recording period."
+ exit 1
+fi
+
+spin() {
+ case "$spin" in
+ 1) printf '\b|';;
+ 2) printf '\b\\';;
+ 3) printf '\b-';;
+ *) printf '\b/';;
+ esac
+ spin=$(( ( ${spin:-0} + 1 ) % 4 ))
+ sleep $1
+}
+
+printf "MSKP captured, Waiting for file serialization to finish.\n"
+
+local_path=~/Downloads/$name
+
+# wait for the file size to stop changing
+
+timeout=$(( $(date +%s) + 300))
+last_size='0' # output of last size check command
+unstable=true # false once the file size stops changing
+counter=0 # used to perform size check only 1/sec though we update spinner 20/sec
+# loop until the file size is unchanged for 1 second.
+while [ $unstable != 0 ] ; do
+ spin 0.05
+ counter=$(( $counter+1 ))
+ if ! (( $counter % 20)) ; then
+ new_size=$(adb_filesize "$remote_path")
+ unstable=$(($new_size != $last_size))
+ last_size=$new_size
+ fi
+ if [ $(date +%s) -gt $timeout ] ; then
+ printf '\bTimed out.\n'
+ exit 3
+ fi
+done
+printf '\b'
+
+printf "MSKP file serialized: %s\n" $(echo $last_size | numfmt --to=iec)
+
+adb pull "$remote_path" "$local_path"
+if ! [ -f "$local_path" ] ; then
+ printf "something went wrong with `adb pull`."
+ exit 4
+fi
+adb shell rm "$remote_path"
+printf 'SKP saved to %s\n\n' "$local_path"
\ No newline at end of file
diff --git a/libs/sensorprivacy/SensorPrivacyManager.cpp b/libs/sensorprivacy/SensorPrivacyManager.cpp
index 7bddee6..4714469 100644
--- a/libs/sensorprivacy/SensorPrivacyManager.cpp
+++ b/libs/sensorprivacy/SensorPrivacyManager.cpp
@@ -64,13 +64,15 @@
}
}
-void SensorPrivacyManager::addIndividualSensorPrivacyListener(int userId, int sensor,
+status_t SensorPrivacyManager::addIndividualSensorPrivacyListener(int userId, int sensor,
const sp<hardware::ISensorPrivacyListener>& listener)
{
sp<hardware::ISensorPrivacyManager> service = getService();
if (service != nullptr) {
- service->addIndividualSensorPrivacyListener(userId, sensor, listener);
+ return service->addIndividualSensorPrivacyListener(userId, sensor, listener)
+ .transactionError();
}
+ return UNEXPECTED_NULL;
}
void SensorPrivacyManager::removeSensorPrivacyListener(
@@ -106,6 +108,19 @@
return false;
}
+status_t SensorPrivacyManager::isIndividualSensorPrivacyEnabled(int userId, int sensor,
+ bool &returnVal)
+{
+ sp<hardware::ISensorPrivacyManager> service = getService();
+ if (service != nullptr) {
+ binder::Status res = service->isIndividualSensorPrivacyEnabled(userId, sensor, &returnVal);
+ return res.transactionError();
+ }
+ // if the SensorPrivacyManager is not available then assume sensor privacy is disabled
+ returnVal = false;
+ return UNKNOWN_ERROR;
+}
+
status_t SensorPrivacyManager::linkToDeath(const sp<IBinder::DeathRecipient>& recipient)
{
sp<hardware::ISensorPrivacyManager> service = getService();
diff --git a/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h b/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h
index bd7c726..12778e1 100644
--- a/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h
+++ b/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h
@@ -36,11 +36,12 @@
SensorPrivacyManager();
void addSensorPrivacyListener(const sp<hardware::ISensorPrivacyListener>& listener);
- void addIndividualSensorPrivacyListener(int userId, int sensor,
+ status_t addIndividualSensorPrivacyListener(int userId, int sensor,
const sp<hardware::ISensorPrivacyListener>& listener);
void removeSensorPrivacyListener(const sp<hardware::ISensorPrivacyListener>& listener);
bool isSensorPrivacyEnabled();
bool isIndividualSensorPrivacyEnabled(int userId, int sensor);
+ status_t isIndividualSensorPrivacyEnabled(int userId, int sensor, bool &result);
status_t linkToDeath(const sp<IBinder::DeathRecipient>& recipient);
status_t unlinkToDeath(const sp<IBinder::DeathRecipient>& recipient);
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 7c68aaa..714ee3e 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -140,7 +140,7 @@
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.allocator@4.0",
- "android.hardware.graphics.common-unstable-ndk_platform",
+ "android.hardware.graphics.common-V2-ndk_platform",
"android.hardware.graphics.common@1.2",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@2.1",
@@ -157,7 +157,7 @@
export_shared_lib_headers: [
"android.hardware.graphics.common@1.2",
- "android.hardware.graphics.common-unstable-ndk_platform",
+ "android.hardware.graphics.common-V2-ndk_platform",
"android.hardware.graphics.mapper@4.0",
"libgralloctypes",
],
diff --git a/libs/ui/OWNERS b/libs/ui/OWNERS
index b1317b1..5110a6c 100644
--- a/libs/ui/OWNERS
+++ b/libs/ui/OWNERS
@@ -4,4 +4,3 @@
lpy@google.com
mathias@google.com
romainguy@google.com
-stoza@google.com
diff --git a/libs/ui/PublicFormat.cpp b/libs/ui/PublicFormat.cpp
index a6595cf..78e82da 100644
--- a/libs/ui/PublicFormat.cpp
+++ b/libs/ui/PublicFormat.cpp
@@ -100,6 +100,7 @@
case HAL_PIXEL_FORMAT_RAW12:
case HAL_PIXEL_FORMAT_YCbCr_420_888:
case HAL_PIXEL_FORMAT_YV12:
+ case HAL_PIXEL_FORMAT_YCBCR_P010:
// Enums overlap in both name and value
return static_cast<PublicFormat>(format);
case HAL_PIXEL_FORMAT_RAW16:
diff --git a/libs/ui/include/ui/DisplayConfig.h b/libs/ui/include/ui/DisplayMode.h
similarity index 81%
rename from libs/ui/include/ui/DisplayConfig.h
rename to libs/ui/include/ui/DisplayMode.h
index d6fbaab..145d7ef 100644
--- a/libs/ui/include/ui/DisplayConfig.h
+++ b/libs/ui/include/ui/DisplayMode.h
@@ -21,10 +21,10 @@
#include <ui/Size.h>
#include <utils/Timers.h>
-namespace android {
+namespace android::ui {
-// Configuration supported by physical display.
-struct DisplayConfig {
+// Mode supported by physical display.
+struct DisplayMode {
ui::Size resolution;
float xDpi = 0;
float yDpi = 0;
@@ -33,9 +33,9 @@
nsecs_t appVsyncOffset = 0;
nsecs_t sfVsyncOffset = 0;
nsecs_t presentationDeadline = 0;
- int configGroup = -1;
+ int group = -1;
};
-static_assert(std::is_trivially_copyable_v<DisplayConfig>);
+static_assert(std::is_trivially_copyable_v<DisplayMode>);
-} // namespace android
+} // namespace android::ui
diff --git a/libs/ui/include/ui/PublicFormat.h b/libs/ui/include/ui/PublicFormat.h
index 22274a2..aa58805 100644
--- a/libs/ui/include/ui/PublicFormat.h
+++ b/libs/ui/include/ui/PublicFormat.h
@@ -54,6 +54,7 @@
YV12 = 0x32315659,
Y8 = 0x20203859,
Y16 = 0x20363159, // @hide
+ YCBCR_P010 = 0x36,
DEPTH16 = 0x44363159,
DEPTH_JPEG = 0x69656963,
HEIC = 0x48454946,
diff --git a/libs/ui/include_vndk/ui/DisplayConfig.h b/libs/ui/include_vndk/ui/DisplayConfig.h
deleted file mode 120000
index 1450319..0000000
--- a/libs/ui/include_vndk/ui/DisplayConfig.h
+++ /dev/null
@@ -1 +0,0 @@
-../../include/ui/DisplayConfig.h
\ No newline at end of file
diff --git a/libs/ui/include_vndk/ui/DisplayMode.h b/libs/ui/include_vndk/ui/DisplayMode.h
new file mode 120000
index 0000000..c87754a
--- /dev/null
+++ b/libs/ui/include_vndk/ui/DisplayMode.h
@@ -0,0 +1 @@
+../../include/ui/DisplayMode.h
\ No newline at end of file
diff --git a/opengl/tests/lib/WindowSurface.cpp b/opengl/tests/lib/WindowSurface.cpp
index dfb9c92..fd4522e 100644
--- a/opengl/tests/lib/WindowSurface.cpp
+++ b/opengl/tests/lib/WindowSurface.cpp
@@ -21,7 +21,7 @@
#include <gui/ISurfaceComposer.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
-#include <ui/DisplayConfig.h>
+#include <ui/DisplayMode.h>
#include <ui/DisplayState.h>
using namespace android;
@@ -42,10 +42,10 @@
return;
}
- DisplayConfig displayConfig;
- err = SurfaceComposerClient::getActiveDisplayConfig(displayToken, &displayConfig);
+ ui::DisplayMode displayMode;
+ err = SurfaceComposerClient::getActiveDisplayMode(displayToken, &displayMode);
if (err != NO_ERROR) {
- fprintf(stderr, "ERROR: unable to get active display config\n");
+ fprintf(stderr, "ERROR: unable to get active display mode\n");
return;
}
@@ -56,7 +56,7 @@
return;
}
- const ui::Size& resolution = displayConfig.resolution;
+ const ui::Size& resolution = displayMode.resolution;
auto width = resolution.getWidth();
auto height = resolution.getHeight();
diff --git a/services/audiomanager/IAudioManager.cpp b/services/audiomanager/IAudioManager.cpp
index 0d17265..ae1bb1a 100644
--- a/services/audiomanager/IAudioManager.cpp
+++ b/services/audiomanager/IAudioManager.cpp
@@ -36,7 +36,7 @@
}
virtual audio_unique_id_t trackPlayer(player_type_t playerType, audio_usage_t usage,
- audio_content_type_t content, const sp<IBinder>& player) {
+ audio_content_type_t content, const sp<IBinder>& player, audio_session_t sessionId) {
Parcel data, reply;
data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
data.writeInt32(1); // non-null PlayerIdCard parcelable
@@ -54,6 +54,8 @@
data.writeInt32(-1977 /*ATTR_PARCEL_IS_NULL_BUNDLE*/); // no bundle
// write IPlayer
data.writeStrongBinder(player);
+ // write session Id
+ data.writeInt32((int32_t)sessionId);
// get new PIId in reply
const status_t res = remote()->transact(TRACK_PLAYER, data, &reply, 0);
if (res != OK || reply.readExceptionCode() != 0) {
@@ -131,6 +133,14 @@
data.writeInt32((int32_t) riid);
return remote()->transact(RELEASE_RECORDER, data, &reply, IBinder::FLAG_ONEWAY);
}
+
+ virtual status_t playerSessionId(audio_unique_id_t piid, audio_session_t sessionId) {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioManager::getInterfaceDescriptor());
+ data.writeInt32((int32_t) piid);
+ data.writeInt32((int32_t) sessionId);
+ return remote()->transact(PLAYER_SESSION_ID, data, &reply, IBinder::FLAG_ONEWAY);
+ }
};
IMPLEMENT_META_INTERFACE(AudioManager, "android.media.IAudioService");
diff --git a/services/automotive/display/AutomotiveDisplayProxyService.cpp b/services/automotive/display/AutomotiveDisplayProxyService.cpp
index 321bb83..d6fc695 100644
--- a/services/automotive/display/AutomotiveDisplayProxyService.cpp
+++ b/services/automotive/display/AutomotiveDisplayProxyService.cpp
@@ -41,10 +41,10 @@
}
// Get the resolution from stored display state.
- DisplayConfig displayConfig = {};
- auto err = SurfaceComposerClient::getActiveDisplayConfig(displayToken, &displayConfig);
+ ui::DisplayMode displayMode = {};
+ auto err = SurfaceComposerClient::getActiveDisplayMode(displayToken, &displayMode);
if (err != NO_ERROR) {
- ALOGE("Failed to get display configuration of %lX. "
+ ALOGE("Failed to get display mode of %lX. "
"This display will be ignored.", (unsigned long)id);
return nullptr;
}
@@ -57,8 +57,8 @@
return nullptr;
}
- auto displayWidth = displayConfig.resolution.getWidth();
- auto displayHeight = displayConfig.resolution.getHeight();
+ auto displayWidth = displayMode.resolution.getWidth();
+ auto displayHeight = displayMode.resolution.getHeight();
if ((displayState.orientation != ui::ROTATION_0) &&
(displayState.orientation != ui::ROTATION_180)) {
std::swap(displayWidth, displayHeight);
@@ -161,10 +161,10 @@
if (displayToken == nullptr) {
ALOGE("Given display id, 0x%lX, is invalid.", (unsigned long)id);
} else {
- DisplayConfig displayConfig = {};
- auto err = SurfaceComposerClient::getActiveDisplayConfig(displayToken, &displayConfig);
+ ui::DisplayMode displayMode = {};
+ auto err = SurfaceComposerClient::getActiveDisplayMode(displayToken, &displayMode);
if (err != NO_ERROR) {
- ALOGW("Failed to get display configuration of %lX. "
+ ALOGW("Failed to get display mode of %lX. "
"This display will be ignored.", (unsigned long)id);
}
@@ -175,7 +175,7 @@
"This display will be ignored.", (unsigned long)id);
}
- activeConfig.setToExternal((uint8_t*)&displayConfig, sizeof(DisplayConfig));
+ activeConfig.setToExternal((uint8_t*)&displayMode, sizeof(ui::DisplayMode));
activeState.setToExternal((uint8_t*)&displayState, sizeof(DisplayState));
}
diff --git a/services/automotive/display/include/AutomotiveDisplayProxyService.h b/services/automotive/display/include/AutomotiveDisplayProxyService.h
index e2fc0d2..4482b9b 100644
--- a/services/automotive/display/include/AutomotiveDisplayProxyService.h
+++ b/services/automotive/display/include/AutomotiveDisplayProxyService.h
@@ -20,7 +20,7 @@
#include <gui/ISurfaceComposer.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
-#include <ui/DisplayConfig.h>
+#include <ui/DisplayMode.h>
#include <ui/DisplayState.h>
#include <tuple>
#include <vector>
diff --git a/services/inputflinger/InputClassifier.cpp b/services/inputflinger/InputClassifier.cpp
index f5f0400..a9cbd5a 100644
--- a/services/inputflinger/InputClassifier.cpp
+++ b/services/inputflinger/InputClassifier.cpp
@@ -396,6 +396,11 @@
mListener->notifySensor(args);
}
+void InputClassifier::notifyVibratorState(const NotifyVibratorStateArgs* args) {
+ // pass through
+ mListener->notifyVibratorState(args);
+}
+
void InputClassifier::notifySwitch(const NotifySwitchArgs* args) {
// pass through
mListener->notifySwitch(args);
diff --git a/services/inputflinger/InputClassifier.h b/services/inputflinger/InputClassifier.h
index bf10920..1eef020 100644
--- a/services/inputflinger/InputClassifier.h
+++ b/services/inputflinger/InputClassifier.h
@@ -230,6 +230,7 @@
virtual void notifyMotion(const NotifyMotionArgs* args) override;
virtual void notifySwitch(const NotifySwitchArgs* args) override;
virtual void notifySensor(const NotifySensorArgs* args) override;
+ virtual void notifyVibratorState(const NotifyVibratorStateArgs* args) override;
virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override;
diff --git a/services/inputflinger/InputListener.cpp b/services/inputflinger/InputListener.cpp
index 4be49b1..4b1f350 100644
--- a/services/inputflinger/InputListener.cpp
+++ b/services/inputflinger/InputListener.cpp
@@ -246,6 +246,24 @@
listener->notifySensor(this);
}
+// --- NotifyVibratorStateArgs ---
+
+NotifyVibratorStateArgs::NotifyVibratorStateArgs(int32_t id, nsecs_t eventTime, int32_t deviceId,
+ bool isOn)
+ : NotifyArgs(id, eventTime), deviceId(deviceId), isOn(isOn) {}
+
+NotifyVibratorStateArgs::NotifyVibratorStateArgs(const NotifyVibratorStateArgs& other)
+ : NotifyArgs(other.id, other.eventTime), deviceId(other.deviceId), isOn(other.isOn) {}
+
+bool NotifyVibratorStateArgs::operator==(const NotifyVibratorStateArgs rhs) const {
+ return id == rhs.id && eventTime == rhs.eventTime && deviceId == rhs.deviceId &&
+ isOn == rhs.isOn;
+}
+
+void NotifyVibratorStateArgs::notify(const sp<InputListenerInterface>& listener) const {
+ listener->notifyVibratorState(this);
+}
+
// --- NotifyDeviceResetArgs ---
NotifyDeviceResetArgs::NotifyDeviceResetArgs(int32_t id, nsecs_t eventTime, int32_t deviceId)
@@ -326,6 +344,11 @@
mArgsQueue.push_back(new NotifySensorArgs(*args));
}
+void QueuedInputListener::notifyVibratorState(const NotifyVibratorStateArgs* args) {
+ traceEvent(__func__, args->id);
+ mArgsQueue.push_back(new NotifyVibratorStateArgs(*args));
+}
+
void QueuedInputListener::notifyDeviceReset(const NotifyDeviceResetArgs* args) {
traceEvent(__func__, args->id);
mArgsQueue.push_back(new NotifyDeviceResetArgs(*args));
diff --git a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
index 887bdd4..d6b7259 100644
--- a/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
+++ b/services/inputflinger/benchmarks/InputDispatcher_benchmarks.cpp
@@ -79,6 +79,8 @@
void notifySensorAccuracy(int32_t deviceId, InputDeviceSensorType sensorType,
InputDeviceSensorAccuracy accuracy) override {}
+ void notifyVibratorState(int32_t deviceId, bool isOn) override {}
+
void notifyUntrustedTouch(const std::string& obscuringPackage) override {}
void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index 0495d68..2909939 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -1247,9 +1247,10 @@
nsecs_t currentTime, const std::shared_ptr<PointerCaptureChangedEntry>& entry,
DropReason& dropReason) {
const bool haveWindowWithPointerCapture = mWindowTokenWithPointerCapture != nullptr;
- if (entry->pointerCaptureEnabled == haveWindowWithPointerCapture) {
- LOG_ALWAYS_FATAL_IF(mFocusedWindowRequestedPointerCapture,
- "The Pointer Capture state has already been dispatched to the window.");
+ if (entry->pointerCaptureEnabled && haveWindowWithPointerCapture) {
+ LOG_ALWAYS_FATAL("Pointer Capture has already been enabled for the window.");
+ }
+ if (!entry->pointerCaptureEnabled && !haveWindowWithPointerCapture) {
// Pointer capture was already forcefully disabled because of focus change.
dropReason = DropReason::NOT_DROPPED;
return;
@@ -3747,6 +3748,14 @@
}
}
+void InputDispatcher::notifyVibratorState(const NotifyVibratorStateArgs* args) {
+#if DEBUG_INBOUND_EVENT_DETAILS
+ ALOGD("notifyVibratorState - eventTime=%" PRId64 ", device=%d, isOn=%d", args->eventTime,
+ args->deviceId, args->isOn);
+#endif
+ mPolicy->notifyVibratorState(args->deviceId, args->isOn);
+}
+
bool InputDispatcher::shouldSendMotionToInputFilterLocked(const NotifyMotionArgs* args) {
return mInputFilterEnabled;
}
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 02f5b87..c93d74e 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -96,6 +96,7 @@
virtual void notifyMotion(const NotifyMotionArgs* args) override;
virtual void notifySwitch(const NotifySwitchArgs* args) override;
virtual void notifySensor(const NotifySensorArgs* args) override;
+ virtual void notifyVibratorState(const NotifyVibratorStateArgs* args) override;
virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
virtual void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override;
diff --git a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
index b976129..909ce54 100644
--- a/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
+++ b/services/inputflinger/dispatcher/include/InputDispatcherPolicyInterface.h
@@ -84,6 +84,7 @@
const std::vector<float>& values) = 0;
virtual void notifySensorAccuracy(int32_t deviceId, InputDeviceSensorType sensorType,
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;
diff --git a/services/inputflinger/include/InputListener.h b/services/inputflinger/include/InputListener.h
index 11f726d..094bc0c 100644
--- a/services/inputflinger/include/InputListener.h
+++ b/services/inputflinger/include/InputListener.h
@@ -223,6 +223,24 @@
virtual void notify(const sp<InputListenerInterface>& listener) const;
};
+/* Describes a vibrator state event. */
+struct NotifyVibratorStateArgs : public NotifyArgs {
+ int32_t deviceId;
+ bool isOn;
+
+ inline NotifyVibratorStateArgs() {}
+
+ NotifyVibratorStateArgs(int32_t id, nsecs_t eventTIme, int32_t deviceId, bool isOn);
+
+ NotifyVibratorStateArgs(const NotifyVibratorStateArgs& other);
+
+ bool operator==(const NotifyVibratorStateArgs rhs) const;
+
+ virtual ~NotifyVibratorStateArgs() {}
+
+ virtual void notify(const sp<InputListenerInterface>& listener) const;
+};
+
/*
* The interface used by the InputReader to notify the InputListener about input events.
*/
@@ -237,6 +255,7 @@
virtual void notifyMotion(const NotifyMotionArgs* args) = 0;
virtual void notifySwitch(const NotifySwitchArgs* args) = 0;
virtual void notifySensor(const NotifySensorArgs* args) = 0;
+ virtual void notifyVibratorState(const NotifyVibratorStateArgs* args) = 0;
virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) = 0;
virtual void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) = 0;
};
@@ -259,6 +278,7 @@
virtual void notifySwitch(const NotifySwitchArgs* args) override;
virtual void notifySensor(const NotifySensorArgs* args) override;
virtual void notifyDeviceReset(const NotifyDeviceResetArgs* args) override;
+ void notifyVibratorState(const NotifyVibratorStateArgs* args) override;
void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override;
void flush();
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index ea9b483..69aea84 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -108,6 +108,10 @@
virtual bool isVibrating(int32_t deviceId) = 0;
virtual std::vector<int32_t> getVibratorIds(int32_t deviceId) = 0;
+ /* Get battery level of a particular input device. */
+ virtual std::optional<int32_t> getBatteryCapacity(int32_t deviceId) = 0;
+ /* Get battery status of a particular input device. */
+ virtual std::optional<int32_t> getBatteryStatus(int32_t deviceId) = 0;
/* Return true if the device can send input events to the specified display. */
virtual bool canDispatchToDisplay(int32_t deviceId, int32_t displayId) = 0;
diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp
index abda4ef..7f979f2 100644
--- a/services/inputflinger/reader/Android.bp
+++ b/services/inputflinger/reader/Android.bp
@@ -30,6 +30,7 @@
"mapper/accumulator/CursorScrollAccumulator.cpp",
"mapper/accumulator/SingleTouchMotionAccumulator.cpp",
"mapper/accumulator/TouchButtonAccumulator.cpp",
+ "mapper/BatteryInputMapper.cpp",
"mapper/CursorInputMapper.cpp",
"mapper/ExternalStylusInputMapper.cpp",
"mapper/InputMapper.cpp",
@@ -60,7 +61,11 @@
"libui",
"libutils",
],
+ static_libs: [
+ "libc++fs",
+ ],
header_libs: [
+ "libbatteryservice_headers",
"libinputreader_headers",
],
}
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index b97ff90..8f8c051 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -29,11 +29,14 @@
#include <sys/inotify.h>
#include <sys/ioctl.h>
#include <sys/limits.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
#include <unistd.h>
#define LOG_TAG "EventHub"
// #define LOG_NDEBUG 0
+#include <android-base/file.h>
#include <android-base/stringprintf.h>
#include <cutils/properties.h>
#include <input/KeyCharacterMap.h>
@@ -64,6 +67,23 @@
static constexpr int32_t FF_STRONG_MAGNITUDE_CHANNEL_IDX = 0;
static constexpr int32_t FF_WEAK_MAGNITUDE_CHANNEL_IDX = 1;
+// must be kept in sync with definitions in kernel /drivers/power/supply/power_supply_sysfs.c
+static const std::unordered_map<std::string, int32_t> BATTERY_STATUS =
+ {{"Unknown", BATTERY_STATUS_UNKNOWN},
+ {"Charging", BATTERY_STATUS_CHARGING},
+ {"Discharging", BATTERY_STATUS_DISCHARGING},
+ {"Not charging", BATTERY_STATUS_NOT_CHARGING},
+ {"Full", BATTERY_STATUS_FULL}};
+
+// Mapping taken from
+// https://gitlab.freedesktop.org/upower/upower/-/blob/master/src/linux/up-device-supply.c#L484
+static const std::unordered_map<std::string, int32_t> BATTERY_LEVEL = {{"Critical", 5},
+ {"Low", 10},
+ {"Normal", 55},
+ {"High", 70},
+ {"Full", 100},
+ {"Unknown", 50}};
+
static inline const char* toString(bool value) {
return value ? "true" : "false";
}
@@ -127,6 +147,73 @@
return inputEventTime;
}
+/**
+ * Returns the sysfs root path of the input device
+ *
+ */
+static std::filesystem::path getSysfsRootPath(const char* devicePath) {
+ std::error_code errorCode;
+
+ // Stat the device path to get the major and minor number of the character file
+ struct stat statbuf;
+ if (stat(devicePath, &statbuf) == -1) {
+ ALOGE("Could not stat device %s due to error: %s.", devicePath, std::strerror(errno));
+ return std::filesystem::path();
+ }
+
+ unsigned int major_num = major(statbuf.st_rdev);
+ unsigned int minor_num = minor(statbuf.st_rdev);
+
+ // Realpath "/sys/dev/char/{major}:{minor}" to get the sysfs path to the input event
+ auto sysfsPath = std::filesystem::path("/sys/dev/char/");
+ sysfsPath /= std::to_string(major_num) + ":" + std::to_string(minor_num);
+ sysfsPath = std::filesystem::canonical(sysfsPath, errorCode);
+
+ // Make sure nothing went wrong in call to canonical()
+ if (errorCode) {
+ ALOGW("Could not run filesystem::canonical() due to error %d : %s.", errorCode.value(),
+ errorCode.message().c_str());
+ return std::filesystem::path();
+ }
+
+ // Continue to go up a directory until we reach a directory named "input"
+ while (sysfsPath != "/" && sysfsPath.filename() != "input") {
+ sysfsPath = sysfsPath.parent_path();
+ }
+
+ // Then go up one more and you will be at the sysfs root of the device
+ sysfsPath = sysfsPath.parent_path();
+
+ // Make sure we didn't reach root path and that directory actually exists
+ if (sysfsPath == "/" || !std::filesystem::exists(sysfsPath, errorCode)) {
+ if (errorCode) {
+ ALOGW("Could not run filesystem::exists() due to error %d : %s.", errorCode.value(),
+ errorCode.message().c_str());
+ }
+
+ // Not found
+ return std::filesystem::path();
+ }
+
+ return sysfsPath;
+}
+
+/**
+ * Returns the power supply node in sys fs
+ *
+ */
+static std::filesystem::path findPowerSupplyNode(const std::filesystem::path& sysfsRootPath) {
+ for (auto path = sysfsRootPath; path != "/"; path = path.parent_path()) {
+ std::error_code errorCode;
+ auto iter = std::filesystem::directory_iterator(path / "power_supply", errorCode);
+ if (!errorCode && iter != std::filesystem::directory_iterator()) {
+ return iter->path();
+ }
+ }
+ // Not found
+ return std::filesystem::path();
+}
+
// --- Global Functions ---
Flags<InputDeviceClass> getAbsAxisUsage(int32_t axis, Flags<InputDeviceClass> deviceClasses) {
@@ -976,6 +1063,56 @@
return nullptr;
}
+std::optional<int32_t> EventHub::getBatteryCapacity(int32_t deviceId) const {
+ std::scoped_lock _l(mLock);
+ Device* device = getDeviceLocked(deviceId);
+ std::string buffer;
+
+ if (!device || (device->sysfsBatteryPath.empty())) {
+ return std::nullopt;
+ }
+
+ // Some devices report battery capacity as an integer through the "capacity" file
+ if (base::ReadFileToString(device->sysfsBatteryPath / "capacity", &buffer)) {
+ return std::stoi(buffer);
+ }
+
+ // Other devices report capacity as an enum value POWER_SUPPLY_CAPACITY_LEVEL_XXX
+ // These values are taken from kernel source code include/linux/power_supply.h
+ if (base::ReadFileToString(device->sysfsBatteryPath / "capacity_level", &buffer)) {
+ const auto it = BATTERY_LEVEL.find(buffer);
+ if (it != BATTERY_LEVEL.end()) {
+ return it->second;
+ }
+ }
+ return std::nullopt;
+}
+
+std::optional<int32_t> EventHub::getBatteryStatus(int32_t deviceId) const {
+ std::scoped_lock _l(mLock);
+ Device* device = getDeviceLocked(deviceId);
+ std::string buffer;
+
+ if (!device || (device->sysfsBatteryPath.empty())) {
+ return std::nullopt;
+ }
+
+ if (!base::ReadFileToString(device->sysfsBatteryPath / "status", &buffer)) {
+ ALOGE("Failed to read sysfs battery info: %s", strerror(errno));
+ return std::nullopt;
+ }
+
+ // Remove trailing new line
+ buffer.erase(std::remove(buffer.begin(), buffer.end(), '\n'), buffer.end());
+ const auto it = BATTERY_STATUS.find(buffer);
+
+ if (it != BATTERY_STATUS.end()) {
+ return it->second;
+ }
+
+ return std::nullopt;
+}
+
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
ALOG_ASSERT(bufferSize >= 1);
@@ -1584,6 +1721,18 @@
return -1;
}
+ // Grab the device's sysfs path
+ device->sysfsRootPath = getSysfsRootPath(devicePath.c_str());
+
+ if (!device->sysfsRootPath.empty()) {
+ device->sysfsBatteryPath = findPowerSupplyNode(device->sysfsRootPath);
+
+ // Check if a battery exists
+ if (!device->sysfsBatteryPath.empty()) {
+ device->classes |= InputDeviceClass::BATTERY;
+ }
+ }
+
// Determine whether the device has a mic.
if (device->deviceHasMicLocked()) {
device->classes |= InputDeviceClass::MIC;
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index 3e6910d..8fc6f4a 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -21,6 +21,7 @@
#include <input/Flags.h>
#include <algorithm>
+#include "BatteryInputMapper.h"
#include "CursorInputMapper.h"
#include "ExternalStylusInputMapper.h"
#include "InputReaderContext.h"
@@ -160,6 +161,11 @@
mappers.push_back(std::make_unique<VibratorInputMapper>(*contextPtr));
}
+ // Battery-like devices.
+ if (classes.test(InputDeviceClass::BATTERY)) {
+ mappers.push_back(std::make_unique<BatteryInputMapper>(*contextPtr));
+ }
+
// Keyboard-like devices.
uint32_t keyboardSource = 0;
int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
@@ -490,6 +496,15 @@
for_each_mapper([when](InputMapper& mapper) { mapper.cancelTouch(when); });
}
+std::optional<int32_t> InputDevice::getBatteryCapacity() {
+ return first_in_mappers<int32_t>(
+ [](InputMapper& mapper) { return mapper.getBatteryCapacity(); });
+}
+
+std::optional<int32_t> InputDevice::getBatteryStatus() {
+ return first_in_mappers<int32_t>([](InputMapper& mapper) { return mapper.getBatteryStatus(); });
+}
+
int32_t InputDevice::getMetaState() {
int32_t result = 0;
for_each_mapper([&result](InputMapper& mapper) { result |= mapper.getMetaState(); });
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 7c448e4..c044393 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -673,6 +673,26 @@
}
}
+std::optional<int32_t> InputReader::getBatteryCapacity(int32_t deviceId) {
+ std::scoped_lock _l(mLock);
+
+ InputDevice* device = findInputDeviceLocked(deviceId);
+ if (device) {
+ return device->getBatteryCapacity();
+ }
+ return std::nullopt;
+}
+
+std::optional<int32_t> InputReader::getBatteryStatus(int32_t deviceId) {
+ std::scoped_lock _l(mLock);
+
+ InputDevice* device = findInputDeviceLocked(deviceId);
+ if (device) {
+ return device->getBatteryStatus();
+ }
+ return std::nullopt;
+}
+
bool InputReader::isInputDeviceEnabled(int32_t deviceId) {
std::scoped_lock _l(mLock);
@@ -908,6 +928,11 @@
mReader->mQueuedListener->notifySensor(&args);
}
+void InputReader::ContextImpl::notifyVibratorState(nsecs_t when, int32_t deviceId, bool isOn) {
+ NotifyVibratorStateArgs args(mIdGenerator.nextId(), when, deviceId, isOn);
+ mReader->mQueuedListener->notifyVibratorState(&args);
+}
+
void InputReader::ContextImpl::notifySwitch(nsecs_t eventTime, uint32_t switchValues,
uint32_t switchMask) {
NotifySwitchArgs args(mIdGenerator.nextId(), eventTime, 0 /*policyFlags*/, switchValues,
diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h
index 2cea017..30967df 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/reader/include/EventHub.h
@@ -23,6 +23,9 @@
#include <vector>
#include <input/Flags.h>
+#include <filesystem>
+
+#include <batteryservice/BatteryService.h>
#include <input/Input.h>
#include <input/InputDevice.h>
#include <input/KeyCharacterMap.h>
@@ -121,6 +124,9 @@
/* The input device has a sensor like accelerometer, gyro, etc */
SENSOR = 0x00002000,
+ /* The input device has a battery */
+ BATTERY = 0x00004000,
+
/* The input device is virtual (not a real device, not part of UI configuration). */
VIRTUAL = 0x40000000,
@@ -242,6 +248,12 @@
virtual void cancelVibrate(int32_t deviceId) = 0;
virtual std::vector<int32_t> getVibratorIds(int32_t deviceId) = 0;
+ /* Query battery level. */
+ virtual std::optional<int32_t> getBatteryCapacity(int32_t deviceId) const = 0;
+
+ /* Query battery status. */
+ virtual std::optional<int32_t> getBatteryStatus(int32_t deviceId) const = 0;
+
/* Requests the EventHub to reopen all input devices on the next call to getEvents(). */
virtual void requestReopenDevices() = 0;
@@ -404,6 +416,10 @@
void monitor() override final;
+ std::optional<int32_t> getBatteryCapacity(int32_t deviceId) const override final;
+
+ std::optional<int32_t> getBatteryStatus(int32_t deviceId) const override final;
+
bool isDeviceEnabled(int32_t deviceId) override final;
status_t enableDevice(int32_t deviceId) override final;
@@ -442,6 +458,10 @@
bool ffEffectPlaying;
int16_t ffEffectId; // initially -1
+ // The paths are invalid when .empty() returns true
+ std::filesystem::path sysfsRootPath;
+ std::filesystem::path sysfsBatteryPath;
+
int32_t controllerNumber;
Device(int fd, int32_t id, const std::string& path,
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index 5af76b7..e4186c8 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -92,6 +92,9 @@
void disableSensor(InputDeviceSensorType sensorType);
void flushSensor(InputDeviceSensorType sensorType);
+ std::optional<int32_t> getBatteryCapacity();
+ std::optional<int32_t> getBatteryStatus();
+
int32_t getMetaState();
void updateMetaState(int32_t keyCode);
@@ -287,6 +290,12 @@
inline std::vector<int32_t> getVibratorIds() { return mEventHub->getVibratorIds(mId); }
+ inline std::optional<int32_t> getBatteryCapacity() {
+ return mEventHub->getBatteryCapacity(mId);
+ }
+
+ inline std::optional<int32_t> getBatteryStatus() { return mEventHub->getBatteryStatus(mId); }
+
inline bool hasAbsoluteAxis(int32_t code) const {
RawAbsoluteAxisInfo info;
mEventHub->getAbsoluteAxisInfo(mId, code, &info);
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index 7be932a..5f78149 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -95,6 +95,10 @@
void flushSensor(int32_t deviceId, InputDeviceSensorType sensorType) override;
+ std::optional<int32_t> getBatteryCapacity(int32_t deviceId) override;
+
+ std::optional<int32_t> getBatteryStatus(int32_t deviceId) override;
+
protected:
// These members are protected so they can be instrumented by test cases.
virtual std::shared_ptr<InputDevice> createDeviceLocked(int32_t deviceId,
@@ -148,6 +152,7 @@
void notifySensor(nsecs_t when, int32_t deviceId, InputDeviceSensorType sensorType,
InputDeviceSensorAccuracy accuracy, bool accuracyChanged,
nsecs_t timestamp, std::vector<float> values) override;
+ void notifyVibratorState(nsecs_t when, int32_t deviceId, bool isOn) override;
void notifyDeviceReset(nsecs_t when, int32_t deviceId) override;
void notifyPointerCaptureChanged(nsecs_t when, bool hasCapture) override;
diff --git a/services/inputflinger/reader/include/InputReaderContext.h b/services/inputflinger/reader/include/InputReaderContext.h
index edab312..e6ea523 100644
--- a/services/inputflinger/reader/include/InputReaderContext.h
+++ b/services/inputflinger/reader/include/InputReaderContext.h
@@ -80,6 +80,7 @@
virtual void notifySensor(nsecs_t when, int32_t deviceId, InputDeviceSensorType sensorType,
InputDeviceSensorAccuracy accuracy, bool accuracyChanged,
nsecs_t timestamp, std::vector<float> values) = 0;
+ virtual void notifyVibratorState(nsecs_t when, int32_t deviceId, bool isOn) = 0;
virtual void notifyDeviceReset(nsecs_t when, int32_t deviceId) = 0;
virtual void notifyPointerCaptureChanged(nsecs_t when, bool hasCapture) = 0;
};
diff --git a/services/inputflinger/reader/mapper/BatteryInputMapper.cpp b/services/inputflinger/reader/mapper/BatteryInputMapper.cpp
new file mode 100644
index 0000000..afdc5ab
--- /dev/null
+++ b/services/inputflinger/reader/mapper/BatteryInputMapper.cpp
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+#include "../Macros.h"
+
+#include "BatteryInputMapper.h"
+
+namespace android {
+
+BatteryInputMapper::BatteryInputMapper(InputDeviceContext& deviceContext)
+ : InputMapper(deviceContext) {}
+
+uint32_t BatteryInputMapper::getSources() {
+ return 0;
+}
+
+void BatteryInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
+ InputMapper::populateDeviceInfo(info);
+
+ info->setHasBattery(true);
+}
+
+void BatteryInputMapper::process(const RawEvent* rawEvent) {}
+
+std::optional<int32_t> BatteryInputMapper::getBatteryCapacity() {
+ return getDeviceContext().getBatteryCapacity();
+}
+
+std::optional<int32_t> BatteryInputMapper::getBatteryStatus() {
+ return getDeviceContext().getBatteryStatus();
+}
+
+void BatteryInputMapper::dump(std::string& dump) {
+ dump += INDENT2 "Battery Input Mapper:\n";
+ dump += getBatteryCapacity().has_value()
+ ? StringPrintf(INDENT3 "Capacity: %d\n", getBatteryCapacity().value())
+ : StringPrintf(INDENT3 "Capacity: Unknown");
+
+ std::string status;
+ switch (getBatteryStatus().value_or(BATTERY_STATUS_UNKNOWN)) {
+ case BATTERY_STATUS_CHARGING:
+ status = "Charging";
+ break;
+ case BATTERY_STATUS_DISCHARGING:
+ status = "Discharging";
+ break;
+ case BATTERY_STATUS_NOT_CHARGING:
+ status = "Not charging";
+ break;
+ case BATTERY_STATUS_FULL:
+ status = "Full";
+ break;
+ default:
+ status = "Unknown";
+ }
+ dump += StringPrintf(INDENT3 "Status: %s\n", status.c_str());
+}
+
+} // namespace android
diff --git a/services/inputflinger/reader/mapper/BatteryInputMapper.h b/services/inputflinger/reader/mapper/BatteryInputMapper.h
new file mode 100644
index 0000000..4fe373e
--- /dev/null
+++ b/services/inputflinger/reader/mapper/BatteryInputMapper.h
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#ifndef _UI_INPUTREADER_BATTERY_INPUT_MAPPER_H
+#define _UI_INPUTREADER_BATTERY_INPUT_MAPPER_H
+
+#include "InputMapper.h"
+
+namespace android {
+
+class BatteryInputMapper : public InputMapper {
+public:
+ explicit BatteryInputMapper(InputDeviceContext& deviceContext);
+ virtual ~BatteryInputMapper(){};
+
+ uint32_t getSources() override;
+ void populateDeviceInfo(InputDeviceInfo* deviceInfo) override;
+ void process(const RawEvent* rawEvent) override;
+
+ std::optional<int32_t> getBatteryCapacity() override;
+ std::optional<int32_t> getBatteryStatus() override;
+
+ void dump(std::string& dump) override;
+};
+
+} // namespace android
+
+#endif // _UI_INPUTREADER_BATTERY_INPUT_MAPPER_H
diff --git a/services/inputflinger/reader/mapper/InputMapper.h b/services/inputflinger/reader/mapper/InputMapper.h
index 6ca6ec9..44af998 100644
--- a/services/inputflinger/reader/mapper/InputMapper.h
+++ b/services/inputflinger/reader/mapper/InputMapper.h
@@ -72,6 +72,9 @@
virtual void disableSensor(InputDeviceSensorType sensorType);
virtual void flushSensor(InputDeviceSensorType sensorType);
+ virtual std::optional<int32_t> getBatteryCapacity() { return std::nullopt; }
+ virtual std::optional<int32_t> getBatteryStatus() { return std::nullopt; }
+
virtual int32_t getMetaState();
virtual void updateMetaState(int32_t keyCode);
diff --git a/services/inputflinger/reader/mapper/VibratorInputMapper.cpp b/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
index f25e59a..2e4ab45 100644
--- a/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/VibratorInputMapper.cpp
@@ -52,6 +52,8 @@
mToken = token;
mIndex = -1;
+ // Request InputReader to notify InputManagerService for vibration started.
+ getContext()->notifyVibratorState(systemTime(), getDeviceId(), true);
nextStep();
}
@@ -84,6 +86,9 @@
}
void VibratorInputMapper::nextStep() {
+#if DEBUG_VIBRATOR
+ ALOGD("nextStep: index=%d, vibrate deviceId=%d", (int)mIndex, getDeviceId());
+#endif
mIndex += 1;
if (size_t(mIndex) >= mSequence.pattern.size()) {
if (mRepeat < 0) {
@@ -124,6 +129,9 @@
ALOGD("stopVibrating: sending cancel vibrate deviceId=%d", getDeviceId());
#endif
getDeviceContext().cancelVibrate();
+
+ // Request InputReader to notify InputManagerService for vibration complete.
+ getContext()->notifyVibratorState(systemTime(), getDeviceId(), false);
}
void VibratorInputMapper::dump(std::string& dump) {
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index c7e05eb..01945db 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -331,6 +331,8 @@
void notifySensorAccuracy(int deviceId, InputDeviceSensorType sensorType,
InputDeviceSensorAccuracy accuracy) override {}
+ void notifyVibratorState(int32_t deviceId, bool isOn) override {}
+
void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig) override {
*outConfig = mConfig;
}
@@ -4215,4 +4217,27 @@
mWindow->assertNoEvents();
}
+TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
+ requestAndVerifyPointerCapture(mWindow, true);
+
+ // The first window loses focus.
+ setFocusedWindow(mSecondWindow);
+ mFakePolicy->waitForSetPointerCapture(false);
+ mWindow->consumeCaptureEvent(false);
+
+ // Request Pointer Capture from the second window before the notification from InputReader
+ // arrives.
+ mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
+ mFakePolicy->waitForSetPointerCapture(true);
+
+ // InputReader notifies Pointer Capture was disabled (because of the focus change).
+ notifyPointerCaptureChanged(false);
+
+ // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
+ notifyPointerCaptureChanged(true);
+
+ mSecondWindow->consumeFocusEvent(true);
+ mSecondWindow->consumeCaptureEvent(true);
+}
+
} // namespace android::inputdispatcher
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 36da8dd..409c62a 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <BatteryInputMapper.h>
#include <CursorInputMapper.h>
#include <InputDevice.h>
#include <InputMapper.h>
@@ -67,6 +68,8 @@
static constexpr int32_t FIRST_TRACKING_ID = 0;
static constexpr int32_t SECOND_TRACKING_ID = 1;
static constexpr int32_t THIRD_TRACKING_ID = 2;
+static constexpr int32_t BATTERY_STATUS = 4;
+static constexpr int32_t BATTERY_CAPACITY = 66;
// Error tolerance for floating point assertions.
static const float EPSILON = 0.001f;
@@ -406,7 +409,7 @@
KeyedVector<int32_t, Device*> mDevices;
std::vector<std::string> mExcludedDevices;
- List<RawEvent> mEvents GUARDED_BY(mLock);
+ std::vector<RawEvent> mEvents GUARDED_BY(mLock);
std::unordered_map<int32_t /*deviceId*/, std::vector<TouchVideoFrame>> mVideoFrames;
std::vector<int32_t> mVibrators = {0, 1};
@@ -719,16 +722,15 @@
mExcludedDevices = devices;
}
- size_t getEvents(int, RawEvent* buffer, size_t) override {
- std::scoped_lock<std::mutex> lock(mLock);
- if (mEvents.empty()) {
- return 0;
- }
+ size_t getEvents(int, RawEvent* buffer, size_t bufferSize) override {
+ std::scoped_lock lock(mLock);
- *buffer = *mEvents.begin();
- mEvents.erase(mEvents.begin());
+ const size_t filledSize = std::min(mEvents.size(), bufferSize);
+ std::copy(mEvents.begin(), mEvents.begin() + filledSize, buffer);
+
+ mEvents.erase(mEvents.begin(), mEvents.begin() + filledSize);
mEventsCondition.notify_all();
- return 1;
+ return filledSize;
}
std::vector<TouchVideoFrame> getVideoFrames(int32_t deviceId) override {
@@ -863,6 +865,10 @@
std::vector<int32_t> getVibratorIds(int32_t deviceId) override { return mVibrators; };
+ std::optional<int32_t> getBatteryCapacity(int32_t) const override { return BATTERY_CAPACITY; }
+
+ std::optional<int32_t> getBatteryStatus(int32_t) const override { return BATTERY_STATUS; }
+
virtual bool isExternal(int32_t) const {
return false;
}
@@ -1924,6 +1930,52 @@
ASSERT_EQ(mReader->getVibratorIds(deviceId).size(), 2U);
}
+class FakeBatteryInputMapper : public FakeInputMapper {
+public:
+ FakeBatteryInputMapper(InputDeviceContext& deviceContext, uint32_t sources)
+ : FakeInputMapper(deviceContext, sources) {}
+
+ std::optional<int32_t> getBatteryCapacity() override {
+ return getDeviceContext().getBatteryCapacity();
+ }
+
+ std::optional<int32_t> getBatteryStatus() override {
+ return getDeviceContext().getBatteryStatus();
+ }
+};
+
+TEST_F(InputReaderTest, BatteryGetCapacity) {
+ constexpr int32_t deviceId = END_RESERVED_ID + 1000;
+ Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
+ constexpr int32_t eventHubId = 1;
+ const char* DEVICE_LOCATION = "BLUETOOTH";
+ std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
+ FakeBatteryInputMapper& mapper =
+ device->addMapper<FakeBatteryInputMapper>(eventHubId, AINPUT_SOURCE_KEYBOARD);
+ mReader->pushNextDevice(device);
+
+ ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
+ ASSERT_NO_FATAL_FAILURE(mapper.assertConfigureWasCalled());
+
+ ASSERT_EQ(mReader->getBatteryCapacity(deviceId), BATTERY_CAPACITY);
+}
+
+TEST_F(InputReaderTest, BatteryGetStatus) {
+ constexpr int32_t deviceId = END_RESERVED_ID + 1000;
+ Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
+ constexpr int32_t eventHubId = 1;
+ const char* DEVICE_LOCATION = "BLUETOOTH";
+ std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
+ FakeBatteryInputMapper& mapper =
+ device->addMapper<FakeBatteryInputMapper>(eventHubId, AINPUT_SOURCE_KEYBOARD);
+ mReader->pushNextDevice(device);
+
+ ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
+ ASSERT_NO_FATAL_FAILURE(mapper.assertConfigureWasCalled());
+
+ ASSERT_EQ(mReader->getBatteryStatus(deviceId), BATTERY_STATUS);
+}
+
// --- InputReaderIntegrationTest ---
// These tests create and interact with the InputReader only through its interface.
@@ -2625,6 +2677,7 @@
TEST_F(VibratorInputMapperTest, Vibrate) {
constexpr uint8_t DEFAULT_AMPLITUDE = 192;
+ constexpr int32_t VIBRATION_TOKEN = 100;
VibratorInputMapper& mapper = addMapperAndConfigure<VibratorInputMapper>();
VibrationElement pattern(2);
@@ -2642,8 +2695,23 @@
std::vector<uint8_t> amplitudes = {DEFAULT_AMPLITUDE, DEFAULT_AMPLITUDE / 2};
ASSERT_FALSE(mapper.isVibrating());
- mapper.vibrate(sequence, -1 /* repeat */, 0 /* token */);
+ // Start vibrating
+ mapper.vibrate(sequence, -1 /* repeat */, VIBRATION_TOKEN);
ASSERT_TRUE(mapper.isVibrating());
+ // Verify vibrator state listener was notified.
+ mReader->loopOnce();
+ NotifyVibratorStateArgs args;
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyVibratorStateWasCalled(&args));
+ ASSERT_EQ(DEVICE_ID, args.deviceId);
+ ASSERT_TRUE(args.isOn);
+ // Stop vibrating
+ mapper.cancelVibrate(VIBRATION_TOKEN);
+ ASSERT_FALSE(mapper.isVibrating());
+ // Verify vibrator state listener was notified.
+ mReader->loopOnce();
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyVibratorStateWasCalled(&args));
+ ASSERT_EQ(DEVICE_ID, args.deviceId);
+ ASSERT_FALSE(args.isOn);
}
// --- SensorInputMapperTest ---
@@ -2799,6 +2867,32 @@
mapper.flushSensor(InputDeviceSensorType::GYROSCOPE);
}
+// --- BatteryInputMapperTest ---
+class BatteryInputMapperTest : public InputMapperTest {
+protected:
+ void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::BATTERY); }
+};
+
+TEST_F(BatteryInputMapperTest, GetSources) {
+ BatteryInputMapper& mapper = addMapperAndConfigure<BatteryInputMapper>();
+
+ ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, mapper.getSources());
+}
+
+TEST_F(BatteryInputMapperTest, GetBatteryCapacity) {
+ BatteryInputMapper& mapper = addMapperAndConfigure<BatteryInputMapper>();
+
+ ASSERT_TRUE(mapper.getBatteryCapacity());
+ ASSERT_EQ(*mapper.getBatteryCapacity(), BATTERY_CAPACITY);
+}
+
+TEST_F(BatteryInputMapperTest, GetBatteryStatus) {
+ BatteryInputMapper& mapper = addMapperAndConfigure<BatteryInputMapper>();
+
+ ASSERT_TRUE(mapper.getBatteryStatus());
+ ASSERT_EQ(*mapper.getBatteryStatus(), BATTERY_STATUS);
+}
+
// --- KeyboardInputMapperTest ---
class KeyboardInputMapperTest : public InputMapperTest {
diff --git a/services/inputflinger/tests/TestInputListener.cpp b/services/inputflinger/tests/TestInputListener.cpp
index 295c6e3..fb7de97 100644
--- a/services/inputflinger/tests/TestInputListener.cpp
+++ b/services/inputflinger/tests/TestInputListener.cpp
@@ -86,6 +86,12 @@
"Expected notifySensor() to have been called."));
}
+void TestInputListener::assertNotifyVibratorStateWasCalled(NotifyVibratorStateArgs* outEventArgs) {
+ ASSERT_NO_FATAL_FAILURE(assertCalled<NotifyVibratorStateArgs>(outEventArgs,
+ "Expected notifyVibratorState() "
+ "to have been called."));
+}
+
void TestInputListener::assertNotifyCaptureWasCalled(
NotifyPointerCaptureChangedArgs* outEventArgs) {
ASSERT_NO_FATAL_FAILURE(
@@ -165,4 +171,8 @@
notify<NotifySensorArgs>(args);
}
+void TestInputListener::notifyVibratorState(const NotifyVibratorStateArgs* args) {
+ notify<NotifyVibratorStateArgs>(args);
+}
+
} // namespace android
diff --git a/services/inputflinger/tests/TestInputListener.h b/services/inputflinger/tests/TestInputListener.h
index e54350a..0ffcaaa 100644
--- a/services/inputflinger/tests/TestInputListener.h
+++ b/services/inputflinger/tests/TestInputListener.h
@@ -56,6 +56,7 @@
void assertNotifyCaptureWasCalled(NotifyPointerCaptureChangedArgs* outEventArgs = nullptr);
void assertNotifySensorWasCalled(NotifySensorArgs* outEventArgs = nullptr);
+ void assertNotifyVibratorStateWasCalled(NotifyVibratorStateArgs* outEventArgs = nullptr);
private:
template <class NotifyArgsType>
@@ -79,6 +80,8 @@
virtual void notifySensor(const NotifySensorArgs* args) override;
+ virtual void notifyVibratorState(const NotifyVibratorStateArgs* args) override;
+
virtual void notifyPointerCaptureChanged(const NotifyPointerCaptureChangedArgs* args) override;
std::mutex mLock;
@@ -92,6 +95,7 @@
std::vector<NotifyMotionArgs>, //
std::vector<NotifySwitchArgs>, //
std::vector<NotifySensorArgs>, //
+ std::vector<NotifyVibratorStateArgs>, //
std::vector<NotifyPointerCaptureChangedArgs>> //
mQueues GUARDED_BY(mLock);
};
diff --git a/services/powermanager/Android.bp b/services/powermanager/Android.bp
index b5e6ae9..68f4f28 100644
--- a/services/powermanager/Android.bp
+++ b/services/powermanager/Android.bp
@@ -29,7 +29,7 @@
"libutils",
"android.hardware.power@1.0",
"android.hardware.power@1.1",
- "android.hardware.power-cpp",
+ "android.hardware.power-V1-cpp",
],
cflags: [
diff --git a/services/powermanager/benchmarks/Android.bp b/services/powermanager/benchmarks/Android.bp
index 4c5d508..ad93a65 100644
--- a/services/powermanager/benchmarks/Android.bp
+++ b/services/powermanager/benchmarks/Android.bp
@@ -29,7 +29,7 @@
"libutils",
"android.hardware.power@1.0",
"android.hardware.power@1.1",
- "android.hardware.power-cpp",
+ "android.hardware.power-V1-cpp",
],
static_libs: [
"libtestUtil",
diff --git a/services/powermanager/tests/Android.bp b/services/powermanager/tests/Android.bp
index 49abc11..0f5037e 100644
--- a/services/powermanager/tests/Android.bp
+++ b/services/powermanager/tests/Android.bp
@@ -37,7 +37,7 @@
"libutils",
"android.hardware.power@1.0",
"android.hardware.power@1.1",
- "android.hardware.power-cpp",
+ "android.hardware.power-V1-cpp",
],
static_libs: [
"libgmock",
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index a7cd258..8d1258a 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -36,7 +36,7 @@
"android.hardware.graphics.composer@2.4",
"android.hardware.power@1.0",
"android.hardware.power@1.3",
- "android.hardware.power-cpp",
+ "android.hardware.power-V1-cpp",
"libbase",
"libbinder",
"libcutils",
@@ -173,7 +173,7 @@
"SurfaceFlingerDefaultFactory.cpp",
"SurfaceInterceptor.cpp",
"SurfaceTracing.cpp",
- "TransactionCompletedThread.cpp",
+ "TransactionCallbackInvoker.cpp",
],
}
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 39ae2fd..ec81ff7 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -377,7 +377,7 @@
displayId && mFlinger->getHwComposer().isConnected(*displayId)) {
// The HWC doesn't support present fences, so use the refresh
// timestamp instead.
- const nsecs_t actualPresentTime = mFlinger->getHwComposer().getRefreshTimestamp(*displayId);
+ const nsecs_t actualPresentTime = display->getRefreshTimestamp();
mFlinger->mTimeStats->setPresentTime(layerId, mCurrentFrameNumber, actualPresentTime);
mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(), mCurrentFrameNumber,
actualPresentTime,
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 32e6b10..3615a02 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -282,8 +282,7 @@
mConsumer->mergeSurfaceDamage(mQueueItems[0].item.mSurfaceDamage);
mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].item.mFrameNumber);
if (mQueueItems[0].surfaceFrame) {
- mQueueItems[0].surfaceFrame->setPresentState(PresentState::Dropped);
- mFlinger->mFrameTimeline->addSurfaceFrame(mQueueItems[0].surfaceFrame);
+ addSurfaceFrameDroppedForBuffer(mQueueItems[0].surfaceFrame);
}
mQueueItems.erase(mQueueItems.begin());
mQueuedFrames--;
@@ -298,8 +297,7 @@
Mutex::Autolock lock(mQueueItemLock);
for (auto& [item, surfaceFrame] : mQueueItems) {
if (surfaceFrame) {
- surfaceFrame->setPresentState(PresentState::Dropped);
- mFlinger->mFrameTimeline->addSurfaceFrame(surfaceFrame);
+ addSurfaceFrameDroppedForBuffer(surfaceFrame);
}
}
mQueueItems.clear();
@@ -329,8 +327,7 @@
mConsumer->mergeSurfaceDamage(mQueueItems[0].item.mSurfaceDamage);
mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].item.mFrameNumber);
if (mQueueItems[0].surfaceFrame) {
- mQueueItems[0].surfaceFrame->setPresentState(PresentState::Dropped);
- mFlinger->mFrameTimeline->addSurfaceFrame(mQueueItems[0].surfaceFrame);
+ addSurfaceFrameDroppedForBuffer(mQueueItems[0].surfaceFrame);
}
mQueueItems.erase(mQueueItems.begin());
mQueuedFrames--;
@@ -342,11 +339,9 @@
FrameTracer::FrameEvent::LATCH);
if (mQueueItems[0].surfaceFrame) {
- mQueueItems[0].surfaceFrame->setAcquireFenceTime(
- mQueueItems[0].item.mFenceTime->getSignalTime());
- mQueueItems[0].surfaceFrame->setPresentState(PresentState::Presented, mLastLatchTime);
- mFlinger->mFrameTimeline->addSurfaceFrame(mQueueItems[0].surfaceFrame);
- mLastLatchTime = latchTime;
+ addSurfaceFramePresentedForBuffer(mQueueItems[0].surfaceFrame,
+ mQueueItems[0].item.mFenceTime->getSignalTime(),
+ latchTime);
}
mQueueItems.erase(mQueueItems.begin());
}
@@ -384,8 +379,8 @@
return NO_ERROR;
}
-void BufferQueueLayer::setFrameTimelineVsyncForBuffer(int64_t frameTimelineVsyncId) {
- mFrameTimelineVsyncId = frameTimelineVsyncId;
+void BufferQueueLayer::setFrameTimelineInfoForBuffer(const FrameTimelineInfo& frameTimelineInfo) {
+ mFrameTimelineInfo = frameTimelineInfo;
}
// -----------------------------------------------------------------------
@@ -444,11 +439,7 @@
}
}
- auto surfaceFrame =
- mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineVsyncId,
- mOwnerPid, mOwnerUid, mName,
- mName);
- surfaceFrame->setActualQueueTime(systemTime());
+ auto surfaceFrame = createSurfaceFrameForBuffer(mFrameTimelineInfo, systemTime(), mName);
mQueueItems.push_back({item, surfaceFrame});
mQueuedFrames++;
@@ -484,11 +475,7 @@
return;
}
- auto surfaceFrame =
- mFlinger->mFrameTimeline->createSurfaceFrameForToken(mFrameTimelineVsyncId,
- mOwnerPid, mOwnerUid, mName,
- mName);
- surfaceFrame->setActualQueueTime(systemTime());
+ auto surfaceFrame = createSurfaceFrameForBuffer(mFrameTimelineInfo, systemTime(), mName);
mQueueItems[mQueueItems.size() - 1].item = item;
mQueueItems[mQueueItems.size() - 1].surfaceFrame = std::move(surfaceFrame);
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index 0e8fdbe..0ea02e1 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -101,7 +101,7 @@
status_t updateActiveBuffer() override;
status_t updateFrameNumber(nsecs_t latchTime) override;
- void setFrameTimelineVsyncForBuffer(int64_t frameTimelineVsyncId) override;
+ void setFrameTimelineInfoForBuffer(const FrameTimelineInfo& frameTimelineInfo) override;
sp<Layer> createClone() override;
@@ -145,15 +145,10 @@
sp<ContentsChangedListener> mContentsChangedListener;
- // The last vsync id received on this layer. This will be used when we get
+ // 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.
- std::optional<int64_t> mFrameTimelineVsyncId;
-
- // Keeps track of the time SF latched the last buffer from this layer.
- // Used in buffer stuffing analysis in FrameTimeline.
- // TODO(b/176106798): Find a way to do this for BLASTBufferQueue as well.
- nsecs_t mLastLatchTime = 0;
+ FrameTimelineInfo mFrameTimelineInfo;
};
} // namespace android
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 0cc15c2..cf87f62 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -28,6 +28,7 @@
#include <limits>
+#include <FrameTimeline/FrameTimeline.h>
#include <compositionengine/LayerFECompositionState.h>
#include <gui/BufferQueue.h>
#include <private/gui/SyncFeatures.h>
@@ -38,6 +39,7 @@
namespace android {
+using PresentState = frametimeline::SurfaceFrame::PresentState;
// clang-format off
const std::array<float, 16> BufferStateLayer::IDENTITY_MATRIX{
1, 0, 0, 0,
@@ -188,7 +190,7 @@
JankData(surfaceFrame->getToken(), surfaceFrame->getJankType().value()));
}
- mFlinger->getTransactionCompletedThread().finalizePendingCallbackHandles(
+ mFlinger->getTransactionCallbackInvoker().finalizePendingCallbackHandles(
mDrawingState.callbackHandles, jankData);
mDrawingState.callbackHandles = {};
@@ -216,8 +218,7 @@
// Returns true if the most recent Transaction applied to CurrentState will be presented.
return (getSidebandStreamChanged() || getAutoRefresh() ||
(mCurrentState.modified &&
- (mCurrentState.buffer != nullptr || mCurrentState.bgColorLayer != nullptr))) &&
- !mLayerDetached;
+ (mCurrentState.buffer != nullptr || mCurrentState.bgColorLayer != nullptr)));
}
/* TODO: vhau uncomment once deferred transaction migration complete in
@@ -336,7 +337,8 @@
bool BufferStateLayer::setBuffer(const sp<GraphicBuffer>& buffer, const sp<Fence>& acquireFence,
nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp,
const client_cache_t& clientCacheId, uint64_t frameNumber,
- std::optional<nsecs_t> /* dequeueTime */) {
+ std::optional<nsecs_t> /* dequeueTime */,
+ const FrameTimelineInfo& info) {
ATRACE_CALL();
if (mCurrentState.buffer) {
@@ -346,6 +348,10 @@
// before swapping to drawing state, then the first buffer will be
// dropped and we should decrement the pending buffer count.
decrementPendingBufferCount();
+ if (mCurrentState.bufferSurfaceFrameTX != nullptr) {
+ addSurfaceFrameDroppedForBuffer(mCurrentState.bufferSurfaceFrameTX);
+ mCurrentState.bufferSurfaceFrameTX.reset();
+ }
}
}
@@ -366,6 +372,11 @@
LayerHistory::LayerUpdateType::Buffer);
addFrameEvent(acquireFence, postTime, isAutoTimestamp ? 0 : desiredPresentTime);
+
+ if (info.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) {
+ setFrameTimelineVsyncForBufferTransaction(info, postTime);
+ }
+
return true;
}
@@ -444,14 +455,14 @@
// Notify the transaction completed thread that there is a pending latched callback
// handle
- mFlinger->getTransactionCompletedThread().registerPendingCallbackHandle(handle);
+ mFlinger->getTransactionCallbackInvoker().registerPendingCallbackHandle(handle);
// Store so latched time and release fence can be set
mCurrentState.callbackHandles.push_back(handle);
} else { // If this layer will NOT need to be relatched and presented this frame
// Notify the transaction completed thread this handle is done
- mFlinger->getTransactionCompletedThread().registerUnpresentedCallbackHandle(handle);
+ mFlinger->getTransactionCallbackInvoker().registerUnpresentedCallbackHandle(handle);
}
}
@@ -461,11 +472,6 @@
return willPresent;
}
-void BufferStateLayer::forceSendCallbacks() {
- mFlinger->getTransactionCompletedThread().finalizePendingCallbackHandles(
- mCurrentState.callbackHandles, std::vector<JankData>());
-}
-
bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) {
mCurrentState.transparentRegionHint = transparent;
mCurrentState.modified = true;
@@ -626,6 +632,17 @@
std::make_shared<FenceTime>(mDrawingState.acquireFence));
mFlinger->mTimeStats->setLatchTime(layerId, mDrawingState.frameNumber, latchTime);
+ auto& bufferSurfaceFrame = mDrawingState.bufferSurfaceFrameTX;
+ if (bufferSurfaceFrame != nullptr &&
+ bufferSurfaceFrame->getPresentState() != PresentState::Presented) {
+ // Update only if the bufferSurfaceFrame wasn't already presented. A Presented
+ // bufferSurfaceFrame could be seen here if a pending state was applied successfully and we
+ // are processing the next state.
+ addSurfaceFramePresentedForBuffer(bufferSurfaceFrame,
+ mDrawingState.acquireFence->getSignalTime(), latchTime);
+ bufferSurfaceFrame.reset();
+ }
+
mCurrentStateModified = false;
return NO_ERROR;
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index f638caa..ea832a2 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -72,7 +72,7 @@
bool setBuffer(const sp<GraphicBuffer>& buffer, const sp<Fence>& acquireFence, nsecs_t postTime,
nsecs_t desiredPresentTime, bool isAutoTimestamp,
const client_cache_t& clientCacheId, uint64_t frameNumber,
- std::optional<nsecs_t> dequeueTime) override;
+ std::optional<nsecs_t> dequeueTime, const FrameTimelineInfo& info) override;
bool setAcquireFence(const sp<Fence>& fence) override;
bool setDataspace(ui::Dataspace dataspace) override;
bool setHdrMetadata(const HdrMetadata& hdrMetadata) override;
@@ -80,7 +80,6 @@
bool setApi(int32_t api) override;
bool setSidebandStream(const sp<NativeHandle>& sidebandStream) override;
bool setTransactionCompletedListeners(const std::vector<sp<CallbackHandle>>& handles) override;
- void forceSendCallbacks() override;
bool addFrameEvent(const sp<Fence>& acquireFence, nsecs_t postedTime,
nsecs_t requestedPresentTime) override;
@@ -125,6 +124,8 @@
private:
friend class SlotGenerationTest;
+ friend class TransactionSurfaceFrameTest;
+
inline void tracePendingBufferCount();
bool updateFrameEventHistory(const sp<Fence>& acquireFence, nsecs_t postedTime,
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h
index 6559ed8..4502eee 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h
@@ -16,6 +16,7 @@
#pragma once
+#include <ui/Size.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/StrongPointer.h>
@@ -71,7 +72,7 @@
virtual void dumpAsString(String8& result) const = 0;
- virtual void resizeBuffers(const uint32_t w, const uint32_t h) = 0;
+ virtual void resizeBuffers(const ui::Size&) = 0;
virtual const sp<Fence>& getClientTargetAcquireFence() const = 0;
};
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplaySurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplaySurface.h
index 31b5f95..168e433 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplaySurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplaySurface.h
@@ -18,6 +18,7 @@
#include <compositionengine/DisplaySurface.h>
#include <gmock/gmock.h>
+#include <ui/Size.h>
#include <utils/String8.h>
namespace android::compositionengine::mock {
@@ -32,7 +33,7 @@
MOCK_METHOD0(advanceFrame, status_t());
MOCK_METHOD0(onFrameCommitted, void());
MOCK_CONST_METHOD1(dumpAsString, void(String8& result));
- MOCK_METHOD2(resizeBuffers, void(uint32_t, uint32_t));
+ MOCK_METHOD1(resizeBuffers, void(const ui::Size&));
MOCK_CONST_METHOD0(getClientTargetAcquireFence, const sp<Fence>&());
};
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 4f99495..3907ac5 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -989,9 +989,16 @@
});
const nsecs_t renderEngineStart = systemTime();
+ // Only use the framebuffer cache when rendering to an internal display
+ // TODO(b/173560331): This is only to help mitigate memory leaks from virtual displays because
+ // right now we don't have a concrete eviction policy for output buffers: GLESRenderEngine
+ // bounds its framebuffer cache but Skia RenderEngine has no current policy. The best fix is
+ // probably to encapsulate the output buffer into a structure that dispatches resource cleanup
+ // over to RenderEngine, in which case this flag can be removed from the drawLayers interface.
+ const bool useFramebufferCache = outputState.layerStackInternal;
status_t status =
renderEngine.drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, buf,
- /*useFramebufferCache=*/true, std::move(fd), &readyFence);
+ useFramebufferCache, std::move(fd), &readyFence);
if (status != NO_ERROR && mClientCompositionRequestCache) {
// If rendering was not successful, remove the request from the cache.
diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
index b47f7fd..3bef77d 100644
--- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
@@ -96,8 +96,7 @@
}
void RenderSurface::setDisplaySize(const ui::Size& size) {
- mDisplaySurface->resizeBuffers(static_cast<uint32_t>(size.width),
- static_cast<uint32_t>(size.height));
+ mDisplaySurface->resizeBuffers(size);
mSize = size;
}
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
index 3133e90..ab00385 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -85,16 +85,15 @@
MOCK_CONST_METHOD0(updatesDeviceProductInfoOnHotplugReconnect, bool());
MOCK_METHOD2(onVsync, bool(hal::HWDisplayId, int64_t));
MOCK_METHOD2(setVsyncEnabled, void(PhysicalDisplayId, hal::Vsync));
- MOCK_CONST_METHOD1(getRefreshTimestamp, nsecs_t(PhysicalDisplayId));
MOCK_CONST_METHOD1(isConnected, bool(PhysicalDisplayId));
- MOCK_CONST_METHOD1(getModes, DisplayModes(PhysicalDisplayId));
- MOCK_CONST_METHOD1(getActiveMode, DisplayModePtr(PhysicalDisplayId));
+ MOCK_CONST_METHOD1(getModes, std::vector<HWComposer::HWCDisplayMode>(PhysicalDisplayId));
+ MOCK_CONST_METHOD1(getActiveMode, std::optional<hal::HWConfigId>(PhysicalDisplayId));
MOCK_CONST_METHOD1(getColorModes, std::vector<ui::ColorMode>(PhysicalDisplayId));
MOCK_METHOD3(setActiveColorMode, status_t(PhysicalDisplayId, ui::ColorMode, ui::RenderIntent));
MOCK_CONST_METHOD0(isUsingVrComposer, bool());
MOCK_CONST_METHOD1(getDisplayConnectionType, DisplayConnectionType(PhysicalDisplayId));
MOCK_CONST_METHOD1(isVsyncPeriodSwitchSupported, bool(PhysicalDisplayId));
- MOCK_CONST_METHOD1(getDisplayVsyncPeriod, nsecs_t(PhysicalDisplayId));
+ MOCK_CONST_METHOD2(getDisplayVsyncPeriod, status_t(PhysicalDisplayId, nsecs_t*));
MOCK_METHOD4(setActiveModeWithConstraints,
status_t(PhysicalDisplayId, hal::HWConfigId,
const hal::VsyncPeriodChangeConstraints&,
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 376bac8..c4ae3a7 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -3003,7 +3003,7 @@
.WillRepeatedly(Return());
EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
- EXPECT_CALL(mRenderEngine, drawLayers(_, IsEmpty(), _, true, _, _))
+ EXPECT_CALL(mRenderEngine, drawLayers(_, IsEmpty(), _, false, _, _))
.WillRepeatedly(Return(NO_ERROR));
verify().execute().expectAFenceWasReturned();
@@ -3030,6 +3030,36 @@
}));
EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
+ EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _, _))
+ .WillRepeatedly(Return(NO_ERROR));
+
+ verify().execute().expectAFenceWasReturned();
+}
+
+TEST_F(OutputComposeSurfacesTest,
+ buildsAndRendersRequestListAndCachesFramebufferForInternalLayers) {
+ LayerFE::LayerSettings r1;
+ LayerFE::LayerSettings r2;
+
+ r1.geometry.boundaries = FloatRect{1, 2, 3, 4};
+ r2.geometry.boundaries = FloatRect{5, 6, 7, 8};
+ const constexpr uint32_t kInternalLayerStack = 1234;
+ mOutput.setLayerStackFilter(kInternalLayerStack, true);
+
+ EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
+ EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
+ EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+ EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
+ EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
+ .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{r1}));
+ EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
+ .WillRepeatedly(
+ Invoke([&](const Region&,
+ std::vector<LayerFE::LayerSettings>& clientCompositionLayers) {
+ clientCompositionLayers.emplace_back(r2);
+ }));
+
+ EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, true, _, _))
.WillRepeatedly(Return(NO_ERROR));
@@ -3054,7 +3084,7 @@
.WillRepeatedly(Return());
EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
- EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, true, _, _))
+ EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _, _))
.Times(2)
.WillOnce(Return(NO_ERROR));
@@ -3083,7 +3113,7 @@
.WillRepeatedly(Return());
EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
- EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, true, _, _))
+ EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _, _))
.WillOnce(Return(NO_ERROR));
EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false));
@@ -3115,7 +3145,7 @@
EXPECT_CALL(*mRenderSurface, dequeueBuffer(_))
.WillOnce(Return(mOutputBuffer))
.WillOnce(Return(otherOutputBuffer));
- EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, true, _, _))
+ EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _, _))
.WillRepeatedly(Return(NO_ERROR));
verify().execute().expectAFenceWasReturned();
@@ -3145,9 +3175,9 @@
.WillRepeatedly(Return());
EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
- EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, true, _, _))
+ EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r2)), _, false, _, _))
.WillOnce(Return(NO_ERROR));
- EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r3)), _, true, _, _))
+ EXPECT_CALL(mRenderEngine, drawLayers(_, ElementsAre(Pointee(r1), Pointee(r3)), _, false, _, _))
.WillOnce(Return(NO_ERROR));
verify().execute().expectAFenceWasReturned();
@@ -3197,7 +3227,7 @@
struct ExpectDisplaySettingsState
: public CallOrderStateMachineHelper<TestType, ExpectDisplaySettingsState> {
auto thenExpectDisplaySettingsUsed(renderengine::DisplaySettings settings) {
- EXPECT_CALL(getInstance()->mRenderEngine, drawLayers(settings, _, _, true, _, _))
+ EXPECT_CALL(getInstance()->mRenderEngine, drawLayers(settings, _, _, false, _, _))
.WillOnce(Return(NO_ERROR));
return nextState<ExecuteState>();
}
@@ -3296,7 +3326,7 @@
EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
.WillRepeatedly(Return());
EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
- EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _))
+ EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, false, _, _))
.WillRepeatedly(Return(NO_ERROR));
}
@@ -3349,7 +3379,7 @@
EXPECT_CALL(*mRenderSurface, setProtected(true));
// Must happen after setting the protected content state.
EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
- EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _)).WillOnce(Return(NO_ERROR));
+ EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, false, _, _)).WillOnce(Return(NO_ERROR));
mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
}
@@ -3419,7 +3449,7 @@
InSequence seq;
EXPECT_CALL(mOutput, setExpensiveRenderingExpected(true));
- EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _)).WillOnce(Return(NO_ERROR));
+ EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, false, _, _)).WillOnce(Return(NO_ERROR));
mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
}
@@ -3434,7 +3464,7 @@
EXPECT_CALL(mLayer.outputLayer, writeStateToHWC(false));
EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
.WillOnce(Return(std::vector<LayerFE::LayerSettings>{}));
- EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, true, _, _)).WillOnce(Return(NO_ERROR));
+ EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, false, _, _)).WillOnce(Return(NO_ERROR));
EXPECT_CALL(mOutput, getOutputLayerCount()).WillRepeatedly(Return(1u));
EXPECT_CALL(mOutput, getOutputLayerOrderedByZByIndex(0u))
.WillRepeatedly(Return(&mLayer.outputLayer));
diff --git a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
index cd39733..5ef5d7b 100644
--- a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
@@ -119,9 +119,10 @@
*/
TEST_F(RenderSurfaceTest, setDisplaySizeAppliesChange) {
- EXPECT_CALL(*mDisplaySurface, resizeBuffers(640, 480)).Times(1);
+ const ui::Size size(640, 480);
+ EXPECT_CALL(*mDisplaySurface, resizeBuffers(size)).Times(1);
- mSurface.setDisplaySize(ui::Size(640, 480));
+ mSurface.setDisplaySize(size);
}
/*
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index b4a3ed1..a785968 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -179,6 +179,31 @@
return nullptr;
}
+nsecs_t DisplayDevice::getVsyncPeriodFromHWC() const {
+ const auto physicalId = getPhysicalId();
+ if (!mHwComposer.isConnected(physicalId)) {
+ return 0;
+ }
+
+ nsecs_t vsyncPeriod;
+ const auto status = mHwComposer.getDisplayVsyncPeriod(physicalId, &vsyncPeriod);
+ if (status == NO_ERROR) {
+ return vsyncPeriod;
+ }
+
+ return getActiveMode()->getFps().getPeriodNsecs();
+}
+
+nsecs_t DisplayDevice::getRefreshTimestamp() const {
+ const nsecs_t now = systemTime(CLOCK_MONOTONIC);
+ const auto vsyncPeriodNanos = getVsyncPeriodFromHWC();
+ return now - ((now - mLastHwVsync) % vsyncPeriodNanos);
+}
+
+void DisplayDevice::onVsync(nsecs_t timestamp) {
+ mLastHwVsync = timestamp;
+}
+
ui::Dataspace DisplayDevice::getCompositionDataSpace() const {
return mCompositionDisplay->getState().dataspace;
}
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 6f07964..b4db933 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -176,6 +176,10 @@
// set-top boxes after a hotplug reconnect.
DisplayModePtr getMode(DisplayModeId) const;
+ void onVsync(nsecs_t timestamp);
+ nsecs_t getVsyncPeriodFromHWC() const;
+ nsecs_t getRefreshTimestamp() const;
+
// release HWC resources (if any) for removable displays
void disconnect();
@@ -207,6 +211,8 @@
DisplayModeId mActiveModeId;
const DisplayModes mSupportedModes;
+ std::atomic<nsecs_t> mLastHwVsync = 0;
+
// TODO(b/74619554): Remove special cases for primary display.
const bool mIsPrimary;
diff --git a/services/surfaceflinger/DisplayHardware/DisplayMode.h b/services/surfaceflinger/DisplayHardware/DisplayMode.h
index 61c1b61..1f0f3c3 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayMode.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayMode.h
@@ -22,6 +22,7 @@
#include <android-base/stringprintf.h>
#include <android/configuration.h>
+#include <ui/Size.h>
#include <utils/Timers.h>
#include <cstddef>
@@ -85,8 +86,8 @@
return *this;
}
- Builder& setConfigGroup(int32_t configGroup) {
- mDisplayMode->mConfigGroup = configGroup;
+ Builder& setGroup(int32_t group) {
+ mDisplayMode->mGroup = group;
return *this;
}
@@ -113,11 +114,15 @@
int32_t getWidth() const { return mWidth; }
int32_t getHeight() const { return mHeight; }
+ ui::Size getSize() const { return {mWidth, mHeight}; }
Fps getFps() const { return mFps; }
nsecs_t getVsyncPeriod() const { return mFps.getPeriodNsecs(); }
float getDpiX() const { return mDpiX; }
float getDpiY() const { return mDpiY; }
- int32_t getConfigGroup() const { return mConfigGroup; }
+
+ // Switches between modes in the same group are seamless, i.e.
+ // without visual interruptions such as a black screen.
+ int32_t getGroup() const { return mGroup; }
private:
explicit DisplayMode(hal::HWConfigId id) : mHwcId(id) {}
@@ -130,15 +135,15 @@
Fps mFps;
float mDpiX = -1;
float mDpiY = -1;
- int32_t mConfigGroup = -1;
+ int32_t mGroup = -1;
};
inline std::string to_string(const DisplayMode& mode) {
return base::StringPrintf("{id=%zu, hwcId=%d, width=%d, height=%d, refreshRate=%s, "
- "dpiX=%.2f, dpiY=%.2f, configGroup=%d}",
+ "dpiX=%.2f, dpiY=%.2f, group=%d}",
mode.getId().value(), mode.getHwcId(), mode.getWidth(),
mode.getHeight(), to_string(mode.getFps()).c_str(), mode.getDpiX(),
- mode.getDpiY(), mode.getConfigGroup());
+ mode.getDpiY(), mode.getGroup());
}
} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 3e856bb..f7fc162 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -58,11 +58,10 @@
FramebufferSurface::FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displayId,
const sp<IGraphicBufferConsumer>& consumer,
- uint32_t maxWidth, uint32_t maxHeight)
+ const ui::Size& size, const ui::Size& maxSize)
: ConsumerBase(consumer),
mDisplayId(displayId),
- mMaxWidth(maxWidth),
- mMaxHeight(maxHeight),
+ mMaxSize(maxSize),
mCurrentBufferSlot(-1),
mCurrentBuffer(),
mCurrentFence(Fence::NO_FENCE),
@@ -77,15 +76,14 @@
mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |
GRALLOC_USAGE_HW_RENDER |
GRALLOC_USAGE_HW_COMPOSER);
- const auto& activeMode = mHwc.getActiveMode(displayId);
- ui::Size limitedSize = limitFramebufferSize(activeMode->getWidth(), activeMode->getHeight());
+ const auto limitedSize = limitFramebufferSize(size);
mConsumer->setDefaultBufferSize(limitedSize.width, limitedSize.height);
mConsumer->setMaxAcquiredBufferCount(
SurfaceFlinger::maxFrameBufferAcquiredBuffers - 1);
}
-void FramebufferSurface::resizeBuffers(uint32_t width, uint32_t height) {
- ui::Size limitedSize = limitFramebufferSize(width, height);
+void FramebufferSurface::resizeBuffers(const ui::Size& newSize) {
+ const auto limitedSize = limitFramebufferSize(newSize);
mConsumer->setDefaultBufferSize(limitedSize.width, limitedSize.height);
}
@@ -181,24 +179,24 @@
}
}
-ui::Size FramebufferSurface::limitFramebufferSize(uint32_t width, uint32_t height) {
- ui::Size framebufferSize(width, height);
- bool wasLimited = true;
- if (width > mMaxWidth && mMaxWidth != 0) {
- float aspectRatio = float(width) / float(height);
- framebufferSize.height = mMaxWidth / aspectRatio;
- framebufferSize.width = mMaxWidth;
+ui::Size FramebufferSurface::limitFramebufferSize(const ui::Size& size) {
+ ui::Size limitedSize = size;
+ bool wasLimited = false;
+ if (size.width > mMaxSize.width && mMaxSize.width != 0) {
+ const float aspectRatio = static_cast<float>(size.width) / size.height;
+ limitedSize.height = mMaxSize.width / aspectRatio;
+ limitedSize.width = mMaxSize.width;
wasLimited = true;
}
- if (height > mMaxHeight && mMaxHeight != 0) {
- float aspectRatio = float(width) / float(height);
- framebufferSize.height = mMaxHeight;
- framebufferSize.width = mMaxHeight * aspectRatio;
+ if (size.height > mMaxSize.height && mMaxSize.height != 0) {
+ const float aspectRatio = static_cast<float>(size.width) / size.height;
+ limitedSize.height = mMaxSize.height;
+ limitedSize.width = mMaxSize.height * aspectRatio;
wasLimited = true;
}
ALOGI_IF(wasLimited, "framebuffer size has been limited to [%dx%d] from [%dx%d]",
- framebufferSize.width, framebufferSize.height, width, height);
- return framebufferSize;
+ limitedSize.width, limitedSize.height, size.width, size.height);
+ return limitedSize;
}
void FramebufferSurface::dumpAsString(String8& result) const {
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 759943a..5d1e131 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -41,8 +41,8 @@
class FramebufferSurface : public ConsumerBase, public compositionengine::DisplaySurface {
public:
FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displayId,
- const sp<IGraphicBufferConsumer>& consumer, uint32_t maxWidth,
- uint32_t maxHeight);
+ const sp<IGraphicBufferConsumer>& consumer, const ui::Size& size,
+ const ui::Size& maxSize);
virtual status_t beginFrame(bool mustRecompose);
virtual status_t prepareFrame(CompositionType compositionType);
@@ -50,7 +50,7 @@
virtual void onFrameCommitted();
virtual void dumpAsString(String8& result) const;
- virtual void resizeBuffers(uint32_t width, uint32_t height);
+ virtual void resizeBuffers(const ui::Size&) override;
virtual const sp<Fence>& getClientTargetAcquireFence() const override;
@@ -62,7 +62,7 @@
virtual void dumpLocked(String8& result, const char* prefix) const;
// Limits the width and height by the maximum width specified in the constructor.
- ui::Size limitFramebufferSize(uint32_t width, uint32_t height);
+ ui::Size limitFramebufferSize(const ui::Size&);
// nextBuffer waits for and then latches the next buffer from the
// BufferQueue and releases the previously latched buffer to the
@@ -74,11 +74,7 @@
// Framebuffer size has a dimension limitation in pixels based on the graphics capabilities of
// the device.
- const uint32_t mMaxWidth;
-
- // Framebuffer size has a dimension limitation in pixels based on the graphics capabilities of
- // the device.
- const uint32_t mMaxHeight;
+ const ui::Size mMaxSize;
// mCurrentBufferIndex is the slot index of the current buffer or
// INVALID_BUFFER_SLOT to indicate that either there is no current buffer
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 46dc54e..b9a8e4b 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -223,8 +223,6 @@
__FUNCTION__, to_string(*displayId).c_str());
{
- std::lock_guard lock(displayData.lastHwVsyncLock);
-
// There have been reports of HWCs that signal several vsync events
// with the same timestamp when turning the display off and on. This
// is a bug in the HWC implementation, but filter the extra events
@@ -295,11 +293,10 @@
hal::DisplayType::PHYSICAL);
newDisplay->setConnected(true);
displayData.hwcDisplay = std::move(newDisplay);
- loadModes(displayData, hwcDisplayId);
}
int32_t HWComposer::getAttribute(hal::HWDisplayId hwcDisplayId, hal::HWConfigId configId,
- hal::Attribute attribute) {
+ hal::Attribute attribute) const {
int32_t value = 0;
auto error = static_cast<hal::Error>(
mComposer->getDisplayAttribute(hwcDisplayId, configId, attribute, &value));
@@ -308,30 +305,6 @@
return value;
}
-void HWComposer::loadModes(DisplayData& displayData, hal::HWDisplayId hwcDisplayId) {
- ALOGV("[HWC display %" PRIu64 "] %s", hwcDisplayId, __FUNCTION__);
-
- std::vector<hal::HWConfigId> configIds;
- auto error = static_cast<hal::Error>(mComposer->getDisplayConfigs(hwcDisplayId, &configIds));
- RETURN_IF_HWC_ERROR_FOR("getDisplayConfigs", error, *toPhysicalDisplayId(hwcDisplayId));
-
- displayData.modes.clear();
- for (auto configId : configIds) {
- auto mode = DisplayMode::Builder(configId)
- .setId(DisplayModeId(displayData.modes.size()))
- .setWidth(getAttribute(hwcDisplayId, configId, hal::Attribute::WIDTH))
- .setHeight(getAttribute(hwcDisplayId, configId, hal::Attribute::HEIGHT))
- .setVsyncPeriod(getAttribute(hwcDisplayId, configId,
- hal::Attribute::VSYNC_PERIOD))
- .setDpiX(getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_X))
- .setDpiY(getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_Y))
- .setConfigGroup(getAttribute(hwcDisplayId, configId,
- hal::Attribute::CONFIG_GROUP))
- .build();
- displayData.modes.push_back(std::move(mode));
- }
-}
-
HWC2::Layer* HWComposer::createLayer(HalDisplayId displayId) {
RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
@@ -348,55 +321,50 @@
RETURN_IF_HWC_ERROR(error, displayId);
}
-nsecs_t HWComposer::getRefreshTimestamp(PhysicalDisplayId displayId) const {
- RETURN_IF_INVALID_DISPLAY(displayId, 0);
- const auto& displayData = mDisplayData.at(displayId);
- // this returns the last refresh timestamp.
- // if the last one is not available, we estimate it based on
- // the refresh period and whatever closest timestamp we have.
- std::lock_guard lock(displayData.lastHwVsyncLock);
- nsecs_t now = systemTime(CLOCK_MONOTONIC);
- auto vsyncPeriodNanos = getDisplayVsyncPeriod(displayId);
- return now - ((now - displayData.lastHwVsync) % vsyncPeriodNanos);
-}
-
bool HWComposer::isConnected(PhysicalDisplayId displayId) const {
RETURN_IF_INVALID_DISPLAY(displayId, false);
return mDisplayData.at(displayId).hwcDisplay->isConnected();
}
-DisplayModes HWComposer::getModes(PhysicalDisplayId displayId) const {
+std::vector<HWComposer::HWCDisplayMode> HWComposer::getModes(PhysicalDisplayId displayId) const {
RETURN_IF_INVALID_DISPLAY(displayId, {});
- // We cache the modes when the DisplayData is created on hotplug. If the modes need to
- // change HWC will send a hotplug event which will recreate displayData.
- return mDisplayData.at(displayId).modes;
+ const auto hwcDisplayId = mDisplayData.at(displayId).hwcDisplay->getId();
+ std::vector<hal::HWConfigId> configIds;
+ auto error = static_cast<hal::Error>(mComposer->getDisplayConfigs(hwcDisplayId, &configIds));
+ RETURN_IF_HWC_ERROR_FOR("getDisplayConfigs", error, *toPhysicalDisplayId(hwcDisplayId), {});
+
+ std::vector<HWCDisplayMode> modes;
+ modes.reserve(configIds.size());
+ for (auto configId : configIds) {
+ modes.push_back(HWCDisplayMode{
+ .hwcId = configId,
+ .width = getAttribute(hwcDisplayId, configId, hal::Attribute::WIDTH),
+ .height = getAttribute(hwcDisplayId, configId, hal::Attribute::HEIGHT),
+ .vsyncPeriod = getAttribute(hwcDisplayId, configId, hal::Attribute::VSYNC_PERIOD),
+ .dpiX = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_X),
+ .dpiY = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_Y),
+ .configGroup = getAttribute(hwcDisplayId, configId, hal::Attribute::CONFIG_GROUP),
+ });
+ }
+
+ return modes;
}
-DisplayModePtr HWComposer::getActiveMode(PhysicalDisplayId displayId) const {
- RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
+std::optional<hal::HWConfigId> HWComposer::getActiveMode(PhysicalDisplayId displayId) const {
+ RETURN_IF_INVALID_DISPLAY(displayId, std::nullopt);
const auto hwcId = *fromPhysicalDisplayId(displayId);
ALOGV("[%" PRIu64 "] getActiveMode", hwcId);
hal::HWConfigId configId;
auto error = static_cast<hal::Error>(mComposer->getActiveConfig(hwcId, &configId));
- const auto& modes = mDisplayData.at(displayId).modes;
if (error == hal::Error::BAD_CONFIG) {
LOG_DISPLAY_ERROR(displayId, "No active mode");
- return nullptr;
+ return std::nullopt;
}
- RETURN_IF_HWC_ERROR(error, displayId, nullptr);
-
- const auto it = std::find_if(modes.begin(), modes.end(),
- [configId](auto mode) { return mode->getHwcId() == configId; });
- if (it == modes.end()) {
- LOG_DISPLAY_ERROR(displayId, "Unknown mode");
- return nullptr;
- }
-
- return *it;
+ return configId;
}
// Composer 2.4
@@ -421,27 +389,20 @@
return mDisplayData.at(displayId).hwcDisplay->isVsyncPeriodSwitchSupported();
}
-nsecs_t HWComposer::getDisplayVsyncPeriod(PhysicalDisplayId displayId) const {
+status_t HWComposer::getDisplayVsyncPeriod(PhysicalDisplayId displayId,
+ nsecs_t* outVsyncPeriod) const {
RETURN_IF_INVALID_DISPLAY(displayId, 0);
- if (isVsyncPeriodSwitchSupported(displayId)) {
- const auto hwcId = *fromPhysicalDisplayId(displayId);
- Hwc2::VsyncPeriodNanos vsyncPeriodNanos = 0;
- auto error =
- static_cast<hal::Error>(mComposer->getDisplayVsyncPeriod(hwcId, &vsyncPeriodNanos));
- RETURN_IF_HWC_ERROR(error, displayId, 0);
- return static_cast<nsecs_t>(vsyncPeriodNanos);
+ if (!isVsyncPeriodSwitchSupported(displayId)) {
+ return INVALID_OPERATION;
}
-
- // Get the default vsync period
- auto mode = getActiveMode(displayId);
-
- if (!mode) {
- // HWC has updated the display modes and hasn't notified us yet.
- RETURN_IF_HWC_ERROR(hal::Error::BAD_CONFIG, displayId, 0);
- }
-
- return mode->getVsyncPeriod();
+ const auto hwcId = *fromPhysicalDisplayId(displayId);
+ Hwc2::VsyncPeriodNanos vsyncPeriodNanos = 0;
+ auto error =
+ static_cast<hal::Error>(mComposer->getDisplayVsyncPeriod(hwcId, &vsyncPeriodNanos));
+ RETURN_IF_HWC_ERROR(error, displayId, 0);
+ *outVsyncPeriod = static_cast<nsecs_t>(vsyncPeriodNanos);
+ return NO_ERROR;
}
std::vector<ui::ColorMode> HWComposer::getColorModes(PhysicalDisplayId displayId) const {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 1ffe276..f9c8e2e 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -83,6 +83,16 @@
ClientTargetProperty clientTargetProperty;
};
+ struct HWCDisplayMode {
+ hal::HWConfigId hwcId;
+ int32_t width = -1;
+ int32_t height = -1;
+ nsecs_t vsyncPeriod = -1;
+ int32_t dpiX = -1;
+ int32_t dpiY = -1;
+ int32_t configGroup = -1;
+ };
+
virtual ~HWComposer();
virtual void setConfiguration(HWC2::ComposerCallback* callback, int32_t sequenceId) = 0;
@@ -182,12 +192,11 @@
virtual bool onVsync(hal::HWDisplayId, int64_t timestamp) = 0;
virtual void setVsyncEnabled(PhysicalDisplayId, hal::Vsync enabled) = 0;
- virtual nsecs_t getRefreshTimestamp(PhysicalDisplayId) const = 0;
virtual bool isConnected(PhysicalDisplayId) const = 0;
- virtual DisplayModes getModes(PhysicalDisplayId) const = 0;
+ virtual std::vector<HWCDisplayMode> getModes(PhysicalDisplayId) const = 0;
- virtual DisplayModePtr getActiveMode(PhysicalDisplayId) const = 0;
+ virtual std::optional<hal::HWConfigId> getActiveMode(PhysicalDisplayId) const = 0;
virtual std::vector<ui::ColorMode> getColorModes(PhysicalDisplayId) const = 0;
@@ -197,7 +206,8 @@
// Composer 2.4
virtual DisplayConnectionType getDisplayConnectionType(PhysicalDisplayId) const = 0;
virtual bool isVsyncPeriodSwitchSupported(PhysicalDisplayId) const = 0;
- virtual nsecs_t getDisplayVsyncPeriod(PhysicalDisplayId) const = 0;
+ virtual status_t getDisplayVsyncPeriod(PhysicalDisplayId displayId,
+ nsecs_t* outVsyncPeriod) const = 0;
virtual status_t setActiveModeWithConstraints(PhysicalDisplayId, hal::HWConfigId,
const hal::VsyncPeriodChangeConstraints&,
hal::VsyncPeriodChangeTimeline* outTimeline) = 0;
@@ -314,12 +324,11 @@
bool onVsync(hal::HWDisplayId, int64_t timestamp) override;
void setVsyncEnabled(PhysicalDisplayId, hal::Vsync enabled) override;
- nsecs_t getRefreshTimestamp(PhysicalDisplayId) const override;
bool isConnected(PhysicalDisplayId) const override;
- DisplayModes getModes(PhysicalDisplayId) const override;
+ std::vector<HWCDisplayMode> getModes(PhysicalDisplayId) const override;
- DisplayModePtr getActiveMode(PhysicalDisplayId) const override;
+ std::optional<hal::HWConfigId> getActiveMode(PhysicalDisplayId) const override;
std::vector<ui::ColorMode> getColorModes(PhysicalDisplayId) const override;
@@ -328,7 +337,8 @@
// Composer 2.4
DisplayConnectionType getDisplayConnectionType(PhysicalDisplayId) const override;
bool isVsyncPeriodSwitchSupported(PhysicalDisplayId) const override;
- nsecs_t getDisplayVsyncPeriod(PhysicalDisplayId displayId) const override;
+ status_t getDisplayVsyncPeriod(PhysicalDisplayId displayId,
+ nsecs_t* outVsyncPeriod) const override;
status_t setActiveModeWithConstraints(PhysicalDisplayId, hal::HWConfigId,
const hal::VsyncPeriodChangeConstraints&,
hal::VsyncPeriodChangeTimeline* outTimeline) override;
@@ -365,7 +375,6 @@
std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
buffer_handle_t outbufHandle = nullptr;
sp<Fence> outbufAcquireFence = Fence::NO_FENCE;
- DisplayModes modes;
bool validateWasSkipped;
hal::Error presentError;
@@ -375,8 +384,7 @@
std::mutex vsyncEnabledLock;
hal::Vsync vsyncEnabled GUARDED_BY(vsyncEnabledLock) = hal::Vsync::DISABLE;
- mutable std::mutex lastHwVsyncLock;
- nsecs_t lastHwVsync GUARDED_BY(lastHwVsyncLock) = 0;
+ nsecs_t lastHwVsync = 0;
};
std::optional<DisplayIdentificationInfo> onHotplugConnect(hal::HWDisplayId);
@@ -384,8 +392,7 @@
bool shouldIgnoreHotplugConnect(hal::HWDisplayId, bool hasDisplayIdentificationData) const;
int32_t getAttribute(hal::HWDisplayId hwcDisplayId, hal::HWConfigId configId,
- hal::Attribute attribute);
- void loadModes(DisplayData& displayData, hal::HWDisplayId hwcDisplayId);
+ hal::Attribute attribute) const;
void loadCapabilities();
void loadLayerMetadataSupport();
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 2ac67cb..e26ab11 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -291,11 +291,11 @@
void VirtualDisplaySurface::dumpAsString(String8& /* result */) const {
}
-void VirtualDisplaySurface::resizeBuffers(const uint32_t w, const uint32_t h) {
- mQueueBufferOutput.width = w;
- mQueueBufferOutput.height = h;
- mSinkBufferWidth = w;
- mSinkBufferHeight = h;
+void VirtualDisplaySurface::resizeBuffers(const ui::Size& newSize) {
+ mQueueBufferOutput.width = newSize.width;
+ mQueueBufferOutput.height = newSize.height;
+ mSinkBufferWidth = newSize.width;
+ mSinkBufferHeight = newSize.height;
}
const sp<Fence>& VirtualDisplaySurface::getClientTargetAcquireFence() const {
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index fba0e3b..bbb6306 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -90,7 +90,7 @@
virtual status_t advanceFrame();
virtual void onFrameCommitted();
virtual void dumpAsString(String8& result) const;
- virtual void resizeBuffers(const uint32_t w, const uint32_t h);
+ virtual void resizeBuffers(const ui::Size&) override;
virtual const sp<Fence>& getClientTargetAcquireFence() const override;
private:
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
index 17d1f3b..3f833f4 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
@@ -275,13 +275,15 @@
return ++mTraceCookie;
}
-SurfaceFrame::SurfaceFrame(int64_t token, pid_t ownerPid, uid_t ownerUid, std::string layerName,
- std::string debugName, PredictionState predictionState,
+SurfaceFrame::SurfaceFrame(const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid,
+ uid_t ownerUid, std::string layerName, std::string debugName,
+ PredictionState predictionState,
frametimeline::TimelineItem&& predictions,
std::shared_ptr<TimeStats> timeStats,
JankClassificationThresholds thresholds,
TraceCookieCounter* traceCookieCounter)
- : mToken(token),
+ : mToken(frameTimelineInfo.vsyncId),
+ mInputEventId(frameTimelineInfo.inputEventId),
mOwnerPid(ownerPid),
mOwnerUid(ownerUid),
mLayerName(std::move(layerName)),
@@ -295,27 +297,31 @@
mTraceCookieCounter(*traceCookieCounter) {}
void SurfaceFrame::setActualStartTime(nsecs_t actualStartTime) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
mActuals.startTime = actualStartTime;
}
void SurfaceFrame::setActualQueueTime(nsecs_t actualQueueTime) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
mActualQueueTime = actualQueueTime;
}
void SurfaceFrame::setAcquireFenceTime(nsecs_t acquireFenceTime) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
mActuals.endTime = std::max(acquireFenceTime, mActualQueueTime);
}
void SurfaceFrame::setPresentState(PresentState presentState, nsecs_t lastLatchTime) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
+ LOG_ALWAYS_FATAL_IF(mPresentState != PresentState::Unknown,
+ "setPresentState called on a SurfaceFrame from Layer - %s, that has a "
+ "PresentState - %s set already.",
+ mDebugName.c_str(), toString(mPresentState).c_str());
mPresentState = presentState;
mLastLatchTime = lastLatchTime;
}
std::optional<int32_t> SurfaceFrame::getJankType() const {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
if (mActuals.presentTime == 0) {
return std::nullopt;
}
@@ -323,32 +329,32 @@
}
nsecs_t SurfaceFrame::getBaseTime() const {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
return getMinTime(mPredictionState, mPredictions, mActuals);
}
TimelineItem SurfaceFrame::getActuals() const {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
return mActuals;
}
SurfaceFrame::PresentState SurfaceFrame::getPresentState() const {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
return mPresentState;
}
FramePresentMetadata SurfaceFrame::getFramePresentMetadata() const {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
return mFramePresentMetadata;
}
FrameReadyMetadata SurfaceFrame::getFrameReadyMetadata() const {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
return mFrameReadyMetadata;
}
void SurfaceFrame::dump(std::string& result, const std::string& indent, nsecs_t baseTime) const {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
StringAppendF(&result, "%s", indent.c_str());
StringAppendF(&result, "Layer - %s", mDebugName.c_str());
if (mJankType != JankType::None) {
@@ -387,7 +393,7 @@
void SurfaceFrame::onPresent(nsecs_t presentTime, int32_t displayFrameJankType,
nsecs_t vsyncPeriod) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
if (mPresentState != PresentState::Presented) {
// No need to update dropped buffers
return;
@@ -479,6 +485,9 @@
mTimeStats->incrementJankyFrames(mOwnerUid, mLayerName, mJankType);
}
+/**
+ * TODO(b/178637512): add inputEventId to the perfetto trace.
+ */
void SurfaceFrame::trace(int64_t displayFrameToken) {
using FrameTimelineDataSource = impl::FrameTimeline::FrameTimelineDataSource;
@@ -486,12 +495,12 @@
bool missingToken = false;
// Expected timeline start
FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
- std::lock_guard<std::mutex> lock(mMutex);
- if (mToken == ISurfaceComposer::INVALID_VSYNC_ID) {
+ std::scoped_lock lock(mMutex);
+ if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
ALOGD("Cannot trace SurfaceFrame - %s with invalid token", mLayerName.c_str());
missingToken = true;
return;
- } else if (displayFrameToken == ISurfaceComposer::INVALID_VSYNC_ID) {
+ } else if (displayFrameToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
ALOGD("Cannot trace SurfaceFrame - %s with invalid displayFrameToken",
mLayerName.c_str());
missingToken = true;
@@ -521,7 +530,7 @@
// Expected timeline end
FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
auto packet = ctx.NewTracePacket();
packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
packet->set_timestamp(static_cast<uint64_t>(mPredictions.endTime));
@@ -535,7 +544,7 @@
int64_t actualTimelineCookie = mTraceCookieCounter.getCookieForTracing();
// Actual timeline start
FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
auto packet = ctx.NewTracePacket();
packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
// Actual start time is not yet available, so use expected start instead
@@ -566,7 +575,7 @@
});
// Actual timeline end
FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
auto packet = ctx.NewTracePacket();
packet->set_timestamp_clock_id(perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC);
packet->set_timestamp(static_cast<uint64_t>(mActuals.endTime));
@@ -582,7 +591,7 @@
int64_t TokenManager::generateTokenForPredictions(TimelineItem&& predictions) {
ATRACE_CALL();
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
const int64_t assignedToken = mCurrentToken++;
mPredictions[assignedToken] = {systemTime(), predictions};
flushTokens(systemTime());
@@ -590,7 +599,7 @@
}
std::optional<TimelineItem> TokenManager::getPredictionsForToken(int64_t token) const {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
auto predictionsIterator = mPredictions.find(token);
if (predictionsIterator != mPredictions.end()) {
return predictionsIterator->second.predictions;
@@ -634,26 +643,28 @@
}
std::shared_ptr<SurfaceFrame> FrameTimeline::createSurfaceFrameForToken(
- std::optional<int64_t> token, pid_t ownerPid, uid_t ownerUid, std::string layerName,
- std::string debugName) {
+ const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid,
+ std::string layerName, std::string debugName) {
ATRACE_CALL();
- if (!token) {
- return std::make_shared<SurfaceFrame>(ISurfaceComposer::INVALID_VSYNC_ID, ownerPid,
- ownerUid, std::move(layerName), std::move(debugName),
+ if (frameTimelineInfo.vsyncId == FrameTimelineInfo::INVALID_VSYNC_ID) {
+ return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid,
+ std::move(layerName), std::move(debugName),
PredictionState::None, TimelineItem(), mTimeStats,
mJankClassificationThresholds, &mTraceCookieCounter);
}
- std::optional<TimelineItem> predictions = mTokenManager.getPredictionsForToken(*token);
+ std::optional<TimelineItem> predictions =
+ mTokenManager.getPredictionsForToken(frameTimelineInfo.vsyncId);
if (predictions) {
- return std::make_shared<SurfaceFrame>(*token, ownerPid, ownerUid, std::move(layerName),
- std::move(debugName), PredictionState::Valid,
- std::move(*predictions), mTimeStats,
- mJankClassificationThresholds, &mTraceCookieCounter);
+ return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid,
+ std::move(layerName), std::move(debugName),
+ PredictionState::Valid, std::move(*predictions),
+ mTimeStats, mJankClassificationThresholds,
+ &mTraceCookieCounter);
}
- return std::make_shared<SurfaceFrame>(*token, ownerPid, ownerUid, std::move(layerName),
- std::move(debugName), PredictionState::Expired,
- TimelineItem(), mTimeStats, mJankClassificationThresholds,
- &mTraceCookieCounter);
+ return std::make_shared<SurfaceFrame>(frameTimelineInfo, ownerPid, ownerUid,
+ std::move(layerName), std::move(debugName),
+ PredictionState::Expired, TimelineItem(), mTimeStats,
+ mJankClassificationThresholds, &mTraceCookieCounter);
}
FrameTimeline::DisplayFrame::DisplayFrame(std::shared_ptr<TimeStats> timeStats,
@@ -669,13 +680,13 @@
void FrameTimeline::addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame) {
ATRACE_CALL();
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
mCurrentDisplayFrame->addSurfaceFrame(surfaceFrame);
}
void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime, nsecs_t vsyncPeriod) {
ATRACE_CALL();
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
mCurrentDisplayFrame->onSfWakeUp(token, vsyncPeriod,
mTokenManager.getPredictionsForToken(token), wakeUpTime);
}
@@ -683,7 +694,7 @@
void FrameTimeline::setSfPresent(nsecs_t sfPresentTime,
const std::shared_ptr<FenceTime>& presentFence) {
ATRACE_CALL();
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
mCurrentDisplayFrame->setActualEndTime(sfPresentTime);
mPendingPresentFences.emplace_back(std::make_pair(presentFence, mCurrentDisplayFrame));
flushPendingPresentFences();
@@ -826,7 +837,7 @@
// Expected timeline start
FrameTimelineDataSource::Trace([&](FrameTimelineDataSource::TraceContext ctx) {
auto packet = ctx.NewTracePacket();
- if (mToken == ISurfaceComposer::INVALID_VSYNC_ID) {
+ if (mToken == FrameTimelineInfo::INVALID_VSYNC_ID) {
ALOGD("Cannot trace DisplayFrame with invalid token");
missingToken = true;
return;
@@ -999,7 +1010,7 @@
}
void FrameTimeline::dumpAll(std::string& result) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
StringAppendF(&result, "Number of display frames : %d\n", (int)mDisplayFrames.size());
nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime();
for (size_t i = 0; i < mDisplayFrames.size(); i++) {
@@ -1009,7 +1020,7 @@
}
void FrameTimeline::dumpJank(std::string& result) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
nsecs_t baseTime = (mDisplayFrames.empty()) ? 0 : mDisplayFrames[0]->getBaseTime();
for (size_t i = 0; i < mDisplayFrames.size(); i++) {
mDisplayFrames[i]->dumpJank(result, baseTime, static_cast<int>(i));
@@ -1031,7 +1042,7 @@
}
void FrameTimeline::setMaxDisplayFrames(uint32_t size) {
- std::lock_guard<std::mutex> lock(mMutex);
+ std::scoped_lock lock(mMutex);
// The size can either increase or decrease, clear everything, to be consistent
mDisplayFrames.clear();
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.h b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
index ed38cc6..54e8efb 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.h
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
@@ -154,10 +154,10 @@
// Only FrameTimeline can construct a SurfaceFrame as it provides Predictions(through
// TokenManager), Thresholds and TimeStats pointer.
- SurfaceFrame(int64_t token, pid_t ownerPid, uid_t ownerUid, std::string layerName,
- std::string debugName, PredictionState predictionState, TimelineItem&& predictions,
- std::shared_ptr<TimeStats> timeStats, JankClassificationThresholds thresholds,
- TraceCookieCounter* traceCookieCounter);
+ SurfaceFrame(const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid,
+ std::string layerName, std::string debugName, PredictionState predictionState,
+ TimelineItem&& predictions, std::shared_ptr<TimeStats> timeStats,
+ JankClassificationThresholds thresholds, TraceCookieCounter* traceCookieCounter);
~SurfaceFrame() = default;
// Returns std::nullopt if the frame hasn't been classified yet.
@@ -166,6 +166,7 @@
// Functions called by SF
int64_t getToken() const { return mToken; };
+ int32_t getInputEventId() const { return mInputEventId; };
TimelineItem getPredictions() const { return mPredictions; };
// Actual timestamps of the app are set individually at different functions.
// Start time (if the app provides) and Queue time are accessible after queueing the frame,
@@ -198,6 +199,7 @@
private:
const int64_t mToken;
+ const int32_t mInputEventId;
const pid_t mOwnerPid;
const uid_t mOwnerUid;
const std::string mLayerName;
@@ -243,10 +245,9 @@
// Create a new surface frame, set the predictions based on a token and return it to the caller.
// Debug name is the human-readable debugging string for dumpsys.
- virtual std::shared_ptr<SurfaceFrame> createSurfaceFrameForToken(std::optional<int64_t> token,
- pid_t ownerPid, uid_t ownerUid,
- std::string layerName,
- std::string debugName) = 0;
+ virtual std::shared_ptr<SurfaceFrame> createSurfaceFrameForToken(
+ const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid,
+ std::string layerName, std::string debugName) = 0;
// Adds a new SurfaceFrame to the current DisplayFrame. Frames from multiple layers can be
// composited into one display frame.
@@ -279,7 +280,7 @@
class TokenManager : public android::frametimeline::TokenManager {
public:
- TokenManager() : mCurrentToken(ISurfaceComposer::INVALID_VSYNC_ID + 1) {}
+ TokenManager() : mCurrentToken(FrameTimelineInfo::INVALID_VSYNC_ID + 1) {}
~TokenManager() = default;
int64_t generateTokenForPredictions(TimelineItem&& predictions) override;
@@ -353,7 +354,7 @@
private:
void dump(std::string& result, nsecs_t baseTime) const;
- int64_t mToken = ISurfaceComposer::INVALID_VSYNC_ID;
+ int64_t mToken = FrameTimelineInfo::INVALID_VSYNC_ID;
/* Usage of TimelineItem w.r.t SurfaceFlinger
* startTime Time when SurfaceFlinger wakes up to handle transactions and buffer updates
@@ -393,10 +394,9 @@
~FrameTimeline() = default;
frametimeline::TokenManager* getTokenManager() override { return &mTokenManager; }
- std::shared_ptr<SurfaceFrame> createSurfaceFrameForToken(std::optional<int64_t> token,
- pid_t ownerPid, uid_t ownerUid,
- std::string layerName,
- std::string debugName) override;
+ std::shared_ptr<SurfaceFrame> createSurfaceFrameForToken(
+ const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid,
+ std::string layerName, std::string debugName) override;
void addSurfaceFrame(std::shared_ptr<frametimeline::SurfaceFrame> surfaceFrame) override;
void setSfWakeUp(int64_t token, nsecs_t wakeupTime, nsecs_t vsyncPeriod) override;
void setSfPresent(nsecs_t sfPresentTime,
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 177a81a..df14003 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -129,7 +129,7 @@
mCurrentState.shadowRadius = 0.f;
mCurrentState.treeHasFrameRateVote = false;
mCurrentState.fixedTransformHint = ui::Transform::ROT_INVALID;
- mCurrentState.frameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID;
+ mCurrentState.frameTimelineInfo = {};
mCurrentState.postTime = -1;
if (args.flags & ISurfaceComposerClient::eNoColorFill) {
@@ -841,13 +841,35 @@
setTransactionFlags(eTransactionNeeded);
mFlinger->setTransactionFlags(eTraversalNeeded);
}
+ if (mCurrentState.bufferlessSurfaceFramesTX.size() >= State::kStateSurfaceFramesThreshold) {
+ // Ideally, the currentState would only contain one SurfaceFrame per transaction (assuming
+ // each Tx uses a different token). We don't expect the current state to hold a huge amount
+ // of SurfaceFrames. However, in the event it happens, this debug statement will leave a
+ // trail that can help in debugging.
+ ALOGW("Bufferless SurfaceFrames size on current state of layer %s is %" PRIu32 "",
+ mName.c_str(), static_cast<uint32_t>(mCurrentState.bufferlessSurfaceFramesTX.size()));
+ }
mPendingStates.push_back(mCurrentState);
+ // Since the current state along with the SurfaceFrames has been pushed into the pendingState,
+ // we no longer need to retain them. If multiple states are pushed and applied together, we have
+ // a merging logic to address the SurfaceFrames at mergeSurfaceFrames().
+ mCurrentState.bufferlessSurfaceFramesTX.clear();
ATRACE_INT(mTransactionName.c_str(), mPendingStates.size());
}
+void Layer::mergeSurfaceFrames(State& source, State& target) {
+ // No need to merge BufferSurfaceFrame as the target's surfaceFrame, if it exists, will be used
+ // directly. Dropping of source's SurfaceFrame is taken care of at setBuffer().
+ target.bufferlessSurfaceFramesTX.merge(source.bufferlessSurfaceFramesTX);
+ source.bufferlessSurfaceFramesTX.clear();
+}
+
void Layer::popPendingState(State* stateToCommit) {
ATRACE_CALL();
+ if (stateToCommit != nullptr) {
+ mergeSurfaceFrames(*stateToCommit, mPendingStates[0]);
+ }
*stateToCommit = mPendingStates[0];
mPendingStates.pop_front();
ATRACE_INT(mTransactionName.c_str(), mPendingStates.size());
@@ -906,24 +928,6 @@
mFlinger->setTraversalNeeded();
}
- if (stateUpdateAvailable) {
- const auto vsyncId =
- stateToCommit->frameTimelineVsyncId == ISurfaceComposer::INVALID_VSYNC_ID
- ? std::nullopt
- : std::make_optional(stateToCommit->frameTimelineVsyncId);
-
- mSurfaceFrame =
- mFlinger->mFrameTimeline->createSurfaceFrameForToken(vsyncId, mOwnerPid, mOwnerUid,
- mName, mTransactionName);
- mSurfaceFrame->setActualQueueTime(stateToCommit->postTime);
- // For transactions we set the acquire fence time to the post time as we
- // don't have a buffer. For BufferStateLayer it is overridden in
- // BufferStateLayer::applyPendingStates
- mSurfaceFrame->setAcquireFenceTime(stateToCommit->postTime);
-
- onSurfaceFrameCreated(mSurfaceFrame);
- }
-
mCurrentState.modified = false;
return stateUpdateAvailable;
}
@@ -1004,19 +1008,6 @@
uint32_t Layer::doTransaction(uint32_t flags) {
ATRACE_CALL();
- if (mLayerDetached) {
- // Ensure BLAST buffer callbacks are processed.
- // detachChildren and mLayerDetached were implemented to avoid geometry updates
- // to layers in the cases of animation. For BufferQueue layers buffers are still
- // consumed as normal. This is useful as otherwise the client could get hung
- // inevitably waiting on a buffer to return. We recreate this semantic for BufferQueue
- // even though it is a little consistent. detachChildren is shortly slated for removal
- // by the hierarchy mirroring work so we don't need to worry about it too much.
- forceSendCallbacks();
- mCurrentState.callbackHandles = {};
- return flags;
- }
-
if (mChildrenChanged) {
flags |= eVisibleRegion;
mChildrenChanged = false;
@@ -1065,10 +1056,22 @@
return flags;
}
-void Layer::commitTransaction(const State& stateToCommit) {
+void Layer::commitTransaction(State& stateToCommit) {
mDrawingState = stateToCommit;
- mSurfaceFrame->setPresentState(PresentState::Presented);
- mFlinger->mFrameTimeline->addSurfaceFrame(mSurfaceFrame);
+
+ // Set the present state for all bufferlessSurfaceFramesTX to Presented. The
+ // bufferSurfaceFrameTX will be presented in latchBuffer.
+ for (auto& [token, surfaceFrame] : mDrawingState.bufferlessSurfaceFramesTX) {
+ if (surfaceFrame->getPresentState() != PresentState::Presented) {
+ // With applyPendingStates, we could end up having presented surfaceframes from previous
+ // states
+ surfaceFrame->setPresentState(PresentState::Presented);
+ mFlinger->mFrameTimeline->addSurfaceFrame(surfaceFrame);
+ }
+ }
+ // Clear the surfaceFrames from the old state now that it has been copied into DrawingState.
+ stateToCommit.bufferSurfaceFrameTX.reset();
+ stateToCommit.bufferlessSurfaceFramesTX.clear();
}
uint32_t Layer::getTransactionFlags(uint32_t flags) {
@@ -1491,11 +1494,94 @@
return true;
}
-void Layer::setFrameTimelineVsyncForTransaction(int64_t frameTimelineVsyncId, nsecs_t postTime) {
- mCurrentState.frameTimelineVsyncId = frameTimelineVsyncId;
+void Layer::setFrameTimelineVsyncForBufferTransaction(const FrameTimelineInfo& info,
+ nsecs_t postTime) {
+ mCurrentState.postTime = postTime;
+
+ // Check if one of the bufferlessSurfaceFramesTX contains the same vsyncId. This can happen if
+ // there are two transactions with the same token, the first one without a buffer and the
+ // second one with a buffer. We promote the bufferlessSurfaceFrame to a bufferSurfaceFrameTX
+ // in that case.
+ auto it = mCurrentState.bufferlessSurfaceFramesTX.find(info.vsyncId);
+ if (it != mCurrentState.bufferlessSurfaceFramesTX.end()) {
+ // Promote the bufferlessSurfaceFrame to a bufferSurfaceFrameTX
+ mCurrentState.bufferSurfaceFrameTX = it->second;
+ mCurrentState.bufferlessSurfaceFramesTX.erase(it);
+ mCurrentState.bufferSurfaceFrameTX->setActualQueueTime(postTime);
+ } else {
+ mCurrentState.bufferSurfaceFrameTX =
+ createSurfaceFrameForBuffer(info, postTime, mTransactionName);
+ }
+}
+
+void Layer::setFrameTimelineVsyncForBufferlessTransaction(const FrameTimelineInfo& info,
+ nsecs_t postTime) {
+ mCurrentState.frameTimelineInfo = info;
mCurrentState.postTime = postTime;
mCurrentState.modified = true;
setTransactionFlags(eTransactionNeeded);
+
+ if (const auto& bufferSurfaceFrameTX = mCurrentState.bufferSurfaceFrameTX;
+ bufferSurfaceFrameTX != nullptr) {
+ if (bufferSurfaceFrameTX->getToken() == info.vsyncId) {
+ // BufferSurfaceFrame takes precedence over BufferlessSurfaceFrame. If the same token is
+ // being used for BufferSurfaceFrame, don't create a new one.
+ return;
+ }
+ }
+ // For Transactions without a buffer, we create only one SurfaceFrame per vsyncId. If multiple
+ // transactions use the same vsyncId, we just treat them as one SurfaceFrame (unless they are
+ // targeting different vsyncs).
+ auto it = mCurrentState.bufferlessSurfaceFramesTX.find(info.vsyncId);
+ if (it == mCurrentState.bufferlessSurfaceFramesTX.end()) {
+ auto surfaceFrame = createSurfaceFrameForTransaction(info, postTime);
+ mCurrentState.bufferlessSurfaceFramesTX[info.vsyncId] = surfaceFrame;
+ } else {
+ if (it->second->getPresentState() == PresentState::Presented) {
+ // If the SurfaceFrame was already presented, its safe to overwrite it since it must
+ // have been from previous vsync.
+ it->second = createSurfaceFrameForTransaction(info, postTime);
+ }
+ }
+}
+
+void Layer::addSurfaceFrameDroppedForBuffer(
+ std::shared_ptr<frametimeline::SurfaceFrame>& surfaceFrame) {
+ surfaceFrame->setPresentState(PresentState::Dropped);
+ mFlinger->mFrameTimeline->addSurfaceFrame(surfaceFrame);
+}
+
+void Layer::addSurfaceFramePresentedForBuffer(
+ std::shared_ptr<frametimeline::SurfaceFrame>& surfaceFrame, nsecs_t acquireFenceTime,
+ nsecs_t currentLatchTime) {
+ surfaceFrame->setAcquireFenceTime(acquireFenceTime);
+ surfaceFrame->setPresentState(PresentState::Presented, mLastLatchTime);
+ mFlinger->mFrameTimeline->addSurfaceFrame(surfaceFrame);
+ mLastLatchTime = currentLatchTime;
+}
+
+std::shared_ptr<frametimeline::SurfaceFrame> Layer::createSurfaceFrameForTransaction(
+ const FrameTimelineInfo& info, nsecs_t postTime) {
+ auto surfaceFrame =
+ mFlinger->mFrameTimeline->createSurfaceFrameForToken(info, mOwnerPid, mOwnerUid, mName,
+ mTransactionName);
+ // For Transactions, the post time is considered to be both queue and acquire fence time.
+ surfaceFrame->setActualQueueTime(postTime);
+ surfaceFrame->setAcquireFenceTime(postTime);
+ onSurfaceFrameCreated(surfaceFrame);
+ return surfaceFrame;
+}
+
+std::shared_ptr<frametimeline::SurfaceFrame> Layer::createSurfaceFrameForBuffer(
+ const FrameTimelineInfo& info, nsecs_t queueTime, std::string debugName) {
+ auto surfaceFrame =
+ mFlinger->mFrameTimeline->createSurfaceFrameForToken(info, mOwnerPid, mOwnerUid, mName,
+ debugName);
+ // For buffers, acquire fence time will set during latch.
+ surfaceFrame->setActualQueueTime(queueTime);
+ // TODO(b/178542907): Implement onSurfaceFrameCreated for BQLayer as well.
+ onSurfaceFrameCreated(surfaceFrame);
+ return surfaceFrame;
}
Layer::FrameRate Layer::getFrameRateForLayerTree() const {
@@ -1523,12 +1609,6 @@
void Layer::deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber) {
ATRACE_CALL();
- if (mLayerDetached) {
- // If the layer is detached, then we don't defer this transaction since we will not
- // commit the pending state while the layer is detached. Adding sync points may cause
- // the barrier layer to wait for the states to be committed before dequeuing a buffer.
- return;
- }
mCurrentState.barrierLayer_legacy = barrierLayer;
mCurrentState.barrierFrameNumber = frameNumber;
@@ -1814,10 +1894,6 @@
}
void Layer::reparentChildren(const sp<Layer>& newParent) {
- if (attachChildren()) {
- setTransactionFlags(eTransactionNeeded);
- }
-
for (const sp<Layer>& child : mCurrentChildren) {
newParent->addChild(child);
}
@@ -1853,17 +1929,6 @@
}
bool Layer::reparent(const sp<IBinder>& newParentHandle) {
- bool callSetTransactionFlags = false;
-
- // While layers are detached, we allow most operations
- // and simply halt performing the actual transaction. However
- // for reparent != null we would enter the mRemovedFromCurrentState
- // state, regardless of whether doTransaction was called, and
- // so we need to prevent the update here.
- if (mLayerDetached && newParentHandle == nullptr) {
- return false;
- }
-
sp<Layer> newParent;
if (newParentHandle != nullptr) {
auto handle = static_cast<Handle*>(newParentHandle.get());
@@ -1890,52 +1955,13 @@
} else {
onRemovedFromCurrentState();
}
-
- if (mLayerDetached) {
- mLayerDetached = false;
- callSetTransactionFlags = true;
- }
} else {
onRemovedFromCurrentState();
}
- if (attachChildren() || callSetTransactionFlags) {
- setTransactionFlags(eTransactionNeeded);
- }
return true;
}
-bool Layer::detachChildren() {
- for (const sp<Layer>& child : mCurrentChildren) {
- sp<Client> parentClient = mClientRef.promote();
- sp<Client> client(child->mClientRef.promote());
- if (client != nullptr && parentClient != client) {
- child->mLayerDetached = true;
- child->detachChildren();
- child->removeRemoteSyncPoints();
- }
- }
-
- return true;
-}
-
-bool Layer::attachChildren() {
- bool changed = false;
- for (const sp<Layer>& child : mCurrentChildren) {
- sp<Client> parentClient = mClientRef.promote();
- sp<Client> client(child->mClientRef.promote());
- if (client != nullptr && parentClient != client) {
- if (child->mLayerDetached) {
- child->mLayerDetached = false;
- child->attachChildren();
- changed = true;
- }
- }
- }
-
- return changed;
-}
-
bool Layer::setColorTransform(const mat4& matrix) {
static const mat4 identityMatrix = mat4();
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 357c4a4..36ae19c 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -54,7 +54,7 @@
#include "Scheduler/Seamlessness.h"
#include "SurfaceFlinger.h"
#include "SurfaceTracing.h"
-#include "TransactionCompletedThread.h"
+#include "TransactionCallbackInvoker.h"
using namespace android::surfaceflinger;
@@ -304,11 +304,25 @@
// a fixed transform hint is not set.
ui::Transform::RotationFlags fixedTransformHint;
- // The vsync id that was used to start the transaction
- int64_t frameTimelineVsyncId;
+ // The vsync info that was used to start the transaction
+ FrameTimelineInfo frameTimelineInfo;
// When the transaction was posted
nsecs_t postTime;
+
+ // SurfaceFrame that tracks the timeline of Transactions that contain a Buffer. Only one
+ // such SurfaceFrame exists because only one buffer can be presented on the layer per vsync.
+ // If multiple buffers are queued, the prior ones will be dropped, along with the
+ // SurfaceFrame that's tracking them.
+ std::shared_ptr<frametimeline::SurfaceFrame> bufferSurfaceFrameTX;
+ // A map of token(frametimelineVsyncId) to the SurfaceFrame that's tracking a transaction
+ // that contains the token. Only one SurfaceFrame exisits for transactions that share the
+ // same token, unless they are presented in different vsyncs.
+ std::unordered_map<int64_t, std::shared_ptr<frametimeline::SurfaceFrame>>
+ bufferlessSurfaceFramesTX;
+ // An arbitrary threshold for the number of BufferlessSurfaceFrames in the state. Used to
+ // trigger a warning if the number of SurfaceFrames crosses the threshold.
+ static constexpr uint32_t kStateSurfaceFramesThreshold = 25;
};
/*
@@ -434,7 +448,6 @@
virtual bool setMetadata(const LayerMetadata& data);
virtual void setChildrenDrawingParent(const sp<Layer>&);
virtual bool reparent(const sp<IBinder>& newParentHandle);
- virtual bool detachChildren();
virtual bool setColorTransform(const mat4& matrix);
virtual mat4 getColorTransform() const;
virtual bool hasColorTransform() const;
@@ -448,7 +461,8 @@
virtual bool setBuffer(const sp<GraphicBuffer>& /*buffer*/, const sp<Fence>& /*acquireFence*/,
nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/,
bool /*isAutoTimestamp*/, const client_cache_t& /*clientCacheId*/,
- uint64_t /* frameNumber */, std::optional<nsecs_t> /* dequeueTime */) {
+ uint64_t /* frameNumber */, std::optional<nsecs_t> /* dequeueTime */,
+ const FrameTimelineInfo& /*info*/) {
return false;
};
virtual bool setAcquireFence(const sp<Fence>& /*fence*/) { return false; };
@@ -461,7 +475,6 @@
const std::vector<sp<CallbackHandle>>& /*handles*/) {
return false;
};
- virtual void forceSendCallbacks() {}
virtual bool addFrameEvent(const sp<Fence>& /*acquireFence*/, nsecs_t /*postedTime*/,
nsecs_t /*requestedPresentTime*/) {
return false;
@@ -613,6 +626,12 @@
virtual void pushPendingState();
+ /*
+ * Merges the BufferlessSurfaceFrames from source with the target. If the same token exists in
+ * both source and target, target's SurfaceFrame will be retained.
+ */
+ void mergeSurfaceFrames(State& source, State& target);
+
/**
* Returns active buffer size in the correct orientation. Buffer size is determined by undoing
* any buffer transformations. If the layer has no buffer then return INVALID_RECT.
@@ -666,8 +685,6 @@
bool reparentChildren(const sp<IBinder>& newParentHandle);
void reparentChildren(const sp<Layer>& newParent);
- bool attachChildren();
- bool isLayerDetached() const { return mLayerDetached; }
bool setShadowRadius(float shadowRadius);
// Before color management is introduced, contents on Android have to be
@@ -869,8 +886,21 @@
bool setFrameRate(FrameRate);
- virtual void setFrameTimelineVsyncForBuffer(int64_t /*frameTimelineVsyncId*/) {}
- void setFrameTimelineVsyncForTransaction(int64_t frameTimelineVsyncId, nsecs_t postTime);
+ virtual void setFrameTimelineInfoForBuffer(const FrameTimelineInfo& /*info*/) {}
+ void setFrameTimelineVsyncForBufferTransaction(const FrameTimelineInfo& info, nsecs_t postTime);
+ void setFrameTimelineVsyncForBufferlessTransaction(const FrameTimelineInfo& info,
+ nsecs_t postTime);
+
+ void addSurfaceFrameDroppedForBuffer(
+ std::shared_ptr<frametimeline::SurfaceFrame>& surfaceFrame);
+ void addSurfaceFramePresentedForBuffer(
+ std::shared_ptr<frametimeline::SurfaceFrame>& surfaceFrame, nsecs_t acquireFenceTime,
+ nsecs_t currentLatchTime);
+
+ std::shared_ptr<frametimeline::SurfaceFrame> createSurfaceFrameForTransaction(
+ const FrameTimelineInfo& info, nsecs_t postTime);
+ std::shared_ptr<frametimeline::SurfaceFrame> createSurfaceFrameForBuffer(
+ const FrameTimelineInfo& info, nsecs_t queueTime, std::string debugName);
// Creates a new handle each time, so we only expect
// this to be called once.
@@ -907,7 +937,6 @@
bool mPendingHWCDestroy{false};
bool backpressureEnabled() { return mDrawingState.flags & layer_state_t::eEnableBackpressure; }
- bool hasPendingBuffer() { return mCurrentState.buffer != mDrawingState.buffer; };
protected:
class SyncPoint {
@@ -975,6 +1004,7 @@
friend class TestableSurfaceFlinger;
friend class RefreshRateSelectionTest;
friend class SetFrameRateTest;
+ friend class TransactionSurfaceFrameTest;
virtual void setInitialValuesForClone(const sp<Layer>& clonedFrom);
virtual std::optional<compositionengine::LayerFE::LayerSettings> prepareClientComposition(
@@ -983,7 +1013,7 @@
const LayerFE::LayerSettings&, const Rect& layerStackRect,
ui::Dataspace outputDataspace);
virtual void preparePerFrameCompositionState();
- virtual void commitTransaction(const State& stateToCommit);
+ virtual void commitTransaction(State& stateToCommit);
virtual bool applyPendingStates(State* stateToCommit);
virtual uint32_t doTransactionResize(uint32_t flags, Layer::State* stateToCommit);
virtual void onSurfaceFrameCreated(const std::shared_ptr<frametimeline::SurfaceFrame>&) {}
@@ -1103,8 +1133,6 @@
wp<Layer> mDrawingParent;
// Can only be accessed with the SF state lock held.
- bool mLayerDetached{false};
- // Can only be accessed with the SF state lock held.
bool mChildrenChanged{false};
// Window types from WindowManager.LayoutParams
@@ -1121,6 +1149,10 @@
// If created from a system process, the value can be passed in.
pid_t mOwnerPid;
+ // Keeps track of the time SF latched the last buffer from this layer.
+ // Used in buffer stuffing analysis in FrameTimeline.
+ nsecs_t mLastLatchTime = 0;
+
private:
virtual void setTransformHint(ui::Transform::RotationFlags) {}
diff --git a/services/surfaceflinger/OWNERS b/services/surfaceflinger/OWNERS
index f273725..43a6e55 100644
--- a/services/surfaceflinger/OWNERS
+++ b/services/surfaceflinger/OWNERS
@@ -1,8 +1,6 @@
adyabr@google.com
-akrulec@google.com
alecmouri@google.com
chaviw@google.com
lpy@google.com
racarr@google.com
-stoza@google.com
vishnun@google.com
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
index 9230e72..49ffc81 100644
--- a/services/surfaceflinger/RefreshRateOverlay.cpp
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -238,7 +238,7 @@
auto buffer = getOrCreateBuffers(*mCurrentFps)[mFrame];
mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, true, {},
mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */),
- std::nullopt /* dequeueTime */);
+ std::nullopt /* dequeueTime */, FrameTimelineInfo{});
mFlinger.mTransactionFlags.fetch_or(eTransactionMask);
}
@@ -251,7 +251,7 @@
auto buffer = buffers[mFrame];
mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, true, {},
mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */),
- std::nullopt /* dequeueTime */);
+ std::nullopt /* dequeueTime */, FrameTimelineInfo{});
mFlinger.mTransactionFlags.fetch_or(eTransactionMask);
}
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 19b3d6e..9186538 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -451,7 +451,7 @@
const sp<SyncScreenCaptureListener> captureListener = new SyncScreenCaptureListener();
mFlinger.captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer,
- true /* regionSampling */, captureListener);
+ true /* regionSampling */, false /* grayscale */, captureListener);
ScreenCaptureResults captureResults = captureListener->waitForResults();
std::vector<Descriptor> activeDescriptors;
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index c12a7b1..ba43e70 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -90,9 +90,9 @@
return StringPrintf("VSync{displayId=%s, count=%u, expectedVSyncTimestamp=%" PRId64 "}",
to_string(event.header.displayId).c_str(), event.vsync.count,
event.vsync.expectedVSyncTimestamp);
- case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED:
- return StringPrintf("ConfigChanged{displayId=%s, configId=%u}",
- to_string(event.header.displayId).c_str(), event.config.configId);
+ case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE:
+ return StringPrintf("ModeChanged{displayId=%s, modeId=%u}",
+ to_string(event.header.displayId).c_str(), event.modeChange.modeId);
default:
return "Event{}";
}
@@ -118,12 +118,12 @@
return event;
}
-DisplayEventReceiver::Event makeConfigChanged(PhysicalDisplayId displayId, DisplayModeId configId,
- nsecs_t vsyncPeriod) {
+DisplayEventReceiver::Event makeModeChanged(PhysicalDisplayId displayId, DisplayModeId modeId,
+ nsecs_t vsyncPeriod) {
DisplayEventReceiver::Event event;
- event.header = {DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED, displayId, systemTime()};
- event.config.configId = configId.value();
- event.config.vsyncPeriod = vsyncPeriod;
+ event.header = {DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE, displayId, systemTime()};
+ event.modeChange.modeId = modeId.value();
+ event.modeChange.vsyncPeriod = vsyncPeriod;
return event;
}
@@ -369,11 +369,11 @@
mCondition.notify_all();
}
-void EventThread::onConfigChanged(PhysicalDisplayId displayId, DisplayModeId configId,
- nsecs_t vsyncPeriod) {
+void EventThread::onModeChanged(PhysicalDisplayId displayId, DisplayModeId modeId,
+ nsecs_t vsyncPeriod) {
std::lock_guard<std::mutex> lock(mMutex);
- mPendingEvents.push_back(makeConfigChanged(displayId, configId, vsyncPeriod));
+ mPendingEvents.push_back(makeModeChanged(displayId, modeId, vsyncPeriod));
mCondition.notify_all();
}
@@ -514,9 +514,9 @@
case DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG:
return true;
- case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED: {
+ case DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE: {
return connection->mEventRegistration.test(
- ISurfaceComposer::EventRegistration::configChanged);
+ ISurfaceComposer::EventRegistration::modeChanged);
}
case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index 15efe21..3540604 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -123,9 +123,9 @@
virtual void onHotplugReceived(PhysicalDisplayId displayId, bool connected) = 0;
- // called when SF changes the active config and apps needs to be notified about the change
- virtual void onConfigChanged(PhysicalDisplayId displayId, DisplayModeId configId,
- nsecs_t vsyncPeriod) = 0;
+ // called when SF changes the active mode and apps needs to be notified about the change
+ virtual void onModeChanged(PhysicalDisplayId displayId, DisplayModeId modeId,
+ nsecs_t vsyncPeriod) = 0;
// called when SF updates the Frame Rate Override list
virtual void onFrameRateOverridesChanged(PhysicalDisplayId displayId,
@@ -173,8 +173,8 @@
void onHotplugReceived(PhysicalDisplayId displayId, bool connected) override;
- void onConfigChanged(PhysicalDisplayId displayId, DisplayModeId configId,
- nsecs_t vsyncPeriod) override;
+ void onModeChanged(PhysicalDisplayId displayId, DisplayModeId modeId,
+ nsecs_t vsyncPeriod) override;
void onFrameRateOverridesChanged(PhysicalDisplayId displayId,
std::vector<FrameRateOverride> overrides) override;
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index 7ef531d..ea92ad8 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -102,7 +102,7 @@
LOG_FATAL_IF(it == mLayerInfos.end(), "%s: unknown layer %p", __FUNCTION__, layer);
const auto& info = it->second;
- info->setLastPresentTime(presentTime, now, updateType, mConfigChangePending);
+ info->setLastPresentTime(presentTime, now, updateType, mModeChangePending);
// Activate layer if inactive.
if (const auto end = activeLayers().end(); it >= end) {
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h
index bae9b5a..05ecc70 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.h
+++ b/services/surfaceflinger/Scheduler/LayerHistory.h
@@ -51,8 +51,8 @@
// Sets the display size. Client is responsible for synchronization.
void setDisplayArea(uint32_t displayArea) { mDisplayArea = displayArea; }
- // Sets whether a config change is pending to be applied
- void setConfigChangePending(bool pending) { mConfigChangePending = pending; }
+ // Sets whether a mode change is pending to be applied
+ void setModeChangePending(bool pending) { mModeChangePending = pending; }
// Represents which layer activity is recorded
enum class LayerUpdateType {
@@ -109,8 +109,8 @@
// Whether to use priority sent from WindowManager to determine the relevancy of the layer.
const bool mUseFrameRatePriority;
- // Whether a config change is in progress or not
- std::atomic<bool> mConfigChangePending = false;
+ // Whether a mode change is in progress or not
+ std::atomic<bool> mModeChangePending = false;
};
} // namespace scheduler
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp
index 4324855..4b4cdae 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.cpp
+++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp
@@ -44,7 +44,7 @@
mRefreshRateHistory(name) {}
void LayerInfo::setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now, LayerUpdateType updateType,
- bool pendingConfigChange) {
+ bool pendingModeChange) {
lastPresentTime = std::max(lastPresentTime, static_cast<nsecs_t>(0));
mLastUpdatedTime = std::max(lastPresentTime, now);
@@ -56,7 +56,7 @@
case LayerUpdateType::Buffer:
FrameTimeData frameTime = {.presentTime = lastPresentTime,
.queueTime = mLastUpdatedTime,
- .pendingConfigChange = pendingConfigChange};
+ .pendingModeChange = pendingModeChange};
mFrameTimes.push_back(frameTime);
if (mFrameTimes.size() > HISTORY_SIZE) {
mFrameTimes.pop_front();
@@ -124,11 +124,11 @@
}
std::optional<nsecs_t> LayerInfo::calculateAverageFrameTime() const {
- // Ignore frames captured during a config change
- const bool isDuringConfigChange =
+ // Ignore frames captured during a mode change
+ const bool isDuringModeChange =
std::any_of(mFrameTimes.begin(), mFrameTimes.end(),
- [](auto frame) { return frame.pendingConfigChange; });
- if (isDuringConfigChange) {
+ [](const auto& frame) { return frame.pendingModeChange; });
+ if (isDuringModeChange) {
return std::nullopt;
}
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h
index e32ba09..40c0214 100644
--- a/services/surfaceflinger/Scheduler/LayerInfo.h
+++ b/services/surfaceflinger/Scheduler/LayerInfo.h
@@ -80,7 +80,7 @@
// the layer was last updated. If the present time is farther in the future than the
// updated time, the updated time is the present time.
void setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now, LayerUpdateType updateType,
- bool pendingConfigChange);
+ bool pendingModeChange);
// Sets an explicit layer vote. This usually comes directly from the application via
// ANativeWindow_setFrameRate API
@@ -124,7 +124,7 @@
struct FrameTimeData {
nsecs_t presentTime; // desiredPresentTime, if provided
nsecs_t queueTime; // buffer queue time
- bool pendingConfigChange;
+ bool pendingModeChange;
};
// Holds information about the calculated and reported refresh rate
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index 81ffe0f..e7a44a7 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -40,13 +40,13 @@
to_string(layer.desiredRefreshRate).c_str());
}
-std::vector<Fps> constructKnownFrameRates(const DisplayModes& configs) {
+std::vector<Fps> constructKnownFrameRates(const DisplayModes& modes) {
std::vector<Fps> knownFrameRates = {Fps(24.0f), Fps(30.0f), Fps(45.0f), Fps(60.0f), Fps(72.0f)};
- knownFrameRates.reserve(knownFrameRates.size() + configs.size());
+ knownFrameRates.reserve(knownFrameRates.size() + modes.size());
// Add all supported refresh rates to the set
- for (const auto& config : configs) {
- const auto refreshRate = Fps::fromPeriodNsecs(config->getVsyncPeriod());
+ for (const auto& mode : modes) {
+ const auto refreshRate = Fps::fromPeriodNsecs(mode->getVsyncPeriod());
knownFrameRates.emplace_back(refreshRate);
}
@@ -65,8 +65,8 @@
std::string RefreshRate::toString() const {
return base::StringPrintf("{id=%zu, hwcId=%d, fps=%.2f, width=%d, height=%d group=%d}",
- getConfigId().value(), hwcConfig->getHwcId(), getFps().getValue(),
- hwcConfig->getWidth(), hwcConfig->getHeight(), getConfigGroup());
+ getModeId().value(), mode->getHwcId(), getFps().getValue(),
+ mode->getWidth(), mode->getHeight(), getModeGroup());
}
std::string RefreshRateConfigs::layerVoteTypeString(LayerVoteType vote) {
@@ -89,9 +89,9 @@
}
std::string RefreshRateConfigs::Policy::toString() const {
- return base::StringPrintf("default config ID: %zu, allowGroupSwitching = %d"
+ return base::StringPrintf("default mode ID: %zu, allowGroupSwitching = %d"
", primary range: %s, app request range: %s",
- defaultConfig.value(), allowGroupSwitching,
+ defaultMode.value(), allowGroupSwitching,
primaryRange.toString().c_str(), appRequestRange.toString().c_str());
}
@@ -291,7 +291,7 @@
scores.emplace_back(RefreshRateScore{refreshRate, 0.0f});
}
- const auto& defaultConfig = mRefreshRates.at(policy->defaultConfig);
+ const auto& defaultMode = mRefreshRates.at(policy->defaultMode);
for (const auto& layer : layers) {
ALOGV("Calculating score for %s (%s, weight %.2f)", layer.name.c_str(),
@@ -303,11 +303,11 @@
auto weight = layer.weight;
for (auto i = 0u; i < scores.size(); i++) {
- const bool isSeamlessSwitch = scores[i].refreshRate->getConfigGroup() ==
- mCurrentRefreshRate->getConfigGroup();
+ const bool isSeamlessSwitch =
+ scores[i].refreshRate->getModeGroup() == mCurrentRefreshRate->getModeGroup();
if (layer.seamlessness == Seamlessness::OnlySeamless && !isSeamlessSwitch) {
- ALOGV("%s ignores %s to avoid non-seamless switch. Current config = %s",
+ ALOGV("%s ignores %s to avoid non-seamless switch. Current mode = %s",
formatLayerInfo(layer, weight).c_str(),
scores[i].refreshRate->toString().c_str(),
mCurrentRefreshRate->toString().c_str());
@@ -317,26 +317,25 @@
if (layer.seamlessness == Seamlessness::SeamedAndSeamless && !isSeamlessSwitch &&
!layer.focused) {
ALOGV("%s ignores %s because it's not focused and the switch is going to be seamed."
- " Current config = %s",
+ " Current mode = %s",
formatLayerInfo(layer, weight).c_str(),
scores[i].refreshRate->toString().c_str(),
mCurrentRefreshRate->toString().c_str());
continue;
}
- // Layers with default seamlessness vote for the current config group if
+ // Layers with default seamlessness vote for the current mode group if
// there are layers with seamlessness=SeamedAndSeamless and for the default
- // config group otherwise. In second case, if the current config group is different
+ // mode group otherwise. In second case, if the current mode group is different
// from the default, this means a layer with seamlessness=SeamedAndSeamless has just
// disappeared.
const bool isInPolicyForDefault = seamedLayers > 0
- ? scores[i].refreshRate->getConfigGroup() ==
- mCurrentRefreshRate->getConfigGroup()
- : scores[i].refreshRate->getConfigGroup() == defaultConfig->getConfigGroup();
+ ? scores[i].refreshRate->getModeGroup() == mCurrentRefreshRate->getModeGroup()
+ : scores[i].refreshRate->getModeGroup() == defaultMode->getModeGroup();
if (layer.seamlessness == Seamlessness::Default && !isInPolicyForDefault &&
!layer.focused) {
- ALOGV("%s ignores %s. Current config = %s", formatLayerInfo(layer, weight).c_str(),
+ ALOGV("%s ignores %s. Current mode = %s", formatLayerInfo(layer, weight).c_str(),
scores[i].refreshRate->toString().c_str(),
mCurrentRefreshRate->toString().c_str());
continue;
@@ -548,12 +547,12 @@
const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicyLocked() const {
for (auto refreshRate : mPrimaryRefreshRates) {
- if (mCurrentRefreshRate->getConfigGroup() == refreshRate->getConfigGroup()) {
+ if (mCurrentRefreshRate->getModeGroup() == refreshRate->getModeGroup()) {
return *refreshRate;
}
}
- ALOGE("Can't find min refresh rate by policy with the same config group"
- " as the current config %s",
+ ALOGE("Can't find min refresh rate by policy with the same mode group"
+ " as the current mode %s",
mCurrentRefreshRate->toString().c_str());
// Defaulting to the lowest refresh rate
return *mPrimaryRefreshRates.front();
@@ -567,12 +566,12 @@
const RefreshRate& RefreshRateConfigs::getMaxRefreshRateByPolicyLocked() const {
for (auto it = mPrimaryRefreshRates.rbegin(); it != mPrimaryRefreshRates.rend(); it++) {
const auto& refreshRate = (**it);
- if (mCurrentRefreshRate->getConfigGroup() == refreshRate.getConfigGroup()) {
+ if (mCurrentRefreshRate->getModeGroup() == refreshRate.getModeGroup()) {
return refreshRate;
}
}
- ALOGE("Can't find max refresh rate by policy with the same config group"
- " as the current config %s",
+ ALOGE("Can't find max refresh rate by policy with the same mode group"
+ " as the current mode %s",
mCurrentRefreshRate->toString().c_str());
// Defaulting to the highest refresh rate
return *mPrimaryRefreshRates.back();
@@ -593,50 +592,50 @@
mCurrentRefreshRate) != mAppRequestRefreshRates.end()) {
return *mCurrentRefreshRate;
}
- return *mRefreshRates.at(getCurrentPolicyLocked()->defaultConfig);
+ return *mRefreshRates.at(getCurrentPolicyLocked()->defaultMode);
}
-void RefreshRateConfigs::setCurrentConfigId(DisplayModeId configId) {
+void RefreshRateConfigs::setCurrentModeId(DisplayModeId modeId) {
std::lock_guard lock(mLock);
- mCurrentRefreshRate = mRefreshRates.at(configId).get();
+ mCurrentRefreshRate = mRefreshRates.at(modeId).get();
}
-RefreshRateConfigs::RefreshRateConfigs(const DisplayModes& configs, DisplayModeId currentConfigId,
+RefreshRateConfigs::RefreshRateConfigs(const DisplayModes& modes, DisplayModeId currentModeId,
bool enableFrameRateOverride)
- : mKnownFrameRates(constructKnownFrameRates(configs)),
+ : mKnownFrameRates(constructKnownFrameRates(modes)),
mEnableFrameRateOverride(enableFrameRateOverride) {
- updateDisplayConfigs(configs, currentConfigId);
+ updateDisplayModes(modes, currentModeId);
}
-void RefreshRateConfigs::updateDisplayConfigs(const DisplayModes& configs,
- DisplayModeId currentConfigId) {
+void RefreshRateConfigs::updateDisplayModes(const DisplayModes& modes,
+ DisplayModeId currentModeId) {
std::lock_guard lock(mLock);
- LOG_ALWAYS_FATAL_IF(configs.empty());
- LOG_ALWAYS_FATAL_IF(currentConfigId.value() >= configs.size());
+ LOG_ALWAYS_FATAL_IF(modes.empty());
+ LOG_ALWAYS_FATAL_IF(currentModeId.value() >= modes.size());
mRefreshRates.clear();
- for (const auto& config : configs) {
- const auto configId = config->getId();
- const auto fps = Fps::fromPeriodNsecs(config->getVsyncPeriod());
- mRefreshRates.emplace(configId,
- std::make_unique<RefreshRate>(configId, config, fps,
+ for (const auto& mode : modes) {
+ const auto modeId = mode->getId();
+ const auto fps = Fps::fromPeriodNsecs(mode->getVsyncPeriod());
+ mRefreshRates.emplace(modeId,
+ std::make_unique<RefreshRate>(modeId, mode, fps,
RefreshRate::ConstructorTag(0)));
- if (configId == currentConfigId) {
- mCurrentRefreshRate = mRefreshRates.at(configId).get();
+ if (modeId == currentModeId) {
+ mCurrentRefreshRate = mRefreshRates.at(modeId).get();
}
}
- std::vector<const RefreshRate*> sortedConfigs;
- getSortedRefreshRateListLocked([](const RefreshRate&) { return true; }, &sortedConfigs);
- mDisplayManagerPolicy.defaultConfig = currentConfigId;
- mMinSupportedRefreshRate = sortedConfigs.front();
- mMaxSupportedRefreshRate = sortedConfigs.back();
+ std::vector<const RefreshRate*> sortedModes;
+ getSortedRefreshRateListLocked([](const RefreshRate&) { return true; }, &sortedModes);
+ mDisplayManagerPolicy.defaultMode = currentModeId;
+ mMinSupportedRefreshRate = sortedModes.front();
+ mMaxSupportedRefreshRate = sortedModes.back();
mSupportsFrameRateOverride = false;
if (mEnableFrameRateOverride) {
- for (const auto& config1 : sortedConfigs) {
- for (const auto& config2 : sortedConfigs) {
- if (getFrameRateDivider(config1->getFps(), config2->getFps()) >= 2) {
+ for (const auto& mode1 : sortedModes) {
+ for (const auto& mode2 : sortedModes) {
+ if (getFrameRateDivider(mode1->getFps(), mode2->getFps()) >= 2) {
mSupportsFrameRateOverride = true;
break;
}
@@ -648,15 +647,15 @@
}
bool RefreshRateConfigs::isPolicyValidLocked(const Policy& policy) const {
- // defaultConfig must be a valid config, and within the given refresh rate range.
- auto iter = mRefreshRates.find(policy.defaultConfig);
+ // defaultMode must be a valid mode, and within the given refresh rate range.
+ auto iter = mRefreshRates.find(policy.defaultMode);
if (iter == mRefreshRates.end()) {
- ALOGE("Default config is not found.");
+ ALOGE("Default mode is not found.");
return false;
}
const RefreshRate& refreshRate = *iter->second;
if (!refreshRate.inPolicy(policy.primaryRange.min, policy.primaryRange.max)) {
- ALOGE("Default config is not in the primary range.");
+ ALOGE("Default mode is not in the primary range.");
return false;
}
return policy.appRequestRange.min.lessThanOrEqualWithMargin(policy.primaryRange.min) &&
@@ -706,10 +705,10 @@
return mDisplayManagerPolicy;
}
-bool RefreshRateConfigs::isConfigAllowed(DisplayModeId config) const {
+bool RefreshRateConfigs::isModeAllowed(DisplayModeId modeId) const {
std::lock_guard lock(mLock);
for (const RefreshRate* refreshRate : mAppRequestRefreshRates) {
- if (refreshRate->configId == config) {
+ if (refreshRate->modeId == modeId) {
return true;
}
}
@@ -723,60 +722,59 @@
outRefreshRates->reserve(mRefreshRates.size());
for (const auto& [type, refreshRate] : mRefreshRates) {
if (shouldAddRefreshRate(*refreshRate)) {
- ALOGV("getSortedRefreshRateListLocked: config %zu added to list policy",
- refreshRate->configId.value());
+ ALOGV("getSortedRefreshRateListLocked: mode %zu added to list policy",
+ refreshRate->modeId.value());
outRefreshRates->push_back(refreshRate.get());
}
}
std::sort(outRefreshRates->begin(), outRefreshRates->end(),
[](const auto refreshRate1, const auto refreshRate2) {
- if (refreshRate1->hwcConfig->getVsyncPeriod() !=
- refreshRate2->hwcConfig->getVsyncPeriod()) {
- return refreshRate1->hwcConfig->getVsyncPeriod() >
- refreshRate2->hwcConfig->getVsyncPeriod();
+ if (refreshRate1->mode->getVsyncPeriod() !=
+ refreshRate2->mode->getVsyncPeriod()) {
+ return refreshRate1->mode->getVsyncPeriod() >
+ refreshRate2->mode->getVsyncPeriod();
} else {
- return refreshRate1->hwcConfig->getConfigGroup() >
- refreshRate2->hwcConfig->getConfigGroup();
+ return refreshRate1->mode->getGroup() > refreshRate2->mode->getGroup();
}
});
}
void RefreshRateConfigs::constructAvailableRefreshRates() {
- // Filter configs based on current policy and sort based on vsync period
+ // Filter modes based on current policy and sort based on vsync period
const Policy* policy = getCurrentPolicyLocked();
- const auto& defaultConfig = mRefreshRates.at(policy->defaultConfig)->hwcConfig;
+ const auto& defaultMode = mRefreshRates.at(policy->defaultMode)->mode;
ALOGV("constructAvailableRefreshRates: %s ", policy->toString().c_str());
- auto filterRefreshRates = [&](Fps min, Fps max, const char* listName,
- std::vector<const RefreshRate*>*
- outRefreshRates) REQUIRES(mLock) {
- getSortedRefreshRateListLocked(
- [&](const RefreshRate& refreshRate) REQUIRES(mLock) {
- const auto& hwcConfig = refreshRate.hwcConfig;
+ auto filterRefreshRates =
+ [&](Fps min, Fps max, const char* listName,
+ std::vector<const RefreshRate*>* outRefreshRates) REQUIRES(mLock) {
+ getSortedRefreshRateListLocked(
+ [&](const RefreshRate& refreshRate) REQUIRES(mLock) {
+ const auto& mode = refreshRate.mode;
- return hwcConfig->getHeight() == defaultConfig->getHeight() &&
- hwcConfig->getWidth() == defaultConfig->getWidth() &&
- hwcConfig->getDpiX() == defaultConfig->getDpiX() &&
- hwcConfig->getDpiY() == defaultConfig->getDpiY() &&
- (policy->allowGroupSwitching ||
- hwcConfig->getConfigGroup() == defaultConfig->getConfigGroup()) &&
- refreshRate.inPolicy(min, max);
- },
- outRefreshRates);
+ return mode->getHeight() == defaultMode->getHeight() &&
+ mode->getWidth() == defaultMode->getWidth() &&
+ mode->getDpiX() == defaultMode->getDpiX() &&
+ mode->getDpiY() == defaultMode->getDpiY() &&
+ (policy->allowGroupSwitching ||
+ mode->getGroup() == defaultMode->getGroup()) &&
+ refreshRate.inPolicy(min, max);
+ },
+ outRefreshRates);
- LOG_ALWAYS_FATAL_IF(outRefreshRates->empty(),
- "No matching configs for %s range: min=%s max=%s", listName,
- to_string(min).c_str(), to_string(max).c_str());
- auto stringifyRefreshRates = [&]() -> std::string {
- std::string str;
- for (auto refreshRate : *outRefreshRates) {
- base::StringAppendF(&str, "%s ", refreshRate->getName().c_str());
- }
- return str;
- };
- ALOGV("%s refresh rates: %s", listName, stringifyRefreshRates().c_str());
- };
+ LOG_ALWAYS_FATAL_IF(outRefreshRates->empty(),
+ "No matching modes for %s range: min=%s max=%s", listName,
+ to_string(min).c_str(), to_string(max).c_str());
+ auto stringifyRefreshRates = [&]() -> std::string {
+ std::string str;
+ for (auto refreshRate : *outRefreshRates) {
+ base::StringAppendF(&str, "%s ", refreshRate->getName().c_str());
+ }
+ return str;
+ };
+ ALOGV("%s refresh rates: %s", listName, stringifyRefreshRates().c_str());
+ };
filterRefreshRates(policy->primaryRange.min, policy->primaryRange.max, "primary",
&mPrimaryRefreshRates);
@@ -845,20 +843,20 @@
void RefreshRateConfigs::dump(std::string& result) const {
std::lock_guard lock(mLock);
- base::StringAppendF(&result, "DesiredDisplayConfigSpecs (DisplayManager): %s\n\n",
+ base::StringAppendF(&result, "DesiredDisplayModeSpecs (DisplayManager): %s\n\n",
mDisplayManagerPolicy.toString().c_str());
scheduler::RefreshRateConfigs::Policy currentPolicy = *getCurrentPolicyLocked();
if (mOverridePolicy && currentPolicy != mDisplayManagerPolicy) {
- base::StringAppendF(&result, "DesiredDisplayConfigSpecs (Override): %s\n\n",
+ base::StringAppendF(&result, "DesiredDisplayModeSpecs (Override): %s\n\n",
currentPolicy.toString().c_str());
}
- auto config = mCurrentRefreshRate->hwcConfig;
- base::StringAppendF(&result, "Current config: %s\n", mCurrentRefreshRate->toString().c_str());
+ auto mode = mCurrentRefreshRate->mode;
+ base::StringAppendF(&result, "Current mode: %s\n", mCurrentRefreshRate->toString().c_str());
result.append("Refresh rates:\n");
for (const auto& [id, refreshRate] : mRefreshRates) {
- config = refreshRate->hwcConfig;
+ mode = refreshRate->mode;
base::StringAppendF(&result, "\t%s\n", refreshRate->toString().c_str());
}
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index 0c7dc05..2bc22b4 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -64,12 +64,12 @@
};
public:
- RefreshRate(DisplayModeId configId, DisplayModePtr config, Fps fps, ConstructorTag)
- : configId(configId), hwcConfig(config), fps(std::move(fps)) {}
+ RefreshRate(DisplayModeId modeId, DisplayModePtr mode, Fps fps, ConstructorTag)
+ : modeId(modeId), mode(mode), fps(std::move(fps)) {}
- DisplayModeId getConfigId() const { return configId; }
- nsecs_t getVsyncPeriod() const { return hwcConfig->getVsyncPeriod(); }
- int32_t getConfigGroup() const { return hwcConfig->getConfigGroup(); }
+ DisplayModeId getModeId() const { return modeId; }
+ nsecs_t getVsyncPeriod() const { return mode->getVsyncPeriod(); }
+ int32_t getModeGroup() const { return mode->getGroup(); }
std::string getName() const { return to_string(fps); }
Fps getFps() const { return fps; }
@@ -81,7 +81,7 @@
}
bool operator!=(const RefreshRate& other) const {
- return configId != other.configId || hwcConfig != other.hwcConfig;
+ return modeId != other.modeId || mode != other.mode;
}
bool operator<(const RefreshRate& other) const {
@@ -99,11 +99,8 @@
friend RefreshRateConfigs;
friend class RefreshRateConfigsTest;
- // This config ID corresponds to the position of the config in the vector that is stored
- // on the device.
- const DisplayModeId configId;
- // The config itself
- DisplayModePtr hwcConfig;
+ const DisplayModeId modeId;
+ DisplayModePtr mode;
// Refresh rate in frames per second
const Fps fps{0.0f};
};
@@ -131,16 +128,16 @@
static constexpr int kAllowGroupSwitchingDefault = false;
public:
- // The default config, used to ensure we only initiate display config switches within the
- // same config group as defaultConfigId's group.
- DisplayModeId defaultConfig;
- // Whether or not we switch config groups to get the best frame rate.
+ // The default mode, used to ensure we only initiate display mode switches within the
+ // same mode group as defaultMode's group.
+ DisplayModeId defaultMode;
+ // Whether or not we switch mode groups to get the best frame rate.
bool allowGroupSwitching = kAllowGroupSwitchingDefault;
// The primary refresh rate range represents display manager's general guidance on the
- // display configs we'll consider when switching refresh rates. Unless we get an explicit
+ // display modes we'll consider when switching refresh rates. Unless we get an explicit
// signal from an app, we should stay within this range.
FpsRange primaryRange;
- // The app request refresh rate range allows us to consider more display configs when
+ // 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
@@ -150,25 +147,25 @@
Policy() = default;
- Policy(DisplayModeId defaultConfig, const FpsRange& range)
- : Policy(defaultConfig, kAllowGroupSwitchingDefault, range, range) {}
+ Policy(DisplayModeId defaultMode, const FpsRange& range)
+ : Policy(defaultMode, kAllowGroupSwitchingDefault, range, range) {}
- Policy(DisplayModeId defaultConfig, bool allowGroupSwitching, const FpsRange& range)
- : Policy(defaultConfig, allowGroupSwitching, range, range) {}
+ Policy(DisplayModeId defaultMode, bool allowGroupSwitching, const FpsRange& range)
+ : Policy(defaultMode, allowGroupSwitching, range, range) {}
- Policy(DisplayModeId defaultConfig, const FpsRange& primaryRange,
+ Policy(DisplayModeId defaultMode, const FpsRange& primaryRange,
const FpsRange& appRequestRange)
- : Policy(defaultConfig, kAllowGroupSwitchingDefault, primaryRange, appRequestRange) {}
+ : Policy(defaultMode, kAllowGroupSwitchingDefault, primaryRange, appRequestRange) {}
- Policy(DisplayModeId defaultConfig, bool allowGroupSwitching, const FpsRange& primaryRange,
+ Policy(DisplayModeId defaultMode, bool allowGroupSwitching, const FpsRange& primaryRange,
const FpsRange& appRequestRange)
- : defaultConfig(defaultConfig),
+ : defaultMode(defaultMode),
allowGroupSwitching(allowGroupSwitching),
primaryRange(primaryRange),
appRequestRange(appRequestRange) {}
bool operator==(const Policy& other) const {
- return defaultConfig == other.defaultConfig && primaryRange == other.primaryRange &&
+ return defaultMode == other.defaultMode && primaryRange == other.primaryRange &&
appRequestRange == other.appRequestRange &&
allowGroupSwitching == other.allowGroupSwitching;
}
@@ -200,8 +197,8 @@
// Gets the display manager policy, regardless of whether an override policy is active.
Policy getDisplayManagerPolicy() const EXCLUDES(mLock);
- // Returns true if config is allowed by the current policy.
- bool isConfigAllowed(DisplayModeId config) const EXCLUDES(mLock);
+ // Returns true if mode is allowed by the current policy.
+ bool isModeAllowed(DisplayModeId) const EXCLUDES(mLock);
// Describes the different options the layer voted for refresh rate
enum class LayerVoteType {
@@ -270,7 +267,7 @@
return {mMinSupportedRefreshRate->getFps(), mMaxSupportedRefreshRate->getFps()};
}
- std::optional<Fps> onKernelTimerChanged(std::optional<DisplayModeId> desiredActiveConfigId,
+ std::optional<Fps> onKernelTimerChanged(std::optional<DisplayModeId> desiredActiveModeId,
bool timerExpired) const EXCLUDES(mLock);
// Returns the highest refresh rate according to the current policy. May change at runtime. Only
@@ -286,14 +283,14 @@
// Returns the refresh rate that corresponds to a DisplayModeId. This may change at
// runtime.
- // TODO(b/159590486) An invalid config id may be given here if the dipslay configs have changed.
- RefreshRate getRefreshRateFromConfigId(DisplayModeId configId) const EXCLUDES(mLock) {
+ // TODO(b/159590486) An invalid mode id may be given here if the dipslay modes have changed.
+ RefreshRate getRefreshRateFromModeId(DisplayModeId modeId) const EXCLUDES(mLock) {
std::lock_guard lock(mLock);
- return *mRefreshRates.at(configId);
+ return *mRefreshRates.at(modeId);
};
- // Stores the current configId the device operates at
- void setCurrentConfigId(DisplayModeId configId) EXCLUDES(mLock);
+ // Stores the current modeId the device operates at
+ void setCurrentModeId(DisplayModeId) EXCLUDES(mLock);
// Returns a string that represents the layer vote type
static std::string layerVoteTypeString(LayerVoteType vote);
@@ -301,14 +298,13 @@
// Returns a known frame rate that is the closest to frameRate
Fps findClosestKnownFrameRate(Fps frameRate) const;
- RefreshRateConfigs(const DisplayModes& configs, DisplayModeId currentConfigId,
+ RefreshRateConfigs(const DisplayModes& modes, DisplayModeId currentModeId,
bool enableFrameRateOverride = false);
- void updateDisplayConfigs(const DisplayModes& configs, DisplayModeId currentConfig)
- EXCLUDES(mLock);
+ void updateDisplayModes(const DisplayModes& mode, DisplayModeId currentModeId) EXCLUDES(mLock);
- // Returns whether switching configs (refresh rate or resolution) is possible.
- // TODO(b/158780872): Consider HAL support, and skip frame rate detection if the configs only
+ // Returns whether switching modes (refresh rate or resolution) is possible.
+ // TODO(b/158780872): Consider HAL support, and skip frame rate detection if the modes only
// differ in resolution.
bool canSwitch() const EXCLUDES(mLock) {
std::lock_guard lock(mLock);
@@ -387,7 +383,7 @@
float calculateLayerScoreLocked(const LayerRequirement&, const RefreshRate&,
bool isSeamlessSwitch) const REQUIRES(mLock);
- // The list of refresh rates, indexed by display config ID. This may change after this
+ // The list of refresh rates, indexed by display modes ID. This may change after this
// object is initialized.
AllRefreshRatesMapType mRefreshRates GUARDED_BY(mLock);
@@ -399,7 +395,7 @@
// vsyncPeriod (the first element is the lowest refresh rate).
std::vector<const RefreshRate*> mAppRequestRefreshRates GUARDED_BY(mLock);
- // The current config. This will change at runtime. This is set by SurfaceFlinger on
+ // The current display mode. This will change at runtime. This is set by SurfaceFlinger on
// the main thread, and read by the Scheduler (and other objects) on other threads.
const RefreshRate* mCurrentRefreshRate GUARDED_BY(mLock);
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index d861209..9813270 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -348,55 +348,53 @@
thread->onFrameRateOverridesChanged(displayId, std::move(overrides));
}
-void Scheduler::onPrimaryDisplayConfigChanged(ConnectionHandle handle, PhysicalDisplayId displayId,
- DisplayModeId configId, nsecs_t vsyncPeriod) {
+void Scheduler::onPrimaryDisplayModeChanged(ConnectionHandle handle, PhysicalDisplayId displayId,
+ DisplayModeId modeId, nsecs_t vsyncPeriod) {
{
std::lock_guard<std::mutex> lock(mFeatureStateLock);
- // Cache the last reported config for primary display.
- mFeatures.cachedConfigChangedParams = {handle, displayId, configId, vsyncPeriod};
+ // Cache the last reported modes for primary display.
+ mFeatures.cachedModeChangedParams = {handle, displayId, modeId, vsyncPeriod};
}
- onNonPrimaryDisplayConfigChanged(handle, displayId, configId, vsyncPeriod);
+ onNonPrimaryDisplayModeChanged(handle, displayId, modeId, vsyncPeriod);
}
-void Scheduler::dispatchCachedReportedConfig() {
+void Scheduler::dispatchCachedReportedMode() {
// Check optional fields first.
- if (!mFeatures.configId.has_value()) {
- ALOGW("No config ID found, not dispatching cached config.");
+ if (!mFeatures.modeId.has_value()) {
+ ALOGW("No mode ID found, not dispatching cached mode.");
return;
}
- if (!mFeatures.cachedConfigChangedParams.has_value()) {
- ALOGW("No config changed params found, not dispatching cached config.");
+ if (!mFeatures.cachedModeChangedParams.has_value()) {
+ ALOGW("No mode changed params found, not dispatching cached mode.");
return;
}
- const auto configId = *mFeatures.configId;
- const auto vsyncPeriod =
- mRefreshRateConfigs.getRefreshRateFromConfigId(configId).getVsyncPeriod();
+ const auto modeId = *mFeatures.modeId;
+ const auto vsyncPeriod = mRefreshRateConfigs.getRefreshRateFromModeId(modeId).getVsyncPeriod();
- // If there is no change from cached config, there is no need to dispatch an event
- if (configId == mFeatures.cachedConfigChangedParams->configId &&
- vsyncPeriod == mFeatures.cachedConfigChangedParams->vsyncPeriod) {
+ // If there is no change from cached mode, there is no need to dispatch an event
+ if (modeId == mFeatures.cachedModeChangedParams->modeId &&
+ vsyncPeriod == mFeatures.cachedModeChangedParams->vsyncPeriod) {
return;
}
- mFeatures.cachedConfigChangedParams->configId = configId;
- mFeatures.cachedConfigChangedParams->vsyncPeriod = vsyncPeriod;
- onNonPrimaryDisplayConfigChanged(mFeatures.cachedConfigChangedParams->handle,
- mFeatures.cachedConfigChangedParams->displayId,
- mFeatures.cachedConfigChangedParams->configId,
- mFeatures.cachedConfigChangedParams->vsyncPeriod);
+ mFeatures.cachedModeChangedParams->modeId = modeId;
+ mFeatures.cachedModeChangedParams->vsyncPeriod = vsyncPeriod;
+ onNonPrimaryDisplayModeChanged(mFeatures.cachedModeChangedParams->handle,
+ mFeatures.cachedModeChangedParams->displayId,
+ mFeatures.cachedModeChangedParams->modeId,
+ mFeatures.cachedModeChangedParams->vsyncPeriod);
}
-void Scheduler::onNonPrimaryDisplayConfigChanged(ConnectionHandle handle,
- PhysicalDisplayId displayId,
- DisplayModeId configId, nsecs_t vsyncPeriod) {
+void Scheduler::onNonPrimaryDisplayModeChanged(ConnectionHandle handle, PhysicalDisplayId displayId,
+ DisplayModeId modeId, nsecs_t vsyncPeriod) {
android::EventThread* thread;
{
std::lock_guard<std::mutex> lock(mConnectionsLock);
RETURN_IF_INVALID_HANDLE(handle);
thread = mConnections[handle].thread.get();
}
- thread->onConfigChanged(displayId, configId, vsyncPeriod);
+ thread->onModeChanged(displayId, modeId, vsyncPeriod);
}
size_t Scheduler::getEventThreadConnectionCount(ConnectionHandle handle) {
@@ -590,9 +588,9 @@
}
}
-void Scheduler::setConfigChangePending(bool pending) {
+void Scheduler::setModeChangePending(bool pending) {
if (mLayerHistory) {
- mLayerHistory->setConfigChangePending(pending);
+ mLayerHistory->setModeChangePending(pending);
}
}
@@ -603,7 +601,7 @@
scheduler::LayerHistory::Summary summary = mLayerHistory->summarize(systemTime());
scheduler::RefreshRateConfigs::GlobalSignals consideredSignals;
- DisplayModeId newConfigId;
+ DisplayModeId newModeId;
bool frameRateChanged;
bool frameRateOverridesChanged;
{
@@ -613,28 +611,28 @@
}
mFeatures.contentRequirements = summary;
- newConfigId = calculateRefreshRateConfigIndexType(&consideredSignals);
- auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId);
+ newModeId = calculateRefreshRateModeId(&consideredSignals);
+ auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromModeId(newModeId);
frameRateOverridesChanged =
updateFrameRateOverrides(consideredSignals, newRefreshRate.getFps());
- if (mFeatures.configId == newConfigId) {
- // We don't need to change the config, but we might need to send an event
- // about a config change, since it was suppressed due to a previous idleConsidered
+ if (mFeatures.modeId == newModeId) {
+ // We don't need to change the display mode, but we might need to send an event
+ // about a mode change, since it was suppressed due to a previous idleConsidered
if (!consideredSignals.idle) {
- dispatchCachedReportedConfig();
+ dispatchCachedReportedMode();
}
frameRateChanged = false;
} else {
- mFeatures.configId = newConfigId;
+ mFeatures.modeId = newModeId;
frameRateChanged = true;
}
}
if (frameRateChanged) {
- auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId);
+ auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromModeId(newModeId);
mSchedulerCallback.changeRefreshRate(newRefreshRate,
- consideredSignals.idle ? ConfigEvent::None
- : ConfigEvent::Changed);
+ consideredSignals.idle ? ModeEvent::None
+ : ModeEvent::Changed);
}
if (frameRateOverridesChanged) {
mSchedulerCallback.triggerOnFrameRateOverridesChanged();
@@ -783,7 +781,7 @@
template <class T>
bool Scheduler::handleTimerStateChanged(T* currentState, T newState) {
- DisplayModeId newConfigId;
+ DisplayModeId newModeId;
bool refreshRateChanged = false;
bool frameRateOverridesChanged;
scheduler::RefreshRateConfigs::GlobalSignals consideredSignals;
@@ -793,29 +791,27 @@
return false;
}
*currentState = newState;
- newConfigId = calculateRefreshRateConfigIndexType(&consideredSignals);
- const RefreshRate& newRefreshRate =
- mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId);
+ newModeId = calculateRefreshRateModeId(&consideredSignals);
+ const RefreshRate& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromModeId(newModeId);
frameRateOverridesChanged =
updateFrameRateOverrides(consideredSignals, newRefreshRate.getFps());
- if (mFeatures.configId == newConfigId) {
- // We don't need to change the config, but we might need to send an event
- // about a config change, since it was suppressed due to a previous idleConsidered
+ if (mFeatures.modeId == newModeId) {
+ // We don't need to change the display mode, but we might need to send an event
+ // about a mode change, since it was suppressed due to a previous idleConsidered
if (!consideredSignals.idle) {
- dispatchCachedReportedConfig();
+ dispatchCachedReportedMode();
}
} else {
- mFeatures.configId = newConfigId;
+ mFeatures.modeId = newModeId;
refreshRateChanged = true;
}
}
if (refreshRateChanged) {
- const RefreshRate& newRefreshRate =
- mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId);
+ const RefreshRate& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromModeId(newModeId);
mSchedulerCallback.changeRefreshRate(newRefreshRate,
- consideredSignals.idle ? ConfigEvent::None
- : ConfigEvent::Changed);
+ consideredSignals.idle ? ModeEvent::None
+ : ModeEvent::Changed);
}
if (frameRateOverridesChanged) {
mSchedulerCallback.triggerOnFrameRateOverridesChanged();
@@ -823,7 +819,7 @@
return consideredSignals.touch;
}
-DisplayModeId Scheduler::calculateRefreshRateConfigIndexType(
+DisplayModeId Scheduler::calculateRefreshRateModeId(
scheduler::RefreshRateConfigs::GlobalSignals* consideredSignals) {
ATRACE_CALL();
if (consideredSignals) *consideredSignals = {};
@@ -833,7 +829,7 @@
if (mDisplayPowerTimer &&
(!mFeatures.isDisplayPowerStateNormal ||
mFeatures.displayPowerTimer == TimerState::Reset)) {
- return mRefreshRateConfigs.getMaxRefreshRateByPolicy().getConfigId();
+ return mRefreshRateConfigs.getMaxRefreshRateByPolicy().getModeId();
}
const bool touchActive = mTouchTimer && mFeatures.touch == TouchState::Active;
@@ -842,16 +838,16 @@
return mRefreshRateConfigs
.getBestRefreshRate(mFeatures.contentRequirements, {.touch = touchActive, .idle = idle},
consideredSignals)
- .getConfigId();
+ .getModeId();
}
-std::optional<DisplayModeId> Scheduler::getPreferredConfigId() {
+std::optional<DisplayModeId> Scheduler::getPreferredModeId() {
std::lock_guard<std::mutex> lock(mFeatureStateLock);
- // Make sure that the default config ID is first updated, before returned.
- if (mFeatures.configId.has_value()) {
- mFeatures.configId = calculateRefreshRateConfigIndexType();
+ // Make sure that the default mode ID is first updated, before returned.
+ if (mFeatures.modeId.has_value()) {
+ mFeatures.modeId = calculateRefreshRateModeId();
}
- return mFeatures.configId;
+ return mFeatures.modeId;
}
void Scheduler::onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline& timeline) {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 340ca8e..5237516 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -70,7 +70,7 @@
class Scheduler {
public:
using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate;
- using ConfigEvent = scheduler::RefreshRateConfigEvent;
+ using ModeEvent = scheduler::RefreshRateConfigEvent;
Scheduler(const scheduler::RefreshRateConfigs&, ISchedulerCallback&);
~Scheduler();
@@ -87,10 +87,10 @@
sp<EventThreadConnection> getEventConnection(ConnectionHandle);
void onHotplugReceived(ConnectionHandle, PhysicalDisplayId, bool connected);
- void onPrimaryDisplayConfigChanged(ConnectionHandle, PhysicalDisplayId, DisplayModeId configId,
- nsecs_t vsyncPeriod) EXCLUDES(mFeatureStateLock);
- void onNonPrimaryDisplayConfigChanged(ConnectionHandle, PhysicalDisplayId,
- DisplayModeId configId, nsecs_t vsyncPeriod);
+ void onPrimaryDisplayModeChanged(ConnectionHandle, PhysicalDisplayId, DisplayModeId,
+ nsecs_t vsyncPeriod) EXCLUDES(mFeatureStateLock);
+ void onNonPrimaryDisplayModeChanged(ConnectionHandle, PhysicalDisplayId, DisplayModeId,
+ nsecs_t vsyncPeriod);
void onScreenAcquired(ConnectionHandle);
void onScreenReleased(ConnectionHandle);
@@ -128,7 +128,7 @@
// Layers are registered on creation, and unregistered when the weak reference expires.
void registerLayer(Layer*);
void recordLayerHistory(Layer*, nsecs_t presentTime, LayerHistory::LayerUpdateType updateType);
- void setConfigChangePending(bool pending);
+ void setModeChangePending(bool pending);
// Detects content using layer history, and selects a matching refresh rate.
void chooseRefreshRateForContent();
@@ -153,7 +153,7 @@
void dumpVsync(std::string&) const;
// Get the appropriate refresh for current conditions.
- std::optional<DisplayModeId> getPreferredConfigId();
+ std::optional<DisplayModeId> getPreferredModeId();
// Notifies the scheduler about a refresh rate timeline change.
void onNewVsyncPeriodChangeTimeline(const hal::VsyncPeriodChangeTimeline& timeline);
@@ -227,11 +227,11 @@
// This function checks whether individual features that are affecting the refresh rate
// selection were initialized, prioritizes them, and calculates the DisplayModeId
// for the suggested refresh rate.
- DisplayModeId calculateRefreshRateConfigIndexType(
+ DisplayModeId calculateRefreshRateModeId(
scheduler::RefreshRateConfigs::GlobalSignals* consideredSignals = nullptr)
REQUIRES(mFeatureStateLock);
- void dispatchCachedReportedConfig() REQUIRES(mFeatureStateLock);
+ void dispatchCachedReportedMode() REQUIRES(mFeatureStateLock);
bool updateFrameRateOverrides(scheduler::RefreshRateConfigs::GlobalSignals consideredSignals,
Fps displayRefreshRate) REQUIRES(mFeatureStateLock)
EXCLUDES(mFrameRateOverridesMutex);
@@ -283,20 +283,20 @@
TouchState touch = TouchState::Inactive;
TimerState displayPowerTimer = TimerState::Expired;
- std::optional<DisplayModeId> configId;
+ std::optional<DisplayModeId> modeId;
LayerHistory::Summary contentRequirements;
bool isDisplayPowerStateNormal = true;
- // Used to cache the last parameters of onPrimaryDisplayConfigChanged
- struct ConfigChangedParams {
+ // Used to cache the last parameters of onPrimaryDisplayModeChanged
+ struct ModeChangedParams {
ConnectionHandle handle;
PhysicalDisplayId displayId;
- DisplayModeId configId;
+ DisplayModeId modeId;
nsecs_t vsyncPeriod;
};
- std::optional<ConfigChangedParams> cachedConfigChangedParams;
+ std::optional<ModeChangedParams> cachedModeChangedParams;
} mFeatures GUARDED_BY(mFeatureStateLock);
const scheduler::RefreshRateConfigs& mRefreshRateConfigs;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a6b05d0..f785cae 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -67,8 +67,9 @@
#include <sys/types.h>
#include <ui/ColorSpace.h>
#include <ui/DebugUtils.h>
-#include <ui/DisplayConfig.h>
+#include <ui/DisplayId.h>
#include <ui/DisplayInfo.h>
+#include <ui/DisplayMode.h>
#include <ui/DisplayStatInfo.h>
#include <ui/DisplayState.h>
#include <ui/GraphicBufferAllocator.h>
@@ -275,7 +276,6 @@
const String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER");
const String16 sRotateSurfaceFlinger("android.permission.ROTATE_SURFACE_FLINGER");
const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER");
-const String16 sUseBackgroundBlur("android.permission.USE_BACKGROUND_BLUR");
const String16 sDump("android.permission.DUMP");
const char* KERNEL_IDLE_TIMER_PROP = "graphics.display.kernel_idle_timer.enabled";
@@ -333,10 +333,6 @@
PermissionCache::checkPermission(sRotateSurfaceFlinger, pid, uid);
}
-bool originalCallerCanUseBlurs(int originPid, int originUid) {
- return PermissionCache::checkPermission(sUseBackgroundBlur, originPid, originUid);
-}
-
SurfaceFlingerBE::SurfaceFlingerBE() : mHwcServiceName(getHwcServiceName()) {}
SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag)
@@ -891,9 +887,9 @@
return NO_ERROR;
}
-status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& displayToken,
- Vector<DisplayConfig>* configs) {
- if (!displayToken || !configs) {
+status_t SurfaceFlinger::getDisplayModes(const sp<IBinder>& displayToken,
+ Vector<ui::DisplayMode>* modes) {
+ if (!displayToken || !modes) {
return BAD_VALUE;
}
@@ -904,16 +900,16 @@
return NAME_NOT_FOUND;
}
- configs->clear();
+ modes->clear();
- for (const auto& mode : display->getSupportedModes()) {
- DisplayConfig config;
+ for (const auto& supportedMode : display->getSupportedModes()) {
+ ui::DisplayMode mode;
- auto width = mode->getWidth();
- auto height = mode->getHeight();
+ auto width = supportedMode->getWidth();
+ auto height = supportedMode->getHeight();
- auto xDpi = mode->getDpiX();
- auto yDpi = mode->getDpiY();
+ auto xDpi = supportedMode->getDpiX();
+ auto yDpi = supportedMode->getDpiY();
if (display->isPrimary() &&
(internalDisplayOrientation == ui::ROTATION_90 ||
@@ -922,24 +918,24 @@
std::swap(xDpi, yDpi);
}
- config.resolution = ui::Size(width, height);
+ mode.resolution = ui::Size(width, height);
if (mEmulatedDisplayDensity) {
- config.xDpi = mEmulatedDisplayDensity;
- config.yDpi = mEmulatedDisplayDensity;
+ mode.xDpi = mEmulatedDisplayDensity;
+ mode.yDpi = mEmulatedDisplayDensity;
} else {
- config.xDpi = xDpi;
- config.yDpi = yDpi;
+ mode.xDpi = xDpi;
+ mode.yDpi = yDpi;
}
- const nsecs_t period = mode->getVsyncPeriod();
- config.refreshRate = Fps::fromPeriodNsecs(period).getValue();
+ const nsecs_t period = supportedMode->getVsyncPeriod();
+ mode.refreshRate = Fps::fromPeriodNsecs(period).getValue();
const auto vsyncConfigSet =
- mVsyncConfiguration->getConfigsForRefreshRate(Fps(config.refreshRate));
- config.appVsyncOffset = vsyncConfigSet.late.appOffset;
- config.sfVsyncOffset = vsyncConfigSet.late.sfOffset;
- config.configGroup = mode->getConfigGroup();
+ mVsyncConfiguration->getConfigsForRefreshRate(Fps(mode.refreshRate));
+ mode.appVsyncOffset = vsyncConfigSet.late.appOffset;
+ mode.sfVsyncOffset = vsyncConfigSet.late.sfOffset;
+ mode.group = supportedMode->getGroup();
// This is how far in advance a buffer must be queued for
// presentation at a given time. If you want a buffer to appear
@@ -953,9 +949,9 @@
//
// We add an additional 1ms to allow for processing time and
// differences between the ideal and actual refresh rate.
- config.presentationDeadline = period - config.sfVsyncOffset + 1000000;
+ mode.presentationDeadline = period - mode.sfVsyncOffset + 1000000;
- configs->push_back(config);
+ modes->push_back(mode);
}
return NO_ERROR;
@@ -970,15 +966,15 @@
return NO_ERROR;
}
-int SurfaceFlinger::getActiveConfig(const sp<IBinder>& displayToken) {
- int activeConfig;
+int SurfaceFlinger::getActiveDisplayModeId(const sp<IBinder>& displayToken) {
+ int activeMode;
bool isPrimary;
{
Mutex::Autolock lock(mStateLock);
if (const auto display = getDisplayDeviceLocked(displayToken)) {
- activeConfig = display->getActiveMode()->getId().value();
+ activeMode = display->getActiveMode()->getId().value();
isPrimary = display->isPrimary();
} else {
ALOGE("%s: Invalid display token %p", __FUNCTION__, displayToken.get());
@@ -987,36 +983,35 @@
}
if (isPrimary) {
- if (const auto config = getDesiredActiveConfig()) {
- return config->configId.value();
+ if (const auto mode = getDesiredActiveMode()) {
+ return mode->modeId.value();
}
}
- return activeConfig;
+ return activeMode;
}
-void SurfaceFlinger::setDesiredActiveConfig(const ActiveConfigInfo& info) {
+void SurfaceFlinger::setDesiredActiveMode(const ActiveModeInfo& info) {
ATRACE_CALL();
- auto refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(info.configId);
- ALOGV("setDesiredActiveConfig(%s)", refreshRate.getName().c_str());
+ auto refreshRate = mRefreshRateConfigs->getRefreshRateFromModeId(info.modeId);
+ ALOGV("%s(%s)", __func__, refreshRate.getName().c_str());
- std::lock_guard<std::mutex> lock(mActiveConfigLock);
- if (mDesiredActiveConfigChanged) {
- // If a config change is pending, just cache the latest request in
- // mDesiredActiveConfig
- const Scheduler::ConfigEvent prevConfig = mDesiredActiveConfig.event;
- mDesiredActiveConfig = info;
- mDesiredActiveConfig.event = mDesiredActiveConfig.event | prevConfig;
+ std::lock_guard<std::mutex> lock(mActiveModeLock);
+ if (mDesiredActiveModeChanged) {
+ // If a mode change is pending, just cache the latest request in mDesiredActiveMode
+ const Scheduler::ModeEvent prevConfig = mDesiredActiveMode.event;
+ mDesiredActiveMode = info;
+ mDesiredActiveMode.event = mDesiredActiveMode.event | prevConfig;
} else {
- // Check if we are already at the desired config
+ // Check if we are already at the desired mode
const auto display = getDefaultDisplayDeviceLocked();
- if (!display || display->getActiveMode()->getId() == refreshRate.getConfigId()) {
+ if (!display || display->getActiveMode()->getId() == refreshRate.getModeId()) {
return;
}
- // Initiate a config change.
- mDesiredActiveConfigChanged = true;
- mDesiredActiveConfig = info;
+ // Initiate a mode change.
+ mDesiredActiveModeChanged = true;
+ mDesiredActiveMode = info;
// This will trigger HWC refresh without resetting the idle timer.
repaintEverythingForHWC();
@@ -1028,7 +1023,7 @@
modulateVsync(&VsyncModulator::onRefreshRateChangeInitiated);
updatePhaseConfiguration(refreshRate.getFps());
- mScheduler->setConfigChangePending(true);
+ mScheduler->setModeChangePending(true);
}
if (mRefreshRateOverlay) {
@@ -1036,7 +1031,7 @@
}
}
-status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int modeId) {
+status_t SurfaceFlinger::setActiveMode(const sp<IBinder>& displayToken, int modeId) {
ATRACE_CALL();
if (!displayToken) {
@@ -1046,13 +1041,13 @@
auto future = schedule([=]() -> status_t {
const auto display = ON_MAIN_THREAD(getDisplayDeviceLocked(displayToken));
if (!display) {
- ALOGE("Attempt to set allowed display configs for invalid display token %p",
+ ALOGE("Attempt to set allowed display modes for invalid display token %p",
displayToken.get());
return NAME_NOT_FOUND;
}
if (display->isVirtual()) {
- ALOGW("Attempt to set allowed display configs for virtual display");
+ ALOGW("Attempt to set allowed display modes for virtual display");
return INVALID_OPERATION;
}
@@ -1071,13 +1066,13 @@
{fps, fps}};
constexpr bool kOverridePolicy = false;
- return setDesiredDisplayConfigSpecsInternal(display, policy, kOverridePolicy);
+ return setDesiredDisplayModeSpecsInternal(display, policy, kOverridePolicy);
});
return future.get();
}
-void SurfaceFlinger::setActiveConfigInternal() {
+void SurfaceFlinger::setActiveModeInternal() {
ATRACE_CALL();
const auto display = getDefaultDisplayDeviceLocked();
@@ -1085,21 +1080,21 @@
return;
}
- const auto upcomingConfig = display->getMode(mUpcomingActiveConfig.configId);
- if (!upcomingConfig) {
- ALOGW("Upcoming active config is no longer supported. ConfigId = %zu",
- mUpcomingActiveConfig.configId.value());
+ const auto upcomingMode = display->getMode(mUpcomingActiveMode.modeId);
+ if (!upcomingMode) {
+ ALOGW("Upcoming active mode is no longer supported. Mode ID = %zu",
+ mUpcomingActiveMode.modeId.value());
// TODO(b/159590486) Handle the error better. Some parts of SurfaceFlinger may
- // have been already updated with the upcoming active config.
+ // have been already updated with the upcoming active mode.
return;
}
const Fps oldRefreshRate = display->getActiveMode()->getFps();
- std::lock_guard<std::mutex> lock(mActiveConfigLock);
- mRefreshRateConfigs->setCurrentConfigId(mUpcomingActiveConfig.configId);
- display->setActiveMode(mUpcomingActiveConfig.configId);
+ std::lock_guard<std::mutex> lock(mActiveModeLock);
+ mRefreshRateConfigs->setCurrentModeId(mUpcomingActiveMode.modeId);
+ display->setActiveMode(mUpcomingActiveMode.modeId);
- const Fps refreshRate = upcomingConfig->getFps();
+ const Fps refreshRate = upcomingMode->getFps();
mRefreshRateStats->setRefreshRate(refreshRate);
@@ -1109,71 +1104,71 @@
updatePhaseConfiguration(refreshRate);
ATRACE_INT("ActiveConfigFPS", refreshRate.getValue());
- if (mUpcomingActiveConfig.event != Scheduler::ConfigEvent::None) {
+ if (mUpcomingActiveMode.event != Scheduler::ModeEvent::None) {
const nsecs_t vsyncPeriod = refreshRate.getPeriodNsecs();
const auto physicalId = display->getPhysicalId();
- mScheduler->onPrimaryDisplayConfigChanged(mAppConnectionHandle, physicalId,
- mUpcomingActiveConfig.configId, vsyncPeriod);
+ mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, physicalId,
+ mUpcomingActiveMode.modeId, vsyncPeriod);
}
}
-void SurfaceFlinger::clearDesiredActiveConfigState() {
- std::lock_guard<std::mutex> lock(mActiveConfigLock);
- mDesiredActiveConfig.event = Scheduler::ConfigEvent::None;
- mDesiredActiveConfigChanged = false;
- mScheduler->setConfigChangePending(false);
+void SurfaceFlinger::clearDesiredActiveModeState() {
+ std::lock_guard<std::mutex> lock(mActiveModeLock);
+ mDesiredActiveMode.event = Scheduler::ModeEvent::None;
+ mDesiredActiveModeChanged = false;
+ mScheduler->setModeChangePending(false);
}
-void SurfaceFlinger::desiredActiveConfigChangeDone() {
- const auto modeId = getDesiredActiveConfig()->configId;
+void SurfaceFlinger::desiredActiveModeChangeDone() {
+ const auto modeId = getDesiredActiveMode()->modeId;
- clearDesiredActiveConfigState();
+ clearDesiredActiveModeState();
const auto refreshRate = getDefaultDisplayDeviceLocked()->getMode(modeId)->getFps();
mScheduler->resyncToHardwareVsync(true, refreshRate.getPeriodNsecs());
updatePhaseConfiguration(refreshRate);
}
-void SurfaceFlinger::performSetActiveConfig() {
+void SurfaceFlinger::performSetActiveMode() {
ATRACE_CALL();
ALOGV("%s", __FUNCTION__);
// Store the local variable to release the lock.
- const auto desiredActiveConfig = getDesiredActiveConfig();
- if (!desiredActiveConfig) {
- // No desired active config pending to be applied
+ const auto desiredActiveMode = getDesiredActiveMode();
+ if (!desiredActiveMode) {
+ // No desired active mode pending to be applied
return;
}
const auto display = getDefaultDisplayDeviceLocked();
- const auto desiredConfig = display->getMode(desiredActiveConfig->configId);
- if (!desiredConfig) {
- ALOGW("Desired display config is no longer supported. Config ID = %zu",
- desiredActiveConfig->configId.value());
- clearDesiredActiveConfigState();
+ const auto desiredMode = display->getMode(desiredActiveMode->modeId);
+ if (!desiredMode) {
+ ALOGW("Desired display mode is no longer supported. Mode ID = %zu",
+ desiredActiveMode->modeId.value());
+ clearDesiredActiveModeState();
return;
}
- const auto refreshRate = desiredConfig->getFps();
- ALOGV("performSetActiveConfig changing active config to %zu(%s)",
- desiredConfig->getId().value(), to_string(refreshRate).c_str());
+ const auto refreshRate = desiredMode->getFps();
+ ALOGV("%s changing active mode to %zu(%s)", __FUNCTION__, desiredMode->getId().value(),
+ to_string(refreshRate).c_str());
- if (!display || display->getActiveMode()->getId() == desiredActiveConfig->configId) {
+ if (!display || display->getActiveMode()->getId() == desiredActiveMode->modeId) {
// display is not valid or we are already in the requested mode
// on both cases there is nothing left to do
- desiredActiveConfigChangeDone();
+ desiredActiveModeChangeDone();
return;
}
- // Desired active config was set, it is different than the config currently in use, however
- // allowed configs might have changed by the time we process the refresh.
- // Make sure the desired config is still allowed
- if (!isDisplayConfigAllowed(desiredActiveConfig->configId)) {
- desiredActiveConfigChangeDone();
+ // Desired active mode was set, it is different than the mode currently in use, however
+ // allowed modes might have changed by the time we process the refresh.
+ // Make sure the desired mode is still allowed
+ if (!isDisplayModeAllowed(desiredActiveMode->modeId)) {
+ desiredActiveModeChangeDone();
return;
}
- mUpcomingActiveConfig = *desiredActiveConfig;
+ mUpcomingActiveMode = *desiredActiveMode;
- ATRACE_INT("ActiveConfigFPS_HWC", refreshRate.getValue());
+ ATRACE_INT("ActiveModeFPS_HWC", refreshRate.getValue());
// TODO(b/142753666) use constrains
hal::VsyncPeriodChangeConstraints constraints;
@@ -1182,7 +1177,7 @@
hal::VsyncPeriodChangeTimeline outTimeline;
const auto status =
- display->initiateModeChange(mUpcomingActiveConfig.configId, constraints, &outTimeline);
+ display->initiateModeChange(mUpcomingActiveMode.modeId, constraints, &outTimeline);
if (status != NO_ERROR) {
// initiateModeChange may fail if a hotplug event is just about
// to be sent. We just log the error in this case.
@@ -1192,7 +1187,7 @@
mScheduler->onNewVsyncPeriodChangeTimeline(outTimeline);
// Scheduler will submit an empty frame to HWC if needed.
- mSetActiveConfigPending = true;
+ mSetActiveModePending = true;
}
status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& displayToken,
@@ -1586,12 +1581,11 @@
}
nsecs_t SurfaceFlinger::getVsyncPeriodFromHWC() const {
- const auto displayId = getInternalDisplayIdLocked();
- if (!displayId || !getHwComposer().isConnected(*displayId)) {
- return 0;
+ if (const auto display = getDefaultDisplayDeviceLocked()) {
+ return display->getVsyncPeriodFromHWC();
}
- return getHwComposer().getDisplayVsyncPeriod(*displayId);
+ return 0;
}
void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, hal::HWDisplayId hwcDisplayId,
@@ -1605,6 +1599,12 @@
return;
}
+ if (const auto displayId = getHwComposer().toPhysicalDisplayId(hwcDisplayId)) {
+ auto token = getPhysicalDisplayTokenLocked(*displayId);
+ auto display = getDisplayDeviceLocked(token);
+ display->onVsync(timestamp);
+ }
+
if (!getHwComposer().onVsync(hwcDisplayId, timestamp)) {
return;
}
@@ -1626,12 +1626,12 @@
*compositorTiming = getBE().mCompositorTiming;
}
-bool SurfaceFlinger::isDisplayConfigAllowed(DisplayModeId configId) const {
- return mRefreshRateConfigs->isConfigAllowed(configId);
+bool SurfaceFlinger::isDisplayModeAllowed(DisplayModeId modeId) const {
+ return mRefreshRateConfigs->isModeAllowed(modeId);
}
void SurfaceFlinger::changeRefreshRateLocked(const RefreshRate& refreshRate,
- Scheduler::ConfigEvent event) {
+ Scheduler::ModeEvent event) {
const auto display = getDefaultDisplayDeviceLocked();
if (!display || mBootStage != BootStage::FINISHED) {
return;
@@ -1639,13 +1639,13 @@
ATRACE_CALL();
// Don't do any updating if the current fps is the same as the new one.
- if (!isDisplayConfigAllowed(refreshRate.getConfigId())) {
- ALOGV("Skipping config %zu as it is not part of allowed configs",
- refreshRate.getConfigId().value());
+ if (!isDisplayModeAllowed(refreshRate.getModeId())) {
+ ALOGV("Skipping mode %zu as it is not part of allowed modes",
+ refreshRate.getModeId().value());
return;
}
- setDesiredActiveConfig({refreshRate.getConfigId(), event});
+ setDesiredActiveMode({refreshRate.getModeId(), event});
}
void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hal::HWDisplayId hwcDisplayId,
@@ -1828,18 +1828,18 @@
mGpuFrameMissedCount++;
}
- // If we are in the middle of a config change and the fence hasn't
+ // If we are in the middle of a mode change and the fence hasn't
// fired yet just wait for the next invalidate
- if (mSetActiveConfigPending) {
+ if (mSetActiveModePending) {
if (framePending) {
mEventQueue->invalidate();
return;
}
// We received the present fence from the HWC, so we assume it successfully updated
- // the config, hence we update SF.
- mSetActiveConfigPending = false;
- ON_MAIN_THREAD(setActiveConfigInternal());
+ // the mode, hence we update SF.
+ mSetActiveModePending = false;
+ ON_MAIN_THREAD(setActiveModeInternal());
}
if (framePending) {
@@ -1919,7 +1919,7 @@
mScheduler->chooseRefreshRateForContent();
}
- ON_MAIN_THREAD(performSetActiveConfig());
+ ON_MAIN_THREAD(performSetActiveMode());
updateCursorAsync();
updateInputFlinger();
@@ -1943,19 +1943,16 @@
bool SurfaceFlinger::handleMessageTransaction() {
ATRACE_CALL();
+
+ if (getTransactionFlags(eTransactionFlushNeeded)) {
+ flushTransactionQueues();
+ }
uint32_t transactionFlags = peekTransactionFlags();
-
- bool flushedATransaction = flushTransactionQueues();
-
bool runHandleTransaction =
- (transactionFlags && (transactionFlags != eTransactionFlushNeeded)) ||
- flushedATransaction ||
- mForceTraversal;
+ ((transactionFlags & (~eTransactionFlushNeeded)) != 0) || mForceTraversal;
if (runHandleTransaction) {
handleTransaction(eTransactionMask);
- } else {
- getTransactionFlags(eTransactionFlushNeeded);
}
if (transactionFlushNeeded()) {
@@ -2197,8 +2194,8 @@
}
});
- mTransactionCompletedThread.addPresentFence(mPreviousPresentFences[0]);
- mTransactionCompletedThread.sendCallbacks();
+ mTransactionCallbackInvoker.addPresentFence(mPreviousPresentFences[0]);
+ mTransactionCallbackInvoker.sendCallbacks();
if (display && display->isPrimary() && display->getPowerMode() == hal::PowerMode::ON &&
presentFenceTime->isValid()) {
@@ -2223,8 +2220,7 @@
} else if (isDisplayConnected) {
// The HWC doesn't support present fences, so use the refresh
// timestamp instead.
- const nsecs_t presentTime =
- getHwComposer().getRefreshTimestamp(display->getPhysicalId());
+ const nsecs_t presentTime = display->getRefreshTimestamp();
mAnimFrameTracker.setActualPresentTime(presentTime);
}
mAnimFrameTracker.advanceFrame();
@@ -2361,6 +2357,24 @@
// here the transaction has been committed
}
+DisplayModes SurfaceFlinger::loadSupportedDisplayModes(PhysicalDisplayId displayId) const {
+ const auto hwcModes = getHwComposer().getModes(displayId);
+ DisplayModes modes;
+ size_t nextModeId = 0;
+ for (const auto& hwcMode : hwcModes) {
+ modes.push_back(DisplayMode::Builder(hwcMode.hwcId)
+ .setId(DisplayModeId{nextModeId++})
+ .setWidth(hwcMode.width)
+ .setHeight(hwcMode.height)
+ .setVsyncPeriod(hwcMode.vsyncPeriod)
+ .setDpiX(hwcMode.dpiX)
+ .setDpiY(hwcMode.dpiY)
+ .setGroup(hwcMode.configGroup)
+ .build());
+ }
+ return modes;
+}
+
void SurfaceFlinger::processDisplayHotplugEventsLocked() {
for (const auto& event : mPendingHotplugEvents) {
std::optional<DisplayIdentificationInfo> info =
@@ -2374,8 +2388,14 @@
const auto it = mPhysicalDisplayTokens.find(displayId);
if (event.connection == hal::Connection::CONNECTED) {
- auto supportedModes = getHwComposer().getModes(displayId);
- const auto activeMode = getHwComposer().getActiveMode(displayId);
+ auto supportedModes = loadSupportedDisplayModes(displayId);
+ const auto activeModeHwcId = getHwComposer().getActiveMode(displayId);
+ LOG_ALWAYS_FATAL_IF(!activeModeHwcId, "HWC returned no active mode");
+
+ const auto activeMode = *std::find_if(supportedModes.begin(), supportedModes.end(),
+ [activeModeHwcId](const DisplayModePtr& mode) {
+ return mode->getHwcId() == *activeModeHwcId;
+ });
// TODO(b/175678215) Handle the case when activeMode is not in supportedModes
if (it == mPhysicalDisplayTokens.end()) {
@@ -2526,17 +2546,15 @@
void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,
const DisplayDeviceState& state) {
- int width = 0;
- int height = 0;
+ ui::Size resolution(0, 0);
ui::PixelFormat pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_UNKNOWN);
if (state.physical) {
- width = state.physical->activeMode->getWidth();
- height = state.physical->activeMode->getHeight();
+ resolution = state.physical->activeMode->getSize();
pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_RGBA_8888);
} else if (state.surface != nullptr) {
- int status = state.surface->query(NATIVE_WINDOW_WIDTH, &width);
+ int status = state.surface->query(NATIVE_WINDOW_WIDTH, &resolution.width);
ALOGE_IF(status != NO_ERROR, "Unable to query width (%d)", status);
- status = state.surface->query(NATIVE_WINDOW_HEIGHT, &height);
+ status = state.surface->query(NATIVE_WINDOW_HEIGHT, &resolution.height);
ALOGE_IF(status != NO_ERROR, "Unable to query height (%d)", status);
int intPixelFormat;
status = state.surface->query(NATIVE_WINDOW_FORMAT, &intPixelFormat);
@@ -2553,7 +2571,7 @@
if (const auto& physical = state.physical) {
builder.setPhysical({physical->id, physical->type});
}
- builder.setPixels(ui::Size(width, height));
+ builder.setPixels(resolution);
builder.setPixelFormat(pixelFormat);
builder.setIsSecure(state.isSecure);
builder.setLayerStackId(state.layerStack);
@@ -2588,7 +2606,8 @@
const auto physicalId = PhysicalDisplayId::tryCast(displayId);
LOG_FATAL_IF(!physicalId);
displaySurface = new FramebufferSurface(getHwComposer(), *physicalId, bqConsumer,
- maxGraphicsWidth, maxGraphicsHeight);
+ state.physical->activeMode->getSize(),
+ ui::Size(maxGraphicsWidth, maxGraphicsHeight));
producer = bqProducer;
}
@@ -2655,9 +2674,8 @@
// TODO(b/175678251) Call a listener instead.
if (currentState.physical->hwcDisplayId == getHwComposer().getInternalHwcDisplayId()) {
- mRefreshRateConfigs
- ->updateDisplayConfigs(currentState.physical->supportedModes,
- currentState.physical->activeMode->getId());
+ mRefreshRateConfigs->updateDisplayModes(currentState.physical->supportedModes,
+ currentState.physical->activeMode->getId());
mVsyncConfiguration->reset();
updatePhaseConfiguration(mRefreshRateConfigs->getCurrentRefreshRate().getFps());
if (mRefreshRateOverlay) {
@@ -2864,7 +2882,6 @@
});
}
- commitInputWindowCommands();
commitTransaction();
}
@@ -2905,11 +2922,6 @@
: nullptr);
}
-void SurfaceFlinger::commitInputWindowCommands() {
- mInputWindowCommands.merge(mPendingInputWindowCommands);
- mPendingInputWindowCommands.clear();
-}
-
void SurfaceFlinger::updateCursorAsync() {
compositionengine::CompositionRefreshArgs refreshArgs;
for (const auto& [_, display] : ON_MAIN_THREAD(mDisplays)) {
@@ -2921,8 +2933,7 @@
mCompositionEngine->updateCursorAsync(refreshArgs);
}
-void SurfaceFlinger::changeRefreshRate(const RefreshRate& refreshRate,
- Scheduler::ConfigEvent event) {
+void SurfaceFlinger::changeRefreshRate(const RefreshRate& refreshRate, Scheduler::ModeEvent event) {
// If this is called from the main thread mStateLock must be locked before
// Currently the only way to call this function from the main thread is from
// Scheduler::chooseRefreshRateForContent
@@ -2982,16 +2993,16 @@
mRegionSamplingThread =
new RegionSamplingThread(*this, *mScheduler,
RegionSamplingThread::EnvironmentTimingTunables());
- // Dispatch a config change request for the primary display on scheduler
+ // Dispatch a mode change request for the primary display on scheduler
// initialization, so that the EventThreads always contain a reference to a
// prior configuration.
//
// This is a bit hacky, but this avoids a back-pointer into the main SF
// classes from EventThread, and there should be no run-time binder cost
// anyway since there are no connected apps at this point.
- mScheduler->onPrimaryDisplayConfigChanged(mAppConnectionHandle, displayId,
- displayState.physical->activeMode->getId(),
- vsyncPeriod);
+ mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, displayId,
+ displayState.physical->activeMode->getId(),
+ vsyncPeriod);
static auto ignorePresentFences =
base::GetBoolProperty("debug.sf.vsync_reactor_ignore_present_fences"s, false);
mScheduler->setIgnorePresentFences(
@@ -3272,58 +3283,91 @@
mForceTraversal = true;
}
-bool SurfaceFlinger::flushTransactionQueues() {
+void SurfaceFlinger::flushTransactionQueues() {
// to prevent onHandleDestroyed from being called while the lock is held,
// we must keep a copy of the transactions (specifically the composer
// states) around outside the scope of the lock
std::vector<const TransactionState> transactions;
- bool flushedATransaction = false;
+ // Layer handles that have transactions with buffers that are ready to be applied.
+ std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>> pendingBuffers;
{
Mutex::Autolock _l(mStateLock);
+ {
+ Mutex::Autolock _l(mQueueLock);
+ // Collect transactions from pending transaction queue.
+ auto it = mPendingTransactionQueues.begin();
+ while (it != mPendingTransactionQueues.end()) {
+ auto& [applyToken, transactionQueue] = *it;
- auto it = mTransactionQueues.begin();
- while (it != mTransactionQueues.end()) {
- auto& [applyToken, transactionQueue] = *it;
+ while (!transactionQueue.empty()) {
+ const auto& transaction = transactionQueue.front();
+ if (!transactionIsReadyToBeApplied(transaction.isAutoTimestamp,
+ transaction.desiredPresentTime,
+ transaction.states,
+ false /* updateTransactionCounters*/,
+ pendingBuffers)) {
+ setTransactionFlags(eTransactionFlushNeeded);
+ break;
+ }
+ transactions.push_back(transaction);
+ transactionQueue.pop();
+ }
- while (!transactionQueue.empty()) {
- const auto& transaction = transactionQueue.front();
+ if (transactionQueue.empty()) {
+ it = mPendingTransactionQueues.erase(it);
+ mTransactionQueueCV.broadcast();
+ } else {
+ it = std::next(it, 1);
+ }
+ }
+
+ // Collect transactions from current transaction queue or queue to pending transactions.
+ // Case 1: push to pending when transactionIsReadyToBeApplied is false.
+ // Case 2: push to pending when there exist a pending queue.
+ // Case 3: others are ready to apply.
+ while (!mTransactionQueue.empty()) {
+ const auto& transaction = mTransactionQueue.front();
+ bool pendingTransactions = mPendingTransactionQueues.find(transaction.applyToken) !=
+ mPendingTransactionQueues.end();
+ // Call transactionIsReadyToBeApplied first in case we need to
+ // incrementPendingBufferCount and keep track of pending buffers
+ // if the transaction contains a buffer.
if (!transactionIsReadyToBeApplied(transaction.isAutoTimestamp,
transaction.desiredPresentTime,
- transaction.states)) {
- setTransactionFlags(eTransactionFlushNeeded);
- break;
+ transaction.states,
+ true /* updateTransactionCounters */,
+ pendingBuffers) ||
+ pendingTransactions) {
+ mPendingTransactionQueues[transaction.applyToken].push(transaction);
+ } else {
+ transactions.push_back(transaction);
}
- transactions.push_back(transaction);
- applyTransactionState(transaction.frameTimelineVsyncId, transaction.states,
- transaction.displays, transaction.flags,
- mPendingInputWindowCommands, transaction.desiredPresentTime,
- transaction.isAutoTimestamp, transaction.buffer,
- transaction.postTime, transaction.privileged,
- transaction.hasListenerCallbacks,
- transaction.listenerCallbacks, transaction.originPid,
- transaction.originUid, transaction.id, /*isMainThread*/ true);
- transactionQueue.pop();
- flushedATransaction = true;
- }
-
- if (transactionQueue.empty()) {
- it = mTransactionQueues.erase(it);
- mTransactionCV.broadcast();
- } else {
- it = std::next(it, 1);
+ mTransactionQueue.pop();
}
}
+
+ // Now apply all transactions.
+ for (const auto& transaction : transactions) {
+ applyTransactionState(transaction.frameTimelineInfo, transaction.states,
+ transaction.displays, transaction.flags,
+ transaction.inputWindowCommands, transaction.desiredPresentTime,
+ transaction.isAutoTimestamp, transaction.buffer,
+ transaction.postTime, transaction.privileged,
+ transaction.hasListenerCallbacks, transaction.listenerCallbacks,
+ transaction.originPid, transaction.originUid, transaction.id);
+ }
}
- return flushedATransaction;
}
bool SurfaceFlinger::transactionFlushNeeded() {
- return !mTransactionQueues.empty();
+ Mutex::Autolock _l(mQueueLock);
+ return !mPendingTransactionQueues.empty();
}
-bool SurfaceFlinger::transactionIsReadyToBeApplied(bool isAutoTimestamp, int64_t desiredPresentTime,
- const Vector<ComposerState>& states,
- bool updateTransactionCounters) {
+bool SurfaceFlinger::transactionIsReadyToBeApplied(
+ bool isAutoTimestamp, int64_t desiredPresentTime, const Vector<ComposerState>& states,
+ bool updateTransactionCounters,
+ std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>>& pendingBuffers) {
const nsecs_t expectedPresentTime = mExpectedPresentTime.load();
bool ready = true;
// Do not present if the desiredPresentTime has not passed unless it is more than one second
@@ -3339,8 +3383,9 @@
continue;
}
if (s.acquireFence && s.acquireFence->getStatus() == Fence::Status::Unsignaled) {
- ready = false;
+ ready = false;
}
+
sp<Layer> layer = nullptr;
if (s.surface) {
layer = fromHandleLocked(s.surface).promote();
@@ -3363,112 +3408,142 @@
// If backpressure is enabled and we already have a buffer to commit, keep the transaction
// in the queue.
- bool hasBuffer = s.what & layer_state_t::eBufferChanged ||
- s.what & layer_state_t::eCachedBufferChanged;
- if (hasBuffer && layer->backpressureEnabled() && layer->hasPendingBuffer() &&
- isAutoTimestamp) {
+ const bool hasPendingBuffer = pendingBuffers.find(s.surface) != pendingBuffers.end();
+ if (layer->backpressureEnabled() && hasPendingBuffer && isAutoTimestamp) {
ready = false;
}
+ pendingBuffers.insert(s.surface);
}
return ready;
}
status_t SurfaceFlinger::setTransactionState(
- int64_t frameTimelineVsyncId, const Vector<ComposerState>& states,
+ const FrameTimelineInfo& frameTimelineInfo, const Vector<ComposerState>& states,
const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) {
ATRACE_CALL();
- const int64_t postTime = systemTime();
+ {
+ Mutex::Autolock _l(mQueueLock);
- bool privileged = callingThreadHasUnscopedSurfaceFlingerAccess();
+ const int64_t postTime = systemTime();
+ bool privileged = callingThreadHasUnscopedSurfaceFlingerAccess();
- Mutex::Autolock _l(mStateLock);
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int originPid = ipc->getCallingPid();
+ const int originUid = ipc->getCallingUid();
- // If its TransactionQueue already has a pending TransactionState or if it is pending
- auto itr = mTransactionQueues.find(applyToken);
- // if this is an animation frame, wait until prior animation frame has
- // been applied by SF
- if (flags & eAnimation) {
- while (itr != mTransactionQueues.end()) {
- status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
- if (CC_UNLIKELY(err != NO_ERROR)) {
- ALOGW_IF(err == TIMED_OUT,
- "setTransactionState timed out "
- "waiting for animation frame to apply");
- break;
+ // If its TransactionQueue already has a pending TransactionState or if it is pending
+ auto itr = mPendingTransactionQueues.find(applyToken);
+ // if this is an animation frame, wait until prior animation frame has
+ // been applied by SF
+ if (flags & eAnimation) {
+ while (itr != mPendingTransactionQueues.end()) {
+ status_t err = mTransactionQueueCV.waitRelative(mQueueLock, s2ns(5));
+ if (CC_UNLIKELY(err != NO_ERROR)) {
+ ALOGW_IF(err == TIMED_OUT,
+ "setTransactionState timed out "
+ "waiting for animation frame to apply");
+ break;
+ }
+ itr = mPendingTransactionQueues.find(applyToken);
}
- itr = mTransactionQueues.find(applyToken);
}
+
+ const bool pendingTransactions = itr != mPendingTransactionQueues.end();
+ // Expected present time is computed and cached on invalidate, so it may be stale.
+ if (!pendingTransactions) {
+ const auto now = systemTime();
+ const bool nextVsyncPending = now < mExpectedPresentTime.load();
+ const DisplayStatInfo stats = mScheduler->getDisplayStatInfo(now);
+ mExpectedPresentTime = calculateExpectedPresentTime(stats);
+ // The transaction might arrive just before the next vsync but after
+ // invalidate was called. In that case we need to get the next vsync
+ // afterwards.
+ if (nextVsyncPending) {
+ mExpectedPresentTime += stats.vsyncPeriod;
+ }
+ }
+
+ mTransactionQueue.emplace(frameTimelineInfo, states, displays, flags, applyToken,
+ inputWindowCommands, desiredPresentTime, isAutoTimestamp,
+ uncacheBuffer, postTime, privileged, hasListenerCallbacks,
+ listenerCallbacks, originPid, originUid, transactionId);
+
+ if (pendingTransactions ||
+ (!isAutoTimestamp && desiredPresentTime > mExpectedPresentTime.load())) {
+ setTransactionFlags(eTransactionFlushNeeded);
+ return NO_ERROR;
+ }
+
+ // TODO(b/159125966): Remove eEarlyWakeup completely as no client should use this flag
+ if (flags & eEarlyWakeup) {
+ ALOGW("eEarlyWakeup is deprecated. Use eExplicitEarlyWakeup[Start|End]");
+ }
+
+ if (!privileged && (flags & (eExplicitEarlyWakeupStart | eExplicitEarlyWakeupEnd))) {
+ ALOGE("Only WindowManager is allowed to use eExplicitEarlyWakeup[Start|End] flags");
+ flags &= ~(eExplicitEarlyWakeupStart | eExplicitEarlyWakeupEnd);
+ }
+
+ const auto schedule = [](uint32_t flags) {
+ if (flags & eEarlyWakeup) return TransactionSchedule::Early;
+ if (flags & eExplicitEarlyWakeupEnd) return TransactionSchedule::EarlyEnd;
+ if (flags & eExplicitEarlyWakeupStart) return TransactionSchedule::EarlyStart;
+ return TransactionSchedule::Late;
+ }(flags);
+ setTransactionFlags(eTransactionFlushNeeded, schedule);
}
- const bool pendingTransactions = itr != mTransactionQueues.end();
- // Expected present time is computed and cached on invalidate, so it may be stale.
- if (!pendingTransactions) {
- const auto now = systemTime();
- const bool nextVsyncPending = now < mExpectedPresentTime.load();
- const DisplayStatInfo stats = mScheduler->getDisplayStatInfo(now);
- mExpectedPresentTime = calculateExpectedPresentTime(stats);
- // The transaction might arrive just before the next vsync but after
- // invalidate was called. In that case we need to get the next vsync
- // afterwards.
- if (nextVsyncPending) {
- mExpectedPresentTime += stats.vsyncPeriod;
- }
- }
-
- IPCThreadState* ipc = IPCThreadState::self();
- const int originPid = ipc->getCallingPid();
- const int originUid = ipc->getCallingUid();
-
- // Call transactionIsReadyToBeApplied first in case we need to incrementPendingBufferCount
- // if the transaction contains a buffer.
- if (!transactionIsReadyToBeApplied(isAutoTimestamp, desiredPresentTime, states, true) ||
- pendingTransactions) {
- mTransactionQueues[applyToken].emplace(frameTimelineVsyncId, states, displays, flags,
- desiredPresentTime, isAutoTimestamp, uncacheBuffer,
- postTime, privileged, hasListenerCallbacks,
- listenerCallbacks, originPid, originUid,
- transactionId);
- setTransactionFlags(eTransactionFlushNeeded);
+ // if this is a synchronous transaction, wait for it to take effect
+ // before returning.
+ const bool synchronous = flags & eSynchronous;
+ const bool syncInput = inputWindowCommands.syncInputWindows;
+ if (!synchronous && !syncInput) {
return NO_ERROR;
}
- applyTransactionState(frameTimelineVsyncId, states, displays, flags, inputWindowCommands,
- desiredPresentTime, isAutoTimestamp, uncacheBuffer, postTime, privileged,
- hasListenerCallbacks, listenerCallbacks, originPid, originUid,
- transactionId, /*isMainThread*/ false);
+ Mutex::Autolock _l(mStateLock);
+ if (synchronous) {
+ mTransactionPending = true;
+ }
+ if (syncInput) {
+ mPendingSyncInputWindows = true;
+ }
+
+ // applyTransactionState can be called by either the main SF thread or by
+ // another process through setTransactionState. While a given process may wish
+ // to wait on synchronous transactions, the main SF thread should never
+ // be blocked. Therefore, we only wait if isMainThread is false.
+ while (mTransactionPending || mPendingSyncInputWindows) {
+ status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
+ if (CC_UNLIKELY(err != NO_ERROR)) {
+ // just in case something goes wrong in SF, return to the
+ // called after a few seconds.
+ ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!");
+ mTransactionPending = false;
+ mPendingSyncInputWindows = false;
+ break;
+ }
+ }
+
return NO_ERROR;
}
-void SurfaceFlinger::applyTransactionState(
- int64_t frameTimelineVsyncId, const Vector<ComposerState>& states,
- const Vector<DisplayState>& displays, uint32_t flags,
- const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime,
- bool isAutoTimestamp, const client_cache_t& uncacheBuffer, const int64_t postTime,
- bool privileged, bool hasListenerCallbacks,
- const std::vector<ListenerCallbacks>& listenerCallbacks, int originPid, int originUid,
- uint64_t transactionId, bool isMainThread) {
+void SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelineInfo,
+ const Vector<ComposerState>& states,
+ const Vector<DisplayState>& displays, uint32_t flags,
+ const InputWindowCommands& inputWindowCommands,
+ const int64_t desiredPresentTime, bool isAutoTimestamp,
+ const client_cache_t& uncacheBuffer,
+ const int64_t postTime, bool privileged,
+ bool hasListenerCallbacks,
+ const std::vector<ListenerCallbacks>& listenerCallbacks,
+ int originPid, int originUid, uint64_t transactionId) {
uint32_t transactionFlags = 0;
- if (flags & eAnimation) {
- // For window updates that are part of an animation we must wait for
- // previous animation "frames" to be handled.
- while (!isMainThread && mAnimTransactionPending) {
- status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
- if (CC_UNLIKELY(err != NO_ERROR)) {
- // just in case something goes wrong in SF, return to the
- // caller after a few seconds.
- ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out "
- "waiting for previous animation frame");
- mAnimTransactionPending = false;
- break;
- }
- }
- }
-
for (const DisplayState& display : displays) {
transactionFlags |= setDisplayStateLocked(display);
}
@@ -3477,17 +3552,16 @@
// that listeners with SurfaceControls will start registration during setClientStateLocked
// below.
for (const auto& listener : listenerCallbacks) {
- mTransactionCompletedThread.startRegistration(listener);
- mTransactionCompletedThread.endRegistration(listener);
+ mTransactionCallbackInvoker.startRegistration(listener);
+ mTransactionCallbackInvoker.endRegistration(listener);
}
std::unordered_set<ListenerCallbacks, ListenerCallbacksHash> listenerCallbacksWithSurfaces;
uint32_t clientStateFlags = 0;
for (const ComposerState& state : states) {
clientStateFlags |=
- setClientStateLocked(frameTimelineVsyncId, state, desiredPresentTime,
- isAutoTimestamp, postTime, privileged,
- listenerCallbacksWithSurfaces, originPid, originUid);
+ setClientStateLocked(frameTimelineInfo, state, desiredPresentTime, isAutoTimestamp,
+ postTime, privileged, listenerCallbacksWithSurfaces);
if ((flags & eAnimation) && state.state.surface) {
if (const auto layer = fromHandleLocked(state.state.surface).promote(); layer) {
mScheduler->recordLayerHistory(layer.get(),
@@ -3498,12 +3572,12 @@
}
for (const auto& listenerCallback : listenerCallbacksWithSurfaces) {
- mTransactionCompletedThread.endRegistration(listenerCallback);
+ mTransactionCallbackInvoker.endRegistration(listenerCallback);
}
// If the state doesn't require a traversal and there are callbacks, send them now
if (!(clientStateFlags & eTraversalNeeded) && hasListenerCallbacks) {
- mTransactionCompletedThread.sendCallbacks();
+ mTransactionCallbackInvoker.sendCallbacks();
}
transactionFlags |= clientStateFlags;
@@ -3527,80 +3601,25 @@
transactionFlags = eTransactionNeeded;
}
- // If we are on the main thread, we are about to preform a traversal. Clear the traversal bit
- // so we don't have to wake up again next frame to preform an uneeded traversal.
- if (isMainThread && (transactionFlags & eTraversalNeeded)) {
- transactionFlags = transactionFlags & (~eTraversalNeeded);
- mForceTraversal = true;
- }
-
- const auto schedule = [](uint32_t flags) {
- if (flags & eEarlyWakeup) return TransactionSchedule::Early;
- if (flags & eExplicitEarlyWakeupEnd) return TransactionSchedule::EarlyEnd;
- if (flags & eExplicitEarlyWakeupStart) return TransactionSchedule::EarlyStart;
- return TransactionSchedule::Late;
- }(flags);
-
if (transactionFlags) {
if (mInterceptor->isEnabled()) {
mInterceptor->saveTransaction(states, mCurrentState.displays, displays, flags,
originPid, originUid, transactionId);
}
- // TODO(b/159125966): Remove eEarlyWakeup completly as no client should use this flag
- if (flags & eEarlyWakeup) {
- ALOGW("eEarlyWakeup is deprecated. Use eExplicitEarlyWakeup[Start|End]");
+ // We are on the main thread, we are about to preform a traversal. Clear the traversal bit
+ // so we don't have to wake up again next frame to preform an unnecessary traversal.
+ if (transactionFlags & eTraversalNeeded) {
+ transactionFlags = transactionFlags & (~eTraversalNeeded);
+ mForceTraversal = true;
}
-
- if (!privileged && (flags & (eExplicitEarlyWakeupStart | eExplicitEarlyWakeupEnd))) {
- ALOGE("Only WindowManager is allowed to use eExplicitEarlyWakeup[Start|End] flags");
- flags &= ~(eExplicitEarlyWakeupStart | eExplicitEarlyWakeupEnd);
+ if (transactionFlags) {
+ setTransactionFlags(transactionFlags);
}
- // this triggers the transaction
- setTransactionFlags(transactionFlags, schedule);
-
if (flags & eAnimation) {
mAnimTransactionPending = true;
}
-
- // if this is a synchronous transaction, wait for it to take effect
- // before returning.
- const bool synchronous = flags & eSynchronous;
- const bool syncInput = inputWindowCommands.syncInputWindows;
- if (!synchronous && !syncInput) {
- return;
- }
-
- if (synchronous) {
- mTransactionPending = true;
- }
- if (syncInput) {
- mPendingSyncInputWindows = true;
- }
-
-
- // applyTransactionState can be called by either the main SF thread or by
- // another process through setTransactionState. While a given process may wish
- // to wait on synchronous transactions, the main SF thread should never
- // be blocked. Therefore, we only wait if isMainThread is false.
- while (!isMainThread && (mTransactionPending || mPendingSyncInputWindows)) {
- status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
- if (CC_UNLIKELY(err != NO_ERROR)) {
- // just in case something goes wrong in SF, return to the
- // called after a few seconds.
- ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!");
- mTransactionPending = false;
- mPendingSyncInputWindows = false;
- break;
- }
- }
- } else {
- // Update VsyncModulator state machine even if transaction is not needed.
- if (schedule == TransactionSchedule::EarlyStart ||
- schedule == TransactionSchedule::EarlyEnd) {
- modulateVsync(&VsyncModulator::setTransactionSchedule, schedule);
- }
}
}
@@ -3665,16 +3684,15 @@
}
uint32_t SurfaceFlinger::setClientStateLocked(
- int64_t frameTimelineVsyncId, const ComposerState& composerState,
+ const FrameTimelineInfo& frameTimelineInfo, const ComposerState& composerState,
int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, bool privileged,
- std::unordered_set<ListenerCallbacks, ListenerCallbacksHash>& listenerCallbacks,
- int originPid, int originUid) {
+ std::unordered_set<ListenerCallbacks, ListenerCallbacksHash>& listenerCallbacks) {
const layer_state_t& s = composerState.state;
for (auto& listener : s.listeners) {
// note that startRegistration will not re-register if the listener has
// already be registered for a prior surface control
- mTransactionCompletedThread.startRegistration(listener);
+ mTransactionCallbackInvoker.startRegistration(listener);
listenerCallbacks.insert(listener);
}
@@ -3687,7 +3705,7 @@
}
if (layer == nullptr) {
for (auto& [listener, callbackIds] : s.listeners) {
- mTransactionCompletedThread.registerUnpresentedCallbackHandle(
+ mTransactionCallbackInvoker.registerUnpresentedCallbackHandle(
new CallbackHandle(listener, callbackIds, s.surface));
}
return 0;
@@ -3814,14 +3832,10 @@
if (layer->setCornerRadius(s.cornerRadius))
flags |= eTraversalNeeded;
}
-
- if (what & layer_state_t::eBackgroundBlurRadiusChanged && !mDisableBlurs && mSupportsBlur &&
- originalCallerCanUseBlurs(originPid, originUid)) {
+ if (what & layer_state_t::eBackgroundBlurRadiusChanged && !mDisableBlurs && mSupportsBlur) {
if (layer->setBackgroundBlurRadius(s.backgroundBlurRadius)) flags |= eTraversalNeeded;
}
-
- if (what & layer_state_t::eBlurRegionsChanged &&
- originalCallerCanUseBlurs(originPid, originUid)) {
+ if (what & layer_state_t::eBlurRegionsChanged) {
if (layer->setBlurRegions(s.blurRegions)) flags |= eTraversalNeeded;
}
if (what & layer_state_t::eLayerStackChanged) {
@@ -3855,9 +3869,6 @@
flags |= eTransactionNeeded|eTraversalNeeded;
}
}
- if (what & layer_state_t::eDetachChildren) {
- layer->detachChildren();
- }
if (what & layer_state_t::eTransformChanged) {
if (layer->setTransform(s.transform)) flags |= eTraversalNeeded;
}
@@ -3925,10 +3936,11 @@
flags |= eTraversalNeeded;
}
}
- if (what & layer_state_t::eFrameTimelineVsyncChanged) {
- layer->setFrameTimelineVsyncForTransaction(s.frameTimelineVsyncId, postTime);
- } else if (frameTimelineVsyncId != ISurfaceComposer::INVALID_VSYNC_ID) {
- layer->setFrameTimelineVsyncForTransaction(frameTimelineVsyncId, postTime);
+ FrameTimelineInfo info;
+ if (what & layer_state_t::eFrameTimelineInfoChanged) {
+ info = s.frameTimelineInfo;
+ } else if (frameTimelineInfo.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) {
+ info = frameTimelineInfo;
}
if (what & layer_state_t::eFixedTransformHintChanged) {
if (layer->setFixedTransformHint(s.fixedTransformHint)) {
@@ -3987,9 +3999,11 @@
: layer->getHeadFrameNumber(-1 /* expectedPresentTime */) + 1;
if (layer->setBuffer(buffer, s.acquireFence, postTime, desiredPresentTime, isAutoTimestamp,
- s.cachedBuffer, frameNumber, dequeueBufferTimestamp)) {
+ s.cachedBuffer, frameNumber, dequeueBufferTimestamp, info)) {
flags |= eTraversalNeeded;
}
+ } else if (info.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) {
+ layer->setFrameTimelineVsyncForBufferlessTransaction(info, postTime);
}
if (layer->setTransactionCompletedListeners(callbackHandles)) flags |= eTraversalNeeded;
@@ -3999,7 +4013,7 @@
}
uint32_t SurfaceFlinger::addInputWindowCommands(const InputWindowCommands& inputWindowCommands) {
- bool hasChanges = mPendingInputWindowCommands.merge(inputWindowCommands);
+ bool hasChanges = mInputWindowCommands.merge(inputWindowCommands);
return hasChanges ? eTraversalNeeded : 0;
}
@@ -4264,9 +4278,11 @@
d.width = 0;
d.height = 0;
displays.add(d);
- setTransactionState(ISurfaceComposer::INVALID_VSYNC_ID, state, displays, 0, nullptr,
- mPendingInputWindowCommands, systemTime(), true, {}, false, {},
- 0 /* Undefined transactionId */);
+
+ // It should be on the main thread, apply it directly.
+ applyTransactionState(FrameTimelineInfo{}, state, displays, 0, mInputWindowCommands,
+ systemTime(), true, {}, systemTime(), true, false, {}, getpid(), getuid(),
+ 0 /* Undefined transactionId */);
setPowerModeInternal(display, hal::PowerMode::ON);
const nsecs_t vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
@@ -4524,8 +4540,8 @@
mRefreshRateConfigs->dump(result);
- StringAppendF(&result, "(config override by backdoor: %s)\n\n",
- mDebugDisplayConfigSetByBackdoor ? "yes" : "no");
+ StringAppendF(&result, "(mode override by backdoor: %s)\n\n",
+ mDebugDisplayModeSetByBackdoor ? "yes" : "no");
mScheduler->dump(mAppConnectionHandle, result);
mScheduler->dumpVsync(result);
@@ -4843,15 +4859,12 @@
" gpu_to_cpu_unsupported : %d\n",
mTransactionFlags.load(), !mGpuToCpuSupported);
- if (const auto displayId = getInternalDisplayIdLocked();
- displayId && getHwComposer().isConnected(*displayId)) {
- const auto activeConfig = getHwComposer().getActiveMode(*displayId);
+ if (const auto display = getDefaultDisplayDeviceLocked()) {
std::string fps, xDpi, yDpi;
- if (activeConfig) {
- const auto vsyncPeriod = getHwComposer().getDisplayVsyncPeriod(*displayId);
- fps = base::StringPrintf("%s", to_string(Fps::fromPeriodNsecs(vsyncPeriod)).c_str());
- xDpi = base::StringPrintf("%.2f", activeConfig->getDpiX());
- yDpi = base::StringPrintf("%.2f", activeConfig->getDpiY());
+ if (const auto activeMode = display->getActiveMode()) {
+ fps = to_string(activeMode->getFps());
+ xDpi = base::StringPrintf("%.2f", activeMode->getDpiX());
+ yDpi = base::StringPrintf("%.2f", activeMode->getDpiY());
} else {
fps = "unknown";
xDpi = "unknown";
@@ -4909,23 +4922,24 @@
result.append("\n");
}
-void SurfaceFlinger::updateColorMatrixLocked() {
- mat4 colorMatrix;
- if (mGlobalSaturationFactor != 1.0f) {
- // Rec.709 luma coefficients
- float3 luminance{0.213f, 0.715f, 0.072f};
- luminance *= 1.0f - mGlobalSaturationFactor;
- mat4 saturationMatrix = mat4(
- vec4{luminance.r + mGlobalSaturationFactor, luminance.r, luminance.r, 0.0f},
- vec4{luminance.g, luminance.g + mGlobalSaturationFactor, luminance.g, 0.0f},
- vec4{luminance.b, luminance.b, luminance.b + mGlobalSaturationFactor, 0.0f},
- vec4{0.0f, 0.0f, 0.0f, 1.0f}
- );
- colorMatrix = mClientColorMatrix * saturationMatrix * mDaltonizer();
- } else {
- colorMatrix = mClientColorMatrix * mDaltonizer();
+mat4 SurfaceFlinger::calculateColorMatrix(float saturation) {
+ if (saturation == 1) {
+ return mat4();
}
+ float3 luminance{0.213f, 0.715f, 0.072f};
+ luminance *= 1.0f - saturation;
+ mat4 saturationMatrix = mat4(vec4{luminance.r + saturation, luminance.r, luminance.r, 0.0f},
+ vec4{luminance.g, luminance.g + saturation, luminance.g, 0.0f},
+ vec4{luminance.b, luminance.b, luminance.b + saturation, 0.0f},
+ vec4{0.0f, 0.0f, 0.0f, 1.0f});
+ return saturationMatrix;
+}
+
+void SurfaceFlinger::updateColorMatrixLocked() {
+ mat4 colorMatrix =
+ mClientColorMatrix * calculateColorMatrix(mGlobalSaturationFactor) * mDaltonizer();
+
if (mCurrentState.colorMatrix != colorMatrix) {
mCurrentState.colorMatrix = colorMatrix;
mCurrentState.colorMatrixChanged = true;
@@ -4946,8 +4960,8 @@
case ENABLE_VSYNC_INJECTIONS:
case GET_ANIMATION_FRAME_STATS:
case GET_HDR_CAPABILITIES:
- case SET_DESIRED_DISPLAY_CONFIG_SPECS:
- case GET_DESIRED_DISPLAY_CONFIG_SPECS:
+ case SET_DESIRED_DISPLAY_MODE_SPECS:
+ case GET_DESIRED_DISPLAY_MODE_SPECS:
case SET_ACTIVE_COLOR_MODE:
case GET_AUTO_LOW_LATENCY_MODE_SUPPORT:
case SET_AUTO_LOW_LATENCY_MODE:
@@ -4989,13 +5003,13 @@
// information, so it is OK to pass them.
case AUTHENTICATE_SURFACE:
case GET_ACTIVE_COLOR_MODE:
- case GET_ACTIVE_CONFIG:
+ case GET_ACTIVE_DISPLAY_MODE:
case GET_PHYSICAL_DISPLAY_IDS:
case GET_PHYSICAL_DISPLAY_TOKEN:
case GET_DISPLAY_COLOR_MODES:
case GET_DISPLAY_NATIVE_PRIMARIES:
case GET_DISPLAY_INFO:
- case GET_DISPLAY_CONFIGS:
+ case GET_DISPLAY_MODES:
case GET_DISPLAY_STATE:
case GET_DISPLAY_STATS:
case GET_SUPPORTED_FRAME_TIMESTAMPS:
@@ -5015,7 +5029,7 @@
case CAPTURE_LAYERS:
case CAPTURE_DISPLAY:
case SET_DISPLAY_BRIGHTNESS:
- case SET_FRAME_TIMELINE_VSYNC:
+ case SET_FRAME_TIMELINE_INFO:
// This is not sensitive information, so should not require permission control.
case GET_GPU_CONTEXT_PRIORITY: {
return OK;
@@ -5369,7 +5383,7 @@
}
case 1035: {
const int modeId = data.readInt32();
- mDebugDisplayConfigSetByBackdoor = false;
+ mDebugDisplayModeSetByBackdoor = false;
const auto displayId = getInternalDisplayId();
if (!displayId) {
@@ -5377,12 +5391,12 @@
return NO_ERROR;
}
- status_t result = setActiveConfig(getPhysicalDisplayToken(*displayId), modeId);
+ status_t result = setActiveMode(getPhysicalDisplayToken(*displayId), modeId);
if (result != NO_ERROR) {
return result;
}
- mDebugDisplayConfigSetByBackdoor = true;
+ mDebugDisplayModeSetByBackdoor = true;
return NO_ERROR;
}
@@ -5461,14 +5475,13 @@
// Update the overlay on the main thread to avoid race conditions with
// mRefreshRateConfigs->getCurrentRefreshRate()
static_cast<void>(schedule([=] {
- const auto desiredActiveConfig = getDesiredActiveConfig();
- const std::optional<DisplayModeId> desiredConfigId = desiredActiveConfig
- ? std::make_optional(desiredActiveConfig->configId)
- : std::nullopt;
+ const auto desiredActiveMode = getDesiredActiveMode();
+ const std::optional<DisplayModeId> desiredModeId =
+ desiredActiveMode ? std::make_optional(desiredActiveMode->modeId) : std::nullopt;
const bool timerExpired = mKernelIdleTimerEnabled && expired;
const auto newRefreshRate =
- mRefreshRateConfigs->onKernelTimerChanged(desiredConfigId, timerExpired);
+ mRefreshRateConfigs->onKernelTimerChanged(desiredModeId, timerExpired);
if (newRefreshRate) {
if (Mutex::Autolock lock(mStateLock); mRefreshRateOverlay) {
mRefreshRateOverlay->changeRefreshRate(*newRefreshRate);
@@ -5637,7 +5650,8 @@
};
return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize,
- args.pixelFormat, args.allowProtected, captureListener);
+ args.pixelFormat, args.allowProtected, args.grayscale,
+ captureListener);
}
status_t SurfaceFlinger::captureDisplay(uint64_t displayOrLayerStack,
@@ -5673,7 +5687,7 @@
return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, size,
ui::PixelFormat::RGBA_8888, false /* allowProtected */,
- captureListener);
+ false /* grayscale */, captureListener);
}
status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
@@ -5719,12 +5733,12 @@
crop.bottom = parentSourceBounds.getHeight();
}
- if (crop.isEmpty() || args.frameScale <= 0.0f) {
+ if (crop.isEmpty() || args.frameScaleX <= 0.0f || args.frameScaleY <= 0.0f) {
// Error out if the layer has no source bounds (i.e. they are boundless) and a source
// crop was not specified, or an invalid frame scale was provided.
return BAD_VALUE;
}
- reqSize = ui::Size(crop.width() * args.frameScale, crop.height() * args.frameScale);
+ reqSize = ui::Size(crop.width() * args.frameScaleX, crop.height() * args.frameScaleY);
for (const auto& handle : args.excludeHandles) {
sp<Layer> excludeLayer = fromHandleLocked(handle).promote();
@@ -5794,13 +5808,14 @@
};
return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize,
- args.pixelFormat, args.allowProtected, captureListener);
+ args.pixelFormat, args.allowProtected, args.grayscale,
+ captureListener);
}
status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture,
TraverseLayersFunction traverseLayers,
ui::Size bufferSize, ui::PixelFormat reqPixelFormat,
- const bool allowProtected,
+ bool allowProtected, bool grayscale,
const sp<IScreenCaptureListener>& captureListener) {
ATRACE_CALL();
@@ -5831,12 +5846,13 @@
static_cast<android_pixel_format>(reqPixelFormat),
1 /* layerCount */, usage, "screenshot");
return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer,
- false /* regionSampling */, captureListener);
+ false /* regionSampling */, grayscale, captureListener);
}
status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture,
TraverseLayersFunction traverseLayers,
- sp<GraphicBuffer>& buffer, const bool regionSampling,
+ sp<GraphicBuffer>& buffer, bool regionSampling,
+ bool grayscale,
const sp<IScreenCaptureListener>& captureListener) {
ATRACE_CALL();
@@ -5852,7 +5868,7 @@
if (mRefreshPending) {
ALOGW("Skipping screenshot for now");
captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, regionSampling,
- captureListener);
+ grayscale, captureListener);
return;
}
ScreenCaptureResults captureResults;
@@ -5867,7 +5883,7 @@
status_t result = NO_ERROR;
renderArea->render([&] {
result = renderScreenImplLocked(*renderArea, traverseLayers, buffer, forSystem,
- regionSampling, captureResults);
+ regionSampling, grayscale, captureResults);
});
captureResults.result = result;
@@ -5880,7 +5896,7 @@
status_t SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea,
TraverseLayersFunction traverseLayers,
const sp<GraphicBuffer>& buffer, bool forSystem,
- bool regionSampling,
+ bool regionSampling, bool grayscale,
ScreenCaptureResults& captureResults) {
ATRACE_CALL();
@@ -5921,6 +5937,9 @@
clientCompositionDisplay.outputDataspace = renderArea.getReqDataSpace();
clientCompositionDisplay.maxLuminance = DisplayDevice::sDefaultMaxLumiance;
+ const float colorSaturation = grayscale ? 0 : 1;
+ clientCompositionDisplay.colorTransform = calculateColorMatrix(colorSaturation);
+
const float alpha = RenderArea::getCaptureFillValue(renderArea.getCaptureFill());
compositionengine::LayerFE::LayerSettings fillLayer;
@@ -6049,7 +6068,7 @@
}
}
-status_t SurfaceFlinger::setDesiredDisplayConfigSpecsInternal(
+status_t SurfaceFlinger::setDesiredDisplayModeSpecsInternal(
const sp<DisplayDevice>& display,
const std::optional<scheduler::RefreshRateConfigs::Policy>& policy, bool overridePolicy) {
Mutex::Autolock lock(mStateLock);
@@ -6059,10 +6078,10 @@
LOG_ALWAYS_FATAL_IF(!policy && !overridePolicy, "Can only clear the override policy");
if (!display->isPrimary()) {
- // TODO(b/144711714): For non-primary displays we should be able to set an active config
+ // TODO(b/144711714): For non-primary displays we should be able to set an active mode
// as well. For now, just call directly to initiateModeChange but ideally
- // it should go thru setDesiredActiveConfig, similar to primary display.
- ALOGV("setAllowedDisplayConfigsInternal for non-primary display");
+ // it should go thru setDesiredActiveMode, similar to primary display.
+ ALOGV("%s for non-primary display", __func__);
const auto displayId = display->getPhysicalId();
hal::VsyncPeriodChangeConstraints constraints;
@@ -6070,23 +6089,22 @@
constraints.seamlessRequired = false;
hal::VsyncPeriodChangeTimeline timeline = {0, 0, 0};
- if (display->initiateModeChange(policy->defaultConfig, constraints, &timeline) !=
- NO_ERROR) {
+ if (display->initiateModeChange(policy->defaultMode, constraints, &timeline) != NO_ERROR) {
return BAD_VALUE;
}
if (timeline.refreshRequired) {
repaintEverythingForHWC();
}
- display->setActiveMode(policy->defaultConfig);
- const nsecs_t vsyncPeriod = display->getMode(policy->defaultConfig)->getVsyncPeriod();
- mScheduler->onNonPrimaryDisplayConfigChanged(mAppConnectionHandle, displayId,
- policy->defaultConfig, vsyncPeriod);
+ display->setActiveMode(policy->defaultMode);
+ const nsecs_t vsyncPeriod = display->getMode(policy->defaultMode)->getVsyncPeriod();
+ mScheduler->onNonPrimaryDisplayModeChanged(mAppConnectionHandle, displayId,
+ policy->defaultMode, vsyncPeriod);
return NO_ERROR;
}
- if (mDebugDisplayConfigSetByBackdoor) {
- // ignore this request as config is overridden by backdoor
+ if (mDebugDisplayModeSetByBackdoor) {
+ // ignore this request as mode is overridden by backdoor
return NO_ERROR;
}
@@ -6101,42 +6119,43 @@
}
scheduler::RefreshRateConfigs::Policy currentPolicy = mRefreshRateConfigs->getCurrentPolicy();
- ALOGV("Setting desired display config specs: %s", currentPolicy.toString().c_str());
+ ALOGV("Setting desired display mode specs: %s", currentPolicy.toString().c_str());
// TODO(b/140204874): Leave the event in until we do proper testing with all apps that might
// be depending in this callback.
- const auto activeConfig = display->getActiveMode();
- const nsecs_t vsyncPeriod = activeConfig->getVsyncPeriod();
+ const auto activeMode = display->getActiveMode();
+ const nsecs_t vsyncPeriod = activeMode->getVsyncPeriod();
const auto physicalId = display->getPhysicalId();
- mScheduler->onPrimaryDisplayConfigChanged(mAppConnectionHandle, physicalId,
- activeConfig->getId(), vsyncPeriod);
+ mScheduler->onPrimaryDisplayModeChanged(mAppConnectionHandle, physicalId, activeMode->getId(),
+ vsyncPeriod);
toggleKernelIdleTimer();
- auto configId = mScheduler->getPreferredConfigId();
- auto preferredRefreshRate = configId
- ? mRefreshRateConfigs->getRefreshRateFromConfigId(*configId)
- // NOTE: Choose the default config ID, if Scheduler doesn't have one in mind.
- : mRefreshRateConfigs->getRefreshRateFromConfigId(currentPolicy.defaultConfig);
- ALOGV("trying to switch to Scheduler preferred config %zu (%s)",
- preferredRefreshRate.getConfigId().value(), preferredRefreshRate.getName().c_str());
+ auto modeId = mScheduler->getPreferredModeId();
+ auto preferredRefreshRate = modeId
+ ? mRefreshRateConfigs->getRefreshRateFromModeId(*modeId)
+ // NOTE: Choose the default mode ID, if Scheduler doesn't have one in mind.
+ : mRefreshRateConfigs->getRefreshRateFromModeId(currentPolicy.defaultMode);
+ ALOGV("trying to switch to Scheduler preferred mode %zu (%s)",
+ preferredRefreshRate.getModeId().value(), preferredRefreshRate.getName().c_str());
- if (isDisplayConfigAllowed(preferredRefreshRate.getConfigId())) {
- ALOGV("switching to Scheduler preferred config %zu",
- preferredRefreshRate.getConfigId().value());
- setDesiredActiveConfig(
- {preferredRefreshRate.getConfigId(), Scheduler::ConfigEvent::Changed});
+ if (isDisplayModeAllowed(preferredRefreshRate.getModeId())) {
+ ALOGV("switching to Scheduler preferred display mode %zu",
+ preferredRefreshRate.getModeId().value());
+ setDesiredActiveMode({preferredRefreshRate.getModeId(), Scheduler::ModeEvent::Changed});
} else {
- LOG_ALWAYS_FATAL("Desired config not allowed: %zu",
- preferredRefreshRate.getConfigId().value());
+ LOG_ALWAYS_FATAL("Desired display mode not allowed: %zu",
+ preferredRefreshRate.getModeId().value());
}
return NO_ERROR;
}
-status_t SurfaceFlinger::setDesiredDisplayConfigSpecs(
- const sp<IBinder>& displayToken, int32_t defaultConfig, bool allowGroupSwitching,
- float primaryRefreshRateMin, float primaryRefreshRateMax, float appRequestRefreshRateMin,
- float appRequestRefreshRateMax) {
+status_t SurfaceFlinger::setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken,
+ size_t defaultMode, bool allowGroupSwitching,
+ float primaryRefreshRateMin,
+ float primaryRefreshRateMax,
+ float appRequestRefreshRateMin,
+ float appRequestRefreshRateMax) {
ATRACE_CALL();
if (!displayToken) {
@@ -6146,34 +6165,34 @@
auto future = schedule([=]() -> status_t {
const auto display = ON_MAIN_THREAD(getDisplayDeviceLocked(displayToken));
if (!display) {
- ALOGE("Attempt to set desired display configs for invalid display token %p",
+ ALOGE("Attempt to set desired display modes for invalid display token %p",
displayToken.get());
return NAME_NOT_FOUND;
} else if (display->isVirtual()) {
- ALOGW("Attempt to set desired display configs for virtual display");
+ ALOGW("Attempt to set desired display modes for virtual display");
return INVALID_OPERATION;
} else {
using Policy = scheduler::RefreshRateConfigs::Policy;
- const Policy policy{DisplayModeId(defaultConfig),
+ const Policy policy{DisplayModeId(defaultMode),
allowGroupSwitching,
{Fps(primaryRefreshRateMin), Fps(primaryRefreshRateMax)},
{Fps(appRequestRefreshRateMin), Fps(appRequestRefreshRateMax)}};
constexpr bool kOverridePolicy = false;
- return setDesiredDisplayConfigSpecsInternal(display, policy, kOverridePolicy);
+ return setDesiredDisplayModeSpecsInternal(display, policy, kOverridePolicy);
}
});
return future.get();
}
-status_t SurfaceFlinger::getDesiredDisplayConfigSpecs(
- const sp<IBinder>& displayToken, int32_t* outDefaultConfig, bool* outAllowGroupSwitching,
+status_t SurfaceFlinger::getDesiredDisplayModeSpecs(
+ const sp<IBinder>& displayToken, size_t* outDefaultMode, bool* outAllowGroupSwitching,
float* outPrimaryRefreshRateMin, float* outPrimaryRefreshRateMax,
float* outAppRequestRefreshRateMin, float* outAppRequestRefreshRateMax) {
ATRACE_CALL();
- if (!displayToken || !outDefaultConfig || !outPrimaryRefreshRateMin ||
+ if (!displayToken || !outDefaultMode || !outPrimaryRefreshRateMin ||
!outPrimaryRefreshRateMax || !outAppRequestRefreshRateMin || !outAppRequestRefreshRateMax) {
return BAD_VALUE;
}
@@ -6187,7 +6206,7 @@
if (display->isPrimary()) {
scheduler::RefreshRateConfigs::Policy policy =
mRefreshRateConfigs->getDisplayManagerPolicy();
- *outDefaultConfig = policy.defaultConfig.value();
+ *outDefaultMode = policy.defaultMode.value();
*outAllowGroupSwitching = policy.allowGroupSwitching;
*outPrimaryRefreshRateMin = policy.primaryRange.min.getValue();
*outPrimaryRefreshRateMax = policy.primaryRange.max.getValue();
@@ -6198,7 +6217,7 @@
return INVALID_OPERATION;
} else {
const auto activeMode = display->getActiveMode();
- *outDefaultConfig = activeMode->getId().value();
+ *outDefaultMode = activeMode->getId().value();
*outAllowGroupSwitching = false;
auto vsyncPeriod = activeMode->getVsyncPeriod();
*outPrimaryRefreshRateMin = Fps::fromPeriodNsecs(vsyncPeriod).getValue();
@@ -6328,16 +6347,15 @@
const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());
// This is a little racy, but not in a way that hurts anything. As we grab the
- // defaultConfig from the display manager policy, we could be setting a new display
- // manager policy, leaving us using a stale defaultConfig. The defaultConfig doesn't
+ // defaultMode from the display manager policy, we could be setting a new display
+ // manager policy, leaving us using a stale defaultMode. The defaultMode doesn't
// matter for the override policy though, since we set allowGroupSwitching to
// true, so it's not a problem.
scheduler::RefreshRateConfigs::Policy overridePolicy;
- overridePolicy.defaultConfig =
- mRefreshRateConfigs->getDisplayManagerPolicy().defaultConfig;
+ overridePolicy.defaultMode = mRefreshRateConfigs->getDisplayManagerPolicy().defaultMode;
overridePolicy.allowGroupSwitching = true;
constexpr bool kOverridePolicy = true;
- result = setDesiredDisplayConfigSpecsInternal(display, overridePolicy, kOverridePolicy);
+ result = setDesiredDisplayModeSpecsInternal(display, overridePolicy, kOverridePolicy);
}
if (result == NO_ERROR) {
@@ -6377,27 +6395,27 @@
if (mFrameRateFlexibilityTokenCount == 0) {
const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());
constexpr bool kOverridePolicy = true;
- status_t result = setDesiredDisplayConfigSpecsInternal(display, {}, kOverridePolicy);
+ status_t result = setDesiredDisplayModeSpecsInternal(display, {}, kOverridePolicy);
LOG_ALWAYS_FATAL_IF(result < 0, "Failed releasing frame rate flexibility token");
}
}));
}
-status_t SurfaceFlinger::setFrameTimelineVsync(const sp<IGraphicBufferProducer>& surface,
- int64_t frameTimelineVsyncId) {
+status_t SurfaceFlinger::setFrameTimelineInfo(const sp<IGraphicBufferProducer>& surface,
+ const FrameTimelineInfo& frameTimelineInfo) {
Mutex::Autolock lock(mStateLock);
if (!authenticateSurfaceTextureLocked(surface)) {
- ALOGE("Attempt to set frame timeline vsync on an unrecognized IGraphicBufferProducer");
+ 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 vsync on a layer that no longer exists");
+ ALOGE("Attempt to set frame timeline info on a layer that no longer exists");
return BAD_VALUE;
}
- layer->setFrameTimelineVsyncForBuffer(frameTimelineVsyncId);
+ layer->setFrameTimelineInfoForBuffer(frameTimelineInfo);
return NO_ERROR;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index e82095b..ed5b098 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -64,7 +64,7 @@
#include "SurfaceFlingerFactory.h"
#include "SurfaceTracing.h"
#include "TracedOrdinal.h"
-#include "TransactionCompletedThread.h"
+#include "TransactionCallbackInvoker.h"
#include <atomic>
#include <cstdint>
@@ -319,8 +319,8 @@
void removeFromOffscreenLayers(Layer* layer);
- TransactionCompletedThread& getTransactionCompletedThread() {
- return mTransactionCompletedThread;
+ TransactionCallbackInvoker& getTransactionCallbackInvoker() {
+ return mTransactionCallbackInvoker;
}
// Converts from a binder handle to a Layer
@@ -343,10 +343,10 @@
virtual ~SurfaceFlinger();
virtual uint32_t setClientStateLocked(
- int64_t frameTimelineVsyncId, const ComposerState& composerState,
+ const FrameTimelineInfo& info, const ComposerState& composerState,
int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, bool privileged,
- std::unordered_set<ListenerCallbacks, ListenerCallbacksHash>& listenerCallbacks,
- int originPid, int originUid) REQUIRES(mStateLock);
+ std::unordered_set<ListenerCallbacks, ListenerCallbacksHash>& listenerCallbacks)
+ REQUIRES(mStateLock);
virtual void commitTransactionLocked();
// Used internally by computeLayerBounds() to gets the clip rectangle to use for the
@@ -414,12 +414,12 @@
void traverseInReverseZOrder(const LayerVector::Visitor& visitor) const;
};
- struct ActiveConfigInfo {
- DisplayModeId configId;
- Scheduler::ConfigEvent event = Scheduler::ConfigEvent::None;
+ struct ActiveModeInfo {
+ DisplayModeId modeId;
+ Scheduler::ModeEvent event = Scheduler::ModeEvent::None;
- bool operator!=(const ActiveConfigInfo& other) const {
- return configId != other.configId || event != other.event;
+ bool operator!=(const ActiveModeInfo& other) const {
+ return modeId != other.modeId || event != other.event;
}
};
@@ -435,17 +435,21 @@
};
struct TransactionState {
- TransactionState(int64_t frameTimelineVsyncId, const Vector<ComposerState>& composerStates,
+ TransactionState(const FrameTimelineInfo& frameTimelineInfo,
+ const Vector<ComposerState>& composerStates,
const Vector<DisplayState>& displayStates, uint32_t transactionFlags,
- int64_t desiredPresentTime, bool isAutoTimestamp,
- const client_cache_t& uncacheBuffer, int64_t postTime, bool privileged,
- bool hasListenerCallbacks,
+ const sp<IBinder>& applyToken,
+ const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
+ bool isAutoTimestamp, const client_cache_t& uncacheBuffer,
+ int64_t postTime, bool privileged, bool hasListenerCallbacks,
std::vector<ListenerCallbacks> listenerCallbacks, int originPid,
int originUid, uint64_t transactionId)
- : frameTimelineVsyncId(frameTimelineVsyncId),
+ : frameTimelineInfo(frameTimelineInfo),
states(composerStates),
displays(displayStates),
flags(transactionFlags),
+ applyToken(applyToken),
+ inputWindowCommands(inputWindowCommands),
desiredPresentTime(desiredPresentTime),
isAutoTimestamp(isAutoTimestamp),
buffer(uncacheBuffer),
@@ -457,10 +461,12 @@
originUid(originUid),
id(transactionId) {}
- int64_t frameTimelineVsyncId;
+ FrameTimelineInfo frameTimelineInfo;
Vector<ComposerState> states;
Vector<DisplayState> displays;
uint32_t flags;
+ sp<IBinder> applyToken;
+ InputWindowCommands inputWindowCommands;
const int64_t desiredPresentTime;
const bool isAutoTimestamp;
client_cache_t buffer;
@@ -522,7 +528,8 @@
void destroyDisplay(const sp<IBinder>& displayToken) override;
std::vector<PhysicalDisplayId> getPhysicalDisplayIds() const override;
sp<IBinder> getPhysicalDisplayToken(PhysicalDisplayId displayId) const override;
- status_t setTransactionState(int64_t frameTimelineVsyncId, const Vector<ComposerState>& state,
+ status_t setTransactionState(const FrameTimelineInfo& frameTimelineInfo,
+ const Vector<ComposerState>& state,
const Vector<DisplayState>& displays, uint32_t flags,
const sp<IBinder>& applyToken,
const InputWindowCommands& inputWindowCommands,
@@ -547,8 +554,8 @@
status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats) override;
status_t getDisplayState(const sp<IBinder>& displayToken, ui::DisplayState*) override;
status_t getDisplayInfo(const sp<IBinder>& displayToken, DisplayInfo*) override;
- status_t getDisplayConfigs(const sp<IBinder>& displayToken, Vector<DisplayConfig>*) override;
- int getActiveConfig(const sp<IBinder>& displayToken) override;
+ status_t getDisplayModes(const sp<IBinder>& displayToken, Vector<ui::DisplayMode>*) override;
+ int getActiveDisplayModeId(const sp<IBinder>& displayToken) override;
status_t getDisplayColorModes(const sp<IBinder>& displayToken, Vector<ui::ColorMode>*) override;
status_t getDisplayNativePrimaries(const sp<IBinder>& displayToken,
ui::DisplayPrimaries&) override;
@@ -587,17 +594,16 @@
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 setDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken, int32_t displayModeId,
- bool allowGroupSwitching, float primaryRefreshRateMin,
- float primaryRefreshRateMax,
- float appRequestRefreshRateMin,
- float appRequestRefreshRateMax) override;
- status_t getDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
- int32_t* outDefaultConfig, bool* outAllowGroupSwitching,
- float* outPrimaryRefreshRateMin,
- float* outPrimaryRefreshRateMax,
- float* outAppRequestRefreshRateMin,
- float* outAppRequestRefreshRateMax) override;
+ status_t setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, size_t displayModeId,
+ bool allowGroupSwitching, float primaryRefreshRateMin,
+ float primaryRefreshRateMax, float appRequestRefreshRateMin,
+ float appRequestRefreshRateMax) override;
+ status_t getDesiredDisplayModeSpecs(const sp<IBinder>& displayToken, size_t* outDefaultMode,
+ bool* outAllowGroupSwitching,
+ float* outPrimaryRefreshRateMin,
+ float* outPrimaryRefreshRateMax,
+ float* outAppRequestRefreshRateMin,
+ float* outAppRequestRefreshRateMax) override;
status_t getDisplayBrightnessSupport(const sp<IBinder>& displayToken,
bool* outSupport) const override;
status_t setDisplayBrightness(const sp<IBinder>& displayToken, float brightness) override;
@@ -608,8 +614,8 @@
int8_t compatibility, bool shouldBeSeamless) override;
status_t acquireFrameRateFlexibilityToken(sp<IBinder>* outToken) override;
- status_t setFrameTimelineVsync(const sp<IGraphicBufferProducer>& surface,
- int64_t frameTimelineVsyncId) override;
+ status_t setFrameTimelineInfo(const sp<IGraphicBufferProducer>& surface,
+ const FrameTimelineInfo& frameTimelineInfo) override;
status_t addTransactionTraceListener(
const sp<gui::ITransactionTraceListener>& listener) override;
@@ -642,7 +648,7 @@
// Toggles hardware VSYNC by calling into HWC.
void setVsyncEnabled(bool) override;
// Initiates a refresh rate change to be applied on invalidate.
- void changeRefreshRate(const Scheduler::RefreshRate&, Scheduler::ConfigEvent) override;
+ void changeRefreshRate(const Scheduler::RefreshRate&, Scheduler::ModeEvent) override;
// Forces full composition on all displays without resetting the scheduler idle timer.
void repaintEverythingForHWC() override;
// Called when kernel idle timer has expired. Used to update the refresh rate overlay.
@@ -670,24 +676,24 @@
// Called on the main thread in response to initializeDisplays()
void onInitializeDisplays() REQUIRES(mStateLock);
- // Sets the desired active config bit. It obtains the lock, and sets mDesiredActiveConfig.
- void setDesiredActiveConfig(const ActiveConfigInfo& info) REQUIRES(mStateLock);
- status_t setActiveConfig(const sp<IBinder>& displayToken, int id);
- // Once HWC has returned the present fence, this sets the active config and a new refresh
+ // Sets the desired active mode bit. It obtains the lock, and sets mDesiredActiveMode.
+ void setDesiredActiveMode(const ActiveModeInfo& info) REQUIRES(mStateLock);
+ status_t setActiveMode(const sp<IBinder>& displayToken, int id);
+ // Once HWC has returned the present fence, this sets the active mode and a new refresh
// rate in SF.
- void setActiveConfigInternal() REQUIRES(mStateLock);
- // Calls to setActiveConfig on the main thread if there is a pending config
+ void setActiveModeInternal() REQUIRES(mStateLock);
+ // Calls to setActiveMode on the main thread if there is a pending mode change
// that needs to be applied.
- void performSetActiveConfig() REQUIRES(mStateLock);
- void clearDesiredActiveConfigState() REQUIRES(mStateLock) EXCLUDES(mActiveConfigLock);
- // Called when active config is no longer is progress
- void desiredActiveConfigChangeDone() REQUIRES(mStateLock);
+ void performSetActiveMode() REQUIRES(mStateLock);
+ void clearDesiredActiveModeState() REQUIRES(mStateLock) EXCLUDES(mActiveModeLock);
+ // Called when active mode is no longer is progress
+ void desiredActiveModeChangeDone() REQUIRES(mStateLock);
// Called on the main thread in response to setPowerMode()
void setPowerModeInternal(const sp<DisplayDevice>& display, hal::PowerMode mode)
REQUIRES(mStateLock);
- // Sets the desired display configs.
- status_t setDesiredDisplayConfigSpecsInternal(
+ // Sets the desired display mode specs.
+ status_t setDesiredDisplayModeSpecsInternal(
const sp<DisplayDevice>& display,
const std::optional<scheduler::RefreshRateConfigs::Policy>& policy, bool overridePolicy)
EXCLUDES(mStateLock);
@@ -727,17 +733,17 @@
/*
* Transactions
*/
- void applyTransactionState(int64_t frameTimelineVsyncId, const Vector<ComposerState>& state,
+ void applyTransactionState(const FrameTimelineInfo& info, const Vector<ComposerState>& state,
const Vector<DisplayState>& displays, uint32_t flags,
const InputWindowCommands& inputWindowCommands,
const int64_t desiredPresentTime, bool isAutoTimestamp,
const client_cache_t& uncacheBuffer, const int64_t postTime,
bool privileged, bool hasListenerCallbacks,
const std::vector<ListenerCallbacks>& listenerCallbacks,
- int originPid, int originUid, uint64_t transactionId,
- bool isMainThread = false) REQUIRES(mStateLock);
- // Returns true if at least one transaction was flushed
- bool flushTransactionQueues();
+ int originPid, int originUid, uint64_t transactionId)
+ REQUIRES(mStateLock);
+ // flush pending transaction that was presented after desiredPresentTime.
+ void flushTransactionQueues();
// Returns true if there is at least one transaction that needs to be flushed
bool transactionFlushNeeded();
uint32_t getTransactionFlags(uint32_t flags);
@@ -753,9 +759,11 @@
uint32_t setTransactionFlags(uint32_t flags, TransactionSchedule);
void commitTransaction() REQUIRES(mStateLock);
void commitOffscreenLayers();
- bool transactionIsReadyToBeApplied(bool isAutoTimestamp, int64_t desiredPresentTime,
- const Vector<ComposerState>& states,
- bool updateTransactionCounters = false) REQUIRES(mStateLock);
+ bool transactionIsReadyToBeApplied(
+ bool isAutoTimestamp, int64_t desiredPresentTime, const Vector<ComposerState>& states,
+ bool updateTransactionCounters,
+ std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>>& pendingBuffers)
+ REQUIRES(mStateLock);
uint32_t setDisplayStateLocked(const DisplayState& s) REQUIRES(mStateLock);
uint32_t addInputWindowCommands(const InputWindowCommands& inputWindowCommands)
REQUIRES(mStateLock);
@@ -810,13 +818,14 @@
void startBootAnim();
status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, ui::Size bufferSize,
- ui::PixelFormat, const bool allowProtected,
+ ui::PixelFormat, bool allowProtected, bool grayscale,
const sp<IScreenCaptureListener>&);
status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, sp<GraphicBuffer>&,
- bool regionSampling, const sp<IScreenCaptureListener>&);
+ bool regionSampling, bool grayscale,
+ const sp<IScreenCaptureListener>&);
status_t renderScreenImplLocked(const RenderArea&, TraverseLayersFunction,
const sp<GraphicBuffer>&, bool forSystem, bool regionSampling,
- ScreenCaptureResults&);
+ bool grayscale, ScreenCaptureResults&);
sp<DisplayDevice> getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) REQUIRES(mStateLock);
sp<DisplayDevice> getDisplayByLayerStack(uint64_t layerStack) REQUIRES(mStateLock);
@@ -894,6 +903,7 @@
/*
* Display management
*/
+ DisplayModes loadSupportedDisplayModes(PhysicalDisplayId) const;
sp<DisplayDevice> setupNewDisplayDeviceInternal(
const wp<IBinder>& displayToken,
std::shared_ptr<compositionengine::Display> compositionDisplay,
@@ -918,9 +928,9 @@
// Sets the refresh rate by switching active configs, if they are available for
// the desired refresh rate.
- void changeRefreshRateLocked(const RefreshRate&, Scheduler::ConfigEvent) REQUIRES(mStateLock);
+ void changeRefreshRateLocked(const RefreshRate&, Scheduler::ModeEvent) REQUIRES(mStateLock);
- bool isDisplayConfigAllowed(DisplayModeId configId) const REQUIRES(mStateLock);
+ bool isDisplayModeAllowed(DisplayModeId) const REQUIRES(mStateLock);
// Gets the fence for the previous frame.
// Must be called on the main thread.
@@ -1019,6 +1029,8 @@
void onFrameRateFlexibilityTokenReleased();
+ static mat4 calculateColorMatrix(float saturation);
+
void updateColorMatrixLocked();
// Verify that transaction is being called by an approved process:
@@ -1034,9 +1046,9 @@
* Misc
*/
- std::optional<ActiveConfigInfo> getDesiredActiveConfig() EXCLUDES(mActiveConfigLock) {
- std::lock_guard<std::mutex> lock(mActiveConfigLock);
- if (mDesiredActiveConfigChanged) return mDesiredActiveConfig;
+ std::optional<ActiveModeInfo> getDesiredActiveMode() EXCLUDES(mActiveModeLock) {
+ std::lock_guard<std::mutex> lock(mActiveModeLock);
+ if (mDesiredActiveModeChanged) return mDesiredActiveMode;
return std::nullopt;
}
@@ -1148,7 +1160,7 @@
std::atomic<uint32_t> mHwcFrameMissedCount = 0;
std::atomic<uint32_t> mGpuFrameMissedCount = 0;
- TransactionCompletedThread mTransactionCompletedThread;
+ TransactionCallbackInvoker mTransactionCallbackInvoker;
// Restrict layers to use two buffers in their bufferqueues.
bool mLayerTripleBufferingDisabled = false;
@@ -1172,8 +1184,11 @@
uint32_t mTexturePoolSize = 0;
std::vector<uint32_t> mTexturePool;
- std::unordered_map<sp<IBinder>, std::queue<TransactionState>, IListenerHash> mTransactionQueues;
-
+ mutable Mutex mQueueLock;
+ Condition mTransactionQueueCV;
+ std::unordered_map<sp<IBinder>, std::queue<TransactionState>, IListenerHash>
+ mPendingTransactionQueues GUARDED_BY(mQueueLock);
+ std::queue<TransactionState> mTransactionQueue GUARDED_BY(mQueueLock);
/*
* Feature prototyping
*/
@@ -1230,18 +1245,18 @@
nsecs_t mScheduledPresentTime = 0;
hal::Vsync mHWCVsyncPendingState = hal::Vsync::DISABLE;
- std::mutex mActiveConfigLock;
- // This bit is set once we start setting the config. We read from this bit during the
- // process. If at the end, this bit is different than mDesiredActiveConfig, we restart
+ std::mutex mActiveModeLock;
+ // This bit is set once we start setting the mode. We read from this bit during the
+ // process. If at the end, this bit is different than mDesiredActiveMode, we restart
// the process.
- ActiveConfigInfo mUpcomingActiveConfig; // Always read and written on the main thread.
- // This bit can be set at any point in time when the system wants the new config.
- ActiveConfigInfo mDesiredActiveConfig GUARDED_BY(mActiveConfigLock);
+ ActiveModeInfo mUpcomingActiveMode; // Always read and written on the main thread.
+ // This bit can be set at any point in time when the system wants the new mode.
+ ActiveModeInfo mDesiredActiveMode GUARDED_BY(mActiveModeLock);
// below flags are set by main thread only
- TracedOrdinal<bool> mDesiredActiveConfigChanged
- GUARDED_BY(mActiveConfigLock) = {"DesiredActiveConfigChanged", false};
- bool mSetActiveConfigPending = false;
+ TracedOrdinal<bool> mDesiredActiveModeChanged
+ GUARDED_BY(mActiveModeLock) = {"DesiredActiveModeChanged", false};
+ bool mSetActiveModePending = false;
bool mLumaSampling = true;
sp<RegionSamplingThread> mRegionSamplingThread;
@@ -1251,7 +1266,6 @@
const float mEmulatedDisplayDensity;
sp<os::IInputFlinger> mInputFlinger;
- InputWindowCommands mPendingInputWindowCommands GUARDED_BY(mStateLock);
// Should only be accessed by the main thread.
InputWindowCommands mInputWindowCommands;
@@ -1266,8 +1280,8 @@
void enableRefreshRateOverlay(bool enable);
std::unique_ptr<RefreshRateOverlay> mRefreshRateOverlay GUARDED_BY(mStateLock);
- // Flag used to set override allowed display configs from backdoor
- bool mDebugDisplayConfigSetByBackdoor = false;
+ // Flag used to set override desired display mode from backdoor
+ bool mDebugDisplayModeSetByBackdoor = false;
// A set of layers that have no parent so they are not drawn on screen.
// Should only be accessed by the main thread.
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index 3548923..61005c9 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -150,7 +150,6 @@
layer_state_t::eLayerHidden | layer_state_t::eLayerOpaque |
layer_state_t::eLayerSecure);
addReparentLocked(transaction, layerId, getLayerIdFromWeakRef(layer->mCurrentParent));
- addDetachChildrenLocked(transaction, layerId, layer->isLayerDetached());
addRelativeParentLocked(transaction, layerId,
getLayerIdFromWeakRef(layer->mCurrentState.zOrderRelativeOf),
layer->mCurrentState.z);
@@ -409,13 +408,6 @@
overrideChange->set_parent_id(parentId);
}
-void SurfaceInterceptor::addDetachChildrenLocked(Transaction* transaction, int32_t layerId,
- bool detached) {
- SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
- DetachChildrenChange* overrideChange(change->mutable_detach_children());
- overrideChange->set_detach_children(detached);
-}
-
void SurfaceInterceptor::addRelativeParentLocked(Transaction* transaction, int32_t layerId,
int32_t parentId, int z) {
SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
@@ -498,9 +490,6 @@
addReparentChildrenLocked(transaction, layerId,
getLayerIdFromHandle(state.reparentSurfaceControl->getHandle()));
}
- if (state.what & layer_state_t::eDetachChildren) {
- addDetachChildrenLocked(transaction, layerId, true);
- }
if (state.what & layer_state_t::eRelativeLayerChanged) {
addRelativeParentLocked(transaction, layerId,
getLayerIdFromHandle(
diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h
index 3df79c6..3e27e83 100644
--- a/services/surfaceflinger/SurfaceInterceptor.h
+++ b/services/surfaceflinger/SurfaceInterceptor.h
@@ -177,7 +177,6 @@
uint64_t transactionId);
void addReparentLocked(Transaction* transaction, int32_t layerId, int32_t parentId);
void addReparentChildrenLocked(Transaction* transaction, int32_t layerId, int32_t parentId);
- void addDetachChildrenLocked(Transaction* transaction, int32_t layerId, bool detached);
void addRelativeParentLocked(Transaction* transaction, int32_t layerId, int32_t parentId,
int z);
void addShadowRadiusLocked(Transaction* transaction, int32_t layerId, float shadowRadius);
diff --git a/services/surfaceflinger/TransactionCallbackInvoker.cpp b/services/surfaceflinger/TransactionCallbackInvoker.cpp
new file mode 100644
index 0000000..a78510e
--- /dev/null
+++ b/services/surfaceflinger/TransactionCallbackInvoker.cpp
@@ -0,0 +1,298 @@
+/*
+ * Copyright 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"
+
+//#define LOG_NDEBUG 0
+#undef LOG_TAG
+#define LOG_TAG "TransactionCallbackInvoker"
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include "TransactionCallbackInvoker.h"
+
+#include <cinttypes>
+
+#include <binder/IInterface.h>
+#include <utils/RefBase.h>
+
+namespace android {
+
+// Returns 0 if they are equal
+// <0 if the first id that doesn't match is lower in c2 or all ids match but c2 is shorter
+// >0 if the first id that doesn't match is greater in c2 or all ids match but c2 is longer
+//
+// See CallbackIdsHash for a explaniation of why this works
+static int compareCallbackIds(const std::vector<CallbackId>& c1,
+ const std::vector<CallbackId>& c2) {
+ if (c1.empty()) {
+ return !c2.empty();
+ }
+ return c1.front() - c2.front();
+}
+
+TransactionCallbackInvoker::~TransactionCallbackInvoker() {
+ {
+ std::lock_guard lock(mMutex);
+ for (const auto& [listener, transactionStats] : mCompletedTransactions) {
+ listener->unlinkToDeath(mDeathRecipient);
+ }
+ }
+}
+
+status_t TransactionCallbackInvoker::startRegistration(const ListenerCallbacks& listenerCallbacks) {
+ std::lock_guard lock(mMutex);
+
+ auto [itr, inserted] = mRegisteringTransactions.insert(listenerCallbacks);
+ auto& [listener, callbackIds] = listenerCallbacks;
+
+ if (inserted) {
+ if (mCompletedTransactions.count(listener) == 0) {
+ status_t err = listener->linkToDeath(mDeathRecipient);
+ if (err != NO_ERROR) {
+ ALOGE("cannot add callback because linkToDeath failed, err: %d", err);
+ return err;
+ }
+ }
+ auto& transactionStatsDeque = mCompletedTransactions[listener];
+ transactionStatsDeque.emplace_back(callbackIds);
+ }
+
+ return NO_ERROR;
+}
+
+status_t TransactionCallbackInvoker::endRegistration(const ListenerCallbacks& listenerCallbacks) {
+ std::lock_guard lock(mMutex);
+
+ auto itr = mRegisteringTransactions.find(listenerCallbacks);
+ if (itr == mRegisteringTransactions.end()) {
+ ALOGE("cannot end a registration that does not exist");
+ return BAD_VALUE;
+ }
+
+ mRegisteringTransactions.erase(itr);
+
+ return NO_ERROR;
+}
+
+bool TransactionCallbackInvoker::isRegisteringTransaction(
+ const sp<IBinder>& transactionListener, const std::vector<CallbackId>& callbackIds) {
+ ListenerCallbacks listenerCallbacks(transactionListener, callbackIds);
+
+ auto itr = mRegisteringTransactions.find(listenerCallbacks);
+ return itr != mRegisteringTransactions.end();
+}
+
+status_t TransactionCallbackInvoker::registerPendingCallbackHandle(
+ const sp<CallbackHandle>& handle) {
+ std::lock_guard lock(mMutex);
+
+ // If we can't find the transaction stats something has gone wrong. The client should call
+ // startRegistration before trying to register a pending callback handle.
+ TransactionStats* transactionStats;
+ status_t err = findTransactionStats(handle->listener, handle->callbackIds, &transactionStats);
+ if (err != NO_ERROR) {
+ ALOGE("cannot find transaction stats");
+ return err;
+ }
+
+ mPendingTransactions[handle->listener][handle->callbackIds]++;
+ return NO_ERROR;
+}
+
+status_t TransactionCallbackInvoker::finalizePendingCallbackHandles(
+ const std::deque<sp<CallbackHandle>>& handles, const std::vector<JankData>& jankData) {
+ if (handles.empty()) {
+ return NO_ERROR;
+ }
+ std::lock_guard lock(mMutex);
+
+ for (const auto& handle : handles) {
+ auto listener = mPendingTransactions.find(handle->listener);
+ if (listener != mPendingTransactions.end()) {
+ auto& pendingCallbacks = listener->second;
+ auto pendingCallback = pendingCallbacks.find(handle->callbackIds);
+
+ if (pendingCallback != pendingCallbacks.end()) {
+ auto& pendingCount = pendingCallback->second;
+
+ // Decrease the pending count for this listener
+ if (--pendingCount == 0) {
+ pendingCallbacks.erase(pendingCallback);
+ }
+ } else {
+ ALOGW("there are more latched callbacks than there were registered callbacks");
+ }
+ if (listener->second.size() == 0) {
+ mPendingTransactions.erase(listener);
+ }
+ } else {
+ ALOGW("cannot find listener in mPendingTransactions");
+ }
+
+ status_t err = addCallbackHandle(handle, jankData);
+ if (err != NO_ERROR) {
+ ALOGE("could not add callback handle");
+ return err;
+ }
+ }
+
+ return NO_ERROR;
+}
+
+status_t TransactionCallbackInvoker::registerUnpresentedCallbackHandle(
+ const sp<CallbackHandle>& handle) {
+ std::lock_guard lock(mMutex);
+
+ return addCallbackHandle(handle, std::vector<JankData>());
+}
+
+status_t TransactionCallbackInvoker::findTransactionStats(
+ const sp<IBinder>& listener, const std::vector<CallbackId>& callbackIds,
+ TransactionStats** outTransactionStats) {
+ auto& transactionStatsDeque = mCompletedTransactions[listener];
+
+ // Search back to front because the most recent transactions are at the back of the deque
+ auto itr = transactionStatsDeque.rbegin();
+ for (; itr != transactionStatsDeque.rend(); itr++) {
+ if (compareCallbackIds(itr->callbackIds, callbackIds) == 0) {
+ *outTransactionStats = &(*itr);
+ return NO_ERROR;
+ }
+ }
+
+ ALOGE("could not find transaction stats");
+ return BAD_VALUE;
+}
+
+status_t TransactionCallbackInvoker::addCallbackHandle(const sp<CallbackHandle>& handle,
+ const std::vector<JankData>& jankData) {
+ // If we can't find the transaction stats something has gone wrong. The client should call
+ // startRegistration before trying to add a callback handle.
+ TransactionStats* transactionStats;
+ status_t err = findTransactionStats(handle->listener, handle->callbackIds, &transactionStats);
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ transactionStats->latchTime = handle->latchTime;
+ // If the layer has already been destroyed, don't add the SurfaceControl to the callback.
+ // The client side keeps a sp<> to the SurfaceControl so if the SurfaceControl has been
+ // destroyed the client side is dead and there won't be anyone to send the callback to.
+ sp<IBinder> surfaceControl = handle->surfaceControl.promote();
+ if (surfaceControl) {
+ FrameEventHistoryStats eventStats(handle->frameNumber,
+ handle->gpuCompositionDoneFence->getSnapshot().fence,
+ handle->compositorTiming, handle->refreshStartTime,
+ handle->dequeueReadyTime);
+ transactionStats->surfaceStats.emplace_back(surfaceControl, handle->acquireTime,
+ handle->previousReleaseFence,
+ handle->transformHint, eventStats, jankData);
+ }
+ return NO_ERROR;
+}
+
+void TransactionCallbackInvoker::addPresentFence(const sp<Fence>& presentFence) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mPresentFence = presentFence;
+}
+
+void TransactionCallbackInvoker::sendCallbacks() {
+ std::lock_guard lock(mMutex);
+
+ // For each listener
+ auto completedTransactionsItr = mCompletedTransactions.begin();
+ while (completedTransactionsItr != mCompletedTransactions.end()) {
+ auto& [listener, transactionStatsDeque] = *completedTransactionsItr;
+ ListenerStats listenerStats;
+ listenerStats.listener = listener;
+
+ // For each transaction
+ auto transactionStatsItr = transactionStatsDeque.begin();
+ while (transactionStatsItr != transactionStatsDeque.end()) {
+ auto& transactionStats = *transactionStatsItr;
+
+ // If this transaction is still registering, it is not safe to send a callback
+ // because there could be surface controls that haven't been added to
+ // transaction stats or mPendingTransactions.
+ if (isRegisteringTransaction(listener, transactionStats.callbackIds)) {
+ break;
+ }
+
+ // If we are still waiting on the callback handles for this transaction, stop
+ // here because all transaction callbacks for the same listener must come in order
+ auto pendingTransactions = mPendingTransactions.find(listener);
+ if (pendingTransactions != mPendingTransactions.end() &&
+ pendingTransactions->second.count(transactionStats.callbackIds) != 0) {
+ break;
+ }
+
+ // If the transaction has been latched
+ if (transactionStats.latchTime >= 0) {
+ if (!mPresentFence) {
+ break;
+ }
+ transactionStats.presentFence = mPresentFence;
+ }
+
+ // Remove the transaction from completed to the callback
+ listenerStats.transactionStats.push_back(std::move(transactionStats));
+ transactionStatsItr = transactionStatsDeque.erase(transactionStatsItr);
+ }
+ // If the listener has completed transactions
+ if (!listenerStats.transactionStats.empty()) {
+ // If the listener is still alive
+ if (listener->isBinderAlive()) {
+ // Send callback. The listener stored in listenerStats
+ // comes from the cross-process setTransactionState call to
+ // SF. This MUST be an ITransactionCompletedListener. We
+ // keep it as an IBinder due to consistency reasons: if we
+ // interface_cast at the IPC boundary when reading a Parcel,
+ // we get pointers that compare unequal in the SF process.
+ interface_cast<ITransactionCompletedListener>(listenerStats.listener)
+ ->onTransactionCompleted(listenerStats);
+ if (transactionStatsDeque.empty()) {
+ listener->unlinkToDeath(mDeathRecipient);
+ completedTransactionsItr =
+ mCompletedTransactions.erase(completedTransactionsItr);
+ } else {
+ completedTransactionsItr++;
+ }
+ } else {
+ completedTransactionsItr =
+ mCompletedTransactions.erase(completedTransactionsItr);
+ }
+ } else {
+ completedTransactionsItr++;
+ }
+ }
+
+ if (mPresentFence) {
+ mPresentFence.clear();
+ }
+}
+
+// -----------------------------------------------------------------------
+
+CallbackHandle::CallbackHandle(const sp<IBinder>& transactionListener,
+ const std::vector<CallbackId>& ids, const sp<IBinder>& sc)
+ : listener(transactionListener), callbackIds(ids), surfaceControl(sc) {}
+
+} // namespace android
+
+// TODO(b/129481165): remove the #pragma below and fix conversion issues
+#pragma clang diagnostic pop // ignored "-Wconversion"
diff --git a/services/surfaceflinger/TransactionCompletedThread.h b/services/surfaceflinger/TransactionCallbackInvoker.h
similarity index 88%
rename from services/surfaceflinger/TransactionCompletedThread.h
rename to services/surfaceflinger/TransactionCallbackInvoker.h
index c4ba7e4..a240c82 100644
--- a/services/surfaceflinger/TransactionCompletedThread.h
+++ b/services/surfaceflinger/TransactionCallbackInvoker.h
@@ -52,11 +52,9 @@
uint64_t frameNumber = 0;
};
-class TransactionCompletedThread {
+class TransactionCallbackInvoker {
public:
- ~TransactionCompletedThread();
-
- void run();
+ ~TransactionCallbackInvoker();
// Adds listener and callbackIds in case there are no SurfaceControls that are supposed
// to be included in the callback. This functions should be call before attempting to register
@@ -66,13 +64,13 @@
// It is safe to send a callback if the Transaction doesn't have any Pending callback handles.
status_t endRegistration(const ListenerCallbacks& listenerCallbacks);
- // Informs the TransactionCompletedThread that there is a Transaction with a CallbackHandle
+ // Informs the TransactionCallbackInvoker that there is a Transaction with a CallbackHandle
// that needs to be latched and presented this frame. This function should be called once the
- // layer has received the CallbackHandle so the TransactionCompletedThread knows not to send
+ // layer has received the CallbackHandle so the TransactionCallbackInvoker knows not to send
// a callback for that Listener/Transaction pair until that CallbackHandle has been latched and
// presented.
status_t registerPendingCallbackHandle(const sp<CallbackHandle>& handle);
- // Notifies the TransactionCompletedThread that a pending CallbackHandle has been presented.
+ // Notifies the TransactionCallbackInvoker that a pending CallbackHandle has been presented.
status_t finalizePendingCallbackHandles(const std::deque<sp<CallbackHandle>>& handles,
const std::vector<JankData>& jankData);
@@ -85,7 +83,6 @@
void sendCallbacks();
private:
- void threadMain();
bool isRegisteringTransaction(const sp<IBinder>& transactionListener,
const std::vector<CallbackId>& callbackIds) REQUIRES(mMutex);
@@ -97,7 +94,7 @@
status_t addCallbackHandle(const sp<CallbackHandle>& handle,
const std::vector<JankData>& jankData) REQUIRES(mMutex);
- class ThreadDeathRecipient : public IBinder::DeathRecipient {
+ class CallbackDeathRecipient : public IBinder::DeathRecipient {
public:
// This function is a no-op. isBinderAlive needs a linked DeathRecipient to work.
// Death recipients needs a binderDied function.
@@ -106,12 +103,8 @@
// sendObituary is only called if linkToDeath was called with a DeathRecipient.)
void binderDied(const wp<IBinder>& /*who*/) override {}
};
- sp<ThreadDeathRecipient> mDeathRecipient;
-
- // Protects the creation and destruction of mThread
- std::mutex mThreadMutex;
-
- std::thread mThread GUARDED_BY(mThreadMutex);
+ sp<CallbackDeathRecipient> mDeathRecipient =
+ new CallbackDeathRecipient();
std::mutex mMutex;
std::condition_variable_any mConditionVariable;
@@ -128,9 +121,6 @@
std::unordered_map<sp<IBinder>, std::deque<TransactionStats>, IListenerHash>
mCompletedTransactions GUARDED_BY(mMutex);
- bool mRunning GUARDED_BY(mMutex) = false;
- bool mKeepRunning GUARDED_BY(mMutex) = true;
-
sp<Fence> mPresentFence GUARDED_BY(mMutex);
};
diff --git a/services/surfaceflinger/TransactionCompletedThread.cpp b/services/surfaceflinger/TransactionCompletedThread.cpp
deleted file mode 100644
index 1797af4..0000000
--- a/services/surfaceflinger/TransactionCompletedThread.cpp
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- * Copyright 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"
-
-//#define LOG_NDEBUG 0
-#undef LOG_TAG
-#define LOG_TAG "TransactionCompletedThread"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-
-#include "TransactionCompletedThread.h"
-
-#include <cinttypes>
-
-#include <binder/IInterface.h>
-#include <utils/RefBase.h>
-
-namespace android {
-
-// Returns 0 if they are equal
-// <0 if the first id that doesn't match is lower in c2 or all ids match but c2 is shorter
-// >0 if the first id that doesn't match is greater in c2 or all ids match but c2 is longer
-//
-// See CallbackIdsHash for a explaniation of why this works
-static int compareCallbackIds(const std::vector<CallbackId>& c1,
- const std::vector<CallbackId>& c2) {
- if (c1.empty()) {
- return !c2.empty();
- }
- return c1.front() - c2.front();
-}
-
-TransactionCompletedThread::~TransactionCompletedThread() {
- std::lock_guard lockThread(mThreadMutex);
-
- {
- std::lock_guard lock(mMutex);
- mKeepRunning = false;
- mConditionVariable.notify_all();
- }
-
- if (mThread.joinable()) {
- mThread.join();
- }
-
- {
- std::lock_guard lock(mMutex);
- for (const auto& [listener, transactionStats] : mCompletedTransactions) {
- listener->unlinkToDeath(mDeathRecipient);
- }
- }
-}
-
-void TransactionCompletedThread::run() {
- std::lock_guard lock(mMutex);
- if (mRunning || !mKeepRunning) {
- return;
- }
- mDeathRecipient = new ThreadDeathRecipient();
- mRunning = true;
-
- std::lock_guard lockThread(mThreadMutex);
- mThread = std::thread(&TransactionCompletedThread::threadMain, this);
-}
-
-status_t TransactionCompletedThread::startRegistration(const ListenerCallbacks& listenerCallbacks) {
- // begin running if not already running
- run();
- std::lock_guard lock(mMutex);
- if (!mRunning) {
- ALOGE("cannot add callback because the callback thread isn't running");
- return BAD_VALUE;
- }
-
- auto [itr, inserted] = mRegisteringTransactions.insert(listenerCallbacks);
- auto& [listener, callbackIds] = listenerCallbacks;
-
- if (inserted) {
- if (mCompletedTransactions.count(listener) == 0) {
- status_t err = listener->linkToDeath(mDeathRecipient);
- if (err != NO_ERROR) {
- ALOGE("cannot add callback because linkToDeath failed, err: %d", err);
- return err;
- }
- }
- auto& transactionStatsDeque = mCompletedTransactions[listener];
- transactionStatsDeque.emplace_back(callbackIds);
- }
-
- return NO_ERROR;
-}
-
-status_t TransactionCompletedThread::endRegistration(const ListenerCallbacks& listenerCallbacks) {
- std::lock_guard lock(mMutex);
- if (!mRunning) {
- ALOGE("cannot add callback because the callback thread isn't running");
- return BAD_VALUE;
- }
-
- auto itr = mRegisteringTransactions.find(listenerCallbacks);
- if (itr == mRegisteringTransactions.end()) {
- ALOGE("cannot end a registration that does not exist");
- return BAD_VALUE;
- }
-
- mRegisteringTransactions.erase(itr);
-
- return NO_ERROR;
-}
-
-bool TransactionCompletedThread::isRegisteringTransaction(
- const sp<IBinder>& transactionListener, const std::vector<CallbackId>& callbackIds) {
- ListenerCallbacks listenerCallbacks(transactionListener, callbackIds);
-
- auto itr = mRegisteringTransactions.find(listenerCallbacks);
- return itr != mRegisteringTransactions.end();
-}
-
-status_t TransactionCompletedThread::registerPendingCallbackHandle(
- const sp<CallbackHandle>& handle) {
- std::lock_guard lock(mMutex);
- if (!mRunning) {
- ALOGE("cannot register callback handle because the callback thread isn't running");
- return BAD_VALUE;
- }
-
- // If we can't find the transaction stats something has gone wrong. The client should call
- // startRegistration before trying to register a pending callback handle.
- TransactionStats* transactionStats;
- status_t err = findTransactionStats(handle->listener, handle->callbackIds, &transactionStats);
- if (err != NO_ERROR) {
- ALOGE("cannot find transaction stats");
- return err;
- }
-
- mPendingTransactions[handle->listener][handle->callbackIds]++;
- return NO_ERROR;
-}
-
-status_t TransactionCompletedThread::finalizePendingCallbackHandles(
- const std::deque<sp<CallbackHandle>>& handles, const std::vector<JankData>& jankData) {
- if (handles.empty()) {
- return NO_ERROR;
- }
- std::lock_guard lock(mMutex);
- if (!mRunning) {
- ALOGE("cannot add presented callback handle because the callback thread isn't running");
- return BAD_VALUE;
- }
-
- for (const auto& handle : handles) {
- auto listener = mPendingTransactions.find(handle->listener);
- if (listener != mPendingTransactions.end()) {
- auto& pendingCallbacks = listener->second;
- auto pendingCallback = pendingCallbacks.find(handle->callbackIds);
-
- if (pendingCallback != pendingCallbacks.end()) {
- auto& pendingCount = pendingCallback->second;
-
- // Decrease the pending count for this listener
- if (--pendingCount == 0) {
- pendingCallbacks.erase(pendingCallback);
- }
- } else {
- ALOGW("there are more latched callbacks than there were registered callbacks");
- }
- if (listener->second.size() == 0) {
- mPendingTransactions.erase(listener);
- }
- } else {
- ALOGW("cannot find listener in mPendingTransactions");
- }
-
- status_t err = addCallbackHandle(handle, jankData);
- if (err != NO_ERROR) {
- ALOGE("could not add callback handle");
- return err;
- }
- }
-
- return NO_ERROR;
-}
-
-status_t TransactionCompletedThread::registerUnpresentedCallbackHandle(
- const sp<CallbackHandle>& handle) {
- std::lock_guard lock(mMutex);
- if (!mRunning) {
- ALOGE("cannot add unpresented callback handle because the callback thread isn't running");
- return BAD_VALUE;
- }
-
- return addCallbackHandle(handle, std::vector<JankData>());
-}
-
-status_t TransactionCompletedThread::findTransactionStats(
- const sp<IBinder>& listener, const std::vector<CallbackId>& callbackIds,
- TransactionStats** outTransactionStats) {
- auto& transactionStatsDeque = mCompletedTransactions[listener];
-
- // Search back to front because the most recent transactions are at the back of the deque
- auto itr = transactionStatsDeque.rbegin();
- for (; itr != transactionStatsDeque.rend(); itr++) {
- if (compareCallbackIds(itr->callbackIds, callbackIds) == 0) {
- *outTransactionStats = &(*itr);
- return NO_ERROR;
- }
- }
-
- ALOGE("could not find transaction stats");
- return BAD_VALUE;
-}
-
-status_t TransactionCompletedThread::addCallbackHandle(const sp<CallbackHandle>& handle,
- const std::vector<JankData>& jankData) {
- // If we can't find the transaction stats something has gone wrong. The client should call
- // startRegistration before trying to add a callback handle.
- TransactionStats* transactionStats;
- status_t err = findTransactionStats(handle->listener, handle->callbackIds, &transactionStats);
- if (err != NO_ERROR) {
- return err;
- }
-
- transactionStats->latchTime = handle->latchTime;
- // If the layer has already been destroyed, don't add the SurfaceControl to the callback.
- // The client side keeps a sp<> to the SurfaceControl so if the SurfaceControl has been
- // destroyed the client side is dead and there won't be anyone to send the callback to.
- sp<IBinder> surfaceControl = handle->surfaceControl.promote();
- if (surfaceControl) {
- FrameEventHistoryStats eventStats(handle->frameNumber,
- handle->gpuCompositionDoneFence->getSnapshot().fence,
- handle->compositorTiming, handle->refreshStartTime,
- handle->dequeueReadyTime);
- transactionStats->surfaceStats.emplace_back(surfaceControl, handle->acquireTime,
- handle->previousReleaseFence,
- handle->transformHint, eventStats, jankData);
- }
- return NO_ERROR;
-}
-
-void TransactionCompletedThread::addPresentFence(const sp<Fence>& presentFence) {
- std::lock_guard<std::mutex> lock(mMutex);
- mPresentFence = presentFence;
-}
-
-void TransactionCompletedThread::sendCallbacks() {
- std::lock_guard lock(mMutex);
- if (mRunning) {
- mConditionVariable.notify_all();
- }
-}
-
-void TransactionCompletedThread::threadMain() {
- std::lock_guard lock(mMutex);
-
- while (mKeepRunning) {
- mConditionVariable.wait(mMutex);
- std::vector<ListenerStats> completedListenerStats;
-
- // For each listener
- auto completedTransactionsItr = mCompletedTransactions.begin();
- while (completedTransactionsItr != mCompletedTransactions.end()) {
- auto& [listener, transactionStatsDeque] = *completedTransactionsItr;
- ListenerStats listenerStats;
- listenerStats.listener = listener;
-
- // For each transaction
- auto transactionStatsItr = transactionStatsDeque.begin();
- while (transactionStatsItr != transactionStatsDeque.end()) {
- auto& transactionStats = *transactionStatsItr;
-
- // If this transaction is still registering, it is not safe to send a callback
- // because there could be surface controls that haven't been added to
- // transaction stats or mPendingTransactions.
- if (isRegisteringTransaction(listener, transactionStats.callbackIds)) {
- break;
- }
-
- // If we are still waiting on the callback handles for this transaction, stop
- // here because all transaction callbacks for the same listener must come in order
- auto pendingTransactions = mPendingTransactions.find(listener);
- if (pendingTransactions != mPendingTransactions.end() &&
- pendingTransactions->second.count(transactionStats.callbackIds) != 0) {
- break;
- }
-
- // If the transaction has been latched
- if (transactionStats.latchTime >= 0) {
- if (!mPresentFence) {
- break;
- }
- transactionStats.presentFence = mPresentFence;
- }
-
- // Remove the transaction from completed to the callback
- listenerStats.transactionStats.push_back(std::move(transactionStats));
- transactionStatsItr = transactionStatsDeque.erase(transactionStatsItr);
- }
- // If the listener has completed transactions
- if (!listenerStats.transactionStats.empty()) {
- // If the listener is still alive
- if (listener->isBinderAlive()) {
- // Send callback. The listener stored in listenerStats
- // comes from the cross-process setTransactionState call to
- // SF. This MUST be an ITransactionCompletedListener. We
- // keep it as an IBinder due to consistency reasons: if we
- // interface_cast at the IPC boundary when reading a Parcel,
- // we get pointers that compare unequal in the SF process.
- interface_cast<ITransactionCompletedListener>(listenerStats.listener)
- ->onTransactionCompleted(listenerStats);
- if (transactionStatsDeque.empty()) {
- listener->unlinkToDeath(mDeathRecipient);
- completedTransactionsItr =
- mCompletedTransactions.erase(completedTransactionsItr);
- } else {
- completedTransactionsItr++;
- }
- } else {
- completedTransactionsItr =
- mCompletedTransactions.erase(completedTransactionsItr);
- }
- } else {
- completedTransactionsItr++;
- }
-
- completedListenerStats.push_back(std::move(listenerStats));
- }
-
- if (mPresentFence) {
- mPresentFence.clear();
- }
-
- // If everyone else has dropped their reference to a layer and its listener is dead,
- // we are about to cause the layer to be deleted. If this happens at the wrong time and
- // we are holding mMutex, we will cause a deadlock.
- //
- // The deadlock happens because this thread is holding on to mMutex and when we delete
- // the layer, it grabs SF's mStateLock. A different SF binder thread grabs mStateLock,
- // then call's TransactionCompletedThread::run() which tries to grab mMutex.
- //
- // To avoid this deadlock, we need to unlock mMutex when dropping our last reference to
- // to the layer.
- mMutex.unlock();
- completedListenerStats.clear();
- mMutex.lock();
- }
-}
-
-// -----------------------------------------------------------------------
-
-CallbackHandle::CallbackHandle(const sp<IBinder>& transactionListener,
- const std::vector<CallbackId>& ids, const sp<IBinder>& sc)
- : listener(transactionListener), callbackIds(ids), surfaceControl(sc) {}
-
-} // 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/Android.bp b/services/surfaceflinger/tests/Android.bp
index e8b24b4..8142aad 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -21,7 +21,6 @@
"CommonTypes_test.cpp",
"Credentials_test.cpp",
"DereferenceSurfaceControl_test.cpp",
- "DetachChildren_test.cpp",
"DisplayConfigs_test.cpp",
"EffectLayer_test.cpp",
"InvalidHandles_test.cpp",
@@ -50,7 +49,7 @@
"android.hardware.graphics.composer@2.1",
],
shared_libs: [
- "android.hardware.graphics.common-unstable-ndk_platform",
+ "android.hardware.graphics.common-V2-ndk_platform",
"android.hardware.graphics.common@1.2",
"libandroid",
"libbase",
diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp
index 9302463..53e37d8 100644
--- a/services/surfaceflinger/tests/Credentials_test.cpp
+++ b/services/surfaceflinger/tests/Credentials_test.cpp
@@ -25,7 +25,7 @@
#include <gui/SurfaceComposerClient.h>
#include <private/android_filesystem_config.h>
#include <private/gui/ComposerService.h>
-#include <ui/DisplayConfig.h>
+#include <ui/DisplayMode.h>
#include <utils/String8.h>
#include <functional>
#include "utils/ScreenshotUtils.h"
@@ -81,14 +81,13 @@
mDisplay = SurfaceComposerClient::getInternalDisplayToken();
ASSERT_FALSE(mDisplay == nullptr);
- DisplayConfig config;
- ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(mDisplay, &config));
+ ui::DisplayMode mode;
+ ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(mDisplay, &mode));
// Background surface
- mBGSurfaceControl =
- mComposerClient->createSurface(SURFACE_NAME, config.resolution.getWidth(),
- config.resolution.getHeight(),
- PIXEL_FORMAT_RGBA_8888, 0);
+ mBGSurfaceControl = mComposerClient->createSurface(SURFACE_NAME, mode.resolution.getWidth(),
+ mode.resolution.getHeight(),
+ PIXEL_FORMAT_RGBA_8888, 0);
ASSERT_TRUE(mBGSurfaceControl != nullptr);
ASSERT_TRUE(mBGSurfaceControl->isValid());
@@ -185,13 +184,13 @@
const auto display = SurfaceComposerClient::getInternalDisplayToken();
ASSERT_TRUE(display != nullptr);
- DisplayConfig config;
- ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
+ ui::DisplayMode mode;
+ ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode));
- Vector<DisplayConfig> configs;
- ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs));
+ Vector<ui::DisplayMode> modes;
+ ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayModes(display, &modes));
- ASSERT_TRUE(SurfaceComposerClient::getActiveConfig(display) >= 0);
+ ASSERT_TRUE(SurfaceComposerClient::getActiveDisplayModeId(display) >= 0);
ASSERT_NE(static_cast<ui::ColorMode>(BAD_VALUE),
SurfaceComposerClient::getActiveColorMode(display));
@@ -217,25 +216,23 @@
TEST_F(CredentialsTest, SetDesiredDisplayConfigsTest) {
const auto display = SurfaceComposerClient::getInternalDisplayToken();
- int32_t defaultConfig;
+ size_t defaultMode;
bool allowGroupSwitching;
float primaryFpsMin;
float primaryFpsMax;
float appRequestFpsMin;
float appRequestFpsMax;
status_t res =
- SurfaceComposerClient::getDesiredDisplayConfigSpecs(display, &defaultConfig,
- &allowGroupSwitching,
- &primaryFpsMin, &primaryFpsMax,
- &appRequestFpsMin,
- &appRequestFpsMax);
+ SurfaceComposerClient::getDesiredDisplayModeSpecs(display, &defaultMode,
+ &allowGroupSwitching, &primaryFpsMin,
+ &primaryFpsMax, &appRequestFpsMin,
+ &appRequestFpsMax);
ASSERT_EQ(res, NO_ERROR);
std::function<status_t()> condition = [=]() {
- return SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, defaultConfig,
- allowGroupSwitching,
- primaryFpsMin, primaryFpsMax,
- appRequestFpsMin,
- appRequestFpsMax);
+ return SurfaceComposerClient::setDesiredDisplayModeSpecs(display, defaultMode,
+ allowGroupSwitching, primaryFpsMin,
+ primaryFpsMax, appRequestFpsMin,
+ appRequestFpsMax);
};
ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
}
diff --git a/services/surfaceflinger/tests/DetachChildren_test.cpp b/services/surfaceflinger/tests/DetachChildren_test.cpp
deleted file mode 100644
index abf8b1a..0000000
--- a/services/surfaceflinger/tests/DetachChildren_test.cpp
+++ /dev/null
@@ -1,377 +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.
- */
-
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-
-#include "LayerTransactionTest.h"
-
-namespace android {
-
-class DetachChildren : public LayerTransactionTest {
-protected:
- virtual void SetUp() {
- LayerTransactionTest::SetUp();
-
- mMainSurface = createLayer(String8("Main Test Surface"), mMainSurfaceBounds.width(),
- mMainSurfaceBounds.height(), 0, mBlackBgSurface.get());
-
- ASSERT_TRUE(mMainSurface != nullptr);
- ASSERT_TRUE(mMainSurface->isValid());
-
- TransactionUtils::fillSurfaceRGBA8(mMainSurface, mMainSurfaceColor);
-
- asTransaction([&](Transaction& t) {
- t.setLayer(mMainSurface, INT32_MAX - 1)
- .setPosition(mMainSurface, mMainSurfaceBounds.left, mMainSurfaceBounds.top)
- .show(mMainSurface);
- });
- }
-
- virtual void TearDown() {
- LayerTransactionTest::TearDown();
- mMainSurface = 0;
- }
-
- sp<SurfaceControl> mMainSurface;
- Color mMainSurfaceColor = {195, 63, 63, 255};
- Rect mMainSurfaceBounds = Rect(64, 64, 128, 128);
- std::unique_ptr<ScreenCapture> mCapture;
-};
-
-TEST_F(DetachChildren, RelativesAreNotDetached) {
- Color relativeColor = {10, 10, 10, 255};
- Rect relBounds = Rect(64, 64, 74, 74);
-
- sp<SurfaceControl> relative =
- createLayer(String8("relativeTestSurface"), relBounds.width(), relBounds.height(), 0);
- TransactionUtils::fillSurfaceRGBA8(relative, relativeColor);
-
- Transaction{}
- .setRelativeLayer(relative, mMainSurface, 1)
- .setPosition(relative, relBounds.left, relBounds.top)
- .apply();
-
- {
- // The relative should be on top of the FG control.
- mCapture = screenshot();
- mCapture->expectColor(relBounds, relativeColor);
- }
- Transaction{}.detachChildren(mMainSurface).apply();
-
- {
- // Nothing should change at this point.
- mCapture = screenshot();
- mCapture->expectColor(relBounds, relativeColor);
- }
-
- Transaction{}.hide(relative).apply();
-
- {
- // Ensure that the relative was actually hidden, rather than
- // being left in the detached but visible state.
- mCapture = screenshot();
- mCapture->expectColor(mMainSurfaceBounds, mMainSurfaceColor);
- }
-}
-
-TEST_F(DetachChildren, DetachChildrenSameClient) {
- Color childColor = {200, 200, 200, 255};
- Rect childBounds = Rect(74, 74, 84, 84);
- sp<SurfaceControl> child = createLayer(String8("Child surface"), childBounds.width(),
- childBounds.height(), 0, mMainSurface.get());
- ASSERT_TRUE(child->isValid());
-
- TransactionUtils::fillSurfaceRGBA8(child, childColor);
-
- asTransaction([&](Transaction& t) {
- t.show(child);
- t.setPosition(child, childBounds.left - mMainSurfaceBounds.left,
- childBounds.top - mMainSurfaceBounds.top);
- });
-
- {
- mCapture = screenshot();
- // Expect main color around the child surface
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectColor(childBounds, childColor);
- }
-
- asTransaction([&](Transaction& t) { t.detachChildren(mMainSurface); });
-
- asTransaction([&](Transaction& t) { t.hide(child); });
-
- // Since the child has the same client as the parent, it will not get
- // detached and will be hidden.
- {
- mCapture = screenshot();
- mCapture->expectColor(mMainSurfaceBounds, mMainSurfaceColor);
- }
-}
-
-TEST_F(DetachChildren, DetachChildrenDifferentClient) {
- Color childColor = {200, 200, 200, 255};
- Rect childBounds = Rect(74, 74, 84, 84);
-
- sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
- sp<SurfaceControl> childNewClient =
- createSurface(newComposerClient, "New Child Test Surface", childBounds.width(),
- childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
- ASSERT_TRUE(childNewClient->isValid());
-
- TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor);
-
- asTransaction([&](Transaction& t) {
- t.show(childNewClient);
- t.setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left,
- childBounds.top - mMainSurfaceBounds.top);
- });
-
- {
- mCapture = screenshot();
- // Expect main color around the child surface
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectColor(childBounds, childColor);
- }
-
- asTransaction([&](Transaction& t) { t.detachChildren(mMainSurface); });
-
- asTransaction([&](Transaction& t) { t.hide(childNewClient); });
-
- // Nothing should have changed.
- {
- mCapture = screenshot();
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectColor(childBounds, childColor);
- }
-}
-
-TEST_F(DetachChildren, DetachChildrenThenAttach) {
- Color childColor = {200, 200, 200, 255};
- Rect childBounds = Rect(74, 74, 84, 84);
-
- sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
- sp<SurfaceControl> childNewClient =
- createSurface(newComposerClient, "New Child Test Surface", childBounds.width(),
- childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
- ASSERT_TRUE(childNewClient->isValid());
-
- TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor);
-
- Transaction()
- .show(childNewClient)
- .setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left,
- childBounds.top - mMainSurfaceBounds.top)
- .apply();
-
- {
- mCapture = screenshot();
- // Expect main color around the child surface
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectColor(childBounds, childColor);
- }
-
- Transaction().detachChildren(mMainSurface).apply();
- Transaction().hide(childNewClient).apply();
-
- // Nothing should have changed.
- {
- mCapture = screenshot();
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectColor(childBounds, childColor);
- }
-
- Color newParentColor = Color::RED;
- Rect newParentBounds = Rect(20, 20, 52, 52);
- sp<SurfaceControl> newParentSurface =
- createLayer(String8("New Parent Surface"), newParentBounds.width(),
- newParentBounds.height(), 0);
- TransactionUtils::fillSurfaceRGBA8(newParentSurface, newParentColor);
- Transaction()
- .setLayer(newParentSurface, INT32_MAX - 1)
- .show(newParentSurface)
- .setPosition(newParentSurface, newParentBounds.left, newParentBounds.top)
- .reparent(childNewClient, newParentSurface)
- .apply();
- {
- mCapture = screenshot();
- // Child is now hidden.
- mCapture->expectColor(newParentBounds, newParentColor);
- }
-}
-
-TEST_F(DetachChildren, DetachChildrenWithDeferredTransaction) {
- Color childColor = {200, 200, 200, 255};
- Rect childBounds = Rect(74, 74, 84, 84);
-
- sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
- sp<SurfaceControl> childNewClient =
- createSurface(newComposerClient, "New Child Test Surface", childBounds.width(),
- childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
- ASSERT_TRUE(childNewClient->isValid());
-
- TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor);
-
- Transaction()
- .show(childNewClient)
- .setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left,
- childBounds.top - mMainSurfaceBounds.top)
- .apply();
-
- {
- mCapture = screenshot();
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectColor(childBounds, childColor);
- }
-
- Transaction()
- .deferTransactionUntil_legacy(childNewClient, mMainSurface,
- mMainSurface->getSurface()->getNextFrameNumber())
- .apply();
- Transaction().detachChildren(mMainSurface).apply();
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(mMainSurface, Color::RED,
- mMainSurfaceBounds.width(),
- mMainSurfaceBounds.height()));
-
- // BufferLayer can still dequeue buffers even though there's a detached layer with a
- // deferred transaction.
- {
- SCOPED_TRACE("new buffer");
- mCapture = screenshot();
- mCapture->expectBorder(childBounds, Color::RED);
- mCapture->expectColor(childBounds, childColor);
- }
-}
-
-/**
- * Tests that a deferring transaction on an already detached layer will be dropped gracefully and
- * allow the barrier layer to dequeue buffers.
- *
- * Fixes b/150924737 - buffer cannot be latched because it waits for a detached layer
- * to commit its pending states.
- */
-TEST_F(DetachChildren, DeferredTransactionOnDetachedChildren) {
- Color childColor = {200, 200, 200, 255};
- Rect childBounds = Rect(74, 74, 84, 84);
-
- sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
- sp<SurfaceControl> childNewClient =
- createSurface(newComposerClient, "New Child Test Surface", childBounds.width(),
- childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
- ASSERT_TRUE(childNewClient->isValid());
-
- TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor);
-
- Transaction()
- .show(childNewClient)
- .setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left,
- childBounds.top - mMainSurfaceBounds.top)
- .apply();
-
- {
- mCapture = screenshot();
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectColor(childBounds, childColor);
- }
-
- Transaction().detachChildren(mMainSurface).apply();
- Transaction()
- .setCrop_legacy(childNewClient, {0, 0, childBounds.width(), childBounds.height()})
- .deferTransactionUntil_legacy(childNewClient, mMainSurface,
- mMainSurface->getSurface()->getNextFrameNumber())
- .apply();
-
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(mMainSurface, Color::RED,
- mMainSurfaceBounds.width(),
- mMainSurfaceBounds.height()));
-
- // BufferLayer can still dequeue buffers even though there's a detached layer with a
- // deferred transaction.
- {
- SCOPED_TRACE("new buffer");
- mCapture = screenshot();
- mCapture->expectBorder(childBounds, Color::RED);
- mCapture->expectColor(childBounds, childColor);
- }
-}
-
-TEST_F(DetachChildren, ReparentParentLayerOfDetachedChildren) {
- Color childColor = {200, 200, 200, 255};
- Rect childBounds = Rect(74, 74, 94, 94);
- Color grandchildColor = Color::RED;
- Rect grandchildBounds = Rect(80, 80, 90, 90);
-
- sp<SurfaceComposerClient> newClient1 = new SurfaceComposerClient;
- sp<SurfaceComposerClient> newClient2 = new SurfaceComposerClient;
-
- sp<SurfaceControl> childSurface =
- createSurface(newClient1, "Child surface", childBounds.width(), childBounds.height(),
- PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
- sp<SurfaceControl> grandchildSurface =
- createSurface(newClient2, "Grandchild Surface", grandchildBounds.width(),
- grandchildBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, childSurface.get());
-
- TransactionUtils::fillSurfaceRGBA8(childSurface, childColor);
- TransactionUtils::fillSurfaceRGBA8(grandchildSurface, grandchildColor);
-
- Transaction()
- .show(childSurface)
- .show(grandchildSurface)
- .setPosition(childSurface, childBounds.left - mMainSurfaceBounds.left,
- childBounds.top - mMainSurfaceBounds.top)
- .setPosition(grandchildSurface, grandchildBounds.left - childBounds.left,
- grandchildBounds.top - childBounds.top)
- .apply();
-
- {
- mCapture = screenshot();
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectBorder(grandchildBounds, childColor);
- mCapture->expectColor(grandchildBounds, grandchildColor);
- }
-
- Transaction().detachChildren(childSurface).apply();
-
- // Remove main surface offscreen
- Transaction().reparent(mMainSurface, nullptr).apply();
- {
- mCapture = screenshot();
- mCapture->expectColor(mMainSurfaceBounds, Color::BLACK);
- }
-
- Transaction().reparent(mMainSurface, mBlackBgSurface).apply();
- {
- mCapture = screenshot();
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectBorder(grandchildBounds, childColor);
- mCapture->expectColor(grandchildBounds, grandchildColor);
- }
-
- Transaction().hide(grandchildSurface).apply();
-
- // grandchild is still detached so it will not hide
- {
- mCapture = screenshot();
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectBorder(grandchildBounds, childColor);
- mCapture->expectColor(grandchildBounds, grandchildColor);
- }
-}
-
-} // 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
diff --git a/services/surfaceflinger/tests/DisplayConfigs_test.cpp b/services/surfaceflinger/tests/DisplayConfigs_test.cpp
index 55b3173..9f025a6 100644
--- a/services/surfaceflinger/tests/DisplayConfigs_test.cpp
+++ b/services/surfaceflinger/tests/DisplayConfigs_test.cpp
@@ -22,7 +22,7 @@
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
#include <private/gui/ComposerService.h>
-#include <ui/DisplayConfig.h>
+#include <ui/DisplayMode.h>
#include <utils/Errors.h>
#include <utils/Vector.h>
@@ -38,7 +38,7 @@
*/
class RefreshRateRangeTest : public ::testing::Test {
private:
- int32_t initialDefaultConfig;
+ size_t initialDefaultMode;
bool initialAllowGroupSwitching;
float initialPrimaryMin;
float initialPrimaryMax;
@@ -49,25 +49,24 @@
void SetUp() override {
mDisplayToken = SurfaceComposerClient::getInternalDisplayToken();
status_t res =
- SurfaceComposerClient::getDesiredDisplayConfigSpecs(mDisplayToken,
- &initialDefaultConfig,
- &initialAllowGroupSwitching,
- &initialPrimaryMin,
- &initialPrimaryMax,
- &initialAppRequestMin,
- &initialAppRequestMax);
+ SurfaceComposerClient::getDesiredDisplayModeSpecs(mDisplayToken,
+ &initialDefaultMode,
+ &initialAllowGroupSwitching,
+ &initialPrimaryMin,
+ &initialPrimaryMax,
+ &initialAppRequestMin,
+ &initialAppRequestMax);
ASSERT_EQ(res, NO_ERROR);
}
void TearDown() override {
status_t res =
- SurfaceComposerClient::setDesiredDisplayConfigSpecs(mDisplayToken,
- initialDefaultConfig,
- initialAllowGroupSwitching,
- initialPrimaryMin,
- initialPrimaryMax,
- initialAppRequestMin,
- initialAppRequestMax);
+ SurfaceComposerClient::setDesiredDisplayModeSpecs(mDisplayToken, initialDefaultMode,
+ initialAllowGroupSwitching,
+ initialPrimaryMin,
+ initialPrimaryMax,
+ initialAppRequestMin,
+ initialAppRequestMax);
ASSERT_EQ(res, NO_ERROR);
}
@@ -77,60 +76,59 @@
};
TEST_F(RefreshRateRangeTest, setAllConfigs) {
- Vector<DisplayConfig> configs;
- status_t res = SurfaceComposerClient::getDisplayConfigs(mDisplayToken, &configs);
+ Vector<ui::DisplayMode> modes;
+ status_t res = SurfaceComposerClient::getDisplayModes(mDisplayToken, &modes);
ASSERT_EQ(res, NO_ERROR);
- ASSERT_GT(configs.size(), 0);
+ ASSERT_GT(modes.size(), 0);
- for (size_t i = 0; i < configs.size(); i++) {
- res = SurfaceComposerClient::setDesiredDisplayConfigSpecs(mDisplayToken,
- static_cast<int32_t>(i), false,
- configs[i].refreshRate,
- configs[i].refreshRate,
- configs[i].refreshRate,
- configs[i].refreshRate);
+ for (size_t i = 0; i < modes.size(); i++) {
+ res = SurfaceComposerClient::setDesiredDisplayModeSpecs(mDisplayToken, i, false,
+ modes[i].refreshRate,
+ modes[i].refreshRate,
+ modes[i].refreshRate,
+ modes[i].refreshRate);
ASSERT_EQ(res, NO_ERROR);
- int defaultConfig;
+ size_t defaultConfig;
bool allowGroupSwitching;
float primaryRefreshRateMin;
float primaryRefreshRateMax;
float appRequestRefreshRateMin;
float appRequestRefreshRateMax;
- res = SurfaceComposerClient::getDesiredDisplayConfigSpecs(mDisplayToken, &defaultConfig,
- &allowGroupSwitching,
- &primaryRefreshRateMin,
- &primaryRefreshRateMax,
- &appRequestRefreshRateMin,
- &appRequestRefreshRateMax);
+ res = SurfaceComposerClient::getDesiredDisplayModeSpecs(mDisplayToken, &defaultConfig,
+ &allowGroupSwitching,
+ &primaryRefreshRateMin,
+ &primaryRefreshRateMax,
+ &appRequestRefreshRateMin,
+ &appRequestRefreshRateMax);
ASSERT_EQ(res, NO_ERROR);
ASSERT_EQ(defaultConfig, i);
ASSERT_EQ(allowGroupSwitching, false);
- ASSERT_EQ(primaryRefreshRateMin, configs[i].refreshRate);
- ASSERT_EQ(primaryRefreshRateMax, configs[i].refreshRate);
- ASSERT_EQ(appRequestRefreshRateMin, configs[i].refreshRate);
- ASSERT_EQ(appRequestRefreshRateMax, configs[i].refreshRate);
+ ASSERT_EQ(primaryRefreshRateMin, modes[i].refreshRate);
+ ASSERT_EQ(primaryRefreshRateMax, modes[i].refreshRate);
+ ASSERT_EQ(appRequestRefreshRateMin, modes[i].refreshRate);
+ ASSERT_EQ(appRequestRefreshRateMax, modes[i].refreshRate);
}
}
void RefreshRateRangeTest::testSetAllowGroupSwitching(bool allowGroupSwitching) {
- status_t res = SurfaceComposerClient::setDesiredDisplayConfigSpecs(mDisplayToken, 0,
- allowGroupSwitching, 0.f,
- 90.f, 0.f, 90.f);
+ status_t res =
+ SurfaceComposerClient::setDesiredDisplayModeSpecs(mDisplayToken, 0, allowGroupSwitching,
+ 0.f, 90.f, 0.f, 90.f);
ASSERT_EQ(res, NO_ERROR);
- int defaultConfig;
+ size_t defaultConfig;
bool newAllowGroupSwitching;
float primaryRefreshRateMin;
float primaryRefreshRateMax;
float appRequestRefreshRateMin;
float appRequestRefreshRateMax;
- res = SurfaceComposerClient::getDesiredDisplayConfigSpecs(mDisplayToken, &defaultConfig,
- &newAllowGroupSwitching,
- &primaryRefreshRateMin,
- &primaryRefreshRateMax,
- &appRequestRefreshRateMin,
- &appRequestRefreshRateMax);
+ res = SurfaceComposerClient::getDesiredDisplayModeSpecs(mDisplayToken, &defaultConfig,
+ &newAllowGroupSwitching,
+ &primaryRefreshRateMin,
+ &primaryRefreshRateMax,
+ &appRequestRefreshRateMin,
+ &appRequestRefreshRateMax);
ASSERT_EQ(res, NO_ERROR);
ASSERT_EQ(defaultConfig, 0);
ASSERT_EQ(newAllowGroupSwitching, allowGroupSwitching);
diff --git a/services/surfaceflinger/tests/IPC_test.cpp b/services/surfaceflinger/tests/IPC_test.cpp
index 4023c66..a8647c3 100644
--- a/services/surfaceflinger/tests/IPC_test.cpp
+++ b/services/surfaceflinger/tests/IPC_test.cpp
@@ -23,7 +23,7 @@
#include <gui/LayerState.h>
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
-#include <ui/DisplayConfig.h>
+#include <ui/DisplayMode.h>
#include <utils/String8.h>
#include <limits>
@@ -227,10 +227,10 @@
ASSERT_EQ(NO_ERROR, mClient->initCheck());
mPrimaryDisplay = mClient->getInternalDisplayToken();
- DisplayConfig config;
- mClient->getActiveDisplayConfig(mPrimaryDisplay, &config);
- mDisplayWidth = config.resolution.getWidth();
- mDisplayHeight = config.resolution.getHeight();
+ ui::DisplayMode mode;
+ mClient->getActiveDisplayMode(mPrimaryDisplay, &mode);
+ mDisplayWidth = mode.resolution.getWidth();
+ mDisplayHeight = mode.resolution.getHeight();
Transaction setupTransaction;
setupTransaction.setDisplayLayerStack(mPrimaryDisplay, 0);
diff --git a/services/surfaceflinger/tests/LayerState_test.cpp b/services/surfaceflinger/tests/LayerState_test.cpp
index 93d5f2f..f010786 100644
--- a/services/surfaceflinger/tests/LayerState_test.cpp
+++ b/services/surfaceflinger/tests/LayerState_test.cpp
@@ -30,12 +30,14 @@
DisplayCaptureArgs args;
args.pixelFormat = ui::PixelFormat::RGB_565;
args.sourceCrop = Rect(0, 0, 500, 200);
- args.frameScale = 2;
+ args.frameScaleX = 2;
+ args.frameScaleY = 4;
args.captureSecureLayers = true;
args.displayToken = new BBinder();
args.width = 10;
args.height = 20;
args.useIdentityTransform = true;
+ args.grayscale = true;
Parcel p;
args.write(p);
@@ -46,23 +48,27 @@
ASSERT_EQ(args.pixelFormat, args2.pixelFormat);
ASSERT_EQ(args.sourceCrop, args2.sourceCrop);
- ASSERT_EQ(args.frameScale, args2.frameScale);
+ ASSERT_EQ(args.frameScaleX, args2.frameScaleX);
+ ASSERT_EQ(args.frameScaleY, args2.frameScaleY);
ASSERT_EQ(args.captureSecureLayers, args2.captureSecureLayers);
ASSERT_EQ(args.displayToken, args2.displayToken);
ASSERT_EQ(args.width, args2.width);
ASSERT_EQ(args.height, args2.height);
ASSERT_EQ(args.useIdentityTransform, args2.useIdentityTransform);
+ ASSERT_EQ(args.grayscale, args2.grayscale);
}
TEST(LayerStateTest, ParcellingLayerCaptureArgs) {
LayerCaptureArgs args;
args.pixelFormat = ui::PixelFormat::RGB_565;
args.sourceCrop = Rect(0, 0, 500, 200);
- args.frameScale = 2;
+ args.frameScaleX = 2;
+ args.frameScaleY = 4;
args.captureSecureLayers = true;
args.layerHandle = new BBinder();
args.excludeHandles = {new BBinder(), new BBinder()};
args.childrenOnly = false;
+ args.grayscale = true;
Parcel p;
args.write(p);
@@ -73,11 +79,13 @@
ASSERT_EQ(args.pixelFormat, args2.pixelFormat);
ASSERT_EQ(args.sourceCrop, args2.sourceCrop);
- ASSERT_EQ(args.frameScale, args2.frameScale);
+ ASSERT_EQ(args.frameScaleX, args2.frameScaleX);
+ ASSERT_EQ(args.frameScaleY, args2.frameScaleY);
ASSERT_EQ(args.captureSecureLayers, args2.captureSecureLayers);
ASSERT_EQ(args.layerHandle, args2.layerHandle);
ASSERT_EQ(args.excludeHandles, args2.excludeHandles);
ASSERT_EQ(args.childrenOnly, args2.childrenOnly);
+ ASSERT_EQ(args.grayscale, args2.grayscale);
}
TEST(LayerStateTest, ParcellingScreenCaptureResults) {
@@ -106,5 +114,34 @@
ASSERT_EQ(results.result, results2.result);
}
+/**
+ * Parcel a layer_state_t struct, and then unparcel. Ensure that the object that was parceled
+ * matches the object that's unparceled.
+ */
+TEST(LayerStateTest, ParcelUnparcelLayerStateT) {
+ layer_state_t input;
+ input.frameTimelineInfo.vsyncId = 1;
+ input.frameTimelineInfo.inputEventId = 2;
+ Parcel p;
+ input.write(p);
+ layer_state_t output;
+ p.setDataPosition(0);
+ output.read(p);
+ ASSERT_EQ(input.frameTimelineInfo.vsyncId, output.frameTimelineInfo.vsyncId);
+ ASSERT_EQ(input.frameTimelineInfo.inputEventId, output.frameTimelineInfo.inputEventId);
+}
+
+TEST(LayerStateTest, LayerStateMerge_SelectsValidInputEvent) {
+ layer_state_t layer1;
+ layer1.frameTimelineInfo.inputEventId = android::os::IInputConstants::INVALID_INPUT_EVENT_ID;
+ layer_state_t layer2;
+ layer2.frameTimelineInfo.inputEventId = 1;
+ layer2.what |= layer_state_t::eFrameTimelineInfoChanged;
+
+ layer1.merge(layer2);
+
+ ASSERT_EQ(1, layer1.frameTimelineInfo.inputEventId);
+}
+
} // namespace test
} // namespace android
diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h
index 6758518..eba2c25 100644
--- a/services/surfaceflinger/tests/LayerTransactionTest.h
+++ b/services/surfaceflinger/tests/LayerTransactionTest.h
@@ -25,7 +25,7 @@
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
#include <private/gui/ComposerService.h>
-#include <ui/DisplayConfig.h>
+#include <ui/DisplayMode.h>
#include "BufferGenerator.h"
#include "utils/ScreenshotUtils.h"
@@ -265,16 +265,16 @@
mDisplay = mClient->getInternalDisplayToken();
ASSERT_FALSE(mDisplay == nullptr) << "failed to get display";
- DisplayConfig config;
- ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(mDisplay, &config));
- mDisplayRect = Rect(config.resolution);
+ ui::DisplayMode mode;
+ ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(mDisplay, &mode));
+ mDisplayRect = Rect(mode.resolution);
mDisplayWidth = mDisplayRect.getWidth();
mDisplayHeight = mDisplayRect.getHeight();
// After a new buffer is queued, SurfaceFlinger is notified and will
// latch the new buffer on next vsync. Let's heuristically wait for 3
// vsyncs.
- mBufferPostDelay = static_cast<int32_t>(1e6 / config.refreshRate) * 3;
+ mBufferPostDelay = static_cast<int32_t>(1e6 / mode.refreshRate) * 3;
mDisplayLayerStack = 0;
diff --git a/services/surfaceflinger/tests/LayerUpdate_test.cpp b/services/surfaceflinger/tests/LayerUpdate_test.cpp
index 6c56d20..ec826ae 100644
--- a/services/surfaceflinger/tests/LayerUpdate_test.cpp
+++ b/services/surfaceflinger/tests/LayerUpdate_test.cpp
@@ -36,9 +36,9 @@
const auto display = SurfaceComposerClient::getInternalDisplayToken();
ASSERT_FALSE(display == nullptr);
- DisplayConfig config;
- ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
- const ui::Size& resolution = config.resolution;
+ ui::DisplayMode mode;
+ ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode));
+ const ui::Size& resolution = mode.resolution;
// Background surface
mBGSurfaceControl = createLayer(String8("BG Test Surface"), resolution.getWidth(),
diff --git a/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp b/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp
index db0c56f..eaf54e3 100644
--- a/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp
+++ b/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp
@@ -37,13 +37,13 @@
mMainDisplay = SurfaceComposerClient::getInternalDisplayToken();
SurfaceComposerClient::getDisplayState(mMainDisplay, &mMainDisplayState);
- SurfaceComposerClient::getActiveDisplayConfig(mMainDisplay, &mMainDisplayConfig);
+ SurfaceComposerClient::getActiveDisplayMode(mMainDisplay, &mMainDisplayMode);
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&mProducer, &consumer);
consumer->setConsumerName(String8("Virtual disp consumer"));
- consumer->setDefaultBufferSize(mMainDisplayConfig.resolution.getWidth(),
- mMainDisplayConfig.resolution.getHeight());
+ consumer->setDefaultBufferSize(mMainDisplayMode.resolution.getWidth(),
+ mMainDisplayMode.resolution.getHeight());
}
virtual void TearDown() {
@@ -59,7 +59,7 @@
t.setDisplaySurface(mVirtualDisplay, mProducer);
t.setDisplayLayerStack(mVirtualDisplay, layerStack);
t.setDisplayProjection(mVirtualDisplay, mMainDisplayState.orientation,
- Rect(layerStackSize), Rect(mMainDisplayConfig.resolution));
+ Rect(layerStackSize), Rect(mMainDisplayMode.resolution));
});
}
@@ -81,7 +81,7 @@
}
ui::DisplayState mMainDisplayState;
- DisplayConfig mMainDisplayConfig;
+ ui::DisplayMode mMainDisplayMode;
sp<IBinder> mMainDisplay;
sp<IBinder> mVirtualDisplay;
sp<IGraphicBufferProducer> mProducer;
diff --git a/services/surfaceflinger/tests/ScreenCapture_test.cpp b/services/surfaceflinger/tests/ScreenCapture_test.cpp
index 214a0cd..4598f9d 100644
--- a/services/surfaceflinger/tests/ScreenCapture_test.cpp
+++ b/services/surfaceflinger/tests/ScreenCapture_test.cpp
@@ -33,9 +33,9 @@
const auto display = SurfaceComposerClient::getInternalDisplayToken();
ASSERT_FALSE(display == nullptr);
- DisplayConfig config;
- ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
- const ui::Size& resolution = config.resolution;
+ ui::DisplayMode mode;
+ ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode));
+ const ui::Size& resolution = mode.resolution;
// Background surface
mBGSurfaceControl = createLayer(String8("BG Test Surface"), resolution.getWidth(),
@@ -487,7 +487,9 @@
// red area to the right of the blue area
mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED);
- captureArgs.frameScale = 0.5f;
+ captureArgs.frameScaleX = 0.5f;
+ captureArgs.frameScaleY = 0.5f;
+
ScreenCapture::captureLayers(&mCapture, captureArgs);
// Capturing the downsized area (30x30) should leave both red and blue but in a smaller area.
mCapture->expectColor(Rect(0, 0, 14, 14), Color::BLUE);
@@ -768,6 +770,41 @@
mCapture->expectBorder(Rect(128, 128, 160, 160), {63, 63, 195, 255});
}
+TEST_F(ScreenCaptureTest, CaptureWithGrayscale) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test layer", 32, 32,
+ ISurfaceComposerClient::eFXSurfaceBufferState,
+ mBGSurfaceControl.get()));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+ Transaction().show(layer).setLayer(layer, INT32_MAX).apply();
+
+ LayerCaptureArgs captureArgs;
+ captureArgs.layerHandle = layer->getHandle();
+
+ ScreenCapture::captureLayers(&mCapture, captureArgs);
+ mCapture->expectColor(Rect(0, 0, 32, 32), Color::RED);
+
+ captureArgs.grayscale = true;
+
+ const uint8_t tolerance = 1;
+
+ // Values based on SurfaceFlinger::calculateColorMatrix
+ float3 luminance{0.213f, 0.715f, 0.072f};
+
+ ScreenCapture::captureLayers(&mCapture, captureArgs);
+
+ uint8_t expectedColor = luminance.r * 255;
+ mCapture->expectColor(Rect(0, 0, 32, 32),
+ Color{expectedColor, expectedColor, expectedColor, 255}, tolerance);
+
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::BLUE, 32, 32));
+ ScreenCapture::captureLayers(&mCapture, captureArgs);
+
+ expectedColor = luminance.b * 255;
+ mCapture->expectColor(Rect(0, 0, 32, 32),
+ Color{expectedColor, expectedColor, expectedColor, 255}, tolerance);
+}
+
// In the following tests we verify successful skipping of a parent layer,
// so we use the same verification logic and only change how we mutate
// the parent layer to verify that various properties are ignored.
diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
index 8dc9a12..a20d5c6 100644
--- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
+++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
@@ -27,7 +27,7 @@
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <private/gui/ComposerService.h>
-#include <ui/DisplayConfig.h>
+#include <ui/DisplayMode.h>
#include <fstream>
#include <random>
@@ -194,7 +194,6 @@
bool deferredTransactionUpdateFound(const SurfaceChange& change, bool foundDeferred);
bool reparentUpdateFound(const SurfaceChange& change, bool found);
bool relativeParentUpdateFound(const SurfaceChange& change, bool found);
- bool detachChildrenUpdateFound(const SurfaceChange& change, bool found);
bool reparentChildrenUpdateFound(const SurfaceChange& change, bool found);
bool shadowRadiusUpdateFound(const SurfaceChange& change, bool found);
bool surfaceUpdateFound(const Trace& trace, SurfaceChange::SurfaceChangeCase changeCase);
@@ -232,7 +231,6 @@
void deferredTransactionUpdate(Transaction&);
void reparentUpdate(Transaction&);
void relativeParentUpdate(Transaction&);
- void detachChildrenUpdate(Transaction&);
void reparentChildrenUpdate(Transaction&);
void shadowRadiusUpdate(Transaction&);
void surfaceCreation(Transaction&);
@@ -269,9 +267,9 @@
const auto display = SurfaceComposerClient::getInternalDisplayToken();
ASSERT_FALSE(display == nullptr);
- DisplayConfig config;
- ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
- const ui::Size& resolution = config.resolution;
+ ui::DisplayMode mode;
+ ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode));
+ const ui::Size& resolution = mode.resolution;
// Background surface
mBGSurfaceControl =
@@ -412,10 +410,6 @@
t.setRelativeLayer(mBGSurfaceControl, mFGSurfaceControl, RELATIVE_Z);
}
-void SurfaceInterceptorTest::detachChildrenUpdate(Transaction& t) {
- t.detachChildren(mBGSurfaceControl);
-}
-
void SurfaceInterceptorTest::reparentChildrenUpdate(Transaction& t) {
t.reparentChildren(mBGSurfaceControl, mFGSurfaceControl);
}
@@ -452,7 +446,6 @@
runInTransaction(&SurfaceInterceptorTest::deferredTransactionUpdate);
runInTransaction(&SurfaceInterceptorTest::reparentUpdate);
runInTransaction(&SurfaceInterceptorTest::reparentChildrenUpdate);
- runInTransaction(&SurfaceInterceptorTest::detachChildrenUpdate);
runInTransaction(&SurfaceInterceptorTest::relativeParentUpdate);
runInTransaction(&SurfaceInterceptorTest::shadowRadiusUpdate);
}
@@ -667,16 +660,6 @@
return found;
}
-bool SurfaceInterceptorTest::detachChildrenUpdateFound(const SurfaceChange& change, bool found) {
- bool detachChildren(change.detach_children().detach_children());
- if (detachChildren && !found) {
- found = true;
- } else if (detachChildren && found) {
- []() { FAIL(); }();
- }
- return found;
-}
-
bool SurfaceInterceptorTest::reparentChildrenUpdateFound(const SurfaceChange& change, bool found) {
bool hasId(change.reparent_children().parent_id() == mFGLayerId);
if (hasId && !found) {
@@ -761,9 +744,6 @@
case SurfaceChange::SurfaceChangeCase::kRelativeParent:
foundUpdate = relativeParentUpdateFound(change, foundUpdate);
break;
- case SurfaceChange::SurfaceChangeCase::kDetachChildren:
- foundUpdate = detachChildrenUpdateFound(change, foundUpdate);
- break;
case SurfaceChange::SurfaceChangeCase::kShadowRadius:
foundUpdate = shadowRadiusUpdateFound(change, foundUpdate);
break;
@@ -793,7 +773,6 @@
ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kReparent));
ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kReparentChildren));
ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kRelativeParent));
- ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kDetachChildren));
}
bool SurfaceInterceptorTest::surfaceCreationFound(const Increment& increment, bool foundSurface) {
@@ -968,11 +947,6 @@
SurfaceChange::SurfaceChangeCase::kRelativeParent);
}
-TEST_F(SurfaceInterceptorTest, InterceptDetachChildrenUpdateWorks) {
- captureTest(&SurfaceInterceptorTest::detachChildrenUpdate,
- SurfaceChange::SurfaceChangeCase::kDetachChildren);
-}
-
TEST_F(SurfaceInterceptorTest, InterceptShadowRadiusUpdateWorks) {
captureTest(&SurfaceInterceptorTest::shadowRadiusUpdate,
SurfaceChange::SurfaceChangeCase::kShadowRadius);
diff --git a/services/surfaceflinger/tests/TransactionTestHarnesses.h b/services/surfaceflinger/tests/TransactionTestHarnesses.h
index a361b1e..89f6086 100644
--- a/services/surfaceflinger/tests/TransactionTestHarnesses.h
+++ b/services/surfaceflinger/tests/TransactionTestHarnesses.h
@@ -40,9 +40,9 @@
ui::DisplayState displayState;
SurfaceComposerClient::getDisplayState(displayToken, &displayState);
- DisplayConfig displayConfig;
- SurfaceComposerClient::getActiveDisplayConfig(displayToken, &displayConfig);
- const ui::Size& resolution = displayConfig.resolution;
+ ui::DisplayMode displayMode;
+ SurfaceComposerClient::getActiveDisplayMode(displayToken, &displayMode);
+ const ui::Size& resolution = displayMode.resolution;
sp<IBinder> vDisplay;
sp<IGraphicBufferProducer> producer;
@@ -57,6 +57,8 @@
// Sample usage bits from screenrecord
GRALLOC_USAGE_HW_VIDEO_ENCODER |
GRALLOC_USAGE_SW_READ_OFTEN);
+ sp<BufferListener> listener = new BufferListener(this);
+ itemConsumer->setFrameAvailableListener(listener);
vDisplay = SurfaceComposerClient::createDisplay(String8("VirtualDisplay"),
false /*secure*/);
@@ -68,6 +70,13 @@
Rect(displayState.layerStackSpaceRect), Rect(resolution));
t.apply();
SurfaceComposerClient::Transaction().apply(true);
+
+ std::unique_lock lock(mMutex);
+ mAvailable = false;
+ // Wait for frame buffer ready.
+ mCondition.wait_for(lock, std::chrono::seconds(2),
+ [this]() NO_THREAD_SAFETY_ANALYSIS { return mAvailable; });
+
BufferItem item;
itemConsumer->acquireBuffer(&item, 0, true);
auto sc = std::make_unique<ScreenCapture>(item.mGraphicBuffer);
@@ -80,6 +89,23 @@
protected:
LayerTransactionTest* mDelegate;
RenderPath mRenderPath;
+ std::mutex mMutex;
+ std::condition_variable mCondition;
+ bool mAvailable = false;
+
+ void onFrameAvailable() {
+ std::unique_lock lock(mMutex);
+ mAvailable = true;
+ mCondition.notify_all();
+ }
+
+ class BufferListener : public ConsumerBase::FrameAvailableListener {
+ public:
+ BufferListener(LayerRenderPathTestHarness* owner) : mOwner(owner) {}
+ LayerRenderPathTestHarness* mOwner;
+
+ void onFrameAvailable(const BufferItem& /*item*/) { mOwner->onFrameAvailable(); }
+ };
};
class LayerTypeTransactionHarness : public LayerTransactionTest {
diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
index bd49728..56e1ae9 100644
--- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
+++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
@@ -43,7 +43,7 @@
#include <hwbinder/ProcessState.h>
#include <log/log.h>
#include <private/gui/ComposerService.h>
-#include <ui/DisplayConfig.h>
+#include <ui/DisplayMode.h>
#include <utils/Looper.h>
#include <gmock/gmock.h>
@@ -63,9 +63,7 @@
// Mock test helpers
using ::testing::_;
-using ::testing::AtLeast;
using ::testing::DoAll;
-using ::testing::Invoke;
using ::testing::Return;
using ::testing::SetArgPointee;
@@ -74,9 +72,11 @@
using Display = V2_1::Display;
///////////////////////////////////////////////
-
-constexpr PhysicalDisplayId kPrimaryDisplayId = PhysicalDisplayId::fromPort(PRIMARY_DISPLAY);
-constexpr PhysicalDisplayId kExternalDisplayId = PhysicalDisplayId::fromPort(EXTERNAL_DISPLAY);
+constexpr PhysicalDisplayId physicalIdFromHwcDisplayId(Display hwcId) {
+ return PhysicalDisplayId::fromPort(hwcId);
+}
+constexpr PhysicalDisplayId kPrimaryDisplayId = physicalIdFromHwcDisplayId(PRIMARY_DISPLAY);
+constexpr PhysicalDisplayId kExternalDisplayId = physicalIdFromHwcDisplayId(EXTERNAL_DISPLAY);
struct TestColor {
public:
@@ -158,7 +158,7 @@
self->mReceivedDisplayEvents.push_back(buffer[i]);
}
}
- ALOGD_IF(n < 0, "Error reading events (%s)\n", strerror(-n));
+ ALOGD_IF(n < 0, "Error reading events (%s)", strerror(-n));
return 1;
}
@@ -174,7 +174,7 @@
void setExpectationsForConfigs(Display display, std::vector<TestConfig> testConfigs,
Config activeConfig, V2_4::VsyncPeriodNanos defaultVsyncPeriod) {
std::vector<Config> configIds;
- for (int i = 0; i < testConfigs.size(); i++) {
+ for (size_t i = 0; i < testConfigs.size(); i++) {
configIds.push_back(testConfigs[i].id);
EXPECT_CALL(*mMockComposer,
@@ -243,9 +243,8 @@
mComposerClient = new SurfaceComposerClient;
ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());
- mReceiver.reset(
- new DisplayEventReceiver(ISurfaceComposer::eVsyncSourceApp,
- ISurfaceComposer::EventRegistration::configChanged));
+ mReceiver.reset(new DisplayEventReceiver(ISurfaceComposer::eVsyncSourceApp,
+ ISurfaceComposer::EventRegistration::modeChanged));
mLooper = new Looper(false);
mLooper->addFd(mReceiver->getFd(), 0, ALOOPER_EVENT_INPUT, processDisplayEvents, this);
}
@@ -269,10 +268,10 @@
mMockComposer = nullptr;
}
- void waitForDisplayTransaction() {
+ void waitForDisplayTransaction(Display display) {
// Both a refresh and a vsync event are needed to apply pending display
// transactions.
- mFakeComposerClient->refreshDisplay(EXTERNAL_DISPLAY);
+ mFakeComposerClient->refreshDisplay(display);
mFakeComposerClient->runVSyncAndWait();
// Extra vsync and wait to avoid a 10% flake due to a race.
@@ -291,7 +290,7 @@
mReceivedDisplayEvents.pop_front();
ALOGV_IF(event.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG,
- "event hotplug: displayId %s, connected %d\t",
+ "event hotplug: displayId %s, connected %d",
to_string(event.header.displayId).c_str(), event.hotplug.connected);
if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG &&
@@ -305,7 +304,7 @@
return false;
}
- bool waitForConfigChangedEvent(Display display, int32_t configId) {
+ bool waitForModeChangedEvent(Display display, int32_t modeId) {
PhysicalDisplayId displayId(display);
int waitCount = 20;
while (waitCount--) {
@@ -313,12 +312,12 @@
auto event = mReceivedDisplayEvents.front();
mReceivedDisplayEvents.pop_front();
- ALOGV_IF(event.header.type == DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED,
- "event config: displayId %s, configId %d\t",
- to_string(event.header.displayId).c_str(), event.config.configId);
+ ALOGV_IF(event.header.type == DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE,
+ "event mode: displayId %s, modeId %d",
+ to_string(event.header.displayId).c_str(), event.modeChange.modeId);
- if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED &&
- event.header.displayId == displayId && event.config.configId == configId) {
+ if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE &&
+ event.header.displayId == displayId && event.modeChange.modeId == modeId) {
return true;
}
}
@@ -341,18 +340,18 @@
mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
V2_1::IComposerCallback::Connection::CONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true));
{
const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId);
EXPECT_FALSE(display == nullptr);
- DisplayConfig config;
- EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
- const ui::Size& resolution = config.resolution;
+ ui::DisplayMode mode;
+ EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode));
+ const ui::Size& resolution = mode.resolution;
EXPECT_EQ(ui::Size(200, 400), resolution);
- EXPECT_EQ(1e9f / 16'666'666, config.refreshRate);
+ EXPECT_EQ(1e9f / 16'666'666, mode.refreshRate);
auto surfaceControl =
mComposerClient->createSurface(String8("Display Test Surface Foo"),
@@ -372,7 +371,7 @@
mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
V2_1::IComposerCallback::Connection::DISCONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
mFakeComposerClient->clearFrames();
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, false));
@@ -380,8 +379,8 @@
const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId);
EXPECT_TRUE(display == nullptr);
- DisplayConfig config;
- EXPECT_NE(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
+ ui::DisplayMode mode;
+ EXPECT_NE(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode));
}
}
@@ -403,20 +402,20 @@
mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
V2_1::IComposerCallback::Connection::CONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true));
const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId);
EXPECT_FALSE(display == nullptr);
- DisplayConfig config;
- EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
- EXPECT_EQ(ui::Size(200, 400), config.resolution);
- EXPECT_EQ(1e9f / 16'666'666, config.refreshRate);
+ ui::DisplayMode mode;
+ EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode));
+ EXPECT_EQ(ui::Size(200, 400), mode.resolution);
+ EXPECT_EQ(1e9f / 16'666'666, mode.refreshRate);
mFakeComposerClient->clearFrames();
{
- const ui::Size& resolution = config.resolution;
+ const ui::Size& resolution = mode.resolution;
auto surfaceControl =
mComposerClient->createSurface(String8("Display Test Surface Foo"),
resolution.getWidth(), resolution.getHeight(),
@@ -433,11 +432,11 @@
}
}
- Vector<DisplayConfig> configs;
- EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs));
- EXPECT_EQ(configs.size(), 2);
+ Vector<ui::DisplayMode> modes;
+ EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayModes(display, &modes));
+ EXPECT_EQ(modes.size(), 2);
- // change active config
+ // change active mode
if (mIs2_4Client) {
EXPECT_CALL(*mMockComposer, setActiveConfigWithConstraints(EXTERNAL_DISPLAY, 2, _, _))
@@ -447,28 +446,28 @@
.WillOnce(Return(V2_1::Error::NONE));
}
- for (int i = 0; i < configs.size(); i++) {
- const auto& config = configs[i];
- if (config.resolution.getWidth() == 800) {
+ for (int i = 0; i < modes.size(); i++) {
+ const auto& mode = modes[i];
+ if (mode.resolution.getWidth() == 800) {
EXPECT_EQ(NO_ERROR,
- SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, false,
- config.refreshRate,
- config.refreshRate,
- config.refreshRate,
- config.refreshRate));
- waitForDisplayTransaction();
- EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
+ SurfaceComposerClient::setDesiredDisplayModeSpecs(display, i, false,
+ mode.refreshRate,
+ mode.refreshRate,
+ mode.refreshRate,
+ mode.refreshRate));
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
+ EXPECT_TRUE(waitForModeChangedEvent(EXTERNAL_DISPLAY, i));
break;
}
}
- EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
- EXPECT_EQ(ui::Size(800, 1600), config.resolution);
- EXPECT_EQ(1e9f / 11'111'111, config.refreshRate);
+ EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode));
+ EXPECT_EQ(ui::Size(800, 1600), mode.resolution);
+ EXPECT_EQ(1e9f / 11'111'111, mode.refreshRate);
mFakeComposerClient->clearFrames();
{
- const ui::Size& resolution = config.resolution;
+ const ui::Size& resolution = mode.resolution;
auto surfaceControl =
mComposerClient->createSurface(String8("Display Test Surface Foo"),
resolution.getWidth(), resolution.getHeight(),
@@ -487,7 +486,7 @@
mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
V2_1::IComposerCallback::Connection::DISCONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
mFakeComposerClient->clearFrames();
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, false));
}
@@ -510,20 +509,20 @@
mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
V2_1::IComposerCallback::Connection::CONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true));
const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId);
EXPECT_FALSE(display == nullptr);
- DisplayConfig config;
- EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
- EXPECT_EQ(ui::Size(800, 1600), config.resolution);
- EXPECT_EQ(1e9f / 16'666'666, config.refreshRate);
+ ui::DisplayMode mode;
+ EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode));
+ EXPECT_EQ(ui::Size(800, 1600), mode.resolution);
+ EXPECT_EQ(1e9f / 16'666'666, mode.refreshRate);
mFakeComposerClient->clearFrames();
{
- const ui::Size& resolution = config.resolution;
+ const ui::Size& resolution = mode.resolution;
auto surfaceControl =
mComposerClient->createSurface(String8("Display Test Surface Foo"),
resolution.getWidth(), resolution.getHeight(),
@@ -540,11 +539,11 @@
}
}
- Vector<DisplayConfig> configs;
- EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs));
- EXPECT_EQ(configs.size(), 2);
+ Vector<ui::DisplayMode> modes;
+ EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayModes(display, &modes));
+ EXPECT_EQ(modes.size(), 2);
- // change active config
+ // change active mode
if (mIs2_4Client) {
EXPECT_CALL(*mMockComposer, setActiveConfigWithConstraints(EXTERNAL_DISPLAY, 3, _, _))
.WillOnce(Return(V2_4::Error::NONE));
@@ -553,28 +552,28 @@
.WillOnce(Return(V2_1::Error::NONE));
}
- for (int i = 0; i < configs.size(); i++) {
- const auto& config = configs[i];
- if (config.refreshRate == 1e9f / 11'111'111) {
+ for (int i = 0; i < modes.size(); i++) {
+ const auto& mode = modes[i];
+ if (mode.refreshRate == 1e9f / 11'111'111) {
EXPECT_EQ(NO_ERROR,
- SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, false,
- config.refreshRate,
- config.refreshRate,
- config.refreshRate,
- config.refreshRate));
- waitForDisplayTransaction();
- EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
+ SurfaceComposerClient::setDesiredDisplayModeSpecs(display, i, false,
+ mode.refreshRate,
+ mode.refreshRate,
+ mode.refreshRate,
+ mode.refreshRate));
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
+ EXPECT_TRUE(waitForModeChangedEvent(EXTERNAL_DISPLAY, i));
break;
}
}
- EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
- EXPECT_EQ(ui::Size(800, 1600), config.resolution);
- EXPECT_EQ(1e9f / 11'111'111, config.refreshRate);
+ EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode));
+ EXPECT_EQ(ui::Size(800, 1600), mode.resolution);
+ EXPECT_EQ(1e9f / 11'111'111, mode.refreshRate);
mFakeComposerClient->clearFrames();
{
- const ui::Size& resolution = config.resolution;
+ const ui::Size& resolution = mode.resolution;
auto surfaceControl =
mComposerClient->createSurface(String8("Display Test Surface Foo"),
resolution.getWidth(), resolution.getHeight(),
@@ -593,7 +592,7 @@
mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
V2_1::IComposerCallback::Connection::DISCONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
mFakeComposerClient->clearFrames();
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, false));
}
@@ -626,20 +625,20 @@
mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
V2_1::IComposerCallback::Connection::CONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true));
const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId);
EXPECT_FALSE(display == nullptr);
- DisplayConfig config;
- EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
- EXPECT_EQ(ui::Size(800, 1600), config.resolution);
- EXPECT_EQ(1e9f / 16'666'666, config.refreshRate);
+ ui::DisplayMode mode;
+ EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode));
+ EXPECT_EQ(ui::Size(800, 1600), mode.resolution);
+ EXPECT_EQ(1e9f / 16'666'666, mode.refreshRate);
mFakeComposerClient->clearFrames();
{
- const ui::Size& resolution = config.resolution;
+ const ui::Size& resolution = mode.resolution;
auto surfaceControl =
mComposerClient->createSurface(String8("Display Test Surface Foo"),
resolution.getWidth(), resolution.getHeight(),
@@ -656,11 +655,11 @@
}
}
- Vector<DisplayConfig> configs;
- EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs));
- EXPECT_EQ(configs.size(), 4);
+ Vector<ui::DisplayMode> modes;
+ EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayModes(display, &modes));
+ EXPECT_EQ(modes.size(), 4);
- // change active config to 800x1600@90Hz
+ // change active mode to 800x1600@90Hz
if (mIs2_4Client) {
EXPECT_CALL(*mMockComposer, setActiveConfigWithConstraints(EXTERNAL_DISPLAY, 3, _, _))
.WillOnce(Return(V2_4::Error::NONE));
@@ -669,29 +668,28 @@
.WillOnce(Return(V2_1::Error::NONE));
}
- for (int i = 0; i < configs.size(); i++) {
- const auto& config = configs[i];
- if (config.resolution.getWidth() == 800 && config.refreshRate == 1e9f / 11'111'111) {
+ for (size_t i = 0; i < modes.size(); i++) {
+ const auto& mode = modes[i];
+ if (mode.resolution.getWidth() == 800 && mode.refreshRate == 1e9f / 11'111'111) {
EXPECT_EQ(NO_ERROR,
- SurfaceComposerClient::
- setDesiredDisplayConfigSpecs(display, i, false,
- configs[i].refreshRate,
- configs[i].refreshRate,
- configs[i].refreshRate,
- configs[i].refreshRate));
- waitForDisplayTransaction();
- EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
+ SurfaceComposerClient::setDesiredDisplayModeSpecs(display, i, false,
+ modes[i].refreshRate,
+ modes[i].refreshRate,
+ modes[i].refreshRate,
+ modes[i].refreshRate));
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
+ EXPECT_TRUE(waitForModeChangedEvent(EXTERNAL_DISPLAY, i));
break;
}
}
- EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
- EXPECT_EQ(ui::Size(800, 1600), config.resolution);
- EXPECT_EQ(1e9f / 11'111'111, config.refreshRate);
+ EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode));
+ EXPECT_EQ(ui::Size(800, 1600), mode.resolution);
+ EXPECT_EQ(1e9f / 11'111'111, mode.refreshRate);
mFakeComposerClient->clearFrames();
{
- const ui::Size& resolution = config.resolution;
+ const ui::Size& resolution = mode.resolution;
auto surfaceControl =
mComposerClient->createSurface(String8("Display Test Surface Foo"),
resolution.getWidth(), resolution.getHeight(),
@@ -708,7 +706,7 @@
}
}
- // change active config to 1600x3200@120Hz
+ // change active mode to 1600x3200@120Hz
if (mIs2_4Client) {
EXPECT_CALL(*mMockComposer, setActiveConfigWithConstraints(EXTERNAL_DISPLAY, 4, _, _))
.WillOnce(Return(V2_4::Error::NONE));
@@ -717,28 +715,28 @@
.WillOnce(Return(V2_1::Error::NONE));
}
- for (int i = 0; i < configs.size(); i++) {
- const auto& config = configs[i];
- if (config.refreshRate == 1e9f / 8'333'333) {
+ for (int i = 0; i < modes.size(); i++) {
+ const auto& mode = modes[i];
+ if (mode.refreshRate == 1e9f / 8'333'333) {
EXPECT_EQ(NO_ERROR,
- SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, false,
- config.refreshRate,
- config.refreshRate,
- config.refreshRate,
- config.refreshRate));
- waitForDisplayTransaction();
- EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
+ SurfaceComposerClient::setDesiredDisplayModeSpecs(display, i, false,
+ mode.refreshRate,
+ mode.refreshRate,
+ mode.refreshRate,
+ mode.refreshRate));
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
+ EXPECT_TRUE(waitForModeChangedEvent(EXTERNAL_DISPLAY, i));
break;
}
}
- EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
- EXPECT_EQ(ui::Size(1600, 3200), config.resolution);
- EXPECT_EQ(1e9f / 8'333'333, config.refreshRate);
+ EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode));
+ EXPECT_EQ(ui::Size(1600, 3200), mode.resolution);
+ EXPECT_EQ(1e9f / 8'333'333, mode.refreshRate);
mFakeComposerClient->clearFrames();
{
- const ui::Size& resolution = config.resolution;
+ const ui::Size& resolution = mode.resolution;
auto surfaceControl =
mComposerClient->createSurface(String8("Display Test Surface Foo"),
resolution.getWidth(), resolution.getHeight(),
@@ -755,7 +753,7 @@
}
}
- // change active config to 1600x3200@90Hz
+ // change active mode to 1600x3200@90Hz
if (mIs2_4Client) {
EXPECT_CALL(*mMockComposer, setActiveConfigWithConstraints(EXTERNAL_DISPLAY, 5, _, _))
.WillOnce(Return(V2_4::Error::NONE));
@@ -764,28 +762,28 @@
.WillOnce(Return(V2_1::Error::NONE));
}
- for (int i = 0; i < configs.size(); i++) {
- const auto& config = configs[i];
- if (config.resolution.getWidth() == 1600 && config.refreshRate == 1e9f / 11'111'111) {
+ for (int i = 0; i < modes.size(); i++) {
+ const auto& mode = modes[i];
+ if (mode.resolution.getWidth() == 1600 && mode.refreshRate == 1e9f / 11'111'111) {
EXPECT_EQ(NO_ERROR,
- SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, false,
- config.refreshRate,
- config.refreshRate,
- config.refreshRate,
- config.refreshRate));
- waitForDisplayTransaction();
- EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
+ SurfaceComposerClient::setDesiredDisplayModeSpecs(display, i, false,
+ mode.refreshRate,
+ mode.refreshRate,
+ mode.refreshRate,
+ mode.refreshRate));
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
+ EXPECT_TRUE(waitForModeChangedEvent(EXTERNAL_DISPLAY, i));
break;
}
}
- EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
- EXPECT_EQ(ui::Size(1600, 3200), config.resolution);
- EXPECT_EQ(1e9f / 11'111'111, config.refreshRate);
+ EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode));
+ EXPECT_EQ(ui::Size(1600, 3200), mode.resolution);
+ EXPECT_EQ(1e9f / 11'111'111, mode.refreshRate);
mFakeComposerClient->clearFrames();
{
- const ui::Size& resolution = config.resolution;
+ const ui::Size& resolution = mode.resolution;
auto surfaceControl =
mComposerClient->createSurface(String8("Display Test Surface Foo"),
resolution.getWidth(), resolution.getHeight(),
@@ -804,7 +802,7 @@
mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
V2_1::IComposerCallback::Connection::DISCONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
mFakeComposerClient->clearFrames();
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, false));
}
@@ -815,15 +813,15 @@
mFakeComposerClient->hotplugDisplay(PRIMARY_DISPLAY,
V2_1::IComposerCallback::Connection::DISCONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(PRIMARY_DISPLAY);
EXPECT_TRUE(waitForHotplugEvent(PRIMARY_DISPLAY, false));
{
const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kPrimaryDisplayId);
EXPECT_TRUE(display == nullptr);
- DisplayConfig config;
- auto result = SurfaceComposerClient::getActiveDisplayConfig(display, &config);
+ ui::DisplayMode mode;
+ auto result = SurfaceComposerClient::getActiveDisplayMode(display, &mode);
EXPECT_NE(NO_ERROR, result);
}
@@ -840,7 +838,7 @@
mFakeComposerClient->hotplugDisplay(PRIMARY_DISPLAY,
V2_1::IComposerCallback::Connection::CONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(PRIMARY_DISPLAY);
EXPECT_TRUE(waitForHotplugEvent(PRIMARY_DISPLAY, true));
@@ -848,11 +846,126 @@
const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kPrimaryDisplayId);
EXPECT_FALSE(display == nullptr);
- DisplayConfig config;
- auto result = SurfaceComposerClient::getActiveDisplayConfig(display, &config);
+ ui::DisplayMode mode;
+ auto result = SurfaceComposerClient::getActiveDisplayMode(display, &mode);
EXPECT_EQ(NO_ERROR, result);
- ASSERT_EQ(ui::Size(400, 200), config.resolution);
- EXPECT_EQ(1e9f / 16'666'666, config.refreshRate);
+ ASSERT_EQ(ui::Size(400, 200), mode.resolution);
+ EXPECT_EQ(1e9f / 16'666'666, mode.refreshRate);
+ }
+ }
+
+ void Test_SubsequentHotplugConnectUpdatesDisplay(Display hwcDisplayId) {
+ ALOGD("DisplayTest::Test_SubsequentHotplugConnectUpdatesDisplay");
+
+ // Send a hotplug connected event to set up the initial display modes.
+ // The primary display is already connected so this will update it.
+ // If we're running the test of an external display this will create it.
+ setExpectationsForConfigs(hwcDisplayId,
+ {{.id = 1,
+ .w = 800,
+ .h = 1600,
+ .vsyncPeriod = 11'111'111,
+ .group = 1}},
+ /* activeConfig */ 1, 11'111'111);
+
+ mFakeComposerClient->hotplugDisplay(hwcDisplayId,
+ V2_1::IComposerCallback::Connection::CONNECTED);
+ waitForDisplayTransaction(hwcDisplayId);
+ EXPECT_TRUE(waitForHotplugEvent(hwcDisplayId, true));
+
+ const auto displayId = physicalIdFromHwcDisplayId(hwcDisplayId);
+ const auto display = SurfaceComposerClient::getPhysicalDisplayToken(displayId);
+ EXPECT_FALSE(display == nullptr);
+
+ // Verify that the active mode and the supported moded are updated
+ {
+ ui::DisplayMode mode;
+ EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode));
+ EXPECT_EQ(ui::Size(800, 1600), mode.resolution);
+ EXPECT_EQ(1e9f / 11'111'111, mode.refreshRate);
+
+ Vector<ui::DisplayMode> modes;
+ EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayModes(display, &modes));
+ EXPECT_EQ(modes.size(), 1);
+ }
+
+ // Send another hotplug connected event
+ setExpectationsForConfigs(hwcDisplayId,
+ {
+ {.id = 1,
+ .w = 800,
+ .h = 1600,
+ .vsyncPeriod = 16'666'666,
+ .group = 1},
+ {.id = 2,
+ .w = 800,
+ .h = 1600,
+ .vsyncPeriod = 11'111'111,
+ .group = 1},
+ {.id = 3,
+ .w = 800,
+ .h = 1600,
+ .vsyncPeriod = 8'333'333,
+ .group = 1},
+ },
+ /* activeConfig */ 1, 16'666'666);
+
+ mFakeComposerClient->hotplugDisplay(hwcDisplayId,
+ V2_1::IComposerCallback::Connection::CONNECTED);
+ waitForDisplayTransaction(hwcDisplayId);
+ EXPECT_TRUE(waitForHotplugEvent(hwcDisplayId, true));
+
+ // Verify that the active mode and the supported moded are updated
+ {
+ ui::DisplayMode mode;
+ EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode));
+ EXPECT_EQ(ui::Size(800, 1600), mode.resolution);
+ EXPECT_EQ(1e9f / 16'666'666, mode.refreshRate);
+ }
+
+ Vector<ui::DisplayMode> modes;
+ EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayModes(display, &modes));
+ EXPECT_EQ(modes.size(), 3);
+
+ EXPECT_EQ(ui::Size(800, 1600), modes[0].resolution);
+ EXPECT_EQ(1e9f / 16'666'666, modes[0].refreshRate);
+
+ EXPECT_EQ(ui::Size(800, 1600), modes[1].resolution);
+ EXPECT_EQ(1e9f / 11'111'111, modes[1].refreshRate);
+
+ EXPECT_EQ(ui::Size(800, 1600), modes[2].resolution);
+ EXPECT_EQ(1e9f / 8'333'333, modes[2].refreshRate);
+
+ // Verify that we are able to switch to any of the modes
+ for (int i = modes.size() - 1; i >= 0; i--) {
+ const auto hwcId = i + 1;
+ // Set up HWC expectations for the mode change
+ if (mIs2_4Client) {
+ EXPECT_CALL(*mMockComposer,
+ setActiveConfigWithConstraints(hwcDisplayId, hwcId, _, _))
+ .WillOnce(Return(V2_4::Error::NONE));
+ } else {
+ EXPECT_CALL(*mMockComposer, setActiveConfig(hwcDisplayId, hwcId))
+ .WillOnce(Return(V2_1::Error::NONE));
+ }
+
+ EXPECT_EQ(NO_ERROR,
+ SurfaceComposerClient::setDesiredDisplayModeSpecs(display, i, false,
+ modes[i].refreshRate,
+ modes[i].refreshRate,
+ modes[i].refreshRate,
+ modes[i].refreshRate));
+ // We need to refresh twice - once to apply the pending mode change request,
+ // and once to process the change.
+ waitForDisplayTransaction(hwcDisplayId);
+ waitForDisplayTransaction(hwcDisplayId);
+ EXPECT_TRUE(waitForModeChangedEvent(hwcDisplayId, i))
+ << "Failure while switching to mode " << i;
+
+ ui::DisplayMode mode;
+ EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode));
+ EXPECT_EQ(ui::Size(800, 1600), mode.resolution);
+ EXPECT_EQ(modes[i].refreshRate, mode.refreshRate);
}
}
@@ -911,6 +1024,14 @@
Test_HotplugPrimaryDisplay();
}
+TEST_F(DisplayTest_2_1, SubsequentHotplugConnectUpdatesPrimaryDisplay) {
+ Test_SubsequentHotplugConnectUpdatesDisplay(PRIMARY_DISPLAY);
+}
+
+TEST_F(DisplayTest_2_1, SubsequentHotplugConnectUpdatesExternalDisplay) {
+ Test_SubsequentHotplugConnectUpdatesDisplay(EXTERNAL_DISPLAY);
+}
+
using DisplayTest_2_2 = DisplayTest<FakeComposerService_2_2>;
TEST_F(DisplayTest_2_2, HotplugOneConfig) {
@@ -933,6 +1054,14 @@
Test_HotplugPrimaryDisplay();
}
+TEST_F(DisplayTest_2_2, SubsequentHotplugConnectUpdatesPrimaryDisplay) {
+ Test_SubsequentHotplugConnectUpdatesDisplay(PRIMARY_DISPLAY);
+}
+
+TEST_F(DisplayTest_2_2, SubsequentHotplugConnectUpdatesExternalDisplay) {
+ Test_SubsequentHotplugConnectUpdatesDisplay(EXTERNAL_DISPLAY);
+}
+
using DisplayTest_2_3 = DisplayTest<FakeComposerService_2_3>;
TEST_F(DisplayTest_2_3, HotplugOneConfig) {
@@ -955,6 +1084,14 @@
Test_HotplugPrimaryDisplay();
}
+TEST_F(DisplayTest_2_3, SubsequentHotplugConnectUpdatesPrimaryDisplay) {
+ Test_SubsequentHotplugConnectUpdatesDisplay(PRIMARY_DISPLAY);
+}
+
+TEST_F(DisplayTest_2_3, SubsequentHotplugConnectUpdatesExternalDisplay) {
+ Test_SubsequentHotplugConnectUpdatesDisplay(EXTERNAL_DISPLAY);
+}
+
using DisplayTest_2_4 = DisplayTest<FakeComposerService_2_4>;
TEST_F(DisplayTest_2_4, HotplugOneConfig) {
@@ -977,6 +1114,14 @@
Test_HotplugPrimaryDisplay();
}
+TEST_F(DisplayTest_2_4, SubsequentHotplugConnectUpdatesPrimaryDisplay) {
+ Test_SubsequentHotplugConnectUpdatesDisplay(PRIMARY_DISPLAY);
+}
+
+TEST_F(DisplayTest_2_4, SubsequentHotplugConnectUpdatesExternalDisplay) {
+ Test_SubsequentHotplugConnectUpdatesDisplay(EXTERNAL_DISPLAY);
+}
+
////////////////////////////////////////////////
template <typename FakeComposerService>
@@ -1021,10 +1166,10 @@
const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kPrimaryDisplayId);
ASSERT_FALSE(display == nullptr);
- DisplayConfig config;
- ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
+ ui::DisplayMode mode;
+ ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode));
- const ui::Size& resolution = config.resolution;
+ const ui::Size& resolution = mode.resolution;
mDisplayWidth = resolution.getWidth();
mDisplayHeight = resolution.getHeight();
@@ -1639,82 +1784,6 @@
EXPECT_TRUE(framesAreSame(referenceFrame2, Base::sFakeComposer->getLatestFrame()));
}
- void Test_DetachChildrenSameClient() {
- {
- TransactionScope ts(*Base::sFakeComposer);
- ts.show(mChild);
- ts.setPosition(mChild, 10, 10);
- ts.setPosition(Base::mFGSurfaceControl, 64, 64);
- }
-
- auto referenceFrame = Base::mBaseFrame;
- referenceFrame[Base::FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 64, 64 + 64};
- referenceFrame[CHILD_LAYER].mDisplayFrame =
- hwc_rect_t{64 + 10, 64 + 10, 64 + 10 + 10, 64 + 10 + 10};
- EXPECT_TRUE(framesAreSame(referenceFrame, Base::sFakeComposer->getLatestFrame()));
-
- {
- TransactionScope ts(*Base::sFakeComposer);
- ts.setPosition(Base::mFGSurfaceControl, 0, 0);
- ts.detachChildren(Base::mFGSurfaceControl);
- }
-
- {
- TransactionScope ts(*Base::sFakeComposer);
- ts.setPosition(Base::mFGSurfaceControl, 64, 64);
- ts.hide(mChild);
- }
-
- std::vector<RenderState> refFrame(2);
- refFrame[Base::BG_LAYER] = Base::mBaseFrame[Base::BG_LAYER];
- refFrame[Base::FG_LAYER] = Base::mBaseFrame[Base::FG_LAYER];
-
- EXPECT_TRUE(framesAreSame(refFrame, Base::sFakeComposer->getLatestFrame()));
- }
-
- void Test_DetachChildrenDifferentClient() {
- sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
- sp<SurfaceControl> childNewClient =
- newComposerClient->createSurface(String8("New Child Test Surface"), 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0,
- Base::mFGSurfaceControl->getHandle());
- ASSERT_TRUE(childNewClient != nullptr);
- ASSERT_TRUE(childNewClient->isValid());
- fillSurfaceRGBA8(childNewClient, LIGHT_GRAY);
-
- {
- TransactionScope ts(*Base::sFakeComposer);
- ts.hide(mChild);
- ts.show(childNewClient);
- ts.setPosition(childNewClient, 10, 10);
- ts.setPosition(Base::mFGSurfaceControl, 64, 64);
- }
-
- auto referenceFrame = Base::mBaseFrame;
- referenceFrame[Base::FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 64, 64 + 64};
- referenceFrame[CHILD_LAYER].mDisplayFrame =
- hwc_rect_t{64 + 10, 64 + 10, 64 + 10 + 10, 64 + 10 + 10};
- EXPECT_TRUE(framesAreSame(referenceFrame, Base::sFakeComposer->getLatestFrame()));
-
- {
- TransactionScope ts(*Base::sFakeComposer);
- ts.detachChildren(Base::mFGSurfaceControl);
- ts.setPosition(Base::mFGSurfaceControl, 0, 0);
- }
-
- {
- TransactionScope ts(*Base::sFakeComposer);
- ts.setPosition(Base::mFGSurfaceControl, 64, 64);
- ts.setPosition(childNewClient, 0, 0);
- ts.hide(childNewClient);
- }
-
- // Nothing should have changed. The child control becomes a no-op
- // zombie on detach. See comments for detachChildren in the
- // SurfaceControl.h file.
- EXPECT_TRUE(framesAreSame(referenceFrame, Base::sFakeComposer->getLatestFrame()));
- }
-
// Regression test for b/37673612
void Test_ChildrenWithParentBufferTransform() {
{
@@ -1815,14 +1884,6 @@
Test_ReparentChildren();
}
-TEST_F(ChildLayerTest_2_1, DISABLED_DetachChildrenSameClient) {
- Test_DetachChildrenSameClient();
-}
-
-TEST_F(ChildLayerTest_2_1, DISABLED_DetachChildrenDifferentClient) {
- Test_DetachChildrenDifferentClient();
-}
-
// Regression test for b/37673612
TEST_F(ChildLayerTest_2_1, DISABLED_ChildrenWithParentBufferTransform) {
Test_ChildrenWithParentBufferTransform();
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index 13b26fc..17928a0 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -73,6 +73,7 @@
"FrameTracerTest.cpp",
"TimerTest.cpp",
"TransactionApplicationTest.cpp",
+ "TransactionSurfaceFrameTest.cpp",
"StrongTypingTest.cpp",
"VSyncDispatchTimerQueueTest.cpp",
"VSyncDispatchRealtimeTest.cpp",
@@ -124,7 +125,7 @@
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.allocator@3.0",
"android.hardware.graphics.common@1.2",
- "android.hardware.power-cpp",
+ "android.hardware.power-V1-cpp",
"libbase",
"libbinder",
"libcutils",
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index f2051d9..b696a6d 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -62,15 +62,9 @@
using testing::_;
using testing::AtLeast;
-using testing::Between;
-using testing::ByMove;
using testing::DoAll;
-using testing::Field;
-using testing::Invoke;
using testing::IsNull;
using testing::Mock;
-using testing::NotNull;
-using testing::Ref;
using testing::Return;
using testing::ReturnRef;
using testing::SetArgPointee;
@@ -86,7 +80,6 @@
constexpr int DEFAULT_DISPLAY_WIDTH = 1920;
constexpr int DEFAULT_DISPLAY_HEIGHT = 1024;
-constexpr int DEFAULT_CONFIG_ID = 0;
constexpr int DEFAULT_TEXTURE_ID = 6000;
constexpr int DEFAULT_LAYER_STACK = 7000;
@@ -147,7 +140,7 @@
EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
EXPECT_CALL(*vsyncTracker, currentPeriod())
- .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
+ .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
constexpr ISchedulerCallback* kCallback = nullptr;
@@ -548,12 +541,6 @@
setupLatchedBuffer(test, layer);
}
- static void setupBufferLayerPostFrameCallExpectations(CompositionTest* test) {
- // BufferLayer::onPostComposition(), when there is no present fence
- EXPECT_CALL(*test->mComposer, getActiveConfig(HWC_DISPLAY, _))
- .WillOnce(DoAll(SetArgPointee<1>(DEFAULT_CONFIG_ID), Return(Error::NONE)));
- }
-
static void setupHwcSetGeometryCallExpectations(CompositionTest* test) {
if (!test->mDisplayOff) {
// TODO: Coverage of other values
@@ -632,8 +619,6 @@
.Times(1);
EXPECT_CALL(*test->mComposer, setLayerBuffer(HWC_DISPLAY, HWC_LAYER, _, _, _)).Times(1);
}
-
- setupBufferLayerPostFrameCallExpectations(test);
}
static void setupREBufferCompositionCommonCallExpectations(CompositionTest* test) {
@@ -793,7 +778,6 @@
static void setupInsecureREBufferCompositionCallExpectations(CompositionTest* test) {
setupInsecureREBufferCompositionCommonCallExpectations(test);
- Base::setupBufferLayerPostFrameCallExpectations(test);
}
static void setupInsecureREBufferScreenshotCompositionCallExpectations(CompositionTest* test) {
diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
index 45bc29c..7cc0032 100644
--- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
+++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp
@@ -141,10 +141,10 @@
createThread(std::move(vsyncSource));
mConnection = createConnection(mConnectionEventCallRecorder,
- ISurfaceComposer::EventRegistration::configChanged |
+ ISurfaceComposer::EventRegistration::modeChanged |
ISurfaceComposer::EventRegistration::frameRateOverride);
mThrottledConnection = createConnection(mThrottledConnectionEventCallRecorder,
- ISurfaceComposer::EventRegistration::configChanged,
+ ISurfaceComposer::EventRegistration::modeChanged,
mThrottledConnectionUid);
// A display must be connected for VSYNC events to be delivered.
@@ -257,10 +257,10 @@
auto args = mConnectionEventCallRecorder.waitForCall();
ASSERT_TRUE(args.has_value());
const auto& event = std::get<0>(args.value());
- EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED, event.header.type);
+ EXPECT_EQ(DisplayEventReceiver::DISPLAY_EVENT_MODE_CHANGE, event.header.type);
EXPECT_EQ(expectedDisplayId, event.header.displayId);
- EXPECT_EQ(expectedConfigId, event.config.configId);
- EXPECT_EQ(expectedVsyncPeriod, event.config.vsyncPeriod);
+ EXPECT_EQ(expectedConfigId, event.modeChange.modeId);
+ EXPECT_EQ(expectedVsyncPeriod, event.modeChange.vsyncPeriod);
}
void EventThreadTest::expectUidFrameRateMappingEventReceivedByConnection(
@@ -540,17 +540,17 @@
}
TEST_F(EventThreadTest, postConfigChangedPrimary) {
- mThread->onConfigChanged(INTERNAL_DISPLAY_ID, DisplayModeId(7), 16666666);
+ mThread->onModeChanged(INTERNAL_DISPLAY_ID, DisplayModeId(7), 16666666);
expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 7, 16666666);
}
TEST_F(EventThreadTest, postConfigChangedExternal) {
- mThread->onConfigChanged(EXTERNAL_DISPLAY_ID, DisplayModeId(5), 16666666);
+ mThread->onModeChanged(EXTERNAL_DISPLAY_ID, DisplayModeId(5), 16666666);
expectConfigChangedEventReceivedByConnection(EXTERNAL_DISPLAY_ID, 5, 16666666);
}
TEST_F(EventThreadTest, postConfigChangedPrimary64bit) {
- mThread->onConfigChanged(DISPLAY_ID_64BIT, DisplayModeId(7), 16666666);
+ mThread->onModeChanged(DISPLAY_ID_64BIT, DisplayModeId(7), 16666666);
expectConfigChangedEventReceivedByConnection(DISPLAY_ID_64BIT, 7, 16666666);
}
@@ -559,7 +559,7 @@
sp<MockEventThreadConnection> suppressConnection =
createConnection(suppressConnectionEventRecorder);
- mThread->onConfigChanged(INTERNAL_DISPLAY_ID, DisplayModeId(9), 16666666);
+ mThread->onModeChanged(INTERNAL_DISPLAY_ID, DisplayModeId(9), 16666666);
expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 9, 16666666);
auto args = suppressConnectionEventRecorder.waitForCall();
diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
index e2584e2..6e9f09b 100644
--- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
+++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
@@ -14,9 +14,6 @@
* limitations under the License.
*/
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wextra"
#include "gmock/gmock-spec-builders.h"
#include "mock/MockTimeStats.h"
@@ -177,16 +174,17 @@
static constexpr const uid_t sUidOne = 0;
static constexpr pid_t sPidOne = 10;
static constexpr pid_t sPidTwo = 20;
+static constexpr int32_t sInputEventId = 5;
TEST_F(FrameTimelineTest, tokenManagerRemovesStalePredictions) {
int64_t token1 = mTokenManager->generateTokenForPredictions({0, 0, 0});
- EXPECT_EQ(getPredictions().size(), 1);
+ EXPECT_EQ(getPredictions().size(), 1u);
flushTokens(systemTime() + maxTokenRetentionTime);
int64_t token2 = mTokenManager->generateTokenForPredictions({10, 20, 30});
std::optional<TimelineItem> predictions = mTokenManager->getPredictionsForToken(token1);
// token1 should have expired
- EXPECT_EQ(getPredictions().size(), 1);
+ EXPECT_EQ(getPredictions().size(), 1u);
EXPECT_EQ(predictions.has_value(), false);
predictions = mTokenManager->getPredictionsForToken(token2);
@@ -194,16 +192,16 @@
}
TEST_F(FrameTimelineTest, createSurfaceFrameForToken_getOwnerPidReturnsCorrectPid) {
- auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne,
+ auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne,
sLayerNameOne, sLayerNameOne);
- auto surfaceFrame2 = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidTwo, sUidOne,
+ auto surfaceFrame2 = mFrameTimeline->createSurfaceFrameForToken({}, sPidTwo, sUidOne,
sLayerNameOne, sLayerNameOne);
EXPECT_EQ(surfaceFrame1->getOwnerPid(), sPidOne);
EXPECT_EQ(surfaceFrame2->getOwnerPid(), sPidTwo);
}
TEST_F(FrameTimelineTest, createSurfaceFrameForToken_noToken) {
- auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne,
+ auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne,
sLayerNameOne, sLayerNameOne);
EXPECT_EQ(surfaceFrame->getPredictionState(), PredictionState::None);
}
@@ -211,21 +209,33 @@
TEST_F(FrameTimelineTest, createSurfaceFrameForToken_expiredToken) {
int64_t token1 = mTokenManager->generateTokenForPredictions({0, 0, 0});
flushTokens(systemTime() + maxTokenRetentionTime);
- auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(token1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ auto surfaceFrame =
+ mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne,
+ sLayerNameOne, sLayerNameOne);
EXPECT_EQ(surfaceFrame->getPredictionState(), PredictionState::Expired);
}
TEST_F(FrameTimelineTest, createSurfaceFrameForToken_validToken) {
int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
- auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(token1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ auto surfaceFrame =
+ mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne,
+ sLayerNameOne, sLayerNameOne);
EXPECT_EQ(surfaceFrame->getPredictionState(), PredictionState::Valid);
EXPECT_EQ(compareTimelineItems(surfaceFrame->getPredictions(), TimelineItem(10, 20, 30)), true);
}
+TEST_F(FrameTimelineTest, createSurfaceFrameForToken_validInputEventId) {
+ int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
+ constexpr int32_t inputEventId = 1;
+ auto surfaceFrame =
+ mFrameTimeline->createSurfaceFrameForToken({token1, inputEventId}, sPidOne, sUidOne,
+ sLayerNameOne, sLayerNameOne);
+
+ EXPECT_EQ(inputEventId, surfaceFrame->getInputEventId());
+}
+
TEST_F(FrameTimelineTest, presentFenceSignaled_droppedFramesNotUpdated) {
// Global increment
EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_));
@@ -234,8 +244,9 @@
int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
int64_t token2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
- auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(token1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ auto surfaceFrame1 =
+ mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne,
+ sLayerNameOne, sLayerNameOne);
// Set up the display frame
mFrameTimeline->setSfWakeUp(token1, 20, 11);
@@ -264,11 +275,11 @@
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 30});
int64_t sfToken2 = mTokenManager->generateTokenForPredictions({52, 56, 60});
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
auto surfaceFrame2 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
- sLayerNameTwo, sLayerNameTwo);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameTwo, sLayerNameTwo);
mFrameTimeline->setSfWakeUp(sfToken1, 22, 11);
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame1);
@@ -288,8 +299,8 @@
// Trigger a flush by finalizing the next DisplayFrame
auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
auto surfaceFrame3 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken2, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
mFrameTimeline->setSfWakeUp(sfToken2, 52, 11);
surfaceFrame3->setPresentState(SurfaceFrame::PresentState::Dropped);
mFrameTimeline->addSurfaceFrame(surfaceFrame3);
@@ -320,8 +331,9 @@
int64_t sfToken = mTokenManager->generateTokenForPredictions(
{22 + frameTimeFactor, 26 + frameTimeFactor, 30 + frameTimeFactor});
auto surfaceFrame =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId},
+ sPidOne, sUidOne, sLayerNameOne,
+ sLayerNameOne);
mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor, 11);
surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame);
@@ -341,8 +353,8 @@
int64_t sfToken = mTokenManager->generateTokenForPredictions(
{22 + frameTimeFactor, 26 + frameTimeFactor, 30 + frameTimeFactor});
auto surfaceFrame =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor, 11);
surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame);
@@ -356,18 +368,18 @@
}
TEST_F(FrameTimelineTest, surfaceFrameEndTimeAcquireFenceAfterQueue) {
- auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, 0,
- "acquireFenceAfterQueue",
- "acquireFenceAfterQueue");
+ auto surfaceFrame =
+ mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, 0, "acquireFenceAfterQueue",
+ "acquireFenceAfterQueue");
surfaceFrame->setActualQueueTime(123);
surfaceFrame->setAcquireFenceTime(456);
EXPECT_EQ(surfaceFrame->getActuals().endTime, 456);
}
TEST_F(FrameTimelineTest, surfaceFrameEndTimeAcquireFenceBeforeQueue) {
- auto surfaceFrame = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, 0,
- "acquireFenceAfterQueue",
- "acquireFenceAfterQueue");
+ auto surfaceFrame =
+ mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, 0, "acquireFenceAfterQueue",
+ "acquireFenceAfterQueue");
surfaceFrame->setActualQueueTime(456);
surfaceFrame->setAcquireFenceTime(123);
EXPECT_EQ(surfaceFrame->getActuals().endTime, 456);
@@ -383,8 +395,8 @@
// Size shouldn't exceed maxDisplayFrames - 64
for (size_t i = 0; i < *maxDisplayFrames + 10; i++) {
auto surfaceFrame =
- mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerNameOne,
+ sLayerNameOne);
int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30});
mFrameTimeline->setSfWakeUp(sfToken, 22, 11);
surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -395,15 +407,15 @@
// Increase the size to 256
mFrameTimeline->setMaxDisplayFrames(256);
- EXPECT_EQ(*maxDisplayFrames, 256);
+ EXPECT_EQ(*maxDisplayFrames, 256u);
// Global increment
EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_))
.Times(static_cast<int32_t>(*maxDisplayFrames + 10));
for (size_t i = 0; i < *maxDisplayFrames + 10; i++) {
auto surfaceFrame =
- mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerNameOne,
+ sLayerNameOne);
int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30});
mFrameTimeline->setSfWakeUp(sfToken, 22, 11);
surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -414,15 +426,15 @@
// Shrink the size to 128
mFrameTimeline->setMaxDisplayFrames(128);
- EXPECT_EQ(*maxDisplayFrames, 128);
+ EXPECT_EQ(*maxDisplayFrames, 128u);
// Global increment
EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_))
.Times(static_cast<int32_t>(*maxDisplayFrames + 10));
for (size_t i = 0; i < *maxDisplayFrames + 10; i++) {
auto surfaceFrame =
- mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerNameOne,
+ sLayerNameOne);
int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30});
mFrameTimeline->setSfWakeUp(sfToken, 22, 11);
surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -449,8 +461,8 @@
std::chrono::duration_cast<std::chrono::nanoseconds>(56ms).count(),
std::chrono::duration_cast<std::chrono::nanoseconds>(60ms).count()});
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
mFrameTimeline->setSfWakeUp(sfToken1,
std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count(),
11);
@@ -478,8 +490,8 @@
std::chrono::duration_cast<std::chrono::nanoseconds>(56ms).count(),
std::chrono::duration_cast<std::chrono::nanoseconds>(60ms).count()});
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
mFrameTimeline->setSfWakeUp(sfToken1,
std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count(),
30);
@@ -507,8 +519,8 @@
std::chrono::duration_cast<std::chrono::nanoseconds>(86ms).count(),
std::chrono::duration_cast<std::chrono::nanoseconds>(90ms).count()});
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame1->setAcquireFenceTime(
std::chrono::duration_cast<std::chrono::nanoseconds>(45ms).count());
mFrameTimeline->setSfWakeUp(sfToken1,
@@ -542,8 +554,9 @@
int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
int64_t token2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
- auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(token1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ auto surfaceFrame1 =
+ mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne,
+ sLayerNameOne, sLayerNameOne);
// Set up the display frame
mFrameTimeline->setSfWakeUp(token1, 20, 11);
@@ -558,7 +571,7 @@
mFrameTimeline->setSfPresent(55, presentFence2);
auto packets = readFrameTimelinePacketsBlocking(tracingSession.get());
- EXPECT_EQ(packets.size(), 0);
+ EXPECT_EQ(packets.size(), 0u);
}
TEST_F(FrameTimelineTest, tracing_sanityTest) {
@@ -573,8 +586,9 @@
tracingSession->StartBlocking();
int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
int64_t token2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
- auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(token1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ auto surfaceFrame1 =
+ mFrameTimeline->createSurfaceFrameForToken({token1, sInputEventId}, sPidOne, sUidOne,
+ sLayerNameOne, sLayerNameOne);
// Set up the display frame
mFrameTimeline->setSfWakeUp(token2, 20, 11);
@@ -594,7 +608,7 @@
auto packets = readFrameTimelinePacketsBlocking(tracingSession.get());
// Display Frame 1 has 8 packets - 4 from DisplayFrame and 4 from SurfaceFrame.
- EXPECT_EQ(packets.size(), 8);
+ EXPECT_EQ(packets.size(), 8u);
}
TEST_F(FrameTimelineTest, traceDisplayFrame_invalidTokenDoesNotEmitTracePacket) {
@@ -622,7 +636,7 @@
tracingSession->StopBlocking();
auto packets = readFrameTimelinePacketsBlocking(tracingSession.get());
- EXPECT_EQ(packets.size(), 0);
+ EXPECT_EQ(packets.size(), 0u);
}
TEST_F(FrameTimelineTest, traceSurfaceFrame_invalidTokenDoesNotEmitTracePacket) {
@@ -635,7 +649,7 @@
tracingSession->StartBlocking();
int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
int64_t token2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
- auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken(std::nullopt, sPidOne, sUidOne,
+ auto surfaceFrame1 = mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne,
sLayerNameOne, sLayerNameOne);
// Set up the display frame
@@ -657,7 +671,7 @@
auto packets = readFrameTimelinePacketsBlocking(tracingSession.get());
// Display Frame 1 has 4 packets (SurfaceFrame shouldn't be traced since it has an invalid
// token).
- EXPECT_EQ(packets.size(), 4);
+ EXPECT_EQ(packets.size(), 4u);
}
void validateTraceEvent(const ProtoExpectedDisplayFrameStart& received,
@@ -791,12 +805,12 @@
tracingSession->StopBlocking();
auto packets = readFrameTimelinePacketsBlocking(tracingSession.get());
- EXPECT_EQ(packets.size(), 4);
+ EXPECT_EQ(packets.size(), 4u);
// Packet - 0 : ExpectedDisplayFrameStart
const auto& packet0 = packets[0];
ASSERT_TRUE(packet0.has_timestamp());
- EXPECT_EQ(packet0.timestamp(), 10);
+ EXPECT_EQ(packet0.timestamp(), 10u);
ASSERT_TRUE(packet0.has_frame_timeline_event());
const auto& event0 = packet0.frame_timeline_event();
@@ -807,7 +821,7 @@
// Packet - 1 : FrameEnd (ExpectedDisplayFrame)
const auto& packet1 = packets[1];
ASSERT_TRUE(packet1.has_timestamp());
- EXPECT_EQ(packet1.timestamp(), 25);
+ EXPECT_EQ(packet1.timestamp(), 25u);
ASSERT_TRUE(packet1.has_frame_timeline_event());
const auto& event1 = packet1.frame_timeline_event();
@@ -818,7 +832,7 @@
// Packet - 2 : ActualDisplayFrameStart
const auto& packet2 = packets[2];
ASSERT_TRUE(packet2.has_timestamp());
- EXPECT_EQ(packet2.timestamp(), 20);
+ EXPECT_EQ(packet2.timestamp(), 20u);
ASSERT_TRUE(packet2.has_frame_timeline_event());
const auto& event2 = packet2.frame_timeline_event();
@@ -829,7 +843,7 @@
// Packet - 3 : FrameEnd (ActualDisplayFrame)
const auto& packet3 = packets[3];
ASSERT_TRUE(packet3.has_timestamp());
- EXPECT_EQ(packet3.timestamp(), 26);
+ EXPECT_EQ(packet3.timestamp(), 26u);
ASSERT_TRUE(packet3.has_frame_timeline_event());
const auto& event3 = packet3.frame_timeline_event();
@@ -853,8 +867,8 @@
int64_t displayFrameToken2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame1->setActualStartTime(0);
surfaceFrame1->setActualQueueTime(15);
surfaceFrame1->setAcquireFenceTime(20);
@@ -904,12 +918,12 @@
tracingSession->StopBlocking();
auto packets = readFrameTimelinePacketsBlocking(tracingSession.get());
- EXPECT_EQ(packets.size(), 8);
+ EXPECT_EQ(packets.size(), 8u);
// Packet - 4 : ExpectedSurfaceFrameStart
const auto& packet4 = packets[4];
ASSERT_TRUE(packet4.has_timestamp());
- EXPECT_EQ(packet4.timestamp(), 10);
+ EXPECT_EQ(packet4.timestamp(), 10u);
ASSERT_TRUE(packet4.has_frame_timeline_event());
const auto& event4 = packet4.frame_timeline_event();
@@ -920,7 +934,7 @@
// Packet - 5 : FrameEnd (ExpectedSurfaceFrame)
const auto& packet5 = packets[5];
ASSERT_TRUE(packet5.has_timestamp());
- EXPECT_EQ(packet5.timestamp(), 25);
+ EXPECT_EQ(packet5.timestamp(), 25u);
ASSERT_TRUE(packet5.has_frame_timeline_event());
const auto& event5 = packet5.frame_timeline_event();
@@ -931,7 +945,7 @@
// Packet - 6 : ActualSurfaceFrameStart
const auto& packet6 = packets[6];
ASSERT_TRUE(packet6.has_timestamp());
- EXPECT_EQ(packet6.timestamp(), 10);
+ EXPECT_EQ(packet6.timestamp(), 10u);
ASSERT_TRUE(packet6.has_frame_timeline_event());
const auto& event6 = packet6.frame_timeline_event();
@@ -942,7 +956,7 @@
// Packet - 7 : FrameEnd (ActualSurfaceFrame)
const auto& packet7 = packets[7];
ASSERT_TRUE(packet7.has_timestamp());
- EXPECT_EQ(packet7.timestamp(), 20);
+ EXPECT_EQ(packet7.timestamp(), 20u);
ASSERT_TRUE(packet7.has_frame_timeline_event());
const auto& event7 = packet7.frame_timeline_event();
@@ -961,8 +975,8 @@
int64_t surfaceFrameToken = mTokenManager->generateTokenForPredictions({10, 20, 30});
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 30});
auto surfaceFrame =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
mFrameTimeline->setSfWakeUp(sfToken1, 22, 11);
surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame);
@@ -1126,8 +1140,8 @@
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({5, 16, 40});
int64_t surfaceFrameToken2 = mTokenManager->generateTokenForPredictions({25, 36, 70});
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame1->setAcquireFenceTime(16);
mFrameTimeline->setSfWakeUp(sfToken1, 22, 11);
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1145,8 +1159,8 @@
// Trigger a flush by finalizing the next DisplayFrame
auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
auto surfaceFrame2 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken2, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame2->setAcquireFenceTime(36);
mFrameTimeline->setSfWakeUp(sfToken2, 52, 11);
surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1199,8 +1213,8 @@
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({5, 16, 40});
int64_t surfaceFrameToken2 = mTokenManager->generateTokenForPredictions({25, 36, 70});
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame1->setAcquireFenceTime(16);
mFrameTimeline->setSfWakeUp(sfToken1, 22, 11);
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1218,8 +1232,8 @@
// Trigger a flush by finalizing the next DisplayFrame
auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
auto surfaceFrame2 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken2, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame2->setAcquireFenceTime(36);
mFrameTimeline->setSfWakeUp(sfToken2, 52, 11);
surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1270,8 +1284,8 @@
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({42, 46, 50});
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({5, 26, 60});
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame1->setAcquireFenceTime(40);
mFrameTimeline->setSfWakeUp(sfToken1, 42, 11);
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1316,8 +1330,8 @@
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({5, 16, 30});
int64_t surfaceFrameToken2 = mTokenManager->generateTokenForPredictions({25, 36, 50});
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame1->setAcquireFenceTime(26);
mFrameTimeline->setSfWakeUp(sfToken1, 32, 11);
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1335,8 +1349,8 @@
// Trigger a flush by finalizing the next DisplayFrame
auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
auto surfaceFrame2 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken2, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame2->setAcquireFenceTime(40);
mFrameTimeline->setSfWakeUp(sfToken2, 43, 11);
surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1390,8 +1404,8 @@
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({52, 56, 60});
int64_t sfToken2 = mTokenManager->generateTokenForPredictions({112, 116, 120});
auto surfaceFrame1 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken1, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame1->setAcquireFenceTime(50);
mFrameTimeline->setSfWakeUp(sfToken1, 52, 30);
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -1409,8 +1423,8 @@
// Trigger a flush by finalizing the next DisplayFrame
auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
auto surfaceFrame2 =
- mFrameTimeline->createSurfaceFrameForToken(surfaceFrameToken2, sPidOne, sUidOne,
- sLayerNameOne, sLayerNameOne);
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame2->setAcquireFenceTime(84);
mFrameTimeline->setSfWakeUp(sfToken2, 112, 30);
surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented, 54);
@@ -1456,6 +1470,3 @@
JankType::AppDeadlineMissed | JankType::BufferStuffing);
}
} // namespace android::frametimeline
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wextra"
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
index 1e24c0a..6b82170 100644
--- a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
@@ -175,90 +175,5 @@
EXPECT_EQ(hal::Error::UNSUPPORTED, result);
}
-class HWComposerConfigsTest : public testing::Test {
-public:
- Hwc2::mock::Composer* mHal = new StrictMock<Hwc2::mock::Composer>();
- MockHWC2ComposerCallback mCallback;
-
- void setActiveConfig(Config config) {
- EXPECT_CALL(*mHal, getActiveConfig(_, _))
- .WillRepeatedly(DoAll(SetArgPointee<1>(config), Return(V2_1::Error::NONE)));
- }
-
- void setDisplayConfigs(std::vector<Config> configs) {
- EXPECT_CALL(*mHal, getDisplayConfigs(_, _))
- .WillOnce(DoAll(SetArgPointee<1>(configs), Return(V2_1::Error::NONE)));
- EXPECT_CALL(*mHal, getDisplayAttribute(_, _, _, _))
- .WillRepeatedly(DoAll(SetArgPointee<3>(1), Return(V2_1::Error::NONE)));
- }
-
- void testSetActiveModeWithConstraintsCommon(bool isVsyncPeriodSwitchSupported);
-};
-
-void HWComposerConfigsTest::testSetActiveModeWithConstraintsCommon(
- bool isVsyncPeriodSwitchSupported) {
- EXPECT_CALL(*mHal, getMaxVirtualDisplayCount()).WillOnce(Return(0));
- EXPECT_CALL(*mHal, getCapabilities()).WillOnce(Return(std::vector<hal::Capability>{}));
- EXPECT_CALL(*mHal, getLayerGenericMetadataKeys(_)).WillOnce(Return(V2_4::Error::UNSUPPORTED));
- EXPECT_CALL(*mHal, registerCallback(_));
- EXPECT_CALL(*mHal, setVsyncEnabled(_, _)).WillRepeatedly(Return(V2_1::Error::NONE));
- EXPECT_CALL(*mHal, getDisplayIdentificationData(_, _, _))
- .WillRepeatedly(Return(V2_1::Error::UNSUPPORTED));
- EXPECT_CALL(*mHal, setClientTargetSlotCount(_)).WillRepeatedly(Return(V2_1::Error::NONE));
-
- EXPECT_CALL(*mHal, isVsyncPeriodSwitchSupported())
- .WillRepeatedly(Return(isVsyncPeriodSwitchSupported));
-
- if (isVsyncPeriodSwitchSupported) {
- EXPECT_CALL(*mHal, setActiveConfigWithConstraints(_, _, _, _))
- .WillRepeatedly(Return(V2_4::Error::NONE));
- } else {
- EXPECT_CALL(*mHal, setActiveConfig(_, _)).WillRepeatedly(Return(V2_1::Error::NONE));
- }
-
- impl::HWComposer hwc{std::unique_ptr<Hwc2::Composer>(mHal)};
- hwc.setConfiguration(&mCallback, 123);
-
- setDisplayConfigs({15});
- setActiveConfig(15);
-
- const auto physicalId = PhysicalDisplayId::fromPort(0);
- const hal::HWDisplayId hwcId = 0;
- hwc.allocatePhysicalDisplay(hwcId, physicalId);
-
- hal::VsyncPeriodChangeConstraints constraints;
- constraints.desiredTimeNanos = systemTime();
- constraints.seamlessRequired = false;
-
- hal::VsyncPeriodChangeTimeline timeline = {0, 0, 0};
- constexpr Config kConfigIndex = 0;
- const auto status =
- hwc.setActiveModeWithConstraints(physicalId, kConfigIndex, constraints, &timeline);
- EXPECT_EQ(NO_ERROR, status);
-
- const std::vector<Config> kConfigs{7, 8, 9, 10, 11};
- // Change the set of supported modes.
- setDisplayConfigs(kConfigs);
- setActiveConfig(11);
- hwc.onHotplug(hwcId, hal::Connection::CONNECTED);
- hwc.allocatePhysicalDisplay(hwcId, physicalId);
-
- for (size_t configIndex = 0; configIndex < kConfigs.size(); configIndex++) {
- const auto status =
- hwc.setActiveModeWithConstraints(physicalId,
- static_cast<hal::HWConfigId>(configIndex),
- constraints, &timeline);
- EXPECT_EQ(NO_ERROR, status) << "Error when switching to config " << configIndex;
- }
-}
-
-TEST_F(HWComposerConfigsTest, setActiveModeWithConstraintsWithVsyncSwitchingSupported) {
- testSetActiveModeWithConstraintsCommon(/*supported=*/true);
-}
-
-TEST_F(HWComposerConfigsTest, setActiveModeWithConstraintsWithVsyncSwitchingNotSupported) {
- testSetActiveModeWithConstraintsCommon(/*supported=*/false);
-}
-
} // namespace
} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
index 04cafbc..fec590e 100644
--- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp
@@ -113,12 +113,12 @@
RefreshRateConfigs mConfigs{{DisplayMode::Builder(0)
.setId(DisplayModeId(0))
.setVsyncPeriod(int32_t(LO_FPS_PERIOD))
- .setConfigGroup(0)
+ .setGroup(0)
.build(),
DisplayMode::Builder(1)
.setId(DisplayModeId(1))
.setVsyncPeriod(int32_t(HI_FPS_PERIOD))
- .setConfigGroup(0)
+ .setGroup(0)
.build()},
DisplayModeId(0)};
diff --git a/services/surfaceflinger/tests/unittests/LayerInfoTest.cpp b/services/surfaceflinger/tests/unittests/LayerInfoTest.cpp
index d5c9b57..be76e8f 100644
--- a/services/surfaceflinger/tests/unittests/LayerInfoTest.cpp
+++ b/services/surfaceflinger/tests/unittests/LayerInfoTest.cpp
@@ -53,7 +53,7 @@
for (int i = 1; i <= kNumFrames; i++) {
frameTimes.push_back(FrameTimeData{.presentTime = kPeriod * i,
.queueTime = 0,
- .pendingConfigChange = false});
+ .pendingModeChange = false});
}
setFrameTimes(frameTimes);
const auto averageFrameTime = calculateAverageFrameTime();
@@ -71,7 +71,7 @@
for (int i = 1; i <= kNumFrames; i++) {
frameTimes.push_back(FrameTimeData{.presentTime = 0,
.queueTime = kPeriod * i,
- .pendingConfigChange = false});
+ .pendingModeChange = false});
}
setFrameTimes(frameTimes);
setLastRefreshRate(Fps(20.0f)); // Set to some valid value
@@ -89,7 +89,7 @@
for (int i = 1; i <= kNumFrames; i++) {
frameTimesWithoutConfigChange.push_back(FrameTimeData{.presentTime = period * i,
.queueTime = period * i,
- .pendingConfigChange = false});
+ .pendingModeChange = false});
}
setFrameTimes(frameTimesWithoutConfigChange);
@@ -98,7 +98,7 @@
{
// Config change in the first record
auto frameTimes = frameTimesWithoutConfigChange;
- frameTimes[0].pendingConfigChange = true;
+ frameTimes[0].pendingModeChange = true;
setFrameTimes(frameTimes);
ASSERT_FALSE(calculateAverageFrameTime().has_value());
}
@@ -106,7 +106,7 @@
{
// Config change in the last record
auto frameTimes = frameTimesWithoutConfigChange;
- frameTimes[frameTimes.size() - 1].pendingConfigChange = true;
+ frameTimes[frameTimes.size() - 1].pendingModeChange = true;
setFrameTimes(frameTimes);
ASSERT_FALSE(calculateAverageFrameTime().has_value());
}
@@ -114,7 +114,7 @@
{
// Config change in the middle
auto frameTimes = frameTimesWithoutConfigChange;
- frameTimes[frameTimes.size() / 2].pendingConfigChange = true;
+ frameTimes[frameTimes.size() / 2].pendingModeChange = true;
setFrameTimes(frameTimes);
ASSERT_FALSE(calculateAverageFrameTime().has_value());
}
@@ -131,12 +131,12 @@
for (int i = 1; i <= kNumIterations; i++) {
frameTimes.push_back(FrameTimeData{.presentTime = kExpectedPeriod * i,
.queueTime = 0,
- .pendingConfigChange = false});
+ .pendingModeChange = false});
// A duplicate frame
frameTimes.push_back(FrameTimeData{.presentTime = kExpectedPeriod * i + kSmallPeriod,
.queueTime = 0,
- .pendingConfigChange = false});
+ .pendingModeChange = false});
}
setFrameTimes(frameTimes);
const auto averageFrameTime = calculateAverageFrameTime();
@@ -156,7 +156,7 @@
auto record = [&](nsecs_t time) {
frameTimes.push_back(
- FrameTimeData{.presentTime = time, .queueTime = 0, .pendingConfigChange = false});
+ FrameTimeData{.presentTime = time, .queueTime = 0, .pendingModeChange = false});
};
auto time = kExpectedPeriod; // Start with non-zero time.
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index 738ded1..376995f 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -81,24 +81,25 @@
static inline const DisplayModeId HWC_CONFIG_ID_50 = DisplayModeId(6);
// Test configs
- DisplayModePtr mConfig60 = createConfig(HWC_CONFIG_ID_60, 0, Fps(60.0f).getPeriodNsecs());
- DisplayModePtr mConfig90 = createConfig(HWC_CONFIG_ID_90, 0, Fps(90.0f).getPeriodNsecs());
+ DisplayModePtr mConfig60 = createDisplayMode(HWC_CONFIG_ID_60, 0, Fps(60.0f).getPeriodNsecs());
+ DisplayModePtr mConfig90 = createDisplayMode(HWC_CONFIG_ID_90, 0, Fps(90.0f).getPeriodNsecs());
DisplayModePtr mConfig90DifferentGroup =
- createConfig(HWC_CONFIG_ID_90, 1, Fps(90.0f).getPeriodNsecs());
+ createDisplayMode(HWC_CONFIG_ID_90, 1, Fps(90.0f).getPeriodNsecs());
DisplayModePtr mConfig90DifferentResolution =
- createConfig(HWC_CONFIG_ID_90, 0, Fps(90.0f).getPeriodNsecs(), ui::Size(111, 222));
- DisplayModePtr mConfig72 = createConfig(HWC_CONFIG_ID_72, 0, Fps(72.0f).getPeriodNsecs());
+ createDisplayMode(HWC_CONFIG_ID_90, 0, Fps(90.0f).getPeriodNsecs(), ui::Size(111, 222));
+ DisplayModePtr mConfig72 = createDisplayMode(HWC_CONFIG_ID_72, 0, Fps(72.0f).getPeriodNsecs());
DisplayModePtr mConfig72DifferentGroup =
- createConfig(HWC_CONFIG_ID_72, 1, Fps(72.0f).getPeriodNsecs());
- DisplayModePtr mConfig120 = createConfig(HWC_CONFIG_ID_120, 0, Fps(120.0f).getPeriodNsecs());
+ createDisplayMode(HWC_CONFIG_ID_72, 1, Fps(72.0f).getPeriodNsecs());
+ DisplayModePtr mConfig120 =
+ createDisplayMode(HWC_CONFIG_ID_120, 0, Fps(120.0f).getPeriodNsecs());
DisplayModePtr mConfig120DifferentGroup =
- createConfig(HWC_CONFIG_ID_120, 1, Fps(120.0f).getPeriodNsecs());
- DisplayModePtr mConfig30 = createConfig(HWC_CONFIG_ID_30, 0, Fps(30.0f).getPeriodNsecs());
+ createDisplayMode(HWC_CONFIG_ID_120, 1, Fps(120.0f).getPeriodNsecs());
+ DisplayModePtr mConfig30 = createDisplayMode(HWC_CONFIG_ID_30, 0, Fps(30.0f).getPeriodNsecs());
DisplayModePtr mConfig30DifferentGroup =
- createConfig(HWC_CONFIG_ID_30, 1, Fps(30.0f).getPeriodNsecs());
+ createDisplayMode(HWC_CONFIG_ID_30, 1, Fps(30.0f).getPeriodNsecs());
DisplayModePtr mConfig25DifferentGroup =
- createConfig(HWC_CONFIG_ID_25, 1, Fps(25.0f).getPeriodNsecs());
- DisplayModePtr mConfig50 = createConfig(HWC_CONFIG_ID_50, 0, Fps(50.0f).getPeriodNsecs());
+ createDisplayMode(HWC_CONFIG_ID_25, 1, Fps(25.0f).getPeriodNsecs());
+ DisplayModePtr mConfig50 = createDisplayMode(HWC_CONFIG_ID_50, 0, Fps(50.0f).getPeriodNsecs());
// Test device configurations
// The positions of the configs in the arrays below MUST match their IDs. For example,
@@ -128,8 +129,8 @@
RefreshRate mExpected60Config = {HWC_CONFIG_ID_60, mConfig60, Fps(60),
RefreshRate::ConstructorTag(0)};
RefreshRate mExpectedAlmost60Config = {HWC_CONFIG_ID_60,
- createConfig(HWC_CONFIG_ID_60, 0, 16666665), Fps(60),
- RefreshRate::ConstructorTag(0)};
+ createDisplayMode(HWC_CONFIG_ID_60, 0, 16666665),
+ Fps(60), RefreshRate::ConstructorTag(0)};
RefreshRate mExpected90Config = {HWC_CONFIG_ID_90, mConfig90, Fps(90),
RefreshRate::ConstructorTag(0)};
RefreshRate mExpected90DifferentGroupConfig = {HWC_CONFIG_ID_90, mConfig90DifferentGroup,
@@ -144,8 +145,8 @@
RefreshRate mExpected120Config = {HWC_CONFIG_ID_120, mConfig120, Fps(120),
RefreshRate::ConstructorTag(0)};
private:
- DisplayModePtr createConfig(DisplayModeId configId, int32_t configGroup, int64_t vsyncPeriod,
- ui::Size resolution = ui::Size());
+ DisplayModePtr createDisplayMode(DisplayModeId modeId, int32_t group, int64_t vsyncPeriod,
+ ui::Size resolution = ui::Size());
};
using Builder = DisplayMode::Builder;
@@ -162,12 +163,12 @@
ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
}
-DisplayModePtr RefreshRateConfigsTest::createConfig(DisplayModeId configId, int32_t configGroup,
- int64_t vsyncPeriod, ui::Size resolution) {
- return DisplayMode::Builder(hal::HWConfigId(configId.value()))
- .setId(configId)
+DisplayModePtr RefreshRateConfigsTest::createDisplayMode(DisplayModeId modeId, int32_t group,
+ int64_t vsyncPeriod, ui::Size resolution) {
+ return DisplayMode::Builder(hal::HWConfigId(modeId.value()))
+ .setId(modeId)
.setVsyncPeriod(int32_t(vsyncPeriod))
- .setConfigGroup(configGroup)
+ .setGroup(group)
.setHeight(resolution.height)
.setWidth(resolution.width)
.build();
@@ -226,7 +227,7 @@
ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {Fps(60), Fps(90)}}),
0);
- refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90);
+ refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_90);
const auto& minRate90 = getMinRefreshRateByPolicy(*refreshRateConfigs);
const auto& performanceRate90 = refreshRateConfigs->getMaxRefreshRateByPolicy();
@@ -252,7 +253,7 @@
ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {Fps(60), Fps(90)}}),
0);
- refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90);
+ refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_90);
const auto& minRate90 = getMinRefreshRateByPolicy(*refreshRateConfigs);
const auto& performanceRate90 = refreshRateConfigs->getMaxRefreshRateByPolicy();
@@ -288,20 +289,20 @@
/*currentConfigId=*/HWC_CONFIG_ID_60);
{
auto current = refreshRateConfigs->getCurrentRefreshRate();
- EXPECT_EQ(current.getConfigId(), HWC_CONFIG_ID_60);
+ EXPECT_EQ(current.getModeId(), HWC_CONFIG_ID_60);
}
- refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90);
+ refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_90);
{
auto current = refreshRateConfigs->getCurrentRefreshRate();
- EXPECT_EQ(current.getConfigId(), HWC_CONFIG_ID_90);
+ EXPECT_EQ(current.getModeId(), HWC_CONFIG_ID_90);
}
ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_90, {Fps(90), Fps(90)}}),
0);
{
auto current = refreshRateConfigs->getCurrentRefreshRate();
- EXPECT_EQ(current.getConfigId(), HWC_CONFIG_ID_90);
+ EXPECT_EQ(current.getModeId(), HWC_CONFIG_ID_90);
}
}
@@ -1196,30 +1197,30 @@
ASSERT_EQ(HWC_CONFIG_ID_60,
refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
- .getConfigId());
+ .getModeId());
RefreshRateConfigs::Policy policy;
- policy.defaultConfig = refreshRateConfigs->getCurrentPolicy().defaultConfig;
+ policy.defaultMode = refreshRateConfigs->getCurrentPolicy().defaultMode;
policy.allowGroupSwitching = true;
ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy(policy), 0);
ASSERT_EQ(HWC_CONFIG_ID_90,
refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
- .getConfigId());
+ .getModeId());
// Verify that we won't change the group if seamless switch is required.
layer.seamlessness = Seamlessness::OnlySeamless;
ASSERT_EQ(HWC_CONFIG_ID_60,
refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
- .getConfigId());
+ .getModeId());
// Verify that we won't do a seamless switch if we request the same mode as the default
- refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90);
+ refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_90);
layer.desiredRefreshRate = Fps(60.0f);
layer.name = "60Hz ExplicitDefault";
layer.seamlessness = Seamlessness::OnlySeamless;
ASSERT_EQ(HWC_CONFIG_ID_90,
refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
- .getConfigId());
+ .getModeId());
// Verify that if the current config is in another group and there are no layers with
// seamlessness=SeamedAndSeamless we'll go back to the default group.
@@ -1228,11 +1229,11 @@
layer.seamlessness = Seamlessness::Default;
ASSERT_EQ(HWC_CONFIG_ID_60,
refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
- .getConfigId());
+ .getModeId());
// If there's a layer with seamlessness=SeamedAndSeamless, another layer with
- // seamlessness=OnlySeamless can't change the config group.
- refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90);
+ // seamlessness=OnlySeamless can't change the mode group.
+ refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_90);
layer.seamlessness = Seamlessness::OnlySeamless;
layers.push_back(LayerRequirement{.weight = 0.5f});
@@ -1245,14 +1246,14 @@
ASSERT_EQ(HWC_CONFIG_ID_90,
refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
- .getConfigId());
+ .getModeId());
// If there's a layer with seamlessness=SeamedAndSeamless, another layer with
- // seamlessness=Default can't change the config group.
+ // seamlessness=Default can't change the mode group.
layers[0].seamlessness = Seamlessness::Default;
ASSERT_EQ(HWC_CONFIG_ID_90,
refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
- .getConfigId());
+ .getModeId());
}
TEST_F(RefreshRateConfigsTest, nonSeamlessVotePrefersSeamlessSwitches) {
@@ -1262,7 +1263,7 @@
// Allow group switching.
RefreshRateConfigs::Policy policy;
- policy.defaultConfig = refreshRateConfigs->getCurrentPolicy().defaultConfig;
+ policy.defaultMode = refreshRateConfigs->getCurrentPolicy().defaultMode;
policy.allowGroupSwitching = true;
ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy(policy), 0);
@@ -1276,12 +1277,12 @@
ASSERT_EQ(HWC_CONFIG_ID_60,
refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
- .getConfigId());
+ .getModeId());
- refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_120);
+ refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_120);
ASSERT_EQ(HWC_CONFIG_ID_120,
refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
- .getConfigId());
+ .getModeId());
}
TEST_F(RefreshRateConfigsTest, nonSeamlessExactAndSeamlessMultipleLayers) {
@@ -1291,7 +1292,7 @@
// Allow group switching.
RefreshRateConfigs::Policy policy;
- policy.defaultConfig = refreshRateConfigs->getCurrentPolicy().defaultConfig;
+ policy.defaultMode = refreshRateConfigs->getCurrentPolicy().defaultMode;
policy.allowGroupSwitching = true;
ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy(policy), 0);
@@ -1312,14 +1313,14 @@
ASSERT_EQ(HWC_CONFIG_ID_50,
refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
- .getConfigId());
+ .getModeId());
seamedLayer.name = "30Hz ExplicitDefault", seamedLayer.desiredRefreshRate = Fps(30.0f);
- refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_30);
+ refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_30);
ASSERT_EQ(HWC_CONFIG_ID_25,
refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false})
- .getConfigId());
+ .getModeId());
}
TEST_F(RefreshRateConfigsTest, primaryVsAppRequestPolicy) {
@@ -1338,7 +1339,7 @@
layers[0].desiredRefreshRate = fps;
layers[0].focused = focused;
return refreshRateConfigs->getBestRefreshRate(layers, {.touch = touchActive, .idle = false})
- .getConfigId();
+ .getModeId();
};
ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy(
@@ -1346,7 +1347,7 @@
0);
EXPECT_EQ(HWC_CONFIG_ID_60,
refreshRateConfigs->getBestRefreshRate({}, {.touch = false, .idle = false})
- .getConfigId());
+ .getModeId());
EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::NoVote, Fps(90.f)));
EXPECT_EQ(HWC_CONFIG_ID_30, getFrameRate(LayerVoteType::Min, Fps(90.f)));
EXPECT_EQ(HWC_CONFIG_ID_60, getFrameRate(LayerVoteType::Max, Fps(90.f)));
@@ -1398,7 +1399,7 @@
refreshRateConfigs
->getBestRefreshRate(layers, {.touch = touchActive, .idle = true},
&consideredSignals)
- .getConfigId();
+ .getModeId();
// Refresh rate will be chosen by either touch state or idle state
EXPECT_EQ(!touchActive, consideredSignals.idle);
return configId;
@@ -1421,10 +1422,10 @@
// With no layers, idle should still be lower priority than touch boost.
EXPECT_EQ(HWC_CONFIG_ID_90,
refreshRateConfigs->getBestRefreshRate({}, {.touch = true, .idle = true})
- .getConfigId());
+ .getModeId());
// Idle should be higher precedence than other layer frame rate considerations.
- refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90);
+ refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_90);
EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::NoVote, /*touchActive=*/false));
EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::Min, /*touchActive=*/false));
EXPECT_EQ(HWC_CONFIG_ID_60, getIdleFrameRate(LayerVoteType::Max, /*touchActive=*/false));
@@ -1437,7 +1438,7 @@
// Idle should be applied rather than the current config when there are no layers.
EXPECT_EQ(HWC_CONFIG_ID_60,
refreshRateConfigs->getBestRefreshRate({}, {.touch = false, .idle = true})
- .getConfigId());
+ .getModeId());
}
TEST_F(RefreshRateConfigsTest, findClosestKnownFrameRate) {
@@ -1628,19 +1629,19 @@
const auto frameRate = Fps(30.f);
EXPECT_EQ(1, refreshRateConfigs->getRefreshRateDivider(frameRate));
- refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_60);
+ refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_60);
EXPECT_EQ(2, refreshRateConfigs->getRefreshRateDivider(frameRate));
- refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_72);
+ refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_72);
EXPECT_EQ(0, refreshRateConfigs->getRefreshRateDivider(frameRate));
- refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90);
+ refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_90);
EXPECT_EQ(3, refreshRateConfigs->getRefreshRateDivider(frameRate));
- refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_120);
+ refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_120);
EXPECT_EQ(4, refreshRateConfigs->getRefreshRateDivider(frameRate));
- refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90);
+ refreshRateConfigs->setCurrentModeId(HWC_CONFIG_ID_90);
EXPECT_EQ(4, refreshRateConfigs->getRefreshRateDivider(Fps(22.5f)));
EXPECT_EQ(4, refreshRateConfigs->getRefreshRateDivider(Fps(22.6f)));
}
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
index c5deb7c..abecd4b 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
@@ -144,7 +144,7 @@
EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
EXPECT_CALL(*vsyncTracker, currentPeriod())
- .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
+ .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker),
std::move(eventThread), std::move(sfEventThread));
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
index ceccd81..bf07106 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
@@ -53,7 +53,7 @@
mRefreshRateConfigs =
std::make_unique<RefreshRateConfigs>(configs, /*currentConfig=*/CONFIG_ID_0);
- const auto currFps = mRefreshRateConfigs->getRefreshRateFromConfigId(CONFIG_ID_0).getFps();
+ const auto currFps = mRefreshRateConfigs->getRefreshRateFromModeId(CONFIG_ID_0).getFps();
mRefreshRateStats = std::make_unique<RefreshRateStats>(mTimeStats, currFps,
/*currentPowerMode=*/PowerMode::OFF);
}
@@ -62,7 +62,7 @@
std::unique_ptr<RefreshRateConfigs> mRefreshRateConfigs;
std::unique_ptr<RefreshRateStats> mRefreshRateStats;
- DisplayModePtr createConfig(DisplayModeId configId, int32_t configGroup, int64_t vsyncPeriod);
+ DisplayModePtr createDisplayMode(DisplayModeId modeId, int32_t group, int64_t vsyncPeriod);
};
RefreshRateStatsTest::RefreshRateStatsTest() {
@@ -77,12 +77,12 @@
ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
}
-DisplayModePtr RefreshRateStatsTest::createConfig(DisplayModeId configId, int32_t configGroup,
- int64_t vsyncPeriod) {
- return DisplayMode::Builder(static_cast<hal::HWConfigId>(configId.value()))
- .setId(configId)
+DisplayModePtr RefreshRateStatsTest::createDisplayMode(DisplayModeId modeId, int32_t group,
+ int64_t vsyncPeriod) {
+ return DisplayMode::Builder(static_cast<hal::HWConfigId>(modeId.value()))
+ .setId(modeId)
.setVsyncPeriod(static_cast<int32_t>(vsyncPeriod))
- .setConfigGroup(configGroup)
+ .setGroup(group)
.build();
}
@@ -91,7 +91,7 @@
* Test cases
*/
TEST_F(RefreshRateStatsTest, oneConfigTest) {
- init({createConfig(CONFIG_ID_0, CONFIG_GROUP_0, VSYNC_90)});
+ init({createDisplayMode(CONFIG_ID_0, CONFIG_GROUP_0, VSYNC_90)});
EXPECT_CALL(mTimeStats, recordRefreshRate(0, _)).Times(AtLeast(1));
EXPECT_CALL(mTimeStats, recordRefreshRate(90, _)).Times(AtLeast(1));
@@ -110,7 +110,7 @@
EXPECT_LT(screenOff, times["ScreenOff"]);
EXPECT_EQ(0u, times.count("90.00fps"));
- const auto config0Fps = mRefreshRateConfigs->getRefreshRateFromConfigId(CONFIG_ID_0).getFps();
+ const auto config0Fps = mRefreshRateConfigs->getRefreshRateFromModeId(CONFIG_ID_0).getFps();
mRefreshRateStats->setRefreshRate(config0Fps);
mRefreshRateStats->setPowerMode(PowerMode::ON);
screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"];
@@ -138,8 +138,8 @@
}
TEST_F(RefreshRateStatsTest, twoConfigsTest) {
- init({createConfig(CONFIG_ID_0, CONFIG_GROUP_0, VSYNC_90),
- createConfig(CONFIG_ID_1, CONFIG_GROUP_0, VSYNC_60)});
+ init({createDisplayMode(CONFIG_ID_0, CONFIG_GROUP_0, VSYNC_90),
+ createDisplayMode(CONFIG_ID_1, CONFIG_GROUP_0, VSYNC_60)});
EXPECT_CALL(mTimeStats, recordRefreshRate(0, _)).Times(AtLeast(1));
EXPECT_CALL(mTimeStats, recordRefreshRate(60, _)).Times(AtLeast(1));
@@ -158,8 +158,8 @@
times = mRefreshRateStats->getTotalTimes();
EXPECT_LT(screenOff, times["ScreenOff"]);
- const auto config0Fps = mRefreshRateConfigs->getRefreshRateFromConfigId(CONFIG_ID_0).getFps();
- const auto config1Fps = mRefreshRateConfigs->getRefreshRateFromConfigId(CONFIG_ID_1).getFps();
+ const auto config0Fps = mRefreshRateConfigs->getRefreshRateFromModeId(CONFIG_ID_0).getFps();
+ const auto config1Fps = mRefreshRateConfigs->getRefreshRateFromModeId(CONFIG_ID_1).getFps();
mRefreshRateStats->setRefreshRate(config0Fps);
mRefreshRateStats->setPowerMode(PowerMode::ON);
screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"];
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index e688e10..694790f 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -52,7 +52,7 @@
SchedulerTest();
const scheduler::RefreshRateConfigs
- mConfigs{{DisplayMode::Builder(0).setVsyncPeriod(16'666'667).setConfigGroup(0).build()},
+ mConfigs{{DisplayMode::Builder(0).setVsyncPeriod(16'666'667).setGroup(0).build()},
DisplayModeId(0)};
mock::SchedulerCallback mSchedulerCallback;
@@ -166,25 +166,25 @@
mScheduler.chooseRefreshRateForContent();
}
-TEST_F(SchedulerTest, testDispatchCachedReportedConfig) {
+TEST_F(SchedulerTest, testDispatchCachedReportedMode) {
// If the optional fields are cleared, the function should return before
- // onConfigChange is called.
+ // onModeChange is called.
mScheduler.clearOptionalFieldsInFeatures();
- EXPECT_NO_FATAL_FAILURE(mScheduler.dispatchCachedReportedConfig());
- EXPECT_CALL(*mEventThread, onConfigChanged(_, _, _)).Times(0);
+ EXPECT_NO_FATAL_FAILURE(mScheduler.dispatchCachedReportedMode());
+ EXPECT_CALL(*mEventThread, onModeChanged(_, _, _)).Times(0);
}
-TEST_F(SchedulerTest, onNonPrimaryDisplayConfigChanged_invalidParameters) {
- DisplayModeId configId = DisplayModeId(111);
+TEST_F(SchedulerTest, onNonPrimaryDisplayModeChanged_invalidParameters) {
+ DisplayModeId modeId = DisplayModeId(111);
nsecs_t vsyncPeriod = 111111;
// If the handle is incorrect, the function should return before
- // onConfigChange is called.
+ // onModeChange is called.
Scheduler::ConnectionHandle invalidHandle = {.id = 123};
- EXPECT_NO_FATAL_FAILURE(mScheduler.onNonPrimaryDisplayConfigChanged(invalidHandle,
- PHYSICAL_DISPLAY_ID,
- configId, vsyncPeriod));
- EXPECT_CALL(*mEventThread, onConfigChanged(_, _, _)).Times(0);
+ EXPECT_NO_FATAL_FAILURE(mScheduler.onNonPrimaryDisplayModeChanged(invalidHandle,
+ PHYSICAL_DISPLAY_ID, modeId,
+ vsyncPeriod));
+ EXPECT_CALL(*mEventThread, onModeChanged(_, _, _)).Times(0);
}
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
index e060df2..a6d07d0 100644
--- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
@@ -185,7 +185,7 @@
EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
EXPECT_CALL(*vsyncTracker, currentPeriod())
- .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
+ .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker),
std::move(eventThread), std::move(sfEventThread));
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HandleTransactionLockedTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HandleTransactionLockedTest.cpp
index 8552e15..b713334 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HandleTransactionLockedTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HandleTransactionLockedTest.cpp
@@ -669,7 +669,7 @@
// --------------------------------------------------------------------
// Call Expectations
- EXPECT_CALL(*displaySurface, resizeBuffers(newWidth, oldHeight)).Times(1);
+ EXPECT_CALL(*displaySurface, resizeBuffers(ui::Size(newWidth, oldHeight))).Times(1);
// --------------------------------------------------------------------
// Invocation
@@ -714,7 +714,7 @@
// --------------------------------------------------------------------
// Call Expectations
- EXPECT_CALL(*displaySurface, resizeBuffers(oldWidth, newHeight)).Times(1);
+ EXPECT_CALL(*displaySurface, resizeBuffers(ui::Size(oldWidth, newHeight))).Times(1);
// --------------------------------------------------------------------
// Invocation
@@ -764,7 +764,7 @@
// --------------------------------------------------------------------
// Call Expectations
- EXPECT_CALL(*displaySurface, resizeBuffers(kNewWidth, kNewHeight)).Times(1);
+ EXPECT_CALL(*displaySurface, resizeBuffers(kNewSize.getSize())).Times(1);
// --------------------------------------------------------------------
// Invocation
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
index 2b5cb77..e32c4bf 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp
@@ -246,7 +246,7 @@
.setVsyncPeriod(DEFAULT_VSYNC_PERIOD)
.setDpiX(DEFAULT_DPI)
.setDpiY(DEFAULT_DPI)
- .setConfigGroup(0)
+ .setGroup(0)
.build();
DisplayModes modes{activeMode};
state.physical = {.id = *displayId,
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index d3e90e3..3f9dd01 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -80,20 +80,19 @@
return mFeatures.touch == Scheduler::TouchState::Active;
}
- void dispatchCachedReportedConfig() {
+ void dispatchCachedReportedMode() {
std::lock_guard<std::mutex> lock(mFeatureStateLock);
- return Scheduler::dispatchCachedReportedConfig();
+ return Scheduler::dispatchCachedReportedMode();
}
void clearOptionalFieldsInFeatures() {
std::lock_guard<std::mutex> lock(mFeatureStateLock);
- mFeatures.cachedConfigChangedParams.reset();
+ mFeatures.cachedModeChangedParams.reset();
}
- void onNonPrimaryDisplayConfigChanged(ConnectionHandle handle, PhysicalDisplayId displayId,
- DisplayModeId configId, nsecs_t vsyncPeriod) {
- return Scheduler::onNonPrimaryDisplayConfigChanged(handle, displayId, configId,
- vsyncPeriod);
+ void onNonPrimaryDisplayModeChanged(ConnectionHandle handle, PhysicalDisplayId displayId,
+ DisplayModeId modeId, nsecs_t vsyncPeriod) {
+ return Scheduler::onNonPrimaryDisplayModeChanged(handle, displayId, modeId, vsyncPeriod);
}
~TestableScheduler() {
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 2701f47..6aa6d31 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -41,6 +41,7 @@
#include "SurfaceFlingerDefaultFactory.h"
#include "SurfaceInterceptor.h"
#include "TestableScheduler.h"
+#include "mock/DisplayHardware/MockComposer.h"
#include "mock/MockDisplayIdGenerator.h"
#include "mock/MockFrameTimeline.h"
#include "mock/MockFrameTracer.h"
@@ -209,26 +210,26 @@
std::unique_ptr<scheduler::VSyncTracker> vsyncTracker,
std::unique_ptr<EventThread> appEventThread,
std::unique_ptr<EventThread> sfEventThread,
- ISchedulerCallback* callback = nullptr, bool hasMultipleConfigs = false) {
- DisplayModes configs{DisplayMode::Builder(0)
- .setId(DisplayModeId(0))
- .setVsyncPeriod(16'666'667)
- .setConfigGroup(0)
- .build()};
+ ISchedulerCallback* callback = nullptr, bool hasMultipleModes = false) {
+ DisplayModes modes{DisplayMode::Builder(0)
+ .setId(DisplayModeId(0))
+ .setVsyncPeriod(16'666'667)
+ .setGroup(0)
+ .build()};
- if (hasMultipleConfigs) {
- configs.emplace_back(DisplayMode::Builder(1)
- .setId(DisplayModeId(1))
- .setVsyncPeriod(11'111'111)
- .setConfigGroup(0)
- .build());
+ if (hasMultipleModes) {
+ modes.emplace_back(DisplayMode::Builder(1)
+ .setId(DisplayModeId(1))
+ .setVsyncPeriod(11'111'111)
+ .setGroup(0)
+ .build());
}
- const auto currConfig = DisplayModeId(0);
+ const auto currMode = DisplayModeId(0);
mFlinger->mRefreshRateConfigs =
- std::make_unique<scheduler::RefreshRateConfigs>(configs, currConfig);
+ std::make_unique<scheduler::RefreshRateConfigs>(modes, currMode);
const auto currFps =
- mFlinger->mRefreshRateConfigs->getRefreshRateFromConfigId(currConfig).getFps();
+ mFlinger->mRefreshRateConfigs->getRefreshRateFromModeId(currMode).getFps();
mFlinger->mRefreshRateStats =
std::make_unique<scheduler::RefreshRateStats>(*mFlinger->mTimeStats, currFps,
/*powerMode=*/hal::PowerMode::OFF);
@@ -353,7 +354,8 @@
bool regionSampling) {
ScreenCaptureResults captureResults;
return mFlinger->renderScreenImplLocked(renderArea, traverseLayers, buffer, forSystem,
- regionSampling, captureResults);
+ regionSampling, false /* grayscale */,
+ captureResults);
}
auto traverseLayersInLayerStack(ui::LayerStack layerStack, int32_t uid,
@@ -366,18 +368,17 @@
return mFlinger->SurfaceFlinger::getDisplayNativePrimaries(displayToken, primaries);
}
- auto& getTransactionQueue() { return mFlinger->mTransactionQueues; }
+ auto& getTransactionQueue() { return mFlinger->mTransactionQueue; }
+ auto& getPendingTransactionQueue() { return mFlinger->mPendingTransactionQueues; }
- auto setTransactionState(int64_t frameTimelineVsyncId, const Vector<ComposerState>& states,
- const Vector<DisplayState>& displays, uint32_t flags,
- const sp<IBinder>& applyToken,
- const InputWindowCommands& inputWindowCommands,
- int64_t desiredPresentTime, bool isAutoTimestamp,
- const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
- std::vector<ListenerCallbacks>& listenerCallbacks,
- uint64_t transactionId) {
- return mFlinger->setTransactionState(frameTimelineVsyncId, states, displays, flags,
- applyToken, inputWindowCommands, desiredPresentTime,
+ auto setTransactionState(
+ const FrameTimelineInfo& frameTimelineInfo, const Vector<ComposerState>& states,
+ const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
+ const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
+ bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
+ std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) {
+ return mFlinger->setTransactionState(frameTimelineInfo, states, displays, flags, applyToken,
+ inputWindowCommands, desiredPresentTime,
isAutoTimestamp, uncacheBuffer, hasListenerCallbacks,
listenerCallbacks, transactionId);
}
@@ -478,7 +479,7 @@
static constexpr hal::HWDisplayId DEFAULT_HWC_DISPLAY_ID = 1000;
static constexpr int32_t DEFAULT_WIDTH = 1920;
static constexpr int32_t DEFAULT_HEIGHT = 1280;
- static constexpr int32_t DEFAULT_REFRESH_RATE = 16'666'666;
+ static constexpr int32_t DEFAULT_VSYNC_PERIOD = 16'666'666;
static constexpr int32_t DEFAULT_CONFIG_GROUP = 7;
static constexpr int32_t DEFAULT_DPI = 320;
static constexpr hal::HWConfigId DEFAULT_ACTIVE_CONFIG = 0;
@@ -503,8 +504,8 @@
return *this;
}
- auto& setRefreshRate(int32_t refreshRate) {
- mRefreshRate = refreshRate;
+ auto& setVsyncPeriod(int32_t vsyncPeriod) {
+ mVsyncPeriod = vsyncPeriod;
return *this;
}
@@ -533,7 +534,12 @@
return *this;
}
- void inject(TestableSurfaceFlinger* flinger, Hwc2::Composer* composer) {
+ void inject(TestableSurfaceFlinger* flinger, Hwc2::mock::Composer* composer) {
+ using ::testing::_;
+ using ::testing::DoAll;
+ using ::testing::Return;
+ using ::testing::SetArgPointee;
+
static const std::unordered_set<hal::Capability> defaultCapabilities;
if (mCapabilities == nullptr) mCapabilities = &defaultCapabilities;
@@ -548,15 +554,39 @@
display->setPowerMode(mPowerMode);
flinger->mutableHwcDisplayData()[mDisplayId].hwcDisplay = std::move(display);
- auto config = DisplayMode::Builder(mActiveConfig)
- .setWidth(mWidth)
- .setHeight(mHeight)
- .setVsyncPeriod(mRefreshRate)
- .setDpiX(mDpiX)
- .setDpiY(mDpiY)
- .setConfigGroup(mConfigGroup)
- .build();
- flinger->mutableHwcDisplayData()[mDisplayId].modes.push_back(config);
+ EXPECT_CALL(*composer, getDisplayConfigs(mHwcDisplayId, _))
+ .WillRepeatedly(
+ DoAll(SetArgPointee<1>(std::vector<hal::HWConfigId>{mActiveConfig}),
+ Return(hal::Error::NONE)));
+
+ EXPECT_CALL(*composer,
+ getDisplayAttribute(mHwcDisplayId, mActiveConfig, hal::Attribute::WIDTH, _))
+ .WillRepeatedly(DoAll(SetArgPointee<3>(mWidth), Return(hal::Error::NONE)));
+
+ EXPECT_CALL(*composer,
+ getDisplayAttribute(mHwcDisplayId, mActiveConfig, hal::Attribute::HEIGHT,
+ _))
+ .WillRepeatedly(DoAll(SetArgPointee<3>(mHeight), Return(hal::Error::NONE)));
+
+ EXPECT_CALL(*composer,
+ getDisplayAttribute(mHwcDisplayId, mActiveConfig,
+ hal::Attribute::VSYNC_PERIOD, _))
+ .WillRepeatedly(
+ DoAll(SetArgPointee<3>(mVsyncPeriod), Return(hal::Error::NONE)));
+
+ EXPECT_CALL(*composer,
+ getDisplayAttribute(mHwcDisplayId, mActiveConfig, hal::Attribute::DPI_X, _))
+ .WillRepeatedly(DoAll(SetArgPointee<3>(mDpiX), Return(hal::Error::NONE)));
+
+ EXPECT_CALL(*composer,
+ getDisplayAttribute(mHwcDisplayId, mActiveConfig, hal::Attribute::DPI_Y, _))
+ .WillRepeatedly(DoAll(SetArgPointee<3>(mDpiY), Return(hal::Error::NONE)));
+
+ EXPECT_CALL(*composer,
+ getDisplayAttribute(mHwcDisplayId, mActiveConfig,
+ hal::Attribute::CONFIG_GROUP, _))
+ .WillRepeatedly(
+ DoAll(SetArgPointee<3>(mConfigGroup), Return(hal::Error::NONE)));
if (mHwcDisplayType == hal::DisplayType::PHYSICAL) {
const auto physicalId = PhysicalDisplayId::tryCast(mDisplayId);
@@ -582,10 +612,10 @@
hal::HWDisplayId mHwcDisplayId = DEFAULT_HWC_DISPLAY_ID;
int32_t mWidth = DEFAULT_WIDTH;
int32_t mHeight = DEFAULT_HEIGHT;
- int32_t mRefreshRate = DEFAULT_REFRESH_RATE;
+ int32_t mVsyncPeriod = DEFAULT_VSYNC_PERIOD;
int32_t mDpiX = DEFAULT_DPI;
- int32_t mConfigGroup = DEFAULT_CONFIG_GROUP;
int32_t mDpiY = DEFAULT_DPI;
+ int32_t mConfigGroup = DEFAULT_CONFIG_GROUP;
hal::HWConfigId mActiveConfig = DEFAULT_ACTIVE_CONFIG;
hal::PowerMode mPowerMode = DEFAULT_POWER_MODE;
const std::unordered_set<hal::Capability>* mCapabilities = nullptr;
@@ -603,6 +633,21 @@
mHwcDisplayId(hwcDisplayId) {
mCreationArgs.connectionType = connectionType;
mCreationArgs.isPrimary = isPrimary;
+
+ mActiveModeId = DisplayModeId(0);
+ DisplayModePtr activeMode =
+ DisplayMode::Builder(FakeHwcDisplayInjector::DEFAULT_ACTIVE_CONFIG)
+ .setId(mActiveModeId)
+ .setWidth(FakeHwcDisplayInjector::DEFAULT_WIDTH)
+ .setHeight(FakeHwcDisplayInjector::DEFAULT_HEIGHT)
+ .setVsyncPeriod(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD)
+ .setDpiX(FakeHwcDisplayInjector::DEFAULT_DPI)
+ .setDpiY(FakeHwcDisplayInjector::DEFAULT_DPI)
+ .setGroup(0)
+ .build();
+
+ DisplayModes modes{activeMode};
+ mCreationArgs.supportedModes = modes;
}
sp<IBinder> token() const { return mDisplayToken; }
@@ -625,6 +670,16 @@
auto& mutableDisplayDevice() { return mFlinger.mutableDisplays()[mDisplayToken]; }
+ auto& setActiveMode(DisplayModeId mode) {
+ mActiveModeId = mode;
+ return *this;
+ }
+
+ auto& setSupportedModes(DisplayModes mode) {
+ mCreationArgs.supportedModes = mode;
+ return *this;
+ }
+
auto& setNativeWindow(const sp<ANativeWindow>& nativeWindow) {
mCreationArgs.nativeWindow = nativeWindow;
return *this;
@@ -677,6 +732,9 @@
state.isSecure = mCreationArgs.isSecure;
sp<DisplayDevice> device = new DisplayDevice(mCreationArgs);
+ if (!device->isVirtual()) {
+ device->setActiveMode(mActiveModeId);
+ }
mFlinger.mutableDisplays().emplace(mDisplayToken, device);
mFlinger.mutableCurrentState().displays.add(mDisplayToken, state);
mFlinger.mutableDrawingState().displays.add(mDisplayToken, state);
@@ -693,11 +751,12 @@
sp<BBinder> mDisplayToken = new BBinder();
DisplayDeviceCreationArgs mCreationArgs;
const std::optional<hal::HWDisplayId> mHwcDisplayId;
+ DisplayModeId mActiveModeId;
};
private:
void setVsyncEnabled(bool) override {}
- void changeRefreshRate(const Scheduler::RefreshRate&, Scheduler::ConfigEvent) override {}
+ void changeRefreshRate(const Scheduler::RefreshRate&, Scheduler::ModeEvent) override {}
void repaintEverythingForHWC() override {}
void kernelTimerChanged(bool) override {}
void triggerOnFrameRateOverridesChanged() {}
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index 06275c6..eb2c1ba 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -14,10 +14,6 @@
* limitations under the License.
*/
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-#pragma clang diagnostic ignored "-Wextra"
#undef LOG_TAG
#define LOG_TAG "CompositionTest"
@@ -76,7 +72,7 @@
EXPECT_CALL(*mVSyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
EXPECT_CALL(*mVSyncTracker, currentPeriod())
- .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
+ .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
mFlinger.setupScheduler(std::unique_ptr<mock::VsyncController>(mVsyncController),
std::unique_ptr<mock::VSyncTracker>(mVSyncTracker),
@@ -100,50 +96,50 @@
InputWindowCommands inputWindowCommands;
int64_t desiredPresentTime = 0;
bool isAutoTimestamp = true;
- int64_t frameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID;
+ FrameTimelineInfo frameTimelineInfo;
client_cache_t uncacheBuffer;
- int64_t id = -1;
+ uint64_t id = static_cast<uint64_t>(-1);
+ static_assert(0xffffffffffffffff == static_cast<uint64_t>(-1));
};
void checkEqual(TransactionInfo info, SurfaceFlinger::TransactionState state) {
- EXPECT_EQ(0, info.states.size());
- EXPECT_EQ(0, state.states.size());
+ EXPECT_EQ(0u, info.states.size());
+ EXPECT_EQ(0u, state.states.size());
- EXPECT_EQ(0, info.displays.size());
- EXPECT_EQ(0, state.displays.size());
+ EXPECT_EQ(0u, info.displays.size());
+ EXPECT_EQ(0u, state.displays.size());
EXPECT_EQ(info.flags, state.flags);
EXPECT_EQ(info.desiredPresentTime, state.desiredPresentTime);
}
void setupSingle(TransactionInfo& transaction, uint32_t flags, bool syncInputWindows,
int64_t desiredPresentTime, bool isAutoTimestamp,
- int64_t frameTimelineVsyncId) {
+ const FrameTimelineInfo& frameTimelineInfo) {
mTransactionNumber++;
transaction.flags |= flags; // ISurfaceComposer::eSynchronous;
transaction.inputWindowCommands.syncInputWindows = syncInputWindows;
transaction.desiredPresentTime = desiredPresentTime;
transaction.isAutoTimestamp = isAutoTimestamp;
- transaction.frameTimelineVsyncId = frameTimelineVsyncId;
+ transaction.frameTimelineInfo = frameTimelineInfo;
}
void NotPlacedOnTransactionQueue(uint32_t flags, bool syncInputWindows) {
- ASSERT_EQ(0, mFlinger.getTransactionQueue().size());
+ ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
// called in SurfaceFlinger::signalTransaction
EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
EXPECT_CALL(*mVSyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillOnce(Return(systemTime()));
TransactionInfo transaction;
setupSingle(transaction, flags, syncInputWindows,
/*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true,
- ISurfaceComposer::INVALID_VSYNC_ID);
+ FrameTimelineInfo{});
nsecs_t applicationTime = systemTime();
- mFlinger.setTransactionState(transaction.frameTimelineVsyncId, transaction.states,
+ mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states,
transaction.displays, transaction.flags,
transaction.applyToken, transaction.inputWindowCommands,
transaction.desiredPresentTime, transaction.isAutoTimestamp,
transaction.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
transaction.id);
- // This transaction should not have been placed on the transaction queue.
// 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
@@ -154,12 +150,13 @@
} else {
EXPECT_LE(returnedTime, applicationTime + s2ns(5));
}
+ // Each transaction should have been placed on the transaction queue
auto transactionQueue = mFlinger.getTransactionQueue();
- EXPECT_EQ(0, transactionQueue.size());
+ EXPECT_EQ(1u, transactionQueue.size());
}
void PlaceOnTransactionQueue(uint32_t flags, bool syncInputWindows) {
- ASSERT_EQ(0, mFlinger.getTransactionQueue().size());
+ ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
// called in SurfaceFlinger::signalTransaction
EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
@@ -170,10 +167,9 @@
.WillOnce(Return(time + nsecs_t(5 * 1e8)));
TransactionInfo transaction;
setupSingle(transaction, flags, syncInputWindows,
- /*desiredPresentTime*/ time + s2ns(1), false,
- ISurfaceComposer::INVALID_VSYNC_ID);
+ /*desiredPresentTime*/ time + s2ns(1), false, FrameTimelineInfo{});
nsecs_t applicationSentTime = systemTime();
- mFlinger.setTransactionState(transaction.frameTimelineVsyncId, transaction.states,
+ mFlinger.setTransactionState(transaction.frameTimelineInfo, transaction.states,
transaction.displays, transaction.flags,
transaction.applyToken, transaction.inputWindowCommands,
transaction.desiredPresentTime, transaction.isAutoTimestamp,
@@ -184,11 +180,11 @@
EXPECT_LE(returnedTime, applicationSentTime + s2ns(5));
// This transaction should have been placed on the transaction queue
auto transactionQueue = mFlinger.getTransactionQueue();
- EXPECT_EQ(1, transactionQueue.size());
+ EXPECT_EQ(1u, transactionQueue.size());
}
void BlockedByPriorTransaction(uint32_t flags, bool syncInputWindows) {
- ASSERT_EQ(0, mFlinger.getTransactionQueue().size());
+ ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
// called in SurfaceFlinger::signalTransaction
nsecs_t time = systemTime();
EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
@@ -197,18 +193,17 @@
// transaction that should go on the pending thread
TransactionInfo transactionA;
setupSingle(transactionA, /*flags*/ 0, /*syncInputWindows*/ false,
- /*desiredPresentTime*/ time + s2ns(1), false,
- ISurfaceComposer::INVALID_VSYNC_ID);
+ /*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,
- ISurfaceComposer::INVALID_VSYNC_ID);
+ FrameTimelineInfo{});
nsecs_t applicationSentTime = systemTime();
- mFlinger.setTransactionState(transactionA.frameTimelineVsyncId, transactionA.states,
+ mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states,
transactionA.displays, transactionA.flags,
transactionA.applyToken, transactionA.inputWindowCommands,
transactionA.desiredPresentTime, transactionA.isAutoTimestamp,
@@ -219,9 +214,11 @@
// (5s is the timeout period that applyTransactionState waits for SF to
// commit the transaction)
EXPECT_LE(systemTime(), applicationSentTime + s2ns(5));
+ // transaction that would goes to pending transaciton queue.
+ mFlinger.flushTransactionQueues();
applicationSentTime = systemTime();
- mFlinger.setTransactionState(transactionB.frameTimelineVsyncId, transactionB.states,
+ mFlinger.setTransactionState(transactionB.frameTimelineInfo, transactionB.states,
transactionB.displays, transactionB.flags,
transactionB.applyToken, transactionB.inputWindowCommands,
transactionB.desiredPresentTime, transactionB.isAutoTimestamp,
@@ -238,12 +235,15 @@
EXPECT_LE(systemTime(), applicationSentTime + s2ns(5));
}
+ // transaction that would goes to pending transaciton queue.
+ mFlinger.flushTransactionQueues();
+
// check that there is one binder on the pending queue.
- auto transactionQueue = mFlinger.getTransactionQueue();
- EXPECT_EQ(1, transactionQueue.size());
+ auto transactionQueue = mFlinger.getPendingTransactionQueue();
+ EXPECT_EQ(1u, transactionQueue.size());
auto& [applyToken, transactionStates] = *(transactionQueue.begin());
- EXPECT_EQ(2, transactionStates.size());
+ EXPECT_EQ(2u, transactionStates.size());
auto& transactionStateA = transactionStates.front();
transactionStates.pop();
@@ -258,7 +258,7 @@
};
TEST_F(TransactionApplicationTest, Flush_RemovesFromQueue) {
- ASSERT_EQ(0, mFlinger.getTransactionQueue().size());
+ ASSERT_EQ(0u, mFlinger.getTransactionQueue().size());
// called in SurfaceFlinger::signalTransaction
EXPECT_CALL(*mMessageQueue, invalidate()).Times(1);
@@ -268,20 +268,17 @@
.WillOnce(Return(s2ns(2)));
TransactionInfo transactionA; // transaction to go on pending queue
setupSingle(transactionA, /*flags*/ 0, /*syncInputWindows*/ false,
- /*desiredPresentTime*/ s2ns(1), false, ISurfaceComposer::INVALID_VSYNC_ID);
- mFlinger.setTransactionState(transactionA.frameTimelineVsyncId, transactionA.states,
+ /*desiredPresentTime*/ s2ns(1), false, FrameTimelineInfo{});
+ mFlinger.setTransactionState(transactionA.frameTimelineInfo, transactionA.states,
transactionA.displays, transactionA.flags, transactionA.applyToken,
transactionA.inputWindowCommands, transactionA.desiredPresentTime,
transactionA.isAutoTimestamp, transactionA.uncacheBuffer,
mHasListenerCallbacks, mCallbacks, transactionA.id);
auto& transactionQueue = mFlinger.getTransactionQueue();
- ASSERT_EQ(1, transactionQueue.size());
+ ASSERT_EQ(1u, transactionQueue.size());
- auto& [applyToken, transactionStates] = *(transactionQueue.begin());
- ASSERT_EQ(1, transactionStates.size());
-
- auto& transactionState = transactionStates.front();
+ auto& transactionState = transactionQueue.front();
checkEqual(transactionA, transactionState);
// because flushing uses the cached expected present time, we send an empty
@@ -289,8 +286,8 @@
// different process) to re-query and reset the cached expected present time
TransactionInfo empty;
empty.applyToken = sp<IBinder>();
- mFlinger.setTransactionState(empty.frameTimelineVsyncId, empty.states, empty.displays,
- empty.flags, empty.applyToken, empty.inputWindowCommands,
+ mFlinger.setTransactionState(empty.frameTimelineInfo, empty.states, empty.displays, empty.flags,
+ empty.applyToken, empty.inputWindowCommands,
empty.desiredPresentTime, empty.isAutoTimestamp,
empty.uncacheBuffer, mHasListenerCallbacks, mCallbacks, empty.id);
@@ -298,7 +295,7 @@
// passed
mFlinger.flushTransactionQueues();
- EXPECT_EQ(0, transactionQueue.size());
+ EXPECT_EQ(0u, transactionQueue.size());
}
TEST_F(TransactionApplicationTest, NotPlacedOnTransactionQueue_Synchronous) {
@@ -343,6 +340,3 @@
EXPECT_EQ(nullptr, ret.promote().get());
}
} // namespace android
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
new file mode 100644
index 0000000..aa6798d
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
@@ -0,0 +1,367 @@
+/*
+ * 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.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "LibSurfaceFlingerUnittests"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <gui/SurfaceComposerClient.h>
+#include <log/log.h>
+#include <utils/String8.h>
+
+#include "TestableSurfaceFlinger.h"
+#include "mock/DisplayHardware/MockComposer.h"
+#include "mock/MockEventThread.h"
+#include "mock/MockVsyncController.h"
+
+namespace android {
+
+using testing::_;
+using testing::Mock;
+using testing::Return;
+using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector;
+using PresentState = frametimeline::SurfaceFrame::PresentState;
+
+class TransactionSurfaceFrameTest : public testing::Test {
+public:
+ TransactionSurfaceFrameTest() {
+ const ::testing::TestInfo* const test_info =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+ ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
+ setupScheduler();
+ setupComposer(0);
+ }
+
+ ~TransactionSurfaceFrameTest() {
+ const ::testing::TestInfo* const test_info =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+ ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
+ }
+
+ sp<BufferStateLayer> createBufferStateLayer() {
+ sp<Client> client;
+ LayerCreationArgs args(mFlinger.flinger(), client, "buffer-state-layer", 100, 100, 0,
+ LayerMetadata());
+ return new BufferStateLayer(args);
+ }
+
+ void commitTransaction(Layer* layer) {
+ layer->pushPendingState();
+ // After pushing the state, the currentState should not store any BufferlessSurfaceFrames
+ EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
+ auto c = layer->getCurrentState();
+ if (layer->applyPendingStates(&c)) {
+ layer->commitTransaction(c);
+ }
+ }
+
+ void setupScheduler() {
+ auto eventThread = std::make_unique<mock::EventThread>();
+ auto sfEventThread = std::make_unique<mock::EventThread>();
+
+ EXPECT_CALL(*eventThread, registerDisplayEventConnection(_));
+ EXPECT_CALL(*eventThread, createEventConnection(_, _))
+ .WillOnce(Return(new EventThreadConnection(eventThread.get(), /*callingUid=*/0,
+ ResyncCallback())));
+
+ EXPECT_CALL(*sfEventThread, registerDisplayEventConnection(_));
+ EXPECT_CALL(*sfEventThread, createEventConnection(_, _))
+ .WillOnce(Return(new EventThreadConnection(sfEventThread.get(), /*callingUid=*/0,
+ ResyncCallback())));
+
+ auto vsyncController = std::make_unique<mock::VsyncController>();
+ auto vsyncTracker = std::make_unique<mock::VSyncTracker>();
+
+ EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
+ EXPECT_CALL(*vsyncTracker, currentPeriod())
+ .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
+ EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
+ mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker),
+ std::move(eventThread), std::move(sfEventThread));
+ }
+
+ void setupComposer(uint32_t virtualDisplayCount) {
+ mComposer = new Hwc2::mock::Composer();
+ EXPECT_CALL(*mComposer, getMaxVirtualDisplayCount()).WillOnce(Return(virtualDisplayCount));
+ mFlinger.setupComposer(std::unique_ptr<Hwc2::Composer>(mComposer));
+
+ Mock::VerifyAndClear(mComposer);
+ }
+
+ TestableSurfaceFlinger mFlinger;
+ Hwc2::mock::Composer* mComposer = nullptr;
+ FenceToFenceTimeMap fenceFactory;
+ client_cache_t mClientCache;
+
+ void PresentedSurfaceFrameForBufferlessTransaction() {
+ sp<BufferStateLayer> layer = createBufferStateLayer();
+ layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0},
+ 10);
+ EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
+ ASSERT_TRUE(layer->mCurrentState.bufferSurfaceFrameTX == nullptr);
+ const auto surfaceFrame = layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 1);
+ commitTransaction(layer.get());
+ EXPECT_EQ(1, surfaceFrame->getToken());
+ EXPECT_EQ(PresentState::Presented, surfaceFrame->getPresentState());
+ }
+
+ void PresentedSurfaceFrameForBufferTransaction() {
+ sp<BufferStateLayer> layer = createBufferStateLayer();
+ sp<Fence> fence(new Fence());
+ auto acquireFence = fenceFactory.createFenceTimeForTest(fence);
+ sp<GraphicBuffer> buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)};
+ layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt,
+ {/*vsyncId*/ 1, /*inputEventId*/ 0});
+ acquireFence->signalForTest(12);
+
+ commitTransaction(layer.get());
+ EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
+ ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
+ const auto& surfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX;
+ // Buffers are presented only at latch time.
+ EXPECT_EQ(PresentState::Unknown, surfaceFrame->getPresentState());
+
+ bool computeVisisbleRegions;
+ layer->updateTexImage(computeVisisbleRegions, 15, 0);
+
+ EXPECT_EQ(1, surfaceFrame->getToken());
+ EXPECT_EQ(PresentState::Presented, surfaceFrame->getPresentState());
+ }
+
+ void DroppedSurfaceFrameForBufferTransaction() {
+ sp<BufferStateLayer> layer = createBufferStateLayer();
+
+ sp<Fence> fence1(new Fence());
+ auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1);
+ sp<GraphicBuffer> buffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)};
+ layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt,
+ {/*vsyncId*/ 1, /*inputEventId*/ 0});
+ EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
+ ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
+ const auto droppedSurfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX;
+
+ sp<Fence> fence2(new Fence());
+ auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2);
+ sp<GraphicBuffer> buffer2{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)};
+ layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt,
+ {/*vsyncId*/ 1, /*inputEventId*/ 0});
+ acquireFence2->signalForTest(12);
+
+ EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
+ ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
+ const auto& presentedSurfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX;
+
+ commitTransaction(layer.get());
+ bool computeVisisbleRegions;
+ layer->updateTexImage(computeVisisbleRegions, 15, 0);
+
+ EXPECT_EQ(1, droppedSurfaceFrame->getToken());
+ EXPECT_EQ(PresentState::Dropped, droppedSurfaceFrame->getPresentState());
+
+ EXPECT_EQ(1, presentedSurfaceFrame->getToken());
+ EXPECT_EQ(PresentState::Presented, presentedSurfaceFrame->getPresentState());
+ }
+
+ void BufferlessSurfaceFramePromotedToBufferSurfaceFrame() {
+ sp<BufferStateLayer> layer = createBufferStateLayer();
+
+ layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0},
+ 10);
+
+ EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
+ ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
+
+ sp<Fence> fence(new Fence());
+ auto acquireFence = fenceFactory.createFenceTimeForTest(fence);
+ sp<GraphicBuffer> buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)};
+
+ layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt,
+ {/*vsyncId*/ 1, /*inputEventId*/ 0});
+ acquireFence->signalForTest(12);
+
+ EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
+ ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
+ const auto& surfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX;
+
+ commitTransaction(layer.get());
+ EXPECT_EQ(1, surfaceFrame->getToken());
+ // Buffers are presented only at latch time.
+ EXPECT_EQ(PresentState::Unknown, surfaceFrame->getPresentState());
+
+ bool computeVisisbleRegions;
+ layer->updateTexImage(computeVisisbleRegions, 15, 0);
+
+ EXPECT_EQ(PresentState::Presented, surfaceFrame->getPresentState());
+ }
+
+ void BufferlessSurfaceFrameNotCreatedIfBufferSufaceFrameExists() {
+ sp<BufferStateLayer> layer = createBufferStateLayer();
+ sp<Fence> fence(new Fence());
+ auto acquireFence = fenceFactory.createFenceTimeForTest(fence);
+ sp<GraphicBuffer> buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)};
+
+ layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt,
+ {/*vsyncId*/ 1, /*inputEventId*/ 0});
+ EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
+ ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
+
+ layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0},
+ 10);
+ EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
+ ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
+ }
+
+ void MultipleSurfaceFramesPresentedTogether() {
+ sp<BufferStateLayer> layer = createBufferStateLayer();
+ layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0},
+ 10);
+ EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
+ ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
+ const auto bufferlessSurfaceFrame1 =
+ layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 1);
+
+ layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 4, /*inputEventId*/ 0},
+ 10);
+ EXPECT_EQ(2u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
+ ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
+ const auto bufferlessSurfaceFrame2 = layer->mCurrentState.bufferlessSurfaceFramesTX[4];
+
+ sp<Fence> fence(new Fence());
+ auto acquireFence = fenceFactory.createFenceTimeForTest(fence);
+ sp<GraphicBuffer> buffer{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)};
+
+ layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt,
+ {/*vsyncId*/ 3, /*inputEventId*/ 0});
+ EXPECT_EQ(2u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
+ ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
+ const auto& bufferSurfaceFrameTX = layer->mCurrentState.bufferSurfaceFrameTX;
+
+ acquireFence->signalForTest(12);
+
+ commitTransaction(layer.get());
+
+ EXPECT_EQ(1, bufferlessSurfaceFrame1->getToken());
+ EXPECT_EQ(PresentState::Presented, bufferlessSurfaceFrame1->getPresentState());
+
+ EXPECT_EQ(4, bufferlessSurfaceFrame2->getToken());
+ EXPECT_EQ(PresentState::Presented, bufferlessSurfaceFrame2->getPresentState());
+
+ EXPECT_EQ(3, bufferSurfaceFrameTX->getToken());
+ // Buffers are presented only at latch time.
+ EXPECT_EQ(PresentState::Unknown, bufferSurfaceFrameTX->getPresentState());
+
+ bool computeVisisbleRegions;
+ layer->updateTexImage(computeVisisbleRegions, 15, 0);
+
+ EXPECT_EQ(PresentState::Presented, bufferSurfaceFrameTX->getPresentState());
+ }
+
+ void MergePendingStates_BufferlessSurfaceFramesWithoutOverlappingToken() {
+ sp<BufferStateLayer> layer = createBufferStateLayer();
+ layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0},
+ 10);
+ EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
+ ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
+ const auto bufferlessSurfaceFrame1 =
+ layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 1);
+
+ layer->pushPendingState();
+ EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
+
+ layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 2, /*inputEventId*/ 0},
+ 12);
+ EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
+ ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
+ const auto bufferlessSurfaceFrame2 =
+ layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 2);
+
+ commitTransaction(layer.get());
+
+ EXPECT_EQ(1, bufferlessSurfaceFrame1->getToken());
+ EXPECT_EQ(PresentState::Presented, bufferlessSurfaceFrame1->getPresentState());
+ EXPECT_EQ(10, bufferlessSurfaceFrame1->getActuals().endTime);
+
+ EXPECT_EQ(2, bufferlessSurfaceFrame2->getToken());
+ EXPECT_EQ(PresentState::Presented, bufferlessSurfaceFrame2->getPresentState());
+ EXPECT_EQ(12, bufferlessSurfaceFrame2->getActuals().endTime);
+ }
+
+ void MergePendingStates_BufferlessSurfaceFramesWithOverlappingToken() {
+ sp<BufferStateLayer> layer = createBufferStateLayer();
+ layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0},
+ 10);
+ EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
+ ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
+ const auto bufferlessSurfaceFrame1 =
+ layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 1);
+
+ layer->pushPendingState();
+ EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
+
+ layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 1, /*inputEventId*/ 0},
+ 12);
+ EXPECT_EQ(1u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
+ ASSERT_EQ(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
+ const auto bufferlessSurfaceFrame2 =
+ layer->mCurrentState.bufferlessSurfaceFramesTX.at(/*token*/ 1);
+
+ commitTransaction(layer.get());
+
+ EXPECT_EQ(1, bufferlessSurfaceFrame1->getToken());
+ EXPECT_EQ(PresentState::Unknown, bufferlessSurfaceFrame1->getPresentState());
+
+ EXPECT_EQ(1, bufferlessSurfaceFrame2->getToken());
+ EXPECT_EQ(PresentState::Presented, bufferlessSurfaceFrame2->getPresentState());
+ EXPECT_EQ(12, bufferlessSurfaceFrame2->getActuals().endTime);
+ }
+};
+
+TEST_F(TransactionSurfaceFrameTest, PresentedBufferlessSurfaceFrame) {
+ PresentedSurfaceFrameForBufferlessTransaction();
+}
+
+TEST_F(TransactionSurfaceFrameTest, PresentedBufferSurfaceFrame) {
+ PresentedSurfaceFrameForBufferTransaction();
+}
+
+TEST_F(TransactionSurfaceFrameTest, DroppedBufferSurfaceFrame) {
+ DroppedSurfaceFrameForBufferTransaction();
+}
+
+TEST_F(TransactionSurfaceFrameTest, BufferlessSurfaceFramePromotedToBufferSurfaceFrame) {
+ BufferlessSurfaceFramePromotedToBufferSurfaceFrame();
+}
+
+TEST_F(TransactionSurfaceFrameTest, BufferlessSurfaceFrameNotCreatedIfBufferSufaceFrameExists) {
+ BufferlessSurfaceFrameNotCreatedIfBufferSufaceFrameExists();
+}
+
+TEST_F(TransactionSurfaceFrameTest, MultipleSurfaceFramesPresentedTogether) {
+ MultipleSurfaceFramesPresentedTogether();
+}
+
+TEST_F(TransactionSurfaceFrameTest,
+ MergePendingStates_BufferlessSurfaceFramesWithoutOverlappingToken) {
+ MergePendingStates_BufferlessSurfaceFramesWithoutOverlappingToken();
+}
+
+TEST_F(TransactionSurfaceFrameTest,
+ MergePendingStates_BufferlessSurfaceFramesWithOverlappingToken) {
+ MergePendingStates_BufferlessSurfaceFramesWithOverlappingToken();
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
index 40437bf..485b4ac 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h
@@ -33,7 +33,7 @@
MOCK_METHOD0(onScreenReleased, void());
MOCK_METHOD0(onScreenAcquired, void());
MOCK_METHOD2(onHotplugReceived, void(PhysicalDisplayId, bool));
- MOCK_METHOD3(onConfigChanged, void(PhysicalDisplayId, DisplayModeId, nsecs_t));
+ MOCK_METHOD3(onModeChanged, void(PhysicalDisplayId, DisplayModeId, nsecs_t));
MOCK_METHOD2(onFrameRateOverridesChanged,
void(PhysicalDisplayId, std::vector<FrameRateOverride>));
MOCK_CONST_METHOD1(dump, void(std::string&));
diff --git a/services/surfaceflinger/tests/utils/ScreenshotUtils.h b/services/surfaceflinger/tests/utils/ScreenshotUtils.h
index a13f93b..2fefa45 100644
--- a/services/surfaceflinger/tests/utils/ScreenshotUtils.h
+++ b/services/surfaceflinger/tests/utils/ScreenshotUtils.h
@@ -84,11 +84,13 @@
}
void expectColor(const Rect& rect, const Color& color, uint8_t tolerance = 0) {
+ ASSERT_NE(nullptr, mOutBuffer);
ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat());
TransactionUtils::expectBufferColor(mOutBuffer, mPixels, rect, color, tolerance);
}
void expectBorder(const Rect& rect, const Color& color, uint8_t tolerance = 0) {
+ ASSERT_NE(nullptr, mOutBuffer);
ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat());
const bool leftBorder = rect.left > 0;
const bool topBorder = rect.top > 0;
@@ -146,6 +148,7 @@
}
void checkPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) {
+ ASSERT_NE(nullptr, mOutBuffer);
ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat());
const uint8_t* pixel = mPixels + (4 * (y * mOutBuffer->getStride() + x));
if (r != pixel[0] || g != pixel[1] || b != pixel[2]) {
@@ -163,10 +166,14 @@
void expectChildColor(uint32_t x, uint32_t y) { checkPixel(x, y, 200, 200, 200); }
explicit ScreenCapture(const sp<GraphicBuffer>& outBuffer) : mOutBuffer(outBuffer) {
- mOutBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&mPixels));
+ if (mOutBuffer) {
+ mOutBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&mPixels));
+ }
}
- ~ScreenCapture() { mOutBuffer->unlock(); }
+ ~ScreenCapture() {
+ if (mOutBuffer) mOutBuffer->unlock();
+ }
private:
sp<GraphicBuffer> mOutBuffer;
diff --git a/services/vibratorservice/Android.bp b/services/vibratorservice/Android.bp
index c18bf18..4f89353 100644
--- a/services/vibratorservice/Android.bp
+++ b/services/vibratorservice/Android.bp
@@ -36,7 +36,7 @@
"libhidlbase",
"liblog",
"libutils",
- "android.hardware.vibrator-unstable-cpp",
+ "android.hardware.vibrator-V2-cpp",
"android.hardware.vibrator@1.0",
"android.hardware.vibrator@1.1",
"android.hardware.vibrator@1.2",
diff --git a/services/vibratorservice/benchmarks/Android.bp b/services/vibratorservice/benchmarks/Android.bp
index d3130f4..7b4cc19 100644
--- a/services/vibratorservice/benchmarks/Android.bp
+++ b/services/vibratorservice/benchmarks/Android.bp
@@ -23,7 +23,7 @@
"liblog",
"libutils",
"libvibratorservice",
- "android.hardware.vibrator-unstable-cpp",
+ "android.hardware.vibrator-V2-cpp",
"android.hardware.vibrator@1.0",
"android.hardware.vibrator@1.1",
"android.hardware.vibrator@1.2",
diff --git a/services/vibratorservice/test/Android.bp b/services/vibratorservice/test/Android.bp
index 9af1b7b..ad85990 100644
--- a/services/vibratorservice/test/Android.bp
+++ b/services/vibratorservice/test/Android.bp
@@ -39,7 +39,7 @@
"liblog",
"libvibratorservice",
"libutils",
- "android.hardware.vibrator-unstable-cpp",
+ "android.hardware.vibrator-V2-cpp",
"android.hardware.vibrator@1.0",
"android.hardware.vibrator@1.1",
"android.hardware.vibrator@1.2",
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 48090af..cb845a0 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -606,44 +606,9 @@
VKAPI_ATTR
VkResult GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice /*pdev*/,
uint32_t /*queue_family*/,
- VkSurfaceKHR surface_handle,
+ VkSurfaceKHR /*surface_handle*/,
VkBool32* supported) {
- ATRACE_CALL();
-
- const Surface* surface = SurfaceFromHandle(surface_handle);
- if (!surface) {
- return VK_ERROR_SURFACE_LOST_KHR;
- }
- const ANativeWindow* window = surface->window.get();
-
- int query_value;
- int err = window->query(window, NATIVE_WINDOW_FORMAT, &query_value);
- if (err != android::OK || query_value < 0) {
- ALOGE("NATIVE_WINDOW_FORMAT query failed: %s (%d) value=%d",
- strerror(-err), err, query_value);
- return VK_ERROR_SURFACE_LOST_KHR;
- }
-
- android_pixel_format native_format =
- static_cast<android_pixel_format>(query_value);
-
- bool format_supported = false;
- switch (native_format) {
- case HAL_PIXEL_FORMAT_RGBA_8888:
- case HAL_PIXEL_FORMAT_RGB_565:
- case HAL_PIXEL_FORMAT_RGBA_FP16:
- case HAL_PIXEL_FORMAT_RGBA_1010102:
- format_supported = true;
- break;
- default:
- break;
- }
-
- *supported = static_cast<VkBool32>(
- format_supported || (surface->consumer_usage &
- (AHARDWAREBUFFER_USAGE_CPU_READ_MASK |
- AHARDWAREBUFFER_USAGE_CPU_WRITE_MASK)) == 0);
-
+ *supported = VK_TRUE;
return VK_SUCCESS;
}