Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
7b7fa25
(WIP) setting up setSystemGestureExclusionRects platform channel
shihaohong Aug 23, 2019
361eb40
Merge branch 'master' of github.com:flutter/engine into set-exclusion…
shihaohong Aug 26, 2019
5245ad3
SystemGesture.setSystemGestureExclusionRects
shihaohong Aug 26, 2019
b37fa16
Cleanup Log.v and unnecessary imports
shihaohong Aug 26, 2019
c155aec
Add Javadoc
shihaohong Aug 26, 2019
53e858b
Reinclude accidentally removed log
shihaohong Aug 26, 2019
009830f
View.getSystemGestureExclusionRects platform channel
shihaohong Aug 26, 2019
9342b27
Handle error case for API level 28 and under
shihaohong Aug 26, 2019
991ad1b
Add guard clause, split encoding logic into its own method
shihaohong Aug 29, 2019
b663b90
Fix merge conflicts
shihaohong Aug 29, 2019
ef8fe9f
Reintroduce accidentally removed getSystemExclusionRects case
shihaohong Aug 29, 2019
50c6509
Add getSystemExclsionRects unit tests
shihaohong Aug 29, 2019
4a230f8
Add Javadocs, improve variable naming
shihaohong Aug 29, 2019
5537541
Add Javadocs
shihaohong Aug 29, 2019
54f01f7
Improve helper function naming
shihaohong Aug 29, 2019
1fad827
Merge branch 'get-exclusion-rects' of github.com:shihaohong/engine in…
shihaohong Aug 29, 2019
024aa3a
Incorporate code review feedback
shihaohong Aug 31, 2019
815d073
Add relevant context for the encodeExclusionRects javadoc
shihaohong Aug 31, 2019
eef30b8
Add ResultsMock back to make tests happy, will be removed in #11804
shihaohong Aug 31, 2019
3c53063
Remove accidental spaces
shihaohong Aug 31, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import io.flutter.Log;
Expand Down Expand Up @@ -145,7 +146,7 @@ private int decodeOrientations(@NonNull JSONArray encodedOrientations) throws JS
* @throws JSONException if {@code inputRects} does not contain expected keys and value types.
*/
@NonNull
private ArrayList<Rect> decodeRects(@NonNull JSONArray inputRects) throws JSONException {
private ArrayList<Rect> decodeExclusionRects(@NonNull JSONArray inputRects) throws JSONException {
ArrayList<Rect> exclusionRects = new ArrayList<Rect>();
for (int i = 0; i < inputRects.length(); i++) {
JSONObject rect = inputRects.getJSONObject(i);
Expand Down Expand Up @@ -173,6 +174,31 @@ private ArrayList<Rect> decodeRects(@NonNull JSONArray inputRects) throws JSONEx
return exclusionRects;
}

/**
* Encodes a List<Rect> provided by the Android host into an
* ArrayList<HashMap<String, Integer>>.
*
* Since View.getSystemGestureExclusionRects returns a list of Rects, these
* Rects need to be transformed into UTF-8 encoded JSON messages to be
* properly decoded by the Flutter framework.
*
* This method is used by the SystemGestures.getSystemGestureExclusionRects
* platform channel.
*/
private ArrayList<HashMap<String, Integer>> encodeExclusionRects(List<Rect> exclusionRects) {
ArrayList<HashMap<String, Integer>> encodedExclusionRects = new ArrayList<HashMap<String, Integer>>();
for (Rect rect : exclusionRects) {
HashMap<String, Integer> rectMap = new HashMap<String, Integer>();
rectMap.put("top", rect.top);
rectMap.put("right", rect.right);
rectMap.put("bottom", rect.bottom);
rectMap.put("left", rect.left);
encodedExclusionRects.add(rectMap);
}

return encodedExclusionRects;
}

@NonNull
private AppSwitcherDescription decodeAppSwitcherDescription(@NonNull JSONObject encodedDescription) throws JSONException {
int color = encodedDescription.getInt("primaryColor");
Expand Down Expand Up @@ -337,6 +363,12 @@ public interface PlatformMessageHandler {
*/
void setClipboardData(@NonNull String text);

/**
* The Flutter application would like to get the system gesture exclusion
* rects.
*/
List<Rect> getSystemGestureExclusionRects();

/**
* The Flutter application would like to set the system gesture exclusion
* rects through the given {@code rects}.
Expand Down Expand Up @@ -594,18 +626,6 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result
platformMessageHandler.popSystemNavigator();
result.success(null);
break;
case "SystemGestures.setSystemGestureExclusionRects":
if (!(arguments instanceof JSONArray)) {
String inputTypeError = "Input type is incorrect. Ensure that a List<Map<String, int>> is passed as the input for SystemGestureExclusionRects.setSystemGestureExclusionRects.";
result.error("inputTypeError", inputTypeError, null);
break;
}

JSONArray inputRects = (JSONArray) arguments;
ArrayList<Rect> decodedRects = decodeRects(inputRects);
platformMessageHandler.setSystemGestureExclusionRects(decodedRects);
result.success(null);
break;
case "Clipboard.getData": {
String contentFormatName = (String) arguments;
ClipboardContentFormat clipboardFormat = null;
Expand Down Expand Up @@ -634,6 +654,30 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result
result.success(null);
break;
}
case "SystemGestures.setSystemGestureExclusionRects":
if (!(arguments instanceof JSONArray)) {
String inputTypeError = "Input type is incorrect. Ensure that a List<Map<String, int>> is passed as the input for SystemGestureExclusionRects.setSystemGestureExclusionRects.";
result.error("inputTypeError", inputTypeError, null);
break;
}

JSONArray inputRects = (JSONArray) arguments;
ArrayList<Rect> decodedRects = decodeExclusionRects(inputRects);
platformMessageHandler.setSystemGestureExclusionRects(decodedRects);
result.success(null);
break;
case "SystemGestures.getSystemGestureExclusionRects": {
List<Rect> exclusionRects = platformMessageHandler.getSystemGestureExclusionRects();
if (exclusionRects == null) {
String incorrectApiLevel = "Exclusion rects only exist for Android API 29+.";
result.error("error", incorrectApiLevel, null);
break;
}

ArrayList<HashMap<String, Integer>> encodedExclusionRects = encodeExclusionRects(exclusionRects);
result.success(encodedExclusionRects);
break;
}
default:
result.notImplemented();
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ public void setClipboardData(@NonNull String text) {
PlatformPlugin.this.setClipboardData(text);
}

@Override
public List<Rect> getSystemGestureExclusionRects() {
return PlatformPlugin.this.getSystemGestureExclusionRects();
}

@Override
public void setSystemGestureExclusionRects(@NonNull ArrayList rects) {
PlatformPlugin.this.setSystemGestureExclusionRects(rects);
Expand Down Expand Up @@ -281,6 +286,16 @@ private void setClipboardData(String text) {
clipboard.setPrimaryClip(clip);
}

private List<Rect> getSystemGestureExclusionRects() {
if (Build.VERSION.SDK_INT >= 29) {
Window window = activity.getWindow();
View view = window.getDecorView();
return view.getSystemGestureExclusionRects();
}

return null;
}

private void setSystemGestureExclusionRects(ArrayList<Rect> rects) {
if (Build.VERSION.SDK_INT < 29) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import android.graphics.Rect;

import java.util.ArrayList;
import java.util.HashMap;

import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.embedding.engine.systemchannels.PlatformChannel;
Expand All @@ -21,6 +22,7 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

@Config(manifest=Config.NONE)
@RunWith(RobolectricTestRunner.class)
Expand Down Expand Up @@ -50,12 +52,12 @@ public void setSystemExclusionRectsSendsSuccessMessageToFramework() throws JSONE
Rect gestureRect = new Rect(left, top, right, bottom);
expectedDecodedRects.add(gestureRect);

MethodCall callSystemGestureExclusionRects = new MethodCall(
MethodCall callSetSystemGestureExclusionRects = new MethodCall(
"SystemGestures.setSystemGestureExclusionRects",
inputRects
);

platformChannel.parsingMethodCallHandler.onMethodCall(callSystemGestureExclusionRects, resultsMock);
platformChannel.parsingMethodCallHandler.onMethodCall(callSetSystemGestureExclusionRects, resultsMock);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how these tests overlap with the other PR, but can we separate the behavior under test from the verification? If it's already done in the other PR, then no worries.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I mistakenly made this variable name update to this PR instead of the more relevant one. Should I move it over there instead? The other PR addresses separating the behavior under test from verification.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either place is fine as long as the right change is made :)

verify(platformMessageHandler, times(1)).setSystemGestureExclusionRects(expectedDecodedRects);
verify(resultsMock, times(1)).success(null);
}
Expand All @@ -69,11 +71,11 @@ public void setSystemExclusionRectsRequiresJSONArrayInput() {

ResultsMock resultsMock = mock(ResultsMock.class);
String nonJsonInput = "Non-JSON";
MethodCall callSystemGestureExclusionRects = new MethodCall(
MethodCall callSetSystemGestureExclusionRects = new MethodCall(
"SystemGestures.setSystemGestureExclusionRects",
nonJsonInput
);
platformChannel.parsingMethodCallHandler.onMethodCall(callSystemGestureExclusionRects, resultsMock);
platformChannel.parsingMethodCallHandler.onMethodCall(callSetSystemGestureExclusionRects, resultsMock);

String inputTypeError = "Input type is incorrect. Ensure that a List<Map<String, int>> is passed as the input for SystemGestureExclusionRects.setSystemGestureExclusionRects.";
verify(resultsMock, times(1)).error(
Expand All @@ -100,11 +102,11 @@ public void setSystemExclusionRectsSendsJSONExceptionOnIncorrectDataShape() thro
JSONArray inputArray = new JSONArray();
inputArray.put(jsonObject);

MethodCall callSystemGestureExclusionRects = new MethodCall(
MethodCall callSetSystemGestureExclusionRects = new MethodCall(
"SystemGestures.setSystemGestureExclusionRects",
inputArray
);
platformChannel.parsingMethodCallHandler.onMethodCall(callSystemGestureExclusionRects, resultsMock);
platformChannel.parsingMethodCallHandler.onMethodCall(callSetSystemGestureExclusionRects, resultsMock);
verify(resultsMock, times(1)).error(
"error",
"JSON error: Incorrect JSON data shape. To set system gesture exclusion rects, \n" +
Expand All @@ -113,6 +115,67 @@ public void setSystemExclusionRectsSendsJSONExceptionOnIncorrectDataShape() thro
);
}

@Test
public void itSendsSuccessMessageToFrameworkWhenGettingSystemGestureExclusionRects() throws JSONException {
// --- Test Setup ---
DartExecutor dartExecutor = mock(DartExecutor.class);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please clearly identify the areas of this test that setup the test, execute the behavior under test, and verify the expected results.

PlatformChannel platformChannel = new PlatformChannel(dartExecutor);
PlatformMessageHandler platformMessageHandler = mock(PlatformMessageHandler.class);
platformChannel.setPlatformMessageHandler(platformMessageHandler);
Result result = mock(Result.class);

// Fake API output setup
ArrayList<Rect> fakeExclusionRects = new ArrayList<Rect>();
Rect gestureRect = new Rect(0, 0, 500, 250);
fakeExclusionRects.add(gestureRect);
when(platformMessageHandler.getSystemGestureExclusionRects()).thenReturn(fakeExclusionRects);

// Parsed API output that should be passed to result.success()
ArrayList<HashMap<String, Integer>> expectedEncodedOutputRects = new ArrayList<HashMap<String, Integer>>();
HashMap<String, Integer> rectMap = new HashMap<String, Integer>();
rectMap.put("top", 0);
rectMap.put("right", 500);
rectMap.put("bottom", 250);
rectMap.put("left", 0);
expectedEncodedOutputRects.add(rectMap);
MethodCall callGetSystemGestureExclusionRects = new MethodCall(
"SystemGestures.getSystemGestureExclusionRects",
null
);

// --- Execute Test ---
platformChannel.parsingMethodCallHandler.onMethodCall(callGetSystemGestureExclusionRects, result);

// --- Verify Results ---
verify(result, times(1)).success(expectedEncodedOutputRects);
}

@Test
public void itSendsAPILevelErrorWhenAndroidVersionIsTooLowWhenGettingSystemGestureExclusionRects() {
// --- Test Setup ---
DartExecutor dartExecutor = mock(DartExecutor.class);
PlatformChannel platformChannel = new PlatformChannel(dartExecutor);
PlatformMessageHandler platformMessageHandler = mock(PlatformMessageHandler.class);
platformChannel.setPlatformMessageHandler(platformMessageHandler);
when(platformMessageHandler.getSystemGestureExclusionRects()).thenReturn(null);
Result result = mock(Result.class);

MethodCall callGetSystemGestureExclusionRects = new MethodCall(
"SystemGestures.getSystemGestureExclusionRects",
null
);

// --- Execute Test ---
platformChannel.parsingMethodCallHandler.onMethodCall(callGetSystemGestureExclusionRects, result);

// --- Verify Results ---
verify(result, times(1)).error(
"error",
"Exclusion rects only exist for Android API 29+.",
null
);
}

private class ResultsMock implements Result {
@Override
public void success(Object result) {}
Expand Down