Revert "Reland Display Features support (Foldable and Cutout) (#29447)" (flutter/engine#29574)

This reverts commit 28a1c9b21b.
This commit is contained in:
Zachary Anderson
2021-11-06 20:43:44 -07:00
committed by GitHub
parent 3251f5df50
commit 9dffe2d4f6
29 changed files with 88 additions and 890 deletions

2
DEPS
View File

@@ -570,7 +570,7 @@ deps = {
'packages': [
{
'package': 'flutter/android/embedding_bundle',
'version': 'last_updated:2021-11-03T10:29:50-0700'
'version': 'last_updated:2021-10-28T23:34:47-0700'
}
],
'condition': 'download_android_deps',

View File

@@ -832,7 +832,6 @@ FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/Rende
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/SplashScreen.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/SplashScreenProvider.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/TransparencyMode.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/android/WindowInfoRepositoryCallbackAdapterWrapper.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngine.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngineCache.java
FILE: ../../../flutter/shell/platform/android/io/flutter/embedding/engine/FlutterEngineConnectionRegistry.java

View File

@@ -339,7 +339,7 @@ void hooksTests() {
window.onMetricsChanged!();
_callHook(
'_updateWindowMetrics',
20,
17,
0, // window Id
0.1234, // device pixel ratio
0.0, // width
@@ -355,11 +355,8 @@ void hooksTests() {
0.0, // system gesture inset top
0.0, // system gesture inset right
0.0, // system gesture inset bottom
0.0, // system gesture inset left
0.0, // system gesture inset left,
22.0, // physicalTouchSlop
<double>[], // display features bounds
<int>[], // display features types
<int>[], // display features states
);
expectIdentical(originalZone, callbackZone);
@@ -406,7 +403,7 @@ void hooksTests() {
test('Window padding/insets/viewPadding/systemGestureInsets', () {
_callHook(
'_updateWindowMetrics',
20,
17,
0, // window Id
1.0, // devicePixelRatio
800.0, // width
@@ -424,9 +421,6 @@ void hooksTests() {
0.0, // systemGestureInsetBottom
0.0, // systemGestureInsetLeft
22.0, // physicalTouchSlop
<double>[], // display features bounds
<int>[], // display features types
<int>[], // display features states
);
expectEquals(window.viewInsets.bottom, 0.0);
@@ -436,7 +430,7 @@ void hooksTests() {
_callHook(
'_updateWindowMetrics',
20,
17,
0, // window Id
1.0, // devicePixelRatio
800.0, // width
@@ -454,9 +448,6 @@ void hooksTests() {
44.0, // systemGestureInsetBottom
0.0, // systemGestureInsetLeft
22.0, // physicalTouchSlop
<double>[], // display features bounds
<int>[], // display features types
<int>[], // display features states
);
expectEquals(window.viewInsets.bottom, 400.0);
@@ -468,7 +459,7 @@ void hooksTests() {
test('Window physical touch slop', () {
_callHook(
'_updateWindowMetrics',
20,
17,
0, // window Id
1.0, // devicePixelRatio
800.0, // width
@@ -486,9 +477,6 @@ void hooksTests() {
0.0, // systemGestureInsetBottom
0.0, // systemGestureInsetLeft
11.0, // physicalTouchSlop
<double>[], // display features bounds
<int>[], // display features types
<int>[], // display features states
);
expectEquals(window.viewConfiguration.gestureSettings,
@@ -496,7 +484,7 @@ void hooksTests() {
_callHook(
'_updateWindowMetrics',
20,
17,
0, // window Id
1.0, // devicePixelRatio
800.0, // width
@@ -514,9 +502,6 @@ void hooksTests() {
44.0, // systemGestureInsetBottom
0.0, // systemGestureInsetLeft
-1.0, // physicalTouchSlop
<double>[], // display features bounds
<int>[], // display features types
<int>[], // display features states
);
expectEquals(window.viewConfiguration.gestureSettings,
@@ -524,7 +509,7 @@ void hooksTests() {
_callHook(
'_updateWindowMetrics',
20,
17,
0, // window Id
1.0, // devicePixelRatio
800.0, // width
@@ -542,9 +527,6 @@ void hooksTests() {
44.0, // systemGestureInsetBottom
0.0, // systemGestureInsetLeft
22.0, // physicalTouchSlop
<double>[], // display features bounds
<int>[], // display features types
<int>[], // display features states
);
expectEquals(window.viewConfiguration.gestureSettings,
@@ -770,7 +752,4 @@ void _callHook(
Object? arg15,
Object? arg16,
Object? arg17,
Object? arg18,
Object? arg19,
Object? arg20,
]) native 'CallHook';

View File

@@ -26,9 +26,6 @@ void _updateWindowMetrics(
double systemGestureInsetBottom,
double systemGestureInsetLeft,
double physicalTouchSlop,
List<double> displayFeaturesBounds,
List<int> displayFeaturesType,
List<int> displayFeaturesState,
) {
PlatformDispatcher.instance._updateWindowMetrics(
id,
@@ -48,9 +45,6 @@ void _updateWindowMetrics(
systemGestureInsetBottom,
systemGestureInsetLeft,
physicalTouchSlop,
displayFeaturesBounds,
displayFeaturesType,
displayFeaturesState,
);
}

View File

@@ -183,9 +183,6 @@ class PlatformDispatcher {
double systemGestureInsetBottom,
double systemGestureInsetLeft,
double physicalTouchSlop,
List<double> displayFeaturesBounds,
List<int> displayFeaturesType,
List<int> displayFeaturesState,
) {
final ViewConfiguration previousConfiguration =
_viewConfigurations[id] ?? const ViewConfiguration();
@@ -224,43 +221,10 @@ class PlatformDispatcher {
gestureSettings: GestureSettings(
physicalTouchSlop: physicalTouchSlop == _kUnsetGestureSetting ? null : physicalTouchSlop,
),
displayFeatures: _decodeDisplayFeatures(
bounds: displayFeaturesBounds,
type: displayFeaturesType,
state: displayFeaturesState,
devicePixelRatio: devicePixelRatio,
),
);
_invoke(onMetricsChanged, _onMetricsChangedZone);
}
List<DisplayFeature> _decodeDisplayFeatures({
required List<double> bounds,
required List<int> type,
required List<int> state,
required double devicePixelRatio,
}) {
assert(bounds.length / 4 == type.length, 'Bounds are rectangles, requiring 4 measurements each');
assert(type.length == state.length);
final List<DisplayFeature> result = <DisplayFeature>[];
for(int i = 0; i < type.length; i++){
final int rectOffset = i * 4;
result.add(DisplayFeature(
bounds: Rect.fromLTRB(
bounds[rectOffset] / devicePixelRatio,
bounds[rectOffset + 1] / devicePixelRatio,
bounds[rectOffset + 2] / devicePixelRatio,
bounds[rectOffset + 3] / devicePixelRatio,
),
type: DisplayFeatureType.values[type[i]],
state: state[i] < DisplayFeatureState.values.length
? DisplayFeatureState.values[state[i]]
: DisplayFeatureState.unknown,
));
}
return result;
}
/// A callback invoked when any view begins a frame.
///
/// A callback that is invoked to notify the application that it is an
@@ -1071,7 +1035,6 @@ class ViewConfiguration {
this.systemGestureInsets = WindowPadding.zero,
this.padding = WindowPadding.zero,
this.gestureSettings = const GestureSettings(),
this.displayFeatures = const <DisplayFeature>[],
});
/// Copy this configuration with some fields replaced.
@@ -1084,8 +1047,7 @@ class ViewConfiguration {
WindowPadding? viewPadding,
WindowPadding? systemGestureInsets,
WindowPadding? padding,
GestureSettings? gestureSettings,
List<DisplayFeature>? displayFeatures,
GestureSettings? gestureSettings
}) {
return ViewConfiguration(
window: window ?? this.window,
@@ -1097,7 +1059,6 @@ class ViewConfiguration {
systemGestureInsets: systemGestureInsets ?? this.systemGestureInsets,
padding: padding ?? this.padding,
gestureSettings: gestureSettings ?? this.gestureSettings,
displayFeatures: displayFeatures ?? this.displayFeatures,
);
}
@@ -1177,26 +1138,6 @@ class ViewConfiguration {
/// touch slop constant.
final GestureSettings gestureSettings;
/// {@template dart.ui.ViewConfiguration.displayFeatures}
/// Areas of the display that are obstructed by hardware features.
///
/// This list is populated only on Android. If the device has no display
/// features, this list is empty.
///
/// The coordinate space in which the [DisplayFeature.bounds] are defined spans
/// across the screens currently in use. This means that the space between the screens
/// is virtually part of the Flutter view space, with the [DisplayFeature.bounds]
/// of the display feature as an obstructed area. The [DisplayFeature.type] can
/// be used to determine if this display feature obstructs the screen or not.
/// For example, [DisplayFeatureType.hinge] and [DisplayFeatureType.cutout] both
/// obstruct the display, while [DisplayFeatureType.fold] is a crease in the display.
///
/// Folding [DisplayFeature]s like the [DisplayFeatureType.hinge] and
/// [DisplayFeatureType.fold] also have a [DisplayFeature.state] which can be
/// used to determine the posture the device is in.
/// {@endtemplate}
final List<DisplayFeature> displayFeatures;
@override
String toString() {
return '$runtimeType[window: $window, geometry: $geometry]';
@@ -1502,134 +1443,6 @@ class WindowPadding {
}
}
/// Area of the display that may be obstructed by a hardware feature.
///
/// This is populated only on Android.
///
/// The [bounds] are measured in logical pixels. On devices with two screens the
/// coordinate system starts with [0,0] in the top-left corner of the left or top screen
/// and expands to include both screens and the visual space between them.
///
/// The [type] describes the behaviour and if [DisplayFeature] obstructs the display.
/// For example, [DisplayFeatureType.hinge] and [DisplayFeatureType.cutout] both obstruct the display,
/// while [DisplayFeatureType.fold] does not.
///
/// ![Device with a hinge display feature](https://flutter.github.io/assets-for-api-docs/assets/hardware/display_feature_hinge.png)
///
/// ![Device with a fold display feature](https://flutter.github.io/assets-for-api-docs/assets/hardware/display_feature_fold.png)
///
/// ![Device with a cutout display feature](https://flutter.github.io/assets-for-api-docs/assets/hardware/display_feature_cutout.png)
///
/// The [state] contains information about the posture for foldable features
/// ([DisplayFeatureType.hinge] and [DisplayFeatureType.fold]). The posture is
/// the shape of the display, for example [DisplayFeatureState.postureFlat] or
/// [DisplayFeatureState.postureHalfOpened]. For [DisplayFeatureType.cutout],
/// the state is not used and has the [DisplayFeatureState.unknown] value.
class DisplayFeature {
const DisplayFeature({
required this.bounds,
required this.type,
required this.state,
}) : assert(!identical(type, DisplayFeatureType.cutout) || identical(state, DisplayFeatureState.unknown));
/// The area of the flutter view occupied by this display feature, measured in logical pixels.
///
/// On devices with two screens, the Flutter view spans from the top-left corner
/// of the left or top screen to the bottom-right corner of the right or bottom screen,
/// including the visual area occupied by any display feature. Bounds of display
/// features are reported in this coordinate system.
///
/// For example, on a dual screen device in portrait mode:
///
/// * [bounds.left] gives you the size of left screen, in logical pixels.
/// * [bounds.right] gives you the size of the left screen + the hinge width.
final Rect bounds;
/// Type of display feature, e.g. hinge, fold, cutout.
final DisplayFeatureType type;
/// Posture of display feature, which is populated only for folds and hinges.
///
/// For cutouts, this is [DisplayFeatureState.unknown]
final DisplayFeatureState state;
@override
bool operator ==(Object other) {
if (identical(this, other))
return true;
if (other.runtimeType != runtimeType)
return false;
return other is DisplayFeature && bounds == other.bounds &&
type == other.type && state == other.state;
}
@override
int get hashCode => hashValues(bounds, type, state);
@override
String toString() {
return 'DisplayFeature(rect: $bounds, type: $type, state: $state)';
}
}
/// Type of [DisplayFeature], describing the [DisplayFeature] behaviour and if
/// it obstructs the display.
///
/// Some types of [DisplayFeature], like [DisplayFeatureType.fold], can be
/// reported without actually impeding drawing on the screen. They are useful
/// for knowing where the display is bent or has a crease. The
/// [DisplayFeature.bounds] can be 0-width in such cases.
///
/// The shape formed by the screens for types [DisplayFeatureType.fold] and
/// [DisplayFeatureType.hinge] is called the posture and is exposed in
/// [DisplayFeature.state]. For example, the [DisplayFeatureState.postureFlat] posture
/// means the screens form a flat surface, while [DisplayFeatureState.postureFlipped]
/// posture means the screens are facing opposite directions.
///
/// ![Device with a hinge display feature](https://flutter.github.io/assets-for-api-docs/assets/hardware/display_feature_hinge.png)
///
/// ![Device with a fold display feature](https://flutter.github.io/assets-for-api-docs/assets/hardware/display_feature_fold.png)
///
/// ![Device with a cutout display feature](https://flutter.github.io/assets-for-api-docs/assets/hardware/display_feature_cutout.png)
enum DisplayFeatureType {
/// [DisplayFeature] type is new and not yet known to Flutter.
unknown,
/// A fold in the flexible screen without a physical gap.
///
/// The bounds for this display feature type indicate where the display makes a crease.
fold,
/// A physical separation with a hinge that allows two display panels to fold.
hinge,
/// A non-displaying area of the screen, usually housing cameras or sensors.
cutout,
}
/// State of the display feature, which contains information about the posture
/// for foldable features.
///
/// The posture is the shape made by the parts of the flexible screen or
/// physical screen panels. They are inspired by and similar to
/// [Android Postures](https://developer.android.com/guide/topics/ui/foldables#postures).
///
/// * For [DisplayFeatureType.fold]s & [DisplayFeatureType.hinge]s, the state is
/// the posture.
/// * For [DisplayFeatureType.cutout]s, the state is not used and has the
/// [DisplayFeatureState.unknown] value.
enum DisplayFeatureState {
/// The display feature is a [DisplayFeatureType.cutout] or this state is new
/// and not yet known to Flutter.
unknown,
/// The foldable device is completely open.
///
/// The screen space that is presented to the user is flat.
postureFlat,
/// Fold angle is in an intermediate position between opened and closed state.
///
/// There is a non-flat angle between parts of the flexible screen or between
/// physical screen panels such that the screens start to face each other.
postureHalfOpened,
}
/// An identifier used to select a user's language and formatting preferences.
///
/// This represents a [Unicode Language

View File

@@ -225,17 +225,6 @@ abstract class FlutterView {
/// applications.
WindowPadding get padding => viewConfiguration.padding;
/// {@macro dart.ui.ViewConfiguration.displayFeatures}
///
/// When this changes, [onMetricsChanged] is called.
///
/// See also:
///
/// * [WidgetsBindingObserver], for a mechanism at the widgets layer to
/// observe when this value changes.
/// * [MediaQuery.of], a simpler mechanism to access this data.
List<DisplayFeature> get displayFeatures => viewConfiguration.displayFeatures;
/// Updates the view's rendering on the GPU with the newly provided [Scene].
///
/// This function must be called within the scope of the

View File

@@ -19,26 +19,22 @@ ViewportMetrics::ViewportMetrics(double p_device_pixel_ratio,
physical_height(p_physical_height),
physical_touch_slop(p_physical_touch_slop) {}
ViewportMetrics::ViewportMetrics(
double p_device_pixel_ratio,
double p_physical_width,
double p_physical_height,
double p_physical_padding_top,
double p_physical_padding_right,
double p_physical_padding_bottom,
double p_physical_padding_left,
double p_physical_view_inset_top,
double p_physical_view_inset_right,
double p_physical_view_inset_bottom,
double p_physical_view_inset_left,
double p_physical_system_gesture_inset_top,
double p_physical_system_gesture_inset_right,
double p_physical_system_gesture_inset_bottom,
double p_physical_system_gesture_inset_left,
double p_physical_touch_slop,
const std::vector<double> p_physical_display_features_bounds,
const std::vector<int> p_physical_display_features_type,
const std::vector<int> p_physical_display_features_state)
ViewportMetrics::ViewportMetrics(double p_device_pixel_ratio,
double p_physical_width,
double p_physical_height,
double p_physical_padding_top,
double p_physical_padding_right,
double p_physical_padding_bottom,
double p_physical_padding_left,
double p_physical_view_inset_top,
double p_physical_view_inset_right,
double p_physical_view_inset_bottom,
double p_physical_view_inset_left,
double p_physical_system_gesture_inset_top,
double p_physical_system_gesture_inset_right,
double p_physical_system_gesture_inset_bottom,
double p_physical_system_gesture_inset_left,
double p_physical_touch_slop)
: device_pixel_ratio(p_device_pixel_ratio),
physical_width(p_physical_width),
physical_height(p_physical_height),
@@ -56,10 +52,7 @@ ViewportMetrics::ViewportMetrics(
physical_system_gesture_inset_bottom(
p_physical_system_gesture_inset_bottom),
physical_system_gesture_inset_left(p_physical_system_gesture_inset_left),
physical_touch_slop(p_physical_touch_slop),
physical_display_features_bounds(p_physical_display_features_bounds),
physical_display_features_type(p_physical_display_features_type),
physical_display_features_state(p_physical_display_features_state) {}
physical_touch_slop(p_physical_touch_slop) {}
bool operator==(const ViewportMetrics& a, const ViewportMetrics& b) {
return a.device_pixel_ratio == b.device_pixel_ratio &&
@@ -81,11 +74,7 @@ bool operator==(const ViewportMetrics& a, const ViewportMetrics& b) {
b.physical_system_gesture_inset_bottom &&
a.physical_system_gesture_inset_left ==
b.physical_system_gesture_inset_left &&
a.physical_touch_slop == b.physical_touch_slop &&
a.physical_display_features_bounds ==
b.physical_display_features_bounds &&
a.physical_display_features_type == b.physical_display_features_type &&
a.physical_display_features_state == b.physical_display_features_state;
a.physical_touch_slop == b.physical_touch_slop;
}
std::ostream& operator<<(std::ostream& os, const ViewportMetrics& a) {
@@ -100,8 +89,7 @@ std::ostream& operator<<(std::ostream& os, const ViewportMetrics& a) {
<< "Gesture Insets: [" << a.physical_system_gesture_inset_top << "T "
<< a.physical_system_gesture_inset_right << "R "
<< a.physical_system_gesture_inset_bottom << "B "
<< a.physical_system_gesture_inset_left << "L] "
<< "Display Features: " << a.physical_display_features_type.size();
<< a.physical_system_gesture_inset_left << "L]";
return os;
}

View File

@@ -6,7 +6,6 @@
#define FLUTTER_LIB_UI_WINDOW_VIEWPORT_METRICS_H_
#include <ostream>
#include <vector>
namespace flutter {
@@ -31,10 +30,7 @@ struct ViewportMetrics {
double p_physical_system_gesture_inset_right,
double p_physical_system_gesture_inset_bottom,
double p_physical_system_gesture_inset_left,
double p_physical_touch_slop,
const std::vector<double> p_physical_display_features_bounds,
const std::vector<int> p_physical_display_features_type,
const std::vector<int> p_physical_display_features_state);
double p_physical_touch_slop);
double device_pixel_ratio = 1.0;
double physical_width = 0;
@@ -52,9 +48,6 @@ struct ViewportMetrics {
double physical_system_gesture_inset_bottom = 0;
double physical_system_gesture_inset_left = 0;
double physical_touch_slop = -1.0;
std::vector<double> physical_display_features_bounds;
std::vector<int> physical_display_features_type;
std::vector<int> physical_display_features_state;
};
bool operator==(const ViewportMetrics& a, const ViewportMetrics& b);

View File

@@ -64,28 +64,22 @@ void Window::UpdateWindowMetrics(const ViewportMetrics& metrics) {
tonic::DartState::Scope scope(dart_state);
tonic::LogIfError(tonic::DartInvokeField(
library_.value(), "_updateWindowMetrics",
{
tonic::ToDart(window_id_),
tonic::ToDart(metrics.device_pixel_ratio),
tonic::ToDart(metrics.physical_width),
tonic::ToDart(metrics.physical_height),
tonic::ToDart(metrics.physical_padding_top),
tonic::ToDart(metrics.physical_padding_right),
tonic::ToDart(metrics.physical_padding_bottom),
tonic::ToDart(metrics.physical_padding_left),
tonic::ToDart(metrics.physical_view_inset_top),
tonic::ToDart(metrics.physical_view_inset_right),
tonic::ToDart(metrics.physical_view_inset_bottom),
tonic::ToDart(metrics.physical_view_inset_left),
tonic::ToDart(metrics.physical_system_gesture_inset_top),
tonic::ToDart(metrics.physical_system_gesture_inset_right),
tonic::ToDart(metrics.physical_system_gesture_inset_bottom),
tonic::ToDart(metrics.physical_system_gesture_inset_left),
tonic::ToDart(metrics.physical_touch_slop),
tonic::ToDart(metrics.physical_display_features_bounds),
tonic::ToDart(metrics.physical_display_features_type),
tonic::ToDart(metrics.physical_display_features_state),
}));
{tonic::ToDart(window_id_), tonic::ToDart(metrics.device_pixel_ratio),
tonic::ToDart(metrics.physical_width),
tonic::ToDart(metrics.physical_height),
tonic::ToDart(metrics.physical_padding_top),
tonic::ToDart(metrics.physical_padding_right),
tonic::ToDart(metrics.physical_padding_bottom),
tonic::ToDart(metrics.physical_padding_left),
tonic::ToDart(metrics.physical_view_inset_top),
tonic::ToDart(metrics.physical_view_inset_right),
tonic::ToDart(metrics.physical_view_inset_bottom),
tonic::ToDart(metrics.physical_view_inset_left),
tonic::ToDart(metrics.physical_system_gesture_inset_top),
tonic::ToDart(metrics.physical_system_gesture_inset_right),
tonic::ToDart(metrics.physical_system_gesture_inset_bottom),
tonic::ToDart(metrics.physical_system_gesture_inset_left),
tonic::ToDart(metrics.physical_touch_slop)}));
}
} // namespace flutter

View File

@@ -156,7 +156,6 @@ class ViewConfiguration {
this.systemGestureInsets = WindowPadding.zero,
this.padding = WindowPadding.zero,
this.gestureSettings = const GestureSettings(),
this.displayFeatures = const <DisplayFeature>[],
});
ViewConfiguration copyWith({
@@ -169,7 +168,6 @@ class ViewConfiguration {
WindowPadding? systemGestureInsets,
WindowPadding? padding,
GestureSettings? gestureSettings,
List<DisplayFeature>? displayFeatures,
}) {
return ViewConfiguration(
window: window ?? this.window,
@@ -181,7 +179,6 @@ class ViewConfiguration {
systemGestureInsets: systemGestureInsets ?? this.systemGestureInsets,
padding: padding ?? this.padding,
gestureSettings: gestureSettings ?? this.gestureSettings,
displayFeatures: displayFeatures ?? this.displayFeatures,
);
}
@@ -194,7 +191,6 @@ class ViewConfiguration {
final WindowPadding systemGestureInsets;
final WindowPadding padding;
final GestureSettings gestureSettings;
final List<DisplayFeature> displayFeatures;
@override
String toString() {
@@ -329,50 +325,6 @@ abstract class WindowPadding {
}
}
class DisplayFeature {
const DisplayFeature({
required this.bounds,
required this.type,
required this.state,
});
final Rect bounds;
final DisplayFeatureType type;
final DisplayFeatureState state;
@override
bool operator ==(Object other) {
if (identical(this, other))
return true;
if (other.runtimeType != runtimeType)
return false;
return other is DisplayFeature && bounds == other.bounds &&
type == other.type && state == other.state;
}
@override
int get hashCode => hashValues(bounds, type, state);
@override
String toString() {
return 'DisplayFeature(rect: $bounds, type: $type, state: $state)';
}
}
enum DisplayFeatureType {
unknown,
fold,
hinge,
cutout,
}
enum DisplayFeatureState {
unknown,
postureFlat,
postureHalfOpened,
postureFlipped,
}
class Locale {
const Locale(
this._languageCode, [

View File

@@ -14,7 +14,6 @@ abstract class FlutterView {
WindowPadding get viewPadding => viewConfiguration.viewPadding;
WindowPadding get systemGestureInsets => viewConfiguration.systemGestureInsets;
WindowPadding get padding => viewConfiguration.padding;
List<DisplayFeature> get displayFeatures => viewConfiguration.displayFeatures;
void render(Scene scene) => platformDispatcher.render(scene, this);
}

View File

@@ -111,25 +111,22 @@ void ShellTest::VSyncFlush(Shell* shell, bool& will_draw_new_frame) {
void ShellTest::SetViewportMetrics(Shell* shell, double width, double height) {
flutter::ViewportMetrics viewport_metrics = {
1, // device pixel ratio
width, // physical width
height, // physical height
0, // padding top
0, // padding right
0, // padding bottom
0, // padding left
0, // view inset top
0, // view inset right
0, // view inset bottom
0, // view inset left
0, // gesture inset top
0, // gesture inset right
0, // gesture inset bottom
0, // gesture inset left
22, // physical touch slop
std::vector<double>(), // display features bounds
std::vector<int>(), // display features type
std::vector<int>() // display features state
1, // device pixel ratio
width, // physical width
height, // physical height
0, // padding top
0, // padding right
0, // padding bottom
0, // padding left
0, // view inset top
0, // view inset right
0, // view inset bottom
0, // view inset left
0, // gesture inset top
0, // gesture inset right
0, // gesture inset bottom
0, // gesture inset left
22 // physical touch slop
};
// Set viewport to nonempty, and call Animator::BeginFrame to make the layer
// tree pipeline nonempty. Without either of this, the layer tree below

View File

@@ -179,7 +179,6 @@ android_java_sources = [
"io/flutter/embedding/android/SplashScreen.java",
"io/flutter/embedding/android/SplashScreenProvider.java",
"io/flutter/embedding/android/TransparencyMode.java",
"io/flutter/embedding/android/WindowInfoRepositoryCallbackAdapterWrapper.java",
"io/flutter/embedding/engine/FlutterEngine.java",
"io/flutter/embedding/engine/FlutterEngineCache.java",
"io/flutter/embedding/engine/FlutterEngineConnectionRegistry.java",

View File

@@ -6,7 +6,6 @@ package io.flutter.embedding.android;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Insets;
@@ -36,20 +35,9 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.annotation.VisibleForTesting;
import androidx.core.content.ContextCompat;
import androidx.core.util.Consumer;
import androidx.window.java.layout.WindowInfoRepositoryCallbackAdapter;
import androidx.window.layout.DisplayFeature;
import androidx.window.layout.FoldingFeature;
import androidx.window.layout.FoldingFeature.OcclusionType;
import androidx.window.layout.FoldingFeature.State;
import androidx.window.layout.WindowInfoRepository;
import androidx.window.layout.WindowLayoutInfo;
import io.flutter.Log;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.renderer.FlutterRenderer;
import io.flutter.embedding.engine.renderer.FlutterRenderer.DisplayFeatureState;
import io.flutter.embedding.engine.renderer.FlutterRenderer.DisplayFeatureType;
import io.flutter.embedding.engine.renderer.FlutterUiDisplayListener;
import io.flutter.embedding.engine.renderer.RenderSurface;
import io.flutter.embedding.engine.systemchannels.SettingsChannel;
@@ -60,9 +48,7 @@ import io.flutter.plugin.platform.PlatformViewsController;
import io.flutter.view.AccessibilityBridge;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
@@ -124,8 +110,6 @@ public class FlutterView extends FrameLayout implements MouseCursorPlugin.MouseC
@Nullable private AndroidTouchProcessor androidTouchProcessor;
@Nullable private AccessibilityBridge accessibilityBridge;
// Provides access to foldable/hinge information
@Nullable private WindowInfoRepositoryCallbackAdapterWrapper windowInfoRepo;
// Directly implemented View behavior that communicates with Flutter.
private final FlutterRenderer.ViewportMetrics viewportMetrics =
new FlutterRenderer.ViewportMetrics();
@@ -160,14 +144,6 @@ public class FlutterView extends FrameLayout implements MouseCursorPlugin.MouseC
}
};
private final Consumer<WindowLayoutInfo> windowInfoListener =
new Consumer<WindowLayoutInfo>() {
@Override
public void accept(WindowLayoutInfo layoutInfo) {
setWindowInfoListenerDisplayFeatures(layoutInfo);
}
};
/**
* Constructs a {@code FlutterView} programmatically, without any XML attributes.
*
@@ -450,114 +426,6 @@ public class FlutterView extends FrameLayout implements MouseCursorPlugin.MouseC
sendViewportMetricsToFlutter();
}
@VisibleForTesting()
protected WindowInfoRepositoryCallbackAdapterWrapper createWindowInfoRepo() {
try {
return new WindowInfoRepositoryCallbackAdapterWrapper(
new WindowInfoRepositoryCallbackAdapter(
WindowInfoRepository.getOrCreate((Activity) getContext())));
} catch (NoClassDefFoundError noClassDefFoundError) {
// Testing environment uses gn/javac, which does not work with aar files. This is why aar
// are converted to jar files, losing resources and other android-specific files.
// androidx.window does contain resources, which causes it to fail during testing, since the
// class androidx.window.R is not found.
// This method is mocked in the tests involving androidx.window, but this catch block is
// needed for other tests, which would otherwise fail during onAttachedToWindow().
return null;
}
}
/**
* Invoked when this is attached to the window.
*
* <p>We register for {@link androidx.window.layout.WindowInfoRepository} updates.
*/
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
this.windowInfoRepo = createWindowInfoRepo();
if (windowInfoRepo != null) {
windowInfoRepo.addWindowLayoutInfoListener(
ContextCompat.getMainExecutor(getContext()), windowInfoListener);
}
}
/**
* Invoked when this is detached from the window.
*
* <p>We unregister from {@link androidx.window.layout.WindowInfoRepository} updates.
*/
@Override
protected void onDetachedFromWindow() {
if (windowInfoRepo != null) {
windowInfoRepo.removeWindowLayoutInfoListener(windowInfoListener);
}
this.windowInfoRepo = null;
super.onDetachedFromWindow();
}
/**
* Refresh {@link androidx.window.layout.WindowInfoRepository} and {@link
* android.view.DisplayCutout} display features. Fold, hinge and cutout areas are populated here.
*/
@TargetApi(28)
protected void setWindowInfoListenerDisplayFeatures(WindowLayoutInfo layoutInfo) {
List<DisplayFeature> displayFeatures = layoutInfo.getDisplayFeatures();
List<FlutterRenderer.DisplayFeature> result = new ArrayList<>();
// Data from WindowInfoRepository display features. Fold and hinge areas are
// populated here.
for (DisplayFeature displayFeature : displayFeatures) {
Log.v(
TAG,
"WindowInfoRepository Display Feature reported with bounds = "
+ displayFeature.getBounds().toString()
+ " and type = "
+ displayFeature.getClass().getSimpleName());
if (displayFeature instanceof FoldingFeature) {
DisplayFeatureType type;
DisplayFeatureState state;
final FoldingFeature feature = (FoldingFeature) displayFeature;
if (feature.getOcclusionType() == OcclusionType.FULL) {
type = DisplayFeatureType.HINGE;
} else {
type = DisplayFeatureType.FOLD;
}
if (feature.getState() == State.FLAT) {
state = DisplayFeatureState.POSTURE_FLAT;
} else if (feature.getState() == State.HALF_OPENED) {
state = DisplayFeatureState.POSTURE_HALF_OPENED;
} else {
state = DisplayFeatureState.UNKNOWN;
}
result.add(new FlutterRenderer.DisplayFeature(displayFeature.getBounds(), type, state));
} else {
result.add(
new FlutterRenderer.DisplayFeature(
displayFeature.getBounds(),
DisplayFeatureType.UNKNOWN,
DisplayFeatureState.UNKNOWN));
}
}
// Data from the DisplayCutout bounds. Cutouts for cameras and other sensors are
// populated here. DisplayCutout was introduced in API 28.
if (Build.VERSION.SDK_INT >= 28) {
WindowInsets insets = getRootWindowInsets();
if (insets != null) {
DisplayCutout cutout = insets.getDisplayCutout();
if (cutout != null) {
for (Rect bounds : cutout.getBoundingRects()) {
Log.v(TAG, "DisplayCutout area reported with bounds = " + bounds.toString());
result.add(new FlutterRenderer.DisplayFeature(bounds, DisplayFeatureType.CUTOUT));
}
}
}
}
viewportMetrics.displayFeatures = result;
sendViewportMetricsToFlutter();
}
// TODO(garyq): Add support for notch cutout API: https://github.com/flutter/flutter/issues/56592
// Decide if we want to zero the padding of the sides. When in Landscape orientation,
// android may decide to place the software navigation bars on the side. When the nav

View File

@@ -1,30 +0,0 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package io.flutter.embedding.android;
import androidx.core.util.Consumer;
import androidx.window.java.layout.WindowInfoRepositoryCallbackAdapter;
import androidx.window.layout.WindowLayoutInfo;
import java.util.concurrent.Executor;
/**
* Wraps {@link WindowInfoRepositoryCallbackAdapter} in order to be able to mock it during testing.
*/
public class WindowInfoRepositoryCallbackAdapterWrapper {
final WindowInfoRepositoryCallbackAdapter adapter;
public WindowInfoRepositoryCallbackAdapterWrapper(WindowInfoRepositoryCallbackAdapter adapter) {
this.adapter = adapter;
}
public void addWindowLayoutInfoListener(Executor executor, Consumer<WindowLayoutInfo> consumer) {
adapter.addWindowLayoutInfoListener(executor, consumer);
}
public void removeWindowLayoutInfoListener(Consumer<WindowLayoutInfo> consumer) {
adapter.removeWindowLayoutInfoListener(consumer);
}
}

View File

@@ -580,10 +580,7 @@ public class FlutterJNI {
int systemGestureInsetRight,
int systemGestureInsetBottom,
int systemGestureInsetLeft,
int physicalTouchSlop,
int[] displayFeaturesBounds,
int[] displayFeaturesType,
int[] displayFeaturesState) {
int physicalTouchSlop) {
ensureRunningOnMainThread();
ensureAttachedToNative();
nativeSetViewportMetrics(
@@ -603,10 +600,7 @@ public class FlutterJNI {
systemGestureInsetRight,
systemGestureInsetBottom,
systemGestureInsetLeft,
physicalTouchSlop,
displayFeaturesBounds,
displayFeaturesType,
displayFeaturesState);
physicalTouchSlop);
}
private native void nativeSetViewportMetrics(
@@ -626,10 +620,7 @@ public class FlutterJNI {
int systemGestureInsetRight,
int systemGestureInsetBottom,
int systemGestureInsetLeft,
int physicalTouchSlop,
int[] displayFeaturesBounds,
int[] displayFeaturesType,
int[] displayFeaturesState);
int physicalTouchSlop);
// ----- End Render Surface Support -----
// ------ Start Touch Interaction Support ---

View File

@@ -6,7 +6,6 @@ package io.flutter.embedding.engine.renderer;
import android.annotation.TargetApi;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.os.Build;
import android.os.Handler;
@@ -17,8 +16,6 @@ import io.flutter.Log;
import io.flutter.embedding.engine.FlutterJNI;
import io.flutter.view.TextureRegistry;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
/**
@@ -329,23 +326,7 @@ public class FlutterRenderer implements TextureRegistry {
+ ", R: "
+ viewportMetrics.systemGestureInsetRight
+ ", B: "
+ viewportMetrics.systemGestureInsetRight
+ "\n"
+ "Display Features: "
+ viewportMetrics.displayFeatures.size());
int[] displayFeaturesBounds = new int[viewportMetrics.displayFeatures.size() * 4];
int[] displayFeaturesType = new int[viewportMetrics.displayFeatures.size()];
int[] displayFeaturesState = new int[viewportMetrics.displayFeatures.size()];
for (int i = 0; i < viewportMetrics.displayFeatures.size(); i++) {
DisplayFeature displayFeature = viewportMetrics.displayFeatures.get(i);
displayFeaturesBounds[4 * i] = displayFeature.bounds.left;
displayFeaturesBounds[4 * i + 1] = displayFeature.bounds.top;
displayFeaturesBounds[4 * i + 2] = displayFeature.bounds.right;
displayFeaturesBounds[4 * i + 3] = displayFeature.bounds.bottom;
displayFeaturesType[i] = displayFeature.type.encodedValue;
displayFeaturesState[i] = displayFeature.state.encodedValue;
}
+ viewportMetrics.viewInsetBottom);
flutterJNI.setViewportMetrics(
viewportMetrics.devicePixelRatio,
@@ -363,10 +344,7 @@ public class FlutterRenderer implements TextureRegistry {
viewportMetrics.systemGestureInsetRight,
viewportMetrics.systemGestureInsetBottom,
viewportMetrics.systemGestureInsetLeft,
viewportMetrics.physicalTouchSlop,
displayFeaturesBounds,
displayFeaturesType,
displayFeaturesState);
viewportMetrics.physicalTouchSlop);
}
// TODO(mattcarroll): describe the native behavior that this invokes
@@ -451,103 +429,5 @@ public class FlutterRenderer implements TextureRegistry {
boolean validate() {
return width > 0 && height > 0 && devicePixelRatio > 0;
}
public List<DisplayFeature> displayFeatures = new ArrayList<DisplayFeature>();
}
/**
* Description of a physical feature on the display.
*
* <p>A display feature is a distinctive physical attribute located within the display panel of
* the device. It can intrude into the application window space and create a visual distortion,
* visual or touch discontinuity, make some area invisible or create a logical divider or
* separation in the screen space.
*
* <p>Based on {@link androidx.window.layout.DisplayFeature}, with added support for cutouts.
*/
public static final class DisplayFeature {
public final Rect bounds;
public final DisplayFeatureType type;
public final DisplayFeatureState state;
public DisplayFeature(Rect bounds, DisplayFeatureType type, DisplayFeatureState state) {
this.bounds = bounds;
this.type = type;
this.state = state;
}
public DisplayFeature(Rect bounds, DisplayFeatureType type) {
this.bounds = bounds;
this.type = type;
this.state = DisplayFeatureState.UNKNOWN;
}
}
/**
* Types of display features that can appear on the viewport.
*
* <p>Some, like {@link #FOLD}, can be reported without actually occluding the screen. They are
* useful for knowing where the display is bent or has a crease. The {@link DisplayFeature#bounds}
* can be 0-width in such cases.
*/
public enum DisplayFeatureType {
/**
* Type of display feature not yet known to Flutter. This can happen if WindowManager is updated
* with new types. The {@link DisplayFeature#bounds} is the only known property.
*/
UNKNOWN(0),
/**
* A fold in the flexible display that does not occlude the screen. Corresponds to {@link
* androidx.window.layout.FoldingFeature.OcclusionType#NONE}
*/
FOLD(1),
/**
* Splits the display in two separate panels that can fold. Occludes the screen. Corresponds to
* {@link androidx.window.layout.FoldingFeature.OcclusionType#FULL}
*/
HINGE(2),
/**
* Area of the screen that usually houses cameras or sensors. Occludes the screen. Corresponds
* to {@link android.view.DisplayCutout}
*/
CUTOUT(3);
public final int encodedValue;
DisplayFeatureType(int encodedValue) {
this.encodedValue = encodedValue;
}
}
/**
* State of the display feature.
*
* <p>For foldables, the state is the posture. For cutouts, this property is {@link #UNKNOWN}
*/
public enum DisplayFeatureState {
/** The display feature is a cutout or this state is new and not yet known to Flutter. */
UNKNOWN(0),
/**
* The foldable device is completely open. The screen space that is presented to the user is
* flat. Corresponds to {@link androidx.window.layout.FoldingFeature.State#FLAT}
*/
POSTURE_FLAT(1),
/**
* The foldable device's hinge is in an intermediate position between opened and closed state.
* There is a non-flat angle between parts of the flexible screen or between physical display
* panels. Corresponds to {@link androidx.window.layout.FoldingFeature.State#HALF_OPENED}
*/
POSTURE_HALF_OPENED(2);
public final int encodedValue;
DisplayFeatureState(int encodedValue) {
this.encodedValue = encodedValue;
}
}
}

View File

@@ -751,10 +751,7 @@ public class FlutterView extends SurfaceView
mMetrics.systemGestureInsetRight,
mMetrics.systemGestureInsetBottom,
mMetrics.systemGestureInsetLeft,
mMetrics.physicalTouchSlop,
new int[0],
new int[0],
new int[0]);
mMetrics.physicalTouchSlop);
}
// Called by FlutterNativeView to notify first Flutter frame rendered.

View File

@@ -281,28 +281,7 @@ static void SetViewportMetrics(JNIEnv* env,
jint systemGestureInsetRight,
jint systemGestureInsetBottom,
jint systemGestureInsetLeft,
jint physicalTouchSlop,
jintArray javaDisplayFeaturesBounds,
jintArray javaDisplayFeaturesType,
jintArray javaDisplayFeaturesState) {
// Convert java->c++. javaDisplayFeaturesBounds, javaDisplayFeaturesType and
// javaDisplayFeaturesState cannot be null
jsize rectSize = env->GetArrayLength(javaDisplayFeaturesBounds);
std::vector<int> boundsIntVector(rectSize);
env->GetIntArrayRegion(javaDisplayFeaturesBounds, 0, rectSize,
&boundsIntVector[0]);
std::vector<double> displayFeaturesBounds(boundsIntVector.begin(),
boundsIntVector.end());
jsize typeSize = env->GetArrayLength(javaDisplayFeaturesType);
std::vector<int> displayFeaturesType(typeSize);
env->GetIntArrayRegion(javaDisplayFeaturesType, 0, typeSize,
&displayFeaturesType[0]);
jsize stateSize = env->GetArrayLength(javaDisplayFeaturesState);
std::vector<int> displayFeaturesState(stateSize);
env->GetIntArrayRegion(javaDisplayFeaturesState, 0, stateSize,
&displayFeaturesState[0]);
jint physicalTouchSlop) {
const flutter::ViewportMetrics metrics{
static_cast<double>(devicePixelRatio),
static_cast<double>(physicalWidth),
@@ -320,9 +299,6 @@ static void SetViewportMetrics(JNIEnv* env,
static_cast<double>(systemGestureInsetBottom),
static_cast<double>(systemGestureInsetLeft),
static_cast<double>(physicalTouchSlop),
displayFeaturesBounds,
displayFeaturesType,
displayFeaturesState,
};
ANDROID_SHELL_HOLDER->GetPlatformView()->SetViewportMetrics(metrics);
@@ -724,7 +700,7 @@ bool RegisterApi(JNIEnv* env) {
},
{
.name = "nativeSetViewportMetrics",
.signature = "(JFIIIIIIIIIIIIIII[I[I[I)V",
.signature = "(JFIIIIIIIIIIIIIII)V",
.fnPtr = reinterpret_cast<void*>(&SetViewportMetrics),
},
{

View File

@@ -6,7 +6,6 @@ import static junit.framework.TestCase.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
@@ -15,13 +14,11 @@ import static org.mockito.Mockito.when;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Insets;
import android.graphics.Rect;
import android.graphics.Region;
import android.hardware.HardwareBuffer;
import android.media.Image;
@@ -35,9 +32,6 @@ import android.view.ViewGroup;
import android.view.WindowInsets;
import android.view.WindowManager;
import android.widget.FrameLayout;
import androidx.core.util.Consumer;
import androidx.window.layout.FoldingFeature;
import androidx.window.layout.WindowLayoutInfo;
import io.flutter.TestUtils;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.embedding.engine.FlutterJNI;
@@ -46,7 +40,6 @@ import io.flutter.embedding.engine.renderer.FlutterRenderer;
import io.flutter.embedding.engine.systemchannels.SettingsChannel;
import io.flutter.plugin.platform.PlatformViewsController;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.Before;
import org.junit.Test;
@@ -57,7 +50,6 @@ import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.Shadows;
@@ -82,7 +74,7 @@ public class FlutterViewTest {
@Test
public void attachToFlutterEngine_alertsPlatformViews() {
FlutterView flutterView = new FlutterView(Robolectric.setupActivity(Activity.class));
FlutterView flutterView = new FlutterView(RuntimeEnvironment.application);
FlutterEngine flutterEngine =
spy(new FlutterEngine(RuntimeEnvironment.application, mockFlutterLoader, mockFlutterJni));
when(flutterEngine.getPlatformViewsController()).thenReturn(platformViewsController);
@@ -94,7 +86,7 @@ public class FlutterViewTest {
@Test
public void detachFromFlutterEngine_alertsPlatformViews() {
FlutterView flutterView = new FlutterView(Robolectric.setupActivity(Activity.class));
FlutterView flutterView = new FlutterView(RuntimeEnvironment.application);
FlutterEngine flutterEngine =
spy(new FlutterEngine(RuntimeEnvironment.application, mockFlutterLoader, mockFlutterJni));
when(flutterEngine.getPlatformViewsController()).thenReturn(platformViewsController);
@@ -107,7 +99,7 @@ public class FlutterViewTest {
@Test
public void detachFromFlutterEngine_turnsOffA11y() {
FlutterView flutterView = new FlutterView(Robolectric.setupActivity(Activity.class));
FlutterView flutterView = new FlutterView(RuntimeEnvironment.application);
FlutterEngine flutterEngine =
spy(new FlutterEngine(RuntimeEnvironment.application, mockFlutterLoader, mockFlutterJni));
FlutterRenderer flutterRenderer = spy(new FlutterRenderer(mockFlutterJni));
@@ -137,7 +129,7 @@ public class FlutterViewTest {
@Test
public void onConfigurationChanged_fizzlesWhenNullEngine() {
FlutterView flutterView = new FlutterView(Robolectric.setupActivity(Activity.class));
FlutterView flutterView = new FlutterView(RuntimeEnvironment.application);
FlutterEngine flutterEngine =
spy(new FlutterEngine(RuntimeEnvironment.application, mockFlutterLoader, mockFlutterJni));
@@ -162,7 +154,7 @@ public class FlutterViewTest {
new AtomicReference<>();
// FYI - The default brightness is LIGHT, which is why we don't need to configure it.
FlutterView flutterView = new FlutterView(Robolectric.setupActivity(Activity.class));
FlutterView flutterView = new FlutterView(RuntimeEnvironment.application);
FlutterEngine flutterEngine =
spy(new FlutterEngine(RuntimeEnvironment.application, mockFlutterLoader, mockFlutterJni));
@@ -200,7 +192,7 @@ public class FlutterViewTest {
AtomicReference<SettingsChannel.PlatformBrightness> reportedBrightness =
new AtomicReference<>();
Context spiedContext = spy(Robolectric.setupActivity(Activity.class));
Context spiedContext = spy(RuntimeEnvironment.application);
Resources spiedResources = spy(spiedContext.getResources());
when(spiedContext.getResources()).thenReturn(spiedResources);
@@ -252,7 +244,7 @@ public class FlutterViewTest {
FlutterViewTest.ShadowFullscreenViewGroup.class
})
public void setPaddingTopToZeroForFullscreenMode() {
FlutterView flutterView = new FlutterView(Robolectric.setupActivity(Activity.class));
FlutterView flutterView = new FlutterView(RuntimeEnvironment.application);
FlutterEngine flutterEngine =
spy(new FlutterEngine(RuntimeEnvironment.application, mockFlutterLoader, mockFlutterJni));
FlutterRenderer flutterRenderer = spy(new FlutterRenderer(mockFlutterJni));
@@ -292,7 +284,7 @@ public class FlutterViewTest {
FlutterViewTest.ShadowFullscreenViewGroup.class
})
public void setPaddingTopToZeroForFullscreenModeLegacy() {
FlutterView flutterView = new FlutterView(Robolectric.setupActivity(Activity.class));
FlutterView flutterView = new FlutterView(RuntimeEnvironment.application);
FlutterEngine flutterEngine =
spy(new FlutterEngine(RuntimeEnvironment.application, mockFlutterLoader, mockFlutterJni));
FlutterRenderer flutterRenderer = spy(new FlutterRenderer(mockFlutterJni));
@@ -324,7 +316,7 @@ public class FlutterViewTest {
@Config(sdk = 30)
public void reportSystemInsetWhenNotFullscreen() {
// Without custom shadows, the default system ui visibility flags is 0.
FlutterView flutterView = new FlutterView(Robolectric.setupActivity(Activity.class));
FlutterView flutterView = new FlutterView(RuntimeEnvironment.application);
assertEquals(0, flutterView.getSystemUiVisibility());
FlutterEngine flutterEngine =
@@ -363,7 +355,7 @@ public class FlutterViewTest {
@Config(sdk = 28)
public void reportSystemInsetWhenNotFullscreenLegacy() {
// Without custom shadows, the default system ui visibility flags is 0.
FlutterView flutterView = new FlutterView(Robolectric.setupActivity(Activity.class));
FlutterView flutterView = new FlutterView(RuntimeEnvironment.application);
assertEquals(0, flutterView.getSystemUiVisibility());
FlutterEngine flutterEngine =
@@ -633,84 +625,6 @@ public class FlutterViewTest {
assertEquals(100, viewportMetricsCaptor.getValue().viewInsetTop);
}
@Test
public void itRegistersAndUnregistersToWindowManager() {
Context context = Robolectric.setupActivity(Activity.class);
FlutterView flutterView = spy(new FlutterView(context));
ShadowDisplay display =
Shadows.shadowOf(
((WindowManager)
RuntimeEnvironment.systemContext.getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay());
WindowInfoRepositoryCallbackAdapterWrapper windowInfoRepo =
mock(WindowInfoRepositoryCallbackAdapterWrapper.class);
// For reasoning behing using doReturn instead of when, read "Important gotcha" at
// https://www.javadoc.io/doc/org.mockito/mockito-core/1.10.19/org/mockito/Mockito.html#13
doReturn(windowInfoRepo).when(flutterView).createWindowInfoRepo();
// When a new FlutterView is attached to the window
flutterView.onAttachedToWindow();
// Then the WindowManager callback is registered
verify(windowInfoRepo, times(1)).addWindowLayoutInfoListener(any(), any());
// When the FlutterView is detached from the window
flutterView.onDetachedFromWindow();
// Then the WindowManager callback is unregistered
verify(windowInfoRepo, times(1)).removeWindowLayoutInfoListener(any());
}
@Test
public void itSendsHingeDisplayFeatureToFlutter() {
Context context = Robolectric.setupActivity(Activity.class);
FlutterView flutterView = spy(new FlutterView(context));
ShadowDisplay display =
Shadows.shadowOf(
((WindowManager)
RuntimeEnvironment.systemContext.getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay());
when(flutterView.getContext()).thenReturn(context);
WindowInfoRepositoryCallbackAdapterWrapper windowInfoRepo =
mock(WindowInfoRepositoryCallbackAdapterWrapper.class);
doReturn(windowInfoRepo).when(flutterView).createWindowInfoRepo();
FlutterEngine flutterEngine =
spy(new FlutterEngine(RuntimeEnvironment.application, mockFlutterLoader, mockFlutterJni));
FlutterRenderer flutterRenderer = spy(new FlutterRenderer(mockFlutterJni));
when(flutterEngine.getRenderer()).thenReturn(flutterRenderer);
FoldingFeature displayFeature = mock(FoldingFeature.class);
when(displayFeature.getBounds()).thenReturn(new Rect(0, 0, 100, 100));
when(displayFeature.getOcclusionType()).thenReturn(FoldingFeature.OcclusionType.FULL);
when(displayFeature.getState()).thenReturn(FoldingFeature.State.FLAT);
WindowLayoutInfo testWindowLayout = new WindowLayoutInfo(Arrays.asList(displayFeature));
// When FlutterView is attached to the engine and window, and a hinge display feature exists
flutterView.attachToFlutterEngine(flutterEngine);
ArgumentCaptor<FlutterRenderer.ViewportMetrics> viewportMetricsCaptor =
ArgumentCaptor.forClass(FlutterRenderer.ViewportMetrics.class);
verify(flutterRenderer).setViewportMetrics(viewportMetricsCaptor.capture());
assertEquals(Arrays.asList(), viewportMetricsCaptor.getValue().displayFeatures);
flutterView.onAttachedToWindow();
ArgumentCaptor<Consumer<WindowLayoutInfo>> wmConsumerCaptor =
ArgumentCaptor.forClass((Class) Consumer.class);
verify(windowInfoRepo).addWindowLayoutInfoListener(any(), wmConsumerCaptor.capture());
Consumer<WindowLayoutInfo> wmConsumer = wmConsumerCaptor.getValue();
wmConsumer.accept(testWindowLayout);
// Then the Renderer receives the display feature
verify(flutterRenderer).setViewportMetrics(viewportMetricsCaptor.capture());
assertEquals(
FlutterRenderer.DisplayFeatureType.HINGE,
viewportMetricsCaptor.getValue().displayFeatures.get(0).type);
assertEquals(
FlutterRenderer.DisplayFeatureState.POSTURE_FLAT,
viewportMetricsCaptor.getValue().displayFeatures.get(0).state);
assertEquals(
new Rect(0, 0, 100, 100), viewportMetricsCaptor.getValue().displayFeatures.get(0).bounds);
}
@Test
public void flutterImageView_acquiresImageAndInvalidates() {
final ImageReader mockReader = mock(ImageReader.class);

View File

@@ -1,9 +1,6 @@
package io.flutter.embedding.engine.renderer;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.anyFloat;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
@@ -11,7 +8,6 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf;
import android.graphics.Rect;
import android.graphics.SurfaceTexture;
import android.os.Looper;
import android.view.Surface;
@@ -21,7 +17,6 @@ import java.util.concurrent.TimeUnit;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
@@ -224,65 +219,4 @@ public class FlutterRendererTest {
// do nothing
}
}
@Test
public void itConvertsDisplayFeatureArrayToPrimitiveArrays() {
// Setup the test.
FlutterRenderer flutterRenderer = new FlutterRenderer(fakeFlutterJNI);
FlutterRenderer.ViewportMetrics metrics = new FlutterRenderer.ViewportMetrics();
metrics.width = 1000;
metrics.height = 1000;
metrics.devicePixelRatio = 2;
metrics.displayFeatures.add(
new FlutterRenderer.DisplayFeature(
new Rect(10, 20, 30, 40),
FlutterRenderer.DisplayFeatureType.FOLD,
FlutterRenderer.DisplayFeatureState.POSTURE_HALF_OPENED));
metrics.displayFeatures.add(
new FlutterRenderer.DisplayFeature(
new Rect(50, 60, 70, 80), FlutterRenderer.DisplayFeatureType.CUTOUT));
// Execute the behavior under test.
flutterRenderer.setViewportMetrics(metrics);
// Verify behavior under test.
ArgumentCaptor<int[]> boundsCaptor = ArgumentCaptor.forClass(int[].class);
ArgumentCaptor<int[]> typeCaptor = ArgumentCaptor.forClass(int[].class);
ArgumentCaptor<int[]> stateCaptor = ArgumentCaptor.forClass(int[].class);
verify(fakeFlutterJNI)
.setViewportMetrics(
anyFloat(),
anyInt(),
anyInt(),
anyInt(),
anyInt(),
anyInt(),
anyInt(),
anyInt(),
anyInt(),
anyInt(),
anyInt(),
anyInt(),
anyInt(),
anyInt(),
anyInt(),
anyInt(),
boundsCaptor.capture(),
typeCaptor.capture(),
stateCaptor.capture());
assertArrayEquals(new int[] {10, 20, 30, 40, 50, 60, 70, 80}, boundsCaptor.getValue());
assertArrayEquals(
new int[] {
FlutterRenderer.DisplayFeatureType.FOLD.encodedValue,
FlutterRenderer.DisplayFeatureType.CUTOUT.encodedValue
},
typeCaptor.getValue());
assertArrayEquals(
new int[] {
FlutterRenderer.DisplayFeatureState.POSTURE_HALF_OPENED.encodedValue,
FlutterRenderer.DisplayFeatureState.UNKNOWN.encodedValue
},
stateCaptor.getValue());
}
}

View File

@@ -18,7 +18,6 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Insets;
@@ -68,7 +67,6 @@ import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@@ -1441,7 +1439,7 @@ public class TextInputPluginTest {
return;
}
FlutterView testView = new FlutterView(Robolectric.setupActivity(Activity.class));
FlutterView testView = new FlutterView(RuntimeEnvironment.application);
TextInputChannel textInputChannel = new TextInputChannel(mock(DartExecutor.class));
TextInputPlugin textInputPlugin =
new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
@@ -1528,7 +1526,7 @@ public class TextInputPluginTest {
return;
}
FlutterView testView = new FlutterView(Robolectric.setupActivity(Activity.class));
FlutterView testView = new FlutterView(RuntimeEnvironment.application);
TextInputChannel textInputChannel = new TextInputChannel(mock(DartExecutor.class));
TextInputPlugin textInputPlugin =
new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
@@ -1580,7 +1578,7 @@ public class TextInputPluginTest {
TestAfm testAfm =
Shadow.extract(RuntimeEnvironment.application.getSystemService(AutofillManager.class));
FlutterView testView = new FlutterView(Robolectric.setupActivity(Activity.class));
FlutterView testView = new FlutterView(RuntimeEnvironment.application);
TextInputChannel textInputChannel = new TextInputChannel(mock(DartExecutor.class));
TextInputPlugin textInputPlugin =
new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
@@ -1711,7 +1709,7 @@ public class TextInputPluginTest {
TestAfm testAfm =
Shadow.extract(RuntimeEnvironment.application.getSystemService(AutofillManager.class));
FlutterView testView = new FlutterView(Robolectric.setupActivity(Activity.class));
FlutterView testView = new FlutterView(RuntimeEnvironment.application);
TextInputChannel textInputChannel = spy(new TextInputChannel(mock(DartExecutor.class)));
TextInputPlugin textInputPlugin =
new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
@@ -1805,7 +1803,7 @@ public class TextInputPluginTest {
TestAfm testAfm =
Shadow.extract(RuntimeEnvironment.application.getSystemService(AutofillManager.class));
FlutterView testView = new FlutterView(Robolectric.setupActivity(Activity.class));
FlutterView testView = new FlutterView(RuntimeEnvironment.application);
TextInputChannel textInputChannel = new TextInputChannel(mock(DartExecutor.class));
TextInputPlugin textInputPlugin =
new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));
@@ -1969,7 +1967,7 @@ public class TextInputPluginTest {
@TargetApi(30)
@Config(sdk = 30)
public void ime_windowInsetsSync() {
FlutterView testView = new FlutterView(Robolectric.setupActivity(Activity.class));
FlutterView testView = new FlutterView(RuntimeEnvironment.application);
TextInputChannel textInputChannel = new TextInputChannel(mock(DartExecutor.class));
TextInputPlugin textInputPlugin =
new TextInputPlugin(testView, textInputChannel, mock(PlatformViewsController.class));

View File

@@ -8,7 +8,6 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.annotation.TargetApi;
import android.app.Activity;
import android.view.PointerIcon;
import io.flutter.embedding.android.FlutterView;
import io.flutter.embedding.engine.dart.DartExecutor;
@@ -19,8 +18,8 @@ import java.util.HashMap;
import org.json.JSONException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@Config(
@@ -32,7 +31,7 @@ public class MouseCursorPluginTest {
@Test
public void mouseCursorPlugin_SetsSystemCursorOnRequest() throws JSONException {
// Initialize a general MouseCursorPlugin.
FlutterView testView = spy(new FlutterView(Robolectric.setupActivity(Activity.class)));
FlutterView testView = spy(new FlutterView(RuntimeEnvironment.application));
MouseCursorChannel mouseCursorChannel = new MouseCursorChannel(mock(DartExecutor.class));
MouseCursorPlugin mouseCursorPlugin = new MouseCursorPlugin(testView, mouseCursorChannel);

View File

@@ -985,10 +985,7 @@ public class PlatformViewsControllerTest {
int systemGestureInsetRight,
int systemGestureInsetBottom,
int systemGestureInsetLeft,
int physicalTouchSlop,
int[] displayFeaturesBounds,
int[] displayFeaturesType,
int[] displayFeaturesState) {}
int physicalTouchSlop) {}
@Implementation
public void invokePlatformMessageResponseCallback(

View File

@@ -43,7 +43,6 @@ android {
testImplementation "androidx.lifecycle:lifecycle-common-java8:2.2.0"
testImplementation "androidx.test:core:1.4.0"
testImplementation "androidx.tracing:tracing:1.0.0"
testImplementation "androidx.window:window-java:1.0.0-beta03"
testImplementation "com.google.android.play:core:1.8.0"
testImplementation "com.ibm.icu:icu4j:69.1"
testImplementation "org.mockito:mockito-core:3.11.2"

View File

@@ -91,9 +91,6 @@ void FlatlandPlatformView::OnGetLayout(
0.0f, // p_physical_system_gesture_inset_bottom
0.0f, // p_physical_system_gesture_inset_left,
-1.0, // p_physical_touch_slop,
{}, // p_physical_display_features_bounds
{}, // p_physical_display_features_type
{}, // p_physical_display_features_state
});
parent_viewport_watcher_->GetLayout(

View File

@@ -253,9 +253,6 @@ void GfxPlatformView::OnScenicEvent(
0.0f, // p_physical_system_gesture_inset_bottom
0.0f, // p_physical_system_gesture_inset_left,
-1.0, // p_physical_touch_slop,
{}, // p_physical_display_features_bounds
{}, // p_physical_display_features_type
{}, // p_physical_display_features_state
});
}
}

View File

@@ -65,19 +65,5 @@
"provides": [
"androidx.core.view.WindowInsetsControllerCompat"
]
},
{
"url": "https://maven.google.com/androidx/window/window-java/1.0.0-beta03/window-java-1.0.0-beta03.aar",
"out_file_name": "androidx_window_java.aar",
"maven_dependency": "androidx.window:window-java:1.0.0-beta03",
"provides": [
"androidx.window.java.layout.WindowInfoRepositoryCallbackAdapter",
"androidx.window.layout.DisplayFeature",
"androidx.window.layout.FoldingFeature",
"androidx.window.layout.FoldingFeature.OcclusionType",
"androidx.window.layout.FoldingFeature.State",
"androidx.window.layout.WindowLayoutInfo",
"androidx.window.layout.WindowInfoRepository"
]
}
]

View File

@@ -44,7 +44,6 @@ android {
embedding "androidx.core:core:1.6.0"
embedding "androidx.fragment:fragment:1.1.0"
embedding "androidx.tracing:tracing:1.0.0"
embedding "androidx.window:window-java:1.0.0-beta03"
def lifecycle_version = "2.2.0"
embedding "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"