Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Guard against NewAPI failures #8048

Merged
merged 5 commits into from
Mar 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -134,7 +134,7 @@ public void detachFromRenderer() {
if (flutterRenderer != null) {
// If we're attached to an Android window then we were rendering a Flutter UI. Now that
// this FlutterSurfaceView is detached from the FlutterRenderer, we need to stop rendering.
if (isAttachedToWindow()) {
if (getWindowToken() != null) {
disconnectSurfaceFromRenderer();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ public void detachFromRenderer() {
if (flutterRenderer != null) {
// If we're attached to an Android window then we were rendering a Flutter UI. Now that
// this FlutterTextureView is detached from the FlutterRenderer, we need to stop rendering.
if (isAttachedToWindow()) {
if (getWindowToken() != null) {
disconnectSurfaceFromRenderer();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

package io.flutter.embedding.engine.android;

import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
Expand All @@ -12,6 +13,7 @@
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.text.format.DateFormat;
import android.util.AttributeSet;
import android.util.Log;
Expand Down Expand Up @@ -179,6 +181,8 @@ protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight)
* the wider than expected padding when the status and navigation bars are hidden.
*/
@Override
@TargetApi(20)
@RequiresApi(20)
public final WindowInsets onApplyWindowInsets(WindowInsets insets) {
WindowInsets newInsets = super.onApplyWindowInsets(insets);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,15 @@ private void setSystemChromeApplicationSwitcherDescription(PlatformChannel.AppSw
return;
}

@SuppressWarnings("deprecation")
TaskDescription taskDescription = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)
? new TaskDescription(description.label, 0, description.color)
: new TaskDescription(description.label, null, description.color);

activity.setTaskDescription(taskDescription);
// Linter refuses to believe we're only executing this code in API 28 unless we use distinct if blocks and
// hardcode the API 28 constant.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P && Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
activity.setTaskDescription(new TaskDescription(description.label));
}
if (Build.VERSION.SDK_INT >= 28) {
TaskDescription taskDescription = new TaskDescription(description.label, 0, description.color);
activity.setTaskDescription(taskDescription);
}
}

private void setSystemChromeEnabledSystemUIOverlays(List<PlatformChannel.SystemUiOverlay> overlaysToShow) {
Expand Down
59 changes: 46 additions & 13 deletions shell/platform/android/io/flutter/view/AccessibilityBridge.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@

package io.flutter.view;

import android.annotation.TargetApi;
import android.app.Activity;
import android.graphics.Rect;
import android.opengl.Matrix;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi;
import android.util.Log;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
Expand Down Expand Up @@ -84,10 +87,12 @@ enum Action {
SHOW_ON_SCREEN(1 << 8),
MOVE_CURSOR_FORWARD_BY_CHARACTER(1 << 9),
MOVE_CURSOR_BACKWARD_BY_CHARACTER(1 << 10),
/** These actions are only supported on Android 4.3 and above. */
SET_SELECTION(1 << 11),
COPY(1 << 12),
CUT(1 << 13),
PASTE(1 << 14),
/** End 4.3 only supported actions. */
DID_GAIN_ACCESSIBILITY_FOCUS(1 << 15),
DID_LOSE_ACCESSIBILITY_FOCUS(1 << 16),
CUSTOM_ACTION(1 << 17),
Expand Down Expand Up @@ -233,17 +238,22 @@ public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) {
}
result.setMovementGranularities(granularities);
}
if (object.hasAction(Action.SET_SELECTION)) {
result.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
}
if (object.hasAction(Action.COPY)) {
result.addAction(AccessibilityNodeInfo.ACTION_COPY);
}
if (object.hasAction(Action.CUT)) {
result.addAction(AccessibilityNodeInfo.ACTION_CUT);
}
if (object.hasAction(Action.PASTE)) {
result.addAction(AccessibilityNodeInfo.ACTION_PASTE);

// These are non-ops on older devices. Attempting to interact with the text will cause Talkback to read the
// contents of the text box instead.
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2) {
if (object.hasAction(Action.SET_SELECTION)) {
result.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
}
if (object.hasAction(Action.COPY)) {
result.addAction(AccessibilityNodeInfo.ACTION_COPY);
}
if (object.hasAction(Action.CUT)) {
result.addAction(AccessibilityNodeInfo.ACTION_CUT);
}
if (object.hasAction(Action.PASTE)) {
result.addAction(AccessibilityNodeInfo.ACTION_PASTE);
}
}

if (object.hasFlag(Flag.IS_BUTTON)) {
Expand Down Expand Up @@ -312,11 +322,14 @@ public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) {
// We should prefer setCollectionInfo to the class names, as this way we get "In List"
// and "Out of list" announcements. But we don't always know the counts, so we
// can fallback to the generic scroll view class names.
//
// On older APIs, we always fall back to the generic scroll view class names here.
//
// TODO(dnfield): We should add semantics properties for rows and columns in 2 dimensional lists, e.g.
// GridView. Right now, we're only supporting ListViews and only if they have scroll children.
if (object.hasFlag(Flag.HAS_IMPLICIT_SCROLLING)) {
if (object.hasAction(Action.SCROLL_LEFT) || object.hasAction(Action.SCROLL_RIGHT)) {
if (shouldSetCollectionInfo(object)) {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT && shouldSetCollectionInfo(object)) {
result.setCollectionInfo(AccessibilityNodeInfo.CollectionInfo.obtain(
0, // rows
object.scrollChildren, // columns
Expand All @@ -325,7 +338,7 @@ public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) {
result.setClassName("android.widget.HorizontalScrollView");
}
} else {
if (shouldSetCollectionInfo(object)) {
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2 && shouldSetCollectionInfo(object)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Here and elsewhere, can you add comments about what happens if the SDK versions are not met?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added to the inline comments above this block.

result.setCollectionInfo(AccessibilityNodeInfo.CollectionInfo.obtain(
object.scrollChildren, // rows
0, // columns
Expand Down Expand Up @@ -465,9 +478,21 @@ public boolean performAction(int virtualViewId, int action, Bundle arguments) {
return true;
}
case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
// Text selection APIs aren't available until API 18. We can't handle the case here so return false
// instead. It's extremely unlikely that this case would ever be triggered in the first place in API <
// 18.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
return false;
}
return performCursorMoveAction(object, virtualViewId, arguments, false);
}
case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
// Text selection APIs aren't available until API 18. We can't handle the case here so return false
// instead. It's extremely unlikely that this case would ever be triggered in the first place in API <
// 18.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
return false;
}
return performCursorMoveAction(object, virtualViewId, arguments, true);
}
case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
Expand Down Expand Up @@ -502,6 +527,12 @@ public boolean performAction(int virtualViewId, int action, Bundle arguments) {
return true;
}
case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
// Text selection APIs aren't available until API 18. We can't handle the case here so return false
// instead. It's extremely unlikely that this case would ever be triggered in the first place in API <
// 18.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
return false;
}
final Map<String, Integer> selection = new HashMap<>();
final boolean hasSelection = arguments != null
&& arguments.containsKey(
Expand Down Expand Up @@ -553,6 +584,8 @@ public boolean performAction(int virtualViewId, int action, Bundle arguments) {
return false;
}

@RequiresApi(18)
@TargetApi(18)
boolean performCursorMoveAction(
SemanticsObject object, int virtualViewId, Bundle arguments, boolean forward) {
final int granularity =
Expand Down
14 changes: 12 additions & 2 deletions shell/platform/android/io/flutter/view/FlutterView.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

package io.flutter.view;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
Expand All @@ -17,6 +18,7 @@
import android.os.Handler;
import android.os.LocaleList;
import android.provider.Settings;
import android.support.annotation.RequiresApi;
import android.text.format.DateFormat;
import android.util.AttributeSet;
import android.util.Log;
Expand Down Expand Up @@ -654,6 +656,8 @@ else if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
// be padded. When the on-screen keyboard is detected, we want to include the full inset
// but when the inset is just the hidden nav bar, we want to provide a zero inset so the space
// can be used.
@TargetApi(20)
@RequiresApi(20)
int calculateBottomKeyboardInset(WindowInsets insets) {
int screenHeight = getRootView().getHeight();
// Magic number due to this being a heuristic. This should be replaced, but we have not
Expand All @@ -672,6 +676,8 @@ int calculateBottomKeyboardInset(WindowInsets insets) {
// This callback is not present in API < 20, which means lower API devices will see
// the wider than expected padding when the status and navigation bars are hidden.
@Override
@TargetApi(20)
@RequiresApi(20)
public final WindowInsets onApplyWindowInsets(WindowInsets insets) {
boolean statusBarHidden =
(SYSTEM_UI_FLAG_FULLSCREEN & getWindowSystemUiVisibility()) != 0;
Expand Down Expand Up @@ -963,8 +969,9 @@ public void onChange(boolean selfChange) {

@Override
public void onChange(boolean selfChange, Uri uri) {
String value = Settings.Global.getString(getContext().getContentResolver(),
Settings.Global.TRANSITION_ANIMATION_SCALE);
String value = Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1 ? null
: Settings.Global.getString(getContext().getContentResolver(),
Settings.Global.TRANSITION_ANIMATION_SCALE);
if (value != null && value.equals("0")) {
mAccessibilityFeatureFlags |= AccessibilityFeature.DISABLE_ANIMATIONS.value;
} else {
Expand All @@ -974,6 +981,9 @@ public void onChange(boolean selfChange, Uri uri) {
}
}

// This is guarded at instantiation time.
@TargetApi(19)
@RequiresApi(19)
class TouchExplorationListener implements AccessibilityManager.TouchExplorationStateChangeListener {
@Override
public void onTouchExplorationStateChanged(boolean enabled) {
Expand Down
19 changes: 17 additions & 2 deletions shell/platform/android/io/flutter/view/ResourceExtractor.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

package io.flutter.view;

import static java.util.Arrays.asList;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
Expand All @@ -16,6 +18,7 @@
import org.json.JSONObject;

import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.concurrent.CancellationException;
Expand All @@ -30,10 +33,12 @@
class ResourceExtractor {
private static final String TAG = "ResourceExtractor";
private static final String TIMESTAMP_PREFIX = "res_timestamp-";
private static final String[] SUPPORTED_ABIS = getSupportedAbis();

@SuppressWarnings("deprecation")
static long getVersionCode(PackageInfo packageInfo) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
// Linter needs P (28) hardcoded or else it will fail these lines.
if (Build.VERSION.SDK_INT >= 28) {
return packageInfo.getLongVersionCode();
} else {
return packageInfo.versionCode;
Expand Down Expand Up @@ -244,7 +249,7 @@ private boolean extractUpdate(File dataDir) {
ZipEntry entry = null;
if (asset.endsWith(".so")) {
// Replicate library lookup logic.
for (String abi : Build.SUPPORTED_ABIS) {
for (String abi : SUPPORTED_ABIS) {
resource = "lib/" + abi + "/" + asset;
entry = zipFile.getEntry(resource);
if (entry == null) {
Expand Down Expand Up @@ -403,4 +408,14 @@ private String getAPKPath() {
return null;
}
}

private static String[] getSupportedAbis() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && Build.SUPPORTED_ABIS.length > 0) {
return Build.SUPPORTED_ABIS;
} else {
ArrayList<String> cpuAbis = new ArrayList<String>(asList(Build.CPU_ABI, Build.CPU_ABI2));
cpuAbis.removeAll(asList(null, ""));
return cpuAbis.toArray(new String[0]);
}
}
}
Loading