Merge "Migrate Presentation to WindowContext"
diff --git a/core/java/android/app/Presentation.java b/core/java/android/app/Presentation.java
index 7a18b81..ad90364 100644
--- a/core/java/android/app/Presentation.java
+++ b/core/java/android/app/Presentation.java
@@ -16,30 +16,28 @@
package android.app;
-import static android.content.Context.DISPLAY_SERVICE;
-import static android.content.Context.WINDOW_SERVICE;
+import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
+import android.annotation.NonNull;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
-import android.os.Binder;
+import android.os.Build;
import android.os.Handler;
-import android.os.IBinder;
-import android.os.Message;
-import android.util.DisplayMetrics;
-import android.util.Log;
+import android.os.Looper;
import android.util.TypedValue;
import android.view.ContextThemeWrapper;
import android.view.Display;
import android.view.Gravity;
import android.view.Window;
import android.view.WindowManager;
-import android.view.WindowManagerImpl;
+import android.view.WindowManager.LayoutParams.WindowType;
+import com.android.internal.util.Preconditions;
/**
* Base class for presentations.
* <p>
@@ -153,11 +151,10 @@
public class Presentation extends Dialog {
private static final String TAG = "Presentation";
- private static final int MSG_CANCEL = 1;
-
private final Display mDisplay;
private final DisplayManager mDisplayManager;
- private final IBinder mToken = new Binder();
+ private final Handler mHandler = new Handler(Preconditions.checkNotNull(Looper.myLooper(),
+ "Presentation must be constructed on a looper thread."));
/**
* Creates a new presentation that is attached to the specified display
@@ -179,6 +176,11 @@
* @param outerContext The context of the application that is showing the presentation.
* The presentation will create its own context (see {@link #getContext()}) based
* on this context and information about the associated display.
+ * From {@link android.os.Build.VERSION_CODES#S}, the presentation will create its own window
+ * context based on this context, information about the associated display. Customizing window
+ * type by {@link Window#setType(int) #getWindow#setType(int)} causes the mismatch of the window
+ * and the created window context, which leads to
+ * {@link android.view.WindowManager.InvalidDisplayException} when invoking {@link #show()}.
* @param display The display to which the presentation should be attached.
* @param theme A style resource describing the theme to use for the window.
* See <a href="{@docRoot}guide/topics/resources/available-resources.html#stylesandthemes">
@@ -187,24 +189,53 @@
* <var>outerContext</var>. If 0, the default presentation theme will be used.
*/
public Presentation(Context outerContext, Display display, int theme) {
- super(createPresentationContext(outerContext, display, theme), theme, false);
+ this(outerContext, display, theme, INVALID_WINDOW_TYPE);
+ }
+
+ /**
+ * Creates a new presentation that is attached to the specified display
+ * using the optionally specified theme, and override the default window type for the
+ * presentation.
+ * @param outerContext The context of the application that is showing the presentation.
+ * The presentation will create its own context (see {@link #getContext()}) based
+ * on this context and information about the associated display.
+ * From {@link android.os.Build.VERSION_CODES#S}, the presentation will create its own window
+ * context based on this context, information about the associated display and the window type.
+ * If the window type is not specified, the presentation will choose the default type for the
+ * presentation.
+ * @param display The display to which the presentation should be attached.
+ * @param theme A style resource describing the theme to use for the window.
+ * See <a href="{@docRoot}guide/topics/resources/available-resources.html#stylesandthemes">
+ * Style and Theme Resources</a> for more information about defining and using
+ * styles. This theme is applied on top of the current theme in
+ * <var>outerContext</var>. If 0, the default presentation theme will be used.
+ * @param type Window type.
+ *
+ * @hide
+ */
+ public Presentation(@NonNull Context outerContext, @NonNull Display display, int theme,
+ @WindowType int type) {
+ super(createPresentationContext(outerContext, display, theme, type), theme, false);
mDisplay = display;
- mDisplayManager = (DisplayManager)getContext().getSystemService(DISPLAY_SERVICE);
-
- final int windowType =
- (display.getFlags() & Display.FLAG_PRIVATE) != 0 ? TYPE_PRIVATE_PRESENTATION
- : TYPE_PRESENTATION;
+ mDisplayManager = getContext().getSystemService(DisplayManager.class);
final Window w = getWindow();
final WindowManager.LayoutParams attr = w.getAttributes();
- attr.token = mToken;
w.setAttributes(attr);
w.setGravity(Gravity.FILL);
- w.setType(windowType);
+ w.setType(getWindowType(type, display));
setCanceledOnTouchOutside(false);
}
+ private static @WindowType int getWindowType(@WindowType int type, @NonNull Display display) {
+ if (type != INVALID_WINDOW_TYPE) {
+ return type;
+ }
+ return (display.getFlags() & Display.FLAG_PRIVATE) != 0 ? TYPE_PRIVATE_PRESENTATION
+ : TYPE_PRESENTATION;
+ }
+
/**
* Gets the {@link Display} that this presentation appears on.
*
@@ -229,16 +260,6 @@
protected void onStart() {
super.onStart();
mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
-
- // Since we were not watching for display changes until just now, there is a
- // chance that the display metrics have changed. If so, we will need to
- // dismiss the presentation immediately. This case is expected
- // to be rare but surprising, so we'll write a log message about it.
- if (!isConfigurationStillValid()) {
- Log.i(TAG, "Presentation is being dismissed because the "
- + "display metrics have changed since it was created.");
- mHandler.sendEmptyMessage(MSG_CANCEL);
- }
}
@Override
@@ -273,10 +294,6 @@
* Called by the system when the properties of the {@link Display} to which
* the presentation is attached have changed.
*
- * If the display metrics have changed (for example, if the display has been
- * resized or rotated), then the system automatically calls
- * {@link #cancel} to dismiss the presentation.
- *
* @see #getDisplay
*/
public void onDisplayChanged() {
@@ -289,28 +306,16 @@
private void handleDisplayChanged() {
onDisplayChanged();
-
- // We currently do not support configuration changes for presentations
- // (although we could add that feature with a bit more work).
- // If the display metrics have changed in any way then the current configuration
- // is invalid and the application must recreate the presentation to get
- // a new context.
- if (!isConfigurationStillValid()) {
- Log.i(TAG, "Presentation is being dismissed because the "
- + "display metrics have changed since it was created.");
- cancel();
- }
}
- private boolean isConfigurationStillValid() {
- DisplayMetrics dm = new DisplayMetrics();
- mDisplay.getMetrics(dm);
- return dm.equalsPhysical(getResources().getDisplayMetrics());
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "{@code N/A}")
+ private static Context createPresentationContext(Context outerContext, Display display,
+ int theme) {
+ return createPresentationContext(outerContext, display, theme, INVALID_WINDOW_TYPE);
}
- @UnsupportedAppUsage
private static Context createPresentationContext(
- Context outerContext, Display display, int theme) {
+ Context outerContext, Display display, int theme, @WindowType int type) {
if (outerContext == null) {
throw new IllegalArgumentException("outerContext must not be null");
}
@@ -318,31 +323,15 @@
throw new IllegalArgumentException("display must not be null");
}
- Context displayContext = outerContext.createDisplayContext(display);
+ Context windowContext = outerContext.createDisplayContext(display)
+ .createWindowContext(getWindowType(type, display), null /* options */);
if (theme == 0) {
TypedValue outValue = new TypedValue();
- displayContext.getTheme().resolveAttribute(
+ windowContext.getTheme().resolveAttribute(
com.android.internal.R.attr.presentationTheme, outValue, true);
theme = outValue.resourceId;
}
-
- // Derive the display's window manager from the outer window manager.
- // We do this because the outer window manager have some extra information
- // such as the parent window, which is important if the presentation uses
- // an application window type.
- final WindowManagerImpl outerWindowManager =
- (WindowManagerImpl)outerContext.getSystemService(WINDOW_SERVICE);
- final WindowManagerImpl displayWindowManager =
- outerWindowManager.createPresentationWindowManager(displayContext);
- return new ContextThemeWrapper(displayContext, theme) {
- @Override
- public Object getSystemService(String name) {
- if (WINDOW_SERVICE.equals(name)) {
- return displayWindowManager;
- }
- return super.getSystemService(name);
- }
- };
+ return new ContextThemeWrapper(windowContext, theme);
}
private final DisplayListener mDisplayListener = new DisplayListener() {
@@ -364,15 +353,4 @@
}
}
};
-
- private final Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_CANCEL:
- cancel();
- break;
- }
- }
- };
}
diff --git a/core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java b/core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java
index 0f6284d..01cf311 100644
--- a/core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java
+++ b/core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java
@@ -362,14 +362,12 @@
private final class TestPresentation extends Presentation {
private final int mColor;
- private final int mWindowType;
private final int mWindowFlags;
public TestPresentation(Context context, Display display,
int color, int windowType, int windowFlags) {
- super(context, display);
+ super(context, display, 0 /* theme */, windowType);
mColor = color;
- mWindowType = windowType;
mWindowFlags = windowFlags;
}
@@ -378,7 +376,6 @@
super.onCreate(savedInstanceState);
setTitle(TAG);
- getWindow().setType(mWindowType);
getWindow().addFlags(mWindowFlags);
// Create a solid color image to use as the content of the presentation.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
index 36d5543..901a736 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
@@ -20,7 +20,7 @@
import android.app.Presentation;
import android.content.Context;
import android.graphics.Color;
-import android.graphics.Point;
+import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.media.MediaRouter;
import android.media.MediaRouter.RouteInfo;
@@ -127,7 +127,7 @@
Presentation presentation = mPresentations.get(displayId);
if (presentation == null) {
final Presentation newPresentation = new KeyguardPresentation(mContext, display,
- mKeyguardStatusViewComponentFactory, LayoutInflater.from(mContext));
+ mKeyguardStatusViewComponentFactory);
newPresentation.setOnDismissListener(dialog -> {
if (newPresentation.equals(mPresentations.get(displayId))) {
mPresentations.remove(displayId);
@@ -245,7 +245,6 @@
private static final int VIDEO_SAFE_REGION = 80; // Percentage of display width & height
private static final int MOVE_CLOCK_TIMEOUT = 10000; // 10s
private final KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory;
- private final LayoutInflater mLayoutInflater;
private KeyguardClockSwitchController mKeyguardClockSwitchController;
private View mClock;
private int mUsableWidth;
@@ -264,18 +263,16 @@
};
KeyguardPresentation(Context context, Display display,
- KeyguardStatusViewComponent.Factory keyguardStatusViewComponentFactory,
- LayoutInflater layoutInflater) {
- super(context, display, R.style.Theme_SystemUI_KeyguardPresentation);
+ KeyguardStatusViewComponent.Factory keyguardStatusViewComponentFactory) {
+ super(context, display, R.style.Theme_SystemUI_KeyguardPresentation,
+ WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
mKeyguardStatusViewComponentFactory = keyguardStatusViewComponentFactory;
- mLayoutInflater = layoutInflater;
- getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
setCancelable(false);
}
@Override
public void cancel() {
- // Do not allow anything to cancel KeyguardPresetation except KeyguardDisplayManager.
+ // Do not allow anything to cancel KeyguardPresentation except KeyguardDisplayManager.
}
@Override
@@ -287,14 +284,15 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- Point p = new Point();
- getDisplay().getSize(p);
- mUsableWidth = VIDEO_SAFE_REGION * p.x/100;
- mUsableHeight = VIDEO_SAFE_REGION * p.y/100;
- mMarginLeft = (100 - VIDEO_SAFE_REGION) * p.x / 200;
- mMarginTop = (100 - VIDEO_SAFE_REGION) * p.y / 200;
+ final Rect bounds = getWindow().getWindowManager().getMaximumWindowMetrics()
+ .getBounds();
+ mUsableWidth = VIDEO_SAFE_REGION * bounds.width() / 100;
+ mUsableHeight = VIDEO_SAFE_REGION * bounds.height() / 100;
+ mMarginLeft = (100 - VIDEO_SAFE_REGION) * bounds.width() / 200;
+ mMarginTop = (100 - VIDEO_SAFE_REGION) * bounds.height() / 200;
- setContentView(mLayoutInflater.inflate(R.layout.keyguard_presentation, null));
+ setContentView(LayoutInflater.from(getContext())
+ .inflate(R.layout.keyguard_presentation, null));
// Logic to make the lock screen fullscreen
getWindow().getDecorView().setSystemUiVisibility(
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java
index ae159c7..62906f3 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java
@@ -20,9 +20,11 @@
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.hardware.display.DisplayManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.util.AttributeSet;
+import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
@@ -104,9 +106,10 @@
@Test
public void testInflation_doesntCrash() {
- KeyguardPresentation keyguardPresentation = new KeyguardPresentation(mContext,
- mContext.getDisplayNoVerify(), mKeyguardStatusViewComponentFactory,
- mLayoutInflater);
+ final Display display = mContext.getSystemService(DisplayManager.class).getDisplay(
+ Display.DEFAULT_DISPLAY);
+ KeyguardPresentation keyguardPresentation = new KeyguardPresentation(mContext, display,
+ mKeyguardStatusViewComponentFactory);
keyguardPresentation.onCreate(null /*savedInstanceState */);
}
}