diff options
| -rw-r--r-- | api/system-current.txt | 2 | ||||
| -rw-r--r-- | api/test-current.txt | 1 | ||||
| -rw-r--r-- | core/java/android/app/Activity.java | 27 | ||||
| -rw-r--r-- | core/java/android/app/IActivityTaskManager.aidl | 1 | ||||
| -rw-r--r-- | core/java/android/content/pm/ActivityInfo.java | 22 | ||||
| -rw-r--r-- | core/java/android/content/pm/PackageParser.java | 4 | ||||
| -rw-r--r-- | core/res/res/values/attrs_manifest.xml | 15 | ||||
| -rw-r--r-- | core/res/res/values/public.xml | 2 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/ActivityRecord.java | 51 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/ActivityStack.java | 7 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/ActivityTaskManagerService.java | 16 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/WindowManagerService.java | 22 |
12 files changed, 131 insertions, 39 deletions
diff --git a/api/system-current.txt b/api/system-current.txt index e79ede8dc9b7..76c14186f996 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -197,6 +197,7 @@ package android { } public static final class R.attr { + field public static final int inheritShowWhenLocked = 16844194; // 0x10105a2 field public static final int isVrOnly = 16844152; // 0x1010578 field public static final int requiredSystemPropertyName = 16844133; // 0x1010565 field public static final int requiredSystemPropertyValue = 16844134; // 0x1010566 @@ -256,6 +257,7 @@ package android.app { method public boolean convertToTranslucent(android.app.Activity.TranslucentConversionListener, android.app.ActivityOptions); method public deprecated boolean isBackgroundVisibleBehind(); method public deprecated void onBackgroundVisibleBehindChanged(boolean); + method public void setInheritShowWhenLocked(boolean); } public static abstract interface Activity.TranslucentConversionListener { diff --git a/api/test-current.txt b/api/test-current.txt index 1401cbb4211e..9ae09ea10c02 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -28,6 +28,7 @@ package android.app { public class Activity extends android.view.ContextThemeWrapper implements android.content.ComponentCallbacks2 android.view.KeyEvent.Callback android.view.LayoutInflater.Factory2 android.view.View.OnCreateContextMenuListener android.view.Window.Callback { method public void onMovedToDisplay(int, android.content.res.Configuration); + method public void setInheritShowWhenLocked(boolean); } public class ActivityManager { diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index 5b8261e38f1e..85656ebe6f8c 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -8282,6 +8282,33 @@ public class Activity extends ContextThemeWrapper } /** + * Specifies whether this {@link Activity} should be shown on top of the lock screen whenever + * the lockscreen is up and this activity has another activity behind it with the showWhenLock + * attribute set. That is, this activity is only visible on the lock screen if there is another + * activity with the showWhenLock attribute visible at the same time on the lock screen. A use + * case for this is permission dialogs, that should only be visible on the lock screen if their + * requesting activity is also visible. This value can be set as a manifest attribute using + * android.R.attr#inheritShowWhenLocked. + * + * @param inheritShowWhenLocked {@code true} to show the {@link Activity} on top of the lock + * screen when this activity has another activity behind it with + * the showWhenLock attribute set; {@code false} otherwise. + * @see #setShowWhenLocked(boolean) + * See android.R.attr#inheritShowWhenLocked + * @hide + */ + @SystemApi + @TestApi + public void setInheritShowWhenLocked(boolean inheritShowWhenLocked) { + try { + ActivityTaskManager.getService().setInheritShowWhenLocked( + mToken, inheritShowWhenLocked); + } catch (RemoteException e) { + Log.e(TAG, "Failed to call setInheritShowWhenLocked", e); + } + } + + /** * Specifies whether the screen should be turned on when the {@link Activity} is resumed. * Normally an activity will be transitioned to the stopped state if it is started while the * screen if off, but with this flag set the activity will cause the screen to turn on if the diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl index dd87dc330b65..cc6c999ed255 100644 --- a/core/java/android/app/IActivityTaskManager.aidl +++ b/core/java/android/app/IActivityTaskManager.aidl @@ -419,6 +419,7 @@ interface IActivityTaskManager { void updateLockTaskFeatures(int userId, int flags); void setShowWhenLocked(in IBinder token, boolean showWhenLocked); + void setInheritShowWhenLocked(in IBinder token, boolean setInheritShownWhenLocked); void setTurnScreenOn(in IBinder token, boolean turnScreenOn); /** diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index 0edb36c5daff..3cfbe0c6f08a 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -505,6 +505,22 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { */ public int flags; + /** + * Bit in {@link #privateFlags} indicating if the activity should be shown when locked in case + * an activity behind this can also be shown when locked. + * See android.R.attr#inheritShowWhenLocked + * @hide + */ + public static final int FLAG_INHERIT_SHOW_WHEN_LOCKED = 0x1; + + /** + * Options that have been set in the activity declaration in the manifest. + * These include: + * {@link #FLAG_INHERIT_SHOW_WHEN_LOCKED}. + * @hide + */ + public int privateFlags; + /** @hide */ @IntDef(prefix = { "SCREEN_ORIENTATION_" }, value = { SCREEN_ORIENTATION_UNSET, @@ -975,6 +991,7 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { taskAffinity = orig.taskAffinity; targetActivity = orig.targetActivity; flags = orig.flags; + privateFlags = orig.privateFlags; screenOrientation = orig.screenOrientation; configChanges = orig.configChanges; softInputMode = orig.softInputMode; @@ -1122,9 +1139,10 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { + " targetActivity=" + targetActivity + " persistableMode=" + persistableModeToString()); } - if (launchMode != 0 || flags != 0 || theme != 0) { + if (launchMode != 0 || flags != 0 || privateFlags != 0 || theme != 0) { pw.println(prefix + "launchMode=" + launchMode + " flags=0x" + Integer.toHexString(flags) + + " privateFlags=0x" + Integer.toHexString(privateFlags) + " theme=0x" + Integer.toHexString(theme)); } if (screenOrientation != SCREEN_ORIENTATION_UNSPECIFIED @@ -1178,6 +1196,7 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { dest.writeString(targetActivity); dest.writeString(launchToken); dest.writeInt(flags); + dest.writeInt(privateFlags); dest.writeInt(screenOrientation); dest.writeInt(configChanges); dest.writeInt(softInputMode); @@ -1307,6 +1326,7 @@ public class ActivityInfo extends ComponentInfo implements Parcelable { targetActivity = source.readString(); launchToken = source.readString(); flags = source.readInt(); + privateFlags = source.readInt(); screenOrientation = source.readInt(); configChanges = source.readInt(); softInputMode = source.readInt(); diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 2b266b730485..29163b7f3c57 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -4546,6 +4546,9 @@ public class PackageParser { a.info.flags |= ActivityInfo.FLAG_TURN_SCREEN_ON; } + if (sa.getBoolean(R.styleable.AndroidManifestActivity_inheritShowWhenLocked, false)) { + a.info.privateFlags |= ActivityInfo.FLAG_INHERIT_SHOW_WHEN_LOCKED; + } } else { a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE; a.info.configChanges = 0; @@ -4925,6 +4928,7 @@ public class PackageParser { info.targetActivity = targetActivity; info.configChanges = target.info.configChanges; info.flags = target.info.flags; + info.privateFlags = target.info.privateFlags; info.icon = target.info.icon; info.logo = target.info.logo; info.banner = target.info.banner; diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 54f6c632907f..18a42bc5ed0b 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -593,7 +593,7 @@ to be set for all windows of this activity --> <attr name="showForAllUsers" format="boolean" /> - <!-- Specifies whether an {@link android.app.Activity} should be shown on top of the the lock screen + <!-- Specifies whether an {@link android.app.Activity} should be shown on top of the lock screen whenever the lockscreen is up and the activity is resumed. Normally an activity will be transitioned to the stopped state if it is started while the lockscreen is up, but with this flag set the activity will remain in the resumed state visible on-top of the lock @@ -2412,6 +2412,19 @@ <attr name="showForAllUsers" /> <attr name="showWhenLocked" /> + <!-- @hide @SystemApi Specifies whether this {@link android.app.Activity} should be shown on + top of the lock screen whenever the lockscreen is up and this activity has another + activity behind it with the {@link android.R.attr#showWhenLocked} attribute set. That + is, this activity is only visible on the lock screen if there is another activity with + the {@link android.R.attr#showWhenLocked} attribute visible at the same time on the + lock screen. A use case for this is permission dialogs, that should only be visible on + the lock screen if their requesting activity is also visible. + + The default value of this attribute is <code>false</code>. --> + <attr name="inheritShowWhenLocked" format="boolean" /> + + + <attr name="inheritShowWhenLocked" /> <attr name="turnScreenOn" /> <attr name="directBootAware" /> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 799d9d858b59..b3b30e992302 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2934,6 +2934,8 @@ <public name="foregroundServiceType" /> <public name="hasFragileUserData" /> <public name="minAspectRatio" /> + <!-- @hide @SystemApi --> + <public name="inheritShowWhenLocked" /> </public-group> <public-group type="drawable" first-id="0x010800b4"> diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 8884615d2fe1..822d3f7975cb 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -54,6 +54,7 @@ import static android.content.pm.ActivityInfo.CONFIG_WINDOW_CONFIGURATION; import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE; import static android.content.pm.ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS; import static android.content.pm.ActivityInfo.FLAG_IMMERSIVE; +import static android.content.pm.ActivityInfo.FLAG_INHERIT_SHOW_WHEN_LOCKED; import static android.content.pm.ActivityInfo.FLAG_MULTIPROCESS; import static android.content.pm.ActivityInfo.FLAG_NO_HISTORY; import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS; @@ -142,6 +143,7 @@ import static org.xmlpull.v1.XmlPullParser.END_TAG; import static org.xmlpull.v1.XmlPullParser.START_TAG; import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.ActivityManager.TaskDescription; import android.app.ActivityOptions; import android.app.PendingIntent; @@ -387,6 +389,7 @@ final class ActivityRecord extends ConfigurationContainer { int mRotationAnimationHint = -1; private boolean mShowWhenLocked; + private boolean mInheritShownWhenLocked; private boolean mTurnScreenOn; /** @@ -996,6 +999,7 @@ final class ActivityRecord extends ConfigurationContainer { null : ComponentName.unflattenFromString(aInfo.requestedVrComponent); mShowWhenLocked = (aInfo.flags & FLAG_SHOW_WHEN_LOCKED) != 0; + mInheritShownWhenLocked = (aInfo.privateFlags & FLAG_INHERIT_SHOW_WHEN_LOCKED) != 0; mTurnScreenOn = (aInfo.flags & FLAG_TURN_SCREEN_ON) != 0; mRotationAnimationHint = aInfo.rotationAnimation; @@ -1481,14 +1485,6 @@ final class ActivityRecord extends ConfigurationContainer { return true; } - /** - * @return true if the activity contains windows that have - * {@link LayoutParams#FLAG_DISMISS_KEYGUARD} set - */ - boolean hasDismissKeyguardWindows() { - return mAtmService.mWindowManager.containsDismissKeyguardWindow(appToken); - } - void makeFinishingLocked() { if (finishing) { return; @@ -3177,16 +3173,45 @@ final class ActivityRecord extends ConfigurationContainer { false /* preserveWindows */); } + void setInheritShowWhenLocked(boolean inheritShowWhenLocked) { + mInheritShownWhenLocked = inheritShowWhenLocked; + mRootActivityContainer.ensureActivitiesVisible(null, 0, false); + } + /** * @return true if the activity windowing mode is not - * {@link android.app.WindowConfiguration#WINDOWING_MODE_PINNED} and activity contains - * windows that have {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set or if the activity - * has set {@link #mShowWhenLocked}. + * {@link android.app.WindowConfiguration#WINDOWING_MODE_PINNED} and a) activity + * contains windows that have {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set or if the + * activity has set {@link #mShowWhenLocked}, or b) if the activity has set + * {@link #mInheritShownWhenLocked} and the activity behind this satisfies the + * conditions a) above. * Multi-windowing mode will be exited if true is returned. */ boolean canShowWhenLocked() { - return !inPinnedWindowingMode() && (mShowWhenLocked - || mAtmService.mWindowManager.containsShowWhenLockedWindow(appToken)); + if (!inPinnedWindowingMode() && (mShowWhenLocked + || (mAppWindowToken != null && mAppWindowToken.containsShowWhenLockedWindow()))) { + return true; + } else if (mInheritShownWhenLocked) { + ActivityRecord r = getActivityBelow(); + return r != null && !r.inPinnedWindowingMode() && (r.mShowWhenLocked + || (r.mAppWindowToken != null + && r.mAppWindowToken.containsShowWhenLockedWindow())); + } else { + return false; + } + } + + /** + * @return an {@link ActivityRecord} of the activity below this activity, or {@code null} if no + * such activity exists. + */ + @Nullable + private ActivityRecord getActivityBelow() { + final int pos = task.mActivities.indexOf(this); + if (pos == -1) { + throw new IllegalStateException("Activity not found in its task"); + } + return pos == 0 ? null : task.getChildAt(pos - 1); } void setTurnScreenOn(boolean turnScreenOn) { diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java index 4581a0f9f350..4d7de9058105 100644 --- a/services/core/java/com/android/server/wm/ActivityStack.java +++ b/services/core/java/com/android/server/wm/ActivityStack.java @@ -2204,7 +2204,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai .isKeyguardOrAodShowing(displayId); final boolean keyguardLocked = mStackSupervisor.getKeyguardController().isKeyguardLocked(); final boolean showWhenLocked = r.canShowWhenLocked(); - final boolean dismissKeyguard = r.hasDismissKeyguardWindows(); + final boolean dismissKeyguard = r.mAppWindowToken != null + && r.mAppWindowToken.containsDismissKeyguardWindow(); if (shouldBeVisible) { if (dismissKeyguard && mTopDismissingKeyguardActivity == null) { mTopDismissingKeyguardActivity = r; @@ -2561,7 +2562,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai final boolean canShowWhenLocked = !mTopActivityOccludesKeyguard && next.canShowWhenLocked(); final boolean mayDismissKeyguard = mTopDismissingKeyguardActivity != next - && next.hasDismissKeyguardWindows(); + && next.mAppWindowToken != null + && next.mAppWindowToken.containsDismissKeyguardWindow(); + if (canShowWhenLocked || mayDismissKeyguard) { ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */, !PRESERVE_WINDOWS); diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index 42121ca08696..99f9973cbbb8 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -4334,6 +4334,22 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } @Override + public void setInheritShowWhenLocked(IBinder token, boolean inheritShowWhenLocked) { + synchronized (mGlobalLock) { + final ActivityRecord r = ActivityRecord.isInStackLocked(token); + if (r == null) { + return; + } + final long origId = Binder.clearCallingIdentity(); + try { + r.setInheritShowWhenLocked(inheritShowWhenLocked); + } finally { + Binder.restoreCallingIdentity(origId); + } + } + } + + @Override public void setTurnScreenOn(IBinder token, boolean turnScreenOn) { synchronized (mGlobalLock) { final ActivityRecord r = ActivityRecord.isInStackLocked(token); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index f5f55e2ebf73..7cfc42f4d651 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2651,28 +2651,6 @@ public class WindowManagerService extends IWindowManager.Stub } /** - * @return true if the activity contains windows that have - * {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set - */ - public boolean containsShowWhenLockedWindow(IBinder token) { - synchronized (mGlobalLock) { - final AppWindowToken wtoken = mRoot.getAppWindowToken(token); - return wtoken != null && wtoken.containsShowWhenLockedWindow(); - } - } - - /** - * @return true if the activity contains windows that have - * {@link LayoutParams#FLAG_DISMISS_KEYGUARD} set - */ - public boolean containsDismissKeyguardWindow(IBinder token) { - synchronized (mGlobalLock) { - final AppWindowToken wtoken = mRoot.getAppWindowToken(token); - return wtoken != null && wtoken.containsDismissKeyguardWindow(); - } - } - - /** * Notifies activity manager that some Keyguard flags have changed and that it needs to * reevaluate the visibilities of the activities. * @param callback Runnable to be called when activity manager is done reevaluating visibilities |