GestureNav: Log exclusion rect heights

Logs the rejected and requested exclusion rect heights.

Test: adb shell device_config put android:window_manager key_system_gesture_exclusion_log_debounce_millis 1000
Bug: 135152789
Change-Id: Ie12640f4bf0a8b40b666e604188a0bedd85e8981
Exempt-From-Owner-Approval: DeviceConfig.java: Adding constant to WindowManager namespace.
This commit is contained in:
Adrian Roos
2019-07-03 18:31:46 +02:00
parent b248a0343f
commit 5f2c9a14f5
11 changed files with 274 additions and 30 deletions

View File

@@ -337,6 +337,20 @@ public final class DeviceConfig {
String KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE =
"system_gestures_excluded_by_pre_q_sticky_immersive";
/**
* The minimum duration between gesture exclusion logging for a given window in
* milliseconds.
*
* Events that happen in-between will be silently dropped.
*
* A non-positive value disables logging.
*
* @see android.provider.DeviceConfig#NAMESPACE_WINDOW_MANAGER
* @hide
*/
String KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS =
"system_gesture_exclusion_log_debounce_millis";
/**
* Key for controlling which packages are explicitly blocked from running at refresh rates
* higher than 60hz.

View File

@@ -28,7 +28,14 @@ oneway interface ISystemGestureExclusionListener {
* Called when the system gesture exclusion for the given display changed.
* @param displayId the display whose system gesture exclusion changed
* @param systemGestureExclusion a {@code Region} where the app would like priority over the
* system gestures, in display coordinates.
* system gestures, in display coordinates. Certain restrictions
* might be applied such that apps don't get all the exclusions
* they request.
* @param systemGestureExclusionUnrestricted a {@code Region} where the app would like priority
* over the system gestures, in display coordinates, without
* any restrictions applied. Null if no restrictions have been
* applied.
*/
void onSystemGestureExclusionChanged(int displayId, in Region systemGestureExclusion);
void onSystemGestureExclusionChanged(int displayId, in Region systemGestureExclusion,
in Region systemGestureExclusionUnrestricted);
}

View File

