Loading core/java/android/app/Presentation.java +59 −81 Original line number Original line Diff line number Diff line Loading @@ -16,30 +16,28 @@ package android.app; package android.app; import static android.content.Context.DISPLAY_SERVICE; import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE; import static android.content.Context.WINDOW_SERVICE; import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION; import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION; import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION; import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION; import android.annotation.NonNull; import android.compat.annotation.UnsupportedAppUsage; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.Context; import android.content.res.Resources; import android.content.res.Resources; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager.DisplayListener; import android.hardware.display.DisplayManager.DisplayListener; import android.os.Binder; import android.os.Build; import android.os.Handler; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.util.DisplayMetrics; import android.util.Log; import android.util.TypedValue; import android.util.TypedValue; import android.view.ContextThemeWrapper; import android.view.ContextThemeWrapper; import android.view.Display; import android.view.Display; import android.view.Gravity; import android.view.Gravity; import android.view.Window; import android.view.Window; import android.view.WindowManager; import android.view.WindowManager; import android.view.WindowManagerImpl; import android.view.WindowManager.LayoutParams.WindowType; import com.android.internal.util.Preconditions; /** /** * Base class for presentations. * Base class for presentations. * <p> * <p> Loading Loading @@ -153,11 +151,10 @@ import android.view.WindowManagerImpl; public class Presentation extends Dialog { public class Presentation extends Dialog { private static final String TAG = "Presentation"; private static final String TAG = "Presentation"; private static final int MSG_CANCEL = 1; private final Display mDisplay; private final Display mDisplay; private final DisplayManager mDisplayManager; 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 * Creates a new presentation that is attached to the specified display Loading @@ -179,6 +176,11 @@ public class Presentation extends Dialog { * @param outerContext The context of the application that is showing 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 * The presentation will create its own context (see {@link #getContext()}) based * on this context and information about the associated display. * 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 display The display to which the presentation should be attached. * @param theme A style resource describing the theme to use for the window. * @param theme A style resource describing the theme to use for the window. * See <a href="{@docRoot}guide/topics/resources/available-resources.html#stylesandthemes"> * See <a href="{@docRoot}guide/topics/resources/available-resources.html#stylesandthemes"> Loading @@ -187,24 +189,53 @@ public class Presentation extends Dialog { * <var>outerContext</var>. If 0, the default presentation theme will be used. * <var>outerContext</var>. If 0, the default presentation theme will be used. */ */ public Presentation(Context outerContext, Display display, int theme) { public Presentation(Context outerContext, Display display, int theme) { super(createPresentationContext(outerContext, display, theme), theme, false); this(outerContext, display, theme, INVALID_WINDOW_TYPE); } mDisplay = display; /** mDisplayManager = (DisplayManager)getContext().getSystemService(DISPLAY_SERVICE); * 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); final int windowType = mDisplay = display; (display.getFlags() & Display.FLAG_PRIVATE) != 0 ? TYPE_PRIVATE_PRESENTATION mDisplayManager = getContext().getSystemService(DisplayManager.class); : TYPE_PRESENTATION; final Window w = getWindow(); final Window w = getWindow(); final WindowManager.LayoutParams attr = w.getAttributes(); final WindowManager.LayoutParams attr = w.getAttributes(); attr.token = mToken; w.setAttributes(attr); w.setAttributes(attr); w.setGravity(Gravity.FILL); w.setGravity(Gravity.FILL); w.setType(windowType); w.setType(getWindowType(type, display)); setCanceledOnTouchOutside(false); 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. * Gets the {@link Display} that this presentation appears on. * * Loading @@ -229,16 +260,6 @@ public class Presentation extends Dialog { protected void onStart() { protected void onStart() { super.onStart(); super.onStart(); mDisplayManager.registerDisplayListener(mDisplayListener, mHandler); 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 @Override Loading Loading @@ -273,10 +294,6 @@ public class Presentation extends Dialog { * Called by the system when the properties of the {@link Display} to which * Called by the system when the properties of the {@link Display} to which * the presentation is attached have changed. * 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 * @see #getDisplay */ */ public void onDisplayChanged() { public void onDisplayChanged() { Loading @@ -289,28 +306,16 @@ public class Presentation extends Dialog { private void handleDisplayChanged() { private void handleDisplayChanged() { onDisplayChanged(); 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() { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "{@code N/A}") DisplayMetrics dm = new DisplayMetrics(); private static Context createPresentationContext(Context outerContext, Display display, mDisplay.getMetrics(dm); int theme) { return dm.equalsPhysical(getResources().getDisplayMetrics()); return createPresentationContext(outerContext, display, theme, INVALID_WINDOW_TYPE); } } @UnsupportedAppUsage private static Context createPresentationContext( private static Context createPresentationContext( Context outerContext, Display display, int theme) { Context outerContext, Display display, int theme, @WindowType int type) { if (outerContext == null) { if (outerContext == null) { throw new IllegalArgumentException("outerContext must not be null"); throw new IllegalArgumentException("outerContext must not be null"); } } Loading @@ -318,31 +323,15 @@ public class Presentation extends Dialog { throw new IllegalArgumentException("display must not be null"); 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) { if (theme == 0) { TypedValue outValue = new TypedValue(); TypedValue outValue = new TypedValue(); displayContext.getTheme().resolveAttribute( windowContext.getTheme().resolveAttribute( com.android.internal.R.attr.presentationTheme, outValue, true); com.android.internal.R.attr.presentationTheme, outValue, true); theme = outValue.resourceId; theme = outValue.resourceId; } } return new ContextThemeWrapper(windowContext, theme); // 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); } }; } } private final DisplayListener mDisplayListener = new DisplayListener() { private final DisplayListener mDisplayListener = new DisplayListener() { Loading @@ -364,15 +353,4 @@ public class Presentation extends Dialog { } } } } }; }; private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_CANCEL: cancel(); break; } } }; } } core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java +1 −4 Original line number Original line Diff line number Diff line Loading @@ -362,14 +362,12 @@ public class VirtualDisplayTest extends AndroidTestCase { private final class TestPresentation extends Presentation { private final class TestPresentation extends Presentation { private final int mColor; private final int mColor; private final int mWindowType; private final int mWindowFlags; private final int mWindowFlags; public TestPresentation(Context context, Display display, public TestPresentation(Context context, Display display, int color, int windowType, int windowFlags) { int color, int windowType, int windowFlags) { super(context, display); super(context, display, 0 /* theme */, windowType); mColor = color; mColor = color; mWindowType = windowType; mWindowFlags = windowFlags; mWindowFlags = windowFlags; } } Loading @@ -378,7 +376,6 @@ public class VirtualDisplayTest extends AndroidTestCase { super.onCreate(savedInstanceState); super.onCreate(savedInstanceState); setTitle(TAG); setTitle(TAG); getWindow().setType(mWindowType); getWindow().addFlags(mWindowFlags); getWindow().addFlags(mWindowFlags); // Create a solid color image to use as the content of the presentation. // Create a solid color image to use as the content of the presentation. Loading packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java +14 −16 Original line number Original line Diff line number Diff line Loading @@ -20,7 +20,7 @@ import static android.view.Display.DEFAULT_DISPLAY; import android.app.Presentation; import android.app.Presentation; import android.content.Context; import android.content.Context; import android.graphics.Color; import android.graphics.Color; import android.graphics.Point; import android.graphics.Rect; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager; import android.media.MediaRouter; import android.media.MediaRouter; import android.media.MediaRouter.RouteInfo; import android.media.MediaRouter.RouteInfo; Loading Loading @@ -127,7 +127,7 @@ public class KeyguardDisplayManager { Presentation presentation = mPresentations.get(displayId); Presentation presentation = mPresentations.get(displayId); if (presentation == null) { if (presentation == null) { final Presentation newPresentation = new KeyguardPresentation(mContext, display, final Presentation newPresentation = new KeyguardPresentation(mContext, display, mKeyguardStatusViewComponentFactory, LayoutInflater.from(mContext)); mKeyguardStatusViewComponentFactory); newPresentation.setOnDismissListener(dialog -> { newPresentation.setOnDismissListener(dialog -> { if (newPresentation.equals(mPresentations.get(displayId))) { if (newPresentation.equals(mPresentations.get(displayId))) { mPresentations.remove(displayId); mPresentations.remove(displayId); Loading Loading @@ -245,7 +245,6 @@ public class KeyguardDisplayManager { private static final int VIDEO_SAFE_REGION = 80; // Percentage of display width & height private static final int VIDEO_SAFE_REGION = 80; // Percentage of display width & height private static final int MOVE_CLOCK_TIMEOUT = 10000; // 10s private static final int MOVE_CLOCK_TIMEOUT = 10000; // 10s private final KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory; private final KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory; private final LayoutInflater mLayoutInflater; private KeyguardClockSwitchController mKeyguardClockSwitchController; private KeyguardClockSwitchController mKeyguardClockSwitchController; private View mClock; private View mClock; private int mUsableWidth; private int mUsableWidth; Loading @@ -264,18 +263,16 @@ public class KeyguardDisplayManager { }; }; KeyguardPresentation(Context context, Display display, KeyguardPresentation(Context context, Display display, KeyguardStatusViewComponent.Factory keyguardStatusViewComponentFactory, KeyguardStatusViewComponent.Factory keyguardStatusViewComponentFactory) { LayoutInflater layoutInflater) { super(context, display, R.style.Theme_SystemUI_KeyguardPresentation, super(context, display, R.style.Theme_SystemUI_KeyguardPresentation); WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); mKeyguardStatusViewComponentFactory = keyguardStatusViewComponentFactory; mKeyguardStatusViewComponentFactory = keyguardStatusViewComponentFactory; mLayoutInflater = layoutInflater; getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); setCancelable(false); setCancelable(false); } } @Override @Override public void cancel() { public void cancel() { // Do not allow anything to cancel KeyguardPresetation except KeyguardDisplayManager. // Do not allow anything to cancel KeyguardPresentation except KeyguardDisplayManager. } } @Override @Override Loading @@ -287,14 +284,15 @@ public class KeyguardDisplayManager { protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.onCreate(savedInstanceState); Point p = new Point(); final Rect bounds = getWindow().getWindowManager().getMaximumWindowMetrics() getDisplay().getSize(p); .getBounds(); mUsableWidth = VIDEO_SAFE_REGION * p.x/100; mUsableWidth = VIDEO_SAFE_REGION * bounds.width() / 100; mUsableHeight = VIDEO_SAFE_REGION * p.y/100; mUsableHeight = VIDEO_SAFE_REGION * bounds.height() / 100; mMarginLeft = (100 - VIDEO_SAFE_REGION) * p.x / 200; mMarginLeft = (100 - VIDEO_SAFE_REGION) * bounds.width() / 200; mMarginTop = (100 - VIDEO_SAFE_REGION) * p.y / 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 // Logic to make the lock screen fullscreen getWindow().getDecorView().setSystemUiVisibility( getWindow().getDecorView().setSystemUiVisibility( Loading packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java +6 −3 Original line number Original line Diff line number Diff line Loading @@ -20,9 +20,11 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; import static org.mockito.Mockito.when; import android.content.Context; import android.content.Context; import android.hardware.display.DisplayManager; import android.testing.AndroidTestingRunner; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper; import android.util.AttributeSet; import android.util.AttributeSet; import android.view.Display; import android.view.LayoutInflater; import android.view.LayoutInflater; import android.view.View; import android.view.View; Loading Loading @@ -104,9 +106,10 @@ public class KeyguardPresentationTest extends SysuiTestCase { @Test @Test public void testInflation_doesntCrash() { public void testInflation_doesntCrash() { KeyguardPresentation keyguardPresentation = new KeyguardPresentation(mContext, final Display display = mContext.getSystemService(DisplayManager.class).getDisplay( mContext.getDisplayNoVerify(), mKeyguardStatusViewComponentFactory, Display.DEFAULT_DISPLAY); mLayoutInflater); KeyguardPresentation keyguardPresentation = new KeyguardPresentation(mContext, display, mKeyguardStatusViewComponentFactory); keyguardPresentation.onCreate(null /*savedInstanceState */); keyguardPresentation.onCreate(null /*savedInstanceState */); } } } } Loading
core/java/android/app/Presentation.java +59 −81 Original line number Original line Diff line number Diff line Loading @@ -16,30 +16,28 @@ package android.app; package android.app; import static android.content.Context.DISPLAY_SERVICE; import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE; import static android.content.Context.WINDOW_SERVICE; import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION; import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION; import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION; import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION; import android.annotation.NonNull; import android.compat.annotation.UnsupportedAppUsage; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.content.Context; import android.content.res.Resources; import android.content.res.Resources; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager.DisplayListener; import android.hardware.display.DisplayManager.DisplayListener; import android.os.Binder; import android.os.Build; import android.os.Handler; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.util.DisplayMetrics; import android.util.Log; import android.util.TypedValue; import android.util.TypedValue; import android.view.ContextThemeWrapper; import android.view.ContextThemeWrapper; import android.view.Display; import android.view.Display; import android.view.Gravity; import android.view.Gravity; import android.view.Window; import android.view.Window; import android.view.WindowManager; import android.view.WindowManager; import android.view.WindowManagerImpl; import android.view.WindowManager.LayoutParams.WindowType; import com.android.internal.util.Preconditions; /** /** * Base class for presentations. * Base class for presentations. * <p> * <p> Loading Loading @@ -153,11 +151,10 @@ import android.view.WindowManagerImpl; public class Presentation extends Dialog { public class Presentation extends Dialog { private static final String TAG = "Presentation"; private static final String TAG = "Presentation"; private static final int MSG_CANCEL = 1; private final Display mDisplay; private final Display mDisplay; private final DisplayManager mDisplayManager; 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 * Creates a new presentation that is attached to the specified display Loading @@ -179,6 +176,11 @@ public class Presentation extends Dialog { * @param outerContext The context of the application that is showing 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 * The presentation will create its own context (see {@link #getContext()}) based * on this context and information about the associated display. * 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 display The display to which the presentation should be attached. * @param theme A style resource describing the theme to use for the window. * @param theme A style resource describing the theme to use for the window. * See <a href="{@docRoot}guide/topics/resources/available-resources.html#stylesandthemes"> * See <a href="{@docRoot}guide/topics/resources/available-resources.html#stylesandthemes"> Loading @@ -187,24 +189,53 @@ public class Presentation extends Dialog { * <var>outerContext</var>. If 0, the default presentation theme will be used. * <var>outerContext</var>. If 0, the default presentation theme will be used. */ */ public Presentation(Context outerContext, Display display, int theme) { public Presentation(Context outerContext, Display display, int theme) { super(createPresentationContext(outerContext, display, theme), theme, false); this(outerContext, display, theme, INVALID_WINDOW_TYPE); } mDisplay = display; /** mDisplayManager = (DisplayManager)getContext().getSystemService(DISPLAY_SERVICE); * 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); final int windowType = mDisplay = display; (display.getFlags() & Display.FLAG_PRIVATE) != 0 ? TYPE_PRIVATE_PRESENTATION mDisplayManager = getContext().getSystemService(DisplayManager.class); : TYPE_PRESENTATION; final Window w = getWindow(); final Window w = getWindow(); final WindowManager.LayoutParams attr = w.getAttributes(); final WindowManager.LayoutParams attr = w.getAttributes(); attr.token = mToken; w.setAttributes(attr); w.setAttributes(attr); w.setGravity(Gravity.FILL); w.setGravity(Gravity.FILL); w.setType(windowType); w.setType(getWindowType(type, display)); setCanceledOnTouchOutside(false); 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. * Gets the {@link Display} that this presentation appears on. * * Loading @@ -229,16 +260,6 @@ public class Presentation extends Dialog { protected void onStart() { protected void onStart() { super.onStart(); super.onStart(); mDisplayManager.registerDisplayListener(mDisplayListener, mHandler); 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 @Override Loading Loading @@ -273,10 +294,6 @@ public class Presentation extends Dialog { * Called by the system when the properties of the {@link Display} to which * Called by the system when the properties of the {@link Display} to which * the presentation is attached have changed. * 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 * @see #getDisplay */ */ public void onDisplayChanged() { public void onDisplayChanged() { Loading @@ -289,28 +306,16 @@ public class Presentation extends Dialog { private void handleDisplayChanged() { private void handleDisplayChanged() { onDisplayChanged(); 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() { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, publicAlternatives = "{@code N/A}") DisplayMetrics dm = new DisplayMetrics(); private static Context createPresentationContext(Context outerContext, Display display, mDisplay.getMetrics(dm); int theme) { return dm.equalsPhysical(getResources().getDisplayMetrics()); return createPresentationContext(outerContext, display, theme, INVALID_WINDOW_TYPE); } } @UnsupportedAppUsage private static Context createPresentationContext( private static Context createPresentationContext( Context outerContext, Display display, int theme) { Context outerContext, Display display, int theme, @WindowType int type) { if (outerContext == null) { if (outerContext == null) { throw new IllegalArgumentException("outerContext must not be null"); throw new IllegalArgumentException("outerContext must not be null"); } } Loading @@ -318,31 +323,15 @@ public class Presentation extends Dialog { throw new IllegalArgumentException("display must not be null"); 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) { if (theme == 0) { TypedValue outValue = new TypedValue(); TypedValue outValue = new TypedValue(); displayContext.getTheme().resolveAttribute( windowContext.getTheme().resolveAttribute( com.android.internal.R.attr.presentationTheme, outValue, true); com.android.internal.R.attr.presentationTheme, outValue, true); theme = outValue.resourceId; theme = outValue.resourceId; } } return new ContextThemeWrapper(windowContext, theme); // 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); } }; } } private final DisplayListener mDisplayListener = new DisplayListener() { private final DisplayListener mDisplayListener = new DisplayListener() { Loading @@ -364,15 +353,4 @@ public class Presentation extends Dialog { } } } } }; }; private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_CANCEL: cancel(); break; } } }; } }
core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java +1 −4 Original line number Original line Diff line number Diff line Loading @@ -362,14 +362,12 @@ public class VirtualDisplayTest extends AndroidTestCase { private final class TestPresentation extends Presentation { private final class TestPresentation extends Presentation { private final int mColor; private final int mColor; private final int mWindowType; private final int mWindowFlags; private final int mWindowFlags; public TestPresentation(Context context, Display display, public TestPresentation(Context context, Display display, int color, int windowType, int windowFlags) { int color, int windowType, int windowFlags) { super(context, display); super(context, display, 0 /* theme */, windowType); mColor = color; mColor = color; mWindowType = windowType; mWindowFlags = windowFlags; mWindowFlags = windowFlags; } } Loading @@ -378,7 +376,6 @@ public class VirtualDisplayTest extends AndroidTestCase { super.onCreate(savedInstanceState); super.onCreate(savedInstanceState); setTitle(TAG); setTitle(TAG); getWindow().setType(mWindowType); getWindow().addFlags(mWindowFlags); getWindow().addFlags(mWindowFlags); // Create a solid color image to use as the content of the presentation. // Create a solid color image to use as the content of the presentation. Loading
packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java +14 −16 Original line number Original line Diff line number Diff line Loading @@ -20,7 +20,7 @@ import static android.view.Display.DEFAULT_DISPLAY; import android.app.Presentation; import android.app.Presentation; import android.content.Context; import android.content.Context; import android.graphics.Color; import android.graphics.Color; import android.graphics.Point; import android.graphics.Rect; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager; import android.media.MediaRouter; import android.media.MediaRouter; import android.media.MediaRouter.RouteInfo; import android.media.MediaRouter.RouteInfo; Loading Loading @@ -127,7 +127,7 @@ public class KeyguardDisplayManager { Presentation presentation = mPresentations.get(displayId); Presentation presentation = mPresentations.get(displayId); if (presentation == null) { if (presentation == null) { final Presentation newPresentation = new KeyguardPresentation(mContext, display, final Presentation newPresentation = new KeyguardPresentation(mContext, display, mKeyguardStatusViewComponentFactory, LayoutInflater.from(mContext)); mKeyguardStatusViewComponentFactory); newPresentation.setOnDismissListener(dialog -> { newPresentation.setOnDismissListener(dialog -> { if (newPresentation.equals(mPresentations.get(displayId))) { if (newPresentation.equals(mPresentations.get(displayId))) { mPresentations.remove(displayId); mPresentations.remove(displayId); Loading Loading @@ -245,7 +245,6 @@ public class KeyguardDisplayManager { private static final int VIDEO_SAFE_REGION = 80; // Percentage of display width & height private static final int VIDEO_SAFE_REGION = 80; // Percentage of display width & height private static final int MOVE_CLOCK_TIMEOUT = 10000; // 10s private static final int MOVE_CLOCK_TIMEOUT = 10000; // 10s private final KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory; private final KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory; private final LayoutInflater mLayoutInflater; private KeyguardClockSwitchController mKeyguardClockSwitchController; private KeyguardClockSwitchController mKeyguardClockSwitchController; private View mClock; private View mClock; private int mUsableWidth; private int mUsableWidth; Loading @@ -264,18 +263,16 @@ public class KeyguardDisplayManager { }; }; KeyguardPresentation(Context context, Display display, KeyguardPresentation(Context context, Display display, KeyguardStatusViewComponent.Factory keyguardStatusViewComponentFactory, KeyguardStatusViewComponent.Factory keyguardStatusViewComponentFactory) { LayoutInflater layoutInflater) { super(context, display, R.style.Theme_SystemUI_KeyguardPresentation, super(context, display, R.style.Theme_SystemUI_KeyguardPresentation); WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); mKeyguardStatusViewComponentFactory = keyguardStatusViewComponentFactory; mKeyguardStatusViewComponentFactory = keyguardStatusViewComponentFactory; mLayoutInflater = layoutInflater; getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); setCancelable(false); setCancelable(false); } } @Override @Override public void cancel() { public void cancel() { // Do not allow anything to cancel KeyguardPresetation except KeyguardDisplayManager. // Do not allow anything to cancel KeyguardPresentation except KeyguardDisplayManager. } } @Override @Override Loading @@ -287,14 +284,15 @@ public class KeyguardDisplayManager { protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); super.onCreate(savedInstanceState); Point p = new Point(); final Rect bounds = getWindow().getWindowManager().getMaximumWindowMetrics() getDisplay().getSize(p); .getBounds(); mUsableWidth = VIDEO_SAFE_REGION * p.x/100; mUsableWidth = VIDEO_SAFE_REGION * bounds.width() / 100; mUsableHeight = VIDEO_SAFE_REGION * p.y/100; mUsableHeight = VIDEO_SAFE_REGION * bounds.height() / 100; mMarginLeft = (100 - VIDEO_SAFE_REGION) * p.x / 200; mMarginLeft = (100 - VIDEO_SAFE_REGION) * bounds.width() / 200; mMarginTop = (100 - VIDEO_SAFE_REGION) * p.y / 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 // Logic to make the lock screen fullscreen getWindow().getDecorView().setSystemUiVisibility( getWindow().getDecorView().setSystemUiVisibility( Loading
packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java +6 −3 Original line number Original line Diff line number Diff line Loading @@ -20,9 +20,11 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; import static org.mockito.Mockito.when; import android.content.Context; import android.content.Context; import android.hardware.display.DisplayManager; import android.testing.AndroidTestingRunner; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper; import android.util.AttributeSet; import android.util.AttributeSet; import android.view.Display; import android.view.LayoutInflater; import android.view.LayoutInflater; import android.view.View; import android.view.View; Loading Loading @@ -104,9 +106,10 @@ public class KeyguardPresentationTest extends SysuiTestCase { @Test @Test public void testInflation_doesntCrash() { public void testInflation_doesntCrash() { KeyguardPresentation keyguardPresentation = new KeyguardPresentation(mContext, final Display display = mContext.getSystemService(DisplayManager.class).getDisplay( mContext.getDisplayNoVerify(), mKeyguardStatusViewComponentFactory, Display.DEFAULT_DISPLAY); mLayoutInflater); KeyguardPresentation keyguardPresentation = new KeyguardPresentation(mContext, display, mKeyguardStatusViewComponentFactory); keyguardPresentation.onCreate(null /*savedInstanceState */); keyguardPresentation.onCreate(null /*savedInstanceState */); } } } }