am f63aa97c: Merge "Fix issue #17289876: startActivityFromRecents appears to launch the wrong task" into lmp-dev

* commit 'f63aa97c6a7ed27ff99044a09562601d08fedd73':
  Fix issue #17289876: startActivityFromRecents appears to launch the wrong task
This commit is contained in:
Dianne Hackborn
2014-08-28 19:46:01 +00:00
committed by Android Git Automerger
3 changed files with 71 additions and 33 deletions

View File

@@ -993,6 +993,6 @@ public final class BatteryStatsHelper {
} catch (RemoteException e) {
Log.w(TAG, "RemoteException:", e);
}
return null;
return new BatteryStatsImpl();
}
}

View File

@@ -1543,6 +1543,15 @@ public final class ActivityStackSupervisor implements DisplayListener {
final Intent intent = r.intent;
final int callingUid = r.launchedFromUid;
// In some flows in to this function, we retrieve the task record and hold on to it
// without a lock before calling back in to here... so the task at this point may
// not actually be in recents. Check for that, and if it isn't in recents just
// consider it invalid.
if (inTask != null && !inTask.inRecents) {
Slog.w(TAG, "Starting activity in task not in recents: " + inTask);
inTask = null;
}
final boolean launchSingleTop = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP;
final boolean launchSingleInstance = r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE;
final boolean launchSingleTask = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK;
@@ -1686,32 +1695,50 @@ public final class ActivityStackSupervisor implements DisplayListener {
// If the caller is not coming from another activity, but has given us an
// explicit task into which they would like us to launch the new activity,
// then let's see about doing that.
if (sourceRecord == null && inTask != null && inTask.stack != null && inTask.inRecents) {
if (sourceRecord == null && inTask != null && inTask.stack != null) {
final Intent baseIntent = inTask.getBaseIntent();
final ActivityRecord root = inTask.getRootActivity();
if (baseIntent == null) {
ActivityOptions.abort(options);
throw new IllegalArgumentException("Launching into task without base intent: "
+ inTask);
}
// 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 (inTask.getRootActivity() == null) {
if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0
&& !launchSingleInstance && !launchSingleTask) {
throw new IllegalStateException("Caller has inTask " + inTask
+ " but target is not a new task");
} else if (inTask.getBaseIntent() == null || !intent.getComponent().equals(
inTask.getBaseIntent().getComponent())) {
throw new IllegalStateException("Caller requested " + inTask + " is component "
+ inTask.getBaseIntent() + " but starting " + intent);
if (launchSingleInstance || launchSingleTask) {
if (!baseIntent.getComponent().equals(r.intent.getComponent())) {
ActivityOptions.abort(options);
throw new IllegalArgumentException("Trying to launch singleInstance/Task "
+ r + " into different task " + inTask);
}
if (root != null) {
ActivityOptions.abort(options);
throw new IllegalArgumentException("Caller with inTask " + inTask
+ " has root " + root + " but target is singleInstance/Task");
}
}
// If task is empty, then adopt the interesting intent launch flags in to the
// activity being started.
if (root == null) {
final int flagsOfInterest = Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_DOCUMENT
| Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
launchFlags = (launchFlags&~flagsOfInterest)
| (baseIntent.getFlags()&flagsOfInterest);
intent.setFlags(launchFlags);
inTask.setIntent(r);
// If the task is not empty, then we are going to add the new activity on top
// of the task, so it can not be launching as a new task.
} else {
if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0
|| launchSingleInstance || launchSingleTask) {
throw new IllegalStateException("Caller has inTask " + inTask
+ " but target is a new task");
}
} else if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
ActivityOptions.abort(options);
throw new IllegalStateException("Caller has inTask " + inTask
+ " but target is a new task");
}
sourceStack = inTask.stack;
reuseTask = inTask;
addingToTask = true;
} else {
inTask = null;
}
@@ -1724,10 +1751,11 @@ public final class ActivityStackSupervisor implements DisplayListener {
if (((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
(launchFlags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
|| launchSingleInstance || launchSingleTask) {
// If bring to front is requested, and no result is requested, and
// 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.
if (r.resultTo == null) {
if (inTask == null && r.resultTo == null) {
// See if there is a task to bring to the front. If this is
// a SINGLE_INSTANCE activity, there can be one and only one
// instance of it in the history, and it is always in its own
@@ -1957,13 +1985,8 @@ public final class ActivityStackSupervisor implements DisplayListener {
Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
if (inTask == null) {
// If we have an incoming task, we are just going to use that.
newTask = true;
targetStack = adjustStackFocus(r, newTask);
} else {
targetStack = inTask.stack;
}
newTask = true;
targetStack = adjustStackFocus(r, newTask);
if (!launchTaskBehind) {
targetStack.moveToFront();
}
@@ -2048,8 +2071,27 @@ public final class ActivityStackSupervisor implements DisplayListener {
return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
}
targetStack = inTask.stack;
targetStack.moveToFront();
targetStack.moveTaskToFrontLocked(inTask, r, options);
mWindowManager.moveTaskToTop(targetStack.topTask().taskId);
// Check whether we should actually launch the new activity in to the task,
// or just reuse the current activity on top.
ActivityRecord top = inTask.getTopActivity();
if (top != null && top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
if ((launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
|| launchSingleTop || launchSingleTask) {
ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
// We don't need to start a new activity, and
// the client said not to do anything if that
// is the case, so this is it!
return ActivityManager.START_RETURN_INTENT_TO_CALLER;
}
top.deliverNewIntentLocked(callingUid, r.intent);
return ActivityManager.START_DELIVERED_TO_TOP;
}
}
r.setTask(inTask, null);
if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
+ " in explicit task " + r.task);

View File

@@ -366,15 +366,11 @@ public class ActivityTestMain extends Activity {
if (recent.id >= 0) {
// Stack on top.
intent.putExtra(DocActivity.LABEL, "Stacked");
task.startActivity(ActivityTestMain.this, intent, null);
} else {
// Start root activity.
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT
| Intent.FLAG_ACTIVITY_MULTIPLE_TASK
| Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS);
intent.putExtra(DocActivity.LABEL, "New Root");
task.startActivity(ActivityTestMain.this, intent, null);
}
task.startActivity(ActivityTestMain.this, intent, null);
}
return true;
}