-
Notifications
You must be signed in to change notification settings - Fork 6k
Move detection of cutouts in Android engine to onApplyWindowInsets
#55992
Conversation
@@ -538,7 +539,7 @@ protected void onDetachedFromWindow() { | |||
@TargetApi(API_LEVELS.API_28) | |||
protected void setWindowInfoListenerDisplayFeatures(WindowLayoutInfo layoutInfo) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I dont understand why only the display cutout features need to be moved and not all the features in this method.
Unrelated to your change it is weird that this had a targetApi of 28 and still did an api check inside the method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding is that this listener is triggered (only) on changes to DisplayFeature
s, which include hinges and display folds but (from @yaakovschectman and my manual testing) not camera cutouts (or other top of device sensors).
Those are instead reported as WindowInsets
with a nonzero element reported by WindowInsets.getDisplayCutout()
(and underlying changes to them instead trigger onApplyWindowInsets
).
Flutter was conflating both of these two distinct groups into a List<FlutterRenderer.DisplayFeature>
, but the list would only get updated in the case of changes to the former group, because underlying updates to the latter didn't trigger the listener (and we didn't handle them appropriately in the listener that was triggered).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK that makes sense thanks for the explanation.
shell/platform/android/test/io/flutter/embedding/android/FlutterViewTest.java
Outdated
Show resolved
Hide resolved
@@ -538,7 +539,7 @@ protected void onDetachedFromWindow() { | |||
@TargetApi(API_LEVELS.API_28) | |||
protected void setWindowInfoListenerDisplayFeatures(WindowLayoutInfo layoutInfo) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK that makes sense thanks for the explanation.
shell/platform/android/io/flutter/embedding/android/FlutterView.java
Outdated
Show resolved
Hide resolved
shell/platform/android/test/io/flutter/embedding/android/FlutterViewTest.java
Outdated
Show resolved
Hide resolved
shell/platform/android/test/io/flutter/embedding/android/FlutterViewTest.java
Outdated
Show resolved
Hide resolved
shell/platform/android/test/io/flutter/embedding/android/FlutterViewTest.java
Outdated
Show resolved
Hide resolved
@@ -1485,6 +1484,10 @@ private void sendViewportMetricsToFlutter() { | |||
viewportMetrics.devicePixelRatio = getResources().getDisplayMetrics().density; | |||
viewportMetrics.physicalTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); | |||
|
|||
viewportMetrics.displayFeatures.clear(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels like a codesmell to have to know to clear this value regularly. Should ViewportMetrics instead have display features and displayCutouts? or should we make a setter for setFeaturesAndCutouts that clears the value and adds both sets?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also thought about separating the two lists within ViewportMetrics
, and wouldn't be opposed.
I'm not too concerned about being required to remember to call clear on viewportMetrics.displayFeatures
, though, because the pr establishes a pattern that list is exclusively handled by this helper (sendViewportMetricsToFlutter
) which takes care of clearing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let us separate the lists in Viewport metrics then. I agree your helper does a good job of isolating the current logic but I think future logic is where we would get an accidental regression.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've separated the two lists, introduced a new DisplayCutout
class, as that inherently represents less data than the generic DisplayFeature
, and modified the view and renderer tests accordingly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm I think my feedback wasn't great/clear here. In my head I was thinking about fully separating DisplayCutout
and DisplayFeature
handling, so the updates would get sent separately to the framework, and users would be able to see them separately, i.e. an equivalent to
https://api.flutter.dev/flutter/widgets/MediaQueryData/displayFeatures.html
for DisplayFeatures
.
But that would be more involved/a breaking change, and I didn't articulate that clearly. Instead, it looks like we are currently essentially just re-translating the new DisplayCutout
s back to a dart equivalent of the original FlutterRenderer.DisplayFeature
, which makes me doubtful of the value of separating the classes in Java, as
- we drift from what seemed to be an intentional mirroring in Dart, potentially confusing future contributors who come looking in the android embedding for
DisplayFeature
s, find an equivalent class, but don't realize that the framework equivalent depends on more than just that class - we get more complicated logic in
setViewPortMetrics
,
But also I realize this is a lot of churn to ask to go back to the old implementation... I'm fine being overruled here. WDYT @reidbaker / @yaakovschectman?
@@ -649,6 +651,69 @@ public void systemInsetDisplayCutoutSimple() { | |||
assertEquals(100, viewportMetricsCaptor.getValue().viewInsetTop); | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on the issue flutter/flutter#155658 I think there are more regression tests we should include.
From my reading this test is verifying that cutouts when triggered how we expect show up in viewpoint metrics.
After Reading the bug i am thinking we should have a rotation test that verifies that cutouts are not "left" after the hardware has changed orientation. Additionally there is logic in this pr to combine displayCutouts and displayFeatures, I would expect a test to modify one and assert the other was preserved and vice versa and a test to show that if both are modfied the joint list is updated correctly. This second (of 3) change might be possible without adding a new test but by adding asserts to existing tests or it might require a new test depending on the existing coverage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For testing the rotation as you mention, this sounds like it would require an integration test to run on an emulator; I do not think we can unit-test it, as changing the orientation in a unit test will have no effect on the value returned by the stubbed methods like we are using here. Do you agree with that? And if so, are there existing integration tests in this repo that perform anything similar?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am hoping we can not do an integration test but instead do a roboletric test that runs on an activity. Possibly by modifying the orientation then recreating the activity.
See https://stackoverflow.com/a/26468296 for inspiration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can change the orientation in a robolectric unit test, but I still fail to see how that will help us for a unit test where the display cutouts are provided through a mock with stubbed methods for returning its metrics. The closest thing I can find is that maybe we can use robolectric's ShadowDisplay (which is deprecated and planned for removal), and to access the ShadowDisplay in the mock's stubs. I have not yet tested this approach, but if that would actually work, I am still unsure if it even reflects the behavior we want to test within reason.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I go back and forth on if an integration test is appropriate here in general we get more flakes with an integration test but also this is something our users are expecting us to handle.
I think your suggestion to use shadowDisplay is interesting but if it is depercrated then not worth the time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are rotation tests if that's what you mean.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@reidbaker do you know if we have any existing examples of forcing a test to run on a specific physical device and/or requiring a test to be run only in the context of certain adb commands?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also I want to make sure I document here before I forget that you can get a list of cutout overlays with
adb shell cmd overlay list | grep "display\.cutout"
and then dis/enable one with
adb shell cmd overlay <enable/disable> <cutout package name>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@reidbaker Actually, I have an integration test on a local branch that can test this behavior. However, as the current state of this behavior is bugged, my understanding is that this PR will need to land first with only the engine-level unit tests before we can add this integration test to the framework. Does this sound right? If so, do you have any more pending thoughts or concerns for this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me rephrase to see if I understand. You have an integration test on a branch of flutter/flutter that fails with the current behavior and passes with a custom engine running this pr. If that is the case then yes we can land this pr then your other pr. That said, let's put that second pr up for review so that reviewers can look at what is covered in each.
TBH having the test fail against flutter/flutter and pass with this patch is exactly the type of test we want here thank you for writing that test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mostly lgtm just one question about the tests
shell/platform/android/test/io/flutter/embedding/android/FlutterViewTest.java
Outdated
Show resolved
Hide resolved
@gmackall will you give this a second pass? |
DisplayCutout displayCutout = viewportMetrics.displayCutouts.get(i); | ||
displayFeaturesBounds[cutoutOffset + 4 * i] = displayCutout.bounds.left; | ||
displayFeaturesBounds[cutoutOffset + 4 * i + 1] = displayCutout.bounds.top; | ||
displayFeaturesBounds[cutoutOffset + 4 * i + 2] = displayCutout.bounds.right; | ||
displayFeaturesBounds[cutoutOffset + 4 * i + 3] = displayCutout.bounds.bottom; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider authoring a helper here since this code is repeated and any bugs in one would likely be a bug in the other.
// Display cutouts always have type CUTOUT and state UNKNOWN. | ||
displayFeaturesType[viewportMetrics.displayFeatures.size() + i] = | ||
DisplayFeatureType.CUTOUT.encodedValue; | ||
displayFeaturesState[viewportMetrics.displayFeatures.size() + i] = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems weird to intentionally be setting unknown here. It seems to be what were were doing before but should we have added a state enum value for these?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current doc-comment for UNKNOWN
states The display feature is a cutout or this state is new and not yet known to Flutter.
The framework also currently expects cutouts to have a state of unknown
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
seems odd but out of scope for this pr.
public static final class DisplayCutout { | ||
public final Rect bounds; | ||
|
||
public DisplayCutout(Rect bounds) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this default to unknown? (or maybe a new state value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not clear on what you are asking here. Should what default to unknown?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Display feature class which we previously used for cutouts has a type and a state. Should those be hardcoded in the DisplayCutout class as type and state then let the code above in setViewportMetrics refer to DisplayCutout.type and DisplayCutout.state instead of using for example DisplayFeatureState.UNKNOWN.encodedValue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not have any strong opinions on it, so I will change it accordingly.
|
||
flutterView.onApplyWindowInsets(windowInsets); | ||
|
||
verify(flutterRenderer, times(2)).setViewportMetrics(viewportMetricsCaptor.capture()); | ||
validateViewportMetricPadding(viewportMetricsCaptor, 200, 150, 200, 150); | ||
validateViewportMetricPadding(viewportMetricsCaptor, 200, 120, 250, 140); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding a comment about why this is a mix of display cutout and waterfall insets so future maintainers can understand at a glance.
DisplayCutout displayCutout = mock(DisplayCutout.class); | ||
when(windowInsets.getDisplayCutout()).thenReturn(displayCutout); | ||
when(displayCutout.getBoundingRects()).thenReturn(boundingRects); | ||
// The following mocked methods are necessary to avoid a NullPointerException when calling |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One larger question and a couple of small nits.
I'm fine being overruled on the larger question, so LGTM as is! But would be interested to see if you feel similarly on the question of if we should introduce the new DisplayCutout
shell/platform/android/io/flutter/embedding/engine/renderer/FlutterRenderer.java
Outdated
Show resolved
Hide resolved
shell/platform/android/io/flutter/embedding/android/FlutterView.java
Outdated
Show resolved
Hide resolved
shell/platform/android/io/flutter/embedding/engine/renderer/FlutterRenderer.java
Outdated
Show resolved
Hide resolved
@@ -1485,6 +1484,10 @@ private void sendViewportMetricsToFlutter() { | |||
viewportMetrics.devicePixelRatio = getResources().getDisplayMetrics().density; | |||
viewportMetrics.physicalTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop(); | |||
|
|||
viewportMetrics.displayFeatures.clear(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm I think my feedback wasn't great/clear here. In my head I was thinking about fully separating DisplayCutout
and DisplayFeature
handling, so the updates would get sent separately to the framework, and users would be able to see them separately, i.e. an equivalent to
https://api.flutter.dev/flutter/widgets/MediaQueryData/displayFeatures.html
for DisplayFeatures
.
But that would be more involved/a breaking change, and I didn't articulate that clearly. Instead, it looks like we are currently essentially just re-translating the new DisplayCutout
s back to a dart equivalent of the original FlutterRenderer.DisplayFeature
, which makes me doubtful of the value of separating the classes in Java, as
- we drift from what seemed to be an intentional mirroring in Dart, potentially confusing future contributors who come looking in the android embedding for
DisplayFeature
s, find an equivalent class, but don't realize that the framework equivalent depends on more than just that class - we get more complicated logic in
setViewPortMetrics
,
But also I realize this is a lot of churn to ask to go back to the old implementation... I'm fine being overruled here. WDYT @reidbaker / @yaakovschectman?
@gmackall If nothing else, using two separate collections would make any future migration to separate them on the framework easier, and simplifies our tests. |
…158127) flutter/engine@05cb5d7...25c7e47 2024-11-04 [email protected] Retry mac_unopt one time in presubmit (flutter/engine#56319) 2024-11-04 [email protected] [Impeller] faster descriptor type mapping. (flutter/engine#56351) 2024-11-04 [email protected] Roll Skia from 75740b68a282 to e2ad60ea8039 (8 revisions) (flutter/engine#56354) 2024-11-04 [email protected] Move detection of cutouts in Android engine to `onApplyWindowInsets` (flutter/engine#55992) 2024-11-04 [email protected] Roll Dart SDK from 69cec5dc51f9 to f238183cf168 (1 revision) (flutter/engine#56353) 2024-11-04 [email protected] Roll Skia from bab7d954758b to 75740b68a282 (1 revision) (flutter/engine#56349) 2024-11-04 [email protected] Roll Fuchsia Linux SDK from 07KmbdEtnhkg_tUhe... to amgHXcqtplha8LuI_... (flutter/engine#56348) 2024-11-03 [email protected] Roll Skia from 6944cd128603 to bab7d954758b (2 revisions) (flutter/engine#56346) 2024-11-02 [email protected] Roll Dart SDK from 61bf0877807e to 69cec5dc51f9 (2 revisions) (flutter/engine#56335) 2024-11-02 [email protected] Multiple touches of a stylus should be considered from the same device (flutter/engine#56075) 2024-11-02 [email protected] Roll Skia from 89ac72bb4922 to 6944cd128603 (2 revisions) (flutter/engine#56331) 2024-11-02 [email protected] [web] Transfer focus to view rootElement on blur/remove. (flutter/engine#55045) Also rolling transitive DEPS: fuchsia/sdk/core/linux-amd64 from 07KmbdEtnhkg to amgHXcqtplha If this roll has caused a breakage, revert this CL and stop the roller using the controls here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll Please CC [email protected],[email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
…lutter#55992) Stop including the translation of window insets cutouts to Flutter cutout DisplayFeatures in the window info listener method, which would not necessarily receive changes in the correct order/state when they update, e.g. when the screen orientation changes. Fixes flutter/flutter#155658 *If you had to change anything in the [flutter/tests] repo, include a link to the migration guide as per the [breaking change policy].* ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide] and the [C++, Objective-C, Java style guides]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I added new tests to check the change I am making or feature I am adding, or the PR is [test-exempt]. See [testing the engine] for instructions on writing and running engine tests. - [x] I updated/added relevant documentation (doc comments with `///`). - [ ] I signed the [CLA]. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/wiki/Tree-hygiene#overview [Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene [test-exempt]: https://github.com/flutter/flutter/wiki/Tree-hygiene#tests [Flutter Style Guide]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style [testing the engine]: https://github.com/flutter/flutter/wiki/Testing-the-engine [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/wiki/Chat
…lutter/engine#55992) Stop including the translation of window insets cutouts to Flutter cutout DisplayFeatures in the window info listener method, which would not necessarily receive changes in the correct order/state when they update, e.g. when the screen orientation changes. Fixes flutter#155658 *If you had to change anything in the [flutter/tests] repo, include a link to the migration guide as per the [breaking change policy].* ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide] and the [C++, Objective-C, Java style guides]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I added new tests to check the change I am making or feature I am adding, or the PR is [test-exempt]. See [testing the engine] for instructions on writing and running engine tests. - [x] I updated/added relevant documentation (doc comments with `///`). - [ ] I signed the [CLA]. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/wiki/Tree-hygiene#overview [Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene [test-exempt]: https://github.com/flutter/flutter/wiki/Tree-hygiene#tests [Flutter Style Guide]: https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style [testing the engine]: https://github.com/flutter/flutter/wiki/Testing-the-engine [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/wiki/Chat
…dowInsets` (#56379) This pull request is created by [automatic cherry pick workflow](https://github.com/flutter/flutter/blob/main/docs/releases/Flutter-Cherrypick-Process.md#automatically-creates-a-cherry-pick-request) Please fill in the form below, and a flutter domain expert will evaluate this cherry pick request. ### Issue Link: What is the link to the issue this cherry-pick is addressing? flutter/flutter#158192 ### Changelog Description: Explain this cherry pick in one line that is accessible to most Flutter developers. See [best practices](https://github.com/flutter/flutter/blob/main/docs/releases/Hotfix-Documentation-Best-Practices.md) for examples #55992. - Positions of display cutouts on Android may not update - as returned by `MediaQuery` and used by `SafeArea` - upon screen orientation change. ### Impact Description: What is the impact (ex. visual jank on Samsung phones, app crash, cannot ship an iOS app)? Does it impact development (ex. flutter doctor crashes when Android Studio is installed), or the shipping production app (the app crashes on launch) The positions of display cutouts as reported by `MediaQuery` would not properly update on screen orientation. ### Workaround: Is there a workaround for this issue? N/A ### Risk: What is the risk level of this cherry-pick? ### Test Coverage: Are you confident that your fix is well-tested by automated tests? ### Validation Steps: What are the steps to validate that this fix works? Run the code sample provided by flutter/flutter#155658 on Android and change the screen orientation.
Test that the position of a cutout as reported by the Android engine repositions based on screen orientation. Related to flutter/engine#55992 Part of #155658 to test run flutter drive integration_test/display_cutout_test.dart from dev/integration_tests/display_cutout_rotation Pr also force upgrades pub dependencies because I was getting presubmit failure in version solve. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing.
Stop including the translation of window insets cutouts to Flutter cutout DisplayFeatures in the window info listener method, which would not necessarily receive changes in the correct order/state when they update, e.g. when the screen orientation changes.
Fixes flutter/flutter#155658
If you had to change anything in the flutter/tests repo, include a link to the migration guide as per the breaking change policy.
Pre-launch Checklist
///
).If you need help, consider asking for advice on the #hackers-new channel on Discord.