diff options
| author | 2024-11-09 02:18:44 +0000 | |
|---|---|---|
| committer | 2024-11-09 02:18:44 +0000 | |
| commit | ea330cacbc0f50547ed8b9bbfe93c052402e3917 (patch) | |
| tree | 2d22e341385e7a4cd623cda9c051ff33751df625 | |
| parent | 5218ed04b5224e5d304cac70e0543f00a9b4fec3 (diff) | |
| parent | 28c8e155fd3f8dc9c133f435b89af4288b4435f7 (diff) | |
Snap for 12630846 from 28c8e155fd3f8dc9c133f435b89af4288b4435f7 to 25Q1-release
Change-Id: I1e25e09c817d53bc7d58d9283d8b9e61e2a077ee
30 files changed, 747 insertions, 265 deletions
diff --git a/include/android/keycodes.h b/include/android/keycodes.h index 79cdbcaf7b..495e0bdb1f 100644 --- a/include/android/keycodes.h +++ b/include/android/keycodes.h @@ -843,6 +843,44 @@ enum { AKEYCODE_EMOJI_PICKER = 317, /** Take Screenshot */ AKEYCODE_SCREENSHOT = 318, + /** To start dictate to an input field */ + AKEYCODE_DICTATE = 319, + /** AC New */ + AKEYCODE_NEW = 320, + /** AC Close */ + AKEYCODE_CLOSE = 321, + /** To toggle 'Do Not Disturb' mode */ + AKEYCODE_DO_NOT_DISTURB = 322, + /** To Print */ + AKEYCODE_PRINT = 323, + /** To Lock the screen */ + AKEYCODE_LOCK = 324, + /** To toggle fullscreen mode (on the current application) */ + AKEYCODE_FULLSCREEN = 325, + /** F13 key */ + AKEYCODE_F13 = 326, + /** F14 key */ + AKEYCODE_F14 = 327, + /** F15 key */ + AKEYCODE_F15 = 328, + /** F16 key */ + AKEYCODE_F16 = 329, + /** F17 key */ + AKEYCODE_F17 = 330, + /** F18 key */ + AKEYCODE_F18 = 331, + /** F19 key */ + AKEYCODE_F19 = 332, + /** F20 key */ + AKEYCODE_F20 = 333, + /** F21 key */ + AKEYCODE_F21 = 334, + /** F22 key */ + AKEYCODE_F22 = 335, + /** F23 key */ + AKEYCODE_F23 = 336, + /** F24 key */ + AKEYCODE_F24 = 337, // NOTE: If you add a new keycode here you must also add it to several other files. // Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list. diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 3260c53a62..c97dfd4cda 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -2129,13 +2129,13 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::notifyPr } SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInputWindowInfo( - const sp<SurfaceControl>& sc, const WindowInfo& info) { + const sp<SurfaceControl>& sc, sp<WindowInfoHandle> info) { layer_state_t* s = getLayerState(sc); if (!s) { mStatus = BAD_INDEX; return *this; } - s->windowInfoHandle = new WindowInfoHandle(info); + s->windowInfoHandle = std::move(info); s->what |= layer_state_t::eInputInfoChanged; return *this; } diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index e9262b3870..7c6b3416f8 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -687,7 +687,8 @@ public: // ONLY FOR BLAST ADAPTER Transaction& notifyProducerDisconnect(const sp<SurfaceControl>& sc); - Transaction& setInputWindowInfo(const sp<SurfaceControl>& sc, const gui::WindowInfo& info); + Transaction& setInputWindowInfo(const sp<SurfaceControl>& sc, + sp<gui::WindowInfoHandle> info); Transaction& setFocusedWindow(const gui::FocusRequest& request); Transaction& addWindowInfosReportedListener( diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp index 17630e304f..0e84d68eec 100644 --- a/libs/gui/tests/EndToEndNativeInputTest.cpp +++ b/libs/gui/tests/EndToEndNativeInputTest.cpp @@ -112,7 +112,7 @@ public: mInputFlinger = getInputFlinger(); if (noInputChannel) { - mInputInfo.setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, true); + mInputInfo->editInfo()->setInputConfig(WindowInfo::InputConfig::NO_INPUT_CHANNEL, true); } else { android::os::InputChannelCore tempChannel; android::binder::Status result = @@ -121,21 +121,21 @@ public: ADD_FAILURE() << "binder call to createInputChannel failed"; } mClientChannel = InputChannel::create(std::move(tempChannel)); - mInputInfo.token = mClientChannel->getConnectionToken(); + mInputInfo->editInfo()->token = mClientChannel->getConnectionToken(); mInputConsumer = new InputConsumer(mClientChannel); } - mInputInfo.name = "Test info"; - mInputInfo.dispatchingTimeout = 5s; - mInputInfo.globalScaleFactor = 1.0; - mInputInfo.touchableRegion.orSelf(Rect(0, 0, width, height)); + mInputInfo->editInfo()->name = "Test info"; + mInputInfo->editInfo()->dispatchingTimeout = 5s; + mInputInfo->editInfo()->globalScaleFactor = 1.0; + mInputInfo->editInfo()->touchableRegion.orSelf(Rect(0, 0, width, height)); InputApplicationInfo aInfo; aInfo.token = new BBinder(); aInfo.name = "Test app info"; aInfo.dispatchingTimeoutMillis = std::chrono::duration_cast<std::chrono::milliseconds>(DISPATCHING_TIMEOUT).count(); - mInputInfo.applicationInfo = aInfo; + mInputInfo->editInfo()->applicationInfo = aInfo; } static std::unique_ptr<InputSurface> makeColorInputSurface(const sp<SurfaceComposerClient>& scc, @@ -183,20 +183,6 @@ public: return std::make_unique<InputSurface>(surfaceControl, width, height); } - InputEvent* consumeEvent(std::chrono::milliseconds timeout = 3000ms) { - mClientChannel->waitForMessage(timeout); - - InputEvent* ev; - uint32_t seqId; - status_t consumed = mInputConsumer->consume(&mInputEventFactory, true, -1, &seqId, &ev); - if (consumed != OK) { - return nullptr; - } - status_t status = mInputConsumer->sendFinishedSignal(seqId, true); - EXPECT_EQ(OK, status) << "Could not send finished signal"; - return ev; - } - void assertFocusChange(bool hasFocus) { InputEvent* ev = consumeEvent(); ASSERT_NE(ev, nullptr); @@ -314,8 +300,8 @@ public: void requestFocus(ui::LogicalDisplayId displayId = ui::LogicalDisplayId::DEFAULT) { SurfaceComposerClient::Transaction t; FocusRequest request; - request.token = mInputInfo.token; - request.windowName = mInputInfo.name; + request.token = mInputInfo->getInfo()->token; + request.windowName = mInputInfo->getInfo()->name; request.timestamp = systemTime(SYSTEM_TIME_MONOTONIC); request.displayId = displayId.val(); t.setFocusedWindow(request); @@ -323,14 +309,30 @@ public: } public: + // But should be private + sp<gui::WindowInfoHandle> mInputInfo = sp<gui::WindowInfoHandle>::make(); sp<SurfaceControl> mSurfaceControl; + +private: std::shared_ptr<InputChannel> mClientChannel; sp<IInputFlinger> mInputFlinger; - WindowInfo mInputInfo; - PreallocatedInputEventFactory mInputEventFactory; InputConsumer* mInputConsumer; + + InputEvent* consumeEvent(std::chrono::milliseconds timeout = 3000ms) { + mClientChannel->waitForMessage(timeout); + + InputEvent* ev; + uint32_t seqId; + status_t consumed = mInputConsumer->consume(&mInputEventFactory, true, -1, &seqId, &ev); + if (consumed != OK) { + return nullptr; + } + status_t status = mInputConsumer->sendFinishedSignal(seqId, true); + EXPECT_EQ(OK, status) << "Could not send finished signal"; + return ev; + } }; class BlastInputSurface : public InputSurface { @@ -458,7 +460,7 @@ TEST_F(InputSurfacesTest, can_receive_input) { injectTap(101, 101); - EXPECT_NE(surface->consumeEvent(), nullptr); + surface->expectTap(1, 1); } /** @@ -521,7 +523,7 @@ TEST_F(InputSurfacesTest, input_respects_surface_insets) { std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100); bgSurface->showAt(100, 100); - fgSurface->mInputInfo.surfaceInset = 5; + fgSurface->mInputInfo->editInfo()->surfaceInset = 5; fgSurface->showAt(100, 100); injectTap(106, 106); @@ -536,8 +538,8 @@ TEST_F(InputSurfacesTest, input_respects_surface_insets_with_replaceTouchableReg std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100); bgSurface->showAt(100, 100); - fgSurface->mInputInfo.surfaceInset = 5; - fgSurface->mInputInfo.replaceTouchableRegionWithCrop = true; + fgSurface->mInputInfo->editInfo()->surfaceInset = 5; + fgSurface->mInputInfo->editInfo()->replaceTouchableRegionWithCrop = true; fgSurface->showAt(100, 100); injectTap(106, 106); @@ -553,7 +555,7 @@ TEST_F(InputSurfacesTest, input_respects_cropped_surface_insets) { std::unique_ptr<InputSurface> childSurface = makeSurface(100, 100); parentSurface->showAt(100, 100); - childSurface->mInputInfo.surfaceInset = 10; + childSurface->mInputInfo->editInfo()->surfaceInset = 10; childSurface->showAt(100, 100); childSurface->doTransaction([&](auto& t, auto& sc) { @@ -574,7 +576,7 @@ TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets) { std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100); bgSurface->showAt(100, 100); - fgSurface->mInputInfo.surfaceInset = 5; + fgSurface->mInputInfo->editInfo()->surfaceInset = 5; fgSurface->showAt(100, 100); fgSurface->doTransaction([&](auto& t, auto& sc) { t.setMatrix(sc, 2.0, 0, 0, 4.0); }); @@ -593,7 +595,7 @@ TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets_overflow) { bgSurface->showAt(100, 100); // In case we pass the very big inset without any checking. - fgSurface->mInputInfo.surfaceInset = INT32_MAX; + fgSurface->mInputInfo->editInfo()->surfaceInset = INT32_MAX; fgSurface->showAt(100, 100); fgSurface->doTransaction([&](auto& t, auto& sc) { t.setMatrix(sc, 2.0, 0, 0, 2.0); }); @@ -606,13 +608,13 @@ TEST_F(InputSurfacesTest, input_respects_scaled_surface_insets_overflow) { TEST_F(InputSurfacesTest, touchable_region) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); - surface->mInputInfo.touchableRegion.set(Rect{19, 29, 21, 31}); + surface->mInputInfo->editInfo()->touchableRegion.set(Rect{19, 29, 21, 31}); surface->showAt(11, 22); // A tap within the surface but outside the touchable region should not be sent to the surface. injectTap(20, 30); - EXPECT_EQ(surface->consumeEvent(/*timeout=*/200ms), nullptr); + surface->assertNoEvent(); injectTap(31, 52); surface->expectTap(20, 30); @@ -627,7 +629,8 @@ TEST_F(InputSurfacesTest, input_respects_touchable_region_offset_overflow) { // Since the surface is offset from the origin, the touchable region will be transformed into // display space, which would trigger an overflow or an underflow. Ensure that we are protected // against such a situation. - fgSurface->mInputInfo.touchableRegion.orSelf(Rect{INT32_MIN, INT32_MIN, INT32_MAX, INT32_MAX}); + fgSurface->mInputInfo->editInfo()->touchableRegion.orSelf( + Rect{INT32_MIN, INT32_MIN, INT32_MAX, INT32_MAX}); fgSurface->showAt(100, 100); @@ -642,7 +645,8 @@ TEST_F(InputSurfacesTest, input_respects_scaled_touchable_region_overflow) { std::unique_ptr<InputSurface> fgSurface = makeSurface(100, 100); bgSurface->showAt(0, 0); - fgSurface->mInputInfo.touchableRegion.orSelf(Rect{INT32_MIN, INT32_MIN, INT32_MAX, INT32_MAX}); + fgSurface->mInputInfo->editInfo()->touchableRegion.orSelf( + Rect{INT32_MIN, INT32_MIN, INT32_MAX, INT32_MAX}); fgSurface->showAt(0, 0); fgSurface->doTransaction([&](auto& t, auto& sc) { t.setMatrix(sc, 2.0, 0, 0, 2.0); }); @@ -812,7 +816,7 @@ TEST_F(InputSurfacesTest, rotate_surface_with_scale) { TEST_F(InputSurfacesTest, rotate_surface_with_scale_and_insets) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); - surface->mInputInfo.surfaceInset = 5; + surface->mInputInfo->editInfo()->surfaceInset = 5; surface->showAt(100, 100); surface->doTransaction([](auto& t, auto& sc) { @@ -841,11 +845,12 @@ TEST_F(InputSurfacesTest, touch_flag_obscured) { // Add non touchable window to fully cover touchable window. Window behind gets touch, but // with flag AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED std::unique_ptr<InputSurface> nonTouchableSurface = makeSurface(100, 100); - nonTouchableSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true); - nonTouchableSurface->mInputInfo.ownerUid = gui::Uid{22222}; + nonTouchableSurface->mInputInfo->editInfo() + ->setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true); + nonTouchableSurface->mInputInfo->editInfo()->ownerUid = gui::Uid{22222}; // Overriding occlusion mode otherwise the touch would be discarded at InputDispatcher by // the default obscured/untrusted touch filter introduced in S. - nonTouchableSurface->mInputInfo.touchOcclusionMode = TouchOcclusionMode::ALLOW; + nonTouchableSurface->mInputInfo->editInfo()->touchOcclusionMode = TouchOcclusionMode::ALLOW; nonTouchableSurface->showAt(100, 100); injectTap(190, 199); @@ -861,10 +866,12 @@ TEST_F(InputSurfacesTest, touch_flag_partially_obscured_with_crop) { // AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED std::unique_ptr<InputSurface> parentSurface = makeSurface(100, 100); std::unique_ptr<InputSurface> nonTouchableSurface = makeSurface(100, 100); - nonTouchableSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true); - parentSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true); - nonTouchableSurface->mInputInfo.ownerUid = gui::Uid{22222}; - parentSurface->mInputInfo.ownerUid = gui::Uid{22222}; + nonTouchableSurface->mInputInfo->editInfo() + ->setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true); + parentSurface->mInputInfo->editInfo()->setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, + true); + nonTouchableSurface->mInputInfo->editInfo()->ownerUid = gui::Uid{22222}; + parentSurface->mInputInfo->editInfo()->ownerUid = gui::Uid{22222}; nonTouchableSurface->showAt(0, 0); parentSurface->showAt(100, 100); @@ -885,10 +892,12 @@ TEST_F(InputSurfacesTest, touch_not_obscured_with_crop) { // the touchable window. Window behind gets touch with no obscured flags. std::unique_ptr<InputSurface> parentSurface = makeSurface(100, 100); std::unique_ptr<InputSurface> nonTouchableSurface = makeSurface(100, 100); - nonTouchableSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true); - parentSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true); - nonTouchableSurface->mInputInfo.ownerUid = gui::Uid{22222}; - parentSurface->mInputInfo.ownerUid = gui::Uid{22222}; + nonTouchableSurface->mInputInfo->editInfo() + ->setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true); + parentSurface->mInputInfo->editInfo()->setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, + true); + nonTouchableSurface->mInputInfo->editInfo()->ownerUid = gui::Uid{22222}; + parentSurface->mInputInfo->editInfo()->ownerUid = gui::Uid{22222}; nonTouchableSurface->showAt(0, 0); parentSurface->showAt(50, 50); @@ -906,8 +915,9 @@ TEST_F(InputSurfacesTest, touch_not_obscured_with_zero_sized_bql) { std::unique_ptr<InputSurface> bufferSurface = InputSurface::makeBufferInputSurface(mComposerClient, 0, 0); - bufferSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true); - bufferSurface->mInputInfo.ownerUid = gui::Uid{22222}; + bufferSurface->mInputInfo->editInfo()->setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, + true); + bufferSurface->mInputInfo->editInfo()->ownerUid = gui::Uid{22222}; surface->showAt(10, 10); bufferSurface->showAt(50, 50, Rect::EMPTY_RECT); @@ -921,8 +931,9 @@ TEST_F(InputSurfacesTest, touch_not_obscured_with_zero_sized_blast) { std::unique_ptr<BlastInputSurface> bufferSurface = BlastInputSurface::makeBlastInputSurface(mComposerClient, 0, 0); - bufferSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true); - bufferSurface->mInputInfo.ownerUid = gui::Uid{22222}; + bufferSurface->mInputInfo->editInfo()->setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, + true); + bufferSurface->mInputInfo->editInfo()->ownerUid = gui::Uid{22222}; surface->showAt(10, 10); bufferSurface->showAt(50, 50, Rect::EMPTY_RECT); @@ -965,13 +976,14 @@ TEST_F(InputSurfacesTest, strict_unobscured_input_scaled_without_crop_window) { TEST_F(InputSurfacesTest, strict_unobscured_input_obscured_window) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); - surface->mInputInfo.ownerUid = gui::Uid{11111}; + surface->mInputInfo->editInfo()->ownerUid = gui::Uid{11111}; surface->doTransaction( [&](auto& t, auto& sc) { t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); }); surface->showAt(100, 100); std::unique_ptr<InputSurface> obscuringSurface = makeSurface(100, 100); - obscuringSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true); - obscuringSurface->mInputInfo.ownerUid = gui::Uid{22222}; + obscuringSurface->mInputInfo->editInfo()->setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, + true); + obscuringSurface->mInputInfo->editInfo()->ownerUid = gui::Uid{22222}; obscuringSurface->showAt(100, 100); injectTap(101, 101); surface->assertNoEvent(); @@ -984,13 +996,14 @@ TEST_F(InputSurfacesTest, strict_unobscured_input_obscured_window) { TEST_F(InputSurfacesTest, strict_unobscured_input_partially_obscured_window) { std::unique_ptr<InputSurface> surface = makeSurface(100, 100); - surface->mInputInfo.ownerUid = gui::Uid{11111}; + surface->mInputInfo->editInfo()->ownerUid = gui::Uid{11111}; surface->doTransaction( [&](auto& t, auto& sc) { t.setDropInputMode(sc, gui::DropInputMode::OBSCURED); }); surface->showAt(100, 100); std::unique_ptr<InputSurface> obscuringSurface = makeSurface(100, 100); - obscuringSurface->mInputInfo.setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, true); - obscuringSurface->mInputInfo.ownerUid = gui::Uid{22222}; + obscuringSurface->mInputInfo->editInfo()->setInputConfig(WindowInfo::InputConfig::NOT_TOUCHABLE, + true); + obscuringSurface->mInputInfo->editInfo()->ownerUid = gui::Uid{22222}; obscuringSurface->showAt(190, 190); injectTap(101, 101); @@ -1054,7 +1067,7 @@ TEST_F(InputSurfacesTest, ignore_touch_region_with_zero_sized_blast) { BlastInputSurface::makeBlastInputSurface(mComposerClient, 0, 0); surface->showAt(100, 100); - bufferSurface->mInputInfo.touchableRegion.orSelf(Rect(0, 0, 200, 200)); + bufferSurface->mInputInfo->editInfo()->touchableRegion.orSelf(Rect(0, 0, 200, 200)); bufferSurface->showAt(100, 100, Rect::EMPTY_RECT); injectTap(101, 101); @@ -1097,8 +1110,8 @@ TEST_F(InputSurfacesTest, cropped_container_replaces_touchable_region_with_null_ InputSurface::makeContainerInputSurface(mComposerClient, 100, 100); containerSurface->doTransaction( [&](auto& t, auto& sc) { t.reparent(sc, parentContainer->mSurfaceControl); }); - containerSurface->mInputInfo.replaceTouchableRegionWithCrop = true; - containerSurface->mInputInfo.touchableRegionCropHandle = nullptr; + containerSurface->mInputInfo->editInfo()->replaceTouchableRegionWithCrop = true; + containerSurface->mInputInfo->editInfo()->touchableRegionCropHandle = nullptr; parentContainer->showAt(10, 10, Rect(0, 0, 20, 20)); containerSurface->showAt(10, 10, Rect(0, 0, 5, 5)); @@ -1124,8 +1137,8 @@ TEST_F(InputSurfacesTest, uncropped_container_replaces_touchable_region_with_nul InputSurface::makeContainerInputSurface(mComposerClient, 100, 100); containerSurface->doTransaction( [&](auto& t, auto& sc) { t.reparent(sc, parentContainer->mSurfaceControl); }); - containerSurface->mInputInfo.replaceTouchableRegionWithCrop = true; - containerSurface->mInputInfo.touchableRegionCropHandle = nullptr; + containerSurface->mInputInfo->editInfo()->replaceTouchableRegionWithCrop = true; + containerSurface->mInputInfo->editInfo()->touchableRegionCropHandle = nullptr; parentContainer->doTransaction( [&](auto& t, auto& sc) { t.reparent(sc, bgContainer->mSurfaceControl); }); bgContainer->showAt(0, 0, Rect(0, 0, 100, 100)); @@ -1152,8 +1165,8 @@ TEST_F(InputSurfacesTest, replace_touchable_region_with_crop) { std::unique_ptr<InputSurface> containerSurface = InputSurface::makeContainerInputSurface(mComposerClient, 100, 100); - containerSurface->mInputInfo.replaceTouchableRegionWithCrop = true; - containerSurface->mInputInfo.touchableRegionCropHandle = + containerSurface->mInputInfo->editInfo()->replaceTouchableRegionWithCrop = true; + containerSurface->mInputInfo->editInfo()->touchableRegionCropHandle = cropLayer->mSurfaceControl->getHandle(); containerSurface->showAt(10, 10, Rect::INVALID_RECT); diff --git a/libs/input/InputEventLabels.cpp b/libs/input/InputEventLabels.cpp index 8db0ca588b..b537feb68f 100644 --- a/libs/input/InputEventLabels.cpp +++ b/libs/input/InputEventLabels.cpp @@ -350,7 +350,26 @@ namespace android { DEFINE_KEYCODE(MACRO_3), \ DEFINE_KEYCODE(MACRO_4), \ DEFINE_KEYCODE(EMOJI_PICKER), \ - DEFINE_KEYCODE(SCREENSHOT) + DEFINE_KEYCODE(SCREENSHOT), \ + DEFINE_KEYCODE(DICTATE), \ + DEFINE_KEYCODE(NEW), \ + DEFINE_KEYCODE(CLOSE), \ + DEFINE_KEYCODE(DO_NOT_DISTURB), \ + DEFINE_KEYCODE(PRINT), \ + DEFINE_KEYCODE(LOCK), \ + DEFINE_KEYCODE(FULLSCREEN), \ + DEFINE_KEYCODE(F13), \ + DEFINE_KEYCODE(F14), \ + DEFINE_KEYCODE(F15), \ + DEFINE_KEYCODE(F16), \ + DEFINE_KEYCODE(F17), \ + DEFINE_KEYCODE(F18), \ + DEFINE_KEYCODE(F19),\ + DEFINE_KEYCODE(F20), \ + DEFINE_KEYCODE(F21), \ + DEFINE_KEYCODE(F22), \ + DEFINE_KEYCODE(F23), \ + DEFINE_KEYCODE(F24) // NOTE: If you add a new axis here you must also add it to several other files. // Refer to frameworks/base/core/java/android/view/MotionEvent.java for the full list. diff --git a/libs/sensor/Sensor.cpp b/libs/sensor/Sensor.cpp index eddd568fb5..797efbe5df 100644 --- a/libs/sensor/Sensor.cpp +++ b/libs/sensor/Sensor.cpp @@ -306,7 +306,18 @@ Sensor::Sensor(struct sensor_t const& hwSensor, const uuid_t& uuid, int halVersi } if (halVersion > SENSORS_DEVICE_API_VERSION_1_0 && hwSensor.requiredPermission) { mRequiredPermission = hwSensor.requiredPermission; - if (!strcmp(mRequiredPermission, SENSOR_PERMISSION_BODY_SENSORS)) { + bool requiresBodySensorPermission = + !strcmp(mRequiredPermission, SENSOR_PERMISSION_BODY_SENSORS); + if (android::permission::flags::replace_body_sensor_permission_enabled()) { + if (requiresBodySensorPermission) { + ALOGE("Sensor %s using deprecated Body Sensor permission", mName.c_str()); + } + + AppOpsManager appOps; + // Lookup to see if an AppOp exists for the permission. If none + // does, the default value of -1 is used. + mRequiredAppOp = appOps.permissionToOpCode(String16(mRequiredPermission)); + } else if (requiresBodySensorPermission) { AppOpsManager appOps; mRequiredAppOp = appOps.permissionToOpCode(String16(SENSOR_PERMISSION_BODY_SENSORS)); } diff --git a/services/inputflinger/tests/InputMapperTest.cpp b/services/inputflinger/tests/InputMapperTest.cpp index 7dff144f87..ca797dce95 100644 --- a/services/inputflinger/tests/InputMapperTest.cpp +++ b/services/inputflinger/tests/InputMapperTest.cpp @@ -53,13 +53,13 @@ void InputMapperUnitTest::SetUpWithBus(int bus) { } void InputMapperUnitTest::setupAxis(int axis, bool valid, int32_t min, int32_t max, - int32_t resolution) { + int32_t resolution, int32_t flat, int32_t fuzz) { EXPECT_CALL(mMockEventHub, getAbsoluteAxisInfo(EVENTHUB_ID, axis)) .WillRepeatedly(Return(valid ? std::optional<RawAbsoluteAxisInfo>{{ .minValue = min, .maxValue = max, - .flat = 0, - .fuzz = 0, + .flat = flat, + .fuzz = fuzz, .resolution = resolution, }} : std::nullopt)); diff --git a/services/inputflinger/tests/InputMapperTest.h b/services/inputflinger/tests/InputMapperTest.h index fc27e4fefd..b6c5812ec5 100644 --- a/services/inputflinger/tests/InputMapperTest.h +++ b/services/inputflinger/tests/InputMapperTest.h @@ -43,7 +43,8 @@ protected: virtual void SetUp() override { SetUpWithBus(0); } virtual void SetUpWithBus(int bus); - void setupAxis(int axis, bool valid, int32_t min, int32_t max, int32_t resolution); + void setupAxis(int axis, bool valid, int32_t min, int32_t max, int32_t resolution, + int32_t flat = 0, int32_t fuzz = 0); void expectScanCodes(bool present, std::set<int> scanCodes); diff --git a/services/inputflinger/tests/SensorInputMapper_test.cpp b/services/inputflinger/tests/SensorInputMapper_test.cpp index 01814a61ec..2c1265378a 100644 --- a/services/inputflinger/tests/SensorInputMapper_test.cpp +++ b/services/inputflinger/tests/SensorInputMapper_test.cpp @@ -16,168 +16,164 @@ #include "SensorInputMapper.h" +#include <cstdint> +#include <list> +#include <optional> +#include <utility> #include <vector> #include <EventHub.h> #include <NotifyArgs.h> +#include <ftl/enum.h> +#include <gmock/gmock.h> #include <gtest/gtest.h> #include <input/Input.h> #include <input/InputDevice.h> +#include <input/PrintTools.h> #include <linux/input-event-codes.h> #include "InputMapperTest.h" +#include "TestEventMatchers.h" namespace android { -class SensorInputMapperTest : public InputMapperTest { -protected: - static const int32_t ACCEL_RAW_MIN; - static const int32_t ACCEL_RAW_MAX; - static const int32_t ACCEL_RAW_FUZZ; - static const int32_t ACCEL_RAW_FLAT; - static const int32_t ACCEL_RAW_RESOLUTION; - - static const int32_t GYRO_RAW_MIN; - static const int32_t GYRO_RAW_MAX; - static const int32_t GYRO_RAW_FUZZ; - static const int32_t GYRO_RAW_FLAT; - static const int32_t GYRO_RAW_RESOLUTION; - - static const float GRAVITY_MS2_UNIT; - static const float DEGREE_RADIAN_UNIT; - - void prepareAccelAxes(); - void prepareGyroAxes(); - void setAccelProperties(); - void setGyroProperties(); - void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::SENSOR); } -}; +using testing::AllOf; +using testing::ElementsAre; +using testing::Return; +using testing::VariantWith; -const int32_t SensorInputMapperTest::ACCEL_RAW_MIN = -32768; -const int32_t SensorInputMapperTest::ACCEL_RAW_MAX = 32768; -const int32_t SensorInputMapperTest::ACCEL_RAW_FUZZ = 16; -const int32_t SensorInputMapperTest::ACCEL_RAW_FLAT = 0; -const int32_t SensorInputMapperTest::ACCEL_RAW_RESOLUTION = 8192; - -const int32_t SensorInputMapperTest::GYRO_RAW_MIN = -2097152; -const int32_t SensorInputMapperTest::GYRO_RAW_MAX = 2097152; -const int32_t SensorInputMapperTest::GYRO_RAW_FUZZ = 16; -const int32_t SensorInputMapperTest::GYRO_RAW_FLAT = 0; -const int32_t SensorInputMapperTest::GYRO_RAW_RESOLUTION = 1024; - -const float SensorInputMapperTest::GRAVITY_MS2_UNIT = 9.80665f; -const float SensorInputMapperTest::DEGREE_RADIAN_UNIT = 0.0174533f; - -void SensorInputMapperTest::prepareAccelAxes() { - mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_X, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ, - ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION); - mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Y, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ, - ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION); - mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_Z, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_FUZZ, - ACCEL_RAW_FLAT, ACCEL_RAW_RESOLUTION); -} +namespace { -void SensorInputMapperTest::prepareGyroAxes() { - mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RX, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ, - GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION); - mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RY, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ, - GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION); - mFakeEventHub->addAbsoluteAxis(EVENTHUB_ID, ABS_RZ, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_FUZZ, - GYRO_RAW_FLAT, GYRO_RAW_RESOLUTION); -} +constexpr int32_t ACCEL_RAW_MIN = -32768; +constexpr int32_t ACCEL_RAW_MAX = 32768; +constexpr int32_t ACCEL_RAW_FUZZ = 16; +constexpr int32_t ACCEL_RAW_FLAT = 0; +constexpr int32_t ACCEL_RAW_RESOLUTION = 8192; -void SensorInputMapperTest::setAccelProperties() { - mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 0, InputDeviceSensorType::ACCELEROMETER, - /* sensorDataIndex */ 0); - mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 1, InputDeviceSensorType::ACCELEROMETER, - /* sensorDataIndex */ 1); - mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 2, InputDeviceSensorType::ACCELEROMETER, - /* sensorDataIndex */ 2); - mFakeEventHub->setMscEvent(EVENTHUB_ID, MSC_TIMESTAMP); - addConfigurationProperty("sensor.accelerometer.reportingMode", "0"); - addConfigurationProperty("sensor.accelerometer.maxDelay", "100000"); - addConfigurationProperty("sensor.accelerometer.minDelay", "5000"); - addConfigurationProperty("sensor.accelerometer.power", "1.5"); -} +constexpr int32_t GYRO_RAW_MIN = -2097152; +constexpr int32_t GYRO_RAW_MAX = 2097152; +constexpr int32_t GYRO_RAW_FUZZ = 16; +constexpr int32_t GYRO_RAW_FLAT = 0; +constexpr int32_t GYRO_RAW_RESOLUTION = 1024; -void SensorInputMapperTest::setGyroProperties() { - mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 3, InputDeviceSensorType::GYROSCOPE, - /* sensorDataIndex */ 0); - mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 4, InputDeviceSensorType::GYROSCOPE, - /* sensorDataIndex */ 1); - mFakeEventHub->addSensorAxis(EVENTHUB_ID, /* absCode */ 5, InputDeviceSensorType::GYROSCOPE, - /* sensorDataIndex */ 2); - mFakeEventHub->setMscEvent(EVENTHUB_ID, MSC_TIMESTAMP); - addConfigurationProperty("sensor.gyroscope.reportingMode", "0"); - addConfigurationProperty("sensor.gyroscope.maxDelay", "100000"); - addConfigurationProperty("sensor.gyroscope.minDelay", "5000"); - addConfigurationProperty("sensor.gyroscope.power", "0.8"); -} +constexpr float GRAVITY_MS2_UNIT = 9.80665f; +constexpr float DEGREE_RADIAN_UNIT = 0.0174533f; + +} // namespace + +class SensorInputMapperTest : public InputMapperUnitTest { +protected: + void SetUp() override { + InputMapperUnitTest::SetUp(); + EXPECT_CALL(mMockEventHub, getDeviceClasses(EVENTHUB_ID)) + .WillRepeatedly(Return(InputDeviceClass::SENSOR)); + // The mapper requests info on all ABS axes, including ones which aren't actually used, so + // just return nullopt for all axes we don't explicitly set up. + EXPECT_CALL(mMockEventHub, getAbsoluteAxisInfo(EVENTHUB_ID, testing::_)) + .WillRepeatedly(Return(std::nullopt)); + } + + void setupSensor(int32_t absCode, InputDeviceSensorType type, int32_t sensorDataIndex) { + EXPECT_CALL(mMockEventHub, mapSensor(EVENTHUB_ID, absCode)) + .WillRepeatedly(Return(std::make_pair(type, sensorDataIndex))); + } +}; TEST_F(SensorInputMapperTest, GetSources) { - SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>(); + mMapper = createInputMapper<SensorInputMapper>(*mDeviceContext, + mFakePolicy->getReaderConfiguration()); - ASSERT_EQ(static_cast<uint32_t>(AINPUT_SOURCE_SENSOR), mapper.getSources()); + ASSERT_EQ(static_cast<uint32_t>(AINPUT_SOURCE_SENSOR), mMapper->getSources()); } TEST_F(SensorInputMapperTest, ProcessAccelerometerSensor) { - setAccelProperties(); - prepareAccelAxes(); - SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>(); - - ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::ACCELEROMETER, - std::chrono::microseconds(10000), - std::chrono::microseconds(0))); - ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(EVENTHUB_ID)); - process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_X, 20000); - process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Y, -20000); - process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_Z, 40000); - process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_TIMESTAMP, 1000); - process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); - - NotifySensorArgs args; + EXPECT_CALL(mMockEventHub, hasMscEvent(EVENTHUB_ID, MSC_TIMESTAMP)) + .WillRepeatedly(Return(true)); + setupSensor(ABS_X, InputDeviceSensorType::ACCELEROMETER, /*sensorDataIndex=*/0); + setupSensor(ABS_Y, InputDeviceSensorType::ACCELEROMETER, /*sensorDataIndex=*/1); + setupSensor(ABS_Z, InputDeviceSensorType::ACCELEROMETER, /*sensorDataIndex=*/2); + setupAxis(ABS_X, /*valid=*/true, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_RESOLUTION, + ACCEL_RAW_FLAT, ACCEL_RAW_FUZZ); + setupAxis(ABS_Y, /*valid=*/true, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_RESOLUTION, + ACCEL_RAW_FLAT, ACCEL_RAW_FUZZ); + setupAxis(ABS_Z, /*valid=*/true, ACCEL_RAW_MIN, ACCEL_RAW_MAX, ACCEL_RAW_RESOLUTION, + ACCEL_RAW_FLAT, ACCEL_RAW_FUZZ); + mPropertyMap.addProperty("sensor.accelerometer.reportingMode", "0"); + mPropertyMap.addProperty("sensor.accelerometer.maxDelay", "100000"); + mPropertyMap.addProperty("sensor.accelerometer.minDelay", "5000"); + mPropertyMap.addProperty("sensor.accelerometer.power", "1.5"); + mMapper = createInputMapper<SensorInputMapper>(*mDeviceContext, + mFakePolicy->getReaderConfiguration()); + + EXPECT_CALL(mMockEventHub, enableDevice(EVENTHUB_ID)); + ASSERT_TRUE(mMapper->enableSensor(InputDeviceSensorType::ACCELEROMETER, + std::chrono::microseconds(10000), + std::chrono::microseconds(0))); + std::list<NotifyArgs> args; + args += process(ARBITRARY_TIME, EV_ABS, ABS_X, 20000); + args += process(ARBITRARY_TIME, EV_ABS, ABS_Y, -20000); + args += process(ARBITRARY_TIME, EV_ABS, ABS_Z, 40000); + args += process(ARBITRARY_TIME, EV_MSC, MSC_TIMESTAMP, 1000); + args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + std::vector<float> values = {20000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT, -20000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT, 40000.0f / ACCEL_RAW_RESOLUTION * GRAVITY_MS2_UNIT}; - ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySensorWasCalled(&args)); - ASSERT_EQ(args.source, AINPUT_SOURCE_SENSOR); - ASSERT_EQ(args.deviceId, DEVICE_ID); - ASSERT_EQ(args.sensorType, InputDeviceSensorType::ACCELEROMETER); - ASSERT_EQ(args.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH); - ASSERT_EQ(args.hwTimestamp, ARBITRARY_TIME); - ASSERT_EQ(args.values, values); - mapper.flushSensor(InputDeviceSensorType::ACCELEROMETER); + ASSERT_EQ(args.size(), 1u); + const NotifySensorArgs& arg = std::get<NotifySensorArgs>(args.front()); + ASSERT_EQ(arg.source, AINPUT_SOURCE_SENSOR); + ASSERT_EQ(arg.deviceId, DEVICE_ID); + ASSERT_EQ(arg.sensorType, InputDeviceSensorType::ACCELEROMETER); + ASSERT_EQ(arg.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH); + ASSERT_EQ(arg.hwTimestamp, ARBITRARY_TIME); + ASSERT_EQ(arg.values, values); + mMapper->flushSensor(InputDeviceSensorType::ACCELEROMETER); } TEST_F(SensorInputMapperTest, ProcessGyroscopeSensor) { - setGyroProperties(); - prepareGyroAxes(); - SensorInputMapper& mapper = constructAndAddMapper<SensorInputMapper>(); - - ASSERT_TRUE(mapper.enableSensor(InputDeviceSensorType::GYROSCOPE, - std::chrono::microseconds(10000), - std::chrono::microseconds(0))); - ASSERT_TRUE(mFakeEventHub->isDeviceEnabled(EVENTHUB_ID)); - process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RX, 20000); - process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RY, -20000); - process(mapper, ARBITRARY_TIME, READ_TIME, EV_ABS, ABS_RZ, 40000); - process(mapper, ARBITRARY_TIME, READ_TIME, EV_MSC, MSC_TIMESTAMP, 1000); - process(mapper, ARBITRARY_TIME, READ_TIME, EV_SYN, SYN_REPORT, 0); - - NotifySensorArgs args; + EXPECT_CALL(mMockEventHub, hasMscEvent(EVENTHUB_ID, MSC_TIMESTAMP)) + .WillRepeatedly(Return(true)); + setupSensor(ABS_RX, InputDeviceSensorType::GYROSCOPE, /*sensorDataIndex=*/0); + setupSensor(ABS_RY, InputDeviceSensorType::GYROSCOPE, /*sensorDataIndex=*/1); + setupSensor(ABS_RZ, InputDeviceSensorType::GYROSCOPE, /*sensorDataIndex=*/2); + setupAxis(ABS_RX, /*valid=*/true, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_RESOLUTION, + GYRO_RAW_FLAT, GYRO_RAW_FUZZ); + setupAxis(ABS_RY, /*valid=*/true, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_RESOLUTION, + GYRO_RAW_FLAT, GYRO_RAW_FUZZ); + setupAxis(ABS_RZ, /*valid=*/true, GYRO_RAW_MIN, GYRO_RAW_MAX, GYRO_RAW_RESOLUTION, + GYRO_RAW_FLAT, GYRO_RAW_FUZZ); + mPropertyMap.addProperty("sensor.gyroscope.reportingMode", "0"); + mPropertyMap.addProperty("sensor.gyroscope.maxDelay", "100000"); + mPropertyMap.addProperty("sensor.gyroscope.minDelay", "5000"); + mPropertyMap.addProperty("sensor.gyroscope.power", "0.8"); + mMapper = createInputMapper<SensorInputMapper>(*mDeviceContext, + mFakePolicy->getReaderConfiguration()); + + EXPECT_CALL(mMockEventHub, enableDevice(EVENTHUB_ID)); + ASSERT_TRUE(mMapper->enableSensor(InputDeviceSensorType::GYROSCOPE, + std::chrono::microseconds(10000), + std::chrono::microseconds(0))); + std::list<NotifyArgs> args; + args += process(ARBITRARY_TIME, EV_ABS, ABS_RX, 20000); + args += process(ARBITRARY_TIME, EV_ABS, ABS_RY, -20000); + args += process(ARBITRARY_TIME, EV_ABS, ABS_RZ, 40000); + args += process(ARBITRARY_TIME, EV_MSC, MSC_TIMESTAMP, 1000); + args += process(ARBITRARY_TIME, EV_SYN, SYN_REPORT, 0); + std::vector<float> values = {20000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT, -20000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT, 40000.0f / GYRO_RAW_RESOLUTION * DEGREE_RADIAN_UNIT}; - ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifySensorWasCalled(&args)); - ASSERT_EQ(args.source, AINPUT_SOURCE_SENSOR); - ASSERT_EQ(args.deviceId, DEVICE_ID); - ASSERT_EQ(args.sensorType, InputDeviceSensorType::GYROSCOPE); - ASSERT_EQ(args.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH); - ASSERT_EQ(args.hwTimestamp, ARBITRARY_TIME); - ASSERT_EQ(args.values, values); - mapper.flushSensor(InputDeviceSensorType::GYROSCOPE); + ASSERT_EQ(args.size(), 1u); + const NotifySensorArgs& arg = std::get<NotifySensorArgs>(args.front()); + ASSERT_EQ(arg.source, AINPUT_SOURCE_SENSOR); + ASSERT_EQ(arg.deviceId, DEVICE_ID); + ASSERT_EQ(arg.sensorType, InputDeviceSensorType::GYROSCOPE); + ASSERT_EQ(arg.accuracy, InputDeviceSensorAccuracy::ACCURACY_HIGH); + ASSERT_EQ(arg.hwTimestamp, ARBITRARY_TIME); + ASSERT_EQ(arg.values, values); + mMapper->flushSensor(InputDeviceSensorType::GYROSCOPE); } } // namespace android
\ No newline at end of file diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp index 8067ace5d4..82eafd4fa8 100644 --- a/services/surfaceflinger/CompositionEngine/Android.bp +++ b/services/surfaceflinger/CompositionEngine/Android.bp @@ -42,6 +42,7 @@ cc_defaults { "libutils", ], static_libs: [ + "libguiflags", "libmath", "librenderengine", "libtimestats", diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h index 98bccd81e4..252adaa8e3 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplayCreationArgs.h @@ -46,6 +46,12 @@ struct DisplayCreationArgs { // content. bool isProtected = false; + // True if this display has picture processing hardware and pipelines. + bool hasPictureProcessing = false; + + // The number of layer-specific picture-processing pipelines. + int32_t maxLayerPictureProfiles = 0; + // Optional pointer to the power advisor interface, if one is needed for // this display. adpf::PowerAdvisor* powerAdvisor = nullptr; @@ -82,6 +88,16 @@ public: return *this; } + DisplayCreationArgsBuilder& setHasPictureProcessing(bool hasPictureProcessing) { + mArgs.hasPictureProcessing = hasPictureProcessing; + return *this; + } + + DisplayCreationArgsBuilder& setMaxLayerPictureProfiles(int32_t maxLayerPictureProfiles) { + mArgs.maxLayerPictureProfiles = maxLayerPictureProfiles; + return *this; + } + DisplayCreationArgsBuilder& setPowerAdvisor(adpf::PowerAdvisor* powerAdvisor) { mArgs.powerAdvisor = powerAdvisor; return *this; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h index 8a91a07115..fb8fed0743 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h @@ -25,6 +25,7 @@ #include <ui/BlurRegion.h> #include <ui/FloatRect.h> #include <ui/LayerStack.h> +#include <ui/PictureProfileHandle.h> #include <ui/Rect.h> #include <ui/Region.h> #include <ui/ShadowSettings.h> @@ -219,6 +220,14 @@ struct LayerFECompositionState { float currentHdrSdrRatio = 1.f; float desiredHdrSdrRatio = 1.f; + // A picture profile handle refers to a PictureProfile configured on the display, which is a + // set of parameters that configures the picture processing hardware that is used to enhance + // the quality of buffer contents. + PictureProfileHandle pictureProfileHandle{PictureProfileHandle::NONE}; + + // A layer's priority in terms of limited picture processing pipeline utilization. + int64_t pictureProfilePriority; + gui::CachingHint cachingHint = gui::CachingHint::Enabled; std::shared_ptr<gui::DisplayLuts> luts; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h index 556aa249a3..bda7856596 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h @@ -16,6 +16,8 @@ #pragma once +#include <ftl/future.h> +#include <ftl/optional.h> #include <cstdint> #include <iterator> #include <optional> @@ -26,18 +28,18 @@ #include <vector> #include <compositionengine/LayerFE.h> -#include <ftl/future.h> #include <renderengine/LayerSettings.h> +#include <ui/DisplayIdentification.h> #include <ui/Fence.h> #include <ui/FenceTime.h> #include <ui/GraphicTypes.h> #include <ui/LayerStack.h> +#include <ui/PictureProfileHandle.h> #include <ui/Region.h> #include <ui/Transform.h> #include <utils/StrongPointer.h> #include <utils/Vector.h> -#include <ui/DisplayIdentification.h> #include "DisplayHardware/HWComposer.h" namespace android { @@ -167,7 +169,7 @@ public: virtual bool isValid() const = 0; // Returns the DisplayId the output represents, if it has one - virtual std::optional<DisplayId> getDisplayId() const = 0; + virtual ftl::Optional<DisplayId> getDisplayId() const = 0; // Enables (or disables) composition on this output virtual void setCompositionEnabled(bool) = 0; @@ -331,6 +333,9 @@ protected: virtual bool canPredictCompositionStrategy(const CompositionRefreshArgs&) = 0; virtual const aidl::android::hardware::graphics::composer3::OverlayProperties* getOverlaySupport() = 0; + virtual bool hasPictureProcessing() const = 0; + virtual int32_t getMaxLayerPictureProfiles() const = 0; + virtual void applyPictureProfile() = 0; }; } // namespace compositionengine diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h index 80c5124c76..2e7a7d9c5a 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h @@ -21,6 +21,7 @@ #include <string> #include <vector> +#include <ui/PictureProfileHandle.h> #include <ui/Transform.h> #include <utils/StrongPointer.h> @@ -86,6 +87,16 @@ public: // longer cares about. virtual void uncacheBuffers(const std::vector<uint64_t>& bufferIdsToUncache) = 0; + // Get the relative priority of the layer's picture profile with respect to the importance of + // the visual content to the user experience. Lower is higher priority. + virtual int64_t getPictureProfilePriority() const = 0; + + // The picture profile handle for the layer. + virtual const PictureProfileHandle& getPictureProfileHandle() const = 0; + + // Commit the picture profile to the composition state. + virtual void commitPictureProfileToCompositionState() = 0; + // Recalculates the state of the output layer from the output-independent // layer. If includeGeometry is false, the geometry state can be skipped. // internalDisplayRotationFlags must be set to the rotation flags for the diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h index 104a61b8e9..5519aafe11 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h @@ -45,7 +45,7 @@ public: virtual ~Display(); // compositionengine::Output overrides - std::optional<DisplayId> getDisplayId() const override; + ftl::Optional<DisplayId> getDisplayId() const override; bool isValid() const override; void dump(std::string&) const override; using compositionengine::impl::Output::setReleasedLayers; @@ -100,11 +100,16 @@ private: void setHintSessionGpuStart(TimePoint startTime) override; void setHintSessionGpuFence(std::unique_ptr<FenceTime>&& gpuFence) override; void setHintSessionRequiresRenderEngine(bool requiresRenderEngine) override; + const aidl::android::hardware::graphics::composer3::OverlayProperties* getOverlaySupport() + override; + bool hasPictureProcessing() const override; + int32_t getMaxLayerPictureProfiles() const override; + DisplayId mId; bool mIsDisconnected = false; adpf::PowerAdvisor* mPowerAdvisor = nullptr; - const aidl::android::hardware::graphics::composer3::OverlayProperties* getOverlaySupport() - override; + bool mHasPictureProcessing = false; + int32_t mMaxLayerPictureProfiles = 0; }; // This template factory function standardizes the implementation details of the diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h index 69e1efc4a7..0ccdd22919 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h @@ -16,6 +16,11 @@ #pragma once +#include <ftl/optional.h> +#include <memory> +#include <utility> +#include <vector> + #include <compositionengine/CompositionEngine.h> #include <compositionengine/LayerFECompositionState.h> #include <compositionengine/Output.h> @@ -28,10 +33,6 @@ #include <renderengine/DisplaySettings.h> #include <renderengine/LayerSettings.h> -#include <memory> -#include <utility> -#include <vector> - namespace android::compositionengine::impl { // The implementation class contains the common implementation, but does not @@ -43,7 +44,7 @@ public: // compositionengine::Output overrides bool isValid() const override; - std::optional<DisplayId> getDisplayId() const override; + ftl::Optional<DisplayId> getDisplayId() const override; void setCompositionEnabled(bool) override; void setLayerCachingEnabled(bool) override; void setLayerCachingTexturePoolEnabled(bool) override; @@ -84,13 +85,14 @@ public: bool supportsOffloadPresent() const override { return false; } void offloadPresentNextFrame() override; - void uncacheBuffers(const std::vector<uint64_t>& bufferIdsToUncache) override; void rebuildLayerStacks(const CompositionRefreshArgs&, LayerFESet&) override; void collectVisibleLayers(const CompositionRefreshArgs&, compositionengine::Output::CoverageState&) override; void ensureOutputLayerIfVisible(sp<compositionengine::LayerFE>&, compositionengine::Output::CoverageState&) override; void setReleasedLayers(const compositionengine::CompositionRefreshArgs&) override; + void uncacheBuffers(const std::vector<uint64_t>& bufferIdsToUncache) override; + void commitPictureProfilesToCompositionState(); void updateCompositionState(const compositionengine::CompositionRefreshArgs&) override; void planComposition() override; @@ -151,6 +153,9 @@ protected: void setHintSessionRequiresRenderEngine(bool requiresRenderEngine) override; bool isPowerHintSessionEnabled() override; bool isPowerHintSessionGpuReportingEnabled() override; + bool hasPictureProcessing() const override; + int32_t getMaxLayerPictureProfiles() const override; + void applyPictureProfile() override; void dumpBase(std::string&) const; // Implemented by the final implementation for the final state it uses. diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h index f8ffde1e51..c76b34481b 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputCompositionState.h @@ -35,6 +35,7 @@ #include <compositionengine/CompositionRefreshArgs.h> #include <compositionengine/ProjectionSpace.h> #include <ui/LayerStack.h> +#include <ui/PictureProfileHandle.h> #include <ui/Rect.h> #include <ui/Region.h> #include <ui/Transform.h> @@ -170,6 +171,8 @@ struct OutputCompositionState { ICEPowerCallback* powerCallback = nullptr; + PictureProfileHandle pictureProfileHandle; + // Debugging void dump(std::string& result) const; }; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h index 0c7e4dd071..cc491c2853 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h @@ -25,6 +25,7 @@ #include <compositionengine/LayerFE.h> #include <compositionengine/OutputLayer.h> #include <ui/FloatRect.h> +#include <ui/PictureProfileHandle.h> #include <ui/Rect.h> #include <ui/DisplayIdentification.h> @@ -48,6 +49,9 @@ public: void setHwcLayer(std::shared_ptr<HWC2::Layer>) override; void uncacheBuffers(const std::vector<uint64_t>& bufferIdsToUncache) override; + int64_t getPictureProfilePriority() const override; + const PictureProfileHandle& getPictureProfileHandle() const override; + void commitPictureProfileToCompositionState() override; void updateCompositionState(bool includeGeometry, bool forceClientComposition, ui::Transform::RotationFlags, diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h index 28216a475c..c558739464 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h @@ -22,6 +22,7 @@ #include <renderengine/ExternalTexture.h> #include <ui/FloatRect.h> #include <ui/GraphicTypes.h> +#include <ui/PictureProfileHandle.h> #include <ui/Rect.h> #include <ui/Region.h> @@ -101,6 +102,9 @@ struct OutputLayerCompositionState { // order to save power. Region outputSpaceBlockingRegionHint; + // The picture profile for this layer. + PictureProfileHandle pictureProfileHandle; + // Overrides the buffer, acquire fence, and display frame stored in LayerFECompositionState struct { std::shared_ptr<renderengine::ExternalTexture> buffer = nullptr; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h index 33cdc54b90..f2c265ad2e 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h @@ -34,7 +34,7 @@ public: virtual ~Output(); MOCK_CONST_METHOD0(isValid, bool()); - MOCK_CONST_METHOD0(getDisplayId, std::optional<DisplayId>()); + MOCK_CONST_METHOD0(getDisplayId, ftl::Optional<DisplayId>()); MOCK_METHOD1(setCompositionEnabled, void(bool)); MOCK_METHOD1(setLayerCachingEnabled, void(bool)); @@ -142,6 +142,9 @@ public: MOCK_METHOD(bool, isPowerHintSessionGpuReportingEnabled, ()); MOCK_METHOD((const aidl::android::hardware::graphics::composer3::OverlayProperties*), getOverlaySupport, ()); + MOCK_METHOD(bool, hasPictureProcessing, (), (const)); + MOCK_METHOD(int32_t, getMaxLayerPictureProfiles, (), (const)); + MOCK_METHOD(void, applyPictureProfile, ()); }; } // namespace android::compositionengine::mock diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h index 12f20942cb..9333ebb8cd 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h @@ -63,7 +63,9 @@ public: (ndk::ScopedFileDescriptor, (std::vector<std::pair< int, aidl::android::hardware::graphics::composer3::LutProperties>>))); - + MOCK_METHOD(int64_t, getPictureProfilePriority, (), (const)); + MOCK_METHOD(const PictureProfileHandle&, getPictureProfileHandle, (), (const)); + MOCK_METHOD(void, commitPictureProfileToCompositionState, ()); MOCK_CONST_METHOD1(dump, void(std::string&)); }; diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp index 6a97c49df6..e37ce0a0eb 100644 --- a/services/surfaceflinger/CompositionEngine/src/Display.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp @@ -54,6 +54,8 @@ Display::~Display() = default; void Display::setConfiguration(const compositionengine::DisplayCreationArgs& args) { mId = args.id; mPowerAdvisor = args.powerAdvisor; + mHasPictureProcessing = args.hasPictureProcessing; + mMaxLayerPictureProfiles = args.maxLayerPictureProfiles; editState().isSecure = args.isSecure; editState().isProtected = args.isProtected; editState().displaySpace.setBounds(args.pixels); @@ -80,7 +82,7 @@ bool Display::isVirtual() const { return mId.isVirtual(); } -std::optional<DisplayId> Display::getDisplayId() const { +ftl::Optional<DisplayId> Display::getDisplayId() const { return mId; } @@ -203,15 +205,16 @@ void Display::setReleasedLayers(const compositionengine::CompositionRefreshArgs& } void Display::applyDisplayBrightness(bool applyImmediately) { - if (const auto displayId = ftl::Optional(getDisplayId()).and_then(PhysicalDisplayId::tryCast); - displayId && getState().displayBrightness) { + if (!getState().displayBrightness) { + return; + } + if (auto displayId = PhysicalDisplayId::tryCast(mId)) { auto& hwc = getCompositionEngine().getHwComposer(); - const status_t result = - hwc.setDisplayBrightness(*displayId, *getState().displayBrightness, - getState().displayBrightnessNits, - Hwc2::Composer::DisplayBrightnessOptions{ - .applyImmediately = applyImmediately}) - .get(); + status_t result = hwc.setDisplayBrightness(*displayId, *getState().displayBrightness, + getState().displayBrightnessNits, + Hwc2::Composer::DisplayBrightnessOptions{ + .applyImmediately = applyImmediately}) + .get(); ALOGE_IF(result != NO_ERROR, "setDisplayBrightness failed for %s: %d, (%s)", getName().c_str(), result, strerror(-result)); } @@ -288,8 +291,8 @@ void Display::applyCompositionStrategy(const std::optional<DeviceRequestedChange } bool Display::getSkipColorTransform() const { - const auto& hwc = getCompositionEngine().getHwComposer(); - if (const auto halDisplayId = HalDisplayId::tryCast(mId)) { + auto& hwc = getCompositionEngine().getHwComposer(); + if (auto halDisplayId = HalDisplayId::tryCast(mId)) { return hwc.hasDisplayCapability(*halDisplayId, DisplayCapability::SKIP_CLIENT_COLOR_TRANSFORM); } @@ -462,6 +465,14 @@ Display::getOverlaySupport() { return &getCompositionEngine().getHwComposer().getOverlaySupport(); } +bool Display::hasPictureProcessing() const { + return mHasPictureProcessing; +} + +int32_t Display::getMaxLayerPictureProfiles() const { + return mMaxLayerPictureProfiles; +} + void Display::finishFrame(GpuCompositionResult&& result) { // We only need to actually compose the display if: // 1) It is being handled by hardware composer, which may need this to @@ -476,8 +487,8 @@ void Display::finishFrame(GpuCompositionResult&& result) { } bool Display::supportsOffloadPresent() const { - if (const auto halDisplayId = HalDisplayId::tryCast(mId)) { - const auto& hwc = getCompositionEngine().getHwComposer(); + if (auto halDisplayId = HalDisplayId::tryCast(mId)) { + auto& hwc = getCompositionEngine().getHwComposer(); return hwc.hasDisplayCapability(*halDisplayId, DisplayCapability::MULTI_THREADED_PRESENT); } diff --git a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp index 2d10866db3..348111d06e 100644 --- a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp +++ b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp @@ -127,6 +127,9 @@ void LayerFECompositionState::dump(std::string& out) const { } dumpVal(out, "colorTransform", colorTransform); dumpVal(out, "caching hint", toString(cachingHint)); + if (pictureProfileHandle) { + dumpVal(out, "pictureProfile", toString(pictureProfileHandle)); + } out.append("\n"); } diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index bb456138d6..98b6666a1f 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -32,9 +32,12 @@ #include <compositionengine/impl/planner/Planner.h> #include <ftl/algorithm.h> #include <ftl/future.h> +#include <ftl/optional.h> #include <scheduler/FrameTargeter.h> #include <scheduler/Time.h> +#include <com_android_graphics_libgui_flags.h> + #include <optional> #include <thread> @@ -111,7 +114,7 @@ bool Output::isValid() const { mRenderSurface->isValid(); } -std::optional<DisplayId> Output::getDisplayId() const { +ftl::Optional<DisplayId> Output::getDisplayId() const { return {}; } @@ -433,7 +436,7 @@ void Output::prepare(const compositionengine::CompositionRefreshArgs& refreshArg ftl::Future<std::monostate> Output::present( const compositionengine::CompositionRefreshArgs& refreshArgs) { const auto stringifyExpectedPresentTime = [this, &refreshArgs]() -> std::string { - return ftl::Optional(getDisplayId()) + return getDisplayId() .and_then(PhysicalDisplayId::tryCast) .and_then([&refreshArgs](PhysicalDisplayId id) { return refreshArgs.frameTargets.get(id); @@ -500,15 +503,6 @@ void Output::offloadPresentNextFrame() { updateHwcAsyncWorker(); } -void Output::uncacheBuffers(std::vector<uint64_t> const& bufferIdsToUncache) { - if (bufferIdsToUncache.empty()) { - return; - } - for (auto outputLayer : getOutputLayersOrderedByZ()) { - outputLayer->uncacheBuffers(bufferIdsToUncache); - } -} - void Output::rebuildLayerStacks(const compositionengine::CompositionRefreshArgs& refreshArgs, LayerFESet& layerFESet) { auto& outputState = editState(); @@ -776,11 +770,11 @@ void Output::ensureOutputLayerIfVisible(sp<compositionengine::LayerFE>& layerFE, // The layer is visible. Either reuse the existing outputLayer if we have // one, or create a new one if we do not. - auto result = ensureOutputLayer(prevOutputLayerIndex, layerFE); + auto outputLayer = ensureOutputLayer(prevOutputLayerIndex, layerFE); // Store the layer coverage information into the layer state as some of it // is useful later. - auto& outputLayerState = result->editState(); + auto& outputLayerState = outputLayer->editState(); outputLayerState.visibleRegion = visibleRegion; outputLayerState.visibleNonTransparentRegion = visibleNonTransparentRegion; outputLayerState.coveredRegion = coveredRegion; @@ -798,6 +792,52 @@ void Output::ensureOutputLayerIfVisible(sp<compositionengine::LayerFE>& layerFE, } } +void Output::uncacheBuffers(std::vector<uint64_t> const& bufferIdsToUncache) { + if (bufferIdsToUncache.empty()) { + return; + } + for (auto outputLayer : getOutputLayersOrderedByZ()) { + outputLayer->uncacheBuffers(bufferIdsToUncache); + } +} + +void Output::commitPictureProfilesToCompositionState() { + if (!com_android_graphics_libgui_flags_apply_picture_profiles()) { + return; + } + if (!hasPictureProcessing()) { + return; + } + auto compare = [](const ::android::compositionengine::OutputLayer* lhs, + const ::android::compositionengine::OutputLayer* rhs) { + return lhs->getPictureProfilePriority() > rhs->getPictureProfilePriority(); + }; + std::priority_queue<::android::compositionengine::OutputLayer*, + std::vector<::android::compositionengine::OutputLayer*>, decltype(compare)> + layersWithProfiles; + for (auto outputLayer : getOutputLayersOrderedByZ()) { + if (outputLayer->getPictureProfileHandle()) { + layersWithProfiles.push(outputLayer); + } + } + + // TODO(b/337330263): Use the default display picture profile from SurfaceFlinger + editState().pictureProfileHandle = PictureProfileHandle::NONE; + + // When layer-specific picture processing is supported, apply as many high priority profiles as + // possible to the layers, and ignore the low priority layers. + if (getMaxLayerPictureProfiles() > 0) { + for (int i = 0; i < getMaxLayerPictureProfiles() && !layersWithProfiles.empty(); + layersWithProfiles.pop(), ++i) { + layersWithProfiles.top()->commitPictureProfileToCompositionState(); + } + // No layer-specific picture processing, so apply the highest priority picture profile to + // the entire display. + } else if (!layersWithProfiles.empty()) { + editState().pictureProfileHandle = layersWithProfiles.top()->getPictureProfileHandle(); + } +} + void Output::setReleasedLayers(const compositionengine::CompositionRefreshArgs&) { // The base class does nothing with this call. } @@ -826,6 +866,7 @@ void Output::updateCompositionState(const compositionengine::CompositionRefreshA forceClientComposition = false; } } + commitPictureProfilesToCompositionState(); } void Output::planComposition() { @@ -847,7 +888,7 @@ void Output::writeCompositionState(const compositionengine::CompositionRefreshAr return; } - if (auto frameTargetPtrOpt = ftl::Optional(getDisplayId()) + if (auto frameTargetPtrOpt = getDisplayId() .and_then(PhysicalDisplayId::tryCast) .and_then([&refreshArgs](PhysicalDisplayId id) { return refreshArgs.frameTargets.get(id); @@ -858,6 +899,8 @@ void Output::writeCompositionState(const compositionengine::CompositionRefreshAr editState().frameInterval = refreshArgs.frameInterval; editState().powerCallback = refreshArgs.powerCallback; + applyPictureProfile(); + compositionengine::OutputLayer* peekThroughLayer = nullptr; sp<GraphicBuffer> previousOverride = nullptr; bool includeGeometry = refreshArgs.updatingGeometryThisFrame; @@ -1763,5 +1806,34 @@ float Output::getHdrSdrRatio(const std::shared_ptr<renderengine::ExternalTexture return getState().displayBrightnessNits / getState().sdrWhitePointNits; } +bool Output::hasPictureProcessing() const { + return false; +} + +int32_t Output::getMaxLayerPictureProfiles() const { + return 0; +} + +void Output::applyPictureProfile() { + if (!com_android_graphics_libgui_flags_apply_picture_profiles()) { + return; + } + + // TODO(b/337330263): Move this into the Display class and add a Display unit test. + if (!getState().pictureProfileHandle) { + return; + } + if (!getDisplayId()) { + return; + } + if (auto displayId = PhysicalDisplayId::tryCast(*getDisplayId())) { + auto& hwc = getCompositionEngine().getHwComposer(); + const status_t error = + hwc.setDisplayPictureProfileHandle(*displayId, getState().pictureProfileHandle); + ALOGE_IF(error, "setDisplayPictureProfileHandle failed for %s: %d, (%s)", getName().c_str(), + error, strerror(-error)); + } +} + } // namespace impl } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index 934909d066..e31d6848eb 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include <DisplayHardware/Hal.h> #include <android-base/stringprintf.h> #include <compositionengine/DisplayColorProfile.h> @@ -22,11 +23,12 @@ #include <compositionengine/impl/OutputCompositionState.h> #include <compositionengine/impl/OutputLayer.h> #include <compositionengine/impl/OutputLayerCompositionState.h> +#include <ui/FloatRect.h> +#include <ui/HdrRenderTypeUtils.h> #include <cstdint> #include "system/graphics-base-v1.0.h" -#include "ui/FloatRect.h" -#include <ui/HdrRenderTypeUtils.h> +#include <com_android_graphics_libgui_flags.h> // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push @@ -422,6 +424,16 @@ void OutputLayer::updateCompositionState( } } +void OutputLayer::commitPictureProfileToCompositionState() { + if (!com_android_graphics_libgui_flags_apply_picture_profiles()) { + return; + } + const auto* layerState = getLayerFE().getCompositionState(); + if (layerState) { + editState().pictureProfileHandle = getLayerFE().getCompositionState()->pictureProfileHandle; + } +} + void OutputLayer::writeStateToHWC(bool includeGeometry, bool skipLayer, uint32_t z, bool zIsOverridden, bool isPeekingThrough) { const auto& state = getState(); @@ -643,6 +655,21 @@ void OutputLayer::writeOutputDependentPerFrameStateToHWC(HWC2::Layer* hwcLayer) ALOGE("[%s] Failed to set brightness %f: %s (%d)", getLayerFE().getDebugName(), dimmingRatio, to_string(error).c_str(), static_cast<int32_t>(error)); } + + if (com_android_graphics_libgui_flags_apply_picture_profiles() && + outputDependentState.pictureProfileHandle) { + if (auto error = + hwcLayer->setPictureProfileHandle(outputDependentState.pictureProfileHandle); + error != hal::Error::NONE) { + ALOGE("[%s] Failed to set picture profile handle: %s (%d)", getLayerFE().getDebugName(), + toString(outputDependentState.pictureProfileHandle).c_str(), + static_cast<int32_t>(error)); + } + // Reset the picture profile state, as it needs to be re-committed on each present cycle + // when Output decides that the limited picture-processing hardware should be used by this + // layer. + editState().pictureProfileHandle = PictureProfileHandle::NONE; + } } void OutputLayer::writeOutputIndependentPerFrameStateToHWC( @@ -748,6 +775,16 @@ void OutputLayer::uncacheBuffers(const std::vector<uint64_t>& bufferIdsToUncache } } +int64_t OutputLayer::getPictureProfilePriority() const { + const auto* layerState = getLayerFE().getCompositionState(); + return layerState ? layerState->pictureProfilePriority : 0; +} + +const PictureProfileHandle& OutputLayer::getPictureProfileHandle() const { + const auto* layerState = getLayerFE().getCompositionState(); + return layerState ? layerState->pictureProfileHandle : PictureProfileHandle::NONE; +} + void OutputLayer::writeBufferStateToHWC(HWC2::Layer* hwcLayer, const LayerFECompositionState& outputIndependentState, bool skipLayer) { @@ -830,14 +867,14 @@ void OutputLayer::writeCursorPositionToHWC() const { return; } - const auto* layerFEState = getLayerFE().getCompositionState(); - if (!layerFEState) { + const auto* layerState = getLayerFE().getCompositionState(); + if (!layerState) { return; } const auto& outputState = getOutput().getState(); - Rect frame = layerFEState->cursorFrame; + Rect frame = layerState->cursorFrame; frame.intersect(outputState.layerStackSpace.getContent(), &frame); Rect position = outputState.transform.transform(frame); diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp index da1f7e49f8..deef74728d 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp @@ -72,6 +72,9 @@ void OutputLayerCompositionState::dump(std::string& out) const { dumpVal(out, "dataspace", toString(dataspace), dataspace); dumpVal(out, "whitePointNits", whitePointNits); dumpVal(out, "dimmingRatio", dimmingRatio); + if (pictureProfileHandle) { + dumpVal(out, "pictureProfile", toString(pictureProfileHandle)); + } dumpVal(out, "override buffer", overrideInfo.buffer.get()); dumpVal(out, "override acquire fence", overrideInfo.acquireFence.get()); dumpVal(out, "override display frame", overrideInfo.displayFrame); diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp index f2c5672ae4..dbffe80a3a 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include <com_android_graphics_libgui_flags.h> #include <compositionengine/impl/HwcBufferCache.h> #include <compositionengine/impl/OutputLayer.h> #include <compositionengine/impl/OutputLayerCompositionState.h> @@ -1332,6 +1333,71 @@ TEST_F(OutputLayerWriteStateToHWCTest, setCompositionTypeRefreshRateIndicator) { /*zIsOverridden*/ false, /*isPeekingThrough*/ false); } +TEST_F(OutputLayerWriteStateToHWCTest, setsPictureProfileWhenCommitted) { + if (!com_android_graphics_libgui_flags_apply_picture_profiles()) { + GTEST_SKIP() << "Feature flag disabled, skipping"; + } + mLayerFEState.compositionType = Composition::DEVICE; + mLayerFEState.pictureProfileHandle = PictureProfileHandle(1); + + expectGeometryCommonCalls(); + expectPerFrameCommonCalls(); + expectSetHdrMetadataAndBufferCalls(); + expectSetCompositionTypeCall(Composition::DEVICE); + + EXPECT_CALL(*mHwcLayer, setPictureProfileHandle(PictureProfileHandle(1))); + + mOutputLayer.commitPictureProfileToCompositionState(); + mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0, + /*zIsOverridden*/ false, /*isPeekingThrough*/ false); +} + +TEST_F(OutputLayerWriteStateToHWCTest, doesNotSetPictureProfileWhenNotCommitted) { + if (!com_android_graphics_libgui_flags_apply_picture_profiles()) { + GTEST_SKIP() << "Feature flag disabled, skipping"; + } + mLayerFEState.compositionType = Composition::DEVICE; + mLayerFEState.pictureProfileHandle = PictureProfileHandle(1); + + expectGeometryCommonCalls(); + expectPerFrameCommonCalls(); + expectSetHdrMetadataAndBufferCalls(); + expectSetCompositionTypeCall(Composition::DEVICE); + + EXPECT_CALL(*mHwcLayer, setPictureProfileHandle(_)).Times(0); + + mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0, + /*zIsOverridden*/ false, /*isPeekingThrough*/ false); +} + +TEST_F(OutputLayerWriteStateToHWCTest, doesNotSetPictureProfileWhenNotCommittedLater) { + if (!com_android_graphics_libgui_flags_apply_picture_profiles()) { + GTEST_SKIP() << "Feature flag disabled, skipping"; + } + mLayerFEState.compositionType = Composition::DEVICE; + mLayerFEState.pictureProfileHandle = PictureProfileHandle(1); + + expectGeometryCommonCalls(); + expectPerFrameCommonCalls(); + expectSetHdrMetadataAndBufferCalls(); + expectSetCompositionTypeCall(Composition::DEVICE); + + EXPECT_CALL(*mHwcLayer, setPictureProfileHandle(PictureProfileHandle(1))); + + mOutputLayer.commitPictureProfileToCompositionState(); + mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0, + /*zIsOverridden*/ false, /*isPeekingThrough*/ false); + + expectGeometryCommonCalls(); + expectPerFrameCommonCalls(); + expectSetHdrMetadataAndBufferCalls(kExpectedHwcSlot, nullptr, kFence); + + EXPECT_CALL(*mHwcLayer, setPictureProfileHandle(PictureProfileHandle(1))).Times(0); + // No committing of picture profile before writing the state + mOutputLayer.writeStateToHWC(/*includeGeometry*/ true, /*skipLayer*/ false, 0, + /*zIsOverridden*/ false, /*isPeekingThrough*/ false); +} + /* * OutputLayer::uncacheBuffers */ diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index fe7dd9a3bc..99e68eb71a 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -15,6 +15,7 @@ */ #include <android-base/stringprintf.h> +#include <com_android_graphics_libgui_flags.h> #include <com_android_graphics_surfaceflinger_flags.h> #include <compositionengine/LayerFECompositionState.h> #include <compositionengine/impl/Output.h> @@ -37,11 +38,14 @@ #include <cstdint> #include <variant> +#include <com_android_graphics_surfaceflinger_flags.h> + #include <common/FlagManager.h> #include <common/test/FlagUtils.h> #include "CallOrderStateMachineHelper.h" #include "RegionMatcher.h" #include "mock/DisplayHardware/MockHWC2.h" +#include "mock/DisplayHardware/MockHWComposer.h" namespace android::compositionengine { namespace { @@ -142,6 +146,24 @@ struct OutputTest : public testing::Test { public: using impl::Output::injectOutputLayerForTest; virtual void injectOutputLayerForTest(std::unique_ptr<compositionengine::OutputLayer>) = 0; + + virtual ftl::Optional<DisplayId> getDisplayId() const override { return mId; } + + virtual bool hasPictureProcessing() const override { return mHasPictureProcessing; } + virtual int32_t getMaxLayerPictureProfiles() const override { + return mMaxLayerPictureProfiles; + } + + void setDisplayIdForTest(DisplayId value) { mId = value; } + + void setHasPictureProcessingForTest(bool value) { mHasPictureProcessing = value; } + + void setMaxLayerPictureProfilesForTest(int32_t value) { mMaxLayerPictureProfiles = value; } + + private: + ftl::Optional<DisplayId> mId; + bool mHasPictureProcessing; + int32_t mMaxLayerPictureProfiles; }; static std::shared_ptr<Output> createOutput( @@ -157,6 +179,7 @@ struct OutputTest : public testing::Test { mOutput->editState().displaySpace.setBounds( ui::Size(kDefaultDisplaySize.getWidth(), kDefaultDisplaySize.getHeight())); EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine)); + EXPECT_CALL(mCompositionEngine, getHwComposer()).WillRepeatedly(ReturnRef(mHwComposer)); } void injectOutputLayer(InjectedLayer& layer) { @@ -169,6 +192,7 @@ struct OutputTest : public testing::Test { static const Rect kDefaultDisplaySize; + StrictMock<::android::mock::HWComposer> mHwComposer; StrictMock<mock::CompositionEngine> mCompositionEngine; StrictMock<renderengine::mock::RenderEngine> mRenderEngine; mock::DisplayColorProfile* mDisplayColorProfile = new StrictMock<mock::DisplayColorProfile>(); @@ -5043,6 +5067,123 @@ TEST_F(OutputUpdateAndWriteCompositionStateTest, handlesBlurRegionRequests) { mOutput->writeCompositionState(args); } +TEST_F(OutputUpdateAndWriteCompositionStateTest, assignsDisplayProfileBasedOnLayerPriority) { + if (!com_android_graphics_libgui_flags_apply_picture_profiles()) { + GTEST_SKIP() << "Feature flag disabled, skipping"; + } + + mOutput->setDisplayIdForTest(PhysicalDisplayId::fromPort(1)); + // Has only one display-global picture processing pipeline + mOutput->setHasPictureProcessingForTest(true); + mOutput->setMaxLayerPictureProfilesForTest(0); + + InjectedLayer layer1; + injectOutputLayer(layer1); + PictureProfileHandle profileForLayer1(1); + EXPECT_CALL(*layer1.outputLayer, getPictureProfilePriority()).WillRepeatedly(Return(3)); + EXPECT_CALL(*layer1.outputLayer, getPictureProfileHandle()) + .WillRepeatedly(ReturnRef(profileForLayer1)); + + InjectedLayer layer2; + injectOutputLayer(layer2); + PictureProfileHandle profileForLayer2(2); + EXPECT_CALL(*layer2.outputLayer, getPictureProfilePriority()).WillRepeatedly(Return(1)); + EXPECT_CALL(*layer2.outputLayer, getPictureProfileHandle()) + .WillRepeatedly(ReturnRef(profileForLayer2)); + + InjectedLayer layer3; + injectOutputLayer(layer3); + PictureProfileHandle profileForLayer3(3); + EXPECT_CALL(*layer3.outputLayer, getPictureProfilePriority()).WillRepeatedly(Return(2)); + EXPECT_CALL(*layer3.outputLayer, getPictureProfileHandle()) + .WillRepeatedly(ReturnRef(profileForLayer3)); + + // Because StrictMock + EXPECT_CALL(*layer1.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false)); + EXPECT_CALL(*layer1.outputLayer, updateCompositionState(_, _, _, _)); + EXPECT_CALL(*layer1.outputLayer, writeStateToHWC(_, _, _, _, _)); + EXPECT_CALL(*layer2.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false)); + EXPECT_CALL(*layer2.outputLayer, updateCompositionState(_, _, _, _)); + EXPECT_CALL(*layer2.outputLayer, writeStateToHWC(_, _, _, _, _)); + EXPECT_CALL(*layer3.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false)); + EXPECT_CALL(*layer3.outputLayer, updateCompositionState(_, _, _, _)); + EXPECT_CALL(*layer3.outputLayer, writeStateToHWC(_, _, _, _, _)); + + // No layer picture profiles should be committed + EXPECT_CALL(*layer1.outputLayer, commitPictureProfileToCompositionState).Times(0); + EXPECT_CALL(*layer2.outputLayer, commitPictureProfileToCompositionState).Times(0); + EXPECT_CALL(*layer3.outputLayer, commitPictureProfileToCompositionState).Times(0); + + // Sets display picture profile to the highest priority layer's profile + EXPECT_CALL(mHwComposer, setDisplayPictureProfileHandle(_, Eq(profileForLayer2))); + + mOutput->editState().isEnabled = true; + CompositionRefreshArgs args; + args.updatingGeometryThisFrame = false; + args.devOptForceClientComposition = false; + mOutput->updateCompositionState(args); + mOutput->planComposition(); + mOutput->writeCompositionState(args); +} + +TEST_F(OutputUpdateAndWriteCompositionStateTest, assignsLayerProfileBasedOnLayerPriority) { + if (!com_android_graphics_libgui_flags_apply_picture_profiles()) { + GTEST_SKIP() << "Feature flag disabled, skipping"; + } + mOutput->setDisplayIdForTest(PhysicalDisplayId::fromPort(1)); + // Has 2 layer-specific picture processing pipelines + mOutput->setHasPictureProcessingForTest(true); + mOutput->setMaxLayerPictureProfilesForTest(2); + + InjectedLayer layer1; + injectOutputLayer(layer1); + PictureProfileHandle profileForLayer1(1); + EXPECT_CALL(*layer1.outputLayer, getPictureProfilePriority()).WillRepeatedly(Return(3)); + EXPECT_CALL(*layer1.outputLayer, getPictureProfileHandle()) + .WillRepeatedly(ReturnRef(profileForLayer1)); + + InjectedLayer layer2; + injectOutputLayer(layer2); + PictureProfileHandle profileForLayer2(2); + EXPECT_CALL(*layer2.outputLayer, getPictureProfilePriority()).WillRepeatedly(Return(1)); + EXPECT_CALL(*layer2.outputLayer, getPictureProfileHandle()) + .WillRepeatedly(ReturnRef(profileForLayer2)); + + InjectedLayer layer3; + injectOutputLayer(layer3); + PictureProfileHandle profileForLayer3(3); + EXPECT_CALL(*layer3.outputLayer, getPictureProfilePriority()).WillRepeatedly(Return(2)); + EXPECT_CALL(*layer3.outputLayer, getPictureProfileHandle()) + .WillRepeatedly(ReturnRef(profileForLayer3)); + + // Because StrictMock + EXPECT_CALL(*layer1.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false)); + EXPECT_CALL(*layer1.outputLayer, updateCompositionState(_, _, _, _)); + EXPECT_CALL(*layer1.outputLayer, writeStateToHWC(_, _, _, _, _)); + EXPECT_CALL(*layer2.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false)); + EXPECT_CALL(*layer2.outputLayer, updateCompositionState(_, _, _, _)); + EXPECT_CALL(*layer2.outputLayer, writeStateToHWC(_, _, _, _, _)); + EXPECT_CALL(*layer3.outputLayer, requiresClientComposition()).WillRepeatedly(Return(false)); + EXPECT_CALL(*layer3.outputLayer, updateCompositionState(_, _, _, _)); + EXPECT_CALL(*layer3.outputLayer, writeStateToHWC(_, _, _, _, _)); + + // The two highest priority layers should have their picture profiles committed + EXPECT_CALL(*layer1.outputLayer, commitPictureProfileToCompositionState).Times(0); + EXPECT_CALL(*layer2.outputLayer, commitPictureProfileToCompositionState); + EXPECT_CALL(*layer3.outputLayer, commitPictureProfileToCompositionState); + + // No display picture profile is sent + EXPECT_CALL(mHwComposer, setDisplayPictureProfileHandle).Times(0); + + mOutput->editState().isEnabled = true; + CompositionRefreshArgs args; + args.updatingGeometryThisFrame = false; + args.devOptForceClientComposition = false; + mOutput->updateCompositionState(args); + mOutput->planComposition(); + mOutput->writeCompositionState(args); +} + TEST_F(GenerateClientCompositionRequestsTest, handlesLandscapeModeSplitScreenRequests) { // In split-screen landscape mode, the screen is rotated 90 degrees, with // one layer on the left covering the left side of the output, and one layer diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp index e6fed63d96..7b6e4bff6a 100644 --- a/services/surfaceflinger/tests/Credentials_test.cpp +++ b/services/surfaceflinger/tests/Credentials_test.cpp @@ -341,9 +341,9 @@ TEST_F(CredentialsTest, TransactionPermissionTest) { WindowInfosListenerUtils windowInfosListenerUtils; std::string name = "Test Layer"; sp<IBinder> token = sp<BBinder>::make(); - WindowInfo windowInfo; - windowInfo.name = name; - windowInfo.token = token; + auto windowInfo = sp<gui::WindowInfoHandle>::make(); + windowInfo->editInfo()->name = name; + windowInfo->editInfo()->token = token; sp<SurfaceControl> surfaceControl = mComposerClient->createSurface(String8(name.c_str()), 100, 100, PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceBufferState); @@ -370,7 +370,8 @@ TEST_F(CredentialsTest, TransactionPermissionTest) { UIDFaker f(AID_SYSTEM); auto windowIsPresentAndNotTrusted = [&](const std::vector<WindowInfo>& windowInfos) { auto foundWindowInfo = - WindowInfosListenerUtils::findMatchingWindowInfo(windowInfo, windowInfos); + WindowInfosListenerUtils::findMatchingWindowInfo(*windowInfo->getInfo(), + windowInfos); if (!foundWindowInfo) { return false; } @@ -386,7 +387,8 @@ TEST_F(CredentialsTest, TransactionPermissionTest) { Transaction().setTrustedOverlay(surfaceControl, true).apply(/*synchronous=*/true); auto windowIsPresentAndTrusted = [&](const std::vector<WindowInfo>& windowInfos) { auto foundWindowInfo = - WindowInfosListenerUtils::findMatchingWindowInfo(windowInfo, windowInfos); + WindowInfosListenerUtils::findMatchingWindowInfo(*windowInfo->getInfo(), + windowInfos); if (!foundWindowInfo) { return false; } diff --git a/services/surfaceflinger/tests/WindowInfosListener_test.cpp b/services/surfaceflinger/tests/WindowInfosListener_test.cpp index ad9a674456..2dd0dd9bd3 100644 --- a/services/surfaceflinger/tests/WindowInfosListener_test.cpp +++ b/services/surfaceflinger/tests/WindowInfosListener_test.cpp @@ -50,9 +50,9 @@ protected: TEST_F(WindowInfosListenerTest, WindowInfoAddedAndRemoved) { std::string name = "Test Layer"; sp<IBinder> token = sp<BBinder>::make(); - WindowInfo windowInfo; - windowInfo.name = name; - windowInfo.token = token; + auto windowInfo = sp<gui::WindowInfoHandle>::make(); + windowInfo->editInfo()->name = name; + windowInfo->editInfo()->token = token; sp<SurfaceControl> surfaceControl = mClient->createSurface(String8(name.c_str()), 100, 100, PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceBufferState); @@ -65,14 +65,14 @@ TEST_F(WindowInfosListenerTest, WindowInfoAddedAndRemoved) { .apply(); auto windowPresent = [&](const std::vector<WindowInfo>& windowInfos) { - return findMatchingWindowInfo(windowInfo, windowInfos); + return findMatchingWindowInfo(*windowInfo->getInfo(), windowInfos); }; ASSERT_TRUE(waitForWindowInfosPredicate(windowPresent)); Transaction().reparent(surfaceControl, nullptr).apply(); auto windowNotPresent = [&](const std::vector<WindowInfo>& windowInfos) { - return !findMatchingWindowInfo(windowInfo, windowInfos); + return !findMatchingWindowInfo(*windowInfo->getInfo(), windowInfos); }; ASSERT_TRUE(waitForWindowInfosPredicate(windowNotPresent)); } @@ -80,9 +80,9 @@ TEST_F(WindowInfosListenerTest, WindowInfoAddedAndRemoved) { TEST_F(WindowInfosListenerTest, WindowInfoChanged) { std::string name = "Test Layer"; sp<IBinder> token = sp<BBinder>::make(); - WindowInfo windowInfo; - windowInfo.name = name; - windowInfo.token = token; + auto windowInfo = sp<gui::WindowInfoHandle>::make(); + windowInfo->editInfo()->name = name; + windowInfo->editInfo()->token = token; sp<SurfaceControl> surfaceControl = mClient->createSurface(String8(name.c_str()), 100, 100, PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceBufferState); @@ -96,7 +96,7 @@ TEST_F(WindowInfosListenerTest, WindowInfoChanged) { .apply(); auto windowIsPresentAndTouchableRegionEmpty = [&](const std::vector<WindowInfo>& windowInfos) { - auto foundWindowInfo = findMatchingWindowInfo(windowInfo, windowInfos); + auto foundWindowInfo = findMatchingWindowInfo(*windowInfo->getInfo(), windowInfos); if (!foundWindowInfo) { return false; } @@ -104,19 +104,19 @@ TEST_F(WindowInfosListenerTest, WindowInfoChanged) { }; ASSERT_TRUE(waitForWindowInfosPredicate(windowIsPresentAndTouchableRegionEmpty)); - windowInfo.addTouchableRegion({0, 0, 50, 50}); + windowInfo->editInfo()->addTouchableRegion({0, 0, 50, 50}); Transaction().setInputWindowInfo(surfaceControl, windowInfo).apply(); auto windowIsPresentAndTouchableRegionMatches = [&](const std::vector<WindowInfo>& windowInfos) { - auto foundWindowInfo = findMatchingWindowInfo(windowInfo, windowInfos); + auto foundWindowInfo = findMatchingWindowInfo(*windowInfo->getInfo(), windowInfos); if (!foundWindowInfo) { return false; } auto touchableRegion = foundWindowInfo->transform.transform(foundWindowInfo->touchableRegion); - return touchableRegion.hasSameRects(windowInfo.touchableRegion); + return touchableRegion.hasSameRects(windowInfo->getInfo()->touchableRegion); }; ASSERT_TRUE(waitForWindowInfosPredicate(windowIsPresentAndTouchableRegionMatches)); } |