Merge "Fix input infos are inconsistent between WMS and InputFlinger (2/2)" into rvc-dev
diff --git a/cmds/dumpstate/DumpstateService.cpp b/cmds/dumpstate/DumpstateService.cpp
index a0b9cbb..1824943 100644
--- a/cmds/dumpstate/DumpstateService.cpp
+++ b/cmds/dumpstate/DumpstateService.cpp
@@ -148,14 +148,13 @@
}
binder::Status DumpstateService::cancelBugreport() {
- // This is a no-op since the cancellation is done from java side via setting sys properties.
- // See BugreportManagerServiceImpl.
- // TODO(b/111441001): maybe make native and java sides use different binder interface
- // to avoid these annoyances.
+ std::lock_guard<std::mutex> lock(lock_);
+ ds_->Cancel();
return binder::Status::ok();
}
status_t DumpstateService::dump(int fd, const Vector<String16>&) {
+ std::lock_guard<std::mutex> lock(lock_);
if (ds_ == nullptr) {
dprintf(fd, "Bugreport not in progress yet");
return NO_ERROR;
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 01b7e63..772b9fe 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -239,6 +239,9 @@
}
static bool UnlinkAndLogOnError(const std::string& file) {
+ if (file.empty()) {
+ return false;
+ }
if (unlink(file.c_str())) {
MYLOGE("Failed to unlink file (%s): %s\n", file.c_str(), strerror(errno));
return false;
@@ -246,7 +249,6 @@
return true;
}
-
int64_t GetModuleMetadataVersion() {
auto binder = defaultServiceManager()->getService(android::String16("package_native"));
if (binder == nullptr) {
@@ -2419,6 +2421,17 @@
return status;
}
+void Dumpstate::Cancel() {
+ CleanupTmpFiles();
+ android::os::UnlinkAndLogOnError(log_path_);
+ for (int i = 0; i < NUM_OF_DUMPS; i++) {
+ android::os::UnlinkAndLogOnError(ds.bugreport_internal_dir_ + "/" +
+ kDumpstateBoardFiles[i]);
+ }
+ tombstone_data_.clear();
+ anr_data_.clear();
+}
+
/*
* Dumps relevant information to a bugreport based on the given options.
*
@@ -2755,7 +2768,7 @@
return ds.options_->bugreport_fd.get() != -1 ? true : false;
}
-void Dumpstate::CleanupFiles() {
+void Dumpstate::CleanupTmpFiles() {
android::os::UnlinkAndLogOnError(tmp_path_);
android::os::UnlinkAndLogOnError(screenshot_path_);
android::os::UnlinkAndLogOnError(path_);
@@ -2763,7 +2776,7 @@
Dumpstate::RunStatus Dumpstate::HandleUserConsentDenied() {
MYLOGD("User denied consent; deleting files and returning\n");
- CleanupFiles();
+ CleanupTmpFiles();
return USER_CONSENT_DENIED;
}
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 7b8d282..9ce662b 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -334,6 +334,9 @@
RunStatus ParseCommandlineAndRun(int argc, char* argv[]);
+ /* Deletes in-progress files */
+ void Cancel();
+
/* Sets runtime options. */
void SetOptions(std::unique_ptr<DumpOptions> options);
@@ -502,7 +505,7 @@
// Removes the in progress files output files (tmp file, zip/txt file, screenshot),
// but leaves the log file alone.
- void CleanupFiles();
+ void CleanupTmpFiles();
RunStatus HandleUserConsentDenied();
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
index c30dcfe..cbcf6ec 100644
--- a/include/android/surface_control.h
+++ b/include/android/surface_control.h
@@ -409,7 +409,7 @@
#if __ANDROID_API__ >= 30
-/*
+/**
* Sets the intended frame rate for |surface_control|.
*
* On devices that are capable of running the display at different refresh rates, the system may
@@ -421,9 +421,9 @@
*
* |frameRate| is the intended frame rate of this surface, in frames per second. 0 is a special
* value that indicates the app will accept the system's choice for the display frame rate, which is
- * the default behavior if this function isn't called. The frameRate param does *not* need to be a
- * valid refresh rate for this device's display - e.g., it's fine to pass 30fps to a device that can
- * only run the display at 60fps.
+ * the default behavior if this function isn't called. The frameRate param does <em>not</em> need to
+ * be a valid refresh rate for this device's display - e.g., it's fine to pass 30fps to a device
+ * that can only run the display at 60fps.
*
* |compatibility| The frame rate compatibility of this surface. The compatibility value may
* influence the system's choice of display frame rate. To specify a compatibility use the
diff --git a/libs/binder/include/binder/AppOpsManager.h b/libs/binder/include/binder/AppOpsManager.h
index 2ee5930..6afcd77 100644
--- a/libs/binder/include/binder/AppOpsManager.h
+++ b/libs/binder/include/binder/AppOpsManager.h
@@ -122,7 +122,16 @@
OP_LEGACY_STORAGE = 87,
OP_ACCESS_ACCESSIBILITY = 88,
OP_READ_DEVICE_IDENTIFIERS = 89,
- _NUM_OP = 90
+ OP_ACCESS_MEDIA_LOCATION = 90,
+ OP_QUERY_ALL_PACKAGES = 91,
+ OP_MANAGE_EXTERNAL_STORAGE = 92,
+ OP_INTERACT_ACROSS_PROFILES = 93,
+ OP_ACTIVATE_PLATFORM_VPN = 94,
+ OP_LOADER_USAGE_STATS = 95,
+ OP_DEPRECATED_1 = 96,
+ OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED = 97,
+ OP_AUTO_REVOKE_MANAGED_BY_INSTALLER = 98,
+ _NUM_OP = 99
};
AppOpsManager();
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index b2b74dc..fd557b7 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -73,6 +73,7 @@
"android.hardware.thermal@2.0::IThermal",
"android.hardware.vr@1.0::IVr",
"android.hardware.automotive.audiocontrol@1.0::IAudioControl",
+ "android.hardware.automotive.audiocontrol@2.0::IAudioControl",
"android.hardware.automotive.vehicle@2.0::IVehicle",
"android.hardware.automotive.evs@1.0::IEvsCamera",
"android.hardware.neuralnetworks@1.0::IDevice",
diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h
index 59aa665..25130e2 100644
--- a/libs/nativewindow/include/android/native_window.h
+++ b/libs/nativewindow/include/android/native_window.h
@@ -233,15 +233,15 @@
#if __ANDROID_API__ >= 30
-/* Parameter for ANativeWindow_setFrameRate */
-enum {
+/** Compatibility value for ANativeWindow_setFrameRate. */
+enum ANativeWindow_FrameRateCompatibility {
/**
* There are no inherent restrictions on the frame rate of this window.
*/
ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT = 0,
/**
* This window is being used to display content with an inherently fixed
- * frame rate, e.g. a video that has a specific frame rate. When the system
+ * frame rate, e.g.\ a video that has a specific frame rate. When the system
* selects a frame rate other than what the app requested, the app will need
* to do pull down or use some other technique to adapt to the system's
* frame rate. The user experience is likely to be worse (e.g. more frame
@@ -272,9 +272,9 @@
* \param frameRate The intended frame rate of this window, in frames per
* second. 0 is a special value that indicates the app will accept the system's
* choice for the display frame rate, which is the default behavior if this
- * function isn't called. The frameRate param does *not* need to be a valid
- * refresh rate for this device's display - e.g., it's fine to pass 30fps to a
- * device that can only run the display at 60fps.
+ * function isn't called. The frameRate param does <em>not</em> need to be a
+ * valid refresh rate for this device's display - e.g., it's fine to pass 30fps
+ * to a device that can only run the display at 60fps.
*
* \param compatibility The frame rate compatibility of this window. The
* compatibility value may influence the system's choice of display refresh
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index bbc8e53..99a572a 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -160,8 +160,8 @@
: InputMapper(deviceContext),
mSource(0),
mDeviceMode(DEVICE_MODE_DISABLED),
- mSurfaceWidth(-1),
- mSurfaceHeight(-1),
+ mRawSurfaceWidth(-1),
+ mRawSurfaceHeight(-1),
mSurfaceLeft(0),
mSurfaceTop(0),
mPhysicalWidth(-1),
@@ -680,7 +680,7 @@
naturalLogicalHeight = mViewport.logicalRight - mViewport.logicalLeft;
naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
- naturalPhysicalLeft = mViewport.deviceHeight - naturalPhysicalWidth;
+ naturalPhysicalLeft = mViewport.deviceHeight - mViewport.physicalBottom;
naturalPhysicalTop = mViewport.physicalLeft;
naturalDeviceWidth = mViewport.deviceHeight;
naturalDeviceHeight = mViewport.deviceWidth;
@@ -701,7 +701,7 @@
naturalPhysicalWidth = mViewport.physicalBottom - mViewport.physicalTop;
naturalPhysicalHeight = mViewport.physicalRight - mViewport.physicalLeft;
naturalPhysicalLeft = mViewport.physicalTop;
- naturalPhysicalTop = mViewport.deviceWidth - naturalPhysicalHeight;
+ naturalPhysicalTop = mViewport.deviceWidth - mViewport.physicalRight;
naturalDeviceWidth = mViewport.deviceHeight;
naturalDeviceHeight = mViewport.deviceWidth;
break;
@@ -729,10 +729,12 @@
mPhysicalLeft = naturalPhysicalLeft;
mPhysicalTop = naturalPhysicalTop;
- mSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth;
- mSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight;
+ mRawSurfaceWidth = naturalLogicalWidth * naturalDeviceWidth / naturalPhysicalWidth;
+ mRawSurfaceHeight = naturalLogicalHeight * naturalDeviceHeight / naturalPhysicalHeight;
mSurfaceLeft = naturalPhysicalLeft * naturalLogicalWidth / naturalPhysicalWidth;
mSurfaceTop = naturalPhysicalTop * naturalLogicalHeight / naturalPhysicalHeight;
+ mSurfaceRight = mSurfaceLeft + naturalLogicalWidth;
+ mSurfaceBottom = mSurfaceTop + naturalLogicalHeight;
mSurfaceOrientation =
mParameters.orientationAware ? mViewport.orientation : DISPLAY_ORIENTATION_0;
@@ -742,8 +744,8 @@
mPhysicalLeft = 0;
mPhysicalTop = 0;
- mSurfaceWidth = rawWidth;
- mSurfaceHeight = rawHeight;
+ mRawSurfaceWidth = rawWidth;
+ mRawSurfaceHeight = rawHeight;
mSurfaceLeft = 0;
mSurfaceTop = 0;
mSurfaceOrientation = DISPLAY_ORIENTATION_0;
@@ -769,12 +771,12 @@
if (viewportChanged || deviceModeChanged) {
ALOGI("Device reconfigured: id=%d, name='%s', size %dx%d, orientation %d, mode %d, "
"display id %d",
- getDeviceId(), getDeviceName().c_str(), mSurfaceWidth, mSurfaceHeight,
+ getDeviceId(), getDeviceName().c_str(), mRawSurfaceWidth, mRawSurfaceHeight,
mSurfaceOrientation, mDeviceMode, mViewport.displayId);
// Configure X and Y factors.
- mXScale = float(mSurfaceWidth) / rawWidth;
- mYScale = float(mSurfaceHeight) / rawHeight;
+ mXScale = float(mRawSurfaceWidth) / rawWidth;
+ mYScale = float(mRawSurfaceHeight) / rawHeight;
mXTranslate = -mSurfaceLeft;
mYTranslate = -mSurfaceTop;
mXPrecision = 1.0f / mXScale;
@@ -793,7 +795,7 @@
mGeometricScale = avg(mXScale, mYScale);
// Size of diagonal axis.
- float diagonalSize = hypotf(mSurfaceWidth, mSurfaceHeight);
+ float diagonalSize = hypotf(mRawSurfaceWidth, mRawSurfaceHeight);
// Size factors.
if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
@@ -956,13 +958,13 @@
mOrientedYPrecision = mXPrecision;
mOrientedRanges.x.min = mYTranslate;
- mOrientedRanges.x.max = mSurfaceHeight + mYTranslate - 1;
+ mOrientedRanges.x.max = mRawSurfaceHeight + mYTranslate - 1;
mOrientedRanges.x.flat = 0;
mOrientedRanges.x.fuzz = 0;
mOrientedRanges.x.resolution = mRawPointerAxes.y.resolution * mYScale;
mOrientedRanges.y.min = mXTranslate;
- mOrientedRanges.y.max = mSurfaceWidth + mXTranslate - 1;
+ mOrientedRanges.y.max = mRawSurfaceWidth + mXTranslate - 1;
mOrientedRanges.y.flat = 0;
mOrientedRanges.y.fuzz = 0;
mOrientedRanges.y.resolution = mRawPointerAxes.x.resolution * mXScale;
@@ -973,13 +975,13 @@
mOrientedYPrecision = mYPrecision;
mOrientedRanges.x.min = mXTranslate;
- mOrientedRanges.x.max = mSurfaceWidth + mXTranslate - 1;
+ mOrientedRanges.x.max = mRawSurfaceWidth + mXTranslate - 1;
mOrientedRanges.x.flat = 0;
mOrientedRanges.x.fuzz = 0;
mOrientedRanges.x.resolution = mRawPointerAxes.x.resolution * mXScale;
mOrientedRanges.y.min = mYTranslate;
- mOrientedRanges.y.max = mSurfaceHeight + mYTranslate - 1;
+ mOrientedRanges.y.max = mRawSurfaceHeight + mYTranslate - 1;
mOrientedRanges.y.flat = 0;
mOrientedRanges.y.fuzz = 0;
mOrientedRanges.y.resolution = mRawPointerAxes.y.resolution * mYScale;
@@ -992,7 +994,7 @@
if (mDeviceMode == DEVICE_MODE_POINTER) {
// Compute pointer gesture detection parameters.
float rawDiagonal = hypotf(rawWidth, rawHeight);
- float displayDiagonal = hypotf(mSurfaceWidth, mSurfaceHeight);
+ float displayDiagonal = hypotf(mRawSurfaceWidth, mRawSurfaceHeight);
// Scale movements such that one whole swipe of the touch pad covers a
// given area relative to the diagonal size of the display when no acceleration
@@ -1027,10 +1029,12 @@
void TouchInputMapper::dumpSurface(std::string& dump) {
dump += StringPrintf(INDENT3 "%s\n", mViewport.toString().c_str());
- dump += StringPrintf(INDENT3 "SurfaceWidth: %dpx\n", mSurfaceWidth);
- dump += StringPrintf(INDENT3 "SurfaceHeight: %dpx\n", mSurfaceHeight);
+ dump += StringPrintf(INDENT3 "RawSurfaceWidth: %dpx\n", mRawSurfaceWidth);
+ dump += StringPrintf(INDENT3 "RawSurfaceHeight: %dpx\n", mRawSurfaceHeight);
dump += StringPrintf(INDENT3 "SurfaceLeft: %d\n", mSurfaceLeft);
dump += StringPrintf(INDENT3 "SurfaceTop: %d\n", mSurfaceTop);
+ dump += StringPrintf(INDENT3 "SurfaceRight: %d\n", mSurfaceRight);
+ dump += StringPrintf(INDENT3 "SurfaceBottom: %d\n", mSurfaceBottom);
dump += StringPrintf(INDENT3 "PhysicalWidth: %dpx\n", mPhysicalWidth);
dump += StringPrintf(INDENT3 "PhysicalHeight: %dpx\n", mPhysicalHeight);
dump += StringPrintf(INDENT3 "PhysicalLeft: %d\n", mPhysicalLeft);
@@ -1074,16 +1078,16 @@
int32_t halfHeight = virtualKeyDefinition.height / 2;
virtualKey.hitLeft =
- (virtualKeyDefinition.centerX - halfWidth) * touchScreenWidth / mSurfaceWidth +
+ (virtualKeyDefinition.centerX - halfWidth) * touchScreenWidth / mRawSurfaceWidth +
touchScreenLeft;
virtualKey.hitRight =
- (virtualKeyDefinition.centerX + halfWidth) * touchScreenWidth / mSurfaceWidth +
+ (virtualKeyDefinition.centerX + halfWidth) * touchScreenWidth / mRawSurfaceWidth +
touchScreenLeft;
- virtualKey.hitTop =
- (virtualKeyDefinition.centerY - halfHeight) * touchScreenHeight / mSurfaceHeight +
+ virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight) * touchScreenHeight /
+ mRawSurfaceHeight +
touchScreenTop;
- virtualKey.hitBottom =
- (virtualKeyDefinition.centerY + halfHeight) * touchScreenHeight / mSurfaceHeight +
+ virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight) * touchScreenHeight /
+ mRawSurfaceHeight +
touchScreenTop;
mVirtualKeys.push_back(virtualKey);
}
@@ -2188,13 +2192,10 @@
rotateAndScale(xTransformed, yTransformed);
// Adjust X, Y, and coverage coords for surface orientation.
- float x, y;
float left, top, right, bottom;
switch (mSurfaceOrientation) {
case DISPLAY_ORIENTATION_90:
- x = yTransformed + mYTranslate;
- y = xTransformed + mXTranslate;
left = float(rawTop - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
right = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
bottom = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale + mXTranslate;
@@ -2207,8 +2208,6 @@
}
break;
case DISPLAY_ORIENTATION_180:
- x = xTransformed + mXTranslate;
- y = yTransformed + mYTranslate;
left = float(mRawPointerAxes.x.maxValue - rawRight) * mXScale;
right = float(mRawPointerAxes.x.maxValue - rawLeft) * mXScale;
bottom = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale + mYTranslate;
@@ -2221,8 +2220,6 @@
}
break;
case DISPLAY_ORIENTATION_270:
- x = yTransformed + mYTranslate;
- y = xTransformed + mXTranslate;
left = float(mRawPointerAxes.y.maxValue - rawBottom) * mYScale;
right = float(mRawPointerAxes.y.maxValue - rawTop) * mYScale;
bottom = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
@@ -2235,8 +2232,6 @@
}
break;
default:
- x = xTransformed + mXTranslate;
- y = yTransformed + mYTranslate;
left = float(rawLeft - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
right = float(rawRight - mRawPointerAxes.x.minValue) * mXScale + mXTranslate;
bottom = float(rawBottom - mRawPointerAxes.y.minValue) * mYScale + mYTranslate;
@@ -2247,8 +2242,8 @@
// Write output coords.
PointerCoords& out = mCurrentCookedState.cookedPointerData.pointerCoords[i];
out.clear();
- out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
- out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
+ out.setAxisValue(AMOTION_EVENT_AXIS_X, xTransformed);
+ out.setAxisValue(AMOTION_EVENT_AXIS_Y, yTransformed);
out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
@@ -3624,34 +3619,47 @@
abortTouches(when, 0 /* policyFlags*/);
}
+// Transform raw coordinate to surface coordinate
void TouchInputMapper::rotateAndScale(float& x, float& y) {
+ // Scale to surface coordinate.
+ const float xScaled = float(x - mRawPointerAxes.x.minValue) * mXScale;
+ const float yScaled = float(y - mRawPointerAxes.y.minValue) * mYScale;
+
+ // Rotate to surface coordinate.
+ // 0 - no swap and reverse.
+ // 90 - swap x/y and reverse y.
+ // 180 - reverse x, y.
+ // 270 - swap x/y and reverse x.
switch (mSurfaceOrientation) {
+ case DISPLAY_ORIENTATION_0:
+ x = xScaled + mXTranslate;
+ y = yScaled + mYTranslate;
+ break;
case DISPLAY_ORIENTATION_90:
- x = float(mRawPointerAxes.x.maxValue - x) * mXScale;
- y = float(y - mRawPointerAxes.y.minValue) * mYScale;
+ y = mSurfaceRight - xScaled;
+ x = yScaled + mYTranslate;
break;
case DISPLAY_ORIENTATION_180:
- x = float(mRawPointerAxes.x.maxValue - x) * mXScale;
- y = float(mRawPointerAxes.y.maxValue - y) * mYScale;
+ x = mSurfaceRight - xScaled;
+ y = mSurfaceBottom - yScaled;
break;
case DISPLAY_ORIENTATION_270:
- x = float(x - mRawPointerAxes.x.minValue) * mXScale;
- y = float(mRawPointerAxes.y.maxValue - y) * mYScale;
+ y = xScaled + mXTranslate;
+ x = mSurfaceBottom - yScaled;
break;
default:
- x = float(x - mRawPointerAxes.x.minValue) * mXScale;
- y = float(y - mRawPointerAxes.y.minValue) * mYScale;
- break;
+ assert(false);
}
}
bool TouchInputMapper::isPointInsideSurface(int32_t x, int32_t y) {
- float xTransformed = x, yTransformed = y;
- rotateAndScale(xTransformed, yTransformed);
+ const float xScaled = (x - mRawPointerAxes.x.minValue) * mXScale;
+ const float yScaled = (y - mRawPointerAxes.y.minValue) * mYScale;
+
return x >= mRawPointerAxes.x.minValue && x <= mRawPointerAxes.x.maxValue &&
- xTransformed >= mSurfaceLeft && xTransformed <= mSurfaceLeft + mSurfaceWidth &&
+ xScaled >= mSurfaceLeft && xScaled <= mSurfaceRight &&
y >= mRawPointerAxes.y.minValue && y <= mRawPointerAxes.y.maxValue &&
- yTransformed >= mSurfaceTop && yTransformed <= mSurfaceTop + mSurfaceHeight;
+ yScaled >= mSurfaceTop && yScaled <= mSurfaceBottom;
}
const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHit(int32_t x, int32_t y) {
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.h b/services/inputflinger/reader/mapper/TouchInputMapper.h
index e21a33a..58bfc5c 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.h
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.h
@@ -407,12 +407,16 @@
// The surface orientation, width and height set by configureSurface().
// The width and height are derived from the viewport but are specified
// in the natural orientation.
+ // They could be used for calculating diagonal, scaling factors, and virtual keys.
+ int32_t mRawSurfaceWidth;
+ int32_t mRawSurfaceHeight;
+
// The surface origin specifies how the surface coordinates should be translated
// to align with the logical display coordinate space.
- int32_t mSurfaceWidth;
- int32_t mSurfaceHeight;
int32_t mSurfaceLeft;
int32_t mSurfaceTop;
+ int32_t mSurfaceRight;
+ int32_t mSurfaceBottom;
// Similar to the surface coordinates, but in the raw display coordinate space rather than in
// the logical coordinate space.
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 618aefc..96d86b6 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -6990,51 +6990,7 @@
ASSERT_EQ(SECONDARY_DISPLAY_ID, args.displayId);
}
-/**
- * Test touch should not work if outside of surface.
- */
-TEST_F(MultiTouchInputMapperTest, Viewports_SurfaceRange) {
- addConfigurationProperty("touch.deviceType", "touchScreen");
- prepareDisplay(DISPLAY_ORIENTATION_0);
- prepareAxes(POSITION);
- MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
- // Touch on left-top area should work.
- int32_t rawX = DISPLAY_WIDTH / 2 - 1;
- int32_t rawY = DISPLAY_HEIGHT / 2 - 1;
- processPosition(mapper, rawX, rawY);
- processSync(mapper);
-
- NotifyMotionArgs args;
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
-
- // Reset.
- mapper.reset(ARBITRARY_TIME);
-
- // Let logical display be different to physical display and rotate 90-degrees.
- std::optional<DisplayViewport> internalViewport =
- mFakePolicy->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
- internalViewport->orientation = DISPLAY_ORIENTATION_90;
- internalViewport->logicalLeft = 0;
- internalViewport->logicalTop = 0;
- internalViewport->logicalRight = DISPLAY_HEIGHT;
- internalViewport->logicalBottom = DISPLAY_WIDTH / 2;
-
- internalViewport->physicalLeft = DISPLAY_HEIGHT;
- internalViewport->physicalTop = DISPLAY_WIDTH / 2;
- internalViewport->physicalRight = DISPLAY_HEIGHT;
- internalViewport->physicalBottom = DISPLAY_WIDTH;
-
- internalViewport->deviceWidth = DISPLAY_HEIGHT;
- internalViewport->deviceHeight = DISPLAY_WIDTH;
- mFakePolicy->updateViewport(internalViewport.value());
- configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
-
- // Display align to right-top after rotate 90-degrees, touch on left-top area should not work.
- processPosition(mapper, rawX, rawY);
- processSync(mapper);
- ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
-}
TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleSingleTouch) {
addConfigurationProperty("touch.deviceType", "touchScreen");
@@ -7161,4 +7117,130 @@
ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
ASSERT_EQ(SECONDARY_DISPLAY_ID, motionArgs.displayId);
}
+
+/**
+ * Test touch should not work if outside of surface.
+ */
+class MultiTouchInputMapperTest_SurfaceRange : public MultiTouchInputMapperTest {
+protected:
+ void halfDisplayToCenterHorizontal(int32_t orientation) {
+ std::optional<DisplayViewport> internalViewport =
+ mFakePolicy->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
+
+ // Half display to (width/4, 0, width * 3/4, height) to make display has offset.
+ internalViewport->orientation = orientation;
+ if (orientation == DISPLAY_ORIENTATION_90 || orientation == DISPLAY_ORIENTATION_270) {
+ internalViewport->logicalLeft = 0;
+ internalViewport->logicalTop = 0;
+ internalViewport->logicalRight = DISPLAY_HEIGHT;
+ internalViewport->logicalBottom = DISPLAY_WIDTH / 2;
+
+ internalViewport->physicalLeft = 0;
+ internalViewport->physicalTop = DISPLAY_WIDTH / 4;
+ internalViewport->physicalRight = DISPLAY_HEIGHT;
+ internalViewport->physicalBottom = DISPLAY_WIDTH * 3 / 4;
+
+ internalViewport->deviceWidth = DISPLAY_HEIGHT;
+ internalViewport->deviceHeight = DISPLAY_WIDTH;
+ } else {
+ internalViewport->logicalLeft = 0;
+ internalViewport->logicalTop = 0;
+ internalViewport->logicalRight = DISPLAY_WIDTH / 2;
+ internalViewport->logicalBottom = DISPLAY_HEIGHT;
+
+ internalViewport->physicalLeft = DISPLAY_WIDTH / 4;
+ internalViewport->physicalTop = 0;
+ internalViewport->physicalRight = DISPLAY_WIDTH * 3 / 4;
+ internalViewport->physicalBottom = DISPLAY_HEIGHT;
+
+ internalViewport->deviceWidth = DISPLAY_WIDTH;
+ internalViewport->deviceHeight = DISPLAY_HEIGHT;
+ }
+
+ mFakePolicy->updateViewport(internalViewport.value());
+ configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+ }
+
+ void processPositionAndVerify(MultiTouchInputMapper& mapper, int32_t xInside, int32_t yInside,
+ int32_t xOutside, int32_t yOutside, int32_t xExpected,
+ int32_t yExpected) {
+ // touch on outside area should not work.
+ processPosition(mapper, toRawX(xOutside), toRawY(yOutside));
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
+
+ // touch on inside area should receive the event.
+ NotifyMotionArgs args;
+ processPosition(mapper, toRawX(xInside), toRawY(yInside));
+ processSync(mapper);
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_NEAR(xExpected, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_X), 1);
+ ASSERT_NEAR(yExpected, args.pointerCoords[0].getAxisValue(AMOTION_EVENT_AXIS_Y), 1);
+
+ // Reset.
+ mapper.reset(ARBITRARY_TIME);
+ }
+};
+
+TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange) {
+ addConfigurationProperty("touch.deviceType", "touchScreen");
+ prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareAxes(POSITION);
+ MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+
+ // Touch on center of normal display should work.
+ const int32_t x = DISPLAY_WIDTH / 4;
+ const int32_t y = DISPLAY_HEIGHT / 2;
+ processPosition(mapper, toRawX(x), toRawY(y));
+ processSync(mapper);
+ NotifyMotionArgs args;
+ ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&args));
+ ASSERT_NO_FATAL_FAILURE(assertPointerCoords(args.pointerCoords[0], x, y, 1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.0f, 0.0f));
+ // Reset.
+ mapper.reset(ARBITRARY_TIME);
+
+ // Let physical display be different to device, and make surface and physical could be 1:1.
+ halfDisplayToCenterHorizontal(DISPLAY_ORIENTATION_0);
+
+ const int32_t xExpected = (x + 1) - (DISPLAY_WIDTH / 4);
+ const int32_t yExpected = y;
+ processPositionAndVerify(mapper, x - 1, y, x + 1, y, xExpected, yExpected);
+}
+
+TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange_90) {
+ addConfigurationProperty("touch.deviceType", "touchScreen");
+ prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareAxes(POSITION);
+ MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+
+ // Half display to (width/4, 0, width * 3/4, height) and rotate 90-degrees.
+ halfDisplayToCenterHorizontal(DISPLAY_ORIENTATION_90);
+
+ const int32_t x = DISPLAY_WIDTH / 4;
+ const int32_t y = DISPLAY_HEIGHT / 2;
+
+ // expect x/y = swap x/y then reverse y.
+ const int32_t xExpected = y;
+ const int32_t yExpected = (DISPLAY_WIDTH * 3 / 4) - (x + 1);
+ processPositionAndVerify(mapper, x - 1, y, x + 1, y, xExpected, yExpected);
+}
+
+TEST_F(MultiTouchInputMapperTest_SurfaceRange, Viewports_SurfaceRange_270) {
+ addConfigurationProperty("touch.deviceType", "touchScreen");
+ prepareDisplay(DISPLAY_ORIENTATION_0);
+ prepareAxes(POSITION);
+ MultiTouchInputMapper& mapper = addMapperAndConfigure<MultiTouchInputMapper>();
+
+ // Half display to (width/4, 0, width * 3/4, height) and rotate 270-degrees.
+ halfDisplayToCenterHorizontal(DISPLAY_ORIENTATION_270);
+
+ const int32_t x = DISPLAY_WIDTH / 4;
+ const int32_t y = DISPLAY_HEIGHT / 2;
+
+ // expect x/y = swap x/y then reverse x.
+ constexpr int32_t xExpected = DISPLAY_HEIGHT - y;
+ constexpr int32_t yExpected = (x + 1) - DISPLAY_WIDTH / 4;
+ processPositionAndVerify(mapper, x - 1, y, x + 1, y, xExpected, yExpected);
+}
} // namespace android
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index e4d754c..a32bc2b 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -272,7 +272,7 @@
// pixel format is HDR Y410 masquerading as RGBA_1010102
return (mBufferInfo.mDataspace == ui::Dataspace::BT2020_ITU_PQ &&
mBufferInfo.mApi == NATIVE_WINDOW_API_MEDIA &&
- mBufferInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102);
+ mBufferInfo.mPixelFormat == HAL_PIXEL_FORMAT_RGBA_1010102);
}
sp<compositionengine::LayerFE> BufferLayer::getCompositionEngineLayerFE() const {
@@ -374,6 +374,12 @@
return true;
}
+void BufferLayer::gatherBufferInfo() {
+ mBufferInfo.mPixelFormat =
+ !mBufferInfo.mBuffer ? PIXEL_FORMAT_NONE : mBufferInfo.mBuffer->format;
+ mBufferInfo.mFrameLatencyNeeded = true;
+}
+
bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
nsecs_t expectedPresentTime) {
ATRACE_CALL();
@@ -434,7 +440,6 @@
gatherBufferInfo();
mRefreshPending = true;
- mBufferInfo.mFrameLatencyNeeded = true;
if (oldBufferInfo.mBuffer == nullptr) {
// the first time we receive a buffer, we need to trigger a
// geometry invalidation.
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index f678910..fbec6ee 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -161,7 +161,7 @@
Region mSurfaceDamage;
HdrMetadata mHdrMetadata;
int mApi;
- PixelFormat mPixelFormat;
+ PixelFormat mPixelFormat{PIXEL_FORMAT_NONE};
bool mTransformToDisplayInverse{false};
sp<GraphicBuffer> mBuffer;
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 4e5c593..c84b15d 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -525,8 +525,6 @@
return BAD_VALUE;
}
- mFormat = format;
-
setDefaultBufferSize(w, h);
mConsumer->setDefaultBufferFormat(format);
mConsumer->setConsumerUsageBits(getEffectiveUsage(0));
@@ -550,6 +548,8 @@
}
void BufferQueueLayer::gatherBufferInfo() {
+ BufferLayer::gatherBufferInfo();
+
mBufferInfo.mDesiredPresentTime = mConsumer->getTimestamp();
mBufferInfo.mFenceTime = mConsumer->getCurrentFenceTime();
mBufferInfo.mFence = mConsumer->getCurrentFence();
@@ -560,7 +560,6 @@
mBufferInfo.mSurfaceDamage = mConsumer->getSurfaceDamage();
mBufferInfo.mHdrMetadata = mConsumer->getCurrentHdrMetadata();
mBufferInfo.mApi = mConsumer->getCurrentApi();
- mBufferInfo.mPixelFormat = mFormat;
mBufferInfo.mTransformToDisplayInverse = mConsumer->getTransformToDisplayInverse();
}
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index 5f7587c..ea7f203 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -132,8 +132,6 @@
sp<BufferLayerConsumer> mConsumer;
sp<IGraphicBufferProducer> mProducer;
- PixelFormat mFormat{PIXEL_FORMAT_NONE};
-
bool mUpdateTexImageFailed{false};
uint64_t mPreviousBufferId = 0;
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 3ed6889..3e65171 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -718,8 +718,9 @@
}
void BufferStateLayer::gatherBufferInfo() {
- const State& s(getDrawingState());
+ BufferLayer::gatherBufferInfo();
+ const State& s(getDrawingState());
mBufferInfo.mDesiredPresentTime = s.desiredPresentTime;
mBufferInfo.mFenceTime = std::make_shared<FenceTime>(s.acquireFence);
mBufferInfo.mFence = s.acquireFence;
@@ -730,8 +731,6 @@
mBufferInfo.mSurfaceDamage = s.surfaceDamageRegion;
mBufferInfo.mHdrMetadata = s.hdrMetadata;
mBufferInfo.mApi = s.api;
- mBufferInfo.mPixelFormat =
- !mBufferInfo.mBuffer ? PIXEL_FORMAT_NONE : mBufferInfo.mBuffer->format;
mBufferInfo.mTransformToDisplayInverse = s.transformToDisplayInverse;
mBufferInfo.mBufferSlot = mHwcSlotGenerator->getHwcCacheSlot(s.clientCacheId);
}
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
index 02226ab..88f6649 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -45,6 +45,7 @@
MOCK_METHOD3(allocateVirtualDisplay,
std::optional<DisplayId>(uint32_t, uint32_t, ui::PixelFormat*));
+ MOCK_METHOD2(allocatePhysicalDisplay, void(hwc2_display_t, DisplayId));
MOCK_METHOD1(createLayer, HWC2::Layer*(DisplayId));
MOCK_METHOD2(destroyLayer, void(DisplayId, HWC2::Layer*));
MOCK_METHOD3(getDeviceCompositionChanges,
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index fb6c817..397fedc 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -183,9 +183,10 @@
struct Physical {
DisplayId id;
DisplayConnectionType type;
+ hwc2_display_t hwcDisplayId;
bool operator==(const Physical& other) const {
- return id == other.id && type == other.type;
+ return id == other.id && type == other.type && hwcDisplayId == other.hwcDisplayId;
}
};
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 1c1e113..560299a 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -205,56 +205,14 @@
std::optional<DisplayIdentificationInfo> HWComposer::onHotplug(hwc2_display_t hwcDisplayId,
HWC2::Connection connection) {
- std::optional<DisplayIdentificationInfo> info;
-
- if (const auto displayId = toPhysicalDisplayId(hwcDisplayId)) {
- info = DisplayIdentificationInfo{.id = *displayId,
- .name = std::string(),
- .deviceProductInfo = std::nullopt};
- } else {
- if (connection == HWC2::Connection::Disconnected) {
- ALOGE("Ignoring disconnection of invalid HWC display %" PRIu64, hwcDisplayId);
+ switch (connection) {
+ case HWC2::Connection::Connected:
+ return onHotplugConnect(hwcDisplayId);
+ case HWC2::Connection::Disconnected:
+ return onHotplugDisconnect(hwcDisplayId);
+ case HWC2::Connection::Invalid:
return {};
- }
-
- info = onHotplugConnect(hwcDisplayId);
- if (!info) return {};
}
-
- ALOGV("%s: %s %s display %s with HWC ID %" PRIu64, __FUNCTION__, to_string(connection).c_str(),
- hwcDisplayId == mInternalHwcDisplayId ? "internal" : "external",
- to_string(info->id).c_str(), hwcDisplayId);
-
- if (connection == HWC2::Connection::Connected) {
- auto& displayData = mDisplayData[info->id];
- // If we get a hotplug connected event for a display we already have,
- // destroy the display and recreate it. This will force us to requery
- // the display params and recreate all layers on that display.
- if (displayData.hwcDisplay != nullptr && displayData.hwcDisplay->isConnected()) {
- ALOGI("Hotplug connecting an already connected display."
- " Clearing old display state.");
- }
- displayData.hwcDisplay.reset();
- auto newDisplay =
- std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities, hwcDisplayId,
- HWC2::DisplayType::Physical);
- newDisplay->setConnected(true);
- displayData.hwcDisplay = std::move(newDisplay);
- mPhysicalDisplayIdMap[hwcDisplayId] = info->id;
- } else if (connection == HWC2::Connection::Disconnected) {
- // The display will later be destroyed by a call to
- // destroyDisplay(). For now we just mark it disconnected.
- auto& displayData = mDisplayData[info->id];
- if (displayData.hwcDisplay) {
- displayData.hwcDisplay->setConnected(false);
- } else {
- ALOGW("Attempted to disconnect unknown display %" PRIu64, hwcDisplayId);
- }
- // The cleanup of Disconnect is handled through HWComposer::disconnectDisplay
- // via SurfaceFlinger's onHotplugReceived callback handling
- }
-
- return info;
}
bool HWComposer::onVsync(hwc2_display_t hwcDisplayId, int64_t timestamp) {
@@ -337,6 +295,22 @@
return displayId;
}
+void HWComposer::allocatePhysicalDisplay(hwc2_display_t hwcDisplayId, DisplayId displayId) {
+ if (!mInternalHwcDisplayId) {
+ mInternalHwcDisplayId = hwcDisplayId;
+ } else if (mInternalHwcDisplayId != hwcDisplayId && !mExternalHwcDisplayId) {
+ mExternalHwcDisplayId = hwcDisplayId;
+ }
+
+ auto& displayData = mDisplayData[displayId];
+ auto newDisplay =
+ std::make_unique<HWC2::impl::Display>(*mComposer.get(), mCapabilities, hwcDisplayId,
+ HWC2::DisplayType::Physical);
+ newDisplay->setConnected(true);
+ displayData.hwcDisplay = std::move(newDisplay);
+ mPhysicalDisplayIdMap[hwcDisplayId] = displayId;
+}
+
HWC2::Layer* HWComposer::createLayer(DisplayId displayId) {
RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
@@ -911,52 +885,93 @@
return {};
}
-std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(hwc2_display_t hwcDisplayId) {
+bool HWComposer::shouldIgnoreHotplugConnect(hwc2_display_t hwcDisplayId,
+ bool hasDisplayIdentificationData) const {
if (isUsingVrComposer() && mInternalHwcDisplayId) {
ALOGE("Ignoring connection of external display %" PRIu64 " in VR mode", hwcDisplayId);
- return {};
+ return true;
}
- uint8_t port;
- DisplayIdentificationData data;
- const bool hasMultiDisplaySupport = getDisplayIdentificationData(hwcDisplayId, &port, &data);
-
- if (mPhysicalDisplayIdMap.empty()) {
- mHasMultiDisplaySupport = hasMultiDisplaySupport;
- ALOGI("Switching to %s multi-display mode",
- hasMultiDisplaySupport ? "generalized" : "legacy");
- } else if (mHasMultiDisplaySupport && !hasMultiDisplaySupport) {
+ if (mHasMultiDisplaySupport && !hasDisplayIdentificationData) {
ALOGE("Ignoring connection of display %" PRIu64 " without identification data",
hwcDisplayId);
- return {};
+ return true;
}
- std::optional<DisplayIdentificationInfo> info;
-
- if (mHasMultiDisplaySupport) {
- info = parseDisplayIdentificationData(port, data);
- ALOGE_IF(!info, "Failed to parse identification data for display %" PRIu64, hwcDisplayId);
- } else if (mInternalHwcDisplayId && mExternalHwcDisplayId) {
+ if (!mHasMultiDisplaySupport && mInternalHwcDisplayId && mExternalHwcDisplayId) {
ALOGE("Ignoring connection of tertiary display %" PRIu64, hwcDisplayId);
- return {};
+ return true;
+ }
+
+ return false;
+}
+
+std::optional<DisplayIdentificationInfo> HWComposer::onHotplugConnect(hwc2_display_t hwcDisplayId) {
+ std::optional<DisplayIdentificationInfo> info;
+ if (const auto displayId = toPhysicalDisplayId(hwcDisplayId)) {
+ info = DisplayIdentificationInfo{.id = *displayId,
+ .name = std::string(),
+ .deviceProductInfo = std::nullopt};
} else {
- ALOGW_IF(hasMultiDisplaySupport, "Ignoring identification data for display %" PRIu64,
- hwcDisplayId);
- port = mInternalHwcDisplayId ? HWC_DISPLAY_EXTERNAL : HWC_DISPLAY_PRIMARY;
+ uint8_t port;
+ DisplayIdentificationData data;
+ const bool hasDisplayIdentificationData =
+ getDisplayIdentificationData(hwcDisplayId, &port, &data);
+ if (mPhysicalDisplayIdMap.empty()) {
+ mHasMultiDisplaySupport = hasDisplayIdentificationData;
+ ALOGI("Switching to %s multi-display mode",
+ mHasMultiDisplaySupport ? "generalized" : "legacy");
+ }
+
+ if (shouldIgnoreHotplugConnect(hwcDisplayId, hasDisplayIdentificationData)) {
+ return {};
+ }
+
+ info = [this, hwcDisplayId, &port, &data, hasDisplayIdentificationData] {
+ const bool isPrimary = !mInternalHwcDisplayId;
+ if (mHasMultiDisplaySupport) {
+ if (const auto info = parseDisplayIdentificationData(port, data)) {
+ return *info;
+ }
+ ALOGE("Failed to parse identification data for display %" PRIu64, hwcDisplayId);
+ } else {
+ ALOGW_IF(hasDisplayIdentificationData,
+ "Ignoring identification data for display %" PRIu64, hwcDisplayId);
+ port = isPrimary ? HWC_DISPLAY_PRIMARY : HWC_DISPLAY_EXTERNAL;
+ }
+
+ return DisplayIdentificationInfo{.id = getFallbackDisplayId(port),
+ .name = isPrimary ? "Internal display"
+ : "External display",
+ .deviceProductInfo = std::nullopt};
+ }();
}
- if (!mInternalHwcDisplayId) {
- mInternalHwcDisplayId = hwcDisplayId;
- } else if (!mExternalHwcDisplayId) {
- mExternalHwcDisplayId = hwcDisplayId;
+ if (!isConnected(info->id)) {
+ allocatePhysicalDisplay(hwcDisplayId, info->id);
+ }
+ return info;
+}
+
+std::optional<DisplayIdentificationInfo> HWComposer::onHotplugDisconnect(
+ hwc2_display_t hwcDisplayId) {
+ const auto displayId = toPhysicalDisplayId(hwcDisplayId);
+ if (!displayId) {
+ ALOGE("Ignoring disconnection of invalid HWC display %" PRIu64, hwcDisplayId);
+ return {};
}
- if (info) return info;
-
- return DisplayIdentificationInfo{.id = getFallbackDisplayId(port),
- .name = hwcDisplayId == mInternalHwcDisplayId
- ? "Internal display"
- : "External display",
+ // The display will later be destroyed by a call to
+ // destroyDisplay(). For now we just mark it disconnected.
+ if (isConnected(*displayId)) {
+ mDisplayData[*displayId].hwcDisplay->setConnected(false);
+ } else {
+ ALOGW("Attempted to disconnect unknown display %" PRIu64, hwcDisplayId);
+ }
+ // The cleanup of Disconnect is handled through HWComposer::disconnectDisplay
+ // via SurfaceFlinger's onHotplugReceived callback handling
+ return DisplayIdentificationInfo{.id = *displayId,
+ .name = std::string(),
.deviceProductInfo = std::nullopt};
}
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 41db501..3cb40b1 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -77,6 +77,8 @@
virtual std::optional<DisplayId> allocateVirtualDisplay(uint32_t width, uint32_t height,
ui::PixelFormat* format) = 0;
+ virtual void allocatePhysicalDisplay(hwc2_display_t hwcDisplayId, DisplayId displayId) = 0;
+
// Attempts to create a new layer on this display
virtual HWC2::Layer* createLayer(DisplayId displayId) = 0;
// Destroy a previously created layer
@@ -164,6 +166,7 @@
// Returns stable display ID (and display name on connection of new or previously disconnected
// display), or std::nullopt if hotplug event was ignored.
+ // This function is called from SurfaceFlinger.
virtual std::optional<DisplayIdentificationInfo> onHotplug(hwc2_display_t hwcDisplayId,
HWC2::Connection connection) = 0;
@@ -238,6 +241,9 @@
std::optional<DisplayId> allocateVirtualDisplay(uint32_t width, uint32_t height,
ui::PixelFormat* format) override;
+ // Called from SurfaceFlinger, when the state for a new physical display needs to be recreated.
+ void allocatePhysicalDisplay(hwc2_display_t hwcDisplayId, DisplayId displayId) override;
+
// Attempts to create a new layer on this display
HWC2::Layer* createLayer(DisplayId displayId) override;
// Destroy a previously created layer
@@ -361,6 +367,10 @@
friend TestableSurfaceFlinger;
std::optional<DisplayIdentificationInfo> onHotplugConnect(hwc2_display_t hwcDisplayId);
+ std::optional<DisplayIdentificationInfo> onHotplugDisconnect(hwc2_display_t hwcDisplayId);
+ bool shouldIgnoreHotplugConnect(hwc2_display_t hwcDisplayId,
+ bool hasDisplayIdentificationData) const;
+
void loadCapabilities();
void loadLayerMetadataSupport();
uint32_t getMaxVirtualDisplayCount() const;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 2da92b3..880be28 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2385,7 +2385,8 @@
}
DisplayDeviceState state;
- state.physical = {displayId, getHwComposer().getDisplayConnectionType(displayId)};
+ state.physical = {displayId, getHwComposer().getDisplayConnectionType(displayId),
+ event.hwcDisplayId};
state.isSecure = true; // All physical displays are currently considered secure.
state.displayName = info->name;
@@ -2394,6 +2395,12 @@
mPhysicalDisplayTokens.emplace(displayId, std::move(token));
mInterceptor->saveDisplayCreation(state);
+ } else {
+ ALOGV("Recreating display %s", to_string(displayId).c_str());
+
+ const auto token = it->second;
+ auto& state = mCurrentState.displays.editValueFor(token);
+ state.sequenceId = DisplayDeviceState{}.sequenceId;
}
} else {
ALOGV("Removing display %s", to_string(displayId).c_str());
@@ -2571,20 +2578,17 @@
producer = bqProducer;
}
- if (displaySurface != nullptr) {
- mDisplays.emplace(displayToken,
- setupNewDisplayDeviceInternal(displayToken, compositionDisplay, state,
- displaySurface, producer));
- if (!state.isVirtual()) {
- LOG_ALWAYS_FATAL_IF(!displayId);
- dispatchDisplayHotplugEvent(displayId->value, true);
- }
+ LOG_FATAL_IF(!displaySurface);
+ const auto display = setupNewDisplayDeviceInternal(displayToken, compositionDisplay, state,
+ displaySurface, producer);
+ mDisplays.emplace(displayToken, display);
+ if (!state.isVirtual()) {
+ LOG_FATAL_IF(!displayId);
+ dispatchDisplayHotplugEvent(displayId->value, true);
+ }
- const auto displayDevice = mDisplays[displayToken];
- if (displayDevice->isPrimary()) {
- mScheduler->onPrimaryDisplayAreaChanged(displayDevice->getWidth() *
- displayDevice->getHeight());
- }
+ if (display->isPrimary()) {
+ mScheduler->onPrimaryDisplayAreaChanged(display->getWidth() * display->getHeight());
}
}
@@ -2595,7 +2599,7 @@
display->disconnect();
if (!display->isVirtual()) {
- LOG_ALWAYS_FATAL_IF(!displayId);
+ LOG_FATAL_IF(!displayId);
dispatchDisplayHotplugEvent(displayId->value, false);
}
}
@@ -2608,13 +2612,19 @@
const DisplayDeviceState& drawingState) {
const sp<IBinder> currentBinder = IInterface::asBinder(currentState.surface);
const sp<IBinder> drawingBinder = IInterface::asBinder(drawingState.surface);
- if (currentBinder != drawingBinder) {
+ if (currentBinder != drawingBinder || currentState.sequenceId != drawingState.sequenceId) {
// changing the surface is like destroying and recreating the DisplayDevice
if (const auto display = getDisplayDeviceLocked(displayToken)) {
display->disconnect();
}
mDisplays.erase(displayToken);
+ if (const auto& physical = currentState.physical) {
+ getHwComposer().allocatePhysicalDisplay(physical->hwcDisplayId, physical->id);
+ }
processDisplayAdded(displayToken, currentState);
+ if (currentState.physical) {
+ initializeDisplays();
+ }
return;
}
@@ -4132,6 +4142,9 @@
}
if (currentMode == HWC_POWER_MODE_OFF) {
+ if (SurfaceFlinger::setSchedFifo(true) != NO_ERROR) {
+ ALOGW("Couldn't set SCHED_FIFO on display on: %s\n", strerror(errno));
+ }
getHwComposer().setPowerMode(*displayId, mode);
if (display->isPrimary() && mode != HWC_POWER_MODE_DOZE_SUSPEND) {
setVsyncEnabledInHWC(*displayId, mHWCVsyncPendingState);
@@ -4142,19 +4155,11 @@
mVisibleRegionsDirty = true;
mHasPoweredOff = true;
repaintEverything();
-
- struct sched_param param = {0};
- param.sched_priority = 1;
- if (sched_setscheduler(0, SCHED_FIFO, ¶m) != 0) {
- ALOGW("Couldn't set SCHED_FIFO on display on");
- }
} else if (mode == HWC_POWER_MODE_OFF) {
// Turn off the display
- struct sched_param param = {0};
- if (sched_setscheduler(0, SCHED_OTHER, ¶m) != 0) {
- ALOGW("Couldn't set SCHED_OTHER on display off");
+ if (SurfaceFlinger::setSchedFifo(false) != NO_ERROR) {
+ ALOGW("Couldn't set SCHED_OTHER on display off: %s\n", strerror(errno));
}
-
if (display->isPrimary() && currentMode != HWC_POWER_MODE_DOZE_SUSPEND) {
mScheduler->disableHardwareVsync(true);
mScheduler->onScreenReleased(mAppConnectionHandle);
@@ -5341,6 +5346,26 @@
}
}
+status_t SurfaceFlinger::setSchedFifo(bool enabled) {
+ static constexpr int kFifoPriority = 2;
+ static constexpr int kOtherPriority = 0;
+
+ struct sched_param param = {0};
+ int sched_policy;
+ if (enabled) {
+ sched_policy = SCHED_FIFO;
+ param.sched_priority = kFifoPriority;
+ } else {
+ sched_policy = SCHED_OTHER;
+ param.sched_priority = kOtherPriority;
+ }
+
+ if (sched_setscheduler(0, sched_policy, ¶m) != 0) {
+ return -errno;
+ }
+ return NO_ERROR;
+}
+
const sp<DisplayDevice> SurfaceFlinger::getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) {
const sp<IBinder> displayToken = getPhysicalDisplayTokenLocked(DisplayId{displayOrLayerStack});
if (displayToken) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 6ab1fcf..60904f6 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -259,6 +259,9 @@
// overhead that is caused by reading from sysprop.
static bool useFrameRateApi;
+ // set main thread scheduling policy
+ static status_t setSchedFifo(bool enabled) ANDROID_API;
+
static char const* getServiceName() ANDROID_API {
return "SurfaceFlinger";
}
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index 5b3cd69..80102bd 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -194,7 +194,7 @@
Increment* SurfaceInterceptor::createTraceIncrementLocked() {
Increment* increment(mTrace.add_increment());
- increment->set_time_stamp(systemTime());
+ increment->set_time_stamp(elapsedRealtimeNano());
return increment;
}
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index d7ad9de..2b8424c 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -31,6 +31,7 @@
#include <binder/ProcessState.h>
#include <configstore/Utils.h>
#include <displayservice/DisplayService.h>
+#include <errno.h>
#include <hidl/LegacySupport.h>
#include <processgroup/sched_policy.h>
#include "SurfaceFlinger.h"
@@ -114,10 +115,8 @@
startDisplayService(); // dependency on SF getting registered above
- struct sched_param param = {0};
- param.sched_priority = 2;
- if (sched_setscheduler(0, SCHED_FIFO, ¶m) != 0) {
- ALOGE("Couldn't set SCHED_FIFO");
+ if (SurfaceFlinger::setSchedFifo(true) != NO_ERROR) {
+ ALOGW("Couldn't set to SCHED_FIFO: %s", strerror(errno));
}
// run surface flinger in this thread
diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h
index 932c7c8..40ec502 100644
--- a/services/surfaceflinger/tests/LayerTransactionTest.h
+++ b/services/surfaceflinger/tests/LayerTransactionTest.h
@@ -52,9 +52,10 @@
virtual sp<SurfaceControl> createLayer(const sp<SurfaceComposerClient>& client,
const char* name, uint32_t width, uint32_t height,
uint32_t flags = 0, SurfaceControl* parent = nullptr,
- uint32_t* outTransformHint = nullptr) {
- auto layer = createSurface(client, name, width, height, PIXEL_FORMAT_RGBA_8888, flags,
- parent, outTransformHint);
+ uint32_t* outTransformHint = nullptr,
+ PixelFormat format = PIXEL_FORMAT_RGBA_8888) {
+ auto layer =
+ createSurface(client, name, width, height, format, flags, parent, outTransformHint);
Transaction t;
t.setLayerStack(layer, mDisplayLayerStack).setLayer(layer, mLayerZBase);
@@ -81,8 +82,9 @@
virtual sp<SurfaceControl> createLayer(const char* name, uint32_t width, uint32_t height,
uint32_t flags = 0, SurfaceControl* parent = nullptr,
- uint32_t* outTransformHint = nullptr) {
- return createLayer(mClient, name, width, height, flags, parent, outTransformHint);
+ uint32_t* outTransformHint = nullptr,
+ PixelFormat format = PIXEL_FORMAT_RGBA_8888) {
+ return createLayer(mClient, name, width, height, flags, parent, outTransformHint, format);
}
sp<SurfaceControl> createColorLayer(const char* name, const Color& color,
diff --git a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp
index 2fd2579..d666d7e 100644
--- a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp
+++ b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp
@@ -365,6 +365,67 @@
getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED);
}
}
+
+TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBufferFormat) {
+ int32_t width = 100;
+ int32_t height = 100;
+ Rect crop = Rect(0, 0, width, height);
+
+ sp<SurfaceControl> behindLayer = createColorLayer("Behind layer", Color::RED);
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", width, height, 0, nullptr, nullptr,
+ PIXEL_FORMAT_RGBX_8888));
+
+ Transaction()
+ .setLayer(layer, INT32_MAX - 1)
+ .show(layer)
+ .setLayerStack(behindLayer, mDisplayLayerStack)
+ .setCrop_legacy(behindLayer, crop)
+ .setLayer(behindLayer, INT32_MAX - 2)
+ .show(behindLayer)
+ .apply();
+
+ sp<Surface> surface = layer->getSurface();
+
+ sp<GraphicBuffer> buffer =
+ new GraphicBuffer(width, height, PIXEL_FORMAT_RGBX_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+ ASSERT_NO_FATAL_FAILURE(
+ TransactionUtils::fillGraphicBufferColor(buffer, crop, Color::TRANSPARENT));
+
+ if (mLayerType == ISurfaceComposerClient::eFXSurfaceBufferQueue) {
+ Surface::attachAndQueueBufferWithDataspace(surface.get(), buffer, ui::Dataspace::V0_SRGB);
+ } else {
+ Transaction().setBuffer(layer, buffer).apply();
+ }
+
+ {
+ SCOPED_TRACE("Buffer Opaque Format");
+ auto shot = screenshot();
+ shot->expectColor(crop, Color::BLACK);
+ }
+
+ buffer = new GraphicBuffer(width, height, PIXEL_FORMAT_RGBA_8888, 1,
+ BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+ BufferUsage::COMPOSER_OVERLAY,
+ "test");
+ ASSERT_NO_FATAL_FAILURE(
+ TransactionUtils::fillGraphicBufferColor(buffer, crop, Color::TRANSPARENT));
+
+ if (mLayerType == ISurfaceComposerClient::eFXSurfaceBufferQueue) {
+ Surface::attachAndQueueBufferWithDataspace(surface.get(), buffer, ui::Dataspace::V0_SRGB);
+ } else {
+ Transaction().setBuffer(layer, buffer).apply();
+ }
+
+ {
+ SCOPED_TRACE("Buffer Transparent Format");
+ auto shot = screenshot();
+ shot->expectColor(crop, Color::RED);
+ }
+}
} // namespace android
// TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/tests/TransactionTestHarnesses.h b/services/surfaceflinger/tests/TransactionTestHarnesses.h
index 040852f..f0af363 100644
--- a/services/surfaceflinger/tests/TransactionTestHarnesses.h
+++ b/services/surfaceflinger/tests/TransactionTestHarnesses.h
@@ -88,13 +88,14 @@
sp<SurfaceControl> createLayer(const char* name, uint32_t width, uint32_t height,
uint32_t flags = 0, SurfaceControl* parent = nullptr,
- uint32_t* outTransformHint = nullptr) {
+ uint32_t* outTransformHint = nullptr,
+ PixelFormat format = PIXEL_FORMAT_RGBA_8888) {
// if the flags already have a layer type specified, return an error
if (flags & ISurfaceComposerClient::eFXSurfaceMask) {
return nullptr;
}
return LayerTransactionTest::createLayer(name, width, height, flags | mLayerType, parent,
- outTransformHint);
+ outTransformHint, format);
}
void fillLayerColor(const sp<SurfaceControl>& layer, const Color& color, int32_t bufferWidth,
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 680b0a0..2dcaf63 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -305,14 +305,14 @@
compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(),
ceDisplayArgs);
- test->mDisplay =
- FakeDisplayDeviceInjector(test->mFlinger, compositionDisplay,
- DisplayConnectionType::Internal, true /* isPrimary */)
- .setDisplaySurface(test->mDisplaySurface)
- .setNativeWindow(test->mNativeWindow)
- .setSecure(Derived::IS_SECURE)
- .setPowerMode(Derived::INIT_POWER_MODE)
- .inject();
+ test->mDisplay = FakeDisplayDeviceInjector(test->mFlinger, compositionDisplay,
+ DisplayConnectionType::Internal, HWC_DISPLAY,
+ true /* isPrimary */)
+ .setDisplaySurface(test->mDisplaySurface)
+ .setNativeWindow(test->mNativeWindow)
+ .setSecure(Derived::IS_SECURE)
+ .setPowerMode(Derived::INIT_POWER_MODE)
+ .inject();
Mock::VerifyAndClear(test->mNativeWindow);
test->mDisplay->setLayerStack(DEFAULT_LAYER_STACK);
}
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 6d00ccc..24eeac7 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -246,6 +246,7 @@
constexpr DisplayId DEFAULT_DISPLAY_ID = DisplayId{777};
constexpr int DEFAULT_DISPLAY_WIDTH = 1080;
constexpr int DEFAULT_DISPLAY_HEIGHT = 1920;
+ constexpr hwc2_display_t DEFAULT_DISPLAY_HWC_DISPLAY_ID = 0;
// The DisplayDevice is required to have a framebuffer (behind the
// ANativeWindow interface) which uses the actual hardware display
@@ -270,7 +271,7 @@
auto injector =
FakeDisplayDeviceInjector(mFlinger, compositionDisplay, DisplayConnectionType::Internal,
- true /* isPrimary */);
+ DEFAULT_DISPLAY_HWC_DISPLAY_ID, true /* isPrimary */);
injector.setNativeWindow(mNativeWindow);
if (injectExtra) {
@@ -373,6 +374,23 @@
static constexpr std::optional<DisplayConnectionType> value = PhysicalDisplay::CONNECTION_TYPE;
};
+template <typename>
+struct HwcDisplayIdGetter {
+ static constexpr std::optional<hwc2_display_t> value;
+};
+
+constexpr hwc2_display_t HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID = 1010;
+
+template <DisplayId::Type displayId>
+struct HwcDisplayIdGetter<VirtualDisplayId<displayId>> {
+ static constexpr std::optional<hwc2_display_t> value = HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID;
+};
+
+template <typename PhysicalDisplay>
+struct HwcDisplayIdGetter<PhysicalDisplayId<PhysicalDisplay>> {
+ static constexpr std::optional<hwc2_display_t> value = PhysicalDisplay::HWC_DISPLAY_ID;
+};
+
// DisplayIdType can be:
// 1) PhysicalDisplayId<...> for generated ID of physical display backed by HWC.
// 2) VirtualDisplayId<...> for hard-coded ID of virtual display backed by HWC.
@@ -382,6 +400,7 @@
struct DisplayVariant {
using DISPLAY_ID = DisplayIdGetter<DisplayIdType>;
using CONNECTION_TYPE = DisplayConnectionTypeGetter<DisplayIdType>;
+ using HWC_DISPLAY_ID_OPT = HwcDisplayIdGetter<DisplayIdType>;
// The display width and height
static constexpr int WIDTH = width;
@@ -418,9 +437,9 @@
compositionengine::impl::createDisplay(test->mFlinger.getCompositionEngine(),
ceDisplayArgs.build());
- auto injector =
- FakeDisplayDeviceInjector(test->mFlinger, compositionDisplay,
- CONNECTION_TYPE::value, static_cast<bool>(PRIMARY));
+ auto injector = FakeDisplayDeviceInjector(test->mFlinger, compositionDisplay,
+ CONNECTION_TYPE::value, HWC_DISPLAY_ID_OPT::value,
+ static_cast<bool>(PRIMARY));
injector.setSecure(static_cast<bool>(SECURE));
injector.setNativeWindow(test->mNativeWindow);
@@ -603,12 +622,11 @@
constexpr uint32_t GRALLOC_USAGE_PHYSICAL_DISPLAY =
GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_FB;
-template <hwc2_display_t hwcDisplayId, typename PhysicalDisplay, int width, int height,
- Critical critical>
+template <typename PhysicalDisplay, int width, int height, Critical critical>
struct PhysicalDisplayVariant
: DisplayVariant<PhysicalDisplayId<PhysicalDisplay>, width, height, critical, Async::FALSE,
Secure::TRUE, PhysicalDisplay::PRIMARY, GRALLOC_USAGE_PHYSICAL_DISPLAY>,
- HwcDisplayVariant<hwcDisplayId, HWC2::DisplayType::Physical,
+ HwcDisplayVariant<PhysicalDisplay::HWC_DISPLAY_ID, HWC2::DisplayType::Physical,
DisplayVariant<PhysicalDisplayId<PhysicalDisplay>, width, height,
critical, Async::FALSE, Secure::TRUE,
PhysicalDisplay::PRIMARY, GRALLOC_USAGE_PHYSICAL_DISPLAY>,
@@ -619,6 +637,7 @@
static constexpr auto CONNECTION_TYPE = DisplayConnectionType::Internal;
static constexpr Primary PRIMARY = Primary::TRUE;
static constexpr uint8_t PORT = 255;
+ static constexpr hwc2_display_t HWC_DISPLAY_ID = 1001;
static constexpr bool HAS_IDENTIFICATION_DATA = hasIdentificationData;
static constexpr auto GET_IDENTIFICATION_DATA = getInternalEdid;
};
@@ -628,6 +647,7 @@
static constexpr auto CONNECTION_TYPE = DisplayConnectionType::External;
static constexpr Primary PRIMARY = Primary::FALSE;
static constexpr uint8_t PORT = 254;
+ static constexpr hwc2_display_t HWC_DISPLAY_ID = 1002;
static constexpr bool HAS_IDENTIFICATION_DATA = hasIdentificationData;
static constexpr auto GET_IDENTIFICATION_DATA = getExternalEdid;
};
@@ -635,19 +655,19 @@
struct TertiaryDisplay {
static constexpr Primary PRIMARY = Primary::FALSE;
static constexpr uint8_t PORT = 253;
+ static constexpr hwc2_display_t HWC_DISPLAY_ID = 1003;
static constexpr auto GET_IDENTIFICATION_DATA = getExternalEdid;
};
// A primary display is a physical display that is critical
using PrimaryDisplayVariant =
- PhysicalDisplayVariant<1001, PrimaryDisplay<false>, 3840, 2160, Critical::TRUE>;
+ PhysicalDisplayVariant<PrimaryDisplay<false>, 3840, 2160, Critical::TRUE>;
// An external display is physical display that is not critical.
using ExternalDisplayVariant =
- PhysicalDisplayVariant<1002, ExternalDisplay<false>, 1920, 1280, Critical::FALSE>;
+ PhysicalDisplayVariant<ExternalDisplay<false>, 1920, 1280, Critical::FALSE>;
-using TertiaryDisplayVariant =
- PhysicalDisplayVariant<1003, TertiaryDisplay, 1600, 1200, Critical::FALSE>;
+using TertiaryDisplayVariant = PhysicalDisplayVariant<TertiaryDisplay, 1600, 1200, Critical::FALSE>;
// A virtual display not supported by the HWC.
constexpr uint32_t GRALLOC_USAGE_NONHWC_VIRTUAL_DISPLAY = 0;
@@ -696,7 +716,7 @@
: DisplayVariant<VirtualDisplayId<42>, width, height, Critical::FALSE, Async::TRUE, secure,
Primary::FALSE, GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY>,
HwcDisplayVariant<
- 1010, HWC2::DisplayType::Virtual,
+ HWC_VIRTUAL_DISPLAY_HWC_DISPLAY_ID, HWC2::DisplayType::Virtual,
DisplayVariant<VirtualDisplayId<42>, width, height, Critical::FALSE, Async::TRUE,
secure, Primary::FALSE, GRALLOC_USAGE_HWC_VIRTUAL_DISPLAY>> {
using Base = DisplayVariant<VirtualDisplayId<42>, width, height, Critical::FALSE, Async::TRUE,
@@ -1767,7 +1787,9 @@
if (const auto connectionType = Case::Display::CONNECTION_TYPE::value) {
const auto displayId = Case::Display::DISPLAY_ID::get();
ASSERT_TRUE(displayId);
- state.physical = {*displayId, *connectionType};
+ const auto hwcDisplayId = Case::Display::HWC_DISPLAY_ID_OPT::value;
+ ASSERT_TRUE(hwcDisplayId);
+ state.physical = {*displayId, *connectionType, *hwcDisplayId};
}
state.isSecure = static_cast<bool>(Case::Display::SECURE);
@@ -1941,7 +1963,9 @@
if (const auto connectionType = Case::Display::CONNECTION_TYPE::value) {
const auto displayId = Case::Display::DISPLAY_ID::get();
ASSERT_TRUE(displayId);
- expectedPhysical = {*displayId, *connectionType};
+ const auto hwcDisplayId = Case::Display::HWC_DISPLAY_ID_OPT::value;
+ ASSERT_TRUE(hwcDisplayId);
+ expectedPhysical = {*displayId, *connectionType, *hwcDisplayId};
}
// The display should have been set up in the current display state
@@ -2124,11 +2148,11 @@
ignoresHotplugConnectCommon<SimpleExternalDisplayCase>();
}
-TEST_F(HandleTransactionLockedTest, processHotplugDisconnectPrimaryDisplay) {
+TEST_F(HandleTransactionLockedTest, processesHotplugDisconnectPrimaryDisplay) {
processesHotplugDisconnectCommon<SimplePrimaryDisplayCase>();
}
-TEST_F(HandleTransactionLockedTest, processHotplugDisconnectExternalDisplay) {
+TEST_F(HandleTransactionLockedTest, processesHotplugDisconnectExternalDisplay) {
processesHotplugDisconnectCommon<SimpleExternalDisplayCase>();
}
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 414085c..058c5cc 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -549,9 +549,10 @@
FakeDisplayDeviceInjector(TestableSurfaceFlinger& flinger,
std::shared_ptr<compositionengine::Display> compositionDisplay,
std::optional<DisplayConnectionType> connectionType,
- bool isPrimary)
+ std::optional<hwc2_display_t> hwcDisplayId, bool isPrimary)
: mFlinger(flinger),
- mCreationArgs(flinger.mFlinger.get(), mDisplayToken, compositionDisplay) {
+ mCreationArgs(flinger.mFlinger.get(), mDisplayToken, compositionDisplay),
+ mHwcDisplayId(hwcDisplayId) {
mCreationArgs.connectionType = connectionType;
mCreationArgs.isPrimary = isPrimary;
}
@@ -619,7 +620,8 @@
DisplayDeviceState state;
if (const auto type = mCreationArgs.connectionType) {
LOG_ALWAYS_FATAL_IF(!displayId);
- state.physical = {*displayId, *type};
+ LOG_ALWAYS_FATAL_IF(!mHwcDisplayId);
+ state.physical = {*displayId, *type, *mHwcDisplayId};
}
state.isSecure = mCreationArgs.isSecure;
@@ -640,6 +642,7 @@
TestableSurfaceFlinger& mFlinger;
sp<BBinder> mDisplayToken = new BBinder();
DisplayDeviceCreationArgs mCreationArgs;
+ const std::optional<hwc2_display_t> mHwcDisplayId;
};
surfaceflinger::test::Factory mFactory;