Merge "Allow a root activity to relinquish task identity"
This commit is contained in:
committed by
Android (Google) Code Review
commit
bb27b1c3a6
@@ -957,6 +957,7 @@ package android {
|
||||
field public static final int ratingBarStyleIndicator = 16843280; // 0x1010210
|
||||
field public static final int ratingBarStyleSmall = 16842877; // 0x101007d
|
||||
field public static final int readPermission = 16842759; // 0x1010007
|
||||
field public static final int relinquishTaskIdentity = 16843893; // 0x1010475
|
||||
field public static final int repeatCount = 16843199; // 0x10101bf
|
||||
field public static final int repeatMode = 16843200; // 0x10101c0
|
||||
field public static final int reqFiveWayNav = 16843314; // 0x1010232
|
||||
@@ -8085,6 +8086,7 @@ package android.content.pm {
|
||||
field public static final int FLAG_IMMERSIVE = 2048; // 0x800
|
||||
field public static final int FLAG_MULTIPROCESS = 1; // 0x1
|
||||
field public static final int FLAG_NO_HISTORY = 128; // 0x80
|
||||
field public static final int FLAG_RELINQUISH_TASK_IDENTITY = 4096; // 0x1000
|
||||
field public static final int FLAG_SINGLE_USER = 1073741824; // 0x40000000
|
||||
field public static final int FLAG_STATE_NOT_NEEDED = 16; // 0x10
|
||||
field public static final int LAUNCH_MULTIPLE = 0; // 0x0
|
||||
|
||||
@@ -251,6 +251,13 @@ public class ActivityInfo extends ComponentInfo
|
||||
* @see android.app.Activity#setImmersive(boolean)
|
||||
*/
|
||||
public static final int FLAG_IMMERSIVE = 0x0800;
|
||||
/**
|
||||
* Bit in {@link #flags}: If set, a task rooted at this activity will have its
|
||||
* baseIntent replaced by the activity immediately above this. Each activity may further
|
||||
* relinquish its identity to the activity above it using this flag. Set from the
|
||||
* android.R.attr#relinquishTaskIdentity attribute.
|
||||
*/
|
||||
public static final int FLAG_RELINQUISH_TASK_IDENTITY = 0x1000;
|
||||
/**
|
||||
* Bit in {@link #flags} indicating that tasks started with this activity are to be
|
||||
* removed from the recent list of tasks when the last activity in the task is finished.
|
||||
|
||||
@@ -2629,6 +2629,12 @@ public class PackageParser {
|
||||
false)) {
|
||||
a.info.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS;
|
||||
}
|
||||
|
||||
if (sa.getBoolean(
|
||||
com.android.internal.R.styleable.AndroidManifestActivity_relinquishTaskIdentity,
|
||||
false)) {
|
||||
a.info.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
|
||||
}
|
||||
} else {
|
||||
a.info.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
|
||||
a.info.configChanges = 0;
|
||||
|
||||
@@ -2742,7 +2742,8 @@
|
||||
android:finishOnCloseSystemDialogs="true"
|
||||
android:excludeFromRecents="true"
|
||||
android:multiprocess="true"
|
||||
android:documentLaunchMode="never">
|
||||
android:documentLaunchMode="never"
|
||||
android:relinquishTaskIdentity="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.CHOOSER" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
|
||||
@@ -985,6 +985,14 @@
|
||||
Intent.FLAG_ACTIVITY_AUTO_REMOVE_FROM_RECENTS} -->
|
||||
<attr name="autoRemoveFromRecents" format="boolean" />
|
||||
|
||||
<!-- Tasks whose root has this attribute set to true will replace baseIntent with that of the
|
||||
next activity in the task. If the next activity also has this attribute set to true then
|
||||
it will yield the baseIntent to any activity that it launches in the same task. This
|
||||
continues until an activity is encountered which has this attribute set to false. False
|
||||
is the default. This attribute set to true also permits activity's use of the
|
||||
TaskDescription to change labels, colors and icons in the recent task list. -->
|
||||
<attr name="relinquishTaskIdentity" format="boolean" />
|
||||
|
||||
<!-- The <code>manifest</code> tag is the root of an
|
||||
<code>AndroidManifest.xml</code> file,
|
||||
describing the contents of an Android package (.apk) file. One
|
||||
@@ -1653,6 +1661,7 @@
|
||||
<attr name="documentLaunchMode" />
|
||||
<attr name="maxRecents" />
|
||||
<attr name="autoRemoveFromRecents" />
|
||||
<attr name="relinquishTaskIdentity" />
|
||||
</declare-styleable>
|
||||
|
||||
<!-- The <code>activity-alias</code> tag declares a new
|
||||
|
||||
@@ -2209,6 +2209,7 @@
|
||||
<public type="attr" name="fullBackupOnly" />
|
||||
<public type="attr" name="propertyXName" />
|
||||
<public type="attr" name="propertyYName" />
|
||||
<public type="attr" name="relinquishTaskIdentity" />
|
||||
|
||||
<public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
|
||||
|
||||
|
||||
@@ -582,11 +582,6 @@ final class ActivityRecord {
|
||||
}
|
||||
}
|
||||
|
||||
boolean isRootActivity() {
|
||||
final ArrayList<ActivityRecord> activities = task.mActivities;
|
||||
return activities.size() == 0 || this == activities.get(0);
|
||||
}
|
||||
|
||||
UriPermissionOwner getUriPermissionsLocked() {
|
||||
if (uriPermissions == null) {
|
||||
uriPermissions = new UriPermissionOwner(service, this);
|
||||
@@ -1035,11 +1030,11 @@ final class ActivityRecord {
|
||||
return -1;
|
||||
}
|
||||
final TaskRecord task = r.task;
|
||||
switch (task.mActivities.indexOf(r)) {
|
||||
case -1: return -1;
|
||||
case 0: return task.taskId;
|
||||
default: return onlyRoot ? -1 : task.taskId;
|
||||
final int activityNdx = task.mActivities.indexOf(r);
|
||||
if (activityNdx < 0 || (onlyRoot && activityNdx > task.findEffectiveRootIndex())) {
|
||||
return -1;
|
||||
}
|
||||
return task.taskId;
|
||||
}
|
||||
|
||||
static ActivityRecord isInStackLocked(IBinder token) {
|
||||
|
||||
@@ -1066,40 +1066,6 @@ final class ActivityStack {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if home should be visible below the passed record.
|
||||
* @param record activity we are querying for.
|
||||
* @return true if home is visible below the passed activity, false otherwise.
|
||||
*/
|
||||
boolean isActivityOverHome(ActivityRecord record) {
|
||||
// Start at record and go down, look for either home or a visible fullscreen activity.
|
||||
final TaskRecord recordTask = record.task;
|
||||
for (int taskNdx = mTaskHistory.indexOf(recordTask); taskNdx >= 0; --taskNdx) {
|
||||
TaskRecord task = mTaskHistory.get(taskNdx);
|
||||
final ArrayList<ActivityRecord> activities = task.mActivities;
|
||||
final int startNdx =
|
||||
task == recordTask ? activities.indexOf(record) : activities.size() - 1;
|
||||
for (int activityNdx = startNdx; activityNdx >= 0; --activityNdx) {
|
||||
final ActivityRecord r = activities.get(activityNdx);
|
||||
if (r.isHomeActivity()) {
|
||||
return true;
|
||||
}
|
||||
if (!r.finishing && r.fullscreen) {
|
||||
// Passed activity is over a fullscreen activity.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (task.mOnTopOfHome) {
|
||||
// Got to the bottom of a task on top of home without finding a visible fullscreen
|
||||
// activity. Home is visible.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Got to the bottom of this stack and still don't know. If this is over the home stack
|
||||
// then record is over home. May not work if we ever get more than two layers.
|
||||
return mStackSupervisor.isFrontStack(this);
|
||||
}
|
||||
|
||||
private void setVisibile(ActivityRecord r, boolean visible) {
|
||||
r.visible = visible;
|
||||
mWindowManager.setAppVisibility(r.appToken, visible);
|
||||
@@ -1954,8 +1920,7 @@ final class ActivityStack {
|
||||
// existing activities from other tasks in to it.
|
||||
// If the caller has requested that the target task be
|
||||
// reset, then do so.
|
||||
if ((r.intent.getFlags()
|
||||
& Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
|
||||
if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
|
||||
resetTaskIfNeededLocked(r, r);
|
||||
doShow = topRunningNonDelayedActivityLocked(null) == r;
|
||||
}
|
||||
@@ -2048,7 +2013,8 @@ final class ActivityStack {
|
||||
// the root, we may no longer have the task!).
|
||||
final ArrayList<ActivityRecord> activities = task.mActivities;
|
||||
final int numActivities = activities.size();
|
||||
for (int i = numActivities - 1; i > 0; --i ) {
|
||||
final int rootActivityNdx = task.findEffectiveRootIndex();
|
||||
for (int i = numActivities - 1; i > rootActivityNdx; --i ) {
|
||||
ActivityRecord target = activities.get(i);
|
||||
|
||||
final int flags = target.info.flags;
|
||||
@@ -2207,8 +2173,10 @@ final class ActivityStack {
|
||||
|
||||
final ArrayList<ActivityRecord> activities = affinityTask.mActivities;
|
||||
final int numActivities = activities.size();
|
||||
// Do not operate on the root Activity.
|
||||
for (int i = numActivities - 1; i > 0; --i) {
|
||||
final int rootActivityNdx = affinityTask.findEffectiveRootIndex();
|
||||
|
||||
// Do not operate on or below the effective root Activity.
|
||||
for (int i = numActivities - 1; i > rootActivityNdx; --i) {
|
||||
ActivityRecord target = activities.get(i);
|
||||
|
||||
final int flags = target.info.flags;
|
||||
|
||||
@@ -27,7 +27,6 @@ import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.service.voice.IVoiceInteractionSession;
|
||||
import android.util.Slog;
|
||||
@@ -57,11 +56,12 @@ final class TaskRecord extends ThumbnailHolder {
|
||||
private static final String ATTR_ONTOPOFHOME = "on_top_of_home";
|
||||
private static final String ATTR_LASTDESCRIPTION = "last_description";
|
||||
private static final String ATTR_LASTTIMEMOVED = "last_time_moved";
|
||||
private static final String ATTR_NEVERRELINQUISH = "never_relinquish_identity";
|
||||
|
||||
private static final String TASK_THUMBNAIL_SUFFIX = "_task_thumbnail";
|
||||
|
||||
final int taskId; // Unique identifier for this task.
|
||||
final String affinity; // The affinity name for this task, or null.
|
||||
String affinity; // The affinity name for this task, or null.
|
||||
final IVoiceInteractionSession voiceSession; // Voice interaction session driving task
|
||||
final IVoiceInteractor voiceInteractor; // Associated interactor to provide to app
|
||||
Intent intent; // The original intent that started the task.
|
||||
@@ -111,13 +111,15 @@ final class TaskRecord extends ThumbnailHolder {
|
||||
* Display.DEFAULT_DISPLAY. */
|
||||
boolean mOnTopOfHome = false;
|
||||
|
||||
/** If original intent did not allow relinquishing task identity, save that information */
|
||||
boolean mNeverRelinquishIdentity = true;
|
||||
|
||||
final ActivityManagerService mService;
|
||||
|
||||
TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
|
||||
IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor) {
|
||||
mService = service;
|
||||
taskId = _taskId;
|
||||
affinity = info.taskAffinity;
|
||||
voiceSession = _voiceSession;
|
||||
voiceInteractor = _voiceInteractor;
|
||||
setIntent(_intent, info);
|
||||
@@ -128,7 +130,7 @@ final class TaskRecord extends ThumbnailHolder {
|
||||
String _affinity, ComponentName _realActivity, ComponentName _origActivity,
|
||||
boolean _rootWasReset, boolean _askedCompatMode, int _taskType, boolean _onTopOfHome,
|
||||
int _userId, String _lastDescription, ArrayList<ActivityRecord> activities,
|
||||
long lastTimeMoved) {
|
||||
long lastTimeMoved, boolean neverRelinquishIdentity) {
|
||||
mService = service;
|
||||
taskId = _taskId;
|
||||
intent = _intent;
|
||||
@@ -146,6 +148,7 @@ final class TaskRecord extends ThumbnailHolder {
|
||||
lastDescription = _lastDescription;
|
||||
mActivities = activities;
|
||||
mLastTimeMoved = lastTimeMoved;
|
||||
mNeverRelinquishIdentity = neverRelinquishIdentity;
|
||||
}
|
||||
|
||||
void touchActiveTime() {
|
||||
@@ -157,6 +160,14 @@ final class TaskRecord extends ThumbnailHolder {
|
||||
}
|
||||
|
||||
void setIntent(Intent _intent, ActivityInfo info) {
|
||||
if (intent == null) {
|
||||
mNeverRelinquishIdentity =
|
||||
(info.flags & ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY) == 0;
|
||||
} else if (mNeverRelinquishIdentity) {
|
||||
return;
|
||||
}
|
||||
|
||||
affinity = info.taskAffinity;
|
||||
stringName = null;
|
||||
|
||||
if (info.targetActivity == null) {
|
||||
@@ -282,6 +293,7 @@ final class TaskRecord extends ThumbnailHolder {
|
||||
|
||||
mActivities.remove(newTop);
|
||||
mActivities.add(newTop);
|
||||
updateEffectiveIntent();
|
||||
|
||||
setFrontOfTask();
|
||||
}
|
||||
@@ -311,6 +323,7 @@ final class TaskRecord extends ThumbnailHolder {
|
||||
r.mActivityType = taskType;
|
||||
}
|
||||
mActivities.add(index, r);
|
||||
updateEffectiveIntent();
|
||||
if (r.isPersistable()) {
|
||||
mService.notifyTaskPersisterLocked(this, false);
|
||||
}
|
||||
@@ -322,6 +335,7 @@ final class TaskRecord extends ThumbnailHolder {
|
||||
// Was previously in list.
|
||||
numFullscreen--;
|
||||
}
|
||||
updateEffectiveIntent();
|
||||
if (r.isPersistable()) {
|
||||
mService.notifyTaskPersisterLocked(this, false);
|
||||
}
|
||||
@@ -579,12 +593,19 @@ final class TaskRecord extends ThumbnailHolder {
|
||||
// utility activities.
|
||||
int activityNdx;
|
||||
final int numActivities = mActivities.size();
|
||||
final boolean relinquish = numActivities == 0 ? false :
|
||||
(mActivities.get(0).info.flags & ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY) != 0;
|
||||
for (activityNdx = Math.min(numActivities, 1); activityNdx < numActivities;
|
||||
++activityNdx) {
|
||||
final ActivityRecord r = mActivities.get(activityNdx);
|
||||
if (relinquish && (r.info.flags & ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
|
||||
// This will be the top activity for determining taskDescription. Pre-inc to
|
||||
// overcome initial decrement below.
|
||||
++activityNdx;
|
||||
break;
|
||||
}
|
||||
if (r.intent != null &&
|
||||
(r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET)
|
||||
!= 0) {
|
||||
(r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -615,6 +636,27 @@ final class TaskRecord extends ThumbnailHolder {
|
||||
}
|
||||
}
|
||||
|
||||
int findEffectiveRootIndex() {
|
||||
int activityNdx;
|
||||
final int topActivityNdx = mActivities.size() - 1;
|
||||
for (activityNdx = 0; activityNdx < topActivityNdx; ++activityNdx) {
|
||||
final ActivityRecord r = mActivities.get(activityNdx);
|
||||
if (r.finishing) {
|
||||
continue;
|
||||
}
|
||||
if ((r.info.flags & ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return activityNdx;
|
||||
}
|
||||
|
||||
void updateEffectiveIntent() {
|
||||
final int effectiveRootIndex = findEffectiveRootIndex();
|
||||
final ActivityRecord r = mActivities.get(effectiveRootIndex);
|
||||
setIntent(r.intent, r.info);
|
||||
}
|
||||
|
||||
void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
|
||||
Slog.i(TAG, "Saving task=" + this);
|
||||
|
||||
@@ -634,6 +676,7 @@ final class TaskRecord extends ThumbnailHolder {
|
||||
out.attribute(null, ATTR_TASKTYPE, String.valueOf(taskType));
|
||||
out.attribute(null, ATTR_ONTOPOFHOME, String.valueOf(mOnTopOfHome));
|
||||
out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved));
|
||||
out.attribute(null, ATTR_NEVERRELINQUISH, String.valueOf(mNeverRelinquishIdentity));
|
||||
if (lastDescription != null) {
|
||||
out.attribute(null, ATTR_LASTDESCRIPTION, lastDescription.toString());
|
||||
}
|
||||
@@ -684,6 +727,7 @@ final class TaskRecord extends ThumbnailHolder {
|
||||
int userId = 0;
|
||||
String lastDescription = null;
|
||||
long lastTimeOnTop = 0;
|
||||
boolean neverRelinquishIdentity = true;
|
||||
int taskId = -1;
|
||||
final int outerDepth = in.getDepth();
|
||||
|
||||
@@ -714,6 +758,8 @@ final class TaskRecord extends ThumbnailHolder {
|
||||
lastDescription = attrValue;
|
||||
} else if (ATTR_LASTTIMEMOVED.equals(attrName)) {
|
||||
lastTimeOnTop = Long.valueOf(attrValue);
|
||||
} else if (ATTR_NEVERRELINQUISH.equals(attrName)) {
|
||||
neverRelinquishIdentity = Boolean.valueOf(attrValue);
|
||||
} else {
|
||||
Slog.w(TAG, "TaskRecord: Unknown attribute=" + attrName);
|
||||
}
|
||||
@@ -748,7 +794,7 @@ final class TaskRecord extends ThumbnailHolder {
|
||||
final TaskRecord task = new TaskRecord(stackSupervisor.mService, taskId, intent,
|
||||
affinityIntent, affinity, realActivity, origActivity, rootHasReset,
|
||||
askedCompatMode, taskType, onTopOfHome, userId, lastDescription, activities,
|
||||
lastTimeOnTop);
|
||||
lastTimeOnTop, neverRelinquishIdentity);
|
||||
|
||||
for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
|
||||
final ActivityRecord r = activities.get(activityNdx);
|
||||
|
||||
Reference in New Issue
Block a user