GestureNav: Limit exclusion rects
Add limits for system gesture exclusion on the left and right edges. This prevents non-immersive-sticky apps from totally disabling the back gesture. Bug: 135522625 Test: atest SystemGestureExclusionRectsTest Change-Id: Ib26161663a6aababe803d3c70044f4017bdbe675 Exempt-From-Owner-Approval: Already +2ed on another branch
This commit is contained in:
@@ -2301,6 +2301,7 @@ package android.provider {
|
|||||||
field public static final String NAMESPACE_PRIVACY = "privacy";
|
field public static final String NAMESPACE_PRIVACY = "privacy";
|
||||||
field public static final String NAMESPACE_ROLLBACK = "rollback";
|
field public static final String NAMESPACE_ROLLBACK = "rollback";
|
||||||
field public static final String NAMESPACE_ROLLBACK_BOOT = "rollback_boot";
|
field public static final String NAMESPACE_ROLLBACK_BOOT = "rollback_boot";
|
||||||
|
field public static final String NAMESPACE_WINDOW_MANAGER = "android:window_manager";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static interface DeviceConfig.OnPropertiesChangedListener {
|
public static interface DeviceConfig.OnPropertiesChangedListener {
|
||||||
@@ -2317,6 +2318,10 @@ package android.provider {
|
|||||||
method @Nullable public String getString(@NonNull String, @Nullable String);
|
method @Nullable public String getString(@NonNull String, @Nullable String);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static interface DeviceConfig.WindowManager {
|
||||||
|
field public static final String KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP = "system_gesture_exclusion_limit_dp";
|
||||||
|
}
|
||||||
|
|
||||||
public final class MediaStore {
|
public final class MediaStore {
|
||||||
method @RequiresPermission(android.Manifest.permission.CLEAR_APP_USER_DATA) public static void deleteContributedMedia(android.content.Context, String, android.os.UserHandle) throws java.io.IOException;
|
method @RequiresPermission(android.Manifest.permission.CLEAR_APP_USER_DATA) public static void deleteContributedMedia(android.content.Context, String, android.os.UserHandle) throws java.io.IOException;
|
||||||
method @RequiresPermission(android.Manifest.permission.CLEAR_APP_USER_DATA) public static long getContributedMediaSize(android.content.Context, String, android.os.UserHandle) throws java.io.IOException;
|
method @RequiresPermission(android.Manifest.permission.CLEAR_APP_USER_DATA) public static long getContributedMediaSize(android.content.Context, String, android.os.UserHandle) throws java.io.IOException;
|
||||||
|
|||||||
@@ -292,6 +292,15 @@ public final class DeviceConfig {
|
|||||||
*/
|
*/
|
||||||
public static final String NAMESPACE_SETTINGS_UI = "settings_ui";
|
public static final String NAMESPACE_SETTINGS_UI = "settings_ui";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Namespace for window manager related features. The names to access the properties in this
|
||||||
|
* namespace should be defined in {@link WindowManager}.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@TestApi
|
||||||
|
public static final String NAMESPACE_WINDOW_MANAGER = "android:window_manager";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of namespaces which can be read without READ_DEVICE_CONFIG permission
|
* List of namespaces which can be read without READ_DEVICE_CONFIG permission
|
||||||
*
|
*
|
||||||
@@ -309,6 +318,23 @@ public final class DeviceConfig {
|
|||||||
@TestApi
|
@TestApi
|
||||||
public static final String NAMESPACE_PRIVACY = "privacy";
|
public static final String NAMESPACE_PRIVACY = "privacy";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for accessing keys belonging to {@link #NAMESPACE_WINDOW_MANAGER}.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@TestApi
|
||||||
|
public interface WindowManager {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Key for accessing the system gesture exclusion limit (an integer in dp).
|
||||||
|
*
|
||||||
|
* @see android.provider.DeviceConfig#NAMESPACE_WINDOW_MANAGER
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@TestApi
|
||||||
|
String KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP = "system_gesture_exclusion_limit_dp";
|
||||||
|
}
|
||||||
|
|
||||||
private static final Object sLock = new Object();
|
private static final Object sLock = new Object();
|
||||||
@GuardedBy("sLock")
|
@GuardedBy("sLock")
|
||||||
private static ArrayMap<OnPropertiesChangedListener, Pair<String, Executor>> sListeners =
|
private static ArrayMap<OnPropertiesChangedListener, Pair<String, Executor>> sListeners =
|
||||||
|
|||||||
@@ -30,16 +30,21 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_USER;
|
|||||||
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
|
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
|
||||||
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
|
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
|
||||||
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
|
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
|
||||||
|
import static android.util.DisplayMetrics.DENSITY_DEFAULT;
|
||||||
import static android.view.Display.DEFAULT_DISPLAY;
|
import static android.view.Display.DEFAULT_DISPLAY;
|
||||||
import static android.view.Display.FLAG_PRIVATE;
|
import static android.view.Display.FLAG_PRIVATE;
|
||||||
import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
|
import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
|
||||||
import static android.view.Display.INVALID_DISPLAY;
|
import static android.view.Display.INVALID_DISPLAY;
|
||||||
import static android.view.InsetsState.TYPE_IME;
|
import static android.view.InsetsState.TYPE_IME;
|
||||||
|
import static android.view.InsetsState.TYPE_LEFT_GESTURES;
|
||||||
|
import static android.view.InsetsState.TYPE_RIGHT_GESTURES;
|
||||||
import static android.view.Surface.ROTATION_0;
|
import static android.view.Surface.ROTATION_0;
|
||||||
import static android.view.Surface.ROTATION_180;
|
import static android.view.Surface.ROTATION_180;
|
||||||
import static android.view.Surface.ROTATION_270;
|
import static android.view.Surface.ROTATION_270;
|
||||||
import static android.view.Surface.ROTATION_90;
|
import static android.view.Surface.ROTATION_90;
|
||||||
import static android.view.View.GONE;
|
import static android.view.View.GONE;
|
||||||
|
import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
|
||||||
|
import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
|
||||||
import static android.view.WindowManager.DOCKED_BOTTOM;
|
import static android.view.WindowManager.DOCKED_BOTTOM;
|
||||||
import static android.view.WindowManager.DOCKED_INVALID;
|
import static android.view.WindowManager.DOCKED_INVALID;
|
||||||
import static android.view.WindowManager.DOCKED_TOP;
|
import static android.view.WindowManager.DOCKED_TOP;
|
||||||
@@ -135,6 +140,7 @@ import static com.android.server.wm.WindowManagerService.logSurface;
|
|||||||
import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
|
import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
|
||||||
import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
|
import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
|
||||||
import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
|
import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
|
||||||
|
import static com.android.server.wm.utils.RegionUtils.forEachRect;
|
||||||
import static com.android.server.wm.utils.RegionUtils.rectListToRegion;
|
import static com.android.server.wm.utils.RegionUtils.rectListToRegion;
|
||||||
|
|
||||||
import android.animation.AnimationHandler;
|
import android.animation.AnimationHandler;
|
||||||
@@ -323,6 +329,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
|||||||
private final RemoteCallbackList<ISystemGestureExclusionListener>
|
private final RemoteCallbackList<ISystemGestureExclusionListener>
|
||||||
mSystemGestureExclusionListeners = new RemoteCallbackList<>();
|
mSystemGestureExclusionListeners = new RemoteCallbackList<>();
|
||||||
private final Region mSystemGestureExclusion = new Region();
|
private final Region mSystemGestureExclusion = new Region();
|
||||||
|
private int mSystemGestureExclusionLimit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For default display it contains real metrics, empty for others.
|
* For default display it contains real metrics, empty for others.
|
||||||
@@ -893,6 +900,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
|||||||
mWallpaperController = new WallpaperController(mWmService, this);
|
mWallpaperController = new WallpaperController(mWmService, this);
|
||||||
display.getDisplayInfo(mDisplayInfo);
|
display.getDisplayInfo(mDisplayInfo);
|
||||||
display.getMetrics(mDisplayMetrics);
|
display.getMetrics(mDisplayMetrics);
|
||||||
|
mSystemGestureExclusionLimit = mWmService.mSystemGestureExclusionLimitDp
|
||||||
|
* mDisplayMetrics.densityDpi / DENSITY_DEFAULT;
|
||||||
isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;
|
isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;
|
||||||
mDisplayFrames = new DisplayFrames(mDisplayId, mDisplayInfo,
|
mDisplayFrames = new DisplayFrames(mDisplayId, mDisplayInfo,
|
||||||
calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
|
calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
|
||||||
@@ -1548,8 +1557,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
|||||||
longSize = height;
|
longSize = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
final int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / mBaseDisplayDensity;
|
final int shortSizeDp = shortSize * DENSITY_DEFAULT / mBaseDisplayDensity;
|
||||||
final int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / mBaseDisplayDensity;
|
final int longSizeDp = longSize * DENSITY_DEFAULT / mBaseDisplayDensity;
|
||||||
|
|
||||||
mDisplayPolicy.updateConfigurationAndScreenSizeDependentBehaviors();
|
mDisplayPolicy.updateConfigurationAndScreenSizeDependentBehaviors();
|
||||||
mDisplayRotation.configure(width, height, shortSizeDp, longSizeDp);
|
mDisplayRotation.configure(width, height, shortSizeDp, longSizeDp);
|
||||||
@@ -2199,6 +2208,18 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
|||||||
onDisplayChanged(this);
|
onDisplayChanged(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void onDisplayChanged(DisplayContent dc) {
|
||||||
|
super.onDisplayChanged(dc);
|
||||||
|
updateSystemGestureExclusionLimit();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateSystemGestureExclusionLimit() {
|
||||||
|
mSystemGestureExclusionLimit = mWmService.mSystemGestureExclusionLimitDp
|
||||||
|
* mDisplayMetrics.densityDpi / DENSITY_DEFAULT;
|
||||||
|
updateSystemGestureExclusion();
|
||||||
|
}
|
||||||
|
|
||||||
void initializeDisplayBaseInfo() {
|
void initializeDisplayBaseInfo() {
|
||||||
final DisplayManagerInternal displayManagerInternal = mWmService.mDisplayManagerInternal;
|
final DisplayManagerInternal displayManagerInternal = mWmService.mDisplayManagerInternal;
|
||||||
if (displayManagerInternal != null) {
|
if (displayManagerInternal != null) {
|
||||||
@@ -5130,24 +5151,35 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
|||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
Region calculateSystemGestureExclusion() {
|
Region calculateSystemGestureExclusion() {
|
||||||
|
final Region unhandled = Region.obtain();
|
||||||
|
unhandled.set(0, 0, mDisplayFrames.mDisplayWidth, mDisplayFrames.mDisplayHeight);
|
||||||
|
|
||||||
|
final Rect leftEdge = mInsetsStateController.getSourceProvider(TYPE_LEFT_GESTURES)
|
||||||
|
.getSource().getFrame();
|
||||||
|
final Rect rightEdge = mInsetsStateController.getSourceProvider(TYPE_RIGHT_GESTURES)
|
||||||
|
.getSource().getFrame();
|
||||||
|
|
||||||
final Region global = Region.obtain();
|
final Region global = Region.obtain();
|
||||||
final Region touchableRegion = Region.obtain();
|
final Region touchableRegion = Region.obtain();
|
||||||
final Region local = Region.obtain();
|
final Region local = Region.obtain();
|
||||||
|
final int[] remainingLeftRight =
|
||||||
|
{mSystemGestureExclusionLimit, mSystemGestureExclusionLimit};
|
||||||
|
|
||||||
// Traverse all windows bottom up to assemble the gesture exclusion rects.
|
// Traverse all windows bottom up to assemble the gesture exclusion rects.
|
||||||
// For each window, we only take the rects that fall within its touchable region.
|
// For each window, we only take the rects that fall within its touchable region.
|
||||||
forAllWindows(w -> {
|
forAllWindows(w -> {
|
||||||
if (w.cantReceiveTouchInput() || !w.isVisible()
|
if (w.cantReceiveTouchInput() || !w.isVisible()
|
||||||
|| (w.getAttrs().flags & FLAG_NOT_TOUCHABLE) != 0) {
|
|| (w.getAttrs().flags & FLAG_NOT_TOUCHABLE) != 0
|
||||||
|
|| unhandled.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final boolean modal =
|
final boolean modal =
|
||||||
(w.mAttrs.flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0;
|
(w.mAttrs.flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0;
|
||||||
|
|
||||||
// Only keep the exclusion zones from the windows behind where the current window
|
// Get the touchable region of the window, and intersect with where the screen is still
|
||||||
// isn't touchable.
|
// touchable, i.e. touchable regions on top are not covering it yet.
|
||||||
w.getTouchableRegion(touchableRegion);
|
w.getTouchableRegion(touchableRegion);
|
||||||
global.op(touchableRegion, Op.DIFFERENCE);
|
touchableRegion.op(unhandled, Op.INTERSECT);
|
||||||
|
|
||||||
rectListToRegion(w.getSystemGestureExclusion(), local);
|
rectListToRegion(w.getSystemGestureExclusion(), local);
|
||||||
|
|
||||||
@@ -5159,13 +5191,78 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
|||||||
// A window can only exclude system gestures where it is actually touchable
|
// A window can only exclude system gestures where it is actually touchable
|
||||||
local.op(touchableRegion, Op.INTERSECT);
|
local.op(touchableRegion, Op.INTERSECT);
|
||||||
|
|
||||||
global.op(local, Op.UNION);
|
// Apply restriction if necessary.
|
||||||
}, false /* topToBottom */);
|
if (needsGestureExclusionRestrictions(w, mLastDispatchedSystemUiVisibility)) {
|
||||||
|
|
||||||
|
// Processes the region along the left edge.
|
||||||
|
remainingLeftRight[0] = addToGlobalAndConsumeLimit(local, global, leftEdge,
|
||||||
|
remainingLeftRight[0]);
|
||||||
|
|
||||||
|
// Processes the region along the right edge.
|
||||||
|
remainingLeftRight[1] = addToGlobalAndConsumeLimit(local, global, rightEdge,
|
||||||
|
remainingLeftRight[1]);
|
||||||
|
|
||||||
|
// Adds the middle (unrestricted area)
|
||||||
|
final Region middle = Region.obtain(local);
|
||||||
|
middle.op(leftEdge, Op.DIFFERENCE);
|
||||||
|
middle.op(rightEdge, Op.DIFFERENCE);
|
||||||
|
global.op(middle, Op.UNION);
|
||||||
|
middle.recycle();
|
||||||
|
} else {
|
||||||
|
global.op(local, Op.UNION);
|
||||||
|
}
|
||||||
|
unhandled.op(touchableRegion, Op.DIFFERENCE);
|
||||||
|
}, true /* topToBottom */);
|
||||||
local.recycle();
|
local.recycle();
|
||||||
touchableRegion.recycle();
|
touchableRegion.recycle();
|
||||||
|
unhandled.recycle();
|
||||||
return global;
|
return global;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Whether gesture exclusion area should be restricted from the window depending on the
|
||||||
|
* current SystemUI visibility flags.
|
||||||
|
*/
|
||||||
|
private static boolean needsGestureExclusionRestrictions(WindowState win, int sysUiVisibility) {
|
||||||
|
final int type = win.mAttrs.type;
|
||||||
|
final int stickyHideNavFlags =
|
||||||
|
SYSTEM_UI_FLAG_HIDE_NAVIGATION | SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
|
||||||
|
final boolean stickyHideNav =
|
||||||
|
(sysUiVisibility & stickyHideNavFlags) == stickyHideNavFlags;
|
||||||
|
return !stickyHideNav && type != TYPE_INPUT_METHOD && type != TYPE_STATUS_BAR
|
||||||
|
&& win.getActivityType() != ACTIVITY_TYPE_HOME;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a local gesture exclusion area to the global area while applying a limit per edge.
|
||||||
|
*
|
||||||
|
* @param local The gesture exclusion area to add.
|
||||||
|
* @param global The destination.
|
||||||
|
* @param edge Only processes the part in that region.
|
||||||
|
* @param limit How much limit in pixels we have.
|
||||||
|
* @return How much of the limit are remaining.
|
||||||
|
*/
|
||||||
|
private static int addToGlobalAndConsumeLimit(Region local, Region global, Rect edge,
|
||||||
|
int limit) {
|
||||||
|
final Region r = Region.obtain(local);
|
||||||
|
r.op(edge, Op.INTERSECT);
|
||||||
|
|
||||||
|
final int[] remaining = {limit};
|
||||||
|
forEachRect(r, rect -> {
|
||||||
|
if (remaining[0] <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final int height = rect.height();
|
||||||
|
if (height > remaining[0]) {
|
||||||
|
rect.bottom = rect.top + remaining[0];
|
||||||
|
}
|
||||||
|
remaining[0] -= height;
|
||||||
|
global.op(rect, Op.UNION);
|
||||||
|
});
|
||||||
|
r.recycle();
|
||||||
|
return remaining[0];
|
||||||
|
}
|
||||||
|
|
||||||
void registerSystemGestureExclusionListener(ISystemGestureExclusionListener listener) {
|
void registerSystemGestureExclusionListener(ISystemGestureExclusionListener listener) {
|
||||||
mSystemGestureExclusionListeners.register(listener);
|
mSystemGestureExclusionListeners.register(listener);
|
||||||
final boolean changed;
|
final boolean changed;
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED;
|
|||||||
import static android.os.Process.SYSTEM_UID;
|
import static android.os.Process.SYSTEM_UID;
|
||||||
import static android.os.Process.myPid;
|
import static android.os.Process.myPid;
|
||||||
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
|
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
|
||||||
|
import static android.provider.DeviceConfig.WindowManager.KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP;
|
||||||
import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS;
|
import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS;
|
||||||
import static android.view.Display.DEFAULT_DISPLAY;
|
import static android.view.Display.DEFAULT_DISPLAY;
|
||||||
import static android.view.Display.INVALID_DISPLAY;
|
import static android.view.Display.INVALID_DISPLAY;
|
||||||
@@ -155,6 +156,7 @@ import android.os.Build;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Debug;
|
import android.os.Debug;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.os.HandlerExecutor;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.IRemoteCallback;
|
import android.os.IRemoteCallback;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
@@ -176,6 +178,7 @@ import android.os.SystemService;
|
|||||||
import android.os.Trace;
|
import android.os.Trace;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.WorkSource;
|
import android.os.WorkSource;
|
||||||
|
import android.provider.DeviceConfig;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.service.vr.IVrManager;
|
import android.service.vr.IVrManager;
|
||||||
import android.service.vr.IVrStateCallbacks;
|
import android.service.vr.IVrStateCallbacks;
|
||||||
@@ -382,6 +385,8 @@ public class WindowManagerService extends IWindowManager.Stub
|
|||||||
|
|
||||||
private static final int ANIMATION_COMPLETED_TIMEOUT_MS = 5000;
|
private static final int ANIMATION_COMPLETED_TIMEOUT_MS = 5000;
|
||||||
|
|
||||||
|
private static final int MIN_GESTURE_EXCLUSION_LIMIT_DP = 200;
|
||||||
|
|
||||||
final WindowTracing mWindowTracing;
|
final WindowTracing mWindowTracing;
|
||||||
|
|
||||||
final private KeyguardDisableHandler mKeyguardDisableHandler;
|
final private KeyguardDisableHandler mKeyguardDisableHandler;
|
||||||
@@ -840,6 +845,8 @@ public class WindowManagerService extends IWindowManager.Stub
|
|||||||
final ArrayList<WindowChangeListener> mWindowChangeListeners = new ArrayList<>();
|
final ArrayList<WindowChangeListener> mWindowChangeListeners = new ArrayList<>();
|
||||||
boolean mWindowsChanged = false;
|
boolean mWindowsChanged = false;
|
||||||
|
|
||||||
|
int mSystemGestureExclusionLimitDp;
|
||||||
|
|
||||||
public interface WindowChangeListener {
|
public interface WindowChangeListener {
|
||||||
public void windowsChanged();
|
public void windowsChanged();
|
||||||
public void focusChanged();
|
public void focusChanged();
|
||||||
@@ -1134,6 +1141,21 @@ public class WindowManagerService extends IWindowManager.Stub
|
|||||||
this, mInputManager, mActivityTaskManager, mH.getLooper());
|
this, mInputManager, mActivityTaskManager, mH.getLooper());
|
||||||
mDragDropController = new DragDropController(this, mH.getLooper());
|
mDragDropController = new DragDropController(this, mH.getLooper());
|
||||||
|
|
||||||
|
mSystemGestureExclusionLimitDp = Math.max(MIN_GESTURE_EXCLUSION_LIMIT_DP,
|
||||||
|
DeviceConfig.getInt(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
|
||||||
|
KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, 0));
|
||||||
|
DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
|
||||||
|
new HandlerExecutor(mH), properties -> {
|
||||||
|
synchronized (mGlobalLock) {
|
||||||
|
final int exclusionLimitDp = Math.max(MIN_GESTURE_EXCLUSION_LIMIT_DP,
|
||||||
|
properties.getInt(KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, 0));
|
||||||
|
if (mSystemGestureExclusionLimitDp != exclusionLimitDp) {
|
||||||
|
mSystemGestureExclusionLimitDp = exclusionLimitDp;
|
||||||
|
mRoot.forAllDisplays(DisplayContent::updateSystemGestureExclusionLimit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
LocalServices.addService(WindowManagerInternal.class, new LocalService());
|
LocalServices.addService(WindowManagerInternal.class, new LocalService());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,10 @@ package com.android.server.wm.utils;
|
|||||||
|
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.Region;
|
import android.graphics.Region;
|
||||||
|
import android.graphics.RegionIterator;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility methods to handle Regions.
|
* Utility methods to handle Regions.
|
||||||
@@ -42,4 +44,18 @@ public class RegionUtils {
|
|||||||
outRegion.union(rects.get(i));
|
outRegion.union(rects.get(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies actions on each rect contained within a {@code Region}.
|
||||||
|
*
|
||||||
|
* @param region the given region.
|
||||||
|
* @param rectConsumer the action holder.
|
||||||
|
*/
|
||||||
|
public static void forEachRect(Region region, Consumer<Rect> rectConsumer) {
|
||||||
|
final RegionIterator it = new RegionIterator(region);
|
||||||
|
final Rect rect = new Rect();
|
||||||
|
while (it.next(rect)) {
|
||||||
|
rectConsumer.accept(rect);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
|
<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
<uses-permission android:name="android.permission.REORDER_TASKS" />
|
<uses-permission android:name="android.permission.REORDER_TASKS" />
|
||||||
|
<uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
|
||||||
|
|
||||||
<!-- TODO: Remove largeHeap hack when memory leak is fixed (b/123984854) -->
|
<!-- TODO: Remove largeHeap hack when memory leak is fixed (b/123984854) -->
|
||||||
<application android:debuggable="true"
|
<application android:debuggable="true"
|
||||||
|
|||||||
Reference in New Issue
Block a user