Loading core/java/android/view/WindowManagerPolicy.java +6 −0 Original line number Diff line number Diff line Loading @@ -1143,6 +1143,12 @@ public interface WindowManagerPolicy { */ public void setLastInputMethodWindowLw(WindowState ime, WindowState target); /** * Show the recents task list app. * @hide */ public void showRecentApps(); /** * @return The current height of the input method window. */ Loading policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +10 −0 Original line number Diff line number Diff line Loading @@ -478,6 +478,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { private static final int MSG_DISABLE_POINTER_LOCATION = 2; private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3; private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4; private static final int MSG_DISPATCH_SHOW_RECENTS = 5; private class PolicyHandler extends Handler { @Override Loading @@ -495,6 +496,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { case MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK: dispatchMediaKeyRepeatWithWakeLock((KeyEvent)msg.obj); break; case MSG_DISPATCH_SHOW_RECENTS: showRecentApps(false); break; } } } Loading Loading @@ -2459,6 +2463,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } @Override public void showRecentApps() { mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS); mHandler.sendEmptyMessage(MSG_DISPATCH_SHOW_RECENTS); } private void showRecentApps(boolean triggeredFromAltTab) { mPreloadedRecentApps = false; // preloading no longer needs to be canceled try { Loading services/core/java/com/android/server/am/ActivityStack.java +43 −59 Original line number Diff line number Diff line Loading @@ -30,6 +30,10 @@ import static com.android.server.am.ActivityManagerService.DEBUG_USER_LEAVING; import static com.android.server.am.ActivityManagerService.DEBUG_VISBILITY; import static com.android.server.am.ActivityManagerService.VALIDATE_TOKENS; import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE; import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE; import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE; import static com.android.server.am.ActivityStackSupervisor.DEBUG_ADD_REMOVE; import static com.android.server.am.ActivityStackSupervisor.DEBUG_APP; import static com.android.server.am.ActivityStackSupervisor.DEBUG_SAVED_STATE; Loading Loading @@ -1040,40 +1044,6 @@ final class ActivityStack { } } /** * Determine if home should be visible below the passed record. * @param record activity we are querying for. * @return true if home is visible below the passed activity, false otherwise. */ boolean isActivityOverHome(ActivityRecord record) { // Start at record and go down, look for either home or a visible fullscreen activity. final TaskRecord recordTask = record.task; for (int taskNdx = mTaskHistory.indexOf(recordTask); taskNdx >= 0; --taskNdx) { TaskRecord task = mTaskHistory.get(taskNdx); final ArrayList<ActivityRecord> activities = task.mActivities; final int startNdx = task == recordTask ? activities.indexOf(record) : activities.size() - 1; for (int activityNdx = startNdx; activityNdx >= 0; --activityNdx) { final ActivityRecord r = activities.get(activityNdx); if (r.isHomeActivity()) { return true; } if (!r.finishing && r.fullscreen) { // Passed activity is over a fullscreen activity. return false; } } if (task.mOnTopOfHome) { // Got to the bottom of a task on top of home without finding a visible fullscreen // activity. Home is visible. return true; } } // Got to the bottom of this stack and still don't know. If this is over the home stack // then record is over home. May not work if we ever get more than two layers. return mStackSupervisor.isFrontStack(this); } private void setVisibile(ActivityRecord r, boolean visible) { r.visible = visible; mWindowManager.setAppVisibility(r.appToken, visible); Loading Loading @@ -1103,7 +1073,8 @@ final class ActivityStack { for (int i = mStacks.indexOf(this) + 1; i < mStacks.size(); i++) { final ArrayList<TaskRecord> tasks = mStacks.get(i).getAllTasks(); for (int taskNdx = 0; taskNdx < tasks.size(); taskNdx++) { final ArrayList<ActivityRecord> activities = tasks.get(taskNdx).mActivities; final TaskRecord task = tasks.get(taskNdx); final ArrayList<ActivityRecord> activities = task.mActivities; for (int activityNdx = 0; activityNdx < activities.size(); activityNdx++) { final ActivityRecord r = activities.get(activityNdx); Loading @@ -1114,7 +1085,7 @@ final class ActivityStack { // - Full Screen Activity OR // - On top of Home and our stack is NOT home if (!r.finishing && r.visible && (r.fullscreen || (!isHomeStack() && r.frontOfTask && tasks.get(taskNdx).mOnTopOfHome))) { (!isHomeStack() && r.frontOfTask && task.isOverHomeStack()))) { return false; } } Loading Loading @@ -1242,7 +1213,7 @@ final class ActivityStack { // At this point, nothing else needs to be shown if (DEBUG_VISBILITY) Slog.v(TAG, "Fullscreen: at " + r); behindFullscreen = true; } else if (!isHomeStack() && r.frontOfTask && task.mOnTopOfHome) { } else if (!isHomeStack() && r.frontOfTask && task.isOverHomeStack()) { if (DEBUG_VISBILITY) Slog.v(TAG, "Showing home: at " + r); behindFullscreen = true; } Loading Loading @@ -1396,6 +1367,7 @@ final class ActivityStack { final boolean userLeaving = mStackSupervisor.mUserLeaving; mStackSupervisor.mUserLeaving = false; final TaskRecord prevTask = prev != null ? prev.task : null; if (next == null) { // There are no more activities! Let's just start up the // Launcher... Loading @@ -1403,7 +1375,10 @@ final class ActivityStack { if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: No more activities go home"); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); // Only resume home if on home display return isOnHomeDisplay() && mStackSupervisor.resumeHomeActivity(prev); final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ? HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo(); return isOnHomeDisplay() && mStackSupervisor.resumeHomeStackTask(returnTaskType, prev); } next.delayedResume = false; Loading @@ -1422,22 +1397,24 @@ final class ActivityStack { } final TaskRecord nextTask = next.task; final TaskRecord prevTask = prev != null ? prev.task : null; if (prevTask != null && prevTask.stack == this && prevTask.mOnTopOfHome && prev.finishing && prev.frontOfTask) { prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) { if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); if (prevTask == nextTask) { prevTask.setFrontOfTask(); } else if (prevTask != topTask()) { // This task is going away but it was supposed to return to the home task. // This task is going away but it was supposed to return to the home stack. // Now the task above it has to return to the home task instead. final int taskNdx = mTaskHistory.indexOf(prevTask) + 1; mTaskHistory.get(taskNdx).mOnTopOfHome = true; mTaskHistory.get(taskNdx).setTaskToReturnTo(HOME_ACTIVITY_TYPE); } else { if (DEBUG_STATES && isOnHomeDisplay()) Slog.d(TAG, "resumeTopActivityLocked: Launching home next"); // Only resume home if on home display return isOnHomeDisplay() && mStackSupervisor.resumeHomeActivity(prev); final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ? HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo(); return isOnHomeDisplay() && mStackSupervisor.resumeHomeStackTask(returnTaskType, prev); } } Loading Loading @@ -1808,10 +1785,11 @@ final class ActivityStack { ActivityStack lastStack = mStackSupervisor.getLastStack(); final boolean fromHome = lastStack.isHomeStack(); if (!isHomeStack() && (fromHome || topTask() != task)) { task.mOnTopOfHome = fromHome; task.setTaskToReturnTo(fromHome ? lastStack.topTask().taskType : APPLICATION_ACTIVITY_TYPE); } } else { task.mOnTopOfHome = false; task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE); } mTaskHistory.remove(task); Loading Loading @@ -2356,8 +2334,8 @@ final class ActivityStack { ActivityRecord next = topRunningActivityLocked(null); if (next != r) { final TaskRecord task = r.task; if (r.frontOfTask && task == topTask() && task.mOnTopOfHome) { mStackSupervisor.moveHomeToTop(); if (r.frontOfTask && task == topTask() && task.isOverHomeStack()) { mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo()); } } ActivityRecord top = mStackSupervisor.topRunningActivityLocked(); Loading Loading @@ -2841,8 +2819,9 @@ final class ActivityStack { if (task != null && task.removeActivity(r)) { if (DEBUG_STACK) Slog.i(TAG, "removeActivityFromHistoryLocked: last activity removed from " + this); if (mStackSupervisor.isFrontStack(this) && task == topTask() && task.mOnTopOfHome) { mStackSupervisor.moveHomeToTop(); if (mStackSupervisor.isFrontStack(this) && task == topTask() && task.isOverHomeStack()) { mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo()); } removeTask(task); } Loading Loading @@ -3157,12 +3136,13 @@ final class ActivityStack { } } void moveHomeTaskToTop() { void moveHomeStackTaskToTop(int homeStackTaskType) { final int top = mTaskHistory.size() - 1; for (int taskNdx = top; taskNdx >= 0; --taskNdx) { final TaskRecord task = mTaskHistory.get(taskNdx); if (task.isHomeTask()) { if (DEBUG_TASKS || DEBUG_STACK) Slog.d(TAG, "moveHomeTaskToTop: moving " + task); if (task.taskType == homeStackTaskType) { if (DEBUG_TASKS || DEBUG_STACK) Slog.d(TAG, "moveHomeStackTaskToTop: moving " + task); mTaskHistory.remove(taskNdx); mTaskHistory.add(top, task); updateTaskMovement(task, true); Loading Loading @@ -3274,12 +3254,12 @@ final class ActivityStack { int numTasks = mTaskHistory.size(); for (int taskNdx = numTasks - 1; taskNdx >= 1; --taskNdx) { final TaskRecord task = mTaskHistory.get(taskNdx); if (task.mOnTopOfHome) { if (task.isOverHomeStack()) { break; } if (taskNdx == 1) { // Set the last task before tr to go to home. task.mOnTopOfHome = true; task.setTaskToReturnTo(HOME_ACTIVITY_TYPE); } } Loading @@ -3300,9 +3280,10 @@ final class ActivityStack { } final TaskRecord task = mResumedActivity != null ? mResumedActivity.task : null; if (task == tr && tr.mOnTopOfHome || numTasks <= 1 && isOnHomeDisplay()) { tr.mOnTopOfHome = false; return mStackSupervisor.resumeHomeActivity(null); if (task == tr && tr.isOverHomeStack() || numTasks <= 1 && isOnHomeDisplay()) { final int taskToReturnTo = tr.getTaskToReturnTo(); tr.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE); return mStackSupervisor.resumeHomeStackTask(taskToReturnTo, null); } mStackSupervisor.resumeTopActivitiesLocked(); Loading Loading @@ -3743,8 +3724,11 @@ final class ActivityStack { final int taskNdx = mTaskHistory.indexOf(task); final int topTaskNdx = mTaskHistory.size() - 1; if (task.mOnTopOfHome && taskNdx < topTaskNdx) { mTaskHistory.get(taskNdx + 1).mOnTopOfHome = true; if (task.isOverHomeStack() && taskNdx < topTaskNdx) { final TaskRecord nextTask = mTaskHistory.get(taskNdx + 1); if (!nextTask.isOverHomeStack()) { nextTask.setTaskToReturnTo(HOME_ACTIVITY_TYPE); } } mTaskHistory.remove(task); updateTaskMovement(task, true); Loading services/core/java/com/android/server/am/ActivityStackSupervisor.java +29 −12 Original line number Diff line number Diff line Loading @@ -31,6 +31,9 @@ import static com.android.server.am.ActivityManagerService.DEBUG_TASKS; import static com.android.server.am.ActivityManagerService.DEBUG_USER_LEAVING; import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG; import static com.android.server.am.ActivityManagerService.TAG; 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.APPLICATION_ACTIVITY_TYPE; import android.app.Activity; import android.app.ActivityManager; Loading Loading @@ -318,18 +321,27 @@ public final class ActivityStackSupervisor implements DisplayListener { } } void moveHomeToTop() { void moveHomeStackTaskToTop(int homeStackTaskType) { if (homeStackTaskType == RECENTS_ACTIVITY_TYPE) { mWindowManager.showRecentApps(); return; } moveHomeStack(true); mHomeStack.moveHomeTaskToTop(); mHomeStack.moveHomeStackTaskToTop(homeStackTaskType); } boolean resumeHomeActivity(ActivityRecord prev) { moveHomeToTop(); boolean resumeHomeStackTask(int homeStackTaskType, ActivityRecord prev) { if (homeStackTaskType == RECENTS_ACTIVITY_TYPE) { mWindowManager.showRecentApps(); return false; } moveHomeStackTaskToTop(homeStackTaskType); if (prev != null) { prev.task.mOnTopOfHome = false; prev.task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE); } ActivityRecord r = mHomeStack.topRunningActivityLocked(null); if (r != null && r.isHomeActivity()) { if (r != null && (r.isHomeActivity() || r.isRecentsActivity())) { mService.setFocusedActivityLocked(r); return resumeTopActivitiesLocked(mHomeStack, prev, null); } Loading Loading @@ -683,7 +695,7 @@ public final class ActivityStackSupervisor implements DisplayListener { } void startHomeActivity(Intent intent, ActivityInfo aInfo) { moveHomeToTop(); moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE); startActivityLocked(null, intent, null, aInfo, null, null, null, null, 0, 0, 0, null, 0, null, false, null, null); } Loading Loading @@ -1615,7 +1627,7 @@ public final class ActivityStackSupervisor implements DisplayListener { (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) { // Caller wants to appear on home activity. intentActivity.task.mOnTopOfHome = true; intentActivity.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE); } options = null; } Loading Loading @@ -1799,6 +1811,11 @@ public final class ActivityStackSupervisor implements DisplayListener { newTaskInfo != null ? newTaskInfo : r.info, newTaskIntent != null ? newTaskIntent : intent, voiceSession, voiceInteractor, true), null, true); if (sourceRecord == null) { // Launched from a service or notification or task that is finishing. r.task.setTaskToReturnTo(isFrontStack(mHomeStack) ? mHomeStack.topTask().taskType : RECENTS_ACTIVITY_TYPE); } if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " + r.task); } else { Loading @@ -1811,7 +1828,7 @@ public final class ActivityStackSupervisor implements DisplayListener { == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) { // Caller wants to appear on home activity, so before starting // their own activity we will bring home to the front. r.task.mOnTopOfHome = r.task.stack.isOnHomeDisplay(); r.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE); } } } else if (sourceRecord != null) { Loading Loading @@ -2162,7 +2179,7 @@ public final class ActivityStackSupervisor implements DisplayListener { if ((flags & ActivityManager.MOVE_TASK_WITH_HOME) != 0) { // Caller wants the home activity moved with it. To accomplish this, // we'll just indicate that this task returns to the home task. task.mOnTopOfHome = true; task.setTaskToReturnTo(HOME_ACTIVITY_TYPE); } task.stack.moveTaskToFrontLocked(task, null, options); if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack=" Loading Loading @@ -2273,7 +2290,7 @@ public final class ActivityStackSupervisor implements DisplayListener { } mWindowManager.addTask(taskId, stackId, false); } resumeHomeActivity(null); resumeHomeStackTask(HOME_ACTIVITY_TYPE, null); } void moveTaskToStack(int taskId, int stackId, boolean toTop) { Loading Loading @@ -2530,7 +2547,7 @@ public final class ActivityStackSupervisor implements DisplayListener { } } else { // Stack was moved to another display while user was swapped out. resumeHomeActivity(null); resumeHomeStackTask(HOME_ACTIVITY_TYPE, null); } return homeInFront; } Loading services/core/java/com/android/server/am/TaskRecord.java +27 −17 Original line number Diff line number Diff line Loading @@ -17,6 +17,9 @@ package com.android.server.am; import static com.android.server.am.ActivityManagerService.TAG; import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE; import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE; import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE; import static com.android.server.am.ActivityStackSupervisor.DEBUG_ADD_REMOVE; import android.app.Activity; Loading Loading @@ -54,7 +57,6 @@ final class TaskRecord extends ThumbnailHolder { private static final String ATTR_ASKEDCOMPATMODE = "asked_compat_mode"; private static final String ATTR_USERID = "user_id"; private static final String ATTR_TASKTYPE = "task_type"; private static final String ATTR_ONTOPOFHOME = "on_top_of_home"; private static final String ATTR_LASTDESCRIPTION = "last_description"; private static final String ATTR_LASTTIMEMOVED = "last_time_moved"; Loading Loading @@ -104,9 +106,11 @@ final class TaskRecord extends ThumbnailHolder { /** True if persistable, has changed, and has not yet been persisted */ boolean needsPersisting = false; /** Launch the home activity when leaving this task. Will be false for tasks that are not on * Display.DEFAULT_DISPLAY. */ boolean mOnTopOfHome = false; /** Indication of what to run next when task exits. Use ActivityRecord types. * ActivityRecord.APPLICATION_ACTIVITY_TYPE indicates to resume the task below this one in the * task stack. */ private int mTaskToReturnTo = APPLICATION_ACTIVITY_TYPE; final ActivityManagerService mService; Loading @@ -123,9 +127,8 @@ final class TaskRecord extends ThumbnailHolder { TaskRecord(ActivityManagerService service, int _taskId, Intent _intent, Intent _affinityIntent, String _affinity, ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset, boolean _askedCompatMode, int _taskType, boolean _onTopOfHome, int _userId, String _lastDescription, ArrayList<ActivityRecord> activities, long lastTimeMoved) { boolean _rootWasReset, boolean _askedCompatMode, int _taskType, int _userId, String _lastDescription, ArrayList<ActivityRecord> activities, long lastTimeMoved) { mService = service; taskId = _taskId; intent = _intent; Loading @@ -138,7 +141,7 @@ final class TaskRecord extends ThumbnailHolder { rootWasReset = _rootWasReset; askedCompatMode = _askedCompatMode; taskType = _taskType; mOnTopOfHome = _onTopOfHome; mTaskToReturnTo = HOME_ACTIVITY_TYPE; userId = _userId; lastDescription = _lastDescription; mActivities = activities; Loading Loading @@ -206,6 +209,14 @@ final class TaskRecord extends ThumbnailHolder { } } void setTaskToReturnTo(int taskToReturnTo) { mTaskToReturnTo = taskToReturnTo; } int getTaskToReturnTo() { return mTaskToReturnTo; } void disposeThumbnail() { super.disposeThumbnail(); for (int i=mActivities.size()-1; i>=0; i--) { Loading Loading @@ -477,11 +488,15 @@ final class TaskRecord extends ThumbnailHolder { } boolean isHomeTask() { return taskType == ActivityRecord.HOME_ACTIVITY_TYPE; return taskType == HOME_ACTIVITY_TYPE; } boolean isApplicationTask() { return taskType == ActivityRecord.APPLICATION_ACTIVITY_TYPE; return taskType == APPLICATION_ACTIVITY_TYPE; } boolean isOverHomeStack() { return mTaskToReturnTo == HOME_ACTIVITY_TYPE || mTaskToReturnTo == RECENTS_ACTIVITY_TYPE; } public TaskAccessInfo getTaskAccessInfoLocked() { Loading Loading @@ -623,7 +638,6 @@ final class TaskRecord extends ThumbnailHolder { out.attribute(null, ATTR_ASKEDCOMPATMODE, String.valueOf(askedCompatMode)); out.attribute(null, ATTR_USERID, String.valueOf(userId)); out.attribute(null, ATTR_TASKTYPE, String.valueOf(taskType)); out.attribute(null, ATTR_ONTOPOFHOME, String.valueOf(mOnTopOfHome)); out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved)); if (lastDescription != null) { out.attribute(null, ATTR_LASTDESCRIPTION, lastDescription.toString()); Loading Loading @@ -669,7 +683,6 @@ final class TaskRecord extends ThumbnailHolder { boolean rootHasReset = false; boolean askedCompatMode = false; int taskType = ActivityRecord.APPLICATION_ACTIVITY_TYPE; boolean onTopOfHome = true; int userId = 0; String lastDescription = null; long lastTimeOnTop = 0; Loading Loading @@ -697,8 +710,6 @@ final class TaskRecord extends ThumbnailHolder { userId = Integer.valueOf(attrValue); } else if (ATTR_TASKTYPE.equals(attrName)) { taskType = Integer.valueOf(attrValue); } else if (ATTR_ONTOPOFHOME.equals(attrName)) { onTopOfHome = Boolean.valueOf(attrValue); } else if (ATTR_LASTDESCRIPTION.equals(attrName)) { lastDescription = attrValue; } else if (ATTR_LASTTIMEMOVED.equals(attrName)) { Loading Loading @@ -736,8 +747,7 @@ final class TaskRecord extends ThumbnailHolder { final TaskRecord task = new TaskRecord(stackSupervisor.mService, taskId, intent, affinityIntent, affinity, realActivity, origActivity, rootHasReset, askedCompatMode, taskType, onTopOfHome, userId, lastDescription, activities, lastTimeOnTop); askedCompatMode, taskType, userId, lastDescription, activities, lastTimeOnTop); for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) { final ActivityRecord r = activities.get(activityNdx); Loading @@ -756,7 +766,7 @@ final class TaskRecord extends ThumbnailHolder { pw.print(" userId="); pw.print(userId); pw.print(" taskType="); pw.print(taskType); pw.print(" numFullscreen="); pw.print(numFullscreen); pw.print(" mOnTopOfHome="); pw.println(mOnTopOfHome); pw.print(" mTaskToReturnTo="); pw.println(mTaskToReturnTo); } if (affinity != null) { pw.print(prefix); pw.print("affinity="); pw.println(affinity); Loading Loading
core/java/android/view/WindowManagerPolicy.java +6 −0 Original line number Diff line number Diff line Loading @@ -1143,6 +1143,12 @@ public interface WindowManagerPolicy { */ public void setLastInputMethodWindowLw(WindowState ime, WindowState target); /** * Show the recents task list app. * @hide */ public void showRecentApps(); /** * @return The current height of the input method window. */ Loading
policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +10 −0 Original line number Diff line number Diff line Loading @@ -478,6 +478,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { private static final int MSG_DISABLE_POINTER_LOCATION = 2; private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3; private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4; private static final int MSG_DISPATCH_SHOW_RECENTS = 5; private class PolicyHandler extends Handler { @Override Loading @@ -495,6 +496,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { case MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK: dispatchMediaKeyRepeatWithWakeLock((KeyEvent)msg.obj); break; case MSG_DISPATCH_SHOW_RECENTS: showRecentApps(false); break; } } } Loading Loading @@ -2459,6 +2463,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } @Override public void showRecentApps() { mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS); mHandler.sendEmptyMessage(MSG_DISPATCH_SHOW_RECENTS); } private void showRecentApps(boolean triggeredFromAltTab) { mPreloadedRecentApps = false; // preloading no longer needs to be canceled try { Loading
services/core/java/com/android/server/am/ActivityStack.java +43 −59 Original line number Diff line number Diff line Loading @@ -30,6 +30,10 @@ import static com.android.server.am.ActivityManagerService.DEBUG_USER_LEAVING; import static com.android.server.am.ActivityManagerService.DEBUG_VISBILITY; import static com.android.server.am.ActivityManagerService.VALIDATE_TOKENS; import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE; import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE; import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE; import static com.android.server.am.ActivityStackSupervisor.DEBUG_ADD_REMOVE; import static com.android.server.am.ActivityStackSupervisor.DEBUG_APP; import static com.android.server.am.ActivityStackSupervisor.DEBUG_SAVED_STATE; Loading Loading @@ -1040,40 +1044,6 @@ final class ActivityStack { } } /** * Determine if home should be visible below the passed record. * @param record activity we are querying for. * @return true if home is visible below the passed activity, false otherwise. */ boolean isActivityOverHome(ActivityRecord record) { // Start at record and go down, look for either home or a visible fullscreen activity. final TaskRecord recordTask = record.task; for (int taskNdx = mTaskHistory.indexOf(recordTask); taskNdx >= 0; --taskNdx) { TaskRecord task = mTaskHistory.get(taskNdx); final ArrayList<ActivityRecord> activities = task.mActivities; final int startNdx = task == recordTask ? activities.indexOf(record) : activities.size() - 1; for (int activityNdx = startNdx; activityNdx >= 0; --activityNdx) { final ActivityRecord r = activities.get(activityNdx); if (r.isHomeActivity()) { return true; } if (!r.finishing && r.fullscreen) { // Passed activity is over a fullscreen activity. return false; } } if (task.mOnTopOfHome) { // Got to the bottom of a task on top of home without finding a visible fullscreen // activity. Home is visible. return true; } } // Got to the bottom of this stack and still don't know. If this is over the home stack // then record is over home. May not work if we ever get more than two layers. return mStackSupervisor.isFrontStack(this); } private void setVisibile(ActivityRecord r, boolean visible) { r.visible = visible; mWindowManager.setAppVisibility(r.appToken, visible); Loading Loading @@ -1103,7 +1073,8 @@ final class ActivityStack { for (int i = mStacks.indexOf(this) + 1; i < mStacks.size(); i++) { final ArrayList<TaskRecord> tasks = mStacks.get(i).getAllTasks(); for (int taskNdx = 0; taskNdx < tasks.size(); taskNdx++) { final ArrayList<ActivityRecord> activities = tasks.get(taskNdx).mActivities; final TaskRecord task = tasks.get(taskNdx); final ArrayList<ActivityRecord> activities = task.mActivities; for (int activityNdx = 0; activityNdx < activities.size(); activityNdx++) { final ActivityRecord r = activities.get(activityNdx); Loading @@ -1114,7 +1085,7 @@ final class ActivityStack { // - Full Screen Activity OR // - On top of Home and our stack is NOT home if (!r.finishing && r.visible && (r.fullscreen || (!isHomeStack() && r.frontOfTask && tasks.get(taskNdx).mOnTopOfHome))) { (!isHomeStack() && r.frontOfTask && task.isOverHomeStack()))) { return false; } } Loading Loading @@ -1242,7 +1213,7 @@ final class ActivityStack { // At this point, nothing else needs to be shown if (DEBUG_VISBILITY) Slog.v(TAG, "Fullscreen: at " + r); behindFullscreen = true; } else if (!isHomeStack() && r.frontOfTask && task.mOnTopOfHome) { } else if (!isHomeStack() && r.frontOfTask && task.isOverHomeStack()) { if (DEBUG_VISBILITY) Slog.v(TAG, "Showing home: at " + r); behindFullscreen = true; } Loading Loading @@ -1396,6 +1367,7 @@ final class ActivityStack { final boolean userLeaving = mStackSupervisor.mUserLeaving; mStackSupervisor.mUserLeaving = false; final TaskRecord prevTask = prev != null ? prev.task : null; if (next == null) { // There are no more activities! Let's just start up the // Launcher... Loading @@ -1403,7 +1375,10 @@ final class ActivityStack { if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: No more activities go home"); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); // Only resume home if on home display return isOnHomeDisplay() && mStackSupervisor.resumeHomeActivity(prev); final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ? HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo(); return isOnHomeDisplay() && mStackSupervisor.resumeHomeStackTask(returnTaskType, prev); } next.delayedResume = false; Loading @@ -1422,22 +1397,24 @@ final class ActivityStack { } final TaskRecord nextTask = next.task; final TaskRecord prevTask = prev != null ? prev.task : null; if (prevTask != null && prevTask.stack == this && prevTask.mOnTopOfHome && prev.finishing && prev.frontOfTask) { prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) { if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); if (prevTask == nextTask) { prevTask.setFrontOfTask(); } else if (prevTask != topTask()) { // This task is going away but it was supposed to return to the home task. // This task is going away but it was supposed to return to the home stack. // Now the task above it has to return to the home task instead. final int taskNdx = mTaskHistory.indexOf(prevTask) + 1; mTaskHistory.get(taskNdx).mOnTopOfHome = true; mTaskHistory.get(taskNdx).setTaskToReturnTo(HOME_ACTIVITY_TYPE); } else { if (DEBUG_STATES && isOnHomeDisplay()) Slog.d(TAG, "resumeTopActivityLocked: Launching home next"); // Only resume home if on home display return isOnHomeDisplay() && mStackSupervisor.resumeHomeActivity(prev); final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ? HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo(); return isOnHomeDisplay() && mStackSupervisor.resumeHomeStackTask(returnTaskType, prev); } } Loading Loading @@ -1808,10 +1785,11 @@ final class ActivityStack { ActivityStack lastStack = mStackSupervisor.getLastStack(); final boolean fromHome = lastStack.isHomeStack(); if (!isHomeStack() && (fromHome || topTask() != task)) { task.mOnTopOfHome = fromHome; task.setTaskToReturnTo(fromHome ? lastStack.topTask().taskType : APPLICATION_ACTIVITY_TYPE); } } else { task.mOnTopOfHome = false; task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE); } mTaskHistory.remove(task); Loading Loading @@ -2356,8 +2334,8 @@ final class ActivityStack { ActivityRecord next = topRunningActivityLocked(null); if (next != r) { final TaskRecord task = r.task; if (r.frontOfTask && task == topTask() && task.mOnTopOfHome) { mStackSupervisor.moveHomeToTop(); if (r.frontOfTask && task == topTask() && task.isOverHomeStack()) { mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo()); } } ActivityRecord top = mStackSupervisor.topRunningActivityLocked(); Loading Loading @@ -2841,8 +2819,9 @@ final class ActivityStack { if (task != null && task.removeActivity(r)) { if (DEBUG_STACK) Slog.i(TAG, "removeActivityFromHistoryLocked: last activity removed from " + this); if (mStackSupervisor.isFrontStack(this) && task == topTask() && task.mOnTopOfHome) { mStackSupervisor.moveHomeToTop(); if (mStackSupervisor.isFrontStack(this) && task == topTask() && task.isOverHomeStack()) { mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo()); } removeTask(task); } Loading Loading @@ -3157,12 +3136,13 @@ final class ActivityStack { } } void moveHomeTaskToTop() { void moveHomeStackTaskToTop(int homeStackTaskType) { final int top = mTaskHistory.size() - 1; for (int taskNdx = top; taskNdx >= 0; --taskNdx) { final TaskRecord task = mTaskHistory.get(taskNdx); if (task.isHomeTask()) { if (DEBUG_TASKS || DEBUG_STACK) Slog.d(TAG, "moveHomeTaskToTop: moving " + task); if (task.taskType == homeStackTaskType) { if (DEBUG_TASKS || DEBUG_STACK) Slog.d(TAG, "moveHomeStackTaskToTop: moving " + task); mTaskHistory.remove(taskNdx); mTaskHistory.add(top, task); updateTaskMovement(task, true); Loading Loading @@ -3274,12 +3254,12 @@ final class ActivityStack { int numTasks = mTaskHistory.size(); for (int taskNdx = numTasks - 1; taskNdx >= 1; --taskNdx) { final TaskRecord task = mTaskHistory.get(taskNdx); if (task.mOnTopOfHome) { if (task.isOverHomeStack()) { break; } if (taskNdx == 1) { // Set the last task before tr to go to home. task.mOnTopOfHome = true; task.setTaskToReturnTo(HOME_ACTIVITY_TYPE); } } Loading @@ -3300,9 +3280,10 @@ final class ActivityStack { } final TaskRecord task = mResumedActivity != null ? mResumedActivity.task : null; if (task == tr && tr.mOnTopOfHome || numTasks <= 1 && isOnHomeDisplay()) { tr.mOnTopOfHome = false; return mStackSupervisor.resumeHomeActivity(null); if (task == tr && tr.isOverHomeStack() || numTasks <= 1 && isOnHomeDisplay()) { final int taskToReturnTo = tr.getTaskToReturnTo(); tr.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE); return mStackSupervisor.resumeHomeStackTask(taskToReturnTo, null); } mStackSupervisor.resumeTopActivitiesLocked(); Loading Loading @@ -3743,8 +3724,11 @@ final class ActivityStack { final int taskNdx = mTaskHistory.indexOf(task); final int topTaskNdx = mTaskHistory.size() - 1; if (task.mOnTopOfHome && taskNdx < topTaskNdx) { mTaskHistory.get(taskNdx + 1).mOnTopOfHome = true; if (task.isOverHomeStack() && taskNdx < topTaskNdx) { final TaskRecord nextTask = mTaskHistory.get(taskNdx + 1); if (!nextTask.isOverHomeStack()) { nextTask.setTaskToReturnTo(HOME_ACTIVITY_TYPE); } } mTaskHistory.remove(task); updateTaskMovement(task, true); Loading
services/core/java/com/android/server/am/ActivityStackSupervisor.java +29 −12 Original line number Diff line number Diff line Loading @@ -31,6 +31,9 @@ import static com.android.server.am.ActivityManagerService.DEBUG_TASKS; import static com.android.server.am.ActivityManagerService.DEBUG_USER_LEAVING; import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG; import static com.android.server.am.ActivityManagerService.TAG; 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.APPLICATION_ACTIVITY_TYPE; import android.app.Activity; import android.app.ActivityManager; Loading Loading @@ -318,18 +321,27 @@ public final class ActivityStackSupervisor implements DisplayListener { } } void moveHomeToTop() { void moveHomeStackTaskToTop(int homeStackTaskType) { if (homeStackTaskType == RECENTS_ACTIVITY_TYPE) { mWindowManager.showRecentApps(); return; } moveHomeStack(true); mHomeStack.moveHomeTaskToTop(); mHomeStack.moveHomeStackTaskToTop(homeStackTaskType); } boolean resumeHomeActivity(ActivityRecord prev) { moveHomeToTop(); boolean resumeHomeStackTask(int homeStackTaskType, ActivityRecord prev) { if (homeStackTaskType == RECENTS_ACTIVITY_TYPE) { mWindowManager.showRecentApps(); return false; } moveHomeStackTaskToTop(homeStackTaskType); if (prev != null) { prev.task.mOnTopOfHome = false; prev.task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE); } ActivityRecord r = mHomeStack.topRunningActivityLocked(null); if (r != null && r.isHomeActivity()) { if (r != null && (r.isHomeActivity() || r.isRecentsActivity())) { mService.setFocusedActivityLocked(r); return resumeTopActivitiesLocked(mHomeStack, prev, null); } Loading Loading @@ -683,7 +695,7 @@ public final class ActivityStackSupervisor implements DisplayListener { } void startHomeActivity(Intent intent, ActivityInfo aInfo) { moveHomeToTop(); moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE); startActivityLocked(null, intent, null, aInfo, null, null, null, null, 0, 0, 0, null, 0, null, false, null, null); } Loading Loading @@ -1615,7 +1627,7 @@ public final class ActivityStackSupervisor implements DisplayListener { (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) { // Caller wants to appear on home activity. intentActivity.task.mOnTopOfHome = true; intentActivity.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE); } options = null; } Loading Loading @@ -1799,6 +1811,11 @@ public final class ActivityStackSupervisor implements DisplayListener { newTaskInfo != null ? newTaskInfo : r.info, newTaskIntent != null ? newTaskIntent : intent, voiceSession, voiceInteractor, true), null, true); if (sourceRecord == null) { // Launched from a service or notification or task that is finishing. r.task.setTaskToReturnTo(isFrontStack(mHomeStack) ? mHomeStack.topTask().taskType : RECENTS_ACTIVITY_TYPE); } if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " + r.task); } else { Loading @@ -1811,7 +1828,7 @@ public final class ActivityStackSupervisor implements DisplayListener { == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) { // Caller wants to appear on home activity, so before starting // their own activity we will bring home to the front. r.task.mOnTopOfHome = r.task.stack.isOnHomeDisplay(); r.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE); } } } else if (sourceRecord != null) { Loading Loading @@ -2162,7 +2179,7 @@ public final class ActivityStackSupervisor implements DisplayListener { if ((flags & ActivityManager.MOVE_TASK_WITH_HOME) != 0) { // Caller wants the home activity moved with it. To accomplish this, // we'll just indicate that this task returns to the home task. task.mOnTopOfHome = true; task.setTaskToReturnTo(HOME_ACTIVITY_TYPE); } task.stack.moveTaskToFrontLocked(task, null, options); if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack=" Loading Loading @@ -2273,7 +2290,7 @@ public final class ActivityStackSupervisor implements DisplayListener { } mWindowManager.addTask(taskId, stackId, false); } resumeHomeActivity(null); resumeHomeStackTask(HOME_ACTIVITY_TYPE, null); } void moveTaskToStack(int taskId, int stackId, boolean toTop) { Loading Loading @@ -2530,7 +2547,7 @@ public final class ActivityStackSupervisor implements DisplayListener { } } else { // Stack was moved to another display while user was swapped out. resumeHomeActivity(null); resumeHomeStackTask(HOME_ACTIVITY_TYPE, null); } return homeInFront; } Loading
services/core/java/com/android/server/am/TaskRecord.java +27 −17 Original line number Diff line number Diff line Loading @@ -17,6 +17,9 @@ package com.android.server.am; import static com.android.server.am.ActivityManagerService.TAG; import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE; import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE; import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE; import static com.android.server.am.ActivityStackSupervisor.DEBUG_ADD_REMOVE; import android.app.Activity; Loading Loading @@ -54,7 +57,6 @@ final class TaskRecord extends ThumbnailHolder { private static final String ATTR_ASKEDCOMPATMODE = "asked_compat_mode"; private static final String ATTR_USERID = "user_id"; private static final String ATTR_TASKTYPE = "task_type"; private static final String ATTR_ONTOPOFHOME = "on_top_of_home"; private static final String ATTR_LASTDESCRIPTION = "last_description"; private static final String ATTR_LASTTIMEMOVED = "last_time_moved"; Loading Loading @@ -104,9 +106,11 @@ final class TaskRecord extends ThumbnailHolder { /** True if persistable, has changed, and has not yet been persisted */ boolean needsPersisting = false; /** Launch the home activity when leaving this task. Will be false for tasks that are not on * Display.DEFAULT_DISPLAY. */ boolean mOnTopOfHome = false; /** Indication of what to run next when task exits. Use ActivityRecord types. * ActivityRecord.APPLICATION_ACTIVITY_TYPE indicates to resume the task below this one in the * task stack. */ private int mTaskToReturnTo = APPLICATION_ACTIVITY_TYPE; final ActivityManagerService mService; Loading @@ -123,9 +127,8 @@ final class TaskRecord extends ThumbnailHolder { TaskRecord(ActivityManagerService service, int _taskId, Intent _intent, Intent _affinityIntent, String _affinity, ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset, boolean _askedCompatMode, int _taskType, boolean _onTopOfHome, int _userId, String _lastDescription, ArrayList<ActivityRecord> activities, long lastTimeMoved) { boolean _rootWasReset, boolean _askedCompatMode, int _taskType, int _userId, String _lastDescription, ArrayList<ActivityRecord> activities, long lastTimeMoved) { mService = service; taskId = _taskId; intent = _intent; Loading @@ -138,7 +141,7 @@ final class TaskRecord extends ThumbnailHolder { rootWasReset = _rootWasReset; askedCompatMode = _askedCompatMode; taskType = _taskType; mOnTopOfHome = _onTopOfHome; mTaskToReturnTo = HOME_ACTIVITY_TYPE; userId = _userId; lastDescription = _lastDescription; mActivities = activities; Loading Loading @@ -206,6 +209,14 @@ final class TaskRecord extends ThumbnailHolder { } } void setTaskToReturnTo(int taskToReturnTo) { mTaskToReturnTo = taskToReturnTo; } int getTaskToReturnTo() { return mTaskToReturnTo; } void disposeThumbnail() { super.disposeThumbnail(); for (int i=mActivities.size()-1; i>=0; i--) { Loading Loading @@ -477,11 +488,15 @@ final class TaskRecord extends ThumbnailHolder { } boolean isHomeTask() { return taskType == ActivityRecord.HOME_ACTIVITY_TYPE; return taskType == HOME_ACTIVITY_TYPE; } boolean isApplicationTask() { return taskType == ActivityRecord.APPLICATION_ACTIVITY_TYPE; return taskType == APPLICATION_ACTIVITY_TYPE; } boolean isOverHomeStack() { return mTaskToReturnTo == HOME_ACTIVITY_TYPE || mTaskToReturnTo == RECENTS_ACTIVITY_TYPE; } public TaskAccessInfo getTaskAccessInfoLocked() { Loading Loading @@ -623,7 +638,6 @@ final class TaskRecord extends ThumbnailHolder { out.attribute(null, ATTR_ASKEDCOMPATMODE, String.valueOf(askedCompatMode)); out.attribute(null, ATTR_USERID, String.valueOf(userId)); out.attribute(null, ATTR_TASKTYPE, String.valueOf(taskType)); out.attribute(null, ATTR_ONTOPOFHOME, String.valueOf(mOnTopOfHome)); out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved)); if (lastDescription != null) { out.attribute(null, ATTR_LASTDESCRIPTION, lastDescription.toString()); Loading Loading @@ -669,7 +683,6 @@ final class TaskRecord extends ThumbnailHolder { boolean rootHasReset = false; boolean askedCompatMode = false; int taskType = ActivityRecord.APPLICATION_ACTIVITY_TYPE; boolean onTopOfHome = true; int userId = 0; String lastDescription = null; long lastTimeOnTop = 0; Loading Loading @@ -697,8 +710,6 @@ final class TaskRecord extends ThumbnailHolder { userId = Integer.valueOf(attrValue); } else if (ATTR_TASKTYPE.equals(attrName)) { taskType = Integer.valueOf(attrValue); } else if (ATTR_ONTOPOFHOME.equals(attrName)) { onTopOfHome = Boolean.valueOf(attrValue); } else if (ATTR_LASTDESCRIPTION.equals(attrName)) { lastDescription = attrValue; } else if (ATTR_LASTTIMEMOVED.equals(attrName)) { Loading Loading @@ -736,8 +747,7 @@ final class TaskRecord extends ThumbnailHolder { final TaskRecord task = new TaskRecord(stackSupervisor.mService, taskId, intent, affinityIntent, affinity, realActivity, origActivity, rootHasReset, askedCompatMode, taskType, onTopOfHome, userId, lastDescription, activities, lastTimeOnTop); askedCompatMode, taskType, userId, lastDescription, activities, lastTimeOnTop); for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) { final ActivityRecord r = activities.get(activityNdx); Loading @@ -756,7 +766,7 @@ final class TaskRecord extends ThumbnailHolder { pw.print(" userId="); pw.print(userId); pw.print(" taskType="); pw.print(taskType); pw.print(" numFullscreen="); pw.print(numFullscreen); pw.print(" mOnTopOfHome="); pw.println(mOnTopOfHome); pw.print(" mTaskToReturnTo="); pw.println(mTaskToReturnTo); } if (affinity != null) { pw.print(prefix); pw.print("affinity="); pw.println(affinity); Loading