@@ -53,6 +53,12 @@ public class PointerLocationView extends View implements InputDeviceListener,
// to plot alongside the default one. Useful for testing and comparison purposes.
private static final String ALT_STRATEGY_PROPERY_KEY = "debug.velocitytracker.alt";
/**
* If set to a positive value between 1-255, shows an overlay with the approved (red) and
* rejected (blue) exclusions.
*/
private static final String GESTURE_EXCLUSION_PROP = "debug.pointerlocation.showexclusion";
public static class PointerState {
// Trace of previous points.
private float[] mTraceX = new float[32];
@@ -138,8 +144,10 @@ public class PointerLocationView extends View implements InputDeviceListener,
private final PointerCoords mTempCoords = new PointerCoords();
private final Region mSystemGestureExclusion = new Region();
private final Region mSystemGestureExclusionRejected = new Region();
private final Path mSystemGestureExclusionPath = new Path();
private final Paint mSystemGestureExclusionPaint;
private final Paint mSystemGestureExclusionRejectedPaint;
private final VelocityTracker mVelocity;
private final VelocityTracker mAltVelocity;
@@ -190,6 +198,10 @@ public class PointerLocationView extends View implements InputDeviceListener,
mSystemGestureExclusionPaint.setARGB(25, 255, 0, 0);
mSystemGestureExclusionPaint.setStyle(Paint.Style.FILL_AND_STROKE);
mSystemGestureExclusionRejectedPaint = new Paint();
mSystemGestureExclusionRejectedPaint.setARGB(25, 0, 0, 255);
mSystemGestureExclusionRejectedPaint.setStyle(Paint.Style.FILL_AND_STROKE);
PointerState ps = new PointerState();
mPointers.add(ps);
mActivePointerId = 0;
@@ -263,6 +275,12 @@ public class PointerLocationView extends View implements InputDeviceListener,
canvas.drawPath(mSystemGestureExclusionPath, mSystemGestureExclusionPaint);
}
if (!mSystemGestureExclusionRejected.isEmpty()) {
mSystemGestureExclusionPath.reset();
mSystemGestureExclusionRejected.getBoundaryPath(mSystemGestureExclusionPath);
canvas.drawPath(mSystemGestureExclusionPath, mSystemGestureExclusionRejectedPaint);
}
// Labels
if (mActivePointerId >= 0) {
final PointerState ps = mPointers.get(mActivePointerId);
@@ -754,6 +772,9 @@ public class PointerLocationView extends View implements InputDeviceListener,
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
final int alpha = systemGestureExclusionOpacity();
mSystemGestureExclusionPaint.setAlpha(alpha);
mSystemGestureExclusionRejectedPaint.setAlpha(alpha);
} else {
mSystemGestureExclusion.setEmpty();
}
@@ -805,7 +826,12 @@ public class PointerLocationView extends View implements InputDeviceListener,
}
private static boolean shouldShowSystemGestureExclusion() {
return SystemProperties.getBoolean("debug.pointerlocation.showexclusion", false);
return systemGestureExclusionOpacity() > 0;
}
private static int systemGestureExclusionOpacity() {
int x = SystemProperties.getInt(GESTURE_EXCLUSION_PROP, 0);
return x >= 0 && x <= 255 ? x : 0;
}
// HACK
@@ -928,12 +954,19 @@ public class PointerLocationView extends View implements InputDeviceListener,
private ISystemGestureExclusionListener mSystemGestureExclusionListener =
new ISystemGestureExclusionListener.Stub() {
@Override
public void onSystemGestureExclusionChanged(int displayId, Region systemGestureExclusion) {
public void onSystemGestureExclusionChanged(int displayId, Region systemGestureExclusion,
Region systemGestureExclusionUnrestricted) {
Region exclusion = Region.obtain(systemGestureExclusion);
Region rejected = Region.obtain();
if (systemGestureExclusionUnrestricted != null) {
rejected.set(systemGestureExclusionUnrestricted);
rejected.op(exclusion, Region.Op.DIFFERENCE);
}
Handler handler = getHandler();
if (handler != null) {
handler.post(() -> {
mSystemGestureExclusion.set(exclusion);
mSystemGestureExclusionRejected.set(rejected);
exclusion.recycle();
invalidate();
});

View File

@@ -34,9 +34,11 @@ public abstract class SystemGestureExclusionListenerCompat {
new ISystemGestureExclusionListener.Stub() {
@Override
public void onSystemGestureExclusionChanged(int displayId,
Region systemGestureExclusion) {
Region systemGestureExclusion, Region unrestrictedOrNull) {
if (displayId == mDisplayId) {
onExclusionChanged(systemGestureExclusion);
Region unrestricted = (unrestrictedOrNull == null)
? systemGestureExclusion : unrestrictedOrNull;
onExclusionChanged(systemGestureExclusion, unrestricted);
}
}
};
@@ -47,10 +49,28 @@ public abstract class SystemGestureExclusionListenerCompat {
}
/**
* Called when the exclusion region has changed
* Called when the exclusion region has changed.
*
* TODO: remove, once all subclasses have migrated to
* {@link #onExclusionChanged(Region, Region)}.
*/
public abstract void onExclusionChanged(Region systemGestureExclusion);
/**
* Called when the exclusion region has changed.
*
* @param systemGestureExclusion the system gesture exclusion to be applied
* @param systemGestureExclusionUnrestricted what would be the system gesture exclusion, if
* there were no restrictions being applied. For logging purposes only.
*
*/
public void onExclusionChanged(Region systemGestureExclusion,
Region systemGestureExclusionUnrestricted) {
// TODO: make abstract, once all subclasses have migrated away from
// onExclusionChanged(Region)
onExclusionChanged(systemGestureExclusion);
}
/**
* Registers the listener for getting exclusion rect changes.
*/

View File

@@ -103,7 +103,7 @@ public class EdgeBackGestureHandler implements DisplayListener {
new ISystemGestureExclusionListener.Stub() {
@Override
public void onSystemGestureExclusionChanged(int displayId,
Region systemGestureExclusion) {
Region systemGestureExclusion, Region unrestrictedOrNull) {
if (displayId == mDisplayId) {
mMainExecutor.execute(() -> mExcludeRegion.set(systemGestureExclusion));
}

View File

@@ -67,6 +67,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
@@ -137,6 +138,8 @@ import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREEN
import static com.android.server.wm.WindowManagerService.WINDOW_FREEZE_TIMEOUT_DURATION;
import static com.android.server.wm.WindowManagerService.dipToPixel;
import static com.android.server.wm.WindowManagerService.logSurface;
import static com.android.server.wm.WindowState.EXCLUSION_LEFT;
import static com.android.server.wm.WindowState.EXCLUSION_RIGHT;
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;
@@ -330,6 +333,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
private final RemoteCallbackList<ISystemGestureExclusionListener>
mSystemGestureExclusionListeners = new RemoteCallbackList<>();
private final Region mSystemGestureExclusion = new Region();
private boolean mSystemGestureExclusionWasRestricted = false;
private final Region mSystemGestureExclusionUnrestricted = new Region();
private int mSystemGestureExclusionLimit;
/**
@@ -5139,16 +5144,21 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
return false;
}
final Region systemGestureExclusion = calculateSystemGestureExclusion();
final Region systemGestureExclusion = Region.obtain();
mSystemGestureExclusionWasRestricted = calculateSystemGestureExclusion(
systemGestureExclusion, mSystemGestureExclusionUnrestricted);
try {
if (mSystemGestureExclusion.equals(systemGestureExclusion)) {
return false;
}
mSystemGestureExclusion.set(systemGestureExclusion);
final Region unrestrictedOrNull = mSystemGestureExclusionWasRestricted
? mSystemGestureExclusionUnrestricted : null;
for (int i = mSystemGestureExclusionListeners.beginBroadcast() - 1; i >= 0; --i) {
try {
mSystemGestureExclusionListeners.getBroadcastItem(i)
.onSystemGestureExclusionChanged(mDisplayId, systemGestureExclusion);
.onSystemGestureExclusionChanged(mDisplayId, systemGestureExclusion,
unrestrictedOrNull);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to notify SystemGestureExclusionListener", e);
}
@@ -5160,8 +5170,22 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
}
/**
* Calculates the system gesture exclusion.
*
* @param outExclusion will be set to the gesture exclusion region
* @param outExclusionUnrestricted will be set to the gesture exclusion region without
* any restrictions applied.
* @return whether any restrictions were applied, i.e. outExclusion and outExclusionUnrestricted
* differ.
*/
@VisibleForTesting
Region calculateSystemGestureExclusion() {
boolean calculateSystemGestureExclusion(Region outExclusion, @Nullable
Region outExclusionUnrestricted) {
outExclusion.setEmpty();
if (outExclusionUnrestricted != null) {
outExclusionUnrestricted.setEmpty();
}
final Region unhandled = Region.obtain();
unhandled.set(0, 0, mDisplayFrames.mDisplayWidth, mDisplayFrames.mDisplayHeight);
@@ -5170,7 +5194,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
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 =
@@ -5208,28 +5231,39 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
if (needsGestureExclusionRestrictions(w, mLastDispatchedSystemUiVisibility)) {
// Processes the region along the left edge.
remainingLeftRight[0] = addToGlobalAndConsumeLimit(local, global, leftEdge,
remainingLeftRight[0]);
remainingLeftRight[0] = addToGlobalAndConsumeLimit(local, outExclusion, leftEdge,
remainingLeftRight[0], w, EXCLUSION_LEFT);
// Processes the region along the right edge.
remainingLeftRight[1] = addToGlobalAndConsumeLimit(local, global, rightEdge,
remainingLeftRight[1]);
remainingLeftRight[1] = addToGlobalAndConsumeLimit(local, outExclusion, rightEdge,
remainingLeftRight[1], w, EXCLUSION_RIGHT);
// 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);
outExclusion.op(middle, Op.UNION);
middle.recycle();
} else {
global.op(local, Op.UNION);
boolean loggable = needsGestureExclusionRestrictions(w, 0 /* lastSysUiVis */);
if (loggable) {
addToGlobalAndConsumeLimit(local, outExclusion, leftEdge,
Integer.MAX_VALUE, w, EXCLUSION_LEFT);
addToGlobalAndConsumeLimit(local, outExclusion, rightEdge,
Integer.MAX_VALUE, w, EXCLUSION_RIGHT);
}
outExclusion.op(local, Op.UNION);
}
if (outExclusionUnrestricted != null) {
outExclusionUnrestricted.op(local, Op.UNION);
}
unhandled.op(touchableRegion, Op.DIFFERENCE);
}, true /* topToBottom */);
local.recycle();
touchableRegion.recycle();
unhandled.recycle();
return global;
return remainingLeftRight[0] < mSystemGestureExclusionLimit
|| remainingLeftRight[1] < mSystemGestureExclusionLimit;
}
/**
@@ -5246,6 +5280,23 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
&& win.getActivityType() != ACTIVITY_TYPE_HOME;
}
/**
* @return Whether gesture exclusion area should be logged for the given window
*/
static boolean logsGestureExclusionRestrictions(WindowState win) {
if (win.mWmService.mSystemGestureExclusionLogDebounceTimeoutMillis <= 0) {
return false;
}
final WindowManager.LayoutParams attrs = win.getAttrs();
final int type = attrs.type;
return type != TYPE_WALLPAPER
&& type != TYPE_APPLICATION_STARTING
&& type != TYPE_NAVIGATION_BAR
&& (attrs.flags & FLAG_NOT_TOUCHABLE) == 0
&& needsGestureExclusionRestrictions(win, 0 /* sysUiVisibility */)
&& win.getDisplayContent().mDisplayPolicy.hasSideGestures();
}
/**
* Adds a local gesture exclusion area to the global area while applying a limit per edge.
*
@@ -5253,25 +5304,34 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
* @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.
* @param win The WindowState that is being processed
* @param side The side that is being processed, either {@link WindowState#EXCLUSION_LEFT} or
* {@link WindowState#EXCLUSION_RIGHT}
* @return How much of the limit is remaining.
*/
private static int addToGlobalAndConsumeLimit(Region local, Region global, Rect edge,
int limit) {
int limit, WindowState win, int side) {
final Region r = Region.obtain(local);
r.op(edge, Op.INTERSECT);
final int[] remaining = {limit};
final int[] requestedExclusion = {0};
forEachRectReverse(r, rect -> {
if (remaining[0] <= 0) {
return;
}
final int height = rect.height();
requestedExclusion[0] += height;
if (height > remaining[0]) {
rect.top = rect.bottom - remaining[0];
}
remaining[0] -= height;
global.op(rect, Op.UNION);
});
final int grantedExclusion = limit - remaining[0];
win.setLastExclusionHeights(side, requestedExclusion[0], grantedExclusion);
r.recycle();
return remaining[0];
}
@@ -5286,10 +5346,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
if (!changed) {
final Region unrestrictedOrNull = mSystemGestureExclusionWasRestricted
? mSystemGestureExclusionUnrestricted : null;
// If updateSystemGestureExclusion changed the exclusion, it will already have
// notified the listener. Otherwise, we'll do it here.
try {
listener.onSystemGestureExclusionChanged(mDisplayId, mSystemGestureExclusion);
listener.onSystemGestureExclusionChanged(mDisplayId, mSystemGestureExclusion,
unrestrictedOrNull);
} catch (RemoteException e) {
Slog.e(TAG, "Failed to notify SystemGestureExclusionListener during register", e);
}

View File

@@ -478,9 +478,10 @@ public class DisplayPolicy {
@Override
public void onSwipeFromRight() {
final Region excludedRegion;
final Region excludedRegion = Region.obtain();
synchronized (mLock) {
excludedRegion = mDisplayContent.calculateSystemGestureExclusion();
mDisplayContent.calculateSystemGestureExclusion(
excludedRegion, null /* outUnrestricted */);
}
final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture
|| mNavigationBarPosition == NAV_BAR_RIGHT;
@@ -488,13 +489,15 @@ public class DisplayPolicy {
&& !mSystemGestures.currentGestureStartedInRegion(excludedRegion)) {
requestTransientBars(mNavigationBar);
}
excludedRegion.recycle();
}
@Override
public void onSwipeFromLeft() {
final Region excludedRegion;
final Region excludedRegion = Region.obtain();
synchronized (mLock) {
excludedRegion = mDisplayContent.calculateSystemGestureExclusion();
mDisplayContent.calculateSystemGestureExclusion(
excludedRegion, null /* outUnrestricted */);
}
final boolean sideAllowed = mNavigationBarAlwaysShowOnSideGesture
|| mNavigationBarPosition == NAV_BAR_LEFT;
@@ -502,6 +505,7 @@ public class DisplayPolicy {
&& !mSystemGestures.currentGestureStartedInRegion(excludedRegion)) {
requestTransientBars(mNavigationBar);
}
excludedRegion.recycle();
}
@Override
@@ -674,6 +678,10 @@ public class DisplayPolicy {
return mHasStatusBar;
}
boolean hasSideGestures() {
return mHasNavigationBar && mSideGestureInset > 0;
}
public boolean navigationBarCanMove() {
return mNavigationBarCanMove;
}

View File

@@ -34,6 +34,7 @@ import static android.os.Process.myPid;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.provider.DeviceConfig.WindowManager.KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE;
import static android.provider.DeviceConfig.WindowManager.KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP;
import static android.provider.DeviceConfig.WindowManager.KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS;
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;
@@ -847,6 +848,16 @@ public class WindowManagerService extends IWindowManager.Stub
int mSystemGestureExclusionLimitDp;
boolean mSystemGestureExcludedByPreQStickyImmersive;
/**
* The minimum duration between gesture exclusion logging for a given window in
* milliseconds.
*
* Events that happen in-between will be silently dropped.
*
* A non-positive value disables logging.
*/
public long mSystemGestureExclusionLogDebounceTimeoutMillis;
public interface WindowChangeListener {
public void windowsChanged();
public void focusChanged();
@@ -1146,6 +1157,9 @@ public class WindowManagerService extends IWindowManager.Stub
mSystemGestureExclusionLimitDp = Math.max(MIN_GESTURE_EXCLUSION_LIMIT_DP,
DeviceConfig.getInt(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, 0));
mSystemGestureExclusionLogDebounceTimeoutMillis =
DeviceConfig.getInt(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS, 0);
mSystemGestureExcludedByPreQStickyImmersive =
DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE, false);
@@ -1163,6 +1177,10 @@ public class WindowManagerService extends IWindowManager.Stub
mSystemGestureExcludedByPreQStickyImmersive = excludedByPreQSticky;
mRoot.forAllDisplays(DisplayContent::updateSystemGestureExclusionLimit);
}
mSystemGestureExclusionLogDebounceTimeoutMillis =
DeviceConfig.getInt(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS, 0);
}
});

View File

@@ -20,6 +20,8 @@ import static android.app.ActivityTaskManager.INVALID_STACK_ID;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_DEFAULT;
import static android.app.AppOpsManager.OP_NONE;
import static android.app.WindowConfiguration.isSplitScreenWindowingMode;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.os.PowerManager.DRAW_WAKE_LOCK;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -80,6 +82,7 @@ import static com.android.server.policy.WindowManagerPolicy.TRANSIT_ENTER;
import static com.android.server.policy.WindowManagerPolicy.TRANSIT_EXIT;
import static com.android.server.policy.WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
import static com.android.server.wm.AnimationSpecProto.MOVE;
import static com.android.server.wm.DisplayContent.logsGestureExclusionRestrictions;
import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
import static com.android.server.wm.IdentifierProto.HASH_CODE;
@@ -174,6 +177,7 @@ import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.util.MergedConfiguration;
import android.util.Slog;
import android.util.StatsLog;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
import android.view.Display;
@@ -227,6 +231,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// to capture touch events in that area.
static final int RESIZE_HANDLE_WIDTH_IN_DP = 30;
static final int EXCLUSION_LEFT = 0;
static final int EXCLUSION_RIGHT = 1;
final WindowManagerPolicy mPolicy;
final Context mContext;
final Session mSession;
@@ -397,6 +404,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
*/
private final List<Rect> mExclusionRects = new ArrayList<>();
// 0 = left, 1 = right
private final int[] mLastRequestedExclusionHeight = {0, 0};
private final int[] mLastGrantedExclusionHeight = {0, 0};
private final long[] mLastExclusionLogUptimeMillis = {0, 0};
private boolean mLastShownChangedReported;
// If a window showing a wallpaper: the requested offset for the
// wallpaper; if a wallpaper window: the currently applied offset.
float mWallpaperX = -1;
@@ -679,6 +693,20 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
&& mAppToken != null && mAppToken.mTargetSdk < Build.VERSION_CODES.Q;
}
void setLastExclusionHeights(int side, int requested, int granted) {
boolean changed = mLastGrantedExclusionHeight[side] != granted
|| mLastRequestedExclusionHeight[side] != requested;
if (changed) {
if (mLastShownChangedReported) {
logExclusionRestrictions(side);
}
mLastGrantedExclusionHeight[side] = granted;
mLastRequestedExclusionHeight[side] = requested;
}
}
interface PowerManagerWrapper {
void wakeUp(long time, @WakeReason int reason, String details);
@@ -2957,6 +2985,49 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mAnimatingExit = false;
}
void onSurfaceShownChanged(boolean shown) {
if (mLastShownChangedReported == shown) {
return;
}
mLastShownChangedReported = shown;
if (shown) {
initExclusionRestrictions();
} else {
logExclusionRestrictions(EXCLUSION_LEFT);
logExclusionRestrictions(EXCLUSION_RIGHT);
}
}
private void logExclusionRestrictions(int side) {
if (!logsGestureExclusionRestrictions(this)
|| SystemClock.uptimeMillis() < mLastExclusionLogUptimeMillis[side]
+ mWmService.mSystemGestureExclusionLogDebounceTimeoutMillis) {
// Drop the log if we have just logged; this is okay, because what we would have logged
// was true only for a short duration.
return;
}
final long now = SystemClock.uptimeMillis();
final long duration = now - mLastExclusionLogUptimeMillis[side];
mLastExclusionLogUptimeMillis[side] = now;
final int requested = mLastRequestedExclusionHeight[side];
final int granted = mLastGrantedExclusionHeight[side];
StatsLog.write(StatsLog.EXCLUSION_RECT_STATE_CHANGED,
mAttrs.packageName, requested, requested - granted /* rejected */,
side + 1 /* Sides are 1-indexed in atoms.proto */,
(getConfiguration().orientation == ORIENTATION_LANDSCAPE),
isSplitScreenWindowingMode(getWindowingMode()), (int) duration);
}
private void initExclusionRestrictions() {
final long now = SystemClock.uptimeMillis();
mLastExclusionLogUptimeMillis[EXCLUSION_LEFT] = now;
mLastExclusionLogUptimeMillis[EXCLUSION_RIGHT] = now;
}
@Override
public boolean isDefaultDisplay() {
final DisplayContent displayContent = getDisplayContent();

View File

@@ -507,6 +507,8 @@ class WindowSurfaceController {
mService.updateNonSystemOverlayWindowsVisibilityIfNeeded(mAnimator.mWin, surfaceShown);
mAnimator.mWin.onSurfaceShownChanged(surfaceShown);
if (mWindowSession != null) {
mWindowSession.onWindowSurfaceVisibilityChanged(this, mSurfaceShown, mWindowType);
}

View File

@@ -756,7 +756,8 @@ public class DisplayContentTests extends WindowTestsBase {
final ISystemGestureExclusionListener.Stub verifier =
new ISystemGestureExclusionListener.Stub() {
@Override
public void onSystemGestureExclusionChanged(int displayId, Region actual) {
public void onSystemGestureExclusionChanged(int displayId, Region actual,
Region unrestricted) {
Region expected = Region.obtain();
expected.set(10, 20, 30, 40);
assertEquals(expected, actual);
@@ -790,7 +791,14 @@ public class DisplayContentTests extends WindowTestsBase {
final Region expected = Region.obtain();
expected.set(20, 30, 40, 50);
assertEquals(expected, dc.calculateSystemGestureExclusion());
assertEquals(expected, calculateSystemGestureExclusion(dc));
}
private Region calculateSystemGestureExclusion(DisplayContent dc) {
Region out = Region.obtain();
Region unrestricted = Region.obtain();
dc.calculateSystemGestureExclusion(out, unrestricted);
return out;
}
@Test
@@ -814,7 +822,7 @@ public class DisplayContentTests extends WindowTestsBase {
win2.setHasSurface(true);
final Region expected = Region.obtain();
assertEquals(expected, dc.calculateSystemGestureExclusion());
assertEquals(expected, calculateSystemGestureExclusion(dc));
}
@Test
@@ -839,7 +847,7 @@ public class DisplayContentTests extends WindowTestsBase {
final Region expected = Region.obtain();
expected.set(dc.getBounds());
assertEquals(expected, dc.calculateSystemGestureExclusion());
assertEquals(expected, calculateSystemGestureExclusion(dc));
win.setHasSurface(false);
}