summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/WindowManager.java10
-rw-r--r--core/java/android/view/WindowManagerPolicy.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java10
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java74
-rw-r--r--services/core/java/com/android/server/wm/Session.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java5
6 files changed, 98 insertions, 16 deletions
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index fe50a6484ba8..e56a82ffabd2 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -16,6 +16,7 @@
package android.view;
+import android.Manifest.permission;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
@@ -1425,6 +1426,15 @@ public interface WindowManager extends ViewManager {
public static final int PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY = 0x00100000;
/**
+ * If this flag is set on the window, window manager will acquire a sleep token that puts
+ * all activities to sleep as long as this window is visible. When this flag is set, the
+ * window needs to occlude all activity windows.
+ * @hide
+ */
+ @RequiresPermission(permission.DEVICE_POWER)
+ public static final int PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN = 0x00200000;
+
+ /**
* Control flags that are private to the platform.
* @hide
*/
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index d2eb7850b6ab..66506a18296b 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -16,6 +16,7 @@
package android.view;
+import static android.Manifest.permission;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
@@ -486,11 +487,17 @@ public interface WindowManagerPolicy {
/**
* Returns true if the window owner can add internal system windows.
- * That is, they have {@link android.Manifest.permission#INTERNAL_SYSTEM_WINDOW}.
+ * That is, they have {@link permission#INTERNAL_SYSTEM_WINDOW}.
*/
default boolean canAddInternalSystemWindow() {
return false;
}
+
+ /**
+ * Returns true if the window owner has the permission to acquire a sleep token when it's
+ * visible. That is, they have the permission {@link permission#DEVICE_POWER}.
+ */
+ boolean canAcquireSleepToken();
}
/**
@@ -775,7 +782,7 @@ public interface WindowManagerPolicy {
* @param type The type of window being assigned.
* @param canAddInternalSystemWindow If the owner window associated with the type we are
* evaluating can add internal system windows. I.e they have
- * {@link android.Manifest.permission#INTERNAL_SYSTEM_WINDOW}. If true, alert window
+ * {@link permission#INTERNAL_SYSTEM_WINDOW}. If true, alert window
* types {@link android.view.WindowManager.LayoutParams#isSystemAlertWindowType(int)}
* can be assigned layers greater than the layer for
* {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY} Else, their
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index eaa6a33b05d7..ed96b4115888 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -30,6 +30,7 @@ import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
import com.android.keyguard.R;
import com.android.systemui.Dumpable;
@@ -230,6 +231,7 @@ public class StatusBarWindowManager implements RemoteInputController.Callback, D
applyModalFlag(state);
applyBrightness(state);
applyHasTopUi(state);
+ applySleepToken(state);
if (mLp.copyFrom(mLpChanged) != 0) {
mWindowManager.updateViewLayout(mStatusBarView, mLp);
}
@@ -273,6 +275,14 @@ public class StatusBarWindowManager implements RemoteInputController.Callback, D
mHasTopUiChanged = isExpanded(state);
}
+ private void applySleepToken(State state) {
+ if (state.dozing) {
+ mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN;
+ } else {
+ mLpChanged.privateFlags &= ~LayoutParams.PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN;
+ }
+ }
+
public void setKeyguardShowing(boolean showing) {
mCurrentState.keyguardShowing = showing;
apply(mCurrentState);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 7fda2aacfca2..73a29ac75b71 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -26,8 +26,8 @@ import static android.app.AppOpsManager.OP_TOAST_WINDOW;
import static android.content.Context.CONTEXT_RESTRICTED;
import static android.content.Context.DISPLAY_SERVICE;
import static android.content.Context.WINDOW_SERVICE;
-import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
import static android.content.pm.PackageManager.FEATURE_LEANBACK;
+import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE;
import static android.content.pm.PackageManager.FEATURE_WATCH;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.content.res.Configuration.EMPTY;
@@ -35,6 +35,8 @@ import static android.content.res.Configuration.UI_MODE_TYPE_CAR;
import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
import static android.os.Build.VERSION_CODES.M;
import static android.os.Build.VERSION_CODES.O;
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.STATE_OFF;
import static android.view.WindowManager.DOCKED_LEFT;
import static android.view.WindowManager.DOCKED_RIGHT;
import static android.view.WindowManager.DOCKED_TOP;
@@ -57,6 +59,7 @@ import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_SYSTEM_WINDOW;
import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
@@ -70,8 +73,8 @@ import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
import static android.view.WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
@@ -180,8 +183,8 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UEventObserver;
import android.os.UserHandle;
-import android.os.Vibrator;
import android.os.VibrationEffect;
+import android.os.Vibrator;
import android.provider.MediaStore;
import android.provider.Settings;
import android.service.dreams.DreamManagerInternal;
@@ -230,6 +233,7 @@ import android.view.autofill.AutofillManagerInternal;
import android.view.inputmethod.InputMethodManagerInternal;
import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IShortcutService;
@@ -244,8 +248,8 @@ import com.android.server.policy.keyguard.KeyguardServiceDelegate;
import com.android.server.policy.keyguard.KeyguardServiceDelegate.DrawnListener;
import com.android.server.policy.keyguard.KeyguardStateMonitor.StateCallback;
import com.android.server.statusbar.StatusBarManagerInternal;
-import com.android.server.wm.AppTransition;
import com.android.server.vr.VrManagerInternal;
+import com.android.server.wm.AppTransition;
import java.io.File;
import java.io.FileReader;
@@ -680,6 +684,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private boolean mLastShowingDream;
boolean mDreamingLockscreen;
boolean mDreamingSleepTokenNeeded;
+ private boolean mWindowSleepTokenNeeded;
+ private boolean mLastWindowSleepTokenNeeded;
+
+ @GuardedBy("mHandler")
+ private SleepToken mWindowSleepToken;
+
SleepToken mDreamingSleepToken;
SleepToken mScreenOffSleepToken;
volatile boolean mKeyguardOccluded;
@@ -1040,6 +1050,22 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
};
+ private final Runnable mAcquireSleepTokenRunnable = () -> {
+ if (mWindowSleepToken != null) {
+ return;
+ }
+ mWindowSleepToken = mActivityManagerInternal.acquireSleepToken("WindowSleepToken",
+ DEFAULT_DISPLAY);
+ };
+
+ private final Runnable mReleaseSleepTokenRunnable = () -> {
+ if (mWindowSleepToken == null) {
+ return;
+ }
+ mWindowSleepToken.release();
+ mWindowSleepToken = null;
+ };
+
private ImmersiveModeConfirmation mImmersiveModeConfirmation;
private SystemGesturesPointerEventListener mSystemGestures;
@@ -2152,7 +2178,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// This method might be called before the policy has been fully initialized
// or for other displays we don't care about.
// TODO(multi-display): Define policy for secondary displays.
- if (mContext == null || display.getDisplayId() != Display.DEFAULT_DISPLAY) {
+ if (mContext == null || display.getDisplayId() != DEFAULT_DISPLAY) {
return;
}
mDisplay = display;
@@ -2248,7 +2274,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public void setDisplayOverscan(Display display, int left, int top, int right, int bottom) {
// TODO(multi-display): Define policy for secondary displays.
- if (display.getDisplayId() == Display.DEFAULT_DISPLAY) {
+ if (display.getDisplayId() == DEFAULT_DISPLAY) {
mOverscanLeft = left;
mOverscanTop = top;
mOverscanRight = right;
@@ -2704,7 +2730,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation, int uiMode,
int displayId) {
// TODO(multi-display): Support navigation bar on secondary displays.
- if (displayId == Display.DEFAULT_DISPLAY && mHasNavigationBar) {
+ if (displayId == DEFAULT_DISPLAY && mHasNavigationBar) {
// For a basic navigation bar, when we are in landscape mode we place
// the navigation bar to the side.
if (mNavigationBarCanMove && fullWidth > fullHeight) {
@@ -2726,7 +2752,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation, int uiMode,
int displayId) {
// TODO(multi-display): Support navigation bar on secondary displays.
- if (displayId == Display.DEFAULT_DISPLAY && mHasNavigationBar) {
+ if (displayId == DEFAULT_DISPLAY && mHasNavigationBar) {
// For a basic navigation bar, when we are in portrait mode we place
// the navigation bar to the bottom.
if (!mNavigationBarCanMove || fullWidth < fullHeight) {
@@ -2750,7 +2776,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// we do want to exclude it since applications can't generally use that part
// of the screen.
// TODO(multi-display): Support status bars on secondary displays.
- if (displayId == Display.DEFAULT_DISPLAY) {
+ if (displayId == DEFAULT_DISPLAY) {
return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation, uiMode, displayId)
- mStatusBarHeight;
}
@@ -2802,7 +2828,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
boolean keyguardLocked = isKeyguardLocked();
boolean hideDockDivider = attrs.type == TYPE_DOCK_DIVIDER
&& !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
- return (keyguardLocked && !allowWhenLocked && win.getDisplayId() == Display.DEFAULT_DISPLAY)
+ return (keyguardLocked && !allowWhenLocked && win.getDisplayId() == DEFAULT_DISPLAY)
|| hideDockDivider;
}
@@ -2972,7 +2998,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
/** Obtain proper context for showing splash screen on the provided display. */
private Context getDisplayContext(Context context, int displayId) {
- if (displayId == Display.DEFAULT_DISPLAY) {
+ if (displayId == DEFAULT_DISPLAY) {
// The default context fits.
return context;
}
@@ -5370,6 +5396,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mAllowLockscreenWhenOn = false;
mShowingDream = false;
+ mWindowSleepTokenNeeded = false;
}
/** {@inheritDoc} */
@@ -5467,6 +5494,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
&& stackId == DOCKED_STACK_ID) {
mTopDockedOpaqueOrDimmingWindowState = win;
}
+
+ // Take note if a window wants to acquire a sleep token.
+ if (win.isVisibleLw() && (attrs.privateFlags & PRIVATE_FLAG_ACQUIRES_SLEEP_TOKEN) != 0
+ && win.canAcquireSleepToken()) {
+ mWindowSleepTokenNeeded = true;
+ }
}
private void applyKeyguardPolicyLw(WindowState win, WindowState imeTarget) {
@@ -5597,11 +5630,24 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mWindowManagerFuncs.notifyShowingDreamChanged();
}
+ updateWindowSleepToken();
+
// update since mAllowLockscreenWhenOn might have changed
updateLockScreenTimeout();
return changes;
}
+ private void updateWindowSleepToken() {
+ if (mWindowSleepTokenNeeded && !mLastWindowSleepTokenNeeded) {
+ mHandler.removeCallbacks(mReleaseSleepTokenRunnable);
+ mHandler.post(mAcquireSleepTokenRunnable);
+ } else if (!mWindowSleepTokenNeeded && mLastWindowSleepTokenNeeded) {
+ mHandler.removeCallbacks(mAcquireSleepTokenRunnable);
+ mHandler.post(mReleaseSleepTokenRunnable);
+ }
+ mLastWindowSleepTokenNeeded = mWindowSleepTokenNeeded;
+ }
+
/**
* Updates the occluded state of the Keyguard.
*
@@ -6335,7 +6381,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) {
- final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF);
+ final boolean displayOff = (mDisplay == null || mDisplay.getState() == STATE_OFF);
if (displayOff && !mHasFeatureWatch) {
return false;
@@ -7476,7 +7522,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (acquire) {
if (mDreamingSleepToken == null) {
mDreamingSleepToken = mActivityManagerInternal.acquireSleepToken(
- "Dream", Display.DEFAULT_DISPLAY);
+ "Dream", DEFAULT_DISPLAY);
}
} else {
if (mDreamingSleepToken != null) {
@@ -7491,7 +7537,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (acquire) {
if (mScreenOffSleepToken == null) {
mScreenOffSleepToken = mActivityManagerInternal.acquireSleepToken(
- "ScreenOff", Display.DEFAULT_DISPLAY);
+ "ScreenOff", DEFAULT_DISPLAY);
}
} else {
if (mScreenOffSleepToken != null) {
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 7a8c2f91b4e9..178124776823 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -16,6 +16,7 @@
package com.android.server.wm;
+import static android.Manifest.permission.DEVICE_POWER;
import static android.Manifest.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -84,6 +85,7 @@ public class Session extends IWindowSession.Stub
private final Set<WindowSurfaceController> mAlertWindowSurfaces = new HashSet<>();
final boolean mCanAddInternalSystemWindow;
final boolean mCanHideNonSystemOverlayWindows;
+ final boolean mCanAcquireSleepToken;
private AlertWindowNotification mAlertWindowNotification;
private boolean mShowingAlertWindowNotificationAllowed;
private boolean mClientDead = false;
@@ -103,6 +105,8 @@ public class Session extends IWindowSession.Stub
INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED;
mCanHideNonSystemOverlayWindows = service.mContext.checkCallingOrSelfPermission(
HIDE_NON_SYSTEM_OVERLAY_WINDOWS) == PERMISSION_GRANTED;
+ mCanAcquireSleepToken = service.mContext.checkCallingOrSelfPermission(DEVICE_POWER)
+ == PERMISSION_GRANTED;
mShowingAlertWindowNotificationAllowed = mService.mShowAlertWindowNotifications;
StringBuilder sb = new StringBuilder();
sb.append("Session{");
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 85e3f6db7363..5a181f1077d3 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -752,6 +752,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
return mOwnerCanAddInternalSystemWindow;
}
+ @Override
+ public boolean canAcquireSleepToken() {
+ return mSession.mCanAcquireSleepToken;
+ }
+
/**
* Subtracts the insets calculated by intersecting {@param layoutFrame} with {@param insetFrame}
* from {@param frame}. In other words, it applies the insets that would result if