diff options
author | Craig Mautner <cmautner@google.com> | 2012-10-05 14:45:52 -0700 |
---|---|---|
committer | Craig Mautner <cmautner@google.com> | 2012-10-06 13:09:58 -0700 |
commit | 5962b12bedc4a1d0354816c1cd6b06ba04f6d807 (patch) | |
tree | b9918fad07cf0e0ff84d510b6e17b31cf48394f9 | |
parent | 88400d3a31139c40c4014faf86c243647087ef6c (diff) | |
download | frameworks_base-5962b12bedc4a1d0354816c1cd6b06ba04f6d807.zip frameworks_base-5962b12bedc4a1d0354816c1cd6b06ba04f6d807.tar.gz frameworks_base-5962b12bedc4a1d0354816c1cd6b06ba04f6d807.tar.bz2 |
Adds showWhenLocked attribute to Activities.
The new attribute allows an Activity such as the alarm to appear
on all users screens.
Bug: 7213805 fixed.
Change-Id: If7866b13d88c04af07debc69e0e875d0adc6050a
16 files changed, 69 insertions, 23 deletions
@@ -912,6 +912,7 @@ package android { field public static final int showAsAction = 16843481; // 0x10102d9 field public static final int showDefault = 16843258; // 0x10101fa field public static final int showDividers = 16843561; // 0x1010329 + field public static final int showOnLockScreen = 16843721; // 0x10103c9 field public static final int showSilent = 16843259; // 0x10101fb field public static final int showWeekNumber = 16843582; // 0x101033e field public static final int shownWeekCount = 16843585; // 0x1010341 diff --git a/api/current.txt b/api/current.txt index e86de90..d7f7c3c 100644 --- a/api/current.txt +++ b/api/current.txt @@ -912,6 +912,7 @@ package android { field public static final int showAsAction = 16843481; // 0x10102d9 field public static final int showDefault = 16843258; // 0x10101fa field public static final int showDividers = 16843561; // 0x1010329 + field public static final int showOnLockScreen = 16843721; // 0x10103c9 field public static final int showSilent = 16843259; // 0x10101fb field public static final int showWeekNumber = 16843582; // 0x101033e field public static final int shownWeekCount = 16843585; // 0x1010341 diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index b884b98..e2ca1dd 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -155,6 +155,12 @@ public class ActivityInfo extends ComponentInfo */ public static final int FLAG_HARDWARE_ACCELERATED = 0x0200; /** + * Value for {@link #flags}: true when the application can be displayed over the lockscreen + * and consequently over all users' windows. + * @hide + */ + public static final int FLAG_SHOW_ON_LOCK_SCREEN = 0x0400; + /** * @hide * Bit in {@link #flags} corresponding to an immersive activity * that wishes not to be interrupted by notifications. @@ -170,7 +176,7 @@ public class ActivityInfo extends ComponentInfo * "toast" window). * {@see android.app.Notification#FLAG_HIGH_PRIORITY} */ - public static final int FLAG_IMMERSIVE = 0x0400; + public static final int FLAG_IMMERSIVE = 0x0800; /** * @hide Bit in {@link #flags}: If set, this component will only be seen * by the primary user. Only works with broadcast receivers. Set from the diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index c2b75f4..3e8c2a8 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -2160,11 +2160,17 @@ public class PackageParser { } if (sa.getBoolean( + com.android.internal.R.styleable.AndroidManifestActivity_showOnLockScreen, + false)) { + a.info.flags |= ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN; + } + + if (sa.getBoolean( com.android.internal.R.styleable.AndroidManifestActivity_immersive, false)) { a.info.flags |= ActivityInfo.FLAG_IMMERSIVE; } - + if (!receiver) { if (sa.getBoolean( com.android.internal.R.styleable.AndroidManifestActivity_hardwareAccelerated, diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index a64cbf7..97202b4 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -74,7 +74,7 @@ interface IWindowManager void addWindowToken(IBinder token, int type); void removeWindowToken(IBinder token); void addAppToken(int addPos, IApplicationToken token, - int groupId, int requestedOrientation, boolean fullscreen); + int groupId, int requestedOrientation, boolean fullscreen, boolean showWhenLocked); void setAppGroupId(IBinder token, int groupId); void setAppOrientation(IApplicationToken token, int requestedOrientation); int getAppOrientation(IApplicationToken token); diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index eb3f72e..4c97414 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -219,12 +219,14 @@ public interface WindowManager extends ViewManager { * Window type: an application window that serves as the "base" window * of the overall application; all other application windows will * appear on top of it. + * In multiuser systems shows only on the owning user's window. */ public static final int TYPE_BASE_APPLICATION = 1; /** * Window type: a normal application window. The {@link #token} must be * an Activity token identifying who the window belongs to. + * In multiuser systems shows only on the owning user's window. */ public static final int TYPE_APPLICATION = 2; @@ -233,6 +235,7 @@ public interface WindowManager extends ViewManager { * application is starting. Not for use by applications themselves; * this is used by the system to display something until the * application can show its own windows. + * In multiuser systems shows on all users' windows. */ public static final int TYPE_APPLICATION_STARTING = 3; diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 58b6572..d899e9d 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -444,6 +444,10 @@ recently launched activities. --> <attr name="excludeFromRecents" format="boolean" /> + <!-- Specify that an Activity should be shown over the lock screen and, + in a multiuser environment, across all users' windows --> + <attr name="showOnLockScreen" format="boolean" /> + <!-- Specify the authorities under which this content provider can be found. Multiple authorities may be supplied by separating them with a semicolon. Authority names should use a Java-style naming @@ -1376,6 +1380,7 @@ <attr name="alwaysRetainTaskState" /> <attr name="stateNotNeeded" /> <attr name="excludeFromRecents" /> + <attr name="showOnLockScreen" /> <!-- Specify whether the activity is enabled or not (that is, can be instantiated by the system). It can also be specified for an application as a whole, in which case a value of "false" will override any component specific values (a value of "true" will not override the diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index ffc09de..d7a480b 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2018,10 +2018,12 @@ <public type="attr" name="permissionGroupFlags" id="0x010103c5" /> <public type="attr" name="labelFor" id="0x010103c6" /> <public type="attr" name="permissionFlags" id="0x010103c7" /> - <public type="attr" name="checkedTextViewStyle" /> - <public type="style" name="Widget.Holo.CheckedTextView" /> - <public type="style" name="Widget.Holo.Light.CheckedTextView" /> - <public type="style" name="Widget.DeviceDefault.CheckedTextView" /> - <public type="style" name="Widget.DeviceDefault.Light.CheckedTextView" /> + <public type="attr" name="checkedTextViewStyle" id="0x010103c8" /> + <public type="attr" name="showOnLockScreen" id="0x010103c9" /> + + <public type="style" name="Widget.Holo.CheckedTextView" id="0x010301d9" /> + <public type="style" name="Widget.Holo.Light.CheckedTextView" id="0x010301da" /> + <public type="style" name="Widget.DeviceDefault.CheckedTextView" id="0x010301db" /> + <public type="style" name="Widget.DeviceDefault.Light.CheckedTextView" id="0x010301dc" /> </resources> diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 3ef6767..dcdde76 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -7453,6 +7453,7 @@ public final class ActivityManagerService extends ActivityManagerNative lp.format = v.getBackground().getOpacity(); lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; + lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS; ((WindowManager)mContext.getSystemService( Context.WINDOW_SERVICE)).addView(v, lp); } diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index a6dc867..4bcb339 100755 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -420,12 +420,17 @@ final class ActivityStack { mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch"); mLaunchingActivity.setReferenceCounted(false); } - + + private boolean okToShow(ActivityRecord r) { + return r.userId == mCurrentUser + || (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0; + } + final ActivityRecord topRunningActivityLocked(ActivityRecord notTop) { int i = mHistory.size()-1; while (i >= 0) { ActivityRecord r = mHistory.get(i); - if (!r.finishing && r != notTop && r.userId == mCurrentUser) { + if (!r.finishing && r != notTop && okToShow(r)) { return r; } i--; @@ -437,7 +442,7 @@ final class ActivityStack { int i = mHistory.size()-1; while (i >= 0) { ActivityRecord r = mHistory.get(i); - if (!r.finishing && !r.delayedResume && r != notTop && r.userId == mCurrentUser) { + if (!r.finishing && !r.delayedResume && r != notTop && okToShow(r)) { return r; } i--; @@ -460,7 +465,7 @@ final class ActivityStack { ActivityRecord r = mHistory.get(i); // Note: the taskId check depends on real taskId fields being non-zero if (!r.finishing && (token != r.appToken) && (taskId != r.task.taskId) - && r.userId == mCurrentUser) { + && okToShow(r)) { return r; } i--; @@ -1806,7 +1811,8 @@ final class ActivityStack { mHistory.add(addPos, r); r.putInHistory(); mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId, - r.info.screenOrientation, r.fullscreen); + r.info.screenOrientation, r.fullscreen, + (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0); if (VALIDATE_TOKENS) { validateAppTokensLocked(); } @@ -1870,7 +1876,8 @@ final class ActivityStack { } r.updateOptionsLocked(options); mService.mWindowManager.addAppToken( - addPos, r.appToken, r.task.taskId, r.info.screenOrientation, r.fullscreen); + addPos, r.appToken, r.task.taskId, r.info.screenOrientation, r.fullscreen, + (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0); boolean doShow = true; if (newTask) { // Even though this activity is starting fresh, we still need @@ -1908,7 +1915,8 @@ final class ActivityStack { // If this is the first activity, don't do any fancy animations, // because there is nothing for it to animate on top of. mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId, - r.info.screenOrientation, r.fullscreen); + r.info.screenOrientation, r.fullscreen, + (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0); ActivityOptions.abort(options); } if (VALIDATE_TOKENS) { @@ -2616,7 +2624,6 @@ final class ActivityStack { Bundle options) { final Intent intent = r.intent; final int callingUid = r.launchedFromUid; - final int userId = r.userId; int launchFlags = intent.getFlags(); diff --git a/services/java/com/android/server/wm/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java index 13b072c..7efffe5 100644 --- a/services/java/com/android/server/wm/AppWindowToken.java +++ b/services/java/com/android/server/wm/AppWindowToken.java @@ -50,6 +50,7 @@ class AppWindowToken extends WindowToken { int groupId = -1; boolean appFullscreen; int requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; + boolean showWhenLocked; // The input dispatching timeout for this application token in nanoseconds. long inputDispatchingTimeoutNanos; diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index 1b1d85b..e670028 100755 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -3703,7 +3703,7 @@ public class WindowManagerService extends IWindowManager.Stub @Override public void addAppToken(int addPos, IApplicationToken token, - int groupId, int requestedOrientation, boolean fullscreen) { + int groupId, int requestedOrientation, boolean fullscreen, boolean showWhenLocked) { if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, "addAppToken()")) { throw new SecurityException("Requires MANAGE_APP_TOKENS permission"); @@ -3733,6 +3733,7 @@ public class WindowManagerService extends IWindowManager.Stub atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos; atoken.groupId = groupId; atoken.appFullscreen = fullscreen; + atoken.showWhenLocked = showWhenLocked; atoken.requestedOrientation = requestedOrientation; if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken + " at " + addPos); @@ -5411,7 +5412,7 @@ public class WindowManagerService extends IWindowManager.Stub final WindowList windows = iterator.next().getWindowList(); for (int i = 0; i < windows.size(); i++) { final WindowState win = windows.get(i); - if (win.isOtherUsersAppWindow()) { + if (win.isHiddenFromUserLocked()) { Slog.w(TAG, "current user violation " + newUserId + " hiding " + win + ", attrs=" + win.mAttrs.type + ", belonging to " + win.mOwnerUid); diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java index 6e388f2..dee66a6 100644 --- a/services/java/com/android/server/wm/WindowState.java +++ b/services/java/com/android/server/wm/WindowState.java @@ -940,7 +940,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { } boolean showLw(boolean doAnimation, boolean requestAnim) { - if (isOtherUsersAppWindow()) { + if (isHiddenFromUserLocked()) { Slog.w(TAG, "current user violation " + mService.mCurrentUserId + " trying to display " + this + ", type " + mAttrs.type + ", belonging to " + mOwnerUid); return false; @@ -1030,7 +1030,18 @@ final class WindowState implements WindowManagerPolicy.WindowState { mShowToOwnerOnly = showToOwnerOnly; } - boolean isOtherUsersAppWindow() { + boolean isHiddenFromUserLocked() { + // Save some cycles by not calling getDisplayInfo unless it is an application + // window intended for all users. + if (mAttrs.type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW + && mAppToken != null && mAppToken.showWhenLocked) { + final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo(); + if (isFullscreen(displayInfo.appWidth, displayInfo.appHeight)) { + // Is a fullscreen window, like the clock alarm. Show to everyone. + return false; + } + } + return mShowToOwnerOnly && UserHandle.getUserId(mOwnerUid) != mService.mCurrentUserId; } diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java index 817a234..d63fb5a 100644 --- a/services/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/java/com/android/server/wm/WindowStateAnimator.java @@ -1334,7 +1334,7 @@ class WindowStateAnimator { // This must be called while inside a transaction. boolean performShowLocked() { - if (mWin.isOtherUsersAppWindow()) { + if (mWin.isHiddenFromUserLocked()) { Slog.w(TAG, "current user violation " + mService.mCurrentUserId + " trying to display " + this + ", type " + mWin.mAttrs.type + ", belonging to " + mWin.mOwnerUid); return false; diff --git a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java index 1f6279c..746ac06 100644 --- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java +++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java @@ -93,7 +93,7 @@ public class WindowManagerPermissionTests extends TestCase { } try { - mWm.addAppToken(0, null, 0, 0, false); + mWm.addAppToken(0, null, 0, 0, false, false); fail("IWindowManager.addAppToken did not throw SecurityException as" + " expected"); } catch (SecurityException e) { diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java index b8d21f3..ddb0665 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java @@ -78,7 +78,8 @@ public class BridgeWindowManager implements IWindowManager { } @Override - public void addAppToken(int arg0, IApplicationToken arg1, int arg2, int arg3, boolean arg4) + public void addAppToken(int arg0, IApplicationToken arg1, int arg2, int arg3, boolean arg4, + boolean arg5) throws RemoteException { // TODO Auto-generated method stub |