Merge "GestureNav: Limit exclusion rects" into qt-dev
am: ea3216d462
Change-Id: Iec5962ddf1dc34f24b99add93a65fc4f69debcde
This commit is contained in:
@@ -2294,6 +2294,7 @@ package android.provider {
|
||||
field public static final String NAMESPACE_PRIVACY = "privacy";
|
||||
field public static final String NAMESPACE_ROLLBACK = "rollback";
|
||||
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 {
|
||||
@@ -2310,6 +2311,10 @@ package android.provider {
|
||||
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 {
|
||||
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;
|
||||
|
||||
@@ -284,6 +284,15 @@ public final class DeviceConfig {
|
||||
*/
|
||||
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
|
||||
*
|
||||
@@ -301,6 +310,23 @@ public final class DeviceConfig {
|
||||
@TestApi
|
||||
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();
|
||||
@GuardedBy("sLock")
|
||||
private static ArrayMap<OnPropertyChangedListener, Pair<String, Executor>> sSingleListeners =
|
||||
|
||||
@@ -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_PORTRAIT;
|
||||
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.FLAG_PRIVATE;
|
||||
import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
|
||||
import static android.view.Display.INVALID_DISPLAY;
|
||||
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_180;
|
||||
import static android.view.Surface.ROTATION_270;
|
||||
import static android.view.Surface.ROTATION_90;
|
||||
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_INVALID;
|
||||
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.WindowStateAnimator.DRAW_PENDING;
|
||||
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 android.animation.AnimationHandler;
|
||||
@@ -324,6 +330,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
private final RemoteCallbackList<ISystemGestureExclusionListener>
|
||||
mSystemGestureExclusionListeners = new RemoteCallbackList<>();
|
||||
private final Region mSystemGestureExclusion = new Region();
|
||||
private int mSystemGestureExclusionLimit;
|
||||
|
||||
/**
|
||||
* For default display it contains real metrics, empty for others.
|
||||
@@ -894,6 +901,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
mWallpaperController = new WallpaperController(mWmService, this);
|
||||
display.getDisplayInfo(mDisplayInfo);
|
||||
display.getMetrics(mDisplayMetrics);
|
||||
mSystemGestureExclusionLimit = mWmService.mSystemGestureExclusionLimitDp
|
||||
* mDisplayMetrics.densityDpi / DENSITY_DEFAULT;
|
||||
isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;
|
||||
mDisplayFrames = new DisplayFrames(mDisplayId, mDisplayInfo,
|
||||
calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
|
||||
@@ -1549,8 +1558,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
longSize = height;
|
||||
}
|
||||
|
||||
final int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / mBaseDisplayDensity;
|
||||
final int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / mBaseDisplayDensity;
|
||||
final int shortSizeDp = shortSize * DENSITY_DEFAULT / mBaseDisplayDensity;
|
||||
final int longSizeDp = longSize * DENSITY_DEFAULT / mBaseDisplayDensity;
|
||||
|
||||
mDisplayPolicy.updateConfigurationAndScreenSizeDependentBehaviors();
|
||||
mDisplayRotation.configure(width, height, shortSizeDp, longSizeDp);
|
||||
@@ -2200,6 +2209,18 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
onDisplayChanged(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
void onDisplayChanged(DisplayContent dc) {
|
||||
super.onDisplayChanged(dc);
|
||||
updateSystemGestureExclusionLimit();
|
||||
}
|
||||
|
||||
void updateSystemGestureExclusionLimit() {
|
||||
mSystemGestureExclusionLimit = mWmService.mSystemGestureExclusionLimitDp
|
||||
* mDisplayMetrics.densityDpi / DENSITY_DEFAULT;
|
||||
updateSystemGestureExclusion();
|
||||
}
|
||||
|
||||
void initializeDisplayBaseInfo() {
|
||||
final DisplayManagerInternal displayManagerInternal = mWmService.mDisplayManagerInternal;
|
||||
if (displayManagerInternal != null) {
|
||||
@@ -5140,24 +5161,35 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
|
||||
@VisibleForTesting
|
||||
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 touchableRegion = Region.obtain();
|
||||
final Region local = Region.obtain();
|
||||
final int[] remainingLeftRight =
|
||||
{mSystemGestureExclusionLimit, mSystemGestureExclusionLimit};
|
||||
|
||||
// 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.
|
||||
forAllWindows(w -> {
|
||||
if (w.cantReceiveTouchInput() || !w.isVisible()
|
||||
|| (w.getAttrs().flags & FLAG_NOT_TOUCHABLE) != 0) {
|
||||
|| (w.getAttrs().flags & FLAG_NOT_TOUCHABLE) != 0
|
||||
|| unhandled.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
final boolean modal =
|
||||
(w.mAttrs.flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0;
|
||||
|
||||
// Only keep the exclusion zones from the windows behind where the current window
|
||||
// isn't touchable.
|
||||
// Get the touchable region of the window, and intersect with where the screen is still
|
||||
// touchable, i.e. touchable regions on top are not covering it yet.
|
||||
w.getTouchableRegion(touchableRegion);
|
||||
global.op(touchableRegion, Op.DIFFERENCE);
|
||||
touchableRegion.op(unhandled, Op.INTERSECT);
|
||||
|
||||
rectListToRegion(w.getSystemGestureExclusion(), local);
|
||||
|
||||
@@ -5169,13 +5201,78 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
|
||||
// A window can only exclude system gestures where it is actually touchable
|
||||
local.op(touchableRegion, Op.INTERSECT);
|
||||
|
||||
global.op(local, Op.UNION);
|
||||
}, false /* topToBottom */);
|
||||
// Apply restriction if necessary.
|
||||
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();
|
||||
touchableRegion.recycle();
|
||||
unhandled.recycle();
|
||||
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) {
|
||||
mSystemGestureExclusionListeners.register(listener);
|
||||
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.myPid;
|
||||
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.view.Display.DEFAULT_DISPLAY;
|
||||
import static android.view.Display.INVALID_DISPLAY;
|
||||
@@ -154,6 +155,7 @@ import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Debug;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerExecutor;
|
||||
import android.os.IBinder;
|
||||
import android.os.IRemoteCallback;
|
||||
import android.os.Looper;
|
||||
@@ -175,6 +177,7 @@ import android.os.SystemService;
|
||||
import android.os.Trace;
|
||||
import android.os.UserHandle;
|
||||
import android.os.WorkSource;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.provider.Settings;
|
||||
import android.service.vr.IVrManager;
|
||||
import android.service.vr.IVrStateCallbacks;
|
||||
@@ -380,6 +383,8 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
|
||||
private static final int ANIMATION_COMPLETED_TIMEOUT_MS = 5000;
|
||||
|
||||
private static final int MIN_GESTURE_EXCLUSION_LIMIT_DP = 200;
|
||||
|
||||
final WindowTracing mWindowTracing;
|
||||
|
||||
final private KeyguardDisableHandler mKeyguardDisableHandler;
|
||||
@@ -838,6 +843,8 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
final ArrayList<WindowChangeListener> mWindowChangeListeners = new ArrayList<>();
|
||||
boolean mWindowsChanged = false;
|
||||
|
||||
int mSystemGestureExclusionLimitDp;
|
||||
|
||||
public interface WindowChangeListener {
|
||||
public void windowsChanged();
|
||||
public void focusChanged();
|
||||
@@ -1132,6 +1139,21 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
this, mInputManager, mActivityTaskManager, 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());
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,10 @@ package com.android.server.wm.utils;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Region;
|
||||
import android.graphics.RegionIterator;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Utility methods to handle Regions.
|
||||
@@ -42,4 +44,18 @@ public class RegionUtils {
|
||||
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.WAKE_LOCK" />
|
||||
<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) -->
|
||||
<application android:debuggable="true"
|
||||
|
||||
Reference in New Issue
Block a user