Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab52125c authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Migrate Presentation to WindowContext"

parents 45eb4c11 f3aefb28
Loading
Loading
Loading
Loading
+59 −81
Original line number Original line Diff line number Diff line
@@ -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>
@@ -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
@@ -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">
@@ -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.
     *
     *
@@ -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
@@ -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() {
@@ -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");
        }
        }
@@ -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() {
@@ -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;
            }
        }
    };
}
}
+1 −4
Original line number Original line Diff line number Diff line
@@ -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;
        }
        }


@@ -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.
+14 −16
Original line number Original line Diff line number Diff line
@@ -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;
@@ -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);
@@ -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;
@@ -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
@@ -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(
+6 −3
Original line number Original line Diff line number Diff line
@@ -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;


@@ -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 */);
    }
    }
}
}