Implement maxRecents and fix TaskPersister bug
Activities can now set the maximum number of times that they will
appear in the recent task lists when using DocCentric mode. The
default number is 15, the min 1, and the max 100.
Also a bug in TaskPersister that deleted files because it did not
properly parse their task ids is fixed.
Fixes bug 13736052.
Change-Id: I7ccb4e6f89d6202ff31c8577bb7b9d8d1b7e5e8d
diff --git a/api/current.txt b/api/current.txt
index 79fb8df..4498507 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -310,7 +310,7 @@
field public static final int autoCompleteTextViewStyle = 16842859; // 0x101006b
field public static final int autoLink = 16842928; // 0x10100b0
field public static final int autoMirrored = 16843754; // 0x10103ea
- field public static final int autoRemoveFromRecents = 16843849; // 0x1010449
+ field public static final int autoRemoveFromRecents = 16843850; // 0x101044a
field public static final int autoStart = 16843445; // 0x10102b5
field public static final deprecated int autoText = 16843114; // 0x101016a
field public static final int autoUrlDetect = 16843404; // 0x101028c
@@ -413,10 +413,10 @@
field public static final int content = 16843355; // 0x101025b
field public static final int contentAuthority = 16843408; // 0x1010290
field public static final int contentDescription = 16843379; // 0x1010273
- field public static final int contentInsetEnd = 16843862; // 0x1010456
- field public static final int contentInsetLeft = 16843863; // 0x1010457
- field public static final int contentInsetRight = 16843864; // 0x1010458
- field public static final int contentInsetStart = 16843861; // 0x1010455
+ field public static final int contentInsetEnd = 16843863; // 0x1010457
+ field public static final int contentInsetLeft = 16843864; // 0x1010458
+ field public static final int contentInsetRight = 16843865; // 0x1010459
+ field public static final int contentInsetStart = 16843862; // 0x1010456
field public static final int controlX1 = 16843798; // 0x1010416
field public static final int controlX2 = 16843800; // 0x1010418
field public static final int controlY1 = 16843799; // 0x1010417
@@ -503,7 +503,7 @@
field public static final int excludeClass = 16843845; // 0x1010445
field public static final int excludeFromRecents = 16842775; // 0x1010017
field public static final int excludeId = 16843844; // 0x1010444
- field public static final int excludeViewName = 16843856; // 0x1010450
+ field public static final int excludeViewName = 16843857; // 0x1010451
field public static final int exitFadeDuration = 16843533; // 0x101030d
field public static final int expandableListPreferredChildIndicatorLeft = 16842834; // 0x1010052
field public static final int expandableListPreferredChildIndicatorRight = 16842835; // 0x1010053
@@ -565,7 +565,7 @@
field public static final int freezesText = 16843116; // 0x101016c
field public static final int fromAlpha = 16843210; // 0x10101ca
field public static final int fromDegrees = 16843187; // 0x10101b3
- field public static final int fromId = 16843852; // 0x101044c
+ field public static final int fromId = 16843853; // 0x101044d
field public static final int fromScene = 16843741; // 0x10103dd
field public static final int fromXDelta = 16843206; // 0x10101c6
field public static final int fromXScale = 16843202; // 0x10101c2
@@ -794,7 +794,7 @@
field public static final int manageSpaceActivity = 16842756; // 0x1010004
field public static final int mapViewStyle = 16842890; // 0x101008a
field public static final int marqueeRepeatLimit = 16843293; // 0x101021d
- field public static final int matchOrder = 16843857; // 0x1010451
+ field public static final int matchOrder = 16843858; // 0x1010452
field public static final int max = 16843062; // 0x1010136
field public static final int maxDate = 16843584; // 0x1010340
field public static final int maxEms = 16843095; // 0x1010157
@@ -803,6 +803,7 @@
field public static final int maxLength = 16843104; // 0x1010160
field public static final int maxLevel = 16843186; // 0x10101b2
field public static final int maxLines = 16843091; // 0x1010153
+ field public static final int maxRecents = 16843849; // 0x1010449
field public static final int maxRows = 16843059; // 0x1010133
field public static final int maxSdkVersion = 16843377; // 0x1010271
field public static final int maxWidth = 16843039; // 0x101011f
@@ -827,7 +828,7 @@
field public static final int moreIcon = 16843061; // 0x1010135
field public static final int multiprocess = 16842771; // 0x1010013
field public static final int name = 16842755; // 0x1010003
- field public static final int navigationBarColor = 16843860; // 0x1010454
+ field public static final int navigationBarColor = 16843861; // 0x1010455
field public static final int navigationMode = 16843471; // 0x10102cf
field public static final int negativeButtonText = 16843254; // 0x10101f6
field public static final int nestedScrollingEnabled = 16843833; // 0x1010439
@@ -861,7 +862,7 @@
field public static final int paddingBottom = 16842969; // 0x10100d9
field public static final int paddingEnd = 16843700; // 0x10103b4
field public static final int paddingLeft = 16842966; // 0x10100d6
- field public static final int paddingMode = 16843865; // 0x1010459
+ field public static final int paddingMode = 16843866; // 0x101045a
field public static final int paddingRight = 16842968; // 0x10100d8
field public static final int paddingStart = 16843699; // 0x10103b3
field public static final int paddingTop = 16842967; // 0x10100d7
@@ -957,7 +958,7 @@
field public static final int restoreAnyVersion = 16843450; // 0x10102ba
field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
field public static final int restrictedAccountType = 16843733; // 0x10103d5
- field public static final int reversible = 16843853; // 0x101044d
+ field public static final int reversible = 16843854; // 0x101044e
field public static final int right = 16843183; // 0x10101af
field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093
field public static final int ringtoneType = 16843257; // 0x10101f9
@@ -1011,7 +1012,7 @@
field public static final int selectAllOnFocus = 16843102; // 0x101015e
field public static final int selectable = 16843238; // 0x10101e6
field public static final int selectableItemBackground = 16843534; // 0x101030e
- field public static final int selectableItemBackgroundBorderless = 16843866; // 0x101045a
+ field public static final int selectableItemBackgroundBorderless = 16843867; // 0x101045b
field public static final int selectedDateVerticalBar = 16843591; // 0x1010347
field public static final int selectedWeekBackgroundColor = 16843586; // 0x1010342
field public static final int sessionService = 16843840; // 0x1010440
@@ -1048,7 +1049,7 @@
field public static final int spinnerStyle = 16842881; // 0x1010081
field public static final int spinnersShown = 16843595; // 0x101034b
field public static final int splitMotionEvents = 16843503; // 0x10102ef
- field public static final int splitTrack = 16843854; // 0x101044e
+ field public static final int splitTrack = 16843855; // 0x101044f
field public static final int src = 16843033; // 0x1010119
field public static final int ssp = 16843747; // 0x10103e3
field public static final int sspPattern = 16843749; // 0x10103e5
@@ -1060,7 +1061,7 @@
field public static final int startDelay = 16843746; // 0x10103e2
field public static final int startOffset = 16843198; // 0x10101be
field public static final deprecated int startYear = 16843132; // 0x101017c
- field public static final int stateListAnimator = 16843850; // 0x101044a
+ field public static final int stateListAnimator = 16843851; // 0x101044b
field public static final int stateNotNeeded = 16842774; // 0x1010016
field public static final int state_above_anchor = 16842922; // 0x10100aa
field public static final int state_accelerated = 16843547; // 0x101031b
@@ -1085,7 +1086,7 @@
field public static final int state_single = 16842915; // 0x10100a3
field public static final int state_window_focused = 16842909; // 0x101009d
field public static final int staticWallpaperPreview = 16843569; // 0x1010331
- field public static final int statusBarColor = 16843859; // 0x1010453
+ field public static final int statusBarColor = 16843860; // 0x1010454
field public static final int stepSize = 16843078; // 0x1010146
field public static final int stopWithTask = 16843626; // 0x101036a
field public static final int streamType = 16843273; // 0x1010209
@@ -1130,7 +1131,7 @@
field public static final int targetId = 16843740; // 0x10103dc
field public static final int targetPackage = 16842785; // 0x1010021
field public static final int targetSdkVersion = 16843376; // 0x1010270
- field public static final int targetViewName = 16843855; // 0x101044f
+ field public static final int targetViewName = 16843856; // 0x1010450
field public static final int taskAffinity = 16842770; // 0x1010012
field public static final int taskCloseEnterAnimation = 16842942; // 0x10100be
field public static final int taskCloseExitAnimation = 16842943; // 0x10100bf
@@ -1220,7 +1221,7 @@
field public static final int titleTextStyle = 16843512; // 0x10102f8
field public static final int toAlpha = 16843211; // 0x10101cb
field public static final int toDegrees = 16843188; // 0x10101b4
- field public static final int toId = 16843851; // 0x101044b
+ field public static final int toId = 16843852; // 0x101044c
field public static final int toScene = 16843742; // 0x10103de
field public static final int toXDelta = 16843207; // 0x10101c7
field public static final int toXScale = 16843203; // 0x10101c3
@@ -1309,7 +1310,7 @@
field public static final int windowContentTransitionManager = 16843795; // 0x1010413
field public static final int windowContentTransitions = 16843794; // 0x1010412
field public static final int windowDisablePreview = 16843298; // 0x1010222
- field public static final int windowDrawsSystemBarBackgrounds = 16843858; // 0x1010452
+ field public static final int windowDrawsSystemBarBackgrounds = 16843859; // 0x1010453
field public static final int windowEnableSplitTouch = 16843543; // 0x1010317
field public static final int windowEnterAnimation = 16842932; // 0x10100b4
field public static final int windowEnterTransition = 16843834; // 0x101043a
@@ -8029,6 +8030,7 @@
field public int documentLaunchMode;
field public int flags;
field public int launchMode;
+ field public int maxRecents;
field public java.lang.String parentActivityName;
field public java.lang.String permission;
field public int screenOrientation;
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index c2fe3a2..cfe4712 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -99,6 +99,12 @@
public int documentLaunchMode;
/**
+ * The maximum number of tasks rooted at this activity that can be in the recent task list.
+ * Refer to {@link android.R.attr#maxRecents}.
+ */
+ public int maxRecents;
+
+ /**
* Optional name of a permission required to be able to access this
* Activity. From the "permission" attribute.
*/
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 1c838c3..8965faa 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -2512,6 +2512,9 @@
a.info.documentLaunchMode = sa.getInt(
com.android.internal.R.styleable.AndroidManifestActivity_documentLaunchMode,
ActivityInfo.DOCUMENT_LAUNCH_NONE);
+ a.info.maxRecents = sa.getInt(
+ com.android.internal.R.styleable.AndroidManifestActivity_maxRecents,
+ 15);
a.info.screenOrientation = sa.getInt(
com.android.internal.R.styleable.AndroidManifestActivity_screenOrientation,
ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index acfbe2d..3a0f767 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -933,6 +933,12 @@
<enum name="always" value="2" />
</attr>
+ <!-- The maximum number of entries of tasks rooted at this activity in the recent task list.
+ When this number of entries is reached the least recently used instance of this activity
+ will be removed from recents. The value will be clamped between 1 and 100 inclusive.
+ The default value for this if it is not specified is 15. -->
+ <attr name="maxRecents" format="integer" />
+
<!-- Tasks launched by activities with this attribute will remain in the recent tasks
list until the last activity in the task is completed. When that happens the task
will be automatically removed from the recent tasks list.
@@ -1607,6 +1613,7 @@
<attr name="persistable" />
<attr name="allowEmbedded" />
<attr name="documentLaunchMode" />
+ <attr name="maxRecents" />
<attr name="autoRemoveFromRecents" />
</declare-styleable>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 88e1cda..ce97035 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2161,6 +2161,7 @@
<public type="attr" name="hideOnContentScroll" />
<public type="attr" name="actionOverflowMenuStyle" />
<public type="attr" name="documentLaunchMode" />
+ <public type="attr" name="maxRecents" />
<public type="attr" name="autoRemoveFromRecents" />
<public type="attr" name="stateListAnimator" />
<public type="attr" name="toId" />
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index fc808ec..70327a6 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -269,7 +269,7 @@
static final boolean IS_USER_BUILD = "user".equals(Build.TYPE);
// Maximum number of recent tasks that we can remember.
- static final int MAX_RECENT_TASKS = ActivityManager.isLowRamDeviceStatic() ? 10 : 20;
+ static final int MAX_RECENT_TASKS = ActivityManager.isLowRamDeviceStatic() ? 10 : 200;
// Amount of time after a call to stopAppSwitches() during which we will
// prevent further untrusted switches from happening.
@@ -3532,6 +3532,9 @@
// Remove any existing entries that are the same kind of task.
final Intent intent = task.intent;
final boolean document = intent != null && intent.isDocument();
+ final ComponentName comp = intent.getComponent();
+
+ int maxRecents = task.maxRecents - 1;
for (int i=0; i<N; i++) {
TaskRecord tr = mRecentTasks.get(i);
if (task != tr) {
@@ -3543,14 +3546,24 @@
(intent == null || !intent.filterEquals(trIntent))) {
continue;
}
- if (document || trIntent != null && trIntent.isDocument()) {
- // Document tasks do not match other tasks.
+ final boolean trIsDocument = trIntent != null && trIntent.isDocument();
+ if (document && trIsDocument) {
+ // These are the same document activity (not necessarily the same doc).
+ if (maxRecents > 0) {
+ --maxRecents;
+ continue;
+ }
+ // Hit the maximum number of documents for this task. Fall through
+ // and remove this document from recents.
+ } else if (document || trIsDocument) {
+ // Only one of these is a document. Not the droid we're looking for.
continue;
}
}
// Either task and tr are the same or, their affinities match or their intents match
- // and neither of them is a document.
+ // and neither of them is a document, or they are documents using the same activity
+ // and their maxRecents has been reached.
tr.disposeThumbnail();
mRecentTasks.remove(i);
i--;
@@ -3560,6 +3573,7 @@
// specified, then replace it with the existing recent task.
task = tr;
}
+ mTaskPersister.notify(tr, false);
}
if (N >= MAX_RECENT_TASKS) {
mRecentTasks.remove(N-1).disposeThumbnail();
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 1804d03..d5a50e7 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -549,14 +549,16 @@
if (DEBUG_TASKS) Slog.d(TAG, "Found matching affinity!");
return r;
}
- } else if (taskIntent != null && taskIntent.getComponent().equals(cls) &&
+ } else if (taskIntent != null && taskIntent.getComponent() != null &&
+ taskIntent.getComponent().compareTo(cls) == 0 &&
Objects.equals(documentData, taskDocumentData)) {
if (DEBUG_TASKS) Slog.d(TAG, "Found matching class!");
//dump();
if (DEBUG_TASKS) Slog.d(TAG, "For Intent " + intent + " bringing to top: "
+ r.intent);
return r;
- } else if (affinityIntent != null && affinityIntent.getComponent().equals(cls) &&
+ } else if (affinityIntent != null && affinityIntent.getComponent() != null &&
+ affinityIntent.getComponent().compareTo(cls) == 0 &&
Objects.equals(documentData, taskDocumentData)) {
if (DEBUG_TASKS) Slog.d(TAG, "Found matching class!");
//dump();
diff --git a/services/core/java/com/android/server/am/TaskPersister.java b/services/core/java/com/android/server/am/TaskPersister.java
index 3bfaca9..bb289fa 100644
--- a/services/core/java/com/android/server/am/TaskPersister.java
+++ b/services/core/java/com/android/server/am/TaskPersister.java
@@ -227,7 +227,7 @@
for (int fileNdx = 0; fileNdx < files.length; ++fileNdx) {
File file = files[fileNdx];
String filename = file.getName();
- final int taskIdEnd = filename.indexOf('_') + 1;
+ final int taskIdEnd = filename.indexOf('_');
if (taskIdEnd > 0) {
final int taskId;
try {
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index ce83ae6..1df230e 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -96,6 +96,7 @@
/** Takes on same value as first root activity */
boolean isPersistable = false;
+ int maxRecents;
/** Only used for persistable tasks, otherwise 0. The last time this task was moved. Used for
* determining the order when restoring. Sign indicates whether last task movement was to front
@@ -104,6 +105,7 @@
/** True if persistable, has changed, and has not yet been persisted */
boolean needsPersisting = false;
+
/** Launch the home activity when leaving this task. Will be false for tasks that are not on
* Display.DEFAULT_DISPLAY. */
boolean mOnTopOfHome = false;
@@ -301,6 +303,8 @@
if (mActivities.isEmpty()) {
taskType = r.mActivityType;
isPersistable = r.isPersistable();
+ // Clamp to [1, 100].
+ maxRecents = Math.min(Math.max(r.info.maxRecents, 1), 100);
} else {
// Otherwise make all added activities match this one.
r.mActivityType = taskType;