summaryrefslogtreecommitdiff
path: root/com/android/server/am
diff options
context:
space:
mode:
Diffstat (limited to 'com/android/server/am')
-rw-r--r--com/android/server/am/ActivityDisplay.java150
-rw-r--r--com/android/server/am/ActivityManagerDebugConfig.java8
-rw-r--r--com/android/server/am/ActivityManagerService.java640
-rw-r--r--com/android/server/am/ActivityManagerShellCommand.java100
-rw-r--r--com/android/server/am/ActivityMetricsLogger.java3
-rw-r--r--com/android/server/am/ActivityRecord.java72
-rw-r--r--com/android/server/am/ActivityStack.java215
-rw-r--r--com/android/server/am/ActivityStackSupervisor.java528
-rw-r--r--com/android/server/am/ActivityStarter.java133
-rw-r--r--com/android/server/am/AppTaskImpl.java150
-rw-r--r--com/android/server/am/BatteryStatsService.java25
-rw-r--r--com/android/server/am/BroadcastFilter.java24
-rw-r--r--com/android/server/am/BroadcastQueue.java52
-rw-r--r--com/android/server/am/BroadcastRecord.java11
-rw-r--r--com/android/server/am/KeyguardController.java10
-rw-r--r--com/android/server/am/LaunchingTaskPositioner.java211
-rw-r--r--com/android/server/am/LockTaskController.java10
-rw-r--r--com/android/server/am/ProcessRecord.java18
-rw-r--r--com/android/server/am/ReceiverList.java31
-rw-r--r--com/android/server/am/RecentTasks.java1040
-rw-r--r--com/android/server/am/ServiceRecord.java20
-rw-r--r--com/android/server/am/TaskPersister.java19
-rw-r--r--com/android/server/am/TaskRecord.java135
23 files changed, 2035 insertions, 1570 deletions
diff --git a/com/android/server/am/ActivityDisplay.java b/com/android/server/am/ActivityDisplay.java
index 8bcbfbef..6ed05552 100644
--- a/com/android/server/am/ActivityDisplay.java
+++ b/com/android/server/am/ActivityDisplay.java
@@ -16,9 +16,7 @@
package com.android.server.am;
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-import static android.app.ActivityManager.StackId.getStackIdForWindowingMode;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
@@ -48,13 +46,14 @@ import android.view.Display;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.wm.ConfigurationContainer;
+import java.io.PrintWriter;
import java.util.ArrayList;
/**
* Exactly one of these classes per Display in the system. Capable of holding zero or more
* attached {@link ActivityStack}s.
*/
-class ActivityDisplay extends ConfigurationContainer {
+class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityDisplay" : TAG_AM;
private static final String TAG_STACK = TAG + POSTFIX_STACK;
@@ -68,7 +67,7 @@ class ActivityDisplay extends ConfigurationContainer {
/** All of the stacks on this display. Order matters, topmost stack is in front of all other
* stacks, bottommost behind. Accessed directly by ActivityManager package classes */
- final ArrayList<ActivityStack> mStacks = new ArrayList<>();
+ private final ArrayList<ActivityStack> mStacks = new ArrayList<>();
/** Array of all UIDs that are present on the display. */
private IntArray mDisplayAccessUIDs = new IntArray();
@@ -80,6 +79,13 @@ class ActivityDisplay extends ConfigurationContainer {
private boolean mSleeping;
+ // Cached reference to some special stacks we tend to get a lot so we don't need to loop
+ // through the list to find them.
+ private ActivityStack mHomeStack = null;
+ private ActivityStack mRecentsStack = null;
+ private ActivityStack mPinnedStack = null;
+ private ActivityStack mSplitScreenPrimaryStack = null;
+
ActivityDisplay(ActivityStackSupervisor supervisor, int displayId) {
mSupervisor = supervisor;
mDisplayId = displayId;
@@ -98,6 +104,7 @@ class ActivityDisplay extends ConfigurationContainer {
}
if (DEBUG_STACK) Slog.v(TAG_STACK, "addChild: attaching " + stack
+ " to displayId=" + mDisplayId + " position=" + position);
+ addStackReferenceIfNeeded(stack);
positionChildAt(stack, position);
mSupervisor.mService.updateSleepIfNeededLocked();
}
@@ -106,6 +113,7 @@ class ActivityDisplay extends ConfigurationContainer {
if (DEBUG_STACK) Slog.v(TAG_STACK, "removeChild: detaching " + stack
+ " from displayId=" + mDisplayId);
mStacks.remove(stack);
+ removeStackReferenceIfNeeded(stack);
mSupervisor.mService.updateSleepIfNeededLocked();
}
@@ -150,6 +158,16 @@ class ActivityDisplay extends ConfigurationContainer {
* @see ConfigurationContainer#isCompatible(int, int)
*/
<T extends ActivityStack> T getStack(int windowingMode, int activityType) {
+ if (activityType == ACTIVITY_TYPE_HOME) {
+ return (T) mHomeStack;
+ } else if (activityType == ACTIVITY_TYPE_RECENTS) {
+ return (T) mRecentsStack;
+ }
+ if (windowingMode == WINDOWING_MODE_PINNED) {
+ return (T) mPinnedStack;
+ } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
+ return (T) mSplitScreenPrimaryStack;
+ }
for (int i = mStacks.size() - 1; i >= 0; --i) {
final ActivityStack stack = mStacks.get(i);
// TODO: Should undefined windowing and activity type be compatible with standard type?
@@ -213,10 +231,14 @@ class ActivityDisplay extends ConfigurationContainer {
if (windowingMode == WINDOWING_MODE_UNDEFINED) {
// TODO: Should be okay to have stacks with with undefined windowing mode long term, but
// have to set them to something for now due to logic that depending on them.
- windowingMode = WINDOWING_MODE_FULLSCREEN;
+ windowingMode = getWindowingMode(); // Put in current display's windowing mode
+ if (windowingMode == WINDOWING_MODE_UNDEFINED) {
+ // Else fullscreen for now...
+ windowingMode = WINDOWING_MODE_FULLSCREEN;
+ }
}
- final boolean inSplitScreenMode = hasSplitScreenStack();
+ final boolean inSplitScreenMode = hasSplitScreenPrimaryStack();
if (!inSplitScreenMode
&& windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY) {
// Switch to fullscreen windowing mode if we are not in split-screen mode and we are
@@ -228,24 +250,7 @@ class ActivityDisplay extends ConfigurationContainer {
windowingMode = WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
}
- int stackId = INVALID_STACK_ID;
- if (mDisplayId == DEFAULT_DISPLAY && (activityType == ACTIVITY_TYPE_STANDARD
- || activityType == ACTIVITY_TYPE_UNDEFINED)) {
- // TODO: Will be removed once we are no longer using static stack ids.
- stackId = getStackIdForWindowingMode(windowingMode);
- if (stackId == INVALID_STACK_ID) {
- // Whatever...put in fullscreen stack for now.
- stackId = FULLSCREEN_WORKSPACE_STACK_ID;
- }
- final T stack = getStack(stackId);
- if (stack != null) {
- return stack;
- }
- }
-
- if (stackId == INVALID_STACK_ID) {
- stackId = mSupervisor.getNextStackId();
- }
+ final int stackId = mSupervisor.getNextStackId();
final T stack = createStackUnchecked(windowingMode, activityType, stackId, onTop);
@@ -291,7 +296,7 @@ class ActivityDisplay extends ConfigurationContainer {
if (stack.getWindowingMode() != windowingMode) {
continue;
}
- mSupervisor.removeStackLocked(stack.mStackId);
+ mSupervisor.removeStack(stack);
}
}
}
@@ -306,12 +311,63 @@ class ActivityDisplay extends ConfigurationContainer {
for (int i = mStacks.size() - 1; i >= 0; --i) {
final ActivityStack stack = mStacks.get(i);
if (stack.getActivityType() == activityType) {
- mSupervisor.removeStackLocked(stack.mStackId);
+ mSupervisor.removeStack(stack);
}
}
}
}
+ void onStackWindowingModeChanged(ActivityStack stack) {
+ removeStackReferenceIfNeeded(stack);
+ addStackReferenceIfNeeded(stack);
+ }
+
+ private void addStackReferenceIfNeeded(ActivityStack stack) {
+ final int activityType = stack.getActivityType();
+ final int windowingMode = stack.getWindowingMode();
+
+ if (activityType == ACTIVITY_TYPE_HOME) {
+ if (mHomeStack != null && mHomeStack != stack) {
+ throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
+ + mHomeStack + " already exist on display=" + this + " stack=" + stack);
+ }
+ mHomeStack = stack;
+ } else if (activityType == ACTIVITY_TYPE_RECENTS) {
+ if (mRecentsStack != null && mRecentsStack != stack) {
+ throw new IllegalArgumentException("addStackReferenceIfNeeded: recents stack="
+ + mRecentsStack + " already exist on display=" + this + " stack=" + stack);
+ }
+ mRecentsStack = stack;
+ }
+ if (windowingMode == WINDOWING_MODE_PINNED) {
+ if (mPinnedStack != null && mPinnedStack != stack) {
+ throw new IllegalArgumentException("addStackReferenceIfNeeded: pinned stack="
+ + mPinnedStack + " already exist on display=" + this
+ + " stack=" + stack);
+ }
+ mPinnedStack = stack;
+ } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
+ if (mSplitScreenPrimaryStack != null && mSplitScreenPrimaryStack != stack) {
+ throw new IllegalArgumentException("addStackReferenceIfNeeded:"
+ + " split-screen-primary" + " stack=" + mSplitScreenPrimaryStack
+ + " already exist on display=" + this + " stack=" + stack);
+ }
+ mSplitScreenPrimaryStack = stack;
+ }
+ }
+
+ private void removeStackReferenceIfNeeded(ActivityStack stack) {
+ if (stack == mHomeStack) {
+ mHomeStack = null;
+ } else if (stack == mRecentsStack) {
+ mRecentsStack = null;
+ } else if (stack == mPinnedStack) {
+ mPinnedStack = null;
+ } else if (stack == mSplitScreenPrimaryStack) {
+ mSplitScreenPrimaryStack = null;
+ }
+ }
+
/** Returns the top visible stack activity type that isn't in the exclude windowing mode. */
int getTopVisibleStackActivityType(int excludeWindowingMode) {
for (int i = mStacks.size() - 1; i >= 0; --i) {
@@ -326,20 +382,42 @@ class ActivityDisplay extends ConfigurationContainer {
return ACTIVITY_TYPE_UNDEFINED;
}
- ActivityStack getSplitScreenStack() {
- return getStack(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
+ /**
+ * Get the topmost stack on the display. It may be different from focused stack, because
+ * focus may be on another display.
+ */
+ ActivityStack getTopStack() {
+ return mStacks.isEmpty() ? null : mStacks.get(mStacks.size() - 1);
}
- boolean hasSplitScreenStack() {
- return getSplitScreenStack() != null;
+ boolean isTopStack(ActivityStack stack) {
+ return stack == getTopStack();
+ }
+
+ int getIndexOf(ActivityStack stack) {
+ return mStacks.indexOf(stack);
+ }
+
+ void onLockTaskPackagesUpdated() {
+ for (int i = mStacks.size() - 1; i >= 0; --i) {
+ mStacks.get(i).onLockTaskPackagesUpdated();
+ }
+ }
+
+ ActivityStack getSplitScreenPrimaryStack() {
+ return mSplitScreenPrimaryStack;
+ }
+
+ boolean hasSplitScreenPrimaryStack() {
+ return mSplitScreenPrimaryStack != null;
}
PinnedActivityStack getPinnedStack() {
- return getStack(WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
+ return (PinnedActivityStack) mPinnedStack;
}
boolean hasPinnedStack() {
- return getPinnedStack() != null;
+ return mPinnedStack != null;
}
@Override
@@ -353,7 +431,7 @@ class ActivityDisplay extends ConfigurationContainer {
}
@Override
- protected ConfigurationContainer getChildAt(int index) {
+ protected ActivityStack getChildAt(int index) {
return mStacks.get(index);
}
@@ -401,6 +479,10 @@ class ActivityDisplay extends ConfigurationContainer {
mSleeping = asleep;
}
+ public void dump(PrintWriter pw, String prefix) {
+ pw.println(prefix + "displayId=" + mDisplayId + " mStacks=" + mStacks);
+ }
+
public void writeToProto(ProtoOutputStream proto, long fieldId) {
final long token = proto.start(fieldId);
super.writeToProto(proto, CONFIGURATION_CONTAINER);
diff --git a/com/android/server/am/ActivityManagerDebugConfig.java b/com/android/server/am/ActivityManagerDebugConfig.java
index 3a9bf125..ceb2ad62 100644
--- a/com/android/server/am/ActivityManagerDebugConfig.java
+++ b/com/android/server/am/ActivityManagerDebugConfig.java
@@ -59,7 +59,6 @@ class ActivityManagerDebugConfig {
static final boolean DEBUG_FOCUS = false;
static final boolean DEBUG_IDLE = DEBUG_ALL_ACTIVITIES || false;
static final boolean DEBUG_IMMERSIVE = DEBUG_ALL || false;
- static final boolean DEBUG_LOCKSCREEN = DEBUG_ALL || false;
static final boolean DEBUG_LOCKTASK = DEBUG_ALL || false;
static final boolean DEBUG_LRU = DEBUG_ALL || false;
static final boolean DEBUG_MU = DEBUG_ALL || false;
@@ -74,10 +73,10 @@ class ActivityManagerDebugConfig {
static final boolean DEBUG_PROVIDER = DEBUG_ALL || false;
static final boolean DEBUG_PSS = DEBUG_ALL || false;
static final boolean DEBUG_RECENTS = DEBUG_ALL || false;
+ static final boolean DEBUG_RECENTS_TRIM_TASKS = DEBUG_RECENTS || false;
static final boolean DEBUG_RELEASE = DEBUG_ALL_ACTIVITIES || false;
static final boolean DEBUG_RESULTS = DEBUG_ALL || false;
static final boolean DEBUG_SAVED_STATE = DEBUG_ALL_ACTIVITIES || false;
- static final boolean DEBUG_SCREENSHOTS = DEBUG_ALL_ACTIVITIES || false;
static final boolean DEBUG_SERVICE = DEBUG_ALL || false;
static final boolean DEBUG_FOREGROUND_SERVICE = DEBUG_ALL || false;
static final boolean DEBUG_SERVICE_EXECUTING = DEBUG_ALL || false;
@@ -85,7 +84,6 @@ class ActivityManagerDebugConfig {
static final boolean DEBUG_STATES = DEBUG_ALL_ACTIVITIES || false;
static final boolean DEBUG_SWITCH = DEBUG_ALL || false;
static final boolean DEBUG_TASKS = DEBUG_ALL || false;
- static final boolean DEBUG_THUMBNAILS = DEBUG_ALL || false;
static final boolean DEBUG_TRANSITION = DEBUG_ALL || false;
static final boolean DEBUG_UID_OBSERVERS = DEBUG_ALL || false;
static final boolean DEBUG_URI_PERMISSION = DEBUG_ALL || false;
@@ -105,7 +103,6 @@ class ActivityManagerDebugConfig {
static final String POSTFIX_FOCUS = (APPEND_CATEGORY_NAME) ? "_Focus" : "";
static final String POSTFIX_IDLE = (APPEND_CATEGORY_NAME) ? "_Idle" : "";
static final String POSTFIX_IMMERSIVE = (APPEND_CATEGORY_NAME) ? "_Immersive" : "";
- static final String POSTFIX_LOCKSCREEN = (APPEND_CATEGORY_NAME) ? "_LockScreen" : "";
static final String POSTFIX_LOCKTASK = (APPEND_CATEGORY_NAME) ? "_LockTask" : "";
static final String POSTFIX_LRU = (APPEND_CATEGORY_NAME) ? "_LRU" : "";
static final String POSTFIX_MU = "_MU";
@@ -122,7 +119,6 @@ class ActivityManagerDebugConfig {
static final String POSTFIX_RELEASE = (APPEND_CATEGORY_NAME) ? "_Release" : "";
static final String POSTFIX_RESULTS = (APPEND_CATEGORY_NAME) ? "_Results" : "";
static final String POSTFIX_SAVED_STATE = (APPEND_CATEGORY_NAME) ? "_SavedState" : "";
- static final String POSTFIX_SCREENSHOTS = (APPEND_CATEGORY_NAME) ? "_Screenshots" : "";
static final String POSTFIX_SERVICE = (APPEND_CATEGORY_NAME) ? "_Service" : "";
static final String POSTFIX_SERVICE_EXECUTING =
(APPEND_CATEGORY_NAME) ? "_ServiceExecuting" : "";
@@ -130,13 +126,11 @@ class ActivityManagerDebugConfig {
static final String POSTFIX_STATES = (APPEND_CATEGORY_NAME) ? "_States" : "";
static final String POSTFIX_SWITCH = (APPEND_CATEGORY_NAME) ? "_Switch" : "";
static final String POSTFIX_TASKS = (APPEND_CATEGORY_NAME) ? "_Tasks" : "";
- static final String POSTFIX_THUMBNAILS = (APPEND_CATEGORY_NAME) ? "_Thumbnails" : "";
static final String POSTFIX_TRANSITION = (APPEND_CATEGORY_NAME) ? "_Transition" : "";
static final String POSTFIX_UID_OBSERVERS = (APPEND_CATEGORY_NAME)
? "_UidObservers" : "";
static final String POSTFIX_URI_PERMISSION = (APPEND_CATEGORY_NAME) ? "_UriPermission" : "";
static final String POSTFIX_USER_LEAVING = (APPEND_CATEGORY_NAME) ? "_UserLeaving" : "";
static final String POSTFIX_VISIBILITY = (APPEND_CATEGORY_NAME) ? "_Visibility" : "";
- static final String POSTFIX_VISIBLE_BEHIND = (APPEND_CATEGORY_NAME) ? "_VisibleBehind" : "";
}
diff --git a/com/android/server/am/ActivityManagerService.java b/com/android/server/am/ActivityManagerService.java
index e6fe6204..f17c9ac3 100644
--- a/com/android/server/am/ActivityManagerService.java
+++ b/com/android/server/am/ActivityManagerService.java
@@ -27,18 +27,10 @@ import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.ActivityManager.RESIZE_MODE_PRESERVE_WINDOW;
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.FIRST_DYNAMIC_STACK_ID;
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
-import static android.app.ActivityManager.StackId.getWindowingModeForStackId;
-import static android.app.ActivityManager.StackId.isStaticStack;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.content.pm.PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS;
@@ -57,6 +49,9 @@ import static android.content.res.Configuration.UI_MODE_TYPE_TELEVISION;
import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode;
import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground;
import static android.os.Build.VERSION_CODES.N;
+import static android.os.IServiceManager.DUMP_PRIORITY_CRITICAL;
+import static android.os.IServiceManager.DUMP_PRIORITY_HIGH;
+import static android.os.IServiceManager.DUMP_PRIORITY_NORMAL;
import static android.os.Process.BLUETOOTH_UID;
import static android.os.Process.FIRST_APPLICATION_UID;
import static android.os.Process.FIRST_ISOLATED_UID;
@@ -137,7 +132,6 @@ import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESSES;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROCESS_OBSERVERS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PROVIDER;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PSS;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SERVICE;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH;
@@ -182,7 +176,6 @@ import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
import static com.android.server.am.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
-import static com.android.server.am.proto.ActivityManagerServiceProto.ACTIVITIES;
import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_OPEN;
import static com.android.server.wm.AppTransition.TRANSIT_NONE;
import static com.android.server.wm.AppTransition.TRANSIT_TASK_IN_PLACE;
@@ -199,7 +192,6 @@ import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
-import android.app.ActivityManager.StackId;
import android.app.ActivityManager.StackInfo;
import android.app.ActivityManager.TaskSnapshot;
import android.app.ActivityManagerInternal;
@@ -216,7 +208,6 @@ import android.app.ContentProviderHolder;
import android.app.Dialog;
import android.app.IActivityController;
import android.app.IActivityManager;
-import android.app.IAppTask;
import android.app.IApplicationThread;
import android.app.IInstrumentationWatcher;
import android.app.INotificationManager;
@@ -404,6 +395,9 @@ import com.android.server.SystemServiceManager;
import com.android.server.ThreadPriorityBooster;
import com.android.server.Watchdog;
import com.android.server.am.ActivityStack.ActivityState;
+import com.android.server.am.proto.ActivityManagerServiceProto;
+import com.android.server.am.proto.BroadcastProto;
+import com.android.server.am.proto.StickyBroadcastProto;
import com.android.server.firewall.IntentFirewall;
import com.android.server.job.JobSchedulerInternal;
import com.android.server.pm.Installer;
@@ -739,9 +733,6 @@ public class ActivityManagerService extends IActivityManager.Stub
doDump(fd, pw, new String[] {"associations"});
}
doDump(fd, pw, new String[] {"processes"});
- doDump(fd, pw, new String[] {"-v", "all"});
- doDump(fd, pw, new String[] {"service", "all"});
- doDump(fd, pw, new String[] {"provider", "all"});
}
@Override
@@ -753,6 +744,8 @@ public class ActivityManagerService extends IActivityManager.Stub
public boolean canShowErrorDialogs() {
return mShowDialogs && !mSleeping && !mShuttingDown
&& !mKeyguardController.isKeyguardShowing(DEFAULT_DISPLAY)
+ && !mUserController.hasUserRestriction(UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS,
+ mUserController.getCurrentUserId())
&& !(UserManager.isDeviceInDemoMode(mContext)
&& mUserController.getCurrentUser().isDemo());
}
@@ -1717,7 +1710,6 @@ public class ActivityManagerService extends IActivityManager.Stub
static final int PUSH_TEMP_WHITELIST_UI_MSG = 68;
static final int SERVICE_FOREGROUND_CRASH_MSG = 69;
static final int DISPATCH_OOM_ADJ_OBSERVER_MSG = 70;
- static final int TOP_APP_KILLED_BY_LMK_MSG = 73;
static final int NOTIFY_VR_KEYGUARD_MSG = 74;
static final int FIRST_ACTIVITY_STACK_MSG = 100;
@@ -1738,9 +1730,6 @@ public class ActivityManagerService extends IActivityManager.Stub
*/
private boolean mUserIsMonkey;
- /** Flag whether the device has a Recents UI */
- boolean mHasRecents;
-
/** The dimensions of the thumbnails in the Recents UI. */
int mThumbnailWidth;
int mThumbnailHeight;
@@ -1946,17 +1935,6 @@ public class ActivityManagerService extends IActivityManager.Stub
dispatchProcessDied(pid, uid);
break;
}
- case TOP_APP_KILLED_BY_LMK_MSG: {
- final String appName = (String) msg.obj;
- final AlertDialog d = new BaseErrorDialog(mUiContext);
- d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
- d.setTitle(mUiContext.getText(R.string.top_app_killed_title));
- d.setMessage(mUiContext.getString(R.string.top_app_killed_message, appName));
- d.setButton(DialogInterface.BUTTON_POSITIVE, mUiContext.getText(R.string.close),
- obtainMessage(DISMISS_DIALOG_UI_MSG, d));
- d.show();
- break;
- }
case DISPATCH_UIDS_CHANGED_UI_MSG: {
dispatchUidsChanged();
} break;
@@ -2111,7 +2089,8 @@ public class ActivityManagerService extends IActivityManager.Stub
String text = mContext.getString(R.string.heavy_weight_notification,
context.getApplicationInfo().loadLabel(context.getPackageManager()));
Notification notification =
- new Notification.Builder(context, SystemNotificationChannels.DEVELOPER)
+ new Notification.Builder(context,
+ SystemNotificationChannels.HEAVY_WEIGHT_APP)
.setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
.setWhen(0)
.setOngoing(true)
@@ -2145,7 +2124,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
try {
inm.cancelNotificationWithTag("android", null,
- SystemMessage.NOTE_HEAVY_WEIGHT_NOTIFICATION, msg.arg1);
+ SystemMessage.NOTE_HEAVY_WEIGHT_NOTIFICATION, msg.arg1);
} catch (RuntimeException e) {
Slog.w(ActivityManagerService.TAG,
"Error canceling notification for service", e);
@@ -2503,13 +2482,16 @@ public class ActivityManagerService extends IActivityManager.Stub
public void setSystemProcess() {
try {
- ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
+ ServiceManager.addService(Context.ACTIVITY_SERVICE, this, /* allowIsolated= */ true,
+ DUMP_PRIORITY_CRITICAL | DUMP_PRIORITY_NORMAL);
ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
- ServiceManager.addService("meminfo", new MemBinder(this));
+ ServiceManager.addService("meminfo", new MemBinder(this), /* allowIsolated= */ false,
+ DUMP_PRIORITY_HIGH | DUMP_PRIORITY_NORMAL);
ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
ServiceManager.addService("dbinfo", new DbBinder(this));
if (MONITOR_CPU_USAGE) {
- ServiceManager.addService("cpuinfo", new CpuBinder(this));
+ ServiceManager.addService("cpuinfo", new CpuBinder(this),
+ /* allowIsolated= */ false, DUMP_PRIORITY_CRITICAL);
}
ServiceManager.addService("permission", new PermissionController(this));
ServiceManager.addService("processinfo", new ProcessInfoService(this));
@@ -2540,7 +2522,6 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized (this) {
mWindowManager = wm;
mStackSupervisor.setWindowManager(wm);
- mActivityStarter.setWindowManager(wm);
mLockTaskController.setWindowManager(wm);
}
}
@@ -2782,8 +2763,9 @@ public class ActivityManagerService extends IActivityManager.Stub
mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);
mTaskChangeNotificationController =
new TaskChangeNotificationController(this, mStackSupervisor, mHandler);
- mActivityStarter = new ActivityStarter(this, mStackSupervisor);
+ mActivityStarter = new ActivityStarter(this);
mRecentTasks = new RecentTasks(this, mStackSupervisor);
+ mStackSupervisor.setRecentTasks(mRecentTasks);
mLockTaskController = new LockTaskController(mContext, mStackSupervisor, mHandler);
mProcessCpuThread = new Thread("CpuTracker") {
@@ -3241,11 +3223,12 @@ public class ActivityManagerService extends IActivityManager.Stub
// stack implementation changes in the future, keep in mind that the use of the fullscreen
// stack is a means to move the activity to the main display and a moveActivityToDisplay()
// option would be a better choice here.
- if (r.requestedVrComponent != null && r.getStackId() >= FIRST_DYNAMIC_STACK_ID) {
+ if (r.requestedVrComponent != null && r.getDisplayId() != DEFAULT_DISPLAY) {
Slog.i(TAG, "Moving " + r.shortComponentName + " from stack " + r.getStackId()
+ " to main stack for VR");
- setTaskWindowingMode(r.getTask().taskId,
- WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY, true /* toTop */);
+ final ActivityStack stack = mStackSupervisor.getDefaultDisplay().getOrCreateStack(
+ WINDOWING_MODE_FULLSCREEN, r.getActivityType(), true /* toTop */);
+ moveTaskToStack(r.getTask().taskId, stack.mStackId, true /* toTop */);
}
mHandler.sendMessage(
mHandler.obtainMessage(VR_MODE_CHANGE_MSG, 0, 0, r));
@@ -5095,11 +5078,12 @@ public class ActivityManagerService extends IActivityManager.Stub
}
synchronized(this) {
- if (mHeavyWeightProcess == null) {
+ final ProcessRecord proc = mHeavyWeightProcess;
+ if (proc == null) {
return;
}
- ArrayList<ActivityRecord> activities = new ArrayList<>(mHeavyWeightProcess.activities);
+ ArrayList<ActivityRecord> activities = new ArrayList<>(proc.activities);
for (int i = 0; i < activities.size(); i++) {
ActivityRecord r = activities.get(i);
if (!r.finishing && r.isInStackLocked()) {
@@ -5109,7 +5093,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
- mHeavyWeightProcess.userId, 0));
+ proc.userId, 0));
mHeavyWeightProcess = null;
}
}
@@ -5428,7 +5412,6 @@ public class ActivityManagerService extends IActivityManager.Stub
boolean doLowMem = app.instr == null;
boolean doOomAdj = doLowMem;
if (!app.killedByAm) {
- maybeNotifyTopAppKilled(app);
Slog.i(TAG, "Process " + app.processName + " (pid " + pid + ") has died: "
+ ProcessList.makeOomAdjString(app.setAdj)
+ ProcessList.makeProcStateString(app.setProcState));
@@ -5462,23 +5445,6 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
- /** Show system error dialog when a top app is killed by LMK */
- void maybeNotifyTopAppKilled(ProcessRecord app) {
- if (!shouldNotifyTopAppKilled(app)) {
- return;
- }
-
- Message msg = mHandler.obtainMessage(TOP_APP_KILLED_BY_LMK_MSG);
- msg.obj = mContext.getPackageManager().getApplicationLabel(app.info);
- mUiHandler.sendMessage(msg);
- }
-
- /** Only show notification when the top app is killed on low ram devices */
- private boolean shouldNotifyTopAppKilled(ProcessRecord app) {
- return app.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP &&
- ActivityManager.isLowRamDeviceStatic();
- }
-
/**
* If a stack trace dump file is configured, dump process stack traces.
* @param clearTraces causes the dump file to be erased prior to the new
@@ -5963,16 +5929,7 @@ public class ActivityManagerService extends IActivityManager.Stub
if (appInfo != null) {
forceStopPackageLocked(packageName, appInfo.uid, "clear data");
- // Remove all tasks match the cleared application package and user
- for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
- final TaskRecord tr = mRecentTasks.get(i);
- final String taskPackageName =
- tr.getBaseIntent().getComponent().getPackageName();
- if (tr.userId != resolvedUserId) continue;
- if (!taskPackageName.equals(packageName)) continue;
- mStackSupervisor.removeTaskByIdLocked(tr.taskId, false,
- REMOVE_FROM_RECENTS);
- }
+ mRecentTasks.removeTasksByPackageName(packageName, resolvedUserId);
}
}
@@ -6553,7 +6510,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
// Clean-up disabled tasks
- cleanupDisabledPackageTasksLocked(packageName, disabledClasses, userId);
+ mRecentTasks.cleanupDisabledPackageTasksLocked(packageName, disabledClasses, userId);
// Clean-up disabled services.
mServices.bringDownDisabledPackageServicesLocked(
@@ -8084,8 +8041,8 @@ public class ActivityManagerService extends IActivityManager.Stub
}
private boolean isInPictureInPictureMode(ActivityRecord r) {
- if (r == null || r.getStack() == null || !r.getStack().isPinnedStack() ||
- r.getStack().isInStackLocked(r) == null) {
+ if (r == null || r.getStack() == null || !r.inPinnedWindowingMode()
+ || r.getStack().isInStackLocked(r) == null) {
return false;
}
@@ -8179,7 +8136,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// Only update the saved args from the args that are set
r.pictureInPictureArgs.copyOnlySet(params);
- if (r.getStack().getStackId() == PINNED_STACK_ID) {
+ if (r.inPinnedWindowingMode()) {
// If the activity is already in picture-in-picture, update the pinned stack now
// if it is not already expanding to fullscreen. Otherwise, the arguments will
// be used the next time the activity enters PiP
@@ -9800,35 +9757,12 @@ public class ActivityManagerService extends IActivityManager.Stub
public List<IBinder> getAppTasks(String callingPackage) {
int callingUid = Binder.getCallingUid();
long ident = Binder.clearCallingIdentity();
-
- synchronized(this) {
- ArrayList<IBinder> list = new ArrayList<IBinder>();
- try {
- if (DEBUG_ALL) Slog.v(TAG, "getAppTasks");
-
- final int N = mRecentTasks.size();
- for (int i = 0; i < N; i++) {
- TaskRecord tr = mRecentTasks.get(i);
- // Skip tasks that do not match the caller. We don't need to verify
- // callingPackage, because we are also limiting to callingUid and know
- // that will limit to the correct security sandbox.
- if (tr.effectiveUid != callingUid) {
- continue;
- }
- Intent intent = tr.getBaseIntent();
- if (intent == null ||
- !callingPackage.equals(intent.getComponent().getPackageName())) {
- continue;
- }
- ActivityManager.RecentTaskInfo taskInfo =
- createRecentTaskInfoFromTaskRecord(tr);
- AppTaskImpl taskImpl = new AppTaskImpl(taskInfo.persistentId, callingUid);
- list.add(taskImpl.asBinder());
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
+ try {
+ synchronized(this) {
+ return mRecentTasks.getAppTasksList(callingUid, callingPackage);
}
- return list;
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
}
@@ -9851,58 +9785,6 @@ public class ActivityManagerService extends IActivityManager.Stub
return list;
}
- /**
- * Creates a new RecentTaskInfo from a TaskRecord.
- */
- private ActivityManager.RecentTaskInfo createRecentTaskInfoFromTaskRecord(TaskRecord tr) {
- // Update the task description to reflect any changes in the task stack
- tr.updateTaskDescription();
-
- // Compose the recent task info
- ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo();
- rti.id = tr.getTopActivity() == null ? INVALID_TASK_ID : tr.taskId;
- rti.persistentId = tr.taskId;
- rti.baseIntent = new Intent(tr.getBaseIntent());
- rti.origActivity = tr.origActivity;
- rti.realActivity = tr.realActivity;
- rti.description = tr.lastDescription;
- rti.stackId = tr.getStackId();
- rti.userId = tr.userId;
- rti.taskDescription = new ActivityManager.TaskDescription(tr.lastTaskDescription);
- rti.firstActiveTime = tr.firstActiveTime;
- rti.lastActiveTime = tr.lastActiveTime;
- rti.affiliatedTaskId = tr.mAffiliatedTaskId;
- rti.affiliatedTaskColor = tr.mAffiliatedTaskColor;
- rti.numActivities = 0;
- if (tr.mBounds != null) {
- rti.bounds = new Rect(tr.mBounds);
- }
- rti.supportsSplitScreenMultiWindow = tr.supportsSplitScreenWindowingMode();
- rti.resizeMode = tr.mResizeMode;
- rti.configuration.setTo(tr.getConfiguration());
-
- ActivityRecord base = null;
- ActivityRecord top = null;
- ActivityRecord tmp;
-
- for (int i = tr.mActivities.size() - 1; i >= 0; --i) {
- tmp = tr.mActivities.get(i);
- if (tmp.finishing) {
- continue;
- }
- base = tmp;
- if (top == null || (top.state == ActivityState.INITIALIZING)) {
- top = base;
- }
- rti.numActivities++;
- }
-
- rti.baseActivity = (base != null) ? base.intent.getComponent() : null;
- rti.topActivity = (top != null) ? top.intent.getComponent() : null;
-
- return rti;
- }
-
private boolean isGetTasksAllowed(String caller, int callingPid, int callingUid) {
boolean allowed = checkPermission(android.Manifest.permission.REAL_GET_TASKS,
callingPid, callingUid) == PackageManager.PERMISSION_GRANTED;
@@ -9936,118 +9818,15 @@ public class ActivityManagerService extends IActivityManager.Stub
final int callingUid = Binder.getCallingUid();
userId = mUserController.handleIncomingUser(Binder.getCallingPid(), callingUid, userId,
false, ALLOW_FULL_ONLY, "getRecentTasks", null);
+ final boolean allowed = isGetTasksAllowed("getRecentTasks", Binder.getCallingPid(),
+ callingUid);
+ final boolean detailed = checkCallingPermission(
+ android.Manifest.permission.GET_DETAILED_TASKS)
+ == PackageManager.PERMISSION_GRANTED;
- final boolean includeProfiles = (flags & ActivityManager.RECENT_INCLUDE_PROFILES) != 0;
- final boolean withExcluded = (flags&ActivityManager.RECENT_WITH_EXCLUDED) != 0;
synchronized (this) {
- final boolean allowed = isGetTasksAllowed("getRecentTasks", Binder.getCallingPid(),
+ return mRecentTasks.getRecentTasks(maxNum, flags, allowed, detailed, userId,
callingUid);
- final boolean detailed = checkCallingPermission(
- android.Manifest.permission.GET_DETAILED_TASKS)
- == PackageManager.PERMISSION_GRANTED;
-
- if (!isUserRunning(userId, ActivityManager.FLAG_AND_UNLOCKED)) {
- Slog.i(TAG, "user " + userId + " is still locked. Cannot load recents");
- return ParceledListSlice.emptyList();
- }
- mRecentTasks.loadUserRecentsLocked(userId);
-
- final int recentsCount = mRecentTasks.size();
- ArrayList<ActivityManager.RecentTaskInfo> res =
- new ArrayList<>(maxNum < recentsCount ? maxNum : recentsCount);
-
- final Set<Integer> includedUsers;
- if (includeProfiles) {
- includedUsers = mUserController.getProfileIds(userId);
- } else {
- includedUsers = new HashSet<>();
- }
- includedUsers.add(Integer.valueOf(userId));
-
- for (int i = 0; i < recentsCount && maxNum > 0; i++) {
- TaskRecord tr = mRecentTasks.get(i);
- // Only add calling user or related users recent tasks
- if (!includedUsers.contains(Integer.valueOf(tr.userId))) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Skipping, not user: " + tr);
- continue;
- }
-
- if (tr.realActivitySuspended) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Skipping, activity suspended: " + tr);
- continue;
- }
-
- // Return the entry if desired by the caller. We always return
- // the first entry, because callers always expect this to be the
- // foreground app. We may filter others if the caller has
- // not supplied RECENT_WITH_EXCLUDED and there is some reason
- // we should exclude the entry.
-
- if (i == 0
- || withExcluded
- || (tr.intent == null)
- || ((tr.intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
- == 0)) {
- if (!allowed) {
- // If the caller doesn't have the GET_TASKS permission, then only
- // allow them to see a small subset of tasks -- their own and home.
- if (!tr.isActivityTypeHome() && tr.effectiveUid != callingUid) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Skipping, not allowed: " + tr);
- continue;
- }
- }
- final ActivityStack stack = tr.getStack();
- if ((flags & ActivityManager.RECENT_IGNORE_HOME_AND_RECENTS_STACK_TASKS) != 0) {
- if (stack != null && stack.isHomeOrRecentsStack()) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
- "Skipping, home or recents stack task: " + tr);
- continue;
- }
- }
- if ((flags & ActivityManager.RECENT_INGORE_DOCKED_STACK_TOP_TASK) != 0) {
- if (stack != null && stack.isDockedStack() && stack.topTask() == tr) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
- "Skipping, top task in docked stack: " + tr);
- continue;
- }
- }
- if ((flags & ActivityManager.RECENT_INGORE_PINNED_STACK_TASKS) != 0) {
- if (stack != null && stack.isPinnedStack()) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
- "Skipping, pinned stack task: " + tr);
- continue;
- }
- }
- if (tr.autoRemoveRecents && tr.getTopActivity() == null) {
- // Don't include auto remove tasks that are finished or finishing.
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
- "Skipping, auto-remove without activity: " + tr);
- continue;
- }
- if ((flags&ActivityManager.RECENT_IGNORE_UNAVAILABLE) != 0
- && !tr.isAvailable) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
- "Skipping, unavail real act: " + tr);
- continue;
- }
-
- if (!tr.mUserSetupComplete) {
- // Don't include task launched while user is not done setting-up.
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
- "Skipping, user setup not complete: " + tr);
- continue;
- }
-
- ActivityManager.RecentTaskInfo rti = createRecentTaskInfoFromTaskRecord(tr);
- if (!detailed) {
- rti.baseIntent.replaceExtras((Bundle)null);
- }
-
- res.add(rti);
- maxNum--;
- }
- }
- return new ParceledListSlice<>(res);
}
}
@@ -10119,23 +9898,10 @@ public class ActivityManagerService extends IActivityManager.Stub
TaskRecord task = new TaskRecord(this,
mStackSupervisor.getNextTaskIdForUserLocked(r.userId),
ainfo, intent, description);
-
- int trimIdx = mRecentTasks.trimForTaskLocked(task, false);
- if (trimIdx >= 0) {
- // If this would have caused a trim, then we'll abort because that
- // means it would be added at the end of the list but then just removed.
+ if (!mRecentTasks.addToBottom(task)) {
return INVALID_TASK_ID;
}
-
- final int N = mRecentTasks.size();
- if (N >= (ActivityManager.getMaxRecentTasksStatic()-1)) {
- final TaskRecord tr = mRecentTasks.remove(N - 1);
- tr.removedFromRecents();
- }
-
- task.inRecents = true;
- mRecentTasks.add(task);
- r.getStack().addTask(task, false, "addAppTask");
+ r.getStack().addTask(task, !ON_TOP, "addAppTask");
// TODO: Send the thumbnail to WM to store it.
@@ -10351,38 +10117,6 @@ public class ActivityManagerService extends IActivityManager.Stub
mWindowManager.executeAppTransition();
}
- private void removeTasksByPackageNameLocked(String packageName, int userId) {
- // Remove all tasks with activities in the specified package from the list of recent tasks
- for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
- TaskRecord tr = mRecentTasks.get(i);
- if (tr.userId != userId) continue;
-
- ComponentName cn = tr.intent.getComponent();
- if (cn != null && cn.getPackageName().equals(packageName)) {
- // If the package name matches, remove the task.
- mStackSupervisor.removeTaskByIdLocked(tr.taskId, true, REMOVE_FROM_RECENTS);
- }
- }
- }
-
- private void cleanupDisabledPackageTasksLocked(String packageName, Set<String> filterByClasses,
- int userId) {
-
- for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
- TaskRecord tr = mRecentTasks.get(i);
- if (userId != UserHandle.USER_ALL && tr.userId != userId) {
- continue;
- }
-
- ComponentName cn = tr.intent.getComponent();
- final boolean sameComponent = cn != null && cn.getPackageName().equals(packageName)
- && (filterByClasses == null || filterByClasses.contains(cn.getClassName()));
- if (sameComponent) {
- mStackSupervisor.removeTaskByIdLocked(tr.taskId, false, REMOVE_FROM_RECENTS);
- }
- }
- }
-
@Override
public void removeStack(int stackId) {
enforceCallingPermission(Manifest.permission.MANAGE_ACTIVITY_STACKS, "removeStack()");
@@ -10390,11 +10124,14 @@ public class ActivityManagerService extends IActivityManager.Stub
final long ident = Binder.clearCallingIdentity();
try {
final ActivityStack stack = mStackSupervisor.getStack(stackId);
- if (stack != null && !stack.isActivityTypeStandardOrUndefined()) {
+ if (stack == null) {
+ return;
+ }
+ if (!stack.isActivityTypeStandardOrUndefined()) {
throw new IllegalArgumentException(
"Removing non-standard stack is not allowed.");
}
- mStackSupervisor.removeStackLocked(stackId);
+ mStackSupervisor.removeStack(stack);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -10609,7 +10346,7 @@ public class ActivityManagerService extends IActivityManager.Stub
}
final ActivityStack stack = r.getStack();
- if (stack == null || stack.mStackId != FREEFORM_WORKSPACE_STACK_ID) {
+ if (stack == null || !stack.inFreeformWindowingMode()) {
throw new IllegalStateException(
"exitFreeformMode: You can only go fullscreen from freeform.");
}
@@ -10677,27 +10414,20 @@ public class ActivityManagerService extends IActivityManager.Stub
if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToStack: moving task=" + taskId
+ " to stackId=" + stackId + " toTop=" + toTop);
- if (stackId == DOCKED_STACK_ID) {
- mWindowManager.setDockedStackCreateState(DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT,
- null /* initialBounds */);
- }
- ActivityStack stack = mStackSupervisor.getStack(stackId);
+ final ActivityStack stack = mStackSupervisor.getStack(stackId);
if (stack == null) {
- if (!isStaticStack(stackId)) {
- throw new IllegalStateException(
- "moveTaskToStack: No stack for stackId=" + stackId);
- }
- final ActivityDisplay display = task.getStack().getDisplay();
- final int windowingMode =
- getWindowingModeForStackId(stackId, display.hasSplitScreenStack());
- stack = display.getOrCreateStack(windowingMode,
- task.getStack().getActivityType(), toTop);
+ throw new IllegalStateException(
+ "moveTaskToStack: No stack for stackId=" + stackId);
}
if (!stack.isActivityTypeStandardOrUndefined()) {
throw new IllegalArgumentException("moveTaskToStack: Attempt to move task "
+ taskId + " to stack " + stackId);
}
+ if (stack.inSplitScreenPrimaryWindowingMode()) {
+ mWindowManager.setDockedStackCreateState(
+ DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT, null /* initialBounds */);
+ }
task.reparent(stack, toTop, REPARENT_KEEP_STACK_AT_FRONT, ANIMATE, !DEFER_RESUME,
"moveTaskToStack");
} finally {
@@ -10767,9 +10497,9 @@ public class ActivityManagerService extends IActivityManager.Stub
try {
synchronized (this) {
final ActivityStack stack =
- mStackSupervisor.getDefaultDisplay().getSplitScreenStack();
+ mStackSupervisor.getDefaultDisplay().getSplitScreenPrimaryStack();
if (toTop) {
- mStackSupervisor.resizeStackLocked(stack.mStackId, null /* destBounds */,
+ mStackSupervisor.resizeStackLocked(stack, null /* destBounds */,
null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
true /* preserveWindows */, true /* allowResizeInDockedMode */,
!DEFER_RESUME);
@@ -10862,7 +10592,12 @@ public class ActivityManagerService extends IActivityManager.Stub
stack.animateResizePinnedStack(null /* sourceHintBounds */, destBounds,
animationDuration, false /* fromFullscreen */);
} else {
- mStackSupervisor.resizeStackLocked(stackId, destBounds, null /* tempTaskBounds */,
+ final ActivityStack stack = mStackSupervisor.getStack(stackId);
+ if (stack == null) {
+ Slog.w(TAG, "resizeStack: stackId " + stackId + " not found.");
+ return;
+ }
+ mStackSupervisor.resizeStackLocked(stack, destBounds, null /* tempTaskBounds */,
null /* tempTaskInsetBounds */, preserveWindows,
allowResizeInDockedMode, !DEFER_RESUME);
}
@@ -12938,6 +12673,10 @@ public class ActivityManagerService extends IActivityManager.Stub
throw new IllegalArgumentException("Provided bugreport type is not correct, value: "
+ bugreportType);
}
+ // Always log caller, even if it does not have permission to dump.
+ String type = extraOptions == null ? "bugreport" : extraOptions;
+ Slog.i(TAG, type + " requested by UID " + Binder.getCallingUid());
+
enforceCallingPermission(android.Manifest.permission.DUMP, "requestBugReport");
if (extraOptions != null) {
SystemProperties.set("dumpstate.options", extraOptions);
@@ -14145,7 +13884,6 @@ public class ActivityManagerService extends IActivityManager.Stub
// Load resources only after the current configuration has been set.
final Resources res = mContext.getResources();
- mHasRecents = res.getBoolean(com.android.internal.R.bool.config_hasRecents);
mThumbnailWidth = res.getDimensionPixelSize(
com.android.internal.R.dimen.thumbnail_width);
mThumbnailHeight = res.getDimensionPixelSize(
@@ -15104,10 +14842,31 @@ public class ActivityManagerService extends IActivityManager.Stub
long origId = Binder.clearCallingIdentity();
if (useProto) {
- //TODO: Options when dumping proto
final ProtoOutputStream proto = new ProtoOutputStream(fd);
- synchronized (this) {
- writeActivitiesToProtoLocked(proto);
+ String cmd = opti < args.length ? args[opti] : "";
+ opti++;
+
+ if ("activities".equals(cmd) || "a".equals(cmd)) {
+ // output proto is ActivityStackSupervisorProto
+ synchronized (this) {
+ writeActivitiesToProtoLocked(proto);
+ }
+ } else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
+ // output proto is BroadcastProto
+ synchronized (this) {
+ writeBroadcastsToProtoLocked(proto);
+ }
+ } else {
+ // default option, dump everything, output is ActivityManagerServiceProto
+ synchronized (this) {
+ long activityToken = proto.start(ActivityManagerServiceProto.ACTIVITIES);
+ writeActivitiesToProtoLocked(proto);
+ proto.end(activityToken);
+
+ long broadcastToken = proto.start(ActivityManagerServiceProto.BROADCASTS);
+ writeBroadcastsToProtoLocked(proto);
+ proto.end(broadcastToken);
+ }
}
proto.flush();
Binder.restoreCallingIdentity(origId);
@@ -15133,7 +14892,9 @@ public class ActivityManagerService extends IActivityManager.Stub
}
} else if ("recents".equals(cmd) || "r".equals(cmd)) {
synchronized (this) {
- dumpRecentsLocked(fd, pw, args, opti, true, dumpPackage);
+ if (mRecentTasks != null) {
+ mRecentTasks.dump(pw, true /* dumpAll */, dumpPackage);
+ }
}
} else if ("broadcasts".equals(cmd) || "b".equals(cmd)) {
String[] newArgs;
@@ -15354,7 +15115,9 @@ public class ActivityManagerService extends IActivityManager.Stub
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
- dumpRecentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
+ if (mRecentTasks != null) {
+ mRecentTasks.dump(pw, dumpAll, dumpPackage);
+ }
pw.println();
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
@@ -15424,7 +15187,9 @@ public class ActivityManagerService extends IActivityManager.Stub
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
}
- dumpRecentsLocked(fd, pw, args, opti, dumpAll, dumpPackage);
+ if (mRecentTasks != null) {
+ mRecentTasks.dump(pw, dumpAll, dumpPackage);
+ }
pw.println();
if (dumpAll) {
pw.println("-------------------------------------------------------------------------------");
@@ -15458,7 +15223,8 @@ public class ActivityManagerService extends IActivityManager.Stub
}
private void writeActivitiesToProtoLocked(ProtoOutputStream proto) {
- mStackSupervisor.writeToProto(proto, ACTIVITIES);
+ // The output proto of "activity --proto activities" is ActivityStackSupervisorProto
+ mStackSupervisor.writeToProto(proto);
}
private void dumpLastANRLocked(PrintWriter pw) {
@@ -15510,42 +15276,6 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
- void dumpRecentsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
- int opti, boolean dumpAll, String dumpPackage) {
- pw.println("ACTIVITY MANAGER RECENT TASKS (dumpsys activity recents)");
-
- boolean printedAnything = false;
-
- if (mRecentTasks != null && mRecentTasks.size() > 0) {
- boolean printedHeader = false;
-
- final int N = mRecentTasks.size();
- for (int i=0; i<N; i++) {
- TaskRecord tr = mRecentTasks.get(i);
- if (dumpPackage != null) {
- if (tr.realActivity == null ||
- !dumpPackage.equals(tr.realActivity.getPackageName())) {
- continue;
- }
- }
- if (!printedHeader) {
- pw.println(" Recent tasks:");
- printedHeader = true;
- printedAnything = true;
- }
- pw.print(" * Recent #"); pw.print(i); pw.print(": ");
- pw.println(tr);
- if (dumpAll) {
- mRecentTasks.get(i).dump(pw, " ");
- }
- }
- }
-
- if (!printedAnything) {
- pw.println(" (nothing)");
- }
- }
-
void dumpAssociationsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
pw.println("ACTIVITY MANAGER ASSOCIATIONS (dumpsys activity associations)");
@@ -16372,6 +16102,40 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
+ void writeBroadcastsToProtoLocked(ProtoOutputStream proto) {
+ if (mRegisteredReceivers.size() > 0) {
+ Iterator it = mRegisteredReceivers.values().iterator();
+ while (it.hasNext()) {
+ ReceiverList r = (ReceiverList)it.next();
+ r.writeToProto(proto, BroadcastProto.RECEIVER_LIST);
+ }
+ }
+ mReceiverResolver.writeToProto(proto, BroadcastProto.RECEIVER_RESOLVER);
+ for (BroadcastQueue q : mBroadcastQueues) {
+ q.writeToProto(proto, BroadcastProto.BROADCAST_QUEUE);
+ }
+ for (int user=0; user<mStickyBroadcasts.size(); user++) {
+ long token = proto.start(BroadcastProto.STICKY_BROADCASTS);
+ proto.write(StickyBroadcastProto.USER, mStickyBroadcasts.keyAt(user));
+ for (Map.Entry<String, ArrayList<Intent>> ent
+ : mStickyBroadcasts.valueAt(user).entrySet()) {
+ long actionToken = proto.start(StickyBroadcastProto.ACTIONS);
+ proto.write(StickyBroadcastProto.StickyAction.NAME, ent.getKey());
+ for (Intent intent : ent.getValue()) {
+ intent.writeToProto(proto, StickyBroadcastProto.StickyAction.INTENTS,
+ false, true, true, false);
+ }
+ proto.end(actionToken);
+ }
+ proto.end(token);
+ }
+
+ long handlerToken = proto.start(BroadcastProto.HANDLER);
+ proto.write(BroadcastProto.MainHandler.HANDLER, mHandler.toString());
+ mHandler.getLooper().writeToProto(proto, BroadcastProto.MainHandler.LOOPER);
+ proto.end(handlerToken);
+ }
+
void dumpBroadcastsLocked(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll, String dumpPackage) {
boolean needSep = false;
@@ -19360,7 +19124,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// Remove all permissions granted from/to this package
removeUriPermissionsForPackageLocked(ssp, userId, true);
- removeTasksByPackageNameLocked(ssp, userId);
+ mRecentTasks.removeTasksByPackageName(ssp, userId);
mServices.forceStopPackageLocked(ssp, userId);
@@ -20697,9 +20461,10 @@ public class ActivityManagerService extends IActivityManager.Stub
/** Helper method that requests bounds from WM and applies them to stack. */
private void resizeStackWithBoundsFromWindowManager(int stackId, boolean deferResume) {
final Rect newStackBounds = new Rect();
- mStackSupervisor.getStack(stackId).getBoundsForNewConfiguration(newStackBounds);
+ final ActivityStack stack = mStackSupervisor.getStack(stackId);
+ stack.getBoundsForNewConfiguration(newStackBounds);
mStackSupervisor.resizeStackLocked(
- stackId, !newStackBounds.isEmpty() ? newStackBounds : null /* bounds */,
+ stack, !newStackBounds.isEmpty() ? newStackBounds : null /* bounds */,
null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
false /* preserveWindows */, false /* allowResizeInDockedMode */, deferResume);
}
@@ -24367,125 +24132,6 @@ public class ActivityManagerService extends IActivityManager.Stub
}
/**
- * An implementation of IAppTask, that allows an app to manage its own tasks via
- * {@link android.app.ActivityManager.AppTask}. We keep track of the callingUid to ensure that
- * only the process that calls getAppTasks() can call the AppTask methods.
- */
- class AppTaskImpl extends IAppTask.Stub {
- private int mTaskId;
- private int mCallingUid;
-
- public AppTaskImpl(int taskId, int callingUid) {
- mTaskId = taskId;
- mCallingUid = callingUid;
- }
-
- private void checkCaller() {
- if (mCallingUid != Binder.getCallingUid()) {
- throw new SecurityException("Caller " + mCallingUid
- + " does not match caller of getAppTasks(): " + Binder.getCallingUid());
- }
- }
-
- @Override
- public void finishAndRemoveTask() {
- checkCaller();
-
- synchronized (ActivityManagerService.this) {
- long origId = Binder.clearCallingIdentity();
- try {
- // We remove the task from recents to preserve backwards
- if (!mStackSupervisor.removeTaskByIdLocked(mTaskId, false,
- REMOVE_FROM_RECENTS)) {
- throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
- }
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
- }
-
- @Override
- public ActivityManager.RecentTaskInfo getTaskInfo() {
- checkCaller();
-
- synchronized (ActivityManagerService.this) {
- long origId = Binder.clearCallingIdentity();
- try {
- TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(mTaskId);
- if (tr == null) {
- throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
- }
- return createRecentTaskInfoFromTaskRecord(tr);
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
- }
-
- @Override
- public void moveToFront() {
- checkCaller();
- // Will bring task to front if it already has a root activity.
- final long origId = Binder.clearCallingIdentity();
- try {
- synchronized (this) {
- mStackSupervisor.startActivityFromRecentsInner(mTaskId, null);
- }
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
-
- @Override
- public int startActivity(IBinder whoThread, String callingPackage,
- Intent intent, String resolvedType, Bundle bOptions) {
- checkCaller();
-
- int callingUser = UserHandle.getCallingUserId();
- TaskRecord tr;
- IApplicationThread appThread;
- synchronized (ActivityManagerService.this) {
- tr = mStackSupervisor.anyTaskForIdLocked(mTaskId);
- if (tr == null) {
- throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
- }
- appThread = IApplicationThread.Stub.asInterface(whoThread);
- if (appThread == null) {
- throw new IllegalArgumentException("Bad app thread " + appThread);
- }
- }
- return mActivityStarter.startActivityMayWait(appThread, -1, callingPackage, intent,
- resolvedType, null, null, null, null, 0, 0, null, null,
- null, bOptions, false, callingUser, tr, "AppTaskImpl");
- }
-
- @Override
- public void setExcludeFromRecents(boolean exclude) {
- checkCaller();
-
- synchronized (ActivityManagerService.this) {
- long origId = Binder.clearCallingIdentity();
- try {
- TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(mTaskId);
- if (tr == null) {
- throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
- }
- Intent intent = tr.getBaseIntent();
- if (exclude) {
- intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- } else {
- intent.setFlags(intent.getFlags()
- & ~Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- }
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
- }
- }
- }
-
- /**
* Kill processes for the user with id userId and that depend on the package named packageName
*/
@Override
diff --git a/com/android/server/am/ActivityManagerShellCommand.java b/com/android/server/am/ActivityManagerShellCommand.java
index 4c934232..f03d2d53 100644
--- a/com/android/server/am/ActivityManagerShellCommand.java
+++ b/com/android/server/am/ActivityManagerShellCommand.java
@@ -73,10 +73,8 @@ import java.util.List;
import static android.app.ActivityManager.RESIZE_MODE_SYSTEM;
import static android.app.ActivityManager.RESIZE_MODE_USER;
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.Display.INVALID_DISPLAY;
@@ -86,15 +84,6 @@ final class ActivityManagerShellCommand extends ShellCommand {
public static final String NO_CLASS_ERROR_CODE = "Error type 3";
private static final String SHELL_PACKAGE_NAME = "com.android.shell";
- // Is the object moving in a positive direction?
- private static final boolean MOVING_FORWARD = true;
- // Is the object moving in the horizontal plan?
- private static final boolean MOVING_HORIZONTALLY = true;
- // Is the object current point great then its target point?
- private static final boolean GREATER_THAN_TARGET = true;
- // Amount we reduce the stack size by when testing a task re-size.
- private static final int STACK_BOUNDS_INSET = 10;
-
// IPC interface to activity manager -- don't need to do additional security checks.
final IActivityManager mInterface;
@@ -1944,8 +1933,6 @@ final class ActivityManagerShellCommand extends ShellCommand {
return runStackInfo(pw);
case "move-top-activity-to-pinned-stack":
return runMoveTopActivityToPinnedStack(pw);
- case "size-docked-stack-test":
- return runStackSizeDockedStackTest(pw);
case "remove":
return runStackRemove(pw);
default:
@@ -2143,89 +2130,6 @@ final class ActivityManagerShellCommand extends ShellCommand {
return 0;
}
- int runStackSizeDockedStackTest(PrintWriter pw) throws RemoteException {
- final PrintWriter err = getErrPrintWriter();
- final int stepSize = Integer.parseInt(getNextArgRequired());
- final String side = getNextArgRequired();
- final String delayStr = getNextArg();
- final int delayMs = (delayStr != null) ? Integer.parseInt(delayStr) : 0;
-
- ActivityManager.StackInfo info = mInterface.getStackInfo(
- WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
- if (info == null) {
- err.println("Docked stack doesn't exist");
- return -1;
- }
- if (info.bounds == null) {
- err.println("Docked stack doesn't have a bounds");
- return -1;
- }
- Rect bounds = info.bounds;
-
- final boolean horizontalGrowth = "l".equals(side) || "r".equals(side);
- final int changeSize = (horizontalGrowth ? bounds.width() : bounds.height()) / 2;
- int currentPoint;
- switch (side) {
- case "l":
- currentPoint = bounds.left;
- break;
- case "r":
- currentPoint = bounds.right;
- break;
- case "t":
- currentPoint = bounds.top;
- break;
- case "b":
- currentPoint = bounds.bottom;
- break;
- default:
- err.println("Unknown growth side: " + side);
- return -1;
- }
-
- final int startPoint = currentPoint;
- final int minPoint = currentPoint - changeSize;
- final int maxPoint = currentPoint + changeSize;
-
- int maxChange;
- pw.println("Shrinking docked stack side=" + side);
- pw.flush();
- while (currentPoint > minPoint) {
- maxChange = Math.min(stepSize, currentPoint - minPoint);
- currentPoint -= maxChange;
- setBoundsSide(bounds, side, currentPoint);
- int res = resizeStack(DOCKED_STACK_ID, bounds, delayMs);
- if (res < 0) {
- return res;
- }
- }
-
- pw.println("Growing docked stack side=" + side);
- pw.flush();
- while (currentPoint < maxPoint) {
- maxChange = Math.min(stepSize, maxPoint - currentPoint);
- currentPoint += maxChange;
- setBoundsSide(bounds, side, currentPoint);
- int res = resizeStack(DOCKED_STACK_ID, bounds, delayMs);
- if (res < 0) {
- return res;
- }
- }
-
- pw.println("Back to Original size side=" + side);
- pw.flush();
- while (currentPoint > startPoint) {
- maxChange = Math.min(stepSize, currentPoint - startPoint);
- currentPoint -= maxChange;
- setBoundsSide(bounds, side, currentPoint);
- int res = resizeStack(DOCKED_STACK_ID, bounds, delayMs);
- if (res < 0) {
- return res;
- }
- }
- return 0;
- }
-
void setBoundsSide(Rect bounds, String side, int value) {
switch (side) {
case "l":
@@ -2687,10 +2591,6 @@ final class ActivityManagerShellCommand extends ShellCommand {
pw.println(" Change docked stack to <LEFT,TOP,RIGHT,BOTTOM>");
pw.println(" and supplying temporary different task bounds indicated by");
pw.println(" <TASK_LEFT,TOP,RIGHT,BOTTOM>");
- pw.println(" size-docked-stack-test: <STEP_SIZE> <l|t|r|b> [DELAY_MS]");
- pw.println(" Test command for sizing docked stack by");
- pw.println(" <STEP_SIZE> increments from the side <l>eft, <t>op, <r>ight, or <b>ottom");
- pw.println(" applying the optional [DELAY_MS] between each step.");
pw.println(" move-top-activity-to-pinned-stack: <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>");
pw.println(" Moves the top activity from");
pw.println(" <STACK_ID> to the pinned stack using <LEFT,TOP,RIGHT,BOTTOM> for the");
diff --git a/com/android/server/am/ActivityMetricsLogger.java b/com/android/server/am/ActivityMetricsLogger.java
index fdcb8c69..93c0f772 100644
--- a/com/android/server/am/ActivityMetricsLogger.java
+++ b/com/android/server/am/ActivityMetricsLogger.java
@@ -5,6 +5,7 @@ import static android.app.ActivityManager.START_TASK_TO_FRONT;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManagerInternal.APP_TRANSITION_TIMEOUT;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
@@ -127,7 +128,7 @@ class ActivityMetricsLogger {
case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY:
mWindowState = WINDOW_STATE_SIDE_BY_SIDE;
break;
- case WINDOW_STATE_FREEFORM:
+ case WINDOWING_MODE_FREEFORM:
mWindowState = WINDOW_STATE_FREEFORM;
break;
default:
diff --git a/com/android/server/am/ActivityRecord.java b/com/android/server/am/ActivityRecord.java
index 7b0b942a..2c72a4db 100644
--- a/com/android/server/am/ActivityRecord.java
+++ b/com/android/server/am/ActivityRecord.java
@@ -17,9 +17,7 @@
package com.android.server.am;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ActivityManager.TaskDescription.ATTR_TASKDESCRIPTION_PREFIX;
import static android.app.ActivityOptions.ANIM_CLIP_REVEAL;
import static android.app.ActivityOptions.ANIM_CUSTOM;
@@ -60,6 +58,10 @@ import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
+import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
+import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
+import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
+import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
import static android.content.pm.ActivityInfo.PERSIST_ACROSS_REBOOTS;
import static android.content.pm.ActivityInfo.PERSIST_ROOT_ONLY;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
@@ -284,6 +286,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
int configChangeFlags; // which config values have changed
private boolean keysPaused; // has key dispatching been paused for it?
int launchMode; // the launch mode activity attribute.
+ int lockTaskLaunchMode; // the lockTaskMode manifest attribute, subject to override
boolean visible; // does this activity's window need to be shown?
boolean visibleIgnoringKeyguard; // is this activity visible, ignoring the fact that Keyguard
// might hide this activity?
@@ -420,9 +423,13 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
if (iconFilename != null || taskDescription.getLabel() != null ||
taskDescription.getPrimaryColor() != 0) {
pw.print(prefix); pw.print("taskDescription:");
- pw.print(" iconFilename="); pw.print(taskDescription.getIconFilename());
pw.print(" label=\""); pw.print(taskDescription.getLabel());
pw.print("\"");
+ pw.print(" icon="); pw.print(taskDescription.getInMemoryIcon() != null
+ ? taskDescription.getInMemoryIcon().getByteCount() + " bytes"
+ : "null");
+ pw.print(" iconResource="); pw.print(taskDescription.getIconResource());
+ pw.print(" iconFilename="); pw.print(taskDescription.getIconFilename());
pw.print(" primaryColor=");
pw.println(Integer.toHexString(taskDescription.getPrimaryColor()));
pw.print(prefix + " backgroundColor=");
@@ -432,9 +439,6 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
pw.print(prefix + " navigationBarColor=");
pw.println(Integer.toHexString(taskDescription.getNavigationBarColor()));
}
- if (iconFilename == null && taskDescription.getIcon() != null) {
- pw.print(prefix); pw.println("taskDescription contains Bitmap");
- }
}
if (results != null) {
pw.print(prefix); pw.print("results="); pw.println(results);
@@ -661,8 +665,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
return;
}
- final boolean inPictureInPictureMode = (task.getStackId() == PINNED_STACK_ID) &&
- (targetStackBounds != null);
+ final boolean inPictureInPictureMode = inPinnedWindowingMode() && targetStackBounds != null;
if (inPictureInPictureMode != mLastReportedPictureInPictureMode || forceUpdate) {
// Picture-in-picture mode changes also trigger a multi-window mode change as well, so
// update that here in order
@@ -684,10 +687,6 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
}
}
- boolean isFreeform() {
- return task != null && task.getStackId() == FREEFORM_WORKSPACE_STACK_ID;
- }
-
@Override
protected int getChildCount() {
// {@link ActivityRecord} is a leaf node and has no children.
@@ -831,23 +830,6 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
hasBeenLaunched = false;
mStackSupervisor = supervisor;
- mRotationAnimationHint = aInfo.rotationAnimation;
-
- if (options != null) {
- pendingOptions = options;
- mLaunchTaskBehind = pendingOptions.getLaunchTaskBehind();
-
- final int rotationAnimation = pendingOptions.getRotationAnimationHint();
- // Only override manifest supplied option if set.
- if (rotationAnimation >= 0) {
- mRotationAnimationHint = rotationAnimation;
- }
- PendingIntent usageReport = pendingOptions.getUsageTimeReport();
- if (usageReport != null) {
- appTimeTracker = new AppTimeTracker(usageReport);
- }
- }
-
// This starts out true, since the initial state of an activity is that we have everything,
// and we shouldn't never consider it lacking in state to be removed if it dies.
haveState = true;
@@ -914,6 +896,32 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
mShowWhenLocked = (aInfo.flags & FLAG_SHOW_WHEN_LOCKED) != 0;
mTurnScreenOn = (aInfo.flags & FLAG_TURN_SCREEN_ON) != 0;
+
+ mRotationAnimationHint = aInfo.rotationAnimation;
+ lockTaskLaunchMode = aInfo.lockTaskLaunchMode;
+ if (appInfo.isPrivilegedApp() && (lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_ALWAYS
+ || lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_NEVER)) {
+ lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_DEFAULT;
+ }
+
+ if (options != null) {
+ pendingOptions = options;
+ mLaunchTaskBehind = options.getLaunchTaskBehind();
+
+ final int rotationAnimation = pendingOptions.getRotationAnimationHint();
+ // Only override manifest supplied option if set.
+ if (rotationAnimation >= 0) {
+ mRotationAnimationHint = rotationAnimation;
+ }
+ final PendingIntent usageReport = pendingOptions.getUsageTimeReport();
+ if (usageReport != null) {
+ appTimeTracker = new AppTimeTracker(usageReport);
+ }
+ final boolean useLockTask = pendingOptions.getLockTaskMode();
+ if (useLockTask && lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_DEFAULT) {
+ lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
+ }
+ }
}
AppWindowContainerController getWindowContainerController() {
@@ -948,7 +956,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
// update the initial multi-window modes so that the callbacks are scheduled correctly when
// the user leaves that mode.
mLastReportedMultiWindowMode = !task.mFullscreen;
- mLastReportedPictureInPictureMode = (task.getStackId() == PINNED_STACK_ID);
+ mLastReportedPictureInPictureMode = inPinnedWindowingMode();
}
void removeWindowContainer() {
@@ -1551,7 +1559,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
// On devices that support leanback only (Android TV), Recents activity can only be
// visible if the home stack is the focused stack or we are in split-screen mode.
final ActivityDisplay display = getDisplay();
- boolean hasSplitScreenStack = display != null && display.hasSplitScreenStack();
+ boolean hasSplitScreenStack = display != null && display.hasSplitScreenPrimaryStack();
isVisible = hasSplitScreenStack || mStackSupervisor.isFocusedStack(getStack());
}
@@ -2739,6 +2747,8 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
void setShowWhenLocked(boolean showWhenLocked) {
mShowWhenLocked = showWhenLocked;
+ mStackSupervisor.ensureActivitiesVisibleLocked(null, 0 /* configChanges */,
+ false /* preserveWindows */);
}
/**
diff --git a/com/android/server/am/ActivityStack.java b/com/android/server/am/ActivityStack.java
index 1940ca2b..f0811dda 100644
--- a/com/android/server/am/ActivityStack.java
+++ b/com/android/server/am/ActivityStack.java
@@ -16,27 +16,25 @@
package com.android.server.am;
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.app.WindowConfiguration.activityTypeToString;
+import static android.app.WindowConfiguration.windowingModeToString;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
-
import static android.view.Display.INVALID_DISPLAY;
+
import static com.android.server.am.ActivityDisplay.POSITION_BOTTOM;
import static com.android.server.am.ActivityDisplay.POSITION_TOP;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE;
@@ -100,7 +98,6 @@ import static java.lang.Integer.MAX_VALUE;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
-import android.app.ActivityManager.StackId;
import android.app.ActivityOptions;
import android.app.AppGlobals;
import android.app.IActivityController;
@@ -110,6 +107,7 @@ import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
+import android.graphics.Point;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Binder;
@@ -192,10 +190,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// finished destroying itself.
private static final int DESTROY_TIMEOUT = 10 * 1000;
- // How long until we reset a task when the user returns to it. Currently
- // disabled.
- private static final long ACTIVITY_INACTIVE_RESET_TIME = 0;
-
// Set to false to disable the preview that is shown while a new activity
// is being started.
private static final boolean SHOW_APP_STARTING_PREVIEW = true;
@@ -352,12 +346,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
private final SparseArray<Rect> mTmpBounds = new SparseArray<>();
private final SparseArray<Rect> mTmpInsetBounds = new SparseArray<>();
private final Rect mTmpRect2 = new Rect();
+ private final Point mTmpSize = new Point();
/** Run all ActivityStacks through this */
protected final ActivityStackSupervisor mStackSupervisor;
- private final LaunchingTaskPositioner mTaskPositioner;
-
private boolean mTopActivityOccludesKeyguard;
private ActivityRecord mTopDismissingKeyguardActivity;
@@ -460,8 +453,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
mWindowManager = mService.mWindowManager;
mStackId = stackId;
mCurrentUser = mService.mUserController.getCurrentUserId();
- mTaskPositioner = mStackId == FREEFORM_WORKSPACE_STACK_ID
- ? new LaunchingTaskPositioner() : null;
mTmpRect2.setEmpty();
setWindowingMode(windowingMode);
setActivityType(activityType);
@@ -479,6 +470,16 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return mWindowContainerController;
}
+ @Override
+ public void onConfigurationChanged(Configuration newParentConfig) {
+ final int prevWindowingMode = getWindowingMode();
+ super.onConfigurationChanged(newParentConfig);
+ final ActivityDisplay display = getDisplay();
+ if (display != null && prevWindowingMode != getWindowingMode()) {
+ display.onStackWindowingModeChanged(this);
+ }
+ }
+
/** Adds the stack to specified display and calls WindowManager to do the same. */
void reparent(ActivityDisplay activityDisplay, boolean onTop) {
removeFromDisplay();
@@ -502,14 +503,11 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
mDisplayId = activityDisplay.mDisplayId;
mBounds = bounds != null ? new Rect(bounds) : null;
mFullscreen = mBounds == null;
- if (mTaskPositioner != null) {
- mTaskPositioner.setDisplay(activityDisplay.mDisplay);
- mTaskPositioner.configure(mBounds);
- }
+
onParentChanged();
activityDisplay.addChild(this, onTop ? POSITION_TOP : POSITION_BOTTOM);
- if (mStackId == DOCKED_STACK_ID) {
+ if (inSplitScreenPrimaryWindowingMode()) {
// If we created a docked stack we want to resize it so it resizes all other stacks
// in the system.
mStackSupervisor.resizeDockedStackLocked(
@@ -533,9 +531,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
display.removeChild(this);
}
mDisplayId = INVALID_DISPLAY;
- if (mTaskPositioner != null) {
- mTaskPositioner.reset();
- }
}
/** Removes the stack completely. Also calls WindowManager to do the same on its side. */
@@ -639,9 +634,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
void setBounds(Rect bounds) {
mBounds = mFullscreen ? null : new Rect(bounds);
- if (mTaskPositioner != null) {
- mTaskPositioner.configure(bounds);
- }
}
ActivityRecord topRunningActivityLocked() {
@@ -818,14 +810,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return isActivityTypeHome() || isActivityTypeRecents();
}
- final boolean isDockedStack() {
- return mStackId == DOCKED_STACK_ID;
- }
-
- final boolean isPinnedStack() {
- return mStackId == PINNED_STACK_ID;
- }
-
final boolean isOnHomeDisplay() {
return mDisplayId == DEFAULT_DISPLAY;
}
@@ -1505,9 +1489,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
* needed. A stack is considered translucent if it don't contain a visible or
* starting (about to be visible) activity that is fullscreen (opaque).
* @param starting The currently starting activity or null if there is none.
- * @param stackBehindId The id of the stack directly behind this one.
+ * @param stackBehind The stack directly behind this one.
*/
- private boolean isStackTranslucent(ActivityRecord starting, int stackBehindId) {
+ private boolean isStackTranslucent(ActivityRecord starting, ActivityStack stackBehind) {
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
final TaskRecord task = mTaskHistory.get(taskNdx);
final ArrayList<ActivityRecord> activities = task.mActivities;
@@ -1532,7 +1516,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return false;
}
- final ActivityStack stackBehind = mStackSupervisor.getStack(stackBehindId);
final boolean stackBehindHomeOrRecent = stackBehind != null
&& stackBehind.isHomeOrRecentsStack();
if (!isHomeOrRecentsStack() && r.frontOfTask && task.isOverHomeStack()
@@ -1553,6 +1536,10 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
&& !mForceHidden;
}
+ boolean isTopStackOnDisplay() {
+ return getDisplay().isTopStack(this);
+ }
+
/**
* Returns true if the stack should be visible.
*
@@ -1563,23 +1550,15 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return false;
}
- if (mStackSupervisor.isFrontStackOnDisplay(this) || mStackSupervisor.isFocusedStack(this)) {
+ final ActivityDisplay display = getDisplay();
+ if (isTopStackOnDisplay() || mStackSupervisor.isFocusedStack(this)) {
return true;
}
- final ActivityDisplay display = getDisplay();
- final ArrayList<ActivityStack> displayStacks = display.mStacks;
- final int stackIndex = displayStacks.indexOf(this);
-
- if (stackIndex == displayStacks.size() - 1) {
- Slog.wtf(TAG,
- "Stack=" + this + " isn't front stack but is at the top of the stack list");
- return false;
- }
+ final int stackIndex = display.getIndexOf(this);
// Check position and visibility of this stack relative to the front stack on its display.
- final ActivityStack topStack = getTopStackOnDisplay();
- final int topStackId = topStack.mStackId;
+ final ActivityStack topStack = getDisplay().getTopStack();
final int windowingMode = getWindowingMode();
final int activityType = getActivityType();
@@ -1587,7 +1566,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// If the assistant stack is focused and translucent, then the docked stack is always
// visible
if (topStack.isActivityTypeAssistant()) {
- return topStack.isStackTranslucent(starting, DOCKED_STACK_ID);
+ return topStack.isStackTranslucent(starting, this);
}
return true;
}
@@ -1596,34 +1575,31 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// A case would be if recents stack exists but has no tasks and is below the docked stack
// and home stack is below recents
if (activityType == ACTIVITY_TYPE_HOME) {
- final ActivityStack splitScreenStack = display.getStack(
- WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
- int dockedStackIndex = displayStacks.indexOf(splitScreenStack);
+ final ActivityStack splitScreenStack = display.getSplitScreenPrimaryStack();
+ int dockedStackIndex = display.getIndexOf(splitScreenStack);
if (dockedStackIndex > stackIndex && stackIndex != dockedStackIndex - 1) {
return false;
}
}
// Find the first stack behind front stack that actually got something visible.
- int stackBehindTopIndex = displayStacks.indexOf(topStack) - 1;
+ int stackBehindTopIndex = display.getIndexOf(topStack) - 1;
while (stackBehindTopIndex >= 0 &&
- displayStacks.get(stackBehindTopIndex).topRunningActivityLocked() == null) {
+ display.getChildAt(stackBehindTopIndex).topRunningActivityLocked() == null) {
stackBehindTopIndex--;
}
final ActivityStack stackBehindTop = (stackBehindTopIndex >= 0)
- ? displayStacks.get(stackBehindTopIndex) : null;
- int stackBehindTopId = INVALID_STACK_ID;
+ ? display.getChildAt(stackBehindTopIndex) : null;
int stackBehindTopWindowingMode = WINDOWING_MODE_UNDEFINED;
int stackBehindTopActivityType = ACTIVITY_TYPE_UNDEFINED;
if (stackBehindTop != null) {
- stackBehindTopId = stackBehindTop.mStackId;
stackBehindTopWindowingMode = stackBehindTop.getWindowingMode();
stackBehindTopActivityType = stackBehindTop.getActivityType();
}
final boolean alwaysOnTop = topStack.getWindowConfiguration().isAlwaysOnTop();
if (topStack.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY || alwaysOnTop) {
- if (stackIndex == stackBehindTopIndex) {
+ if (this == stackBehindTop) {
// Stacks directly behind the docked or pinned stack are always visible.
return true;
} else if (alwaysOnTop && stackIndex == stackBehindTopIndex - 1) {
@@ -1632,14 +1608,13 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
if (stackBehindTopWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
return true;
} else if (stackBehindTopActivityType == ACTIVITY_TYPE_ASSISTANT) {
- return displayStacks.get(stackBehindTopIndex).isStackTranslucent(
- starting, mStackId);
+ return stackBehindTop.isStackTranslucent(starting, this);
}
}
}
if (topStack.isBackdropToTranslucentActivity()
- && topStack.isStackTranslucent(starting, stackBehindTopId)) {
+ && topStack.isStackTranslucent(starting, stackBehindTop)) {
// Stacks behind the fullscreen or assistant stack with a translucent activity are
// always visible so they can act as a backdrop to the translucent activity.
// For example, dialog activities
@@ -1657,14 +1632,15 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
}
- if (StackId.isStaticStack(mStackId)
- || isHomeOrRecentsStack() || isActivityTypeAssistant()) {
- // Visibility of any static stack should have been determined by the conditions above.
+ if (isOnHomeDisplay()) {
+ // Visibility of any stack on default display should have been determined by the
+ // conditions above.
return false;
}
- for (int i = stackIndex + 1; i < displayStacks.size(); i++) {
- final ActivityStack stack = displayStacks.get(i);
+ final int stackCount = display.getChildCount();
+ for (int i = stackIndex + 1; i < stackCount; i++) {
+ final ActivityStack stack = display.getChildAt(i);
if (!stack.mFullscreen && !stack.hasFullscreenTask()) {
continue;
@@ -1675,7 +1651,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return false;
}
- if (!stack.isStackTranslucent(starting, INVALID_STACK_ID)) {
+ if (!stack.isStackTranslucent(starting, null /* stackBehind */)) {
return false;
}
}
@@ -1801,7 +1777,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
makeInvisible(r);
}
}
- if (mStackId == FREEFORM_WORKSPACE_STACK_ID) {
+ final int windowingMode = getWindowingMode();
+ if (windowingMode == WINDOWING_MODE_FREEFORM) {
// The visibility of tasks and the activities they contain in freeform stack are
// determined individually unlike other stacks where the visibility or fullscreen
// status of an activity in a previous task affects other.
@@ -1816,7 +1793,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// show activities in the next application stack behind them vs. another
// task in the home stack like recents.
behindFullscreenActivity = true;
- } else if (mStackId == FULLSCREEN_WORKSPACE_STACK_ID) {
+ } else if (windowingMode == WINDOWING_MODE_FULLSCREEN
+ || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Skipping after task=" + task
+ " returning to non-application type=" + task.getTaskToReturnTo());
// Once we reach a fullscreen stack task that has a running activity and should
@@ -1852,6 +1830,32 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
/**
+ * Returns true if this stack should be resized to match the bounds specified by
+ * {@link ActivityOptions#setLaunchBounds} when launching an activity into the stack.
+ */
+ boolean resizeStackWithLaunchBounds() {
+ return inPinnedWindowingMode();
+ }
+
+ /**
+ * Returns true if we try to maintain focus in the current stack when the top activity finishes.
+ */
+ private boolean keepFocusInStackIfPossible() {
+ final int windowingMode = getWindowingMode();
+ return windowingMode == WINDOWING_MODE_FREEFORM
+ || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
+ || windowingMode == WINDOWING_MODE_PINNED;
+ }
+
+ /**
+ * Returns true if the top task in the task is allowed to return home when finished and
+ * there are other tasks in the stack.
+ */
+ boolean allowTopTaskToReturnHome() {
+ return !inPinnedWindowingMode();
+ }
+
+ /**
* @return the top most visible activity that wants to dismiss Keyguard
*/
ActivityRecord getTopDismissingKeyguardActivity() {
@@ -1867,7 +1871,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
*/
boolean checkKeyguardVisibility(ActivityRecord r, boolean shouldBeVisible,
boolean isTop) {
- final boolean isInPinnedStack = r.getStack().getStackId() == PINNED_STACK_ID;
+ final boolean isInPinnedStack = r.inPinnedWindowingMode();
final boolean keyguardShowing = mStackSupervisor.mKeyguardController.isKeyguardShowing(
mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY);
final boolean keyguardLocked = mStackSupervisor.mKeyguardController.isKeyguardLocked();
@@ -2165,7 +2169,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
mResumedActivity = r;
r.state = ActivityState.RESUMED;
mService.setResumedActivityUncheckLocked(r, reason);
- mStackSupervisor.addRecentActivity(r);
+ mStackSupervisor.mRecentTasks.add(r.getTask());
}
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
@@ -2572,8 +2576,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
Slog.i(TAG, "Restarting because process died: " + next);
if (!next.hasBeenLaunched) {
next.hasBeenLaunched = true;
- } else if (SHOW_APP_STARTING_PREVIEW && lastStack != null &&
- mStackSupervisor.isFrontStackOnDisplay(lastStack)) {
+ } else if (SHOW_APP_STARTING_PREVIEW && lastStack != null
+ && lastStack.isTopStackOnDisplay()) {
next.showStartingWindow(null /* prev */, false /* newTask */,
false /* taskSwitch */);
}
@@ -2617,7 +2621,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
private boolean resumeTopActivityInNextFocusableStack(ActivityRecord prev,
ActivityOptions options, String reason) {
- if ((!mFullscreen || !isOnHomeDisplay()) && adjustFocusToNextFocusableStackLocked(reason)) {
+ if (adjustFocusToNextFocusableStackLocked(reason)) {
// Try to move focus to the next visible stack with a running activity if this
// stack is not covering the entire screen or is on a secondary display (with no home
// stack).
@@ -2746,9 +2750,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// make underlying task focused when this one will be finished.
int returnToType = isLastTaskOverHome
? task.getTaskToReturnTo() : ACTIVITY_TYPE_STANDARD;
- if (fromHomeOrRecents && StackId.allowTopTaskToReturnHome(mStackId)) {
- returnToType = topTask == null
- ? ACTIVITY_TYPE_HOME : topTask.getActivityType();
+ if (fromHomeOrRecents && allowTopTaskToReturnHome()) {
+ returnToType = topTask == null ? ACTIVITY_TYPE_HOME : topTask.getActivityType();
}
task.setTaskToReturnTo(returnToType);
}
@@ -2901,7 +2904,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// Ensure the caller has requested not to trigger auto-enter PiP
return false;
}
- if (pipCandidate == null || pipCandidate.getStackId() == PINNED_STACK_ID) {
+ if (pipCandidate == null || pipCandidate.inPinnedWindowingMode()) {
// Ensure that we do not trigger entering PiP an activity on the pinned stack
return false;
}
@@ -3186,15 +3189,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
final ActivityRecord resetTaskIfNeededLocked(ActivityRecord taskTop,
ActivityRecord newActivity) {
- boolean forceReset =
+ final boolean forceReset =
(newActivity.info.flags & ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
- if (ACTIVITY_INACTIVE_RESET_TIME > 0
- && taskTop.getTask().getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
- if ((newActivity.info.flags & ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
- forceReset = true;
- }
- }
-
final TaskRecord task = taskTop.getTask();
/** False until we evaluate the TaskRecord associated with taskTop. Switches to true
@@ -3291,7 +3287,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
final String myReason = reason + " adjustFocus";
if (next != r) {
- if (next != null && StackId.keepFocusInStackIfPossible(mStackId) && isFocusable()) {
+ if (next != null && keepFocusInStackIfPossible() && isFocusable()) {
// For freeform, docked, and pinned stacks we always keep the focus within the
// stack as long as there is a running activity.
return;
@@ -3757,7 +3753,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
if (mode == FINISH_IMMEDIATELY
|| (prevState == ActivityState.PAUSED
- && (mode == FINISH_AFTER_PAUSE || mStackId == PINNED_STACK_ID))
+ && (mode == FINISH_AFTER_PAUSE || inPinnedWindowingMode()))
|| finishingActivityInNonFocusedStack
|| prevState == STOPPING
|| prevState == STOPPED
@@ -4436,7 +4432,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
AppTimeTracker timeTracker, String reason) {
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr);
- final ActivityStack topStack = getTopStackOnDisplay();
+ final ActivityStack topStack = getDisplay().getTopStack();
final ActivityRecord topActivity = topStack != null ? topStack.topActivity() : null;
final int numTasks = mTaskHistory.size();
final int index = mTaskHistory.indexOf(tr);
@@ -4464,7 +4460,9 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// Don't refocus if invisible to current user
final ActivityRecord top = tr.getTopActivity();
if (top == null || !top.okToShowLocked()) {
- mStackSupervisor.addRecentActivity(top);
+ if (top != null) {
+ mStackSupervisor.mRecentTasks.add(top.getTask());
+ }
ActivityOptions.abort(options);
return;
}
@@ -4524,7 +4522,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
// If we have a watcher, preflight the move before committing to it. First check
// for *other* available tasks, but if none are available, then try again allowing the
// current task to be selected.
- if (mStackSupervisor.isFrontStackOnDisplay(this) && mService.mController != null) {
+ if (isTopStackOnDisplay() && mService.mController != null) {
ActivityRecord next = topRunningActivityLocked(null, taskId);
if (next == null) {
next = topRunningActivityLocked(null, 0);
@@ -4571,8 +4569,8 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
mWindowContainerController.positionChildAtBottom(tr.getWindowContainerController());
}
- if (mStackId == PINNED_STACK_ID) {
- mStackSupervisor.removeStackLocked(PINNED_STACK_ID);
+ if (inPinnedWindowingMode()) {
+ mStackSupervisor.removeStack(this);
return true;
}
@@ -4604,15 +4602,6 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
return true;
}
- /**
- * Get the topmost stack on the current display. It may be different from focused stack, because
- * focus may be on another display.
- */
- private ActivityStack getTopStackOnDisplay() {
- final ArrayList<ActivityStack> stacks = getDisplay().mStacks;
- return stacks.isEmpty() ? null : stacks.get(stacks.size() - 1);
- }
-
static void logStartActivity(int tag, ActivityRecord r, TaskRecord task) {
final Uri data = r.intent.getData();
final String strData = data != null ? data.toSafeString() : null;
@@ -4687,7 +4676,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
for (int i = mTaskHistory.size() - 1; i >= 0; i--) {
final TaskRecord task = mTaskHistory.get(i);
if (task.isResizeable()) {
- if (mStackId == FREEFORM_WORKSPACE_STACK_ID) {
+ if (inFreeformWindowingMode()) {
// For freeform stack we don't adjust the size of the tasks to match that
// of the stack, but we do try to make sure the tasks are still contained
// with the bounds of the stack.
@@ -4889,7 +4878,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
if (focusedStack && topTask) {
// Give the latest time to ensure foreground task can be sorted
// at the first, because lastActiveTime of creating task is 0.
- ci.lastActiveTime = System.currentTimeMillis();
+ ci.lastActiveTime = SystemClock.elapsedRealtime();
topTask = false;
}
@@ -5069,7 +5058,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
if (task.autoRemoveFromRecents() || isVoiceSession) {
// Task creator asked to remove this when done, or this task was a voice
// interaction, so it should not remain on the recent tasks list.
- mStackSupervisor.removeTaskFromRecents(task);
+ mStackSupervisor.mRecentTasks.remove(task);
}
task.removeWindowContainer();
@@ -5097,7 +5086,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
task.setStack(null);
// Notify if a task from the pinned stack is being removed (or moved depending on the mode)
- if (mStackId == PINNED_STACK_ID) {
+ if (inPinnedWindowingMode()) {
mService.mTaskChangeNotificationController.notifyActivityUnpinned();
}
}
@@ -5120,10 +5109,12 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
}
boolean layoutTaskInStack(TaskRecord task, ActivityInfo.WindowLayout windowLayout) {
- if (mTaskPositioner == null) {
+ if (!task.inFreeformWindowingMode()) {
return false;
}
- mTaskPositioner.updateDefaultBounds(task, mTaskHistory, windowLayout);
+ mStackSupervisor.getLaunchingTaskPositioner()
+ .updateDefaultBounds(task, mTaskHistory, windowLayout);
+
return true;
}
@@ -5248,10 +5239,12 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
@Override
public String toString() {
return "ActivityStack{" + Integer.toHexString(System.identityHashCode(this))
- + " stackId=" + mStackId + ", " + mTaskHistory.size() + " tasks}";
+ + " stackId=" + mStackId + " type=" + activityTypeToString(getActivityType())
+ + " mode=" + windowingModeToString(getWindowingMode()) + ", "
+ + mTaskHistory.size() + " tasks}";
}
- void onLockTaskPackagesUpdatedLocked() {
+ void onLockTaskPackagesUpdated() {
for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
mTaskHistory.get(taskNdx).setLockTaskAuth();
}
diff --git a/com/android/server/am/ActivityStackSupervisor.java b/com/android/server/am/ActivityStackSupervisor.java
index da2827a6..5c91e3cc 100644
--- a/com/android/server/am/ActivityStackSupervisor.java
+++ b/com/android/server/am/ActivityStackSupervisor.java
@@ -21,11 +21,7 @@ import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.Manifest.permission.START_ANY_ACTIVITY;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
-import static android.app.ActivityManager.StackId.FIRST_DYNAMIC_STACK_ID;
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SECONDARY_DISPLAY;
import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
@@ -35,10 +31,13 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.app.WindowConfiguration.activityTypeToString;
+import static android.app.WindowConfiguration.windowingModeToString;
import static android.content.pm.PackageManager.PERMISSION_DENIED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.PowerManager.PARTIAL_WAKE_LOCK;
@@ -47,6 +46,7 @@ import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static android.view.Display.TYPE_VIRTUAL;
+
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_PICTURE_IN_PICTURE_EXPANDED_TO_FULLSCREEN;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
@@ -86,12 +86,13 @@ import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
import static com.android.server.am.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
+import static com.android.server.am.proto.ActivityStackSupervisorProto.CONFIGURATION_CONTAINER;
import static com.android.server.am.proto.ActivityStackSupervisorProto.DISPLAYS;
import static com.android.server.am.proto.ActivityStackSupervisorProto.FOCUSED_STACK_ID;
import static com.android.server.am.proto.ActivityStackSupervisorProto.KEYGUARD_CONTROLLER;
import static com.android.server.am.proto.ActivityStackSupervisorProto.RESUMED_ACTIVITY;
-import static com.android.server.am.proto.ActivityStackSupervisorProto.CONFIGURATION_CONTAINER;
import static com.android.server.wm.AppTransition.TRANSIT_DOCK_TASK_FROM_RECENTS;
+
import static java.lang.Integer.MAX_VALUE;
import android.Manifest;
@@ -102,7 +103,6 @@ import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
-import android.app.ActivityManager.StackId;
import android.app.ActivityManager.StackInfo;
import android.app.ActivityManagerInternal.SleepToken;
import android.app.ActivityOptions;
@@ -176,7 +176,8 @@ import java.util.Iterator;
import java.util.List;
import java.util.Set;
-public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener {
+public class ActivityStackSupervisor extends ConfigurationContainer implements DisplayListener,
+ RecentTasks.Callbacks {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStackSupervisor" : TAG_AM;
private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
private static final String TAG_IDLE = TAG + POSTFIX_IDLE;
@@ -286,7 +287,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
final ActivityManagerService mService;
- private RecentTasks mRecentTasks;
+ RecentTasks mRecentTasks;
final ActivityStackSupervisorHandler mHandler;
@@ -294,8 +295,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
WindowManagerService mWindowManager;
DisplayManager mDisplayManager;
+ LaunchingTaskPositioner mTaskPositioner = new LaunchingTaskPositioner();
+
/** Counter for next free stack ID to use for dynamic activity stacks. */
- private int mNextFreeStackId = FIRST_DYNAMIC_STACK_ID;
+ private int mNextFreeStackId = 0;
/**
* Maps the task identifier that activities are currently being started in to the userId of the
@@ -576,6 +579,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
void setRecentTasks(RecentTasks recentTasks) {
mRecentTasks = recentTasks;
+ mRecentTasks.registerCallback(this);
}
/**
@@ -627,15 +631,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
return stack != null && stack == mFocusedStack;
}
- /** The top most stack on its display. */
- boolean isFrontStackOnDisplay(ActivityStack stack) {
- return isFrontOfStackList(stack, stack.getDisplay().mStacks);
- }
-
- private boolean isFrontOfStackList(ActivityStack stack, List<ActivityStack> stackList) {
- return stack == stackList.get((stackList.size() - 1));
- }
-
/** NOTE: Should only be called from {@link ActivityStack#moveToFront} */
void setFocusStackUnchecked(String reason, ActivityStack focusCandidate) {
if (!focusCandidate.isFocusable()) {
@@ -731,9 +726,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
final TaskRecord task = stack.taskForIdLocked(id);
if (task != null) {
return task;
@@ -749,7 +744,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// Otherwise, check the recent tasks and return if we find it there and we are not restoring
// the task from recents
if (DEBUG_RECENTS) Slog.v(TAG_RECENTS, "Looking for task id=" + id + " in recents");
- final TaskRecord task = mRecentTasks.taskForIdLocked(id);
+ final TaskRecord task = mRecentTasks.getTask(id);
if (task == null) {
if (DEBUG_RECENTS) {
@@ -776,9 +771,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
ActivityRecord isInAnyStackLocked(IBinder token) {
int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityRecord r = stacks.get(stackNdx).isInStackLocked(token);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ final ActivityRecord r = stack.isInStackLocked(token);
if (r != null) {
return r;
}
@@ -816,18 +812,21 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
void lockAllProfileTasks(@UserIdInt int userId) {
mWindowManager.deferSurfaceLayout();
try {
- final List<ActivityStack> stacks = getStacks();
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; stackNdx--) {
- final List<TaskRecord> tasks = stacks.get(stackNdx).getAllTasks();
- for (int taskNdx = tasks.size() - 1; taskNdx >= 0; taskNdx--) {
- final TaskRecord task = tasks.get(taskNdx);
-
- // Check the task for a top activity belonging to userId, or returning a result
- // to an activity belonging to userId. Example case: a document picker for
- // personal files, opened by a work app, should still get locked.
- if (taskTopActivityIsUser(task, userId)) {
- mService.mTaskChangeNotificationController.notifyTaskProfileLocked(
- task.taskId, userId);
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ final List<TaskRecord> tasks = stack.getAllTasks();
+ for (int taskNdx = tasks.size() - 1; taskNdx >= 0; taskNdx--) {
+ final TaskRecord task = tasks.get(taskNdx);
+
+ // Check the task for a top activity belonging to userId, or returning a
+ // result to an activity belonging to userId. Example case: a document
+ // picker for personal files, opened by a work app, should still get locked.
+ if (taskTopActivityIsUser(task, userId)) {
+ mService.mTaskChangeNotificationController.notifyTaskProfileLocked(
+ task.taskId, userId);
+ }
}
}
}
@@ -858,7 +857,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// [u*MAX_TASK_IDS_PER_USER, (u+1)*MAX_TASK_IDS_PER_USER-1], so if MAX_TASK_IDS_PER_USER
// was 10, user 0 could only have taskIds 0 to 9, user 1: 10 to 19, user 2: 20 to 29, so on.
int candidateTaskId = nextTaskIdForUser(currentTaskId, userId);
- while (mRecentTasks.taskIdTakenForUserLocked(candidateTaskId, userId)
+ while (mRecentTasks.containsTaskId(candidateTaskId, userId)
|| anyTaskForIdLocked(
candidateTaskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) != null) {
candidateTaskId = nextTaskIdForUser(candidateTaskId, userId);
@@ -893,9 +892,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
final String processName = app.processName;
boolean didSomething = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
if (!isFocusedStack(stack)) {
continue;
}
@@ -928,9 +927,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
boolean allResumedActivitiesIdle() {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
if (!isFocusedStack(stack) || stack.numActivities() == 0) {
continue;
}
@@ -949,9 +948,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
boolean allResumedActivitiesComplete() {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
if (isFocusedStack(stack)) {
final ActivityRecord r = stack.mResumedActivity;
if (r != null && r.state != RESUMED) {
@@ -968,12 +967,12 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
return true;
}
- boolean allResumedActivitiesVisible() {
+ private boolean allResumedActivitiesVisible() {
boolean foundResumed = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
final ActivityRecord r = stack.mResumedActivity;
if (r != null) {
if (!r.nowVisible || mActivitiesWaitingForVisibleActivity.contains(r)) {
@@ -997,9 +996,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming, boolean dontWait) {
boolean someActivityPaused = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
if (!isFocusedStack(stack) && stack.mResumedActivity != null) {
if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
" mResumedActivity=" + stack.mResumedActivity);
@@ -1014,9 +1013,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
boolean allPausedActivitiesComplete() {
boolean pausing = true;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
final ActivityRecord r = stack.mPausingActivity;
if (r != null && r.state != PAUSED && r.state != STOPPED && r.state != STOPPING) {
if (DEBUG_STATES) {
@@ -1034,9 +1033,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
void cancelInitializingActivities() {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- stacks.get(stackNdx).cancelInitializingActivities();
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ stack.cancelInitializingActivities();
}
}
}
@@ -1134,13 +1134,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
for (int i = mTmpOrderedDisplayIds.size() - 1; i >= 0; --i) {
final int displayId = mTmpOrderedDisplayIds.get(i);
- final List<ActivityStack> stacks = mActivityDisplays.get(displayId).mStacks;
- if (stacks == null) {
- continue;
- }
- for (int j = stacks.size() - 1; j >= 0; --j) {
- final ActivityStack stack = stacks.get(j);
- if (stack != focusedStack && isFrontStackOnDisplay(stack) && stack.isFocusable()) {
+ final ActivityDisplay display = mActivityDisplays.get(displayId);
+ for (int j = display.getChildCount() - 1; j >= 0; --j) {
+ final ActivityStack stack = display.getChildAt(j);
+ if (stack != focusedStack && stack.isTopStackOnDisplay() && stack.isFocusable()) {
r = stack.topRunningActivityLocked();
if (r != null) {
return r;
@@ -1156,9 +1153,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
ArrayList<ArrayList<RunningTaskInfo>> runningTaskLists = new ArrayList<>();
final int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
ArrayList<RunningTaskInfo> stackTaskList = new ArrayList<>();
runningTaskLists.add(stackTaskList);
stack.getTasksLocked(stackTaskList, callingUid, allowed);
@@ -1607,6 +1604,16 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
+ // Check if someone tries to launch an unwhitelisted activity into LockTask mode.
+ final boolean lockTaskMode = options.getLockTaskMode();
+ if (lockTaskMode && !mService.mLockTaskController.isPackageWhitelisted(
+ UserHandle.getUserId(callingUid), aInfo.packageName)) {
+ final String msg = "Permission Denial: starting " + intent.toString()
+ + " from " + callerApp + " (pid=" + callingPid
+ + ", uid=" + callingUid + ") with lockTaskMode=true";
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ }
}
return true;
@@ -1928,9 +1935,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
boolean handleAppDiedLocked(ProcessRecord app) {
boolean hasVisibleActivities = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- hasVisibleActivities |= stacks.get(stackNdx).handleAppDiedLocked(app);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ hasVisibleActivities |= stack.handleAppDiedLocked(app);
}
}
return hasVisibleActivities;
@@ -1938,9 +1946,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
void closeSystemDialogsLocked() {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- stacks.get(stackNdx).closeSystemDialogsLocked();
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ stack.closeSystemDialogsLocked();
}
}
}
@@ -1966,9 +1975,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
boolean doit, boolean evenPersistent, int userId) {
boolean didSomething = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
if (stack.finishDisabledPackageActivitiesLocked(
packageName, filterByClasses, doit, evenPersistent, userId)) {
didSomething = true;
@@ -1988,9 +1997,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// hosted by the process that is actually still the foreground.
ProcessRecord fgApp = null;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
if (isFocusedStack(stack)) {
if (stack.mResumedActivity != null) {
fgApp = stack.mResumedActivity.app;
@@ -2040,9 +2049,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
void updateActivityApplicationInfoLocked(ApplicationInfo aInfo) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- stacks.get(stackNdx).updateActivityApplicationInfoLocked(aInfo);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ stack.updateActivityApplicationInfoLocked(aInfo);
}
}
}
@@ -2051,10 +2061,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
TaskRecord finishedTask = null;
ActivityStack focusedStack = getFocusedStack();
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- final int numStacks = stacks.size();
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ final int numStacks = display.getChildCount();
for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityStack stack = display.getChildAt(stackNdx);
TaskRecord t = stack.finishTopRunningActivityLocked(app, reason);
if (stack == focusedStack || finishedTask == null) {
finishedTask = t;
@@ -2066,10 +2076,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
void finishVoiceTask(IVoiceInteractionSession session) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- final int numStacks = stacks.size();
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ final int numStacks = display.getChildCount();
for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityStack stack = display.getChildAt(stackNdx);
stack.finishVoiceTask(session);
}
}
@@ -2105,8 +2115,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// moveTaskToStackUncheckedLocked() should already placed the task on top,
// still need moveTaskToFrontLocked() below for any transition settings.
}
- if (StackId.resizeStackWithLaunchBounds(stack.mStackId)) {
- resizeStackLocked(stack.mStackId, bounds, null /* tempTaskBounds */,
+ if (stack.resizeStackWithLaunchBounds()) {
+ resizeStackLocked(stack, bounds, null /* tempTaskBounds */,
null /* tempTaskInsetBounds */, !PRESERVE_WINDOWS,
true /* allowResizeInDockedMode */, !DEFER_RESUME);
} else {
@@ -2125,7 +2135,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
"findTaskToMoveToFront: moved to front of stack=" + currentStack);
handleNonResizableTaskIfNeeded(task, WINDOWING_MODE_UNDEFINED, DEFAULT_DISPLAY,
- currentStack.mStackId, forceNonResizeable);
+ currentStack, forceNonResizeable);
}
boolean canUseActivityOptionsLaunchBounds(ActivityOptions options) {
@@ -2139,6 +2149,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
|| mService.mSupportsFreeformWindowManagement;
}
+ LaunchingTaskPositioner getLaunchingTaskPositioner() {
+ return mTaskPositioner;
+ }
+
protected <T extends ActivityStack> T getStack(int stackId) {
for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
final T stack = mActivityDisplays.valueAt(i).getStack(stackId);
@@ -2316,8 +2330,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
final ActivityDisplay display = getActivityDisplayOrCreateLocked(displayId);
if (display != null) {
- for (int i = display.mStacks.size() - 1; i >= 0; --i) {
- stack = (T) display.mStacks.get(i);
+ for (int i = display.getChildCount() - 1; i >= 0; --i) {
+ stack = (T) display.getChildAt(i);
if (stack.isCompatible(windowingMode, activityType)) {
return stack;
}
@@ -2385,8 +2399,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
// Return the topmost valid stack on the display.
- for (int i = activityDisplay.mStacks.size() - 1; i >= 0; --i) {
- final ActivityStack stack = activityDisplay.mStacks.get(i);
+ for (int i = activityDisplay.getChildCount() - 1; i >= 0; --i) {
+ final ActivityStack stack = activityDisplay.getChildAt(i);
if (isValidLaunchStack(stack, displayId, r)) {
return stack;
}
@@ -2417,25 +2431,13 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY: return r.supportsSplitScreenWindowingMode();
}
- if (StackId.isDynamicStack(stack.mStackId)) {
+ if (!stack.isOnHomeDisplay()) {
return r.canBeLaunchedOnDisplay(displayId);
}
Slog.e(TAG, "isValidLaunchStack: Unexpected stack=" + stack);
return false;
}
- ArrayList<ActivityStack> getStacks() {
- ArrayList<ActivityStack> allStacks = new ArrayList<>();
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- allStacks.addAll(mActivityDisplays.valueAt(displayNdx).mStacks);
- }
- return allStacks;
- }
-
- ArrayList<ActivityStack> getStacksOnDefaultDisplay() {
- return mActivityDisplays.valueAt(DEFAULT_DISPLAY).mStacks;
- }
-
/**
* Get next focusable stack in the system. This will search across displays and stacks
* in last-focused order for a focusable and visible stack, different from the target stack.
@@ -2450,10 +2452,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
for (int i = mTmpOrderedDisplayIds.size() - 1; i >= 0; --i) {
final int displayId = mTmpOrderedDisplayIds.get(i);
// If a display is registered in WM, it must also be available in AM.
- @SuppressWarnings("ConstantConditions")
- final List<ActivityStack> stacks = getActivityDisplayOrCreateLocked(displayId).mStacks;
- for (int j = stacks.size() - 1; j >= 0; --j) {
- final ActivityStack stack = stacks.get(j);
+ final ActivityDisplay display = getActivityDisplayOrCreateLocked(displayId);
+ for (int j = display.getChildCount() - 1; j >= 0; --j) {
+ final ActivityStack stack = display.getChildAt(j);
if (stack != currentFocus && stack.isFocusable()
&& stack.shouldBeVisible(null)) {
return stack;
@@ -2511,20 +2512,17 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
return null;
}
- void resizeStackLocked(int stackId, Rect bounds, Rect tempTaskBounds, Rect tempTaskInsetBounds,
- boolean preserveWindows, boolean allowResizeInDockedMode, boolean deferResume) {
- if (stackId == DOCKED_STACK_ID) {
+ void resizeStackLocked(ActivityStack stack, Rect bounds, Rect tempTaskBounds,
+ Rect tempTaskInsetBounds, boolean preserveWindows, boolean allowResizeInDockedMode,
+ boolean deferResume) {
+
+ if (stack.inSplitScreenPrimaryWindowingMode()) {
resizeDockedStackLocked(bounds, tempTaskBounds, tempTaskInsetBounds, null, null,
preserveWindows, deferResume);
return;
}
- final ActivityStack stack = getStack(stackId);
- if (stack == null) {
- Slog.w(TAG, "resizeStack: stackId " + stackId + " not found.");
- return;
- }
- final boolean splitScreenActive = getDefaultDisplay().hasSplitScreenStack();
+ final boolean splitScreenActive = getDefaultDisplay().hasSplitScreenPrimaryStack();
if (!allowResizeInDockedMode
&& !stack.getWindowConfiguration().tasksAreFloating() && splitScreenActive) {
// If the docked stack exists, don't resize non-floating stacks independently of the
@@ -2532,7 +2530,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
return;
}
- Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeStack_" + stackId);
+ Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeStack_" + stack.mStackId);
mWindowManager.deferSurfaceLayout();
try {
if (stack.supportsSplitScreenWindowingMode()) {
@@ -2584,8 +2582,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
/**
* TODO: This should just change the windowing mode and resize vs. actually moving task around.
- * Can do that once we are no longer using static stack ids. Specially when
- * {@link ActivityManager.StackId#FULLSCREEN_WORKSPACE_STACK_ID} is removed.
+ * Can do that once we are no longer using static stack ids.
*/
private void moveTasksToFullscreenStackInSurfaceTransaction(ActivityStack fromStack,
int toDisplayId, boolean onTop) {
@@ -2600,13 +2597,12 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// We are moving all tasks from the docked stack to the fullscreen stack,
// which is dismissing the docked stack, so resize all other stacks to
// fullscreen here already so we don't end up with resize trashing.
- final ArrayList<ActivityStack> displayStacks = toDisplay.mStacks;
- for (int i = displayStacks.size() - 1; i >= 0; --i) {
- final ActivityStack otherStack = displayStacks.get(i);
+ for (int i = toDisplay.getChildCount() - 1; i >= 0; --i) {
+ final ActivityStack otherStack = toDisplay.getChildAt(i);
if (!otherStack.inSplitScreenSecondaryWindowingMode()) {
continue;
}
- resizeStackLocked(otherStack.mStackId, null, null, null, PRESERVE_WINDOWS,
+ resizeStackLocked(otherStack, null, null, null, PRESERVE_WINDOWS,
true /* allowResizeInDockedMode */, DEFER_RESUME);
}
@@ -2697,8 +2693,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
return;
}
- final ActivityStack stack = getDefaultDisplay().getStack(
- WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
+ final ActivityStack stack = getDefaultDisplay().getSplitScreenPrimaryStack();
if (stack == null) {
Slog.w(TAG, "resizeDockedStackLocked: docked stack not found");
return;
@@ -2727,10 +2722,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// static stacks need to be adjusted so they don't overlap with the docked stack.
// We get the bounds to use from window manager which has been adjusted for any
// screen controls and is also the same for all stacks.
- final ArrayList<ActivityStack> stacks = getStacksOnDefaultDisplay();
+ final ActivityDisplay display = getDefaultDisplay();
final Rect otherTaskRect = new Rect();
- for (int i = stacks.size() - 1; i >= 0; --i) {
- final ActivityStack current = stacks.get(i);
+ for (int i = display.getChildCount() - 1; i >= 0; --i) {
+ final ActivityStack current = display.getChildAt(i);
if (current.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
continue;
}
@@ -2744,7 +2739,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
tempRect /* outStackBounds */,
otherTaskRect /* outTempTaskBounds */, true /* ignoreVisibility */);
- resizeStackLocked(current.mStackId, !tempRect.isEmpty() ? tempRect : null,
+ resizeStackLocked(current, !tempRect.isEmpty() ? tempRect : null,
!otherTaskRect.isEmpty() ? otherTaskRect : tempOtherTaskBounds,
tempOtherTaskInsetBounds, preserveWindows,
true /* allowResizeInDockedMode */, deferResume);
@@ -2762,8 +2757,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
void resizePinnedStackLocked(Rect pinnedBounds, Rect tempPinnedTaskBounds) {
// TODO(multi-display): Pinned stack display should be passed in.
- final PinnedActivityStack stack = getDefaultDisplay().getStack(
- WINDOWING_MODE_PINNED, ACTIVITY_TYPE_UNDEFINED);
+ final PinnedActivityStack stack = getDefaultDisplay().getPinnedStack();
if (stack == null) {
Slog.w(TAG, "resizePinnedStackLocked: pinned stack not found");
return;
@@ -2801,12 +2795,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
}
- private void removeStackInSurfaceTransaction(int stackId) {
- final ActivityStack stack = getStack(stackId);
- if (stack == null) {
- return;
- }
-
+ private void removeStackInSurfaceTransaction(ActivityStack stack) {
final ArrayList<TaskRecord> tasks = stack.getAllTasks();
if (stack.getWindowingMode() == WINDOWING_MODE_PINNED) {
/**
@@ -2836,12 +2825,12 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
/**
- * Removes the stack associated with the given {@param stackId}. If the {@param stackId} is the
+ * Removes the stack associated with the given {@param stack}. If the {@param stack} is the
* pinned stack, then its tasks are not explicitly removed when the stack is destroyed, but
* instead moved back onto the fullscreen stack.
*/
- void removeStackLocked(int stackId) {
- mWindowManager.inSurfaceTransaction(() -> removeStackInSurfaceTransaction(stackId));
+ void removeStack(ActivityStack stack) {
+ mWindowManager.inSurfaceTransaction(() -> removeStackInSurfaceTransaction(stack));
}
/**
@@ -2892,23 +2881,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
return false;
}
- void addRecentActivity(ActivityRecord r) {
- if (r == null) {
- return;
- }
- final TaskRecord task = r.getTask();
- mRecentTasks.addLocked(task);
- task.touchActiveTime();
- }
-
- void removeTaskFromRecents(TaskRecord task) {
- mRecentTasks.remove(task);
- task.removedFromRecents();
- }
-
void cleanUpRemovedTaskLocked(TaskRecord tr, boolean killProcess, boolean removeFromRecents) {
if (removeFromRecents) {
- removeTaskFromRecents(tr);
+ mRecentTasks.remove(tr);
}
ComponentName component = tr.getBaseIntent().getComponent();
if (component == null) {
@@ -2979,8 +2954,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
int getNextStackId() {
while (true) {
- if (mNextFreeStackId >= FIRST_DYNAMIC_STACK_ID
- && getStack(mNextFreeStackId) == null) {
+ if (getStack(mNextFreeStackId) == null) {
break;
}
mNextFreeStackId++;
@@ -2989,7 +2963,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
/**
- * Restores a recent task to a stack
+ * Called to restore the state of the task into the stack that it's supposed to go into.
+ *
* @param task The recent task to be restored.
* @param aOptions The activity options to use for restoration.
* @return true if the task has been restored successfully.
@@ -3020,6 +2995,22 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
return true;
}
+ @Override
+ public void onRecentTaskAdded(TaskRecord task) {
+ task.touchActiveTime();
+ }
+
+ @Override
+ public void onRecentTaskRemoved(TaskRecord task, boolean wasTrimmed) {
+ if (wasTrimmed) {
+ // Task was trimmed from the recent tasks list -- remove the active task record as well
+ // since the user won't really be able to go back to it
+ removeTaskByIdLocked(task.taskId, false /* killProcess */,
+ false /* removeFromRecents */);
+ }
+ task.removedFromRecents();
+ }
+
/**
* Move stack with all its existing content to specified display.
* @param stackId Id of stack to move.
@@ -3160,7 +3151,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// Resize the pinned stack to match the current size of the task the activity we are
// going to be moving is currently contained in. We do this to have the right starting
// animation bounds for the pinned stack to the desired bounds the caller wants.
- resizeStackLocked(PINNED_STACK_ID, task.mBounds, null /* tempTaskBounds */,
+ resizeStackLocked(stack, task.mBounds, null /* tempTaskBounds */,
null /* tempTaskInsetBounds */, !PRESERVE_WINDOWS,
true /* allowResizeInDockedMode */, !DEFER_RESUME);
@@ -3257,9 +3248,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
ActivityRecord affinityMatch = null;
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + r);
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
if (!r.hasCompatibleActivityType(stack)) {
if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping stack: (mismatch activity/stack) "
+ stack);
@@ -3292,12 +3283,13 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
ActivityRecord findActivityLocked(Intent intent, ActivityInfo info,
- boolean compareIntentFilters) {
+ boolean compareIntentFilters) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityRecord ar = stacks.get(stackNdx)
- .findActivityLocked(intent, info, compareIntentFilters);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ final ActivityRecord ar = stack.findActivityLocked(
+ intent, info, compareIntentFilters);
if (ar != null) {
return ar;
}
@@ -3391,9 +3383,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
// Set the sleeping state of the stacks on the display.
- final ArrayList<ActivityStack> stacks = display.mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
if (displayShouldSleep) {
stack.goToSleepIfPossible(false /* shuttingDown */);
} else {
@@ -3455,12 +3446,13 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
private boolean putStacksToSleepLocked(boolean allowDelay, boolean shuttingDown) {
boolean allSleep = true;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
if (allowDelay) {
- allSleep &= stacks.get(stackNdx).goToSleepIfPossible(shuttingDown);
+ allSleep &= stack.goToSleepIfPossible(shuttingDown);
} else {
- stacks.get(stackNdx).goToSleep();
+ stack.goToSleep();
}
}
}
@@ -3485,11 +3477,10 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
void handleAppCrashLocked(ProcessRecord app) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- int stackNdx = stacks.size() - 1;
- while (stackNdx >= 0) {
- stacks.get(stackNdx).handleAppCrashLocked(app);
- stackNdx--;
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ stack.handleAppCrashLocked(app);
}
}
}
@@ -3500,7 +3491,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
final ActivityStack stack = task.getStack();
r.mLaunchTaskBehind = false;
- mRecentTasks.addLocked(task);
+ mRecentTasks.add(task);
mService.mTaskChangeNotificationController.notifyTaskStackChanged();
r.setVisibility(false);
@@ -3522,10 +3513,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
try {
// First the front stacks. In case any are not fullscreen and are in front of home.
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- final int topStackNdx = stacks.size() - 1;
- for (int stackNdx = topStackNdx; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
stack.ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows);
}
}
@@ -3536,10 +3526,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
void addStartingWindowsForVisibleActivities(boolean taskSwitch) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- final int topStackNdx = stacks.size() - 1;
- for (int stackNdx = topStackNdx; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
stack.addStartingWindowsForVisibleActivities(taskSwitch);
}
}
@@ -3555,20 +3544,20 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
mTaskLayersChanged = false;
for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); displayNdx++) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
int baseLayer = 0;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- baseLayer += stacks.get(stackNdx).rankTaskLayers(baseLayer);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ baseLayer += stack.rankTaskLayers(baseLayer);
}
}
}
void clearOtherAppTimeTrackers(AppTimeTracker except) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- final int topStackNdx = stacks.size() - 1;
- for (int stackNdx = topStackNdx; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
stack.clearOtherAppTimeTrackers(except);
}
}
@@ -3576,10 +3565,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- final int numStacks = stacks.size();
- for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
stack.scheduleDestroyActivities(app, reason);
}
}
@@ -3631,10 +3619,11 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// let's iterate through the tasks and release the oldest one.
final int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ final int stackCount = display.getChildCount();
// Step through all stacks starting from behind, to hit the oldest things first.
- for (int stackNdx = 0; stackNdx < stacks.size(); stackNdx++) {
- final ActivityStack stack = stacks.get(stackNdx);
+ for (int stackNdx = 0; stackNdx < stackCount; stackNdx++) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
// Try to release activities in this stack; if we manage to, we are done.
if (stack.releaseSomeActivitiesLocked(app, tasks, reason) > 0) {
return;
@@ -3646,14 +3635,14 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
boolean switchUserLocked(int userId, UserState uss) {
final int focusStackId = mFocusedStack.getStackId();
// We dismiss the docked stack whenever we switch users.
- final ActivityStack dockedStack = getDefaultDisplay().getSplitScreenStack();
+ final ActivityStack dockedStack = getDefaultDisplay().getSplitScreenPrimaryStack();
if (dockedStack != null) {
moveTasksToFullscreenStackLocked(dockedStack, mFocusedStack == dockedStack);
}
// Also dismiss the pinned stack whenever we switch users. Removing the pinned stack will
// also cause all tasks to be moved to the fullscreen stack at a position that is
// appropriate.
- removeStackLocked(PINNED_STACK_ID);
+ removeStacksInWindowingModes(WINDOWING_MODE_PINNED);
mUserStackInFront.put(mCurrentUser, focusStackId);
final int restoreStackId = mUserStackInFront.get(userId, mHomeStack.mStackId);
@@ -3661,9 +3650,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
mStartingUsers.add(uss);
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
stack.switchUserLocked(userId);
TaskRecord task = stack.topTask();
if (task != null) {
@@ -3761,9 +3750,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
void validateTopActivitiesLocked() {
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
final ActivityRecord r = stack.topRunningActivityLocked();
final ActivityState state = r == null ? DESTROYED : r.state;
if (isFocusedStack(stack)) {
@@ -3798,7 +3787,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
pw.print(prefix); pw.println("mUserStackInFront=" + mUserStackInFront);
for (int i = mActivityDisplays.size() - 1; i >= 0; --i) {
final ActivityDisplay display = mActivityDisplays.valueAt(i);
- pw.println(prefix + "displayId=" + display.mDisplayId + " mStacks=" + display.mStacks);
+ display.dump(pw, prefix);
}
if (!mWaitingForActivityVisible.isEmpty()) {
pw.print(prefix); pw.println("mWaitingForActivityVisible=");
@@ -3811,8 +3800,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
mService.mLockTaskController.dump(pw, prefix);
}
- public void writeToProto(ProtoOutputStream proto, long fieldId) {
- final long token = proto.start(fieldId);
+ public void writeToProto(ProtoOutputStream proto) {
super.writeToProto(proto, CONFIGURATION_CONTAINER);
for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
ActivityDisplay activityDisplay = mActivityDisplays.valueAt(displayNdx);
@@ -3828,7 +3816,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
} else {
proto.write(FOCUSED_STACK_ID, INVALID_STACK_ID);
}
- proto.end(token);
}
/**
@@ -3857,9 +3844,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
ArrayList<ActivityRecord> activities = new ArrayList<>();
int numDisplays = mActivityDisplays.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
if (!dumpVisibleStacksOnly || stack.shouldBeVisible(null)) {
activities.addAll(stack.getDumpActivitiesLocked(name));
}
@@ -3892,11 +3879,13 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
ActivityDisplay activityDisplay = mActivityDisplays.valueAt(displayNdx);
pw.print("Display #"); pw.print(activityDisplay.mDisplayId);
pw.println(" (activities from top to bottom):");
- ArrayList<ActivityStack> stacks = activityDisplay.mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
pw.println();
- pw.println(" Stack #" + stack.mStackId + ":");
+ pw.println(" Stack #" + stack.mStackId
+ + ": type=" + activityTypeToString(stack.getActivityType())
+ + " mode=" + windowingModeToString(stack.getWindowingMode()));
pw.println(" mFullscreen=" + stack.mFullscreen);
pw.println(" isSleeping=" + stack.shouldSleepActivities());
pw.println(" mBounds=" + stack.mBounds);
@@ -4140,30 +4129,29 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
synchronized (mService) {
- ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
- if (activityDisplay != null) {
- final boolean destroyContentOnRemoval
- = activityDisplay.shouldDestroyContentOnRemove();
- final ArrayList<ActivityStack> stacks = activityDisplay.mStacks;
- while (!stacks.isEmpty()) {
- final ActivityStack stack = stacks.get(0);
- if (destroyContentOnRemoval) {
- moveStackToDisplayLocked(stack.mStackId, DEFAULT_DISPLAY,
- false /* onTop */);
- stack.finishAllActivitiesLocked(true /* immediately */);
- } else {
- // Moving all tasks to fullscreen stack, because it's guaranteed to be
- // a valid launch stack for all activities. This way the task history from
- // external display will be preserved on primary after move.
- moveTasksToFullscreenStackLocked(stack, true /* onTop */);
- }
+ final ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
+ if (activityDisplay == null) {
+ return;
+ }
+ final boolean destroyContentOnRemoval
+ = activityDisplay.shouldDestroyContentOnRemove();
+ while (activityDisplay.getChildCount() > 0) {
+ final ActivityStack stack = activityDisplay.getChildAt(0);
+ if (destroyContentOnRemoval) {
+ moveStackToDisplayLocked(stack.mStackId, DEFAULT_DISPLAY, false /* onTop */);
+ stack.finishAllActivitiesLocked(true /* immediately */);
+ } else {
+ // Moving all tasks to fullscreen stack, because it's guaranteed to be
+ // a valid launch stack for all activities. This way the task history from
+ // external display will be preserved on primary after move.
+ moveTasksToFullscreenStackLocked(stack, true /* onTop */);
}
+ }
- releaseSleepTokens(activityDisplay);
+ releaseSleepTokens(activityDisplay);
- mActivityDisplays.remove(displayId);
- mWindowManager.onDisplayRemoved(displayId);
- }
+ mActivityDisplays.remove(displayId);
+ mWindowManager.onDisplayRemoved(displayId);
}
}
@@ -4235,7 +4223,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
info.userId = stack.mCurrentUser;
info.visible = stack.shouldBeVisible(null);
// A stack might be not attached to a display.
- info.position = display != null ? display.mStacks.indexOf(stack) : 0;
+ info.position = display != null ? display.getIndexOf(stack) : 0;
info.configuration.setTo(stack.getConfiguration());
ArrayList<TaskRecord> tasks = stack.getAllTasks();
@@ -4281,25 +4269,25 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
ArrayList<StackInfo> getAllStackInfosLocked() {
ArrayList<StackInfo> list = new ArrayList<>();
for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
- ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- for (int ndx = stacks.size() - 1; ndx >= 0; --ndx) {
- list.add(getStackInfo(stacks.get(ndx)));
+ final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
+ list.add(getStackInfo(stack));
}
}
return list;
}
void handleNonResizableTaskIfNeeded(TaskRecord task, int preferredWindowingMode,
- int preferredDisplayId, int actualStackId) {
+ int preferredDisplayId, ActivityStack actualStack) {
handleNonResizableTaskIfNeeded(task, preferredWindowingMode, preferredDisplayId,
- actualStackId, false /* forceNonResizable */);
+ actualStack, false /* forceNonResizable */);
}
void handleNonResizableTaskIfNeeded(TaskRecord task, int preferredWindowingMode,
- int preferredDisplayId, int actualStackId, boolean forceNonResizable) {
+ int preferredDisplayId, ActivityStack actualStack, boolean forceNonResizable) {
final boolean isSecondaryDisplayPreferred =
(preferredDisplayId != DEFAULT_DISPLAY && preferredDisplayId != INVALID_DISPLAY);
- final ActivityStack actualStack = getStack(actualStackId);
final boolean inSplitScreenMode = actualStack != null
&& actualStack.inSplitScreenWindowingMode();
if (((!inSplitScreenMode && preferredWindowingMode != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)
@@ -4315,8 +4303,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// The task landed on an inappropriate display somehow, move it to the default
// display.
// TODO(multi-display): Find proper stack for the task on the default display.
- mService.moveTaskToStack(task.taskId, FULLSCREEN_WORKSPACE_STACK_ID,
- true /* toTop */);
+ mService.setTaskWindowingMode(task.taskId,
+ WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY, true /* toTop */);
launchOnSecondaryDisplayFailed = true;
} else {
// The task might have landed on a display different from requested.
@@ -4346,10 +4334,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
// Dismiss docked stack. If task appeared to be in docked stack but is not resizable -
// we need to move it to top of fullscreen stack, otherwise it will be covered.
- final ActivityStack dockedStack = task.getStack().getDisplay().getSplitScreenStack();
+ final ActivityStack dockedStack = task.getStack().getDisplay().getSplitScreenPrimaryStack();
if (dockedStack != null) {
- moveTasksToFullscreenStackLocked(dockedStack,
- actualStackId == dockedStack.getStackId());
+ moveTasksToFullscreenStackLocked(dockedStack, actualStack == dockedStack);
}
} else if (topActivity != null && topActivity.isNonResizableOrForcedResizable()
&& !topActivity.noDisplay) {
@@ -4402,7 +4389,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
void scheduleUpdatePictureInPictureModeIfNeeded(TaskRecord task, ActivityStack prevStack) {
final ActivityStack stack = task.getStack();
if (prevStack == null || prevStack == stack
- || (prevStack.mStackId != PINNED_STACK_ID && stack.mStackId != PINNED_STACK_ID)) {
+ || (!prevStack.inPinnedWindowingMode() && !stack.inPinnedWindowingMode())) {
return;
}
@@ -4561,14 +4548,13 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
if (display == null) {
return null;
}
- final ArrayList<ActivityStack> stacks = display.mStacks;
- for (int i = stacks.size() - 1; i >= 0; i--) {
- if (stacks.get(i) == stack && i > 0) {
- return stacks.get(i - 1);
+ for (int i = display.getChildCount() - 1; i >= 0; i--) {
+ if (display.getChildAt(i) == stack && i > 0) {
+ return display.getChildAt(i - 1);
}
}
throw new IllegalStateException("Failed to find a stack behind stack=" + stack
- + " in=" + stacks);
+ + " in=" + display);
}
/**
@@ -4681,8 +4667,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
for (int i = mActivityDisplays.size() - 1; i >= 0; i--) {
final ActivityDisplay display = mActivityDisplays.valueAt(i);
// Traverse all stacks on a display.
- for (int j = display.mStacks.size() - 1; j >= 0; j--) {
- final ActivityStack stack = display.mStacks.get(j);
+ for (int j = display.getChildCount() - 1; j >= 0; --j) {
+ final ActivityStack stack = display.getChildAt(j);
// Get top activity from a visible stack and add it to the list.
if (stack.shouldBeVisible(null /* starting */)) {
final ActivityRecord top = stack.topActivity();
diff --git a/com/android/server/am/ActivityStarter.java b/com/android/server/am/ActivityStarter.java
index d444c663..6f74d851 100644
--- a/com/android/server/am/ActivityStarter.java
+++ b/com/android/server/am/ActivityStarter.java
@@ -26,15 +26,9 @@ import static android.app.ActivityManager.START_RETURN_INTENT_TO_CALLER;
import static android.app.ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
import static android.app.ActivityManager.START_SUCCESS;
import static android.app.ActivityManager.START_TASK_TO_FRONT;
-import static android.app.ActivityManager.StackId;
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
-import static android.app.ActivityManager.StackId.isDynamicStack;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
@@ -121,7 +115,6 @@ import com.android.internal.app.HeavyWeightSwitcherActivity;
import com.android.internal.app.IVoiceInteractor;
import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
import com.android.server.pm.InstantAppResolver;
-import com.android.server.wm.WindowManagerService;
import java.io.PrintWriter;
import java.text.DateFormat;
@@ -140,11 +133,11 @@ class ActivityStarter {
private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
+ private static final int INVALID_LAUNCH_MODE = -1;
private final ActivityManagerService mService;
private final ActivityStackSupervisor mSupervisor;
private final ActivityStartInterceptor mInterceptor;
- private WindowManagerService mWindowManager;
final ArrayList<PendingActivityLaunch> mPendingActivityLaunches = new ArrayList<>();
@@ -154,9 +147,7 @@ class ActivityStarter {
private int mCallingUid;
private ActivityOptions mOptions;
- private boolean mLaunchSingleTop;
- private boolean mLaunchSingleInstance;
- private boolean mLaunchSingleTask;
+ private int mLaunchMode;
private boolean mLaunchTaskBehind;
private int mLaunchFlags;
@@ -166,6 +157,7 @@ class ActivityStarter {
private boolean mDoResume;
private int mStartFlags;
private ActivityRecord mSourceRecord;
+
// The display to launch the activity onto, barring any strong reason to do otherwise.
private int mPreferredDisplayId;
@@ -195,8 +187,6 @@ class ActivityStarter {
private IVoiceInteractionSession mVoiceSession;
private IVoiceInteractor mVoiceInteractor;
- private boolean mUsingVr2dDisplay;
-
// Last home activity record we attempted to start
private final ActivityRecord[] mLastHomeActivityStartRecord = new ActivityRecord[1];
// The result of the last home activity we attempted to start.
@@ -216,11 +206,9 @@ class ActivityStarter {
mCallingUid = -1;
mOptions = null;
- mLaunchSingleTop = false;
- mLaunchSingleInstance = false;
- mLaunchSingleTask = false;
mLaunchTaskBehind = false;
mLaunchFlags = 0;
+ mLaunchMode = INVALID_LAUNCH_MODE;
mLaunchBounds = null;
@@ -248,16 +236,13 @@ class ActivityStarter {
mVoiceSession = null;
mVoiceInteractor = null;
- mUsingVr2dDisplay = false;
-
mIntentDelivered = false;
}
- ActivityStarter(ActivityManagerService service, ActivityStackSupervisor supervisor) {
+ ActivityStarter(ActivityManagerService service) {
mService = service;
- mSupervisor = supervisor;
+ mSupervisor = mService.mStackSupervisor;
mInterceptor = new ActivityStartInterceptor(mService, mSupervisor);
- mUsingVr2dDisplay = false;
}
int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
@@ -610,38 +595,41 @@ class ActivityStarter {
mSupervisor.reportTaskToFrontNoLaunch(mStartActivity);
}
- int startedActivityStackId = INVALID_STACK_ID;
+ ActivityStack startedActivityStack = null;
final ActivityStack currentStack = r.getStack();
if (currentStack != null) {
- startedActivityStackId = currentStack.mStackId;
+ startedActivityStack = currentStack;
} else if (mTargetStack != null) {
- startedActivityStackId = targetStack.mStackId;
+ startedActivityStack = targetStack;
}
- if (startedActivityStackId == DOCKED_STACK_ID) {
- final ActivityStack homeStack = mSupervisor.getDefaultDisplay().getStack(
- WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME);
+ if (startedActivityStack == null) {
+ return;
+ }
+
+ if (startedActivityStack.inSplitScreenPrimaryWindowingMode()) {
+ final ActivityStack homeStack = mSupervisor.mHomeStack;
final boolean homeStackVisible = homeStack != null && homeStack.isVisible();
if (homeStackVisible) {
// We launch an activity while being in home stack, which means either launcher or
// recents into docked stack. We don't want the launched activity to be alone in a
// docked stack, so we want to immediately launch recents too.
if (DEBUG_RECENTS) Slog.d(TAG, "Scheduling recents launch.");
- mWindowManager.showRecentApps(true /* fromHome */);
+ mService.mWindowManager.showRecentApps(true /* fromHome */);
}
return;
}
boolean clearedTask = (mLaunchFlags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK))
== (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TASK) && (mReuseTask != null);
- if (startedActivityStackId == PINNED_STACK_ID && (result == START_TASK_TO_FRONT
- || result == START_DELIVERED_TO_TOP || clearedTask)) {
+ if (startedActivityStack.inPinnedWindowingMode()
+ && (result == START_TASK_TO_FRONT || result == START_DELIVERED_TO_TOP
+ || clearedTask)) {
// The activity was already running in the pinned stack so it wasn't started, but either
// brought to the front or the new intent was delivered to it since it was already in
// front. Notify anyone interested in this piece of information.
mService.mTaskChangeNotificationController.notifyPinnedActivityRestartAttempt(
clearedTask);
- return;
}
}
@@ -1062,7 +1050,7 @@ class ActivityStarter {
// operations.
if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
|| isDocumentLaunchesIntoExisting(mLaunchFlags)
- || mLaunchSingleInstance || mLaunchSingleTask) {
+ || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
final TaskRecord task = reusedActivity.getTask();
// In this situation we want to remove all activities from the task up to the one
@@ -1145,7 +1133,7 @@ class ActivityStarter {
&& top.userId == mStartActivity.userId
&& top.app != null && top.app.thread != null
&& ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
- || mLaunchSingleTop || mLaunchSingleTask);
+ || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK));
if (dontStart) {
// For paranoia, make sure we have correctly resumed the top activity.
topStack.mLastPausedActivity = null;
@@ -1164,7 +1152,7 @@ class ActivityStarter {
// Don't use mStartActivity.task to show the toast. We're not starting a new activity
// but reusing 'top'. Fields in mStartActivity may not be fully initialized.
mSupervisor.handleNonResizableTaskIfNeeded(top.getTask(), preferredWindowingMode,
- preferredLaunchDisplayId, topStack.mStackId);
+ preferredLaunchDisplayId, topStack);
return START_DELIVERED_TO_TOP;
}
@@ -1227,7 +1215,7 @@ class ActivityStarter {
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();
+ mService.mWindowManager.executeAppTransition();
} else {
// If the target stack was not previously focusable (previous top running activity
// on that stack was not visible) then any prior calls to move the stack to the
@@ -1240,13 +1228,13 @@ class ActivityStarter {
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
}
- } else {
- mSupervisor.addRecentActivity(mStartActivity);
+ } else if (mStartActivity != null) {
+ mSupervisor.mRecentTasks.add(mStartActivity.getTask());
}
mSupervisor.updateUserStackLocked(mStartActivity.userId, mTargetStack);
mSupervisor.handleNonResizableTaskIfNeeded(mStartActivity.getTask(), preferredWindowingMode,
- preferredLaunchDisplayId, mTargetStack.mStackId);
+ preferredLaunchDisplayId, mTargetStack);
return START_SUCCESS;
}
@@ -1268,13 +1256,13 @@ class ActivityStarter {
mLaunchBounds = getOverrideBounds(r, options, inTask);
- mLaunchSingleTop = r.launchMode == LAUNCH_SINGLE_TOP;
- mLaunchSingleInstance = r.launchMode == LAUNCH_SINGLE_INSTANCE;
- mLaunchSingleTask = r.launchMode == LAUNCH_SINGLE_TASK;
+ mLaunchMode = r.launchMode;
+
mLaunchFlags = adjustLaunchFlagsToDocumentMode(
- r, mLaunchSingleInstance, mLaunchSingleTask, mIntent.getFlags());
+ r, LAUNCH_SINGLE_INSTANCE == mLaunchMode,
+ LAUNCH_SINGLE_TASK == mLaunchMode, mIntent.getFlags());
mLaunchTaskBehind = r.mLaunchTaskBehind
- && !mLaunchSingleTask && !mLaunchSingleInstance
+ && !isLaunchModeOneOf(LAUNCH_SINGLE_TASK, LAUNCH_SINGLE_INSTANCE)
&& (mLaunchFlags & FLAG_ACTIVITY_NEW_DOCUMENT) != 0;
sendNewTaskResultRequestIfNeeded();
@@ -1384,7 +1372,7 @@ class ActivityStarter {
// If this task is empty, then we are adding the first activity -- it
// determines the root, and must be launching as a NEW_TASK.
- if (mLaunchSingleInstance || mLaunchSingleTask) {
+ if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
if (!baseIntent.getComponent().equals(mStartActivity.intent.getComponent())) {
ActivityOptions.abort(mOptions);
throw new IllegalArgumentException("Trying to launch singleInstance/Task "
@@ -1427,7 +1415,7 @@ class ActivityStarter {
// in any task/stack, however it could launch other activities like ResolverActivity,
// and we want those to stay in the original task.
if ((mStartActivity.isResolverActivity() || mStartActivity.noDisplay) && mSourceRecord != null
- && mSourceRecord.isFreeform()) {
+ && mSourceRecord.inFreeformWindowingMode()) {
mAddingToTask = true;
}
}
@@ -1446,7 +1434,7 @@ class ActivityStarter {
// instance... this new activity it is starting must go on its
// own task.
mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
- } else if (mLaunchSingleInstance || mLaunchSingleTask) {
+ } else if (isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
// The activity being started is a single instance... it always
// gets launched into its own task.
mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
@@ -1497,7 +1485,7 @@ class ActivityStarter {
// launch this as a new task behind the current one.
boolean putIntoExistingTask = ((mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0 &&
(mLaunchFlags & FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
- || mLaunchSingleInstance || mLaunchSingleTask;
+ || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK);
// If bring to front is requested, and no result is requested and we have not been given
// an explicit task to launch in to, and we can find a task that was started with this
// same component, then instead of launching bring that one to the front.
@@ -1507,7 +1495,7 @@ class ActivityStarter {
final TaskRecord task = mSupervisor.anyTaskForIdLocked(mOptions.getLaunchTaskId());
intentActivity = task != null ? task.getTopActivity() : null;
} else if (putIntoExistingTask) {
- if (mLaunchSingleInstance) {
+ if (LAUNCH_SINGLE_INSTANCE == mLaunchMode) {
// There can be one and only one instance of single instance activity in the
// history, and it is always in its own unique task, so we do a special search.
intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
@@ -1516,7 +1504,7 @@ class ActivityStarter {
// For the launch adjacent case we only want to put the activity in an existing
// task if the activity already exists in the history.
intentActivity = mSupervisor.findActivityLocked(mIntent, mStartActivity.info,
- !mLaunchSingleTask);
+ !(LAUNCH_SINGLE_TASK == mLaunchMode));
} else {
// Otherwise find the best task to put the activity in.
intentActivity = mSupervisor.findTaskLocked(mStartActivity, mPreferredDisplayId);
@@ -1545,7 +1533,6 @@ class ActivityStarter {
if (DEBUG_STACK) {
Slog.d(TAG, "getSourceDisplayId :" + displayId);
}
- mUsingVr2dDisplay = true;
return displayId;
}
@@ -1667,7 +1654,7 @@ class ActivityStarter {
}
mSupervisor.handleNonResizableTaskIfNeeded(intentActivity.getTask(),
- WINDOWING_MODE_UNDEFINED, DEFAULT_DISPLAY, mTargetStack.mStackId);
+ WINDOWING_MODE_UNDEFINED, DEFAULT_DISPLAY, mTargetStack);
// If the caller has requested that the target task be reset, then do so.
if ((mLaunchFlags & FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
@@ -1719,7 +1706,7 @@ class ActivityStarter {
// mTaskToReturnTo values and we don't want to overwrite them accidentally.
mMovedOtherTask = true;
} else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
- || mLaunchSingleInstance || mLaunchSingleTask) {
+ || isLaunchModeOneOf(LAUNCH_SINGLE_INSTANCE, LAUNCH_SINGLE_TASK)) {
ActivityRecord top = intentActivity.getTask().performClearTaskLocked(mStartActivity,
mLaunchFlags);
if (top == null) {
@@ -1748,7 +1735,8 @@ class ActivityStarter {
// so we take that as a request to bring the task to the foreground. If the top
// activity in the task is the root activity, deliver this new intent to it if it
// desires.
- if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0 || mLaunchSingleTop)
+ if (((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
+ || LAUNCH_SINGLE_TOP == mLaunchMode)
&& intentActivity.realActivity.equals(mStartActivity.realActivity)) {
if (intentActivity.frontOfTask) {
intentActivity.getTask().setIntent(mStartActivity);
@@ -1952,7 +1940,7 @@ class ActivityStarter {
if (top != null && top.realActivity.equals(mStartActivity.realActivity)
&& top.userId == mStartActivity.userId) {
if ((mLaunchFlags & FLAG_ACTIVITY_SINGLE_TOP) != 0
- || mLaunchSingleTop || mLaunchSingleTask) {
+ || isLaunchModeOneOf(LAUNCH_SINGLE_TOP, LAUNCH_SINGLE_TASK)) {
mTargetStack.moveTaskToFrontLocked(mInTask, mNoAnimation, mOptions,
mStartActivity.appTimeTracker, "inTaskToFront");
if ((mStartFlags & START_FLAG_ONLY_IF_NEEDED) != 0) {
@@ -2001,9 +1989,9 @@ class ActivityStarter {
return;
}
- final int stackId = task.getStackId();
- if (StackId.resizeStackWithLaunchBounds(stackId)) {
- mService.resizeStack(stackId, bounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
+ final ActivityStack stack = task.getStack();
+ if (stack != null && stack.resizeStackWithLaunchBounds()) {
+ mService.resizeStack(stack.mStackId, bounds, true, !PRESERVE_WINDOWS, ANIMATE, -1);
} else {
task.updateOverrideConfiguration(bounds);
}
@@ -2115,11 +2103,10 @@ class ActivityStarter {
}
if (stack == null) {
// We first try to put the task in the first dynamic stack on home display.
- final ArrayList<ActivityStack> homeDisplayStacks =
- mSupervisor.getStacksOnDefaultDisplay();
- for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- stack = homeDisplayStacks.get(stackNdx);
- if (isDynamicStack(stack.mStackId)) {
+ final ActivityDisplay display = mSupervisor.getDefaultDisplay();
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ stack = display.getChildAt(stackNdx);
+ if (!stack.isOnHomeDisplay()) {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG_FOCUS,
"computeStackFocus: Setting focused stack=" + stack);
return stack;
@@ -2138,7 +2125,6 @@ class ActivityStarter {
private boolean canLaunchIntoFocusedStack(ActivityRecord r, boolean newTask) {
final ActivityStack focusedStack = mSupervisor.mFocusedStack;
final boolean canUseFocusedStack;
- final int focusedStackId = mSupervisor.mFocusedStack.mStackId;
if (focusedStack.isActivityTypeAssistant()) {
canUseFocusedStack = r.isActivityTypeAssistant();
} else {
@@ -2161,7 +2147,7 @@ class ActivityStarter {
default:
// Dynamic stacks behave similarly to the fullscreen stack and can contain any
// resizeable task.
- canUseFocusedStack = isDynamicStack(focusedStackId)
+ canUseFocusedStack = !focusedStack.isOnHomeDisplay()
&& r.canBeLaunchedOnDisplay(focusedStack.mDisplayId);
}
}
@@ -2177,7 +2163,8 @@ class ActivityStarter {
return mReuseTask.getStack();
}
- final int vrDisplayId = mUsingVr2dDisplay ? mPreferredDisplayId : INVALID_DISPLAY;
+ final int vrDisplayId = mPreferredDisplayId == mService.mVr2dDisplayId
+ ? mPreferredDisplayId : INVALID_DISPLAY;
final ActivityStack launchStack = mSupervisor.getLaunchStack(r, aOptions, task, ON_TOP,
vrDisplayId);
@@ -2205,7 +2192,7 @@ class ActivityStarter {
return mSupervisor.mFocusedStack;
}
- if (parentStack != null && parentStack.isDockedStack()) {
+ if (parentStack != null && parentStack.inSplitScreenPrimaryWindowingMode()) {
// If parent was in docked stack, the natural place to launch another activity
// will be fullscreen, so it can appear alongside the docked window.
final int activityType = mSupervisor.resolveActivityType(r, mOptions, task);
@@ -2215,8 +2202,8 @@ class ActivityStarter {
// If the parent is not in the docked stack, we check if there is docked window
// and if yes, we will launch into that stack. If not, we just put the new
// activity into parent's stack, because we can't find a better place.
- final ActivityStack dockedStack = mSupervisor.getDefaultDisplay().getStack(
- WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_UNDEFINED);
+ final ActivityStack dockedStack =
+ mSupervisor.getDefaultDisplay().getSplitScreenPrimaryStack();
if (dockedStack != null && !dockedStack.shouldBeVisible(r)) {
// There is a docked stack, but it isn't visible, so we can't launch into that.
return null;
@@ -2236,8 +2223,8 @@ class ActivityStarter {
return newBounds;
}
- void setWindowManager(WindowManagerService wm) {
- mWindowManager = wm;
+ private boolean isLaunchModeOneOf(int mode1, int mode2) {
+ return mode1 == mLaunchMode || mode2 == mLaunchMode;
}
static boolean isDocumentLaunchesIntoExisting(int flags) {
@@ -2318,11 +2305,11 @@ class ActivityStarter {
}
pw.print(prefix);
pw.print("mLaunchSingleTop=");
- pw.print(mLaunchSingleTop);
+ pw.print(LAUNCH_SINGLE_TOP == mLaunchMode);
pw.print(" mLaunchSingleInstance=");
- pw.print(mLaunchSingleInstance);
+ pw.print(LAUNCH_SINGLE_INSTANCE == mLaunchMode);
pw.print(" mLaunchSingleTask=");
- pw.println(mLaunchSingleTask);
+ pw.println(LAUNCH_SINGLE_TASK == mLaunchMode);
pw.print(prefix);
pw.print("mLaunchFlags=0x");
pw.print(Integer.toHexString(mLaunchFlags));
diff --git a/com/android/server/am/AppTaskImpl.java b/com/android/server/am/AppTaskImpl.java
new file mode 100644
index 00000000..a4e2e70e
--- /dev/null
+++ b/com/android/server/am/AppTaskImpl.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
+
+import android.app.ActivityManager;
+import android.app.IAppTask;
+import android.app.IApplicationThread;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.UserHandle;
+
+/**
+ * An implementation of IAppTask, that allows an app to manage its own tasks via
+ * {@link android.app.ActivityManager.AppTask}. We keep track of the callingUid to ensure that
+ * only the process that calls getAppTasks() can call the AppTask methods.
+ */
+class AppTaskImpl extends IAppTask.Stub {
+ private ActivityManagerService mService;
+
+ private int mTaskId;
+ private int mCallingUid;
+
+ public AppTaskImpl(ActivityManagerService service, int taskId, int callingUid) {
+ mService = service;
+ mTaskId = taskId;
+ mCallingUid = callingUid;
+ }
+
+ private void checkCaller() {
+ if (mCallingUid != Binder.getCallingUid()) {
+ throw new SecurityException("Caller " + mCallingUid
+ + " does not match caller of getAppTasks(): " + Binder.getCallingUid());
+ }
+ }
+
+ @Override
+ public void finishAndRemoveTask() {
+ checkCaller();
+
+ synchronized (mService) {
+ long origId = Binder.clearCallingIdentity();
+ try {
+ // We remove the task from recents to preserve backwards
+ if (!mService.mStackSupervisor.removeTaskByIdLocked(mTaskId, false,
+ REMOVE_FROM_RECENTS)) {
+ throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+ }
+
+ @Override
+ public ActivityManager.RecentTaskInfo getTaskInfo() {
+ checkCaller();
+
+ synchronized (mService) {
+ long origId = Binder.clearCallingIdentity();
+ try {
+ TaskRecord tr = mService.mStackSupervisor.anyTaskForIdLocked(mTaskId);
+ if (tr == null) {
+ throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
+ }
+ return RecentTasks.createRecentTaskInfo(tr);
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+ }
+
+ @Override
+ public void moveToFront() {
+ checkCaller();
+ // Will bring task to front if it already has a root activity.
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ synchronized (this) {
+ mService.mStackSupervisor.startActivityFromRecentsInner(mTaskId, null);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
+ @Override
+ public int startActivity(IBinder whoThread, String callingPackage,
+ Intent intent, String resolvedType, Bundle bOptions) {
+ checkCaller();
+
+ int callingUser = UserHandle.getCallingUserId();
+ TaskRecord tr;
+ IApplicationThread appThread;
+ synchronized (mService) {
+ tr = mService.mStackSupervisor.anyTaskForIdLocked(mTaskId);
+ if (tr == null) {
+ throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
+ }
+ appThread = IApplicationThread.Stub.asInterface(whoThread);
+ if (appThread == null) {
+ throw new IllegalArgumentException("Bad app thread " + appThread);
+ }
+ }
+ return mService.mActivityStarter.startActivityMayWait(appThread, -1, callingPackage,
+ intent, resolvedType, null, null, null, null, 0, 0, null, null,
+ null, bOptions, false, callingUser, tr, "AppTaskImpl");
+ }
+
+ @Override
+ public void setExcludeFromRecents(boolean exclude) {
+ checkCaller();
+
+ synchronized (mService) {
+ long origId = Binder.clearCallingIdentity();
+ try {
+ TaskRecord tr = mService.mStackSupervisor.anyTaskForIdLocked(mTaskId);
+ if (tr == null) {
+ throw new IllegalArgumentException("Unable to find task ID " + mTaskId);
+ }
+ Intent intent = tr.getBaseIntent();
+ if (exclude) {
+ intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ } else {
+ intent.setFlags(intent.getFlags()
+ & ~Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/com/android/server/am/BatteryStatsService.java b/com/android/server/am/BatteryStatsService.java
index 7c9cd00e..68ed9aec 100644
--- a/com/android/server/am/BatteryStatsService.java
+++ b/com/android/server/am/BatteryStatsService.java
@@ -297,26 +297,12 @@ public final class BatteryStatsService extends IBatteryStats.Stub
void noteProcessStart(String name, int uid) {
synchronized (mStats) {
mStats.noteProcessStartLocked(name, uid);
-
- // TODO: remove this once we figure out properly where and how
- // PROCESS_EVENT = 1112
- // KEY_STATE = 1
- // KEY_PACKAGE_NAME: 1002
- // KEY_UID: 2
- StatsLog.writeArray(1112, 1, 1, 1002, name, 2, uid);
}
}
void noteProcessCrash(String name, int uid) {
synchronized (mStats) {
mStats.noteProcessCrashLocked(name, uid);
-
- // TODO: remove this once we figure out properly where and how
- // PROCESS_EVENT = 1112
- // KEY_STATE = 1
- // KEY_PACKAGE_NAME: 1002
- // KEY_UID: 2
- StatsLog.writeArray(1112, 1, 2, 1002, name, 2, uid);
}
}
@@ -334,6 +320,9 @@ public final class BatteryStatsService extends IBatteryStats.Stub
void noteUidProcessState(int uid, int state) {
synchronized (mStats) {
+ // TODO: remove this once we figure out properly where and how
+ StatsLog.write(StatsLog.PROCESS_STATE_CHANGED, uid, state);
+
mStats.noteUidProcessStateLocked(uid, state);
}
}
@@ -548,12 +537,10 @@ public final class BatteryStatsService extends IBatteryStats.Stub
enforceCallingPermission();
if (DBG) Slog.d(TAG, "begin noteScreenState");
synchronized (mStats) {
- mStats.noteScreenStateLocked(state);
// TODO: remove this once we figure out properly where and how
- // SCREEN_EVENT = 2
- // KEY_STATE: 1
- // State value: state. We can change this to our own def later.
- StatsLog.writeArray(2, 1, state);
+ StatsLog.write(StatsLog.SCREEN_STATE_CHANGED, state);
+
+ mStats.noteScreenStateLocked(state);
}
if (DBG) Slog.d(TAG, "end noteScreenState");
}
diff --git a/com/android/server/am/BroadcastFilter.java b/com/android/server/am/BroadcastFilter.java
index f96b06fa..7ff227f5 100644
--- a/com/android/server/am/BroadcastFilter.java
+++ b/com/android/server/am/BroadcastFilter.java
@@ -19,6 +19,9 @@ package com.android.server.am;
import android.content.IntentFilter;
import android.util.PrintWriterPrinter;
import android.util.Printer;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.server.am.proto.BroadcastFilterProto;
import java.io.PrintWriter;
@@ -44,27 +47,38 @@ final class BroadcastFilter extends IntentFilter {
instantApp = _instantApp;
visibleToInstantApp = _visibleToInstantApp;
}
-
+
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ long token = proto.start(fieldId);
+ super.writeToProto(proto, BroadcastFilterProto.INTENT_FILTER);
+ if (requiredPermission != null) {
+ proto.write(BroadcastFilterProto.REQUIRED_PERMISSION, requiredPermission);
+ }
+ proto.write(BroadcastFilterProto.HEX_HASH, Integer.toHexString(System.identityHashCode(this)));
+ proto.write(BroadcastFilterProto.OWNING_USER_ID, owningUserId);
+ proto.end(token);
+ }
+
public void dump(PrintWriter pw, String prefix) {
dumpInReceiverList(pw, new PrintWriterPrinter(pw), prefix);
receiverList.dumpLocal(pw, prefix);
}
-
+
public void dumpBrief(PrintWriter pw, String prefix) {
dumpBroadcastFilterState(pw, prefix);
}
-
+
public void dumpInReceiverList(PrintWriter pw, Printer pr, String prefix) {
super.dump(pr, prefix);
dumpBroadcastFilterState(pw, prefix);
}
-
+
void dumpBroadcastFilterState(PrintWriter pw, String prefix) {
if (requiredPermission != null) {
pw.print(prefix); pw.print("requiredPermission="); pw.println(requiredPermission);
}
}
-
+
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("BroadcastFilter{");
diff --git a/com/android/server/am/BroadcastQueue.java b/com/android/server/am/BroadcastQueue.java
index d8354549..c62cc38b 100644
--- a/com/android/server/am/BroadcastQueue.java
+++ b/com/android/server/am/BroadcastQueue.java
@@ -51,9 +51,12 @@ import android.os.UserHandle;
import android.util.EventLog;
import android.util.Slog;
import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
import static com.android.server.am.ActivityManagerDebugConfig.*;
+import com.android.server.am.proto.BroadcastQueueProto;
+
/**
* BROADCASTS
*
@@ -1585,6 +1588,55 @@ public final class BroadcastQueue {
&& (mPendingBroadcast == null);
}
+ void writeToProto(ProtoOutputStream proto, long fieldId) {
+ long token = proto.start(fieldId);
+ proto.write(BroadcastQueueProto.QUEUE_NAME, mQueueName);
+ int N;
+ N = mParallelBroadcasts.size();
+ for (int i = N - 1; i >= 0; i--) {
+ mParallelBroadcasts.get(i).writeToProto(proto, BroadcastQueueProto.PARALLEL_BROADCASTS);
+ }
+ N = mOrderedBroadcasts.size();
+ for (int i = N - 1; i >= 0; i--) {
+ mOrderedBroadcasts.get(i).writeToProto(proto, BroadcastQueueProto.ORDERED_BROADCASTS);
+ }
+ if (mPendingBroadcast != null) {
+ mPendingBroadcast.writeToProto(proto, BroadcastQueueProto.PENDING_BROADCAST);
+ }
+
+ int lastIndex = mHistoryNext;
+ int ringIndex = lastIndex;
+ do {
+ // increasing index = more recent entry, and we want to print the most
+ // recent first and work backwards, so we roll through the ring backwards.
+ ringIndex = ringAdvance(ringIndex, -1, MAX_BROADCAST_HISTORY);
+ BroadcastRecord r = mBroadcastHistory[ringIndex];
+ if (r != null) {
+ r.writeToProto(proto, BroadcastQueueProto.HISTORICAL_BROADCASTS);
+ }
+ } while (ringIndex != lastIndex);
+
+ lastIndex = ringIndex = mSummaryHistoryNext;
+ do {
+ ringIndex = ringAdvance(ringIndex, -1, MAX_BROADCAST_SUMMARY_HISTORY);
+ Intent intent = mBroadcastSummaryHistory[ringIndex];
+ if (intent == null) {
+ continue;
+ }
+ long summaryToken = proto.start(BroadcastQueueProto.HISTORICAL_BROADCASTS_SUMMARY);
+ intent.writeToProto(proto, BroadcastQueueProto.BroadcastSummary.INTENT,
+ false, true, true, false);
+ proto.write(BroadcastQueueProto.BroadcastSummary.ENQUEUE_CLOCK_TIME_MS,
+ mSummaryHistoryEnqueueTime[ringIndex]);
+ proto.write(BroadcastQueueProto.BroadcastSummary.DISPATCH_CLOCK_TIME_MS,
+ mSummaryHistoryDispatchTime[ringIndex]);
+ proto.write(BroadcastQueueProto.BroadcastSummary.FINISH_CLOCK_TIME_MS,
+ mSummaryHistoryFinishTime[ringIndex]);
+ proto.end(summaryToken);
+ } while (ringIndex != lastIndex);
+ proto.end(token);
+ }
+
final boolean dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args,
int opti, boolean dumpAll, String dumpPackage, boolean needSep) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
diff --git a/com/android/server/am/BroadcastRecord.java b/com/android/server/am/BroadcastRecord.java
index 6bc0744f..5b3b2a8e 100644
--- a/com/android/server/am/BroadcastRecord.java
+++ b/com/android/server/am/BroadcastRecord.java
@@ -30,6 +30,9 @@ import android.os.SystemClock;
import android.os.UserHandle;
import android.util.PrintWriterPrinter;
import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
+
+import com.android.server.am.proto.BroadcastRecordProto;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
@@ -331,9 +334,17 @@ final class BroadcastRecord extends Binder {
return didSomething;
}
+ @Override
public String toString() {
return "BroadcastRecord{"
+ Integer.toHexString(System.identityHashCode(this))
+ " u" + userId + " " + intent.getAction() + "}";
}
+
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ long token = proto.start(fieldId);
+ proto.write(BroadcastRecordProto.USER_ID, userId);
+ proto.write(BroadcastRecordProto.INTENT_ACTION, intent.getAction());
+ proto.end(token);
+ }
}
diff --git a/com/android/server/am/KeyguardController.java b/com/android/server/am/KeyguardController.java
index 5c48f90d..c3fed171 100644
--- a/com/android/server/am/KeyguardController.java
+++ b/com/android/server/am/KeyguardController.java
@@ -16,7 +16,6 @@
package com.android.server.am;
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
@@ -47,7 +46,6 @@ import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.server.wm.WindowManagerService;
import java.io.PrintWriter;
-import java.util.ArrayList;
/**
* Controls Keyguard occluding, dismissing and transitions depending on what kind of activities are
@@ -238,9 +236,9 @@ class KeyguardController {
final ActivityRecord lastDismissingKeyguardActivity = mDismissingKeyguardActivity;
mOccluded = false;
mDismissingKeyguardActivity = null;
- final ArrayList<ActivityStack> stacks = mStackSupervisor.getStacksOnDefaultDisplay();
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityDisplay display = mStackSupervisor.getDefaultDisplay();
+ for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = display.getChildAt(stackNdx);
// Only the focused stack top activity may control occluded state
if (mStackSupervisor.isFocusedStack(stack)) {
@@ -342,7 +340,7 @@ class KeyguardController {
// show on top of the lock screen. In this can we want to dismiss the docked
// stack since it will be complicated/risky to try to put the activity on top
// of the lock screen in the right fullscreen configuration.
- final ActivityStack stack = mStackSupervisor.getDefaultDisplay().getSplitScreenStack();
+ final ActivityStack stack = mStackSupervisor.getDefaultDisplay().getSplitScreenPrimaryStack();
if (stack == null) {
return;
}
diff --git a/com/android/server/am/LaunchingTaskPositioner.java b/com/android/server/am/LaunchingTaskPositioner.java
index d6523418..0dc73e98 100644
--- a/com/android/server/am/LaunchingTaskPositioner.java
+++ b/com/android/server/am/LaunchingTaskPositioner.java
@@ -24,8 +24,8 @@ import android.content.pm.ActivityInfo;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.Slog;
-import android.view.Display;
import android.view.Gravity;
+import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
@@ -64,43 +64,11 @@ class LaunchingTaskPositioner {
private static final int SHIFT_POLICY_HORIZONTAL_RIGHT = 2;
private static final int SHIFT_POLICY_HORIZONTAL_LEFT = 3;
- private boolean mDefaultStartBoundsConfigurationSet = false;
private final Rect mAvailableRect = new Rect();
private final Rect mTmpProposal = new Rect();
private final Rect mTmpOriginal = new Rect();
- private int mDefaultFreeformStartX;
- private int mDefaultFreeformStartY;
- private int mDefaultFreeformWidth;
- private int mDefaultFreeformHeight;
- private int mDefaultFreeformStepHorizontal;
- private int mDefaultFreeformStepVertical;
- private int mDisplayWidth;
- private int mDisplayHeight;
-
- void setDisplay(Display display) {
- Point size = new Point();
- display.getSize(size);
- mDisplayWidth = size.x;
- mDisplayHeight = size.y;
- }
-
- void configure(Rect stackBounds) {
- if (stackBounds == null) {
- mAvailableRect.set(0, 0, mDisplayWidth, mDisplayHeight);
- } else {
- mAvailableRect.set(stackBounds);
- }
- int width = mAvailableRect.width();
- int height = mAvailableRect.height();
- mDefaultFreeformStartX = mAvailableRect.left + width / MARGIN_SIZE_DENOMINATOR;
- mDefaultFreeformStartY = mAvailableRect.top + height / MARGIN_SIZE_DENOMINATOR;
- mDefaultFreeformWidth = width / WINDOW_SIZE_DENOMINATOR;
- mDefaultFreeformHeight = height / WINDOW_SIZE_DENOMINATOR;
- mDefaultFreeformStepHorizontal = Math.max(width / STEP_DENOMINATOR, MINIMAL_STEP);
- mDefaultFreeformStepVertical = Math.max(height / STEP_DENOMINATOR, MINIMAL_STEP);
- mDefaultStartBoundsConfigurationSet = true;
- }
+ private final Point mDisplaySize = new Point();
/**
* Tries to set task's bound in a way that it won't collide with any other task. By colliding
@@ -114,104 +82,154 @@ class LaunchingTaskPositioner {
*/
void updateDefaultBounds(TaskRecord task, ArrayList<TaskRecord> tasks,
@Nullable ActivityInfo.WindowLayout windowLayout) {
- if (!mDefaultStartBoundsConfigurationSet) {
- return;
- }
+ updateAvailableRect(task, mAvailableRect);
+
if (windowLayout == null) {
- positionCenter(task, tasks, mDefaultFreeformWidth, mDefaultFreeformHeight);
+ positionCenter(task, tasks, mAvailableRect, getFreeformWidth(mAvailableRect),
+ getFreeformHeight(mAvailableRect));
return;
}
- int width = getFinalWidth(windowLayout);
- int height = getFinalHeight(windowLayout);
+ int width = getFinalWidth(windowLayout, mAvailableRect);
+ int height = getFinalHeight(windowLayout, mAvailableRect);
int verticalGravity = windowLayout.gravity & Gravity.VERTICAL_GRAVITY_MASK;
int horizontalGravity = windowLayout.gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
if (verticalGravity == Gravity.TOP) {
if (horizontalGravity == Gravity.RIGHT) {
- positionTopRight(task, tasks, width, height);
+ positionTopRight(task, tasks, mAvailableRect, width, height);
} else {
- positionTopLeft(task, tasks, width, height);
+ positionTopLeft(task, tasks, mAvailableRect, width, height);
}
} else if (verticalGravity == Gravity.BOTTOM) {
if (horizontalGravity == Gravity.RIGHT) {
- positionBottomRight(task, tasks, width, height);
+ positionBottomRight(task, tasks, mAvailableRect, width, height);
} else {
- positionBottomLeft(task, tasks, width, height);
+ positionBottomLeft(task, tasks, mAvailableRect, width, height);
}
} else {
// Some fancy gravity setting that we don't support yet. We just put the activity in the
// center.
Slog.w(TAG, "Received unsupported gravity: " + windowLayout.gravity
+ ", positioning in the center instead.");
- positionCenter(task, tasks, width, height);
+ positionCenter(task, tasks, mAvailableRect, width, height);
}
}
- private int getFinalWidth(ActivityInfo.WindowLayout windowLayout) {
- int width = mDefaultFreeformWidth;
+ private void updateAvailableRect(TaskRecord task, Rect availableRect) {
+ final Rect stackBounds = task.getStack().mBounds;
+
+ if (stackBounds != null) {
+ availableRect.set(stackBounds);
+ } else {
+ task.getStack().getDisplay().mDisplay.getSize(mDisplaySize);
+ availableRect.set(0, 0, mDisplaySize.x, mDisplaySize.y);
+ }
+ }
+
+ @VisibleForTesting
+ static int getFreeformStartLeft(Rect bounds) {
+ return bounds.left + bounds.width() / MARGIN_SIZE_DENOMINATOR;
+ }
+
+ @VisibleForTesting
+ static int getFreeformStartTop(Rect bounds) {
+ return bounds.top + bounds.height() / MARGIN_SIZE_DENOMINATOR;
+ }
+
+ @VisibleForTesting
+ static int getFreeformWidth(Rect bounds) {
+ return bounds.width() / WINDOW_SIZE_DENOMINATOR;
+ }
+
+ @VisibleForTesting
+ static int getFreeformHeight(Rect bounds) {
+ return bounds.height() / WINDOW_SIZE_DENOMINATOR;
+ }
+
+ @VisibleForTesting
+ static int getHorizontalStep(Rect bounds) {
+ return Math.max(bounds.width() / STEP_DENOMINATOR, MINIMAL_STEP);
+ }
+
+ @VisibleForTesting
+ static int getVerticalStep(Rect bounds) {
+ return Math.max(bounds.height() / STEP_DENOMINATOR, MINIMAL_STEP);
+ }
+
+
+
+ private int getFinalWidth(ActivityInfo.WindowLayout windowLayout, Rect availableRect) {
+ int width = getFreeformWidth(availableRect);
if (windowLayout.width > 0) {
width = windowLayout.width;
}
if (windowLayout.widthFraction > 0) {
- width = (int) (mAvailableRect.width() * windowLayout.widthFraction);
+ width = (int) (availableRect.width() * windowLayout.widthFraction);
}
return width;
}
- private int getFinalHeight(ActivityInfo.WindowLayout windowLayout) {
- int height = mDefaultFreeformHeight;
+ private int getFinalHeight(ActivityInfo.WindowLayout windowLayout, Rect availableRect) {
+ int height = getFreeformHeight(availableRect);
if (windowLayout.height > 0) {
height = windowLayout.height;
}
if (windowLayout.heightFraction > 0) {
- height = (int) (mAvailableRect.height() * windowLayout.heightFraction);
+ height = (int) (availableRect.height() * windowLayout.heightFraction);
}
return height;
}
- private void positionBottomLeft(TaskRecord task, ArrayList<TaskRecord> tasks, int width,
- int height) {
- mTmpProposal.set(mAvailableRect.left, mAvailableRect.bottom - height,
- mAvailableRect.left + width, mAvailableRect.bottom);
- position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_RIGHT);
+ private void positionBottomLeft(TaskRecord task, ArrayList<TaskRecord> tasks,
+ Rect availableRect, int width, int height) {
+ mTmpProposal.set(availableRect.left, availableRect.bottom - height,
+ availableRect.left + width, availableRect.bottom);
+ position(task, tasks, availableRect, mTmpProposal, !ALLOW_RESTART,
+ SHIFT_POLICY_HORIZONTAL_RIGHT);
}
- private void positionBottomRight(TaskRecord task, ArrayList<TaskRecord> tasks, int width,
- int height) {
- mTmpProposal.set(mAvailableRect.right - width, mAvailableRect.bottom - height,
- mAvailableRect.right, mAvailableRect.bottom);
- position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_LEFT);
+ private void positionBottomRight(TaskRecord task, ArrayList<TaskRecord> tasks,
+ Rect availableRect, int width, int height) {
+ mTmpProposal.set(availableRect.right - width, availableRect.bottom - height,
+ availableRect.right, availableRect.bottom);
+ position(task, tasks, availableRect, mTmpProposal, !ALLOW_RESTART,
+ SHIFT_POLICY_HORIZONTAL_LEFT);
}
- private void positionTopLeft(TaskRecord task, ArrayList<TaskRecord> tasks, int width,
- int height) {
- mTmpProposal.set(mAvailableRect.left, mAvailableRect.top,
- mAvailableRect.left + width, mAvailableRect.top + height);
- position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_RIGHT);
+ private void positionTopLeft(TaskRecord task, ArrayList<TaskRecord> tasks,
+ Rect availableRect, int width, int height) {
+ mTmpProposal.set(availableRect.left, availableRect.top,
+ availableRect.left + width, availableRect.top + height);
+ position(task, tasks, availableRect, mTmpProposal, !ALLOW_RESTART,
+ SHIFT_POLICY_HORIZONTAL_RIGHT);
}
- private void positionTopRight(TaskRecord task, ArrayList<TaskRecord> tasks, int width,
- int height) {
- mTmpProposal.set(mAvailableRect.right - width, mAvailableRect.top,
- mAvailableRect.right, mAvailableRect.top + height);
- position(task, tasks, mTmpProposal, !ALLOW_RESTART, SHIFT_POLICY_HORIZONTAL_LEFT);
+ private void positionTopRight(TaskRecord task, ArrayList<TaskRecord> tasks,
+ Rect availableRect, int width, int height) {
+ mTmpProposal.set(availableRect.right - width, availableRect.top,
+ availableRect.right, availableRect.top + height);
+ position(task, tasks, availableRect, mTmpProposal, !ALLOW_RESTART,
+ SHIFT_POLICY_HORIZONTAL_LEFT);
}
- private void positionCenter(TaskRecord task, ArrayList<TaskRecord> tasks, int width,
- int height) {
- mTmpProposal.set(mDefaultFreeformStartX, mDefaultFreeformStartY,
- mDefaultFreeformStartX + width, mDefaultFreeformStartY + height);
- position(task, tasks, mTmpProposal, ALLOW_RESTART, SHIFT_POLICY_DIAGONAL_DOWN);
+ private void positionCenter(TaskRecord task, ArrayList<TaskRecord> tasks,
+ Rect availableRect, int width, int height) {
+ final int defaultFreeformLeft = getFreeformStartLeft(availableRect);
+ final int defaultFreeformTop = getFreeformStartTop(availableRect);
+ mTmpProposal.set(defaultFreeformLeft, defaultFreeformTop,
+ defaultFreeformLeft + width, defaultFreeformTop + height);
+ position(task, tasks, availableRect, mTmpProposal, ALLOW_RESTART,
+ SHIFT_POLICY_DIAGONAL_DOWN);
}
- private void position(TaskRecord task, ArrayList<TaskRecord> tasks, Rect proposal,
- boolean allowRestart, int shiftPolicy) {
+ private void position(TaskRecord task, ArrayList<TaskRecord> tasks, Rect availableRect,
+ Rect proposal, boolean allowRestart, int shiftPolicy) {
mTmpOriginal.set(proposal);
boolean restarted = false;
while (boundsConflict(proposal, tasks)) {
// Unfortunately there is already a task at that spot, so we need to look for some
// other place.
- shiftStartingPoint(proposal, shiftPolicy);
- if (shiftedToFar(proposal, shiftPolicy)) {
+ shiftStartingPoint(proposal, availableRect, shiftPolicy);
+ if (shiftedTooFar(proposal, availableRect, shiftPolicy)) {
// We don't want the task to go outside of the stack, because it won't look
// nice. Depending on the starting point we either restart, or immediately give up.
if (!allowRestart) {
@@ -220,13 +238,13 @@ class LaunchingTaskPositioner {
}
// We must have started not from the top. Let's restart from there because there
// might be some space there.
- proposal.set(mAvailableRect.left, mAvailableRect.top,
- mAvailableRect.left + proposal.width(),
- mAvailableRect.top + proposal.height());
+ proposal.set(availableRect.left, availableRect.top,
+ availableRect.left + proposal.width(),
+ availableRect.top + proposal.height());
restarted = true;
}
- if (restarted && (proposal.left > mDefaultFreeformStartX
- || proposal.top > mDefaultFreeformStartY)) {
+ if (restarted && (proposal.left > getFreeformStartLeft(availableRect)
+ || proposal.top > getFreeformStartTop(availableRect))) {
// If we restarted and crossed the initial position, let's not struggle anymore.
// The user already must have ton of tasks visible, we can just smack the new
// one in the center.
@@ -237,27 +255,30 @@ class LaunchingTaskPositioner {
task.updateOverrideConfiguration(proposal);
}
- private boolean shiftedToFar(Rect start, int shiftPolicy) {
+ private boolean shiftedTooFar(Rect start, Rect availableRect, int shiftPolicy) {
switch (shiftPolicy) {
case SHIFT_POLICY_HORIZONTAL_LEFT:
- return start.left < mAvailableRect.left;
+ return start.left < availableRect.left;
case SHIFT_POLICY_HORIZONTAL_RIGHT:
- return start.right > mAvailableRect.right;
+ return start.right > availableRect.right;
default: // SHIFT_POLICY_DIAGONAL_DOWN
- return start.right > mAvailableRect.right || start.bottom > mAvailableRect.bottom;
+ return start.right > availableRect.right || start.bottom > availableRect.bottom;
}
}
- private void shiftStartingPoint(Rect posposal, int shiftPolicy) {
+ private void shiftStartingPoint(Rect posposal, Rect availableRect, int shiftPolicy) {
+ final int defaultFreeformStepHorizontal = getHorizontalStep(availableRect);
+ final int defaultFreeformStepVertical = getVerticalStep(availableRect);
+
switch (shiftPolicy) {
case SHIFT_POLICY_HORIZONTAL_LEFT:
- posposal.offset(-mDefaultFreeformStepHorizontal, 0);
+ posposal.offset(-defaultFreeformStepHorizontal, 0);
break;
case SHIFT_POLICY_HORIZONTAL_RIGHT:
- posposal.offset(mDefaultFreeformStepHorizontal, 0);
+ posposal.offset(defaultFreeformStepHorizontal, 0);
break;
default: // SHIFT_POLICY_DIAGONAL_DOWN:
- posposal.offset(mDefaultFreeformStepHorizontal, mDefaultFreeformStepVertical);
+ posposal.offset(defaultFreeformStepHorizontal, defaultFreeformStepVertical);
break;
}
}
@@ -296,8 +317,4 @@ class LaunchingTaskPositioner {
return Math.abs(first.right - second.right) < BOUNDS_CONFLICT_MIN_DISTANCE
&& Math.abs(first.bottom - second.bottom) < BOUNDS_CONFLICT_MIN_DISTANCE;
}
-
- void reset() {
- mDefaultStartBoundsConfigurationSet = false;
- }
}
diff --git a/com/android/server/am/LockTaskController.java b/com/android/server/am/LockTaskController.java
index 72b5de88..940f9051 100644
--- a/com/android/server/am/LockTaskController.java
+++ b/com/android/server/am/LockTaskController.java
@@ -19,7 +19,6 @@ package com.android.server.am;
import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.StatusBarManager.DISABLE_BACK;
import static android.app.StatusBarManager.DISABLE_HOME;
import static android.app.StatusBarManager.DISABLE_MASK;
@@ -59,7 +58,6 @@ import android.provider.Settings;
import android.util.Slog;
import android.util.SparseArray;
-import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.widget.LockPatternUtils;
@@ -433,7 +431,7 @@ public class LockTaskController {
mWindowManager.executeAppTransition();
} else if (lockTaskModeState != LOCK_TASK_MODE_NONE) {
mSupervisor.handleNonResizableTaskIfNeeded(task, WINDOWING_MODE_UNDEFINED,
- DEFAULT_DISPLAY, task.getStackId(), true /* forceNonResizable */);
+ DEFAULT_DISPLAY, task.getStack(), true /* forceNonResizable */);
}
}
@@ -494,11 +492,7 @@ public class LockTaskController {
}
for (int displayNdx = mSupervisor.getChildCount() - 1; displayNdx >= 0; --displayNdx) {
- ArrayList<ActivityStack> stacks = mSupervisor.getChildAt(displayNdx).mStacks;
- for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
- stack.onLockTaskPackagesUpdatedLocked();
- }
+ mSupervisor.getChildAt(displayNdx).onLockTaskPackagesUpdated();
}
final ActivityRecord r = mSupervisor.topRunningActivityLocked();
diff --git a/com/android/server/am/ProcessRecord.java b/com/android/server/am/ProcessRecord.java
index 0e318d9c..e8477231 100644
--- a/com/android/server/am/ProcessRecord.java
+++ b/com/android/server/am/ProcessRecord.java
@@ -27,6 +27,7 @@ import android.util.Slog;
import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.app.procstats.ProcessState;
import com.android.internal.os.BatteryStatsImpl;
+import com.android.server.am.proto.ProcessRecordProto;
import android.app.ActivityManager;
import android.app.Dialog;
@@ -44,6 +45,7 @@ import android.os.Trace;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.TimeUtils;
+import android.util.proto.ProtoOutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -621,6 +623,22 @@ final class ProcessRecord {
}
}
+ public void writeToProto(ProtoOutputStream proto, long fieldId) {
+ long token = proto.start(fieldId);
+ proto.write(ProcessRecordProto.PID, pid);
+ proto.write(ProcessRecordProto.PROCESS_NAME, processName);
+ if (info.uid < Process.FIRST_APPLICATION_UID) {
+ proto.write(ProcessRecordProto.UID, uid);
+ } else {
+ proto.write(ProcessRecordProto.USER_ID, userId);
+ proto.write(ProcessRecordProto.APP_ID, UserHandle.getAppId(info.uid));
+ if (uid != info.uid) {
+ proto.write(ProcessRecordProto.ISOLATED_APP_ID, UserHandle.getAppId(uid));
+ }
+ }
+ proto.end(token);
+ }
+
public String toShortString() {
if (shortStringName != null) {
return shortStringName;
diff --git a/com/android/server/am/ReceiverList.java b/com/android/server/am/ReceiverList.java
index 6ade7361..a9890631 100644
--- a/com/android/server/am/ReceiverList.java
+++ b/com/android/server/am/ReceiverList.java
@@ -21,6 +21,8 @@ import android.os.Binder;
import android.os.IBinder;
import android.util.PrintWriterPrinter;
import android.util.Printer;
+import android.util.proto.ProtoOutputStream;
+import com.android.server.am.proto.ReceiverListProto;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -41,7 +43,7 @@ final class ReceiverList extends ArrayList<BroadcastFilter>
boolean linkedToDeath = false;
String stringName;
-
+
ReceiverList(ActivityManagerService _owner, ProcessRecord _app,
int _pid, int _uid, int _userId, IIntentReceiver _receiver) {
owner = _owner;
@@ -59,12 +61,31 @@ final class ReceiverList extends ArrayList<BroadcastFilter>
public int hashCode() {
return System.identityHashCode(this);
}
-
+
public void binderDied() {
linkedToDeath = false;
owner.unregisterReceiver(receiver);
}
-
+
+ void writeToProto(ProtoOutputStream proto, long fieldId) {
+ long token = proto.start(fieldId);
+ app.writeToProto(proto, ReceiverListProto.APP);
+ proto.write(ReceiverListProto.PID, pid);
+ proto.write(ReceiverListProto.UID, uid);
+ proto.write(ReceiverListProto.USER, userId);
+ if (curBroadcast != null) {
+ curBroadcast.writeToProto(proto, ReceiverListProto.CURRENT);
+ }
+ proto.write(ReceiverListProto.LINKED_TO_DEATH, linkedToDeath);
+ final int N = size();
+ for (int i=0; i<N; i++) {
+ BroadcastFilter bf = get(i);
+ bf.writeToProto(proto, ReceiverListProto.FILTERS);
+ }
+ proto.write(ReceiverListProto.HEX_HASH, Integer.toHexString(System.identityHashCode(this)));
+ proto.end(token);
+ }
+
void dumpLocal(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("app="); pw.print(app != null ? app.toShortString() : null);
pw.print(" pid="); pw.print(pid); pw.print(" uid="); pw.print(uid);
@@ -74,7 +95,7 @@ final class ReceiverList extends ArrayList<BroadcastFilter>
pw.print(" linkedToDeath="); pw.println(linkedToDeath);
}
}
-
+
void dump(PrintWriter pw, String prefix) {
Printer pr = new PrintWriterPrinter(pw);
dumpLocal(pw, prefix);
@@ -89,7 +110,7 @@ final class ReceiverList extends ArrayList<BroadcastFilter>
bf.dumpInReceiverList(pw, pr, p2);
}
}
-
+
public String toString() {
if (stringName != null) {
return stringName;
diff --git a/com/android/server/am/RecentTasks.java b/com/android/server/am/RecentTasks.java
index 365c5b1d..78274bdc 100644
--- a/com/android/server/am/RecentTasks.java
+++ b/com/android/server/am/RecentTasks.java
@@ -16,15 +16,25 @@
package com.android.server.am;
+import static android.app.ActivityManager.FLAG_AND_UNLOCKED;
+import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE;
+import static android.app.ActivityManager.RECENT_WITH_EXCLUDED;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS_TRIM_TASKS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RECENTS;
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TASKS;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
import com.google.android.collect.Sets;
@@ -37,43 +47,87 @@ import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
+import android.content.pm.ParceledListSlice;
+import android.content.pm.UserInfo;
+import android.content.res.Resources;
import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.os.Bundle;
import android.os.Environment;
+import android.os.IBinder;
import android.os.RemoteException;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.util.ArraySet;
+import android.util.MutableBoolean;
+import android.util.MutableInt;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.am.ActivityStack.ActivityState;
+
import java.io.File;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Set;
+import java.util.concurrent.TimeUnit;
/**
- * Class for managing the recent tasks list.
+ * Class for managing the recent tasks list. The list is ordered by most recent (index 0) to the
+ * least recent.
*/
-class RecentTasks extends ArrayList<TaskRecord> {
+class RecentTasks {
private static final String TAG = TAG_WITH_CLASS_NAME ? "RecentTasks" : TAG_AM;
private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
private static final String TAG_TASKS = TAG + POSTFIX_TASKS;
+ private static final boolean TRIMMED = true;
- // Maximum number recent bitmaps to keep in memory.
- private static final int MAX_RECENT_BITMAPS = 3;
private static final int DEFAULT_INITIAL_CAPACITY = 5;
// Whether or not to move all affiliated tasks to the front when one of the tasks is launched
private static final boolean MOVE_AFFILIATED_TASKS_TO_FRONT = false;
+ // Comparator to sort by taskId
+ private static final Comparator<TaskRecord> TASK_ID_COMPARATOR =
+ (lhs, rhs) -> rhs.taskId - lhs.taskId;
+
+ // Placeholder variables to keep track of activities/apps that are no longer avialble while
+ // iterating through the recents list
+ private static final ActivityInfo NO_ACTIVITY_INFO_TOKEN = new ActivityInfo();
+ private static final ApplicationInfo NO_APPLICATION_INFO_TOKEN = new ApplicationInfo();
+
+ /**
+ * Callbacks made when manipulating the list.
+ */
+ interface Callbacks {
+ /**
+ * Called when a task is added to the recent tasks list.
+ */
+ void onRecentTaskAdded(TaskRecord task);
+
+ /**
+ * Called when a task is removed from the recent tasks list.
+ */
+ void onRecentTaskRemoved(TaskRecord task, boolean wasTrimmed);
+ }
+
/**
* Save recent tasks information across reboots.
*/
private final TaskPersister mTaskPersister;
private final ActivityManagerService mService;
+ private final UserController mUserController;
+
+ /**
+ * Mapping of user id -> whether recent tasks have been loaded for that user.
+ */
private final SparseBooleanArray mUsersWithRecentsLoaded = new SparseBooleanArray(
DEFAULT_INITIAL_CAPACITY);
@@ -81,21 +135,106 @@ class RecentTasks extends ArrayList<TaskRecord> {
* Stores for each user task ids that are taken by tasks residing in persistent storage. These
* tasks may or may not currently be in memory.
*/
- final SparseArray<SparseBooleanArray> mPersistedTaskIds = new SparseArray<>(
+ private final SparseArray<SparseBooleanArray> mPersistedTaskIds = new SparseArray<>(
DEFAULT_INITIAL_CAPACITY);
+ // List of all active recent tasks
+ private final ArrayList<TaskRecord> mTasks = new ArrayList<>();
+ private final ArrayList<Callbacks> mCallbacks = new ArrayList<>();
+
+ // These values are generally loaded from resources, but can be set dynamically in the tests
+ private boolean mHasVisibleRecentTasks;
+ private int mGlobalMaxNumTasks;
+ private int mMinNumVisibleTasks;
+ private int mMaxNumVisibleTasks;
+ private long mActiveTasksSessionDurationMs;
+
// Mainly to avoid object recreation on multiple calls.
- private final ArrayList<TaskRecord> mTmpRecents = new ArrayList<TaskRecord>();
+ private final ArrayList<TaskRecord> mTmpRecents = new ArrayList<>();
private final HashMap<ComponentName, ActivityInfo> mTmpAvailActCache = new HashMap<>();
private final HashMap<String, ApplicationInfo> mTmpAvailAppCache = new HashMap<>();
- private final ActivityInfo mTmpActivityInfo = new ActivityInfo();
- private final ApplicationInfo mTmpAppInfo = new ApplicationInfo();
+ private final SparseBooleanArray mTmpQuietProfileUserIds = new SparseBooleanArray();
- RecentTasks(ActivityManagerService service, ActivityStackSupervisor mStackSupervisor) {
- File systemDir = Environment.getDataSystemDirectory();
+ @VisibleForTesting
+ RecentTasks(ActivityManagerService service, TaskPersister taskPersister,
+ UserController userController) {
mService = service;
- mTaskPersister = new TaskPersister(systemDir, mStackSupervisor, service, this);
- mStackSupervisor.setRecentTasks(this);
+ mUserController = userController;
+ mTaskPersister = taskPersister;
+ mGlobalMaxNumTasks = ActivityManager.getMaxRecentTasksStatic();
+ mHasVisibleRecentTasks = true;
+ }
+
+ RecentTasks(ActivityManagerService service, ActivityStackSupervisor stackSupervisor) {
+ final File systemDir = Environment.getDataSystemDirectory();
+ final Resources res = service.mContext.getResources();
+ mService = service;
+ mUserController = service.mUserController;
+ mTaskPersister = new TaskPersister(systemDir, stackSupervisor, service, this);
+ mGlobalMaxNumTasks = ActivityManager.getMaxRecentTasksStatic();
+ mHasVisibleRecentTasks = res.getBoolean(com.android.internal.R.bool.config_hasRecents);
+ loadParametersFromResources(service.mContext.getResources());
+ }
+
+ @VisibleForTesting
+ void setParameters(int minNumVisibleTasks, int maxNumVisibleTasks,
+ long activeSessionDurationMs) {
+ mMinNumVisibleTasks = minNumVisibleTasks;
+ mMaxNumVisibleTasks = maxNumVisibleTasks;
+ mActiveTasksSessionDurationMs = activeSessionDurationMs;
+ }
+
+ @VisibleForTesting
+ void setGlobalMaxNumTasks(int globalMaxNumTasks) {
+ mGlobalMaxNumTasks = globalMaxNumTasks;
+ }
+
+ /**
+ * Loads the parameters from the system resources.
+ */
+ @VisibleForTesting
+ void loadParametersFromResources(Resources res) {
+ if (ActivityManager.isLowRamDeviceStatic()) {
+ mMinNumVisibleTasks = res.getInteger(
+ com.android.internal.R.integer.config_minNumVisibleRecentTasks_lowRam);
+ mMaxNumVisibleTasks = res.getInteger(
+ com.android.internal.R.integer.config_maxNumVisibleRecentTasks_lowRam);
+ } else if (SystemProperties.getBoolean("ro.recents.grid", false)) {
+ mMinNumVisibleTasks = res.getInteger(
+ com.android.internal.R.integer.config_minNumVisibleRecentTasks_grid);
+ mMaxNumVisibleTasks = res.getInteger(
+ com.android.internal.R.integer.config_maxNumVisibleRecentTasks_grid);
+ } else {
+ mMinNumVisibleTasks = res.getInteger(
+ com.android.internal.R.integer.config_minNumVisibleRecentTasks);
+ mMaxNumVisibleTasks = res.getInteger(
+ com.android.internal.R.integer.config_maxNumVisibleRecentTasks);
+ }
+ final int sessionDurationHrs = res.getInteger(
+ com.android.internal.R.integer.config_activeTaskDurationHours);
+ mActiveTasksSessionDurationMs = (sessionDurationHrs > 0)
+ ? TimeUnit.HOURS.toMillis(sessionDurationHrs)
+ : -1;
+ }
+
+ void registerCallback(Callbacks callback) {
+ mCallbacks.add(callback);
+ }
+
+ void unregisterCallback(Callbacks callback) {
+ mCallbacks.remove(callback);
+ }
+
+ private void notifyTaskAdded(TaskRecord task) {
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).onRecentTaskAdded(task);
+ }
+ }
+
+ private void notifyTaskRemoved(TaskRecord task, boolean wasTrimmed) {
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).onRecentTaskRemoved(task, wasTrimmed);
+ }
}
/**
@@ -106,6 +245,7 @@ class RecentTasks extends ArrayList<TaskRecord> {
*/
void loadUserRecentsLocked(int userId) {
if (mUsersWithRecentsLoaded.get(userId)) {
+ // User already loaded, return early
return;
}
@@ -114,14 +254,14 @@ class RecentTasks extends ArrayList<TaskRecord> {
// Check if any tasks are added before recents is loaded
final SparseBooleanArray preaddedTasks = new SparseBooleanArray();
- for (final TaskRecord task : this) {
+ for (final TaskRecord task : mTasks) {
if (task.userId == userId && shouldPersistTaskLocked(task)) {
preaddedTasks.put(task.taskId, true);
}
}
Slog.i(TAG, "Loading recents for user " + userId + " into memory.");
- addAll(mTaskPersister.restoreTasksForUserLocked(userId, preaddedTasks));
+ mTasks.addAll(mTaskPersister.restoreTasksForUserLocked(userId, preaddedTasks));
cleanupLocked(userId);
mUsersWithRecentsLoaded.put(userId, true);
@@ -140,11 +280,25 @@ class RecentTasks extends ArrayList<TaskRecord> {
}
}
- boolean taskIdTakenForUserLocked(int taskId, int userId) {
+ /**
+ * @return whether the {@param taskId} is currently in use for the given user.
+ */
+ boolean containsTaskId(int taskId, int userId) {
loadPersistedTaskIdsForUserLocked(userId);
return mPersistedTaskIds.get(userId).get(taskId);
}
+ /**
+ * @return all the task ids for the user with the given {@param userId}.
+ */
+ SparseBooleanArray getTaskIdsForUser(int userId) {
+ loadPersistedTaskIdsForUserLocked(userId);
+ return mPersistedTaskIds.get(userId);
+ }
+
+ /**
+ * Kicks off the task persister to write any pending tasks to disk.
+ */
void notifyTaskPersisterLocked(TaskRecord task, boolean flush) {
final ActivityStack stack = task != null ? task.getStack() : null;
if (stack != null && stack.isHomeOrRecentsStack()) {
@@ -164,8 +318,8 @@ class RecentTasks extends ArrayList<TaskRecord> {
mPersistedTaskIds.valueAt(i).clear();
}
}
- for (int i = size() - 1; i >= 0; i--) {
- final TaskRecord task = get(i);
+ for (int i = mTasks.size() - 1; i >= 0; i--) {
+ final TaskRecord task = mTasks.get(i);
if (shouldPersistTaskLocked(task)) {
// Set of persisted taskIds for task.userId should not be null here
// TODO Investigate why it can happen. For now initialize with an empty set
@@ -180,12 +334,12 @@ class RecentTasks extends ArrayList<TaskRecord> {
}
private static boolean shouldPersistTaskLocked(TaskRecord task) {
- final ActivityStack<?> stack = task.getStack();
+ final ActivityStack stack = task.getStack();
return task.isPersistable && (stack == null || !stack.isHomeOrRecentsStack());
}
void onSystemReadyLocked() {
- clear();
+ mTasks.clear();
mTaskPersister.startPersisting();
}
@@ -225,14 +379,6 @@ class RecentTasks extends ArrayList<TaskRecord> {
return usersWithRecentsLoaded;
}
- private void unloadUserRecentsLocked(int userId) {
- if (mUsersWithRecentsLoaded.get(userId)) {
- Slog.i(TAG, "Unloading recents for user " + userId + " from memory.");
- mUsersWithRecentsLoaded.delete(userId);
- removeTasksForUserLocked(userId);
- }
- }
-
/**
* Removes recent tasks and any other state kept in memory for the passed in user. Does not
* touch the information present on persistent storage.
@@ -240,44 +386,36 @@ class RecentTasks extends ArrayList<TaskRecord> {
* @param userId the id of the user
*/
void unloadUserDataFromMemoryLocked(int userId) {
- unloadUserRecentsLocked(userId);
+ if (mUsersWithRecentsLoaded.get(userId)) {
+ Slog.i(TAG, "Unloading recents for user " + userId + " from memory.");
+ mUsersWithRecentsLoaded.delete(userId);
+ removeTasksForUserLocked(userId);
+ }
mPersistedTaskIds.delete(userId);
mTaskPersister.unloadUserDataFromMemory(userId);
}
- TaskRecord taskForIdLocked(int id) {
- final int recentsCount = size();
- for (int i = 0; i < recentsCount; i++) {
- TaskRecord tr = get(i);
- if (tr.taskId == id) {
- return tr;
- }
- }
- return null;
- }
-
/** Remove recent tasks for a user. */
- void removeTasksForUserLocked(int userId) {
+ private void removeTasksForUserLocked(int userId) {
if(userId <= 0) {
Slog.i(TAG, "Can't remove recent task on user " + userId);
return;
}
- for (int i = size() - 1; i >= 0; --i) {
- TaskRecord tr = get(i);
+ for (int i = mTasks.size() - 1; i >= 0; --i) {
+ TaskRecord tr = mTasks.get(i);
if (tr.userId == userId) {
if(DEBUG_TASKS) Slog.i(TAG_TASKS,
"remove RecentTask " + tr + " when finishing user" + userId);
- remove(i);
- tr.removedFromRecents();
+ remove(mTasks.get(i));
}
}
}
void onPackagesSuspendedChanged(String[] packages, boolean suspended, int userId) {
final Set<String> packageNames = Sets.newHashSet(packages);
- for (int i = size() - 1; i >= 0; --i) {
- final TaskRecord tr = get(i);
+ for (int i = mTasks.size() - 1; i >= 0; --i) {
+ final TaskRecord tr = mTasks.get(i);
if (tr.realActivity != null
&& packageNames.contains(tr.realActivity.getPackageName())
&& tr.userId == userId
@@ -286,7 +424,36 @@ class RecentTasks extends ArrayList<TaskRecord> {
notifyTaskPersisterLocked(tr, false);
}
}
+ }
+
+ void removeTasksByPackageName(String packageName, int userId) {
+ for (int i = mTasks.size() - 1; i >= 0; --i) {
+ final TaskRecord tr = mTasks.get(i);
+ final String taskPackageName =
+ tr.getBaseIntent().getComponent().getPackageName();
+ if (tr.userId != userId) return;
+ if (!taskPackageName.equals(packageName)) return;
+
+ mService.mStackSupervisor.removeTaskByIdLocked(tr.taskId, true, REMOVE_FROM_RECENTS);
+ }
+ }
+
+ void cleanupDisabledPackageTasksLocked(String packageName, Set<String> filterByClasses,
+ int userId) {
+ for (int i = mTasks.size() - 1; i >= 0; --i) {
+ final TaskRecord tr = mTasks.get(i);
+ if (userId != UserHandle.USER_ALL && tr.userId != userId) {
+ continue;
+ }
+ ComponentName cn = tr.intent.getComponent();
+ final boolean sameComponent = cn != null && cn.getPackageName().equals(packageName)
+ && (filterByClasses == null || filterByClasses.contains(cn.getClassName()));
+ if (sameComponent) {
+ mService.mStackSupervisor.removeTaskByIdLocked(tr.taskId, false,
+ REMOVE_FROM_RECENTS);
+ }
+ }
}
/**
@@ -295,24 +462,28 @@ class RecentTasks extends ArrayList<TaskRecord> {
* of affiliations.
*/
void cleanupLocked(int userId) {
- int recentsCount = size();
+ int recentsCount = mTasks.size();
if (recentsCount == 0) {
// Happens when called from the packagemanager broadcast before boot,
// or just any empty list.
return;
}
+ // Clear the temp lists
+ mTmpAvailActCache.clear();
+ mTmpAvailAppCache.clear();
+
final IPackageManager pm = AppGlobals.getPackageManager();
for (int i = recentsCount - 1; i >= 0; i--) {
- final TaskRecord task = get(i);
+ final TaskRecord task = mTasks.get(i);
if (userId != UserHandle.USER_ALL && task.userId != userId) {
// Only look at tasks for the user ID of interest.
continue;
}
if (task.autoRemoveRecents && task.getTopActivity() == null) {
// This situation is broken, and we should just get rid of it now.
- remove(i);
- task.removedFromRecents();
+ mTasks.remove(i);
+ notifyTaskRemoved(task, !TRIMMED);
Slog.w(TAG, "Removing auto-remove without activity: " + task);
continue;
}
@@ -331,11 +502,11 @@ class RecentTasks extends ArrayList<TaskRecord> {
continue;
}
if (ai == null) {
- ai = mTmpActivityInfo;
+ ai = NO_ACTIVITY_INFO_TOKEN;
}
mTmpAvailActCache.put(task.realActivity, ai);
}
- if (ai == mTmpActivityInfo) {
+ if (ai == NO_ACTIVITY_INFO_TOKEN) {
// This could be either because the activity no longer exists, or the
// app is temporarily gone. For the former we want to remove the recents
// entry; for the latter we want to mark it as unavailable.
@@ -350,15 +521,15 @@ class RecentTasks extends ArrayList<TaskRecord> {
continue;
}
if (app == null) {
- app = mTmpAppInfo;
+ app = NO_APPLICATION_INFO_TOKEN;
}
mTmpAvailAppCache.put(task.realActivity.getPackageName(), app);
}
- if (app == mTmpAppInfo
+ if (app == NO_APPLICATION_INFO_TOKEN
|| (app.flags & ApplicationInfo.FLAG_INSTALLED) == 0) {
// Doesn't exist any more! Good-bye.
- remove(i);
- task.removedFromRecents();
+ mTasks.remove(i);
+ notifyTaskRemoved(task, !TRIMMED);
Slog.w(TAG, "Removing no longer valid recent: " + task);
continue;
} else {
@@ -390,121 +561,197 @@ class RecentTasks extends ArrayList<TaskRecord> {
// Verify the affiliate chain for each task.
int i = 0;
- recentsCount = size();
+ recentsCount = mTasks.size();
while (i < recentsCount) {
i = processNextAffiliateChainLocked(i);
}
// recent tasks are now in sorted, affiliated order.
}
- private final boolean moveAffiliatedTasksToFront(TaskRecord task, int taskIndex) {
- int recentsCount = size();
- TaskRecord top = task;
- int topIndex = taskIndex;
- while (top.mNextAffiliate != null && topIndex > 0) {
- top = top.mNextAffiliate;
- topIndex--;
+ /**
+ * @return whether the given {@param task} can be added to the list without causing another
+ * task to be trimmed as a result of that add.
+ */
+ private boolean canAddTaskWithoutTrim(TaskRecord task) {
+ return findTrimIndexForAddTask(task) == -1;
+ }
+
+ /**
+ * Returns the list of {@link ActivityManager.AppTask}s.
+ */
+ ArrayList<IBinder> getAppTasksList(int callingUid, String callingPackage) {
+ final ArrayList<IBinder> list = new ArrayList<>();
+ final int size = mTasks.size();
+ for (int i = 0; i < size; i++) {
+ final TaskRecord tr = mTasks.get(i);
+ // Skip tasks that do not match the caller. We don't need to verify
+ // callingPackage, because we are also limiting to callingUid and know
+ // that will limit to the correct security sandbox.
+ if (tr.effectiveUid != callingUid) {
+ continue;
+ }
+ Intent intent = tr.getBaseIntent();
+ if (intent == null || !callingPackage.equals(intent.getComponent().getPackageName())) {
+ continue;
+ }
+ ActivityManager.RecentTaskInfo taskInfo = createRecentTaskInfo(tr);
+ AppTaskImpl taskImpl = new AppTaskImpl(mService, taskInfo.persistentId, callingUid);
+ list.add(taskImpl.asBinder());
}
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: adding affilliates starting at "
- + topIndex + " from intial " + taskIndex);
- // Find the end of the chain, doing a sanity check along the way.
- boolean sane = top.mAffiliatedTaskId == task.mAffiliatedTaskId;
- int endIndex = topIndex;
- TaskRecord prev = top;
- while (endIndex < recentsCount) {
- TaskRecord cur = get(endIndex);
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: looking at next chain @"
- + endIndex + " " + cur);
- if (cur == top) {
- // Verify start of the chain.
- if (cur.mNextAffiliate != null || cur.mNextAffiliateTaskId != INVALID_TASK_ID) {
- Slog.wtf(TAG, "Bad chain @" + endIndex
- + ": first task has next affiliate: " + prev);
- sane = false;
- break;
+ return list;
+ }
+
+ /**
+ * @return the list of recent tasks for presentation.
+ */
+ ParceledListSlice<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum, int flags,
+ boolean getTasksAllowed, boolean getDetailedTasks, int userId, int callingUid) {
+ final boolean withExcluded = (flags & RECENT_WITH_EXCLUDED) != 0;
+
+ if (!mService.isUserRunning(userId, FLAG_AND_UNLOCKED)) {
+ Slog.i(TAG, "user " + userId + " is still locked. Cannot load recents");
+ return ParceledListSlice.emptyList();
+ }
+ loadUserRecentsLocked(userId);
+
+ final Set<Integer> includedUsers = mUserController.getProfileIds(userId);
+ includedUsers.add(Integer.valueOf(userId));
+
+ final ArrayList<ActivityManager.RecentTaskInfo> res = new ArrayList<>();
+ final int size = mTasks.size();
+ int numVisibleTasks = 0;
+ for (int i = 0; i < size; i++) {
+ final TaskRecord tr = mTasks.get(i);
+
+ if (isVisibleRecentTask(tr)) {
+ numVisibleTasks++;
+ if (isInVisibleRange(tr, numVisibleTasks)) {
+ // Fall through
+ } else {
+ // Not in visible range
+ continue;
}
} else {
- // Verify middle of the chain's next points back to the one before.
- if (cur.mNextAffiliate != prev
- || cur.mNextAffiliateTaskId != prev.taskId) {
- Slog.wtf(TAG, "Bad chain @" + endIndex
- + ": middle task " + cur + " @" + endIndex
- + " has bad next affiliate "
- + cur.mNextAffiliate + " id " + cur.mNextAffiliateTaskId
- + ", expected " + prev);
- sane = false;
- break;
- }
+ // Not visible
+ continue;
}
- if (cur.mPrevAffiliateTaskId == INVALID_TASK_ID) {
- // Chain ends here.
- if (cur.mPrevAffiliate != null) {
- Slog.wtf(TAG, "Bad chain @" + endIndex
- + ": last task " + cur + " has previous affiliate "
- + cur.mPrevAffiliate);
- sane = false;
- }
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: end of chain @" + endIndex);
- break;
- } else {
- // Verify middle of the chain's prev points to a valid item.
- if (cur.mPrevAffiliate == null) {
- Slog.wtf(TAG, "Bad chain @" + endIndex
- + ": task " + cur + " has previous affiliate "
- + cur.mPrevAffiliate + " but should be id "
- + cur.mPrevAffiliate);
- sane = false;
- break;
- }
+
+ // Skip remaining tasks once we reach the requested size
+ if (res.size() >= maxNum) {
+ continue;
}
- if (cur.mAffiliatedTaskId != task.mAffiliatedTaskId) {
- Slog.wtf(TAG, "Bad chain @" + endIndex
- + ": task " + cur + " has affiliated id "
- + cur.mAffiliatedTaskId + " but should be "
- + task.mAffiliatedTaskId);
- sane = false;
- break;
+
+ // Only add calling user or related users recent tasks
+ if (!includedUsers.contains(Integer.valueOf(tr.userId))) {
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Skipping, not user: " + tr);
+ continue;
}
- prev = cur;
- endIndex++;
- if (endIndex >= recentsCount) {
- Slog.wtf(TAG, "Bad chain ran off index " + endIndex
- + ": last task " + prev);
- sane = false;
- break;
+
+ if (tr.realActivitySuspended) {
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Skipping, activity suspended: " + tr);
+ continue;
}
- }
- if (sane) {
- if (endIndex < taskIndex) {
- Slog.wtf(TAG, "Bad chain @" + endIndex
- + ": did not extend to task " + task + " @" + taskIndex);
- sane = false;
+
+ // Return the entry if desired by the caller. We always return
+ // the first entry, because callers always expect this to be the
+ // foreground app. We may filter others if the caller has
+ // not supplied RECENT_WITH_EXCLUDED and there is some reason
+ // we should exclude the entry.
+
+ if (i == 0
+ || withExcluded
+ || (tr.intent == null)
+ || ((tr.intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
+ == 0)) {
+ if (!getTasksAllowed) {
+ // If the caller doesn't have the GET_TASKS permission, then only
+ // allow them to see a small subset of tasks -- their own and home.
+ if (!tr.isActivityTypeHome() && tr.effectiveUid != callingUid) {
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Skipping, not allowed: " + tr);
+ continue;
+ }
+ }
+ if (tr.autoRemoveRecents && tr.getTopActivity() == null) {
+ // Don't include auto remove tasks that are finished or finishing.
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
+ "Skipping, auto-remove without activity: " + tr);
+ continue;
+ }
+ if ((flags & RECENT_IGNORE_UNAVAILABLE) != 0 && !tr.isAvailable) {
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
+ "Skipping, unavail real act: " + tr);
+ continue;
+ }
+
+ if (!tr.mUserSetupComplete) {
+ // Don't include task launched while user is not done setting-up.
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
+ "Skipping, user setup not complete: " + tr);
+ continue;
+ }
+
+ ActivityManager.RecentTaskInfo rti = RecentTasks.createRecentTaskInfo(tr);
+ if (!getDetailedTasks) {
+ rti.baseIntent.replaceExtras((Bundle)null);
+ }
+
+ res.add(rti);
}
}
- if (sane) {
- // All looks good, we can just move all of the affiliated tasks
- // to the top.
- for (int i=topIndex; i<=endIndex; i++) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: moving affiliated " + task
- + " from " + i + " to " + (i-topIndex));
- TaskRecord cur = remove(i);
- add(i - topIndex, cur);
+ return new ParceledListSlice<>(res);
+ }
+
+ /**
+ * @return the list of persistable task ids.
+ */
+ void getPersistableTaskIds(ArraySet<Integer> persistentTaskIds) {
+ final int size = mTasks.size();
+ for (int i = 0; i < size; i++) {
+ final TaskRecord task = mTasks.get(i);
+ if (TaskPersister.DEBUG) Slog.d(TAG, "LazyTaskWriter: task=" + task
+ + " persistable=" + task.isPersistable);
+ final ActivityStack stack = task.getStack();
+ if ((task.isPersistable || task.inRecents)
+ && (stack == null || !stack.isHomeOrRecentsStack())) {
+ if (TaskPersister.DEBUG) Slog.d(TAG, "adding to persistentTaskIds task=" + task);
+ persistentTaskIds.add(task.taskId);
+ } else {
+ if (TaskPersister.DEBUG) Slog.d(TAG, "omitting from persistentTaskIds task="
+ + task);
}
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: done moving tasks " + topIndex
- + " to " + endIndex);
- return true;
}
+ }
- // Whoops, couldn't do it.
- return false;
+ @VisibleForTesting
+ ArrayList<TaskRecord> getRawTasks() {
+ return mTasks;
+ }
+
+ /**
+ * @return the task in the task list with the given {@param id} if one exists.
+ */
+ TaskRecord getTask(int id) {
+ final int recentsCount = mTasks.size();
+ for (int i = 0; i < recentsCount; i++) {
+ TaskRecord tr = mTasks.get(i);
+ if (tr.taskId == id) {
+ return tr;
+ }
+ }
+ return null;
}
- final void addLocked(TaskRecord task) {
+ /**
+ * Add a new task to the recent tasks list.
+ */
+ void add(TaskRecord task) {
+ if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "add: task=" + task);
+
final boolean isAffiliated = task.mAffiliatedTaskId != task.taskId
|| task.mNextAffiliateTaskId != INVALID_TASK_ID
|| task.mPrevAffiliateTaskId != INVALID_TASK_ID;
- int recentsCount = size();
+ int recentsCount = mTasks.size();
// Quick case: never add voice sessions.
// TODO: VI what about if it's just an activity?
// Probably nothing to do here
@@ -514,15 +761,15 @@ class RecentTasks extends ArrayList<TaskRecord> {
return;
}
// Another quick case: check if the top-most recent task is the same.
- if (!isAffiliated && recentsCount > 0 && get(0) == task) {
+ if (!isAffiliated && recentsCount > 0 && mTasks.get(0) == task) {
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: already at top: " + task);
return;
}
// Another quick case: check if this is part of a set of affiliated
// tasks that are at the top.
if (isAffiliated && recentsCount > 0 && task.inRecents
- && task.mAffiliatedTaskId == get(0).mAffiliatedTaskId) {
- if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: affiliated " + get(0)
+ && task.mAffiliatedTaskId == mTasks.get(0).mAffiliatedTaskId) {
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: affiliated " + mTasks.get(0)
+ " at top when adding " + task);
return;
}
@@ -532,12 +779,12 @@ class RecentTasks extends ArrayList<TaskRecord> {
// Slightly less quick case: the task is already in recents, so all we need
// to do is move it.
if (task.inRecents) {
- int taskIndex = indexOf(task);
+ int taskIndex = mTasks.indexOf(task);
if (taskIndex >= 0) {
- if (!isAffiliated || MOVE_AFFILIATED_TASKS_TO_FRONT) {
+ if (!isAffiliated || !MOVE_AFFILIATED_TASKS_TO_FRONT) {
// Simple case: this is not an affiliated task, so we just move it to the front.
- remove(taskIndex);
- add(0, task);
+ mTasks.remove(taskIndex);
+ mTasks.add(0, task);
notifyTaskPersisterLocked(task, false);
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: moving to top " + task
+ " from " + taskIndex);
@@ -560,20 +807,14 @@ class RecentTasks extends ArrayList<TaskRecord> {
}
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: trimming tasks for " + task);
- trimForTaskLocked(task, true);
+ trimForAddTask(task);
- recentsCount = size();
- final int maxRecents = ActivityManager.getMaxRecentTasksStatic();
- while (recentsCount >= maxRecents) {
- final TaskRecord tr = remove(recentsCount - 1);
- tr.removedFromRecents();
- recentsCount--;
- }
task.inRecents = true;
if (!isAffiliated || needAffiliationFix) {
// If this is a simple non-affiliated task, or we had some failure trying to
// handle it as part of an affilated task, then just place it at the top.
- add(0, task);
+ mTasks.add(0, task);
+ notifyTaskAdded(task);
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: adding " + task);
} else if (isAffiliated) {
// If this is a new affiliated task, then move all of the affiliated tasks
@@ -583,7 +824,7 @@ class RecentTasks extends ArrayList<TaskRecord> {
other = task.mPrevAffiliate;
}
if (other != null) {
- int otherIndex = indexOf(other);
+ int otherIndex = mTasks.indexOf(other);
if (otherIndex >= 0) {
// Insert new task at appropriate location.
int taskIndex;
@@ -598,7 +839,8 @@ class RecentTasks extends ArrayList<TaskRecord> {
}
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS,
"addRecent: new affiliated task added at " + taskIndex + ": " + task);
- add(taskIndex, task);
+ mTasks.add(taskIndex, task);
+ notifyTaskAdded(task);
// Now move everything to the front.
if (moveAffiliatedTasksToFront(task, taskIndex)) {
@@ -625,21 +867,235 @@ class RecentTasks extends ArrayList<TaskRecord> {
if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: regrouping affiliations");
cleanupLocked(task.userId);
}
+
+ // Trim the set of tasks to the active set
+ trimInactiveRecentTasks();
+ }
+
+ /**
+ * Add the task to the bottom if possible.
+ */
+ boolean addToBottom(TaskRecord task) {
+ if (!canAddTaskWithoutTrim(task)) {
+ // Adding this task would cause the task to be removed (since it's appended at
+ // the bottom and would be trimmed) so just return now
+ return false;
+ }
+
+ add(task);
+ return true;
+ }
+
+ /**
+ * Remove a task from the recent tasks list.
+ */
+ void remove(TaskRecord task) {
+ mTasks.remove(task);
+ notifyTaskRemoved(task, !TRIMMED);
+ }
+
+ /**
+ * Trims the recents task list to the global max number of recents.
+ */
+ private void trimInactiveRecentTasks() {
+ int recentsCount = mTasks.size();
+
+ // Remove from the end of the list until we reach the max number of recents
+ while (recentsCount > mGlobalMaxNumTasks) {
+ final TaskRecord tr = mTasks.remove(recentsCount - 1);
+ notifyTaskRemoved(tr, TRIMMED);
+ recentsCount--;
+ if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "Trimming over max-recents task=" + tr
+ + " max=" + mGlobalMaxNumTasks);
+ }
+
+ // Remove any tasks that belong to currently quiet profiles
+ final int[] profileUserIds = mUserController.getCurrentProfileIds();
+ mTmpQuietProfileUserIds.clear();
+ for (int userId : profileUserIds) {
+ final UserInfo userInfo = mUserController.getUserInfo(userId);
+ if (userInfo.isManagedProfile() && userInfo.isQuietModeEnabled()) {
+ mTmpQuietProfileUserIds.put(userId, true);
+ }
+ if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "User: " + userInfo
+ + " quiet=" + mTmpQuietProfileUserIds.get(userId));
+ }
+
+ // Remove any inactive tasks, calculate the latest set of visible tasks
+ int numVisibleTasks = 0;
+ for (int i = 0; i < mTasks.size();) {
+ final TaskRecord task = mTasks.get(i);
+
+ if (isActiveRecentTask(task, mTmpQuietProfileUserIds)) {
+ if (!mHasVisibleRecentTasks) {
+ // Keep all active tasks if visible recent tasks is not supported
+ i++;
+ continue;
+ }
+
+ if (!isVisibleRecentTask(task)) {
+ // Keep all active-but-invisible tasks
+ i++;
+ continue;
+ } else {
+ numVisibleTasks++;
+ if (isInVisibleRange(task, numVisibleTasks)) {
+ // Keep visible tasks in range
+ i++;
+ continue;
+ } else {
+ // Fall through to trim visible tasks that are no longer in range
+ if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG,
+ "Trimming out-of-range visible task=" + task);
+ }
+ }
+ } else {
+ // Fall through to trim inactive tasks
+ if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "Trimming inactive task=" + task);
+ }
+
+ // Task is no longer active, trim it from the list
+ mTasks.remove(task);
+ notifyTaskRemoved(task, TRIMMED);
+ notifyTaskPersisterLocked(task, false /* flush */);
+ }
+ }
+
+ /**
+ * @return whether the given task should be considered active.
+ */
+ private boolean isActiveRecentTask(TaskRecord task, SparseBooleanArray quietProfileUserIds) {
+ if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "isActiveRecentTask: task=" + task
+ + " globalMax=" + mGlobalMaxNumTasks);
+
+ if (quietProfileUserIds.get(task.userId)) {
+ // Quiet profile user's tasks are never active
+ if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "\tisQuietProfileTask=true");
+ return false;
+ }
+
+ if (task.mAffiliatedTaskId != INVALID_TASK_ID && task.mAffiliatedTaskId != task.taskId) {
+ // Keep the task active if its affiliated task is also active
+ final TaskRecord affiliatedTask = getTask(task.mAffiliatedTaskId);
+ if (affiliatedTask != null) {
+ if (!isActiveRecentTask(affiliatedTask, quietProfileUserIds)) {
+ if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG,
+ "\taffiliatedWithTask=" + affiliatedTask + " is not active");
+ return false;
+ }
+ }
+ }
+
+ // All other tasks are considered active
+ return true;
+ }
+
+ /**
+ * @return whether the given active task should be presented to the user through SystemUI.
+ */
+ private boolean isVisibleRecentTask(TaskRecord task) {
+ if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "isVisibleRecentTask: task=" + task
+ + " minVis=" + mMinNumVisibleTasks + " maxVis=" + mMaxNumVisibleTasks
+ + " sessionDuration=" + mActiveTasksSessionDurationMs
+ + " inactiveDuration=" + task.getInactiveDuration()
+ + " activityType=" + task.getActivityType()
+ + " windowingMode=" + task.getWindowingMode());
+
+ // Ignore certain activity types completely
+ switch (task.getActivityType()) {
+ case ACTIVITY_TYPE_HOME:
+ case ACTIVITY_TYPE_RECENTS:
+ return false;
+ }
+
+ // Ignore certain windowing modes
+ switch (task.getWindowingMode()) {
+ case WINDOWING_MODE_PINNED:
+ return false;
+ case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
+ if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "\ttop=" + task.getStack().topTask());
+ final ActivityStack stack = task.getStack();
+ if (stack != null && stack.topTask() == task) {
+ // Only the non-top task of the primary split screen mode is visible
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * @return whether the given visible task is within the policy range.
+ */
+ private boolean isInVisibleRange(TaskRecord task, int numVisibleTasks) {
+ // Keep the last most task even if it is excluded from recents
+ final boolean isExcludeFromRecents =
+ (task.getBaseIntent().getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
+ == Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
+ if (isExcludeFromRecents) {
+ if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "\texcludeFromRecents=true");
+ return numVisibleTasks == 1;
+ }
+
+ if (mMinNumVisibleTasks >= 0 && numVisibleTasks <= mMinNumVisibleTasks) {
+ // Always keep up to the min number of recent tasks, after that fall through to the
+ // checks below
+ return true;
+ }
+
+ if (mMaxNumVisibleTasks >= 0) {
+ // Always keep up to the max number of recent tasks, but return false afterwards
+ return numVisibleTasks <= mMaxNumVisibleTasks;
+ }
+
+ if (mActiveTasksSessionDurationMs > 0) {
+ // Keep the task if the inactive time is within the session window, this check must come
+ // after the checks for the min/max visible task range
+ if (task.getInactiveDuration() <= mActiveTasksSessionDurationMs) {
+ return true;
+ }
+ }
+
+ return false;
}
/**
* If needed, remove oldest existing entries in recents that are for the same kind
* of task as the given one.
*/
- int trimForTaskLocked(TaskRecord task, boolean doTrim) {
- int recentsCount = size();
+ private void trimForAddTask(TaskRecord task) {
+ final int removeIndex = findTrimIndexForAddTask(task);
+ if (removeIndex == -1) {
+ // Nothing to trim
+ return;
+ }
+
+ // There is a similar task that will be removed for the addition of {@param task}, but it
+ // can be the same task, and if so, the task will be re-added in add(), so skip the
+ // callbacks here.
+ final TaskRecord removedTask = mTasks.remove(removeIndex);
+ if (removedTask != task) {
+ notifyTaskRemoved(removedTask, TRIMMED);
+ if (DEBUG_RECENTS_TRIM_TASKS) Slog.d(TAG, "Trimming task=" + removedTask
+ + " for addition of task=" + task);
+ }
+ notifyTaskPersisterLocked(removedTask, false /* flush */);
+ }
+
+ /**
+ * Find the task that would be removed if the given {@param task} is added to the recent tasks
+ * list (if any).
+ */
+ private int findTrimIndexForAddTask(TaskRecord task) {
+ int recentsCount = mTasks.size();
final Intent intent = task.intent;
final boolean document = intent != null && intent.isDocument();
int maxRecents = task.maxRecents - 1;
final ActivityStack stack = task.getStack();
for (int i = 0; i < recentsCount; i++) {
- final TaskRecord tr = get(i);
+ final TaskRecord tr = mTasks.get(i);
final ActivityStack trStack = tr.getStack();
+
if (task != tr) {
if (stack != null && trStack != null && stack != trStack) {
continue;
@@ -650,7 +1106,7 @@ class RecentTasks extends ArrayList<TaskRecord> {
final Intent trIntent = tr.intent;
final boolean sameAffinity =
task.affinity != null && task.affinity.equals(tr.affinity);
- final boolean sameIntentFilter = intent != null && intent.filterEquals(trIntent);
+ final boolean sameIntent = intent != null && intent.filterEquals(trIntent);
boolean multiTasksAllowed = false;
final int flags = intent.getFlags();
if ((flags & (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_NEW_DOCUMENT)) != 0
@@ -659,7 +1115,7 @@ class RecentTasks extends ArrayList<TaskRecord> {
}
final boolean trIsDocument = trIntent != null && trIntent.isDocument();
final boolean bothDocuments = document && trIsDocument;
- if (!sameAffinity && !sameIntentFilter && !bothDocuments) {
+ if (!sameAffinity && !sameIntent && !bothDocuments) {
continue;
}
@@ -668,17 +1124,17 @@ class RecentTasks extends ArrayList<TaskRecord> {
final boolean sameActivity = task.realActivity != null
&& tr.realActivity != null
&& task.realActivity.equals(tr.realActivity);
- // If the document is open in another app or is not the same
- // document, we don't need to trim it.
if (!sameActivity) {
+ // If the document is open in another app or is not the same document, we
+ // don't need to trim it.
continue;
- // Otherwise only trim if we are over our max recents for this task
} else if (maxRecents > 0) {
+ // Otherwise only trim if we are over our max recents for this task
--maxRecents;
- if (!doTrim || !sameIntentFilter || multiTasksAllowed) {
+ if (!sameIntent || multiTasksAllowed) {
// We don't want to trim if we are not over the max allowed entries and
- // the caller doesn't want us to trim, the tasks are not of the same
- // intent filter, or multiple entries fot the task is allowed.
+ // the tasks are not of the same intent filter, or multiple entries for
+ // the task is allowed.
continue;
}
}
@@ -689,44 +1145,14 @@ class RecentTasks extends ArrayList<TaskRecord> {
continue;
}
}
-
- if (!doTrim) {
- // If the caller is not actually asking for a trim, just tell them we reached
- // a point where the trim would happen.
- return i;
- }
-
- // Either task and tr are the same or, their affinities match or their intents match
- // and neither of them is a document, or they are documents using the same activity
- // and their maxRecents has been reached.
- remove(i);
- if (task != tr) {
- tr.removedFromRecents();
- }
- i--;
- recentsCount--;
- if (task.intent == null) {
- // If the new recent task we are adding is not fully
- // specified, then replace it with the existing recent task.
- task = tr;
- }
- notifyTaskPersisterLocked(tr, false);
+ return i;
}
-
return -1;
}
- // Sort by taskId
- private static Comparator<TaskRecord> sTaskRecordComparator = new Comparator<TaskRecord>() {
- @Override
- public int compare(TaskRecord lhs, TaskRecord rhs) {
- return rhs.taskId - lhs.taskId;
- }
- };
-
// Extract the affiliates of the chain containing recent at index start.
private int processNextAffiliateChainLocked(int start) {
- final TaskRecord startTask = get(start);
+ final TaskRecord startTask = mTasks.get(start);
final int affiliateId = startTask.mAffiliatedTaskId;
// Quick identification of isolated tasks. I.e. those not launched behind.
@@ -741,17 +1167,17 @@ class RecentTasks extends ArrayList<TaskRecord> {
// Remove all tasks that are affiliated to affiliateId and put them in mTmpRecents.
mTmpRecents.clear();
- for (int i = size() - 1; i >= start; --i) {
- final TaskRecord task = get(i);
+ for (int i = mTasks.size() - 1; i >= start; --i) {
+ final TaskRecord task = mTasks.get(i);
if (task.mAffiliatedTaskId == affiliateId) {
- remove(i);
+ mTasks.remove(i);
mTmpRecents.add(task);
}
}
// Sort them all by taskId. That is the order they were create in and that order will
// always be correct.
- Collections.sort(mTmpRecents, sTaskRecordComparator);
+ Collections.sort(mTmpRecents, TASK_ID_COMPARATOR);
// Go through and fix up the linked list.
// The first one is the end of the chain and has no next.
@@ -789,11 +1215,197 @@ class RecentTasks extends ArrayList<TaskRecord> {
notifyTaskPersisterLocked(last, false);
}
- // Insert the group back into mRecentTasks at start.
- addAll(start, mTmpRecents);
+ // Insert the group back into mTmpTasks at start.
+ mTasks.addAll(start, mTmpRecents);
mTmpRecents.clear();
// Let the caller know where we left off.
return start + tmpSize;
}
+
+ private boolean moveAffiliatedTasksToFront(TaskRecord task, int taskIndex) {
+ int recentsCount = mTasks.size();
+ TaskRecord top = task;
+ int topIndex = taskIndex;
+ while (top.mNextAffiliate != null && topIndex > 0) {
+ top = top.mNextAffiliate;
+ topIndex--;
+ }
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: adding affilliates starting at "
+ + topIndex + " from intial " + taskIndex);
+ // Find the end of the chain, doing a sanity check along the way.
+ boolean sane = top.mAffiliatedTaskId == task.mAffiliatedTaskId;
+ int endIndex = topIndex;
+ TaskRecord prev = top;
+ while (endIndex < recentsCount) {
+ TaskRecord cur = mTasks.get(endIndex);
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: looking at next chain @"
+ + endIndex + " " + cur);
+ if (cur == top) {
+ // Verify start of the chain.
+ if (cur.mNextAffiliate != null || cur.mNextAffiliateTaskId != INVALID_TASK_ID) {
+ Slog.wtf(TAG, "Bad chain @" + endIndex
+ + ": first task has next affiliate: " + prev);
+ sane = false;
+ break;
+ }
+ } else {
+ // Verify middle of the chain's next points back to the one before.
+ if (cur.mNextAffiliate != prev
+ || cur.mNextAffiliateTaskId != prev.taskId) {
+ Slog.wtf(TAG, "Bad chain @" + endIndex
+ + ": middle task " + cur + " @" + endIndex
+ + " has bad next affiliate "
+ + cur.mNextAffiliate + " id " + cur.mNextAffiliateTaskId
+ + ", expected " + prev);
+ sane = false;
+ break;
+ }
+ }
+ if (cur.mPrevAffiliateTaskId == INVALID_TASK_ID) {
+ // Chain ends here.
+ if (cur.mPrevAffiliate != null) {
+ Slog.wtf(TAG, "Bad chain @" + endIndex
+ + ": last task " + cur + " has previous affiliate "
+ + cur.mPrevAffiliate);
+ sane = false;
+ }
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: end of chain @" + endIndex);
+ break;
+ } else {
+ // Verify middle of the chain's prev points to a valid item.
+ if (cur.mPrevAffiliate == null) {
+ Slog.wtf(TAG, "Bad chain @" + endIndex
+ + ": task " + cur + " has previous affiliate "
+ + cur.mPrevAffiliate + " but should be id "
+ + cur.mPrevAffiliate);
+ sane = false;
+ break;
+ }
+ }
+ if (cur.mAffiliatedTaskId != task.mAffiliatedTaskId) {
+ Slog.wtf(TAG, "Bad chain @" + endIndex
+ + ": task " + cur + " has affiliated id "
+ + cur.mAffiliatedTaskId + " but should be "
+ + task.mAffiliatedTaskId);
+ sane = false;
+ break;
+ }
+ prev = cur;
+ endIndex++;
+ if (endIndex >= recentsCount) {
+ Slog.wtf(TAG, "Bad chain ran off index " + endIndex
+ + ": last task " + prev);
+ sane = false;
+ break;
+ }
+ }
+ if (sane) {
+ if (endIndex < taskIndex) {
+ Slog.wtf(TAG, "Bad chain @" + endIndex
+ + ": did not extend to task " + task + " @" + taskIndex);
+ sane = false;
+ }
+ }
+ if (sane) {
+ // All looks good, we can just move all of the affiliated tasks
+ // to the top.
+ for (int i=topIndex; i<=endIndex; i++) {
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: moving affiliated " + task
+ + " from " + i + " to " + (i-topIndex));
+ TaskRecord cur = mTasks.remove(i);
+ mTasks.add(i - topIndex, cur);
+ }
+ if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "addRecent: done moving tasks " + topIndex
+ + " to " + endIndex);
+ return true;
+ }
+
+ // Whoops, couldn't do it.
+ return false;
+ }
+
+ void dump(PrintWriter pw, boolean dumpAll, String dumpPackage) {
+ pw.println("ACTIVITY MANAGER RECENT TASKS (dumpsys activity recents)");
+ if (mTasks.isEmpty()) {
+ return;
+ }
+
+ final MutableBoolean printedAnything = new MutableBoolean(false);
+ final MutableBoolean printedHeader = new MutableBoolean(false);
+ final int size = mTasks.size();
+ for (int i = 0; i < size; i++) {
+ final TaskRecord tr = mTasks.get(i);
+ if (dumpPackage != null && (tr.realActivity == null ||
+ !dumpPackage.equals(tr.realActivity.getPackageName()))) {
+ continue;
+ }
+
+ if (!printedHeader.value) {
+ pw.println(" Recent tasks:");
+ printedHeader.value = true;
+ printedAnything.value = true;
+ }
+ pw.print(" * Recent #"); pw.print(i); pw.print(": ");
+ pw.println(tr);
+ if (dumpAll) {
+ tr.dump(pw, " ");
+ }
+ }
+
+ if (!printedAnything.value) {
+ pw.println(" (nothing)");
+ }
+ }
+
+ /**
+ * Creates a new RecentTaskInfo from a TaskRecord.
+ */
+ static ActivityManager.RecentTaskInfo createRecentTaskInfo(TaskRecord tr) {
+ // Update the task description to reflect any changes in the task stack
+ tr.updateTaskDescription();
+
+ // Compose the recent task info
+ ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo();
+ rti.id = tr.getTopActivity() == null ? INVALID_TASK_ID : tr.taskId;
+ rti.persistentId = tr.taskId;
+ rti.baseIntent = new Intent(tr.getBaseIntent());
+ rti.origActivity = tr.origActivity;
+ rti.realActivity = tr.realActivity;
+ rti.description = tr.lastDescription;
+ rti.stackId = tr.getStackId();
+ rti.userId = tr.userId;
+ rti.taskDescription = new ActivityManager.TaskDescription(tr.lastTaskDescription);
+ rti.lastActiveTime = tr.lastActiveTime;
+ rti.affiliatedTaskId = tr.mAffiliatedTaskId;
+ rti.affiliatedTaskColor = tr.mAffiliatedTaskColor;
+ rti.numActivities = 0;
+ if (tr.mBounds != null) {
+ rti.bounds = new Rect(tr.mBounds);
+ }
+ rti.supportsSplitScreenMultiWindow = tr.supportsSplitScreenWindowingMode();
+ rti.resizeMode = tr.mResizeMode;
+ rti.configuration.setTo(tr.getConfiguration());
+
+ ActivityRecord base = null;
+ ActivityRecord top = null;
+ ActivityRecord tmp;
+
+ for (int i = tr.mActivities.size() - 1; i >= 0; --i) {
+ tmp = tr.mActivities.get(i);
+ if (tmp.finishing) {
+ continue;
+ }
+ base = tmp;
+ if (top == null || (top.state == ActivityState.INITIALIZING)) {
+ top = base;
+ }
+ rti.numActivities++;
+ }
+
+ rti.baseActivity = (base != null) ? base.intent.getComponent() : null;
+ rti.topActivity = (top != null) ? top.intent.getComponent() : null;
+
+ return rti;
+ }
}
diff --git a/com/android/server/am/ServiceRecord.java b/com/android/server/am/ServiceRecord.java
index ac85e6b1..16995e50 100644
--- a/com/android/server/am/ServiceRecord.java
+++ b/com/android/server/am/ServiceRecord.java
@@ -33,6 +33,7 @@ import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.net.Uri;
import android.os.Binder;
+import android.os.Build;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -517,14 +518,27 @@ final class ServiceRecord extends Binder {
} catch (PackageManager.NameNotFoundException e) {
}
}
- if (localForegroundNoti.getSmallIcon() == null
- || nm.getNotificationChannel(localPackageName, appUid,
+ if (nm.getNotificationChannel(localPackageName, appUid,
localForegroundNoti.getChannelId()) == null) {
+ int targetSdkVersion = Build.VERSION_CODES.O_MR1;
+ try {
+ final ApplicationInfo applicationInfo =
+ ams.mContext.getPackageManager().getApplicationInfoAsUser(
+ appInfo.packageName, 0, userId);
+ targetSdkVersion = applicationInfo.targetSdkVersion;
+ } catch (PackageManager.NameNotFoundException e) {
+ }
+ if (targetSdkVersion >= Build.VERSION_CODES.O_MR1) {
+ throw new RuntimeException(
+ "invalid channel for service notification: "
+ + foregroundNoti);
+ }
+ }
+ if (localForegroundNoti.getSmallIcon() == null) {
// Notifications whose icon is 0 are defined to not show
// a notification, silently ignoring it. We don't want to
// just ignore it, we want to prevent the service from
// being foreground.
- // Also every notification needs a channel.
throw new RuntimeException("invalid service notification: "
+ foregroundNoti);
}
diff --git a/com/android/server/am/TaskPersister.java b/com/android/server/am/TaskPersister.java
index 61994b55..2689d6a4 100644
--- a/com/android/server/am/TaskPersister.java
+++ b/com/android/server/am/TaskPersister.java
@@ -567,7 +567,7 @@ public class TaskPersister {
SparseArray<SparseBooleanArray> changedTaskIdsPerUser = new SparseArray<>();
synchronized (mService) {
for (int userId : mRecentTasks.usersWithRecentsLoadedLocked()) {
- SparseBooleanArray taskIdsToSave = mRecentTasks.mPersistedTaskIds.get(userId);
+ SparseBooleanArray taskIdsToSave = mRecentTasks.getTaskIdsForUser(userId);
SparseBooleanArray persistedIdsInFile = mTaskIdsInFile.get(userId);
if (persistedIdsInFile != null && persistedIdsInFile.equals(taskIdsToSave)) {
continue;
@@ -640,7 +640,7 @@ public class TaskPersister {
@Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
- ArraySet<Integer> persistentTaskIds = new ArraySet<Integer>();
+ ArraySet<Integer> persistentTaskIds = new ArraySet<>();
while (true) {
// We can't lock mService while holding TaskPersister.this, but we don't want to
// call removeObsoleteFiles every time through the loop, only the last time before
@@ -654,20 +654,7 @@ public class TaskPersister {
persistentTaskIds.clear();
synchronized (mService) {
if (DEBUG) Slog.d(TAG, "mRecents=" + mRecentTasks);
- for (int taskNdx = mRecentTasks.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mRecentTasks.get(taskNdx);
- if (DEBUG) Slog.d(TAG, "LazyTaskWriter: task=" + task +
- " persistable=" + task.isPersistable);
- final ActivityStack stack = task.getStack();
- if ((task.isPersistable || task.inRecents)
- && (stack == null || !stack.isHomeOrRecentsStack())) {
- if (DEBUG) Slog.d(TAG, "adding to persistentTaskIds task=" + task);
- persistentTaskIds.add(task.taskId);
- } else {
- if (DEBUG) Slog.d(TAG,
- "omitting from persistentTaskIds task=" + task);
- }
- }
+ mRecentTasks.getPersistableTaskIds(persistentTaskIds);
mService.mWindowManager.removeObsoleteTaskFiles(persistentTaskIds,
mRecentTasks.usersWithRecentsLoadedLocked());
}
diff --git a/com/android/server/am/TaskRecord.java b/com/android/server/am/TaskRecord.java
index 0d8df796..a1b45a1e 100644
--- a/com/android/server/am/TaskRecord.java
+++ b/com/android/server/am/TaskRecord.java
@@ -18,10 +18,7 @@ package com.android.server.am;
import static android.app.ActivityManager.RESIZE_MODE_FORCED;
import static android.app.ActivityManager.RESIZE_MODE_SYSTEM;
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
@@ -31,6 +28,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
import static android.content.pm.ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
@@ -45,7 +43,6 @@ import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
-import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
import static android.view.Display.DEFAULT_DISPLAY;
@@ -86,7 +83,6 @@ import android.annotation.IntDef;
import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityManager;
-import android.app.ActivityManager.StackId;
import android.app.ActivityManager.TaskDescription;
import android.app.ActivityManager.TaskSnapshot;
import android.app.ActivityOptions;
@@ -102,6 +98,7 @@ import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Debug;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
import android.provider.Settings;
@@ -155,8 +152,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
private static final String ATTR_EFFECTIVE_UID = "effective_uid";
@Deprecated
private static final String ATTR_TASKTYPE = "task_type";
- private static final String ATTR_FIRSTACTIVETIME = "first_active_time";
- private static final String ATTR_LASTACTIVETIME = "last_active_time";
private static final String ATTR_LASTDESCRIPTION = "last_description";
private static final String ATTR_LASTTIMEMOVED = "last_time_moved";
private static final String ATTR_NEVERRELINQUISH = "never_relinquish_identity";
@@ -168,7 +163,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
private static final String ATTR_CALLING_PACKAGE = "calling_package";
private static final String ATTR_SUPPORTS_PICTURE_IN_PICTURE = "supports_picture_in_picture";
private static final String ATTR_RESIZE_MODE = "resize_mode";
- private static final String ATTR_PRIVILEGED = "privileged";
private static final String ATTR_NON_FULLSCREEN_BOUNDS = "non_fullscreen_bounds";
private static final String ATTR_MIN_WIDTH = "min_width";
private static final String ATTR_MIN_HEIGHT = "min_height";
@@ -212,9 +206,10 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
ComponentName realActivity; // The actual activity component that started the task.
boolean realActivitySuspended; // True if the actual activity component that started the
// task is suspended.
- long firstActiveTime; // First time this task was active.
- long lastActiveTime; // Last time this task was active, including sleep.
boolean inRecents; // Actually in the recents list?
+ long lastActiveTime; // Last time this task was active in the current device session,
+ // including sleep. This time is initialized to the elapsed time when
+ // restored from disk.
boolean isAvailable; // Is the activity available to be launched?
boolean rootWasReset; // True if the intent at the root of the task had
// the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
@@ -237,10 +232,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
// of the root activity.
boolean mTemporarilyUnresizable; // Separate flag from mResizeMode used to suppress resize
// changes on a temporary basis.
- private int mLockTaskMode; // Which tasklock mode to launch this task in. One of
- // ActivityManager.LOCK_TASK_LAUNCH_MODE_*
- private boolean mPrivileged; // The root activity application of this task holds
- // privileged permissions.
/** Can't be put in lockTask mode. */
final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
@@ -339,6 +330,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
TaskPersister.IMAGE_EXTENSION;
userId = UserHandle.getUserId(info.applicationInfo.uid);
taskId = _taskId;
+ lastActiveTime = SystemClock.elapsedRealtime();
mAffiliatedTaskId = _taskId;
voiceSession = _voiceSession;
voiceInteractor = _voiceInteractor;
@@ -359,6 +351,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
TaskPersister.IMAGE_EXTENSION;
userId = UserHandle.getUserId(info.applicationInfo.uid);
taskId = _taskId;
+ lastActiveTime = SystemClock.elapsedRealtime();
mAffiliatedTaskId = _taskId;
voiceSession = null;
voiceInteractor = null;
@@ -385,12 +378,11 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
boolean _autoRemoveRecents, boolean _askedCompatMode, int _userId,
int _effectiveUid, String _lastDescription, ArrayList<ActivityRecord> activities,
- long _firstActiveTime, long _lastActiveTime, long lastTimeMoved,
- boolean neverRelinquishIdentity, TaskDescription _lastTaskDescription,
- int taskAffiliation, int prevTaskId, int nextTaskId, int taskAffiliationColor,
- int callingUid, String callingPackage, int resizeMode, boolean supportsPictureInPicture,
- boolean privileged, boolean _realActivitySuspended, boolean userSetupComplete,
- int minWidth, int minHeight) {
+ long lastTimeMoved, boolean neverRelinquishIdentity,
+ TaskDescription _lastTaskDescription, int taskAffiliation, int prevTaskId,
+ int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
+ int resizeMode, boolean supportsPictureInPicture, boolean _realActivitySuspended,
+ boolean userSetupComplete, int minWidth, int minHeight) {
mService = service;
mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX +
TaskPersister.IMAGE_EXTENSION;
@@ -412,8 +404,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
userId = _userId;
mUserSetupComplete = userSetupComplete;
effectiveUid = _effectiveUid;
- firstActiveTime = _firstActiveTime;
- lastActiveTime = _lastActiveTime;
+ lastActiveTime = SystemClock.elapsedRealtime();
lastDescription = _lastDescription;
mActivities = activities;
mLastTimeMoved = lastTimeMoved;
@@ -427,7 +418,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
mCallingPackage = callingPackage;
mResizeMode = resizeMode;
mSupportsPictureInPicture = supportsPictureInPicture;
- mPrivileged = privileged;
mMinWidth = minWidth;
mMinHeight = minHeight;
mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
@@ -520,7 +510,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
// All we can do for now is update the bounds so it can be used when the task is
// added to window manager.
updateOverrideConfiguration(bounds);
- if (getStackId() != FREEFORM_WORKSPACE_STACK_ID) {
+ if (!inFreeformWindowingMode()) {
// re-restore the task so it can have the proper stack association.
mService.mStackSupervisor.restoreRecentTaskLocked(this, null);
}
@@ -616,8 +606,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
* @return whether the task was reparented
*/
// TODO: Inspect all call sites and change to just changing windowing mode of the stack vs.
- // re-parenting the task. Can only be done when we are no longer using static stack Ids like
- /** {@link ActivityManager.StackId#FULLSCREEN_WORKSPACE_STACK_ID} */
+ // re-parenting the task. Can only be done when we are no longer using static stack Ids.
boolean reparent(ActivityStack preferredStack, int position,
@ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
boolean schedulePictureInPictureModeChange, String reason) {
@@ -630,12 +619,12 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
return false;
}
- final int sourceStackId = getStackId();
- final int stackId = toStack.getStackId();
+ final int toStackWindowingMode = toStack.getWindowingMode();
final ActivityRecord topActivity = getTopActivity();
- final boolean mightReplaceWindow = StackId.replaceWindowsOnTaskMove(sourceStackId, stackId)
- && topActivity != null;
+ final boolean mightReplaceWindow =
+ replaceWindowsOnTaskMove(getWindowingMode(), toStackWindowingMode)
+ && topActivity != null;
if (mightReplaceWindow) {
// We are about to relaunch the activity because its configuration changed due to
// being maximized, i.e. size change. The activity will first remove the old window
@@ -660,7 +649,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
// In some cases the focused stack isn't the front stack. E.g. pinned stack.
// Whenever we are moving the top activity from the front stack we want to make sure to
// move the stack to the front.
- final boolean wasFront = r != null && supervisor.isFrontStackOnDisplay(sourceStack)
+ final boolean wasFront = r != null && sourceStack.isTopStackOnDisplay()
&& (sourceStack.topRunningActivityLocked() == r);
// Adjust the position for the new parent stack as needed.
@@ -707,10 +696,10 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
toStack.prepareFreezingTaskBounds();
// Make sure the task has the appropriate bounds/size for the stack it is in.
- final int toStackWindowingMode = toStack.getWindowingMode();
final boolean toStackSplitScreenPrimary =
toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
- if (stackId == FULLSCREEN_WORKSPACE_STACK_ID
+ if ((toStackWindowingMode == WINDOWING_MODE_FULLSCREEN
+ || toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY)
&& !Objects.equals(mBounds, toStack.mBounds)) {
kept = resize(toStack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow,
deferResume);
@@ -749,9 +738,9 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
}
// TODO: Handle incorrect request to move before the actual move, not after.
- final boolean inSplitScreenMode = supervisor.getDefaultDisplay().hasSplitScreenStack();
+ final boolean inSplitScreenMode = supervisor.getDefaultDisplay().hasSplitScreenPrimaryStack();
supervisor.handleNonResizableTaskIfNeeded(this, preferredStack.getWindowingMode(),
- DEFAULT_DISPLAY, stackId);
+ DEFAULT_DISPLAY, toStack);
boolean successful = (preferredStack == toStack);
if (successful && toStack.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
@@ -761,6 +750,18 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
return successful;
}
+ /**
+ * Returns true if the windows of tasks being moved to the target stack from the source
+ * stack should be replaced, meaning that window manager will keep the old window around
+ * until the new is ready.
+ * @hide
+ */
+ private static boolean replaceWindowsOnTaskMove(
+ int sourceWindowingMode, int targetWindowingMode) {
+ return sourceWindowingMode == WINDOWING_MODE_FREEFORM
+ || targetWindowingMode == WINDOWING_MODE_FREEFORM;
+ }
+
void cancelWindowTransition() {
mWindowContainerController.cancelWindowTransition();
}
@@ -780,14 +781,11 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
}
void touchActiveTime() {
- lastActiveTime = System.currentTimeMillis();
- if (firstActiveTime == 0) {
- firstActiveTime = lastActiveTime;
- }
+ lastActiveTime = SystemClock.elapsedRealtime();
}
long getInactiveDuration() {
- return System.currentTimeMillis() - lastActiveTime;
+ return SystemClock.elapsedRealtime() - lastActiveTime;
}
/** Sets the original intent, and the calling uid and package. */
@@ -795,6 +793,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
mCallingUid = r.launchedFromUid;
mCallingPackage = r.launchedFromPackage;
setIntent(r.intent, r.info);
+ setLockTaskAuth(r);
}
/** Sets the original intent, _without_ updating the calling uid or package. */
@@ -878,14 +877,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
}
mResizeMode = info.resizeMode;
mSupportsPictureInPicture = info.supportsPictureInPicture();
- mPrivileged = (info.applicationInfo.privateFlags & PRIVATE_FLAG_PRIVILEGED) != 0;
- mLockTaskMode = info.lockTaskLaunchMode;
- if (!mPrivileged && (mLockTaskMode == LOCK_TASK_LAUNCH_MODE_ALWAYS
- || mLockTaskMode == LOCK_TASK_LAUNCH_MODE_NEVER)) {
- // Non-priv apps are not allowed to use always or never, fall back to default
- mLockTaskMode = LOCK_TASK_LAUNCH_MODE_DEFAULT;
- }
- setLockTaskAuth();
}
/** Sets the original minimal width and height. */
@@ -1263,7 +1254,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
mService.notifyTaskPersisterLocked(this, false);
}
- if (getStackId() == PINNED_STACK_ID) {
+ if (inPinnedWindowingMode()) {
// We normally notify listeners of task stack changes on pause, however pinned stack
// activities are normally in the paused state so no notification will be sent there
// before the activity is removed. We send it here so instead.
@@ -1422,8 +1413,17 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
}
void setLockTaskAuth() {
+ setLockTaskAuth(getRootActivity());
+ }
+
+ private void setLockTaskAuth(@Nullable ActivityRecord r) {
+ if (r == null) {
+ mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
+ return;
+ }
+
final String pkg = (realActivity != null) ? realActivity.getPackageName() : null;
- switch (mLockTaskMode) {
+ switch (r.lockTaskLaunchMode) {
case LOCK_TASK_LAUNCH_MODE_DEFAULT:
mLockTaskAuth = mService.mLockTaskController.isPackageWhitelisted(userId, pkg)
? LOCK_TASK_AUTH_WHITELISTED : LOCK_TASK_AUTH_PINNABLE;
@@ -1493,7 +1493,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
* @return True if the requested bounds are okay for a resizing request.
*/
private boolean canResizeToBounds(Rect bounds) {
- if (bounds == null || getStackId() != FREEFORM_WORKSPACE_STACK_ID) {
+ if (bounds == null || !inFreeformWindowingMode()) {
// Note: If not on the freeform workspace, we ignore the bounds.
return true;
}
@@ -1559,6 +1559,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
// values in the TaskRecord.
String label = null;
String iconFilename = null;
+ int iconResource = -1;
int colorPrimary = 0;
int colorBackground = 0;
int statusBarColor = 0;
@@ -1570,6 +1571,9 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
if (label == null) {
label = r.taskDescription.getLabel();
}
+ if (iconResource == -1) {
+ iconResource = r.taskDescription.getIconResource();
+ }
if (iconFilename == null) {
iconFilename = r.taskDescription.getIconFilename();
}
@@ -1584,8 +1588,8 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
}
topActivity = false;
}
- lastTaskDescription = new TaskDescription(label, null, iconFilename, colorPrimary,
- colorBackground, statusBarColor, navigationBarColor);
+ lastTaskDescription = new TaskDescription(label, null, iconResource, iconFilename,
+ colorPrimary, colorBackground, statusBarColor, navigationBarColor);
if (mWindowContainerController != null) {
mWindowContainerController.setTaskDescription(lastTaskDescription);
}
@@ -1647,8 +1651,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
out.attribute(null, ATTR_USERID, String.valueOf(userId));
out.attribute(null, ATTR_USER_SETUP_COMPLETE, String.valueOf(mUserSetupComplete));
out.attribute(null, ATTR_EFFECTIVE_UID, String.valueOf(effectiveUid));
- out.attribute(null, ATTR_FIRSTACTIVETIME, String.valueOf(firstActiveTime));
- out.attribute(null, ATTR_LASTACTIVETIME, String.valueOf(lastActiveTime));
out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved));
out.attribute(null, ATTR_NEVERRELINQUISH, String.valueOf(mNeverRelinquishIdentity));
if (lastDescription != null) {
@@ -1666,7 +1668,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
out.attribute(null, ATTR_RESIZE_MODE, String.valueOf(mResizeMode));
out.attribute(null, ATTR_SUPPORTS_PICTURE_IN_PICTURE,
String.valueOf(mSupportsPictureInPicture));
- out.attribute(null, ATTR_PRIVILEGED, String.valueOf(mPrivileged));
if (mLastNonFullscreenBounds != null) {
out.attribute(
null, ATTR_NON_FULLSCREEN_BOUNDS, mLastNonFullscreenBounds.flattenToString());
@@ -1721,8 +1722,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
boolean userSetupComplete = true;
int effectiveUid = -1;
String lastDescription = null;
- long firstActiveTime = -1;
- long lastActiveTime = -1;
long lastTimeOnTop = 0;
boolean neverRelinquishIdentity = true;
int taskId = INVALID_TASK_ID;
@@ -1736,7 +1735,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
String callingPackage = "";
int resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
boolean supportsPictureInPicture = false;
- boolean privileged = false;
Rect bounds = null;
int minWidth = INVALID_MIN_SIZE;
int minHeight = INVALID_MIN_SIZE;
@@ -1774,10 +1772,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
effectiveUid = Integer.parseInt(attrValue);
} else if (ATTR_TASKTYPE.equals(attrName)) {
taskType = Integer.parseInt(attrValue);
- } else if (ATTR_FIRSTACTIVETIME.equals(attrName)) {
- firstActiveTime = Long.parseLong(attrValue);
- } else if (ATTR_LASTACTIVETIME.equals(attrName)) {
- lastActiveTime = Long.parseLong(attrValue);
} else if (ATTR_LASTDESCRIPTION.equals(attrName)) {
lastDescription = attrValue;
} else if (ATTR_LASTTIMEMOVED.equals(attrName)) {
@@ -1802,8 +1796,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
resizeMode = Integer.parseInt(attrValue);
} else if (ATTR_SUPPORTS_PICTURE_IN_PICTURE.equals(attrName)) {
supportsPictureInPicture = Boolean.parseBoolean(attrValue);
- } else if (ATTR_PRIVILEGED.equals(attrName)) {
- privileged = Boolean.parseBoolean(attrValue);
} else if (ATTR_NON_FULLSCREEN_BOUNDS.equals(attrName)) {
bounds = Rect.unflattenFromString(attrValue);
} else if (ATTR_MIN_WIDTH.equals(attrName)) {
@@ -1888,10 +1880,10 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
final TaskRecord task = new TaskRecord(stackSupervisor.mService, taskId, intent,
affinityIntent, affinity, rootAffinity, realActivity, origActivity, rootHasReset,
autoRemoveRecents, askedCompatMode, userId, effectiveUid, lastDescription,
- activities, firstActiveTime, lastActiveTime, lastTimeOnTop, neverRelinquishIdentity,
- taskDescription, taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor,
- callingUid, callingPackage, resizeMode, supportsPictureInPicture, privileged,
- realActivitySuspended, userSetupComplete, minWidth, minHeight);
+ activities, lastTimeOnTop, neverRelinquishIdentity, taskDescription,
+ taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor, callingUid,
+ callingPackage, resizeMode, supportsPictureInPicture, realActivitySuspended,
+ userSetupComplete, minWidth, minHeight);
task.updateOverrideConfiguration(bounds);
for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
@@ -1911,7 +1903,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
// If the task has no requested minimal size, we'd like to enforce a minimal size
// so that the user can not render the task too small to manipulate. We don't need
// to do this for the pinned stack as the bounds are controlled by the system.
- if (getStackId() != PINNED_STACK_ID) {
+ if (!inPinnedWindowingMode()) {
if (minWidth == INVALID_MIN_SIZE) {
minWidth = mService.mStackSupervisor.mDefaultMinSizeOfResizeableTask;
}
@@ -2085,7 +2077,7 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
return;
}
- if (inStack.mStackId == FREEFORM_WORKSPACE_STACK_ID) {
+ if (inStack.inFreeformWindowingMode()) {
if (!isResizeable()) {
throw new IllegalArgumentException("Can not position non-resizeable task="
+ this + " in stack=" + inStack);
@@ -2220,7 +2212,6 @@ class TaskRecord extends ConfigurationContainer implements TaskWindowContainerLi
pw.print(" mResizeMode=" + ActivityInfo.resizeModeToString(mResizeMode));
pw.print(" mSupportsPictureInPicture=" + mSupportsPictureInPicture);
pw.print(" isResizeable=" + isResizeable());
- pw.print(" firstActiveTime=" + firstActiveTime);
pw.print(" lastActiveTime=" + lastActiveTime);
pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)");
}