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

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

Merge "Support show KeyguardPresentation on all public displays."

parents a5b5f309 e7903ea9
Loading
Loading
Loading
Loading
+0 −11
Original line number Diff line number Diff line
@@ -265,17 +265,6 @@ interface IActivityManager {
    void getMyMemoryState(out ActivityManager.RunningAppProcessInfo outInfo);
    boolean killProcessesBelowForeground(in String reason);
    UserInfo getCurrentUser();
    /**
     * Informs ActivityManagerService that the keyguard is showing.
     *
     * @param showingKeyguard True if the keyguard is showing, false otherwise.
     * @param showingAod True if AOD is showing, false otherwise.
     * @param secondaryDisplayShowing The displayId of the secondary display on which the keyguard
     *        is showing, or INVALID_DISPLAY if there is no such display. Only meaningful if
     *        showing is true.
     */
    void setLockScreenShown(boolean showingKeyguard, boolean showingAod,
            int secondaryDisplayShowing);
    // This is not public because you need to be very careful in how you
    // manage your activity to make sure it is always the uid you expect.
    int getLaunchedFromUid(in IBinder activityToken);
+5 −5
Original line number Diff line number Diff line
@@ -245,16 +245,16 @@ interface IActivityTaskManager {
    ActivityManager.StackInfo getStackInfo(int windowingMode, int activityType);

    /**
     * Informs ActivityManagerService that the keyguard is showing.
     * Informs ActivityTaskManagerService that the keyguard is showing.
     *
     * @param showingKeyguard True if the keyguard is showing, false otherwise.
     * @param showingAod True if AOD is showing, false otherwise.
     * @param secondaryDisplayShowing The displayId of the secondary display on which the keyguard
     *        is showing, or INVALID_DISPLAY if there is no such display. Only meaningful if
     *        showing is true.
     * @param secondaryDisplaysShowing The displayId's of the secondary displays on which the
     * keyguard is showing, or {@code null} if there is no such display. Only meaningful if showing
     * is {@code true}.
     */
    void setLockScreenShown(boolean showingKeyguard, boolean showingAod,
            int secondaryDisplayShowing);
            in int[] secondaryDisplaysShowing);
    Bundle getAssistContextExtras(int requestType);
    boolean launchAssistIntent(in Intent intent, int requestType, in String hint, int userHandle,
            in Bundle args);
+139 −61
Original line number Diff line number Diff line
@@ -15,54 +15,164 @@
 */
package com.android.keyguard;

import static android.view.Display.INVALID_DISPLAY;
import static android.view.Display.DEFAULT_DISPLAY;

import android.annotation.Nullable;
import android.app.Presentation;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.graphics.Point;
import android.hardware.display.DisplayManager;
import android.media.MediaRouter;
import android.media.MediaRouter.RouteInfo;
import android.os.Bundle;
import android.util.Slog;
import android.util.Log;
import android.util.SparseArray;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;

import java.util.function.BooleanSupplier;

// TODO(multi-display): Support multiple external displays
public class KeyguardDisplayManager {
    protected static final String TAG = "KeyguardDisplayManager";
    private static boolean DEBUG = KeyguardConstants.DEBUG;

    private final ViewMediatorCallback mCallback;

    private final MediaRouter mMediaRouter;
    private final DisplayManager mDisplayService;
    private final Context mContext;

    Presentation mPresentation;
    private boolean mShowing;

    private final SparseArray<Presentation> mPresentations = new SparseArray<>();

    private final DisplayManager.DisplayListener mDisplayListener =
            new DisplayManager.DisplayListener() {

        @Override
        public void onDisplayAdded(int displayId) {
            final Display display = mDisplayService.getDisplay(displayId);
            if (mShowing) {
                notifyIfChanged(() -> showPresentation(display));
            }
        }

        @Override
        public void onDisplayChanged(int displayId) {
            if (displayId == DEFAULT_DISPLAY) return;
            final Display display = mDisplayService.getDisplay(displayId);
            if (display != null && mShowing) {
                final Presentation presentation = mPresentations.get(displayId);
                if (presentation != null && !presentation.getDisplay().equals(display)) {
                    hidePresentation(displayId);
                    showPresentation(display);
                }
            }
        }

        @Override
        public void onDisplayRemoved(int displayId) {
            notifyIfChanged(() -> hidePresentation(displayId));
        }
    };

    public KeyguardDisplayManager(Context context, ViewMediatorCallback callback) {
        mContext = context;
        mCallback = callback;
        mMediaRouter = (MediaRouter) mContext.getSystemService(Context.MEDIA_ROUTER_SERVICE);
        mMediaRouter = mContext.getSystemService(MediaRouter.class);
        mDisplayService = mContext.getSystemService(DisplayManager.class);
        mDisplayService.registerDisplayListener(mDisplayListener, null /* handler */);
    }

    /**
     * @param display The display to show the presentation on.
     * @return {@code true} if a presentation was added.
     *         {@code false} if the presentation cannot be added on that display or the presentation
     *         was already there.
     */
    private boolean showPresentation(Display display) {
        if (display == null || display.getDisplayId() == DEFAULT_DISPLAY) return false;
        if (DEBUG) Log.i(TAG, "Keyguard enabled on display: " + display);
        final int displayId = display.getDisplayId();
        Presentation presentation = mPresentations.get(displayId);
        if (presentation == null) {
            presentation = new KeyguardPresentation(mContext, display);
            presentation.setOnDismissListener(dialog -> {
                if (null != mPresentations.get(displayId)) {
                    mPresentations.remove(displayId);
                }
            });
            try {
                presentation.show();
            } catch (WindowManager.InvalidDisplayException ex) {
                Log.w(TAG, "Invalid display:", ex);
                presentation = null;
            }
            if (presentation != null) {
                mPresentations.append(displayId, presentation);
                return true;
            }
        }
        return false;
    }

    /**
     * @param displayId The id of the display to hide the presentation off.
     * @return {@code true} if the a presentation was removed.
     *         {@code false} if the presentation was not added before.
     */
    private boolean hidePresentation(int displayId) {
        final Presentation presentation = mPresentations.get(displayId);
        if (presentation != null) {
            presentation.dismiss();
            mPresentations.remove(displayId);
            return true;
        }
        return false;
    }

    private void notifyIfChanged(BooleanSupplier updateMethod) {
        if (updateMethod.getAsBoolean()) {
            final int[] displayList = getPresentationDisplayIds();
            mCallback.onSecondaryDisplayShowingChanged(displayList);
        }
    }

    /**
     * @return An array of displayId's on which a {@link KeyguardPresentation} is showing on.
     */
    @Nullable
    private int[] getPresentationDisplayIds() {
        final int size = mPresentations.size();
        if (size == 0) return null;

        final int[] displayIds = new int[size];
        for (int i = mPresentations.size() - 1; i >= 0; i--) {
            final Presentation presentation = mPresentations.valueAt(i);
            if (presentation != null) {
                displayIds[i] = presentation.getDisplay().getDisplayId();
            }
        }
        return displayIds;
    }

    public void show() {
        if (!mShowing) {
            if (DEBUG) Slog.v(TAG, "show");
            if (DEBUG) Log.v(TAG, "show");
            mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY,
                    mMediaRouterCallback, MediaRouter.CALLBACK_FLAG_PASSIVE_DISCOVERY);
            updateDisplays(true);
            notifyIfChanged(() -> updateDisplays(true /* showing */));
        }
        mShowing = true;
    }

    public void hide() {
        if (mShowing) {
            if (DEBUG) Slog.v(TAG, "hide");
            if (DEBUG) Log.v(TAG, "hide");
            mMediaRouter.removeCallback(mMediaRouterCallback);
            updateDisplays(false);
            notifyIfChanged(() -> updateDisplays(false /* showing */));
        }
        mShowing = false;
    }
@@ -71,71 +181,38 @@ public class KeyguardDisplayManager {
            new MediaRouter.SimpleCallback() {
        @Override
        public void onRouteSelected(MediaRouter router, int type, RouteInfo info) {
            if (DEBUG) Slog.d(TAG, "onRouteSelected: type=" + type + ", info=" + info);
            updateDisplays(mShowing);
            if (DEBUG) Log.d(TAG, "onRouteSelected: type=" + type + ", info=" + info);
            notifyIfChanged(() -> updateDisplays(mShowing));
        }

        @Override
        public void onRouteUnselected(MediaRouter router, int type, RouteInfo info) {
            if (DEBUG) Slog.d(TAG, "onRouteUnselected: type=" + type + ", info=" + info);
            updateDisplays(mShowing);
            if (DEBUG) Log.d(TAG, "onRouteUnselected: type=" + type + ", info=" + info);
            notifyIfChanged(() -> updateDisplays(mShowing));
        }

        @Override
        public void onRoutePresentationDisplayChanged(MediaRouter router, RouteInfo info) {
            if (DEBUG) Slog.d(TAG, "onRoutePresentationDisplayChanged: info=" + info);
            updateDisplays(mShowing);
        }
    };

    private OnDismissListener mOnDismissListener = new OnDismissListener() {

        @Override
        public void onDismiss(DialogInterface dialog) {
            mPresentation = null;
            if (DEBUG) Log.d(TAG, "onRoutePresentationDisplayChanged: info=" + info);
            notifyIfChanged(() -> updateDisplays(mShowing));
        }
    };

    protected void updateDisplays(boolean showing) {
        Presentation originalPresentation = mPresentation;
    protected boolean updateDisplays(boolean showing) {
        boolean changed = false;
        if (showing) {
            MediaRouter.RouteInfo route = mMediaRouter.getSelectedRoute(
                    MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY);
            boolean useDisplay = route != null
                    && route.getPlaybackType() == MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE;
            Display presentationDisplay = useDisplay ? route.getPresentationDisplay() : null;

            if (mPresentation != null && mPresentation.getDisplay() != presentationDisplay) {
                if (DEBUG) Slog.v(TAG, "Display gone: " + mPresentation.getDisplay());
                mPresentation.dismiss();
                mPresentation = null;
            }

            if (mPresentation == null && presentationDisplay != null) {
                if (DEBUG) Slog.i(TAG, "Keyguard enabled on display: " + presentationDisplay);
                mPresentation = new KeyguardPresentation(mContext, presentationDisplay,
                        R.style.keyguard_presentation_theme);
                mPresentation.setOnDismissListener(mOnDismissListener);
                try {
                    mPresentation.show();
                } catch (WindowManager.InvalidDisplayException ex) {
                    Slog.w(TAG, "Invalid display:", ex);
                    mPresentation = null;
                }
            final Display[] displays = mDisplayService.getDisplays();
            for (Display display : displays) {
                changed |= showPresentation(display);
            }
        } else {
            if (mPresentation != null) {
                mPresentation.dismiss();
                mPresentation = null;
            }
            changed = mPresentations.size() > 0;
            for (int i = mPresentations.size() - 1; i >= 0; i--) {
                mPresentations.valueAt(i).dismiss();
            }

        // mPresentation is only updated when the display changes
        if (mPresentation != originalPresentation) {
            final int displayId = mPresentation != null
                    ? mPresentation.getDisplay().getDisplayId() : INVALID_DISPLAY;
            mCallback.onSecondaryDisplayShowingChanged(displayId);
            mPresentations.clear();
        }
        return changed;
    }

    private final static class KeyguardPresentation extends Presentation {
@@ -157,9 +234,10 @@ public class KeyguardDisplayManager {
            }
        };

        public KeyguardPresentation(Context context, Display display, int theme) {
            super(context, display, theme);
        KeyguardPresentation(Context context, Display display) {
            super(context, display, R.style.keyguard_presentation_theme);
            getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
            setCancelable(false);
        }

        @Override
+8 −1
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
package com.android.keyguard;

import static android.app.slice.Slice.HINT_LIST_ITEM;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;

import android.animation.LayoutTransition;
import android.animation.ObjectAnimator;
@@ -80,6 +82,7 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe
    private float mDarkAmount = 0;

    private LiveData<Slice> mLiveData;
    private int mDisplayId = INVALID_DISPLAY;
    private int mIconSize;
    /**
     * Runnable called whenever the view contents change.
@@ -129,6 +132,7 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();

        mDisplayId = getDisplay().getDisplayId();
        // Make sure we always have the most current slice
        mLiveData.observeForever(this);
        Dependency.get(ConfigurationController.class).addCallback(this);
@@ -138,7 +142,10 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();

        // TODO(b/117344873) Remove below work around after this issue be fixed.
        if (mDisplayId == DEFAULT_DISPLAY) {
            mLiveData.removeObserver(this);
        }
        Dependency.get(ConfigurationController.class).removeCallback(this);
    }

+2 −2
Original line number Diff line number Diff line
@@ -96,9 +96,9 @@ public interface ViewMediatorCallback {
    int getBouncerPromptReason();

    /**
     * Invoked when the secondary display showing a keyguard window changes.
     * Invoked when the secondary displays showing a keyguard window changes.
     */
    void onSecondaryDisplayShowingChanged(int displayId);
    void onSecondaryDisplayShowingChanged(int[] displayId);

    /**
     * Consumes a message that was enqueued to be displayed on the next time the bouncer shows up.
Loading