diff options
9 files changed, 87 insertions, 53 deletions
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java index a30f6299a4d9..4c8ddc7eb6b1 100644 --- a/core/java/android/app/ActivityOptions.java +++ b/core/java/android/app/ActivityOptions.java @@ -161,10 +161,10 @@ public class ActivityOptions { private static final String KEY_LAUNCH_TASK_ID = "android.activity.launchTaskId"; /** - * See {@link #setAvoidMoveToFront}. + * See {@link #setTaskOverlay}. * @hide */ - private static final String KEY_DONT_MOVE_TO_FRONT = "android.activity.dontMoveToFront"; + private static final String KEY_TASK_OVERLAY = "android.activity.taskOverlay"; /** * Where the docked stack should be positioned. @@ -239,7 +239,7 @@ public class ActivityOptions { private int mLaunchStackId = INVALID_STACK_ID; private int mLaunchTaskId = -1; private int mDockCreateMode = DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT; - private boolean mAvoidMoveToFront; + private boolean mTaskOverlay; private AppTransitionAnimationSpec mAnimSpecs[]; /** @@ -782,7 +782,7 @@ public class ActivityOptions { } mLaunchStackId = opts.getInt(KEY_LAUNCH_STACK_ID, INVALID_STACK_ID); mLaunchTaskId = opts.getInt(KEY_LAUNCH_TASK_ID, -1); - mAvoidMoveToFront = opts.getBoolean(KEY_DONT_MOVE_TO_FRONT, false); + mTaskOverlay = opts.getBoolean(KEY_TASK_OVERLAY, false); mDockCreateMode = opts.getInt(KEY_DOCK_CREATE_MODE, DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT); if (opts.containsKey(KEY_ANIM_SPECS)) { Parcelable[] specs = opts.getParcelableArray(KEY_ANIM_SPECS); @@ -961,20 +961,20 @@ public class ActivityOptions { } /** - * Set's whether the task should be moved to the front. This is different from - * {@link #getLaunchTaskBehind()} as we don't want to have an animation at all when launching - * an activity that shouldn't be moved to the front. + * Set's whether the activity launched with this option should be a task overlay. That is the + * activity will always be the top activity of the task and doesn't cause the task to be moved + * to the front when it is added. * @hide */ - public void setAvoidMoveToFront(boolean avoidMoveToFront) { - mAvoidMoveToFront = avoidMoveToFront; + public void setTaskOverlay(boolean taskOverlay) { + mTaskOverlay = taskOverlay; } /** * @hide */ - public boolean getAvoidMoveToFront() { - return mAvoidMoveToFront; + public boolean getTaskOverlay() { + return mTaskOverlay; } /** @hide */ @@ -1130,7 +1130,7 @@ public class ActivityOptions { } b.putInt(KEY_LAUNCH_STACK_ID, mLaunchStackId); b.putInt(KEY_LAUNCH_TASK_ID, mLaunchTaskId); - b.putBoolean(KEY_DONT_MOVE_TO_FRONT, mAvoidMoveToFront); + b.putBoolean(KEY_TASK_OVERLAY, mTaskOverlay); b.putInt(KEY_DOCK_CREATE_MODE, mDockCreateMode); if (mAnimSpecs != null) { b.putParcelableArray(KEY_ANIM_SPECS, mAnimSpecs); diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 4ba97d5f8bea..f8a6a17a0f57 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -163,7 +163,12 @@ interface IWindowManager IAppTransitionAnimationSpecsFuture specsFuture, IRemoteCallback startedCallback, boolean scaleUp); void executeAppTransition(); - void setAppStartingWindow(IBinder token, String pkg, int theme, + + /** + * Called to set the starting window for the input token and returns true if the starting + * window was set for the token. + */ + boolean setAppStartingWindow(IBinder token, String pkg, int theme, in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags, IBinder transferFrom, boolean createIfNeeded); void setAppVisibility(IBinder token, boolean visible); diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java index 34a37ba51bf1..5f083d57f9ae 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java @@ -111,7 +111,7 @@ public class ForcedResizableInfoActivityController { Intent intent = new Intent(mContext, ForcedResizableInfoActivity.class); ActivityOptions options = ActivityOptions.makeBasic(); options.setLaunchTaskId(mPendingTaskIds.valueAt(i)); - options.setAvoidMoveToFront(true); + options.setTaskOverlay(true); mContext.startActivity(intent, options.toBundle()); } mPendingTaskIds.clear(); diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index fa69b4a857df..3ccac9e2f1e4 100755 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -202,6 +202,7 @@ final class ActivityRecord { static final int STARTING_WINDOW_SHOWN = 1; static final int STARTING_WINDOW_REMOVED = 2; int mStartingWindowState = STARTING_WINDOW_NOT_SHOWN; + boolean mTaskOverlay = false; // Task is always on-top of other activities in the task. boolean mUpdateTaskThumbnailWhenHidden; ActivityContainer mInitialActivityContainer; @@ -1390,6 +1391,17 @@ final class ActivityRecord { pendingVoiceInteractionStart = false; } + void showStartingWindow(ActivityRecord prev, boolean createIfNeeded) { + final CompatibilityInfo compatInfo = + service.compatibilityInfoForPackageLocked(info.applicationInfo); + final boolean shown = service.mWindowManager.setAppStartingWindow( + appToken, packageName, theme, compatInfo, nonLocalizedLabel, labelRes, icon, + logo, windowFlags, prev != null ? prev.appToken : null, createIfNeeded); + if (shown) { + mStartingWindowState = STARTING_WINDOW_SHOWN; + } + } + void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException { out.attribute(null, ATTR_ID, String.valueOf(createTime)); out.attribute(null, ATTR_LAUNCHEDFROMUID, String.valueOf(launchedFromUid)); diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 62d114d1257a..893bd371a1bf 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -2459,12 +2459,7 @@ final class ActivityStack { next.hasBeenLaunched = true; } else if (SHOW_APP_STARTING_PREVIEW && lastStack != null && mStackSupervisor.isFrontStack(lastStack)) { - mWindowManager.setAppStartingWindow( - next.appToken, next.packageName, next.theme, - mService.compatibilityInfoForPackageLocked(next.info.applicationInfo), - next.nonLocalizedLabel, next.labelRes, next.icon, next.logo, - next.windowFlags, null, true); - next.mStartingWindowState = STARTING_WINDOW_SHOWN; + next.showStartingWindow(null, true); } mStackSupervisor.startSpecificActivityLocked(next, true, false); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); @@ -2490,14 +2485,7 @@ final class ActivityStack { next.hasBeenLaunched = true; } else { if (SHOW_APP_STARTING_PREVIEW) { - mWindowManager.setAppStartingWindow( - next.appToken, next.packageName, next.theme, - mService.compatibilityInfoForPackageLocked( - next.info.applicationInfo), - next.nonLocalizedLabel, - next.labelRes, next.icon, next.logo, next.windowFlags, - null, true); - next.mStartingWindowState = STARTING_WINDOW_SHOWN; + next.showStartingWindow(null, true); } if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next); } @@ -2712,7 +2700,7 @@ final class ActivityStack { // "has the same starting icon" as the next one. This allows the // window manager to keep the previous window it had previously // created, if it still had one. - ActivityRecord prev = mResumedActivity; + ActivityRecord prev = r.task.topRunningActivityWithStartingWindowLocked(); if (prev != null) { // We don't want to reuse the previous starting preview if: // (1) The current activity is in a different task. @@ -2724,13 +2712,7 @@ final class ActivityStack { prev = null; } } - mWindowManager.setAppStartingWindow( - r.appToken, r.packageName, r.theme, - mService.compatibilityInfoForPackageLocked( - r.info.applicationInfo), r.nonLocalizedLabel, - r.labelRes, r.icon, r.logo, r.windowFlags, - prev != null ? prev.appToken : null, showStartingIcon); - r.mStartingWindowState = STARTING_WINDOW_SHOWN; + r.showStartingWindow(prev, showStartingIcon); } } else { // If this is the first activity, don't do any fancy animations, diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index 64bd14c3c0b5..fbb4b7773c03 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -1149,17 +1149,22 @@ class ActivityStarter { // activity. mService.setFocusedActivityLocked(mStartActivity, "startedActivity"); } - if (mTargetStack.isFocusable()) { - mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity, - mOptions); - } else { + final ActivityRecord topTaskActivity = mStartActivity.task.topRunningActivityLocked(); + if (!mTargetStack.isFocusable() + || (topTaskActivity != null && topTaskActivity.mTaskOverlay)) { // If the activity is not focusable, we can't resume it, but still would like to // make sure it becomes visible as it starts (this will also trigger entry // animation). An example of this are PIP activities. + // Also, we don't want to resume activities in a task that currently has an overlay + // as the starting activity just needs to be in the visible paused state until the + // over is removed. mTargetStack.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); // Go ahead and tell window manager to execute app transition for this activity // since the app transition will not be triggered through the resume channel. mWindowManager.executeAppTransition(); + } else { + mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity, + mOptions); } } else { mTargetStack.addRecentActivityLocked(mStartActivity); @@ -1226,7 +1231,8 @@ class ActivityStarter { mDoResume = false; } - if (mOptions != null && mOptions.getLaunchTaskId() != -1 && mOptions.getAvoidMoveToFront()) { + if (mOptions != null && mOptions.getLaunchTaskId() != -1 && mOptions.getTaskOverlay()) { + r.mTaskOverlay = true; final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId()); final ActivityRecord top = task != null ? task.getTopActivity() : null; if (top != null && !top.visible) { diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index af7740f8083a..729d32fbfc4f 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -88,6 +88,7 @@ import static com.android.server.am.ActivityManagerService.LOCK_SCREEN_SHOWN; import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE; import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE; import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE; +import static com.android.server.am.ActivityRecord.STARTING_WINDOW_SHOWN; final class TaskRecord { private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_AM; @@ -685,6 +686,20 @@ final class TaskRecord { return null; } + ActivityRecord topRunningActivityWithStartingWindowLocked() { + if (stack != null) { + for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) { + ActivityRecord r = mActivities.get(activityNdx); + if (r.mStartingWindowState != STARTING_WINDOW_SHOWN + || r.finishing || !stack.okToShowLocked(r)) { + continue; + } + return r; + } + } + return null; + } + void setFrontOfTask() { setFrontOfTask(null); } @@ -760,6 +775,18 @@ final class TaskRecord { // Otherwise make all added activities match this one. r.mActivityType = taskType; } + + final int size = mActivities.size(); + + if (index == size && size > 0) { + final ActivityRecord top = mActivities.get(size - 1); + if (top.mTaskOverlay) { + // Place below the task overlay activity since the overlay activity should always + // be on top. + index--; + } + } + mActivities.add(index, r); updateEffectiveIntent(); if (r.isPersistable()) { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 11327582a481..5ea4e9ef7051 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -4023,7 +4023,7 @@ public class WindowManagerService extends IWindowManager.Stub } @Override - public void setAppStartingWindow(IBinder token, String pkg, + public boolean setAppStartingWindow(IBinder token, String pkg, int theme, CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags, IBinder transferFrom, boolean createIfNeeded) { @@ -4040,18 +4040,18 @@ public class WindowManagerService extends IWindowManager.Stub AppWindowToken wtoken = findAppWindowToken(token); if (wtoken == null) { Slog.w(TAG_WM, "Attempted to set icon of non-existing app token: " + token); - return; + return false; } // If the display is frozen, we won't do anything until the // actual window is displayed so there is no reason to put in // the starting window. if (!okToDisplay()) { - return; + return false; } if (wtoken.startingData != null) { - return; + return false; } // If this is a translucent window, then don't @@ -4066,7 +4066,7 @@ public class WindowManagerService extends IWindowManager.Stub if (ent == null) { // Whoops! App doesn't exist. Um. Okay. We'll just // pretend like we didn't see that. - return; + return false; } final boolean windowIsTranslucent = ent.array.getBoolean( com.android.internal.R.styleable.Window_windowIsTranslucent, false); @@ -4080,33 +4080,33 @@ public class WindowManagerService extends IWindowManager.Stub + " Floating=" + windowIsFloating + " ShowWallpaper=" + windowShowWallpaper); if (windowIsTranslucent) { - return; + return false; } if (windowIsFloating || windowDisableStarting) { - return; + return false; } if (windowShowWallpaper) { if (mWallpaperControllerLocked.getWallpaperTarget() == null) { // If this theme is requesting a wallpaper, and the wallpaper - // is not curently visible, then this effectively serves as + // is not currently visible, then this effectively serves as // an opaque window and our starting window transition animation // can still work. We just need to make sure the starting window // is also showing the wallpaper. windowFlags |= FLAG_SHOW_WALLPAPER; } else { - return; + return false; } } } if (transferStartingWindow(transferFrom, wtoken)) { - return; + return true; } // There is no existing starting window, and the caller doesn't // want us to create one, so that's it! if (!createIfNeeded) { - return; + return false; } if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating StartingData"); @@ -4119,6 +4119,7 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Enqueueing ADD_STARTING"); mH.sendMessageAtFrontOfQueue(m); } + return true; } private boolean transferStartingWindow(IBinder transferFrom, AppWindowToken wtoken) { diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java index f9e008e1cf92..ceebdd50021a 100644 --- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java +++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java @@ -336,10 +336,11 @@ public class IWindowManagerImpl implements IWindowManager { } @Override - public void setAppStartingWindow(IBinder arg0, String arg1, int arg2, CompatibilityInfo arg3, + public boolean setAppStartingWindow(IBinder arg0, String arg1, int arg2, CompatibilityInfo arg3, CharSequence arg4, int arg5, int arg6, int arg7, int arg8, IBinder arg9, boolean arg10) throws RemoteException { // TODO Auto-generated method stub + return false; } @Override |