From e7903ea985debe04a34a542fa1b322bc15b485a0 Mon Sep 17 00:00:00 2001 From: wilsonshih Date: Wed, 26 Sep 2018 16:17:59 +0800 Subject: [PATCH] Support show KeyguardPresentation on all public displays. Support show keyguard presentation on all public displays when Keyguard is show. Modify API ActivityTaskManager#setLockScreenShown, extends to multi-displayIds. bug: 111955725 Test: Manual test with chromecast. Test: atest SystemUITests Test: atest ActivityManagerMultiDisplayTests Test: atest ActivityManagerDisplayKeyguardTests Change-Id: I9967e1b1adcb796593332b46853a10101e206013 --- core/java/android/app/IActivityManager.aidl | 11 - .../android/app/IActivityTaskManager.aidl | 10 +- .../keyguard/KeyguardDisplayManager.java | 200 ++++++++++++------ .../android/keyguard/KeyguardSliceView.java | 9 +- .../keyguard/ViewMediatorCallback.java | 4 +- .../keyguard/KeyguardViewMediator.java | 34 +-- .../server/am/ActivityManagerService.java | 17 +- .../keyguard/KeyguardServiceDelegate.java | 8 +- .../server/wm/ActivityTaskManagerService.java | 14 +- .../android/server/wm/KeyguardController.java | 52 +++-- 10 files changed, 221 insertions(+), 138 deletions(-) diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index 519a2749e5bb0..e7597620e138a 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -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); diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl index fcfcc2192d9e2..6f11a762c6cdf 100644 --- a/core/java/android/app/IActivityTaskManager.aidl +++ b/core/java/android/app/IActivityTaskManager.aidl @@ -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); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java index 2bc0e45c725d7..e051317b96b6f 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java @@ -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 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); + if (DEBUG) Log.d(TAG, "onRoutePresentationDisplayChanged: info=" + info); + notifyIfChanged(() -> updateDisplays(mShowing)); } }; - private OnDismissListener mOnDismissListener = new OnDismissListener() { - - @Override - public void onDismiss(DialogInterface dialog) { - mPresentation = null; - } - }; - - 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(); } + mPresentations.clear(); } - - // mPresentation is only updated when the display changes - if (mPresentation != originalPresentation) { - final int displayId = mPresentation != null - ? mPresentation.getDisplay().getDisplayId() : INVALID_DISPLAY; - mCallback.onSecondaryDisplayShowingChanged(displayId); - } + 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 diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java index 50b98a10b7f0f..79966f78373c7 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java @@ -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 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(); - mLiveData.removeObserver(this); + // 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); } diff --git a/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java b/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java index 41b86a7450a3b..a07c5cbde956f 100644 --- a/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java +++ b/packages/SystemUI/src/com/android/keyguard/ViewMediatorCallback.java @@ -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. diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 4988f07ca3f3a..fe1b35609ae50 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -17,7 +17,6 @@ package com.android.systemui.keyguard; import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT; -import static android.view.Display.INVALID_DISPLAY; import static com.android.internal.telephony.IccCardConstants.State.ABSENT; import static com.android.internal.telephony.IccCardConstants.State.PIN_REQUIRED; @@ -95,6 +94,7 @@ import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; /** * Mediates requests related to the keyguard. This includes queries about the @@ -246,8 +246,8 @@ public class KeyguardViewMediator extends SystemUI { // AOD is enabled and status bar is in AOD state. private boolean mAodShowing; - // display id of the secondary display on which we have put a keyguard window - private int mSecondaryDisplayShowing = INVALID_DISPLAY; + // display ids of the external display on which we have put a keyguard window + private int[] mSecondaryDisplaysShowing; /** Cached value of #isInputRestricted */ private boolean mInputRestricted; @@ -700,9 +700,9 @@ public class KeyguardViewMediator extends SystemUI { } @Override - public void onSecondaryDisplayShowingChanged(int displayId) { + public void onSecondaryDisplayShowingChanged(int[] displayIds) { synchronized (KeyguardViewMediator.this) { - setShowingLocked(mShowing, mAodShowing, displayId, false); + setShowingLocked(mShowing, mAodShowing, displayIds, false); } } }; @@ -749,10 +749,10 @@ public class KeyguardViewMediator extends SystemUI { setShowingLocked(!shouldWaitForProvisioning() && !mLockPatternUtils.isLockScreenDisabled( KeyguardUpdateMonitor.getCurrentUser()), - mAodShowing, mSecondaryDisplayShowing, true /* forceCallbacks */); + mAodShowing, mSecondaryDisplaysShowing, true /* forceCallbacks */); } else { // The system's keyguard is disabled or missing. - setShowingLocked(false, mAodShowing, mSecondaryDisplayShowing, true); + setShowingLocked(false, mAodShowing, mSecondaryDisplaysShowing, true); } mStatusBarKeyguardViewManager = @@ -1776,11 +1776,11 @@ public class KeyguardViewMediator extends SystemUI { } private void updateActivityLockScreenState(boolean showing, boolean aodShowing, - int secondaryDisplayShowing) { + int[] secondaryDisplaysShowing) { mUiOffloadThread.submit(() -> { try { ActivityTaskManager.getService().setLockScreenShown(showing, aodShowing, - secondaryDisplayShowing); + secondaryDisplaysShowing); } catch (RemoteException e) { } }); @@ -1895,7 +1895,8 @@ public class KeyguardViewMediator extends SystemUI { if (!mHiding) { // Tell ActivityManager that we canceled the keyguardExitAnimation. - setShowingLocked(mShowing, mAodShowing, mSecondaryDisplayShowing, true /* force */); + setShowingLocked(mShowing, mAodShowing, mSecondaryDisplaysShowing, + true /* force */); return; } mHiding = false; @@ -2164,22 +2165,23 @@ public class KeyguardViewMediator extends SystemUI { } private void setShowingLocked(boolean showing, boolean aodShowing) { - setShowingLocked(showing, aodShowing, mSecondaryDisplayShowing, + setShowingLocked(showing, aodShowing, mSecondaryDisplaysShowing, false /* forceCallbacks */); } - private void setShowingLocked(boolean showing, boolean aodShowing, int secondaryDisplayShowing, - boolean forceCallbacks) { + private void setShowingLocked(boolean showing, boolean aodShowing, + int[] secondaryDisplaysShowing, boolean forceCallbacks) { final boolean notifyDefaultDisplayCallbacks = showing != mShowing || aodShowing != mAodShowing || forceCallbacks; - if (notifyDefaultDisplayCallbacks || secondaryDisplayShowing != mSecondaryDisplayShowing) { + if (notifyDefaultDisplayCallbacks + || !Arrays.equals(secondaryDisplaysShowing, mSecondaryDisplaysShowing)) { mShowing = showing; mAodShowing = aodShowing; - mSecondaryDisplayShowing = secondaryDisplayShowing; + mSecondaryDisplaysShowing = secondaryDisplaysShowing; if (notifyDefaultDisplayCallbacks) { notifyDefaultDisplayCallbacks(showing); } - updateActivityLockScreenState(showing, aodShowing, secondaryDisplayShowing); + updateActivityLockScreenState(showing, aodShowing, secondaryDisplaysShowing); } } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index d631fa87c11e2..45f41e0d26915 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -127,6 +127,11 @@ import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SERVICE; import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_UID_OBSERVERS; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; +import static com.android.server.am.MemoryStatUtil.MEMORY_STAT_INTERESTING_NATIVE_PROCESSES; +import static com.android.server.am.MemoryStatUtil.hasMemcg; +import static com.android.server.am.MemoryStatUtil.readCmdlineFromProcfs; +import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem; +import static com.android.server.am.MemoryStatUtil.readMemoryStatFromProcfs; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION; import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH; @@ -144,11 +149,6 @@ import static com.android.server.wm.ActivityTaskManagerService.DUMP_STARTER_CMD; import static com.android.server.wm.ActivityTaskManagerService.KEY_DISPATCHING_TIMEOUT_MS; import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE; import static com.android.server.wm.ActivityTaskManagerService.relaunchReasonToString; -import static com.android.server.am.MemoryStatUtil.MEMORY_STAT_INTERESTING_NATIVE_PROCESSES; -import static com.android.server.am.MemoryStatUtil.hasMemcg; -import static com.android.server.am.MemoryStatUtil.readCmdlineFromProcfs; -import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem; -import static com.android.server.am.MemoryStatUtil.readMemoryStatFromProcfs; import android.Manifest; import android.Manifest.permission; @@ -7319,13 +7319,6 @@ public class ActivityManagerService extends IActivityManager.Stub return timedout; } - @Override - public void setLockScreenShown(boolean keyguardShowing, boolean aodShowing, - int secondaryDisplayShowing) { - mActivityTaskManager.setLockScreenShown( - keyguardShowing, aodShowing, secondaryDisplayShowing); - } - @Override public void notifyLockedProfile(@UserIdInt int userId) { mAtmInternal.notifyLockedProfile(userId, mUserController.getCurrentUserId()); diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java index 1e0b52adb2f4b..ae1090cfb0452 100644 --- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java +++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java @@ -1,13 +1,11 @@ package com.android.server.policy.keyguard; -import static android.view.Display.INVALID_DISPLAY; import static com.android.server.wm.KeyguardServiceDelegateProto.INTERACTIVE_STATE; import static com.android.server.wm.KeyguardServiceDelegateProto.OCCLUDED; import static com.android.server.wm.KeyguardServiceDelegateProto.SCREEN_STATE; import static com.android.server.wm.KeyguardServiceDelegateProto.SECURE; import static com.android.server.wm.KeyguardServiceDelegateProto.SHOWING; -import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.content.ComponentName; import android.content.Context; @@ -212,10 +210,10 @@ public class KeyguardServiceDelegate { mHandler.post(() -> { try { // There are no longer any keyguard windows on secondary displays, so pass - // INVALID_DISPLAY. All that means is that showWhenLocked activities on - // secondary displays now get to show. + // {@code null}. All that means is that showWhenLocked activities on + // external displays now get to show. ActivityTaskManager.getService().setLockScreenShown(true /* keyguardShowing */, - false /* aodShowing */, INVALID_DISPLAY); + false /* aodShowing */, null /* secondaryDisplaysShowing */); } catch (RemoteException e) { // Local call. } diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 3ede8bc818e08..3359eac880c7d 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -114,17 +114,17 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SWITC import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; -import static com.android.server.wm.ActivityTaskManagerService.H.REPORT_TIME_TRACKER_MSG; -import static com.android.server.wm.ActivityTaskManagerService.UiHandler.DISMISS_DIALOG_UI_MSG; -import static com.android.server.wm.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK; -import static com.android.server.wm.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT; -import static com.android.server.wm.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE; import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT; import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_DATA; import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_RECEIVER_EXTRAS; import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE; +import static com.android.server.wm.ActivityTaskManagerService.H.REPORT_TIME_TRACKER_MSG; +import static com.android.server.wm.ActivityTaskManagerService.UiHandler.DISMISS_DIALOG_UI_MSG; import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE; import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION; +import static com.android.server.wm.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK; +import static com.android.server.wm.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT; +import static com.android.server.wm.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE; import android.Manifest; import android.annotation.NonNull; @@ -2885,7 +2885,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @Override public void setLockScreenShown(boolean keyguardShowing, boolean aodShowing, - int secondaryDisplayShowing) { + int[] secondaryDisplaysShowing) { if (checkCallingPermission(android.Manifest.permission.DEVICE_POWER) != PackageManager.PERMISSION_GRANTED) { throw new SecurityException("Requires permission " @@ -2903,7 +2903,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } try { mKeyguardController.setKeyguardShown(keyguardShowing, aodShowing, - secondaryDisplayShowing); + secondaryDisplaysShowing); } finally { Binder.restoreCallingIdentity(ident); } diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java index 3560635ced098..c91af73dc6ddb 100644 --- a/services/core/java/com/android/server/wm/KeyguardController.java +++ b/services/core/java/com/android/server/wm/KeyguardController.java @@ -18,7 +18,6 @@ package com.android.server.wm; import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import static android.view.Display.DEFAULT_DISPLAY; -import static android.view.Display.INVALID_DISPLAY; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE; import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER; @@ -30,13 +29,13 @@ import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE; import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER; -import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS; -import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; -import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.KeyguardControllerProto.KEYGUARD_OCCLUDED_STATES; import static com.android.server.am.KeyguardControllerProto.KEYGUARD_SHOWING; import static com.android.server.am.KeyguardOccludedProto.DISPLAY_ID; import static com.android.server.am.KeyguardOccludedProto.KEYGUARD_OCCLUDED; +import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS; +import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; +import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; import android.os.IBinder; import android.os.RemoteException; @@ -50,6 +49,7 @@ import com.android.server.policy.WindowManagerPolicy; import com.android.server.wm.ActivityTaskManagerInternal.SleepToken; import java.io.PrintWriter; +import java.util.Arrays; /** * Controls Keyguard occluding, dismissing and transitions depending on what kind of activities are @@ -67,10 +67,9 @@ class KeyguardController { private boolean mAodShowing; private boolean mKeyguardGoingAway; private boolean mDismissalRequested; + private int[] mSecondaryDisplayIdsShowing; private int mBeforeUnoccludeTransit; private int mVisibilityTransactionDepth; - // TODO(b/111955725): Support multiple external displays - private int mSecondaryDisplayShowing = INVALID_DISPLAY; private final SparseArray mDisplayStates = new SparseArray<>(); private final ActivityTaskManagerService mService; @@ -90,7 +89,9 @@ class KeyguardController { */ boolean isKeyguardOrAodShowing(int displayId) { return (mKeyguardShowing || mAodShowing) && !mKeyguardGoingAway - && !isDisplayOccluded(displayId); + && (displayId == DEFAULT_DISPLAY + ? !isDisplayOccluded(DEFAULT_DISPLAY) + : isShowingOnSecondaryDisplay(displayId)); } /** @@ -98,7 +99,10 @@ class KeyguardController { * display, false otherwise */ boolean isKeyguardShowing(int displayId) { - return mKeyguardShowing && !mKeyguardGoingAway && !isDisplayOccluded(displayId); + return mKeyguardShowing && !mKeyguardGoingAway + && (displayId == DEFAULT_DISPLAY + ? !isDisplayOccluded(DEFAULT_DISPLAY) + : isShowingOnSecondaryDisplay(displayId)); } /** @@ -120,16 +124,17 @@ class KeyguardController { * Update the Keyguard showing state. */ void setKeyguardShown(boolean keyguardShowing, boolean aodShowing, - int secondaryDisplayShowing) { + int[] secondaryDisplaysShowing) { boolean showingChanged = keyguardShowing != mKeyguardShowing || aodShowing != mAodShowing; // If keyguard is going away, but SystemUI aborted the transition, need to reset state. showingChanged |= mKeyguardGoingAway && keyguardShowing; - if (!showingChanged && secondaryDisplayShowing == mSecondaryDisplayShowing) { + if (!showingChanged && Arrays.equals(secondaryDisplaysShowing, + mSecondaryDisplayIdsShowing)) { return; } mKeyguardShowing = keyguardShowing; mAodShowing = aodShowing; - mSecondaryDisplayShowing = secondaryDisplayShowing; + mSecondaryDisplayIdsShowing = secondaryDisplaysShowing; mWindowManager.setAodShowing(aodShowing); if (showingChanged) { dismissDockedStackIfNeeded(); @@ -145,6 +150,14 @@ class KeyguardController { updateKeyguardSleepToken(); } + private boolean isShowingOnSecondaryDisplay(int displayId) { + if (mSecondaryDisplayIdsShowing == null) return false; + for (int showingId : mSecondaryDisplayIdsShowing) { + if (displayId == showingId) return true; + } + return false; + } + /** * Called when Keyguard is going away. * @@ -386,16 +399,18 @@ class KeyguardController { } private KeyguardDisplayState getDisplay(int displayId) { - if (mDisplayStates.get(displayId) == null) { - mDisplayStates.append(displayId, - new KeyguardDisplayState(mService, displayId)); + KeyguardDisplayState state = mDisplayStates.get(displayId); + if (state == null) { + state = new KeyguardDisplayState(mService, displayId); + mDisplayStates.append(displayId, state); } - return mDisplayStates.get(displayId); + return state; } void onDisplayRemoved(int displayId) { - if (mDisplayStates.get(displayId) != null) { - mDisplayStates.get(displayId).onRemoved(); + final KeyguardDisplayState state = mDisplayStates.get(displayId); + if (state != null) { + state.onRemoved(); mDisplayStates.remove(displayId); } } @@ -456,7 +471,8 @@ class KeyguardController { mOccluded |= controller.mWindowManager.isShowingDream(); } - // TODO(b/113840485): Handle app transition for individual display. + // TODO(b/113840485): Handle app transition for individual display, and apply occluded + // state change to secondary displays. // For now, only default display can change occluded. if (lastOccluded != mOccluded && mDisplayId == DEFAULT_DISPLAY) { controller.handleOccludedChanged();