diff options
3 files changed, 71 insertions, 33 deletions
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java index ee406bd..eae4427 100644 --- a/core/java/com/android/internal/os/BatteryStatsHelper.java +++ b/core/java/com/android/internal/os/BatteryStatsHelper.java @@ -993,6 +993,6 @@ public final class BatteryStatsHelper { } catch (RemoteException e) { Log.w(TAG, "RemoteException:", e); } - return null; + return new BatteryStatsImpl(); } } diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 9b32b65..1d2f7a9 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -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); diff --git a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java index ea0db56..e03b9c8 100644 --- a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java +++ b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java @@ -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; } |