void startAppFreezingScreen(IBinder token, int configChanges);
void stopAppFreezingScreen(IBinder token, boolean force);
void removeAppToken(IBinder token);
+ void moveAppToken(int index, IBinder token);
+ void moveAppTokensToTop(in List<IBinder> tokens);
+ void moveAppTokensToBottom(in List<IBinder> tokens);
// Re-evaluate the current orientation from the caller's state.
// If there is a change, the new Configuration is returned and the
import android.app.Activity;
import android.app.ActivityManager;
-import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityManagerNative;
import android.app.ActivityOptions;
import android.app.ActivityThread;
static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false;
static final boolean DEBUG_MU = localLOGV || false;
static final boolean DEBUG_IMMERSIVE = localLOGV || false;
- static final boolean VALIDATE_TOKENS = true;
+ static final boolean VALIDATE_TOKENS = false;
static final boolean SHOW_ACTIVITY_START_TIME = true;
// Control over CPU and battery monitoring.
/**
* List of intents that were used to start the most recent tasks.
*/
- private final ArrayList<TaskRecord> mRecentTasks = new ArrayList<TaskRecord>();
+ final ArrayList<TaskRecord> mRecentTasks = new ArrayList<TaskRecord>();
public class PendingActivityExtras extends Binder implements Runnable {
public final ActivityRecord activity;
* List of PendingThumbnailsRecord objects of clients who are still
* waiting to receive all of the thumbnails for a task.
*/
- final ArrayList<PendingThumbnailsRecord> mPendingThumbnails =
- new ArrayList<PendingThumbnailsRecord>();
+ final ArrayList mPendingThumbnails = new ArrayList();
+
+ /**
+ * List of HistoryRecord objects that have been finished and must
+ * still report back to a pending thumbnail receiver.
+ */
+ final ArrayList mCancelledThumbnails = new ArrayList();
final ProviderMap mProviderMap;
for (int i=0; i<activities.size(); i++) {
ActivityRecord r = activities.get(i);
if (!r.finishing) {
- mMainStack.finishActivityLocked(r, Activity.RESULT_CANCELED,
- null, "finish-heavy", true);
+ int index = mMainStack.indexOfTokenLocked(r.appToken);
+ if (index >= 0) {
+ mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
+ null, "finish-heavy", true);
+ }
}
}
}
}
- @Override
public boolean willActivityBeVisible(IBinder token) {
synchronized(this) {
- return mMainStack.willActivityBeVisibleLocked(token);
+ int i;
+ for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
+ ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
+ if (r.appToken == token) {
+ return true;
+ }
+ if (r.fullscreen && !r.finishing) {
+ return false;
+ }
+ }
+ return true;
}
}
-
+
public void overridePendingTransition(IBinder token, String packageName,
int enterAnim, int exitAnim) {
synchronized(this) {
}
mWindowManager.closeSystemDialogs(reason);
- mMainStack.closeSystemDialogsLocked();
+ for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
+ ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
+ if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
+ r.stack.finishActivityLocked(r, i,
+ Activity.RESULT_CANCELED, null, "close-sys", true);
+ }
+ }
broadcastIntentLocked(null, null, intent, null,
null, 0, null, null, null, AppOpsManager.OP_NONE, false, false, -1,
boolean didSomething = killPackageProcessesLocked(name, appId, userId,
-100, callerWillRestart, true, doit, evenPersistent,
name == null ? ("force stop user " + userId) : ("force stop " + name));
-
- if (mMainStack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
- if (!doit) {
- return true;
+
+ TaskRecord lastTask = null;
+ for (i=0; i<mMainStack.mHistory.size(); i++) {
+ ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
+ final boolean samePackage = r.packageName.equals(name)
+ || (name == null && r.userId == userId);
+ if ((userId == UserHandle.USER_ALL || r.userId == userId)
+ && (samePackage || r.task == lastTask)
+ && (r.app == null || evenPersistent || !r.app.persistent)) {
+ if (!doit) {
+ if (r.finishing) {
+ // If this activity is just finishing, then it is not
+ // interesting as far as something to stop.
+ continue;
+ }
+ return true;
+ }
+ didSomething = true;
+ Slog.i(TAG, " Force finishing activity " + r);
+ if (samePackage) {
+ if (r.app != null) {
+ r.app.removed = true;
+ }
+ r.app = null;
+ }
+ lastTask = r.task;
+ if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
+ null, "force-stop", true)) {
+ i--;
+ }
}
- didSomething = true;
}
if (mServices.forceStopLocked(name, userId, evenPersistent, doit)) {
// TASK MANAGEMENT
// =========================================================
- @Override
- public List<RunningTaskInfo> getTasks(int maxNum, int flags,
+ public List getTasks(int maxNum, int flags,
IThumbnailReceiver receiver) {
- ArrayList<RunningTaskInfo> list = new ArrayList<RunningTaskInfo>();
+ ArrayList list = new ArrayList();
- PendingThumbnailsRecord pending = new PendingThumbnailsRecord(receiver);
+ PendingThumbnailsRecord pending = null;
+ IApplicationThread topThumbnail = null;
ActivityRecord topRecord = null;
synchronized(this) {
throw new SecurityException(msg);
}
- topRecord = mMainStack.getTasksLocked(maxNum, receiver, pending, list);
+ int pos = mMainStack.mHistory.size()-1;
+ ActivityRecord next =
+ pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
+ ActivityRecord top = null;
+ TaskRecord curTask = null;
+ int numActivities = 0;
+ int numRunning = 0;
+ while (pos >= 0 && maxNum > 0) {
+ final ActivityRecord r = next;
+ pos--;
+ next = pos >= 0 ? (ActivityRecord)mMainStack.mHistory.get(pos) : null;
+
+ // Initialize state for next task if needed.
+ if (top == null ||
+ (top.state == ActivityState.INITIALIZING
+ && top.task == r.task)) {
+ top = r;
+ curTask = r.task;
+ numActivities = numRunning = 0;
+ }
+
+ // Add 'r' into the current task.
+ numActivities++;
+ if (r.app != null && r.app.thread != null) {
+ numRunning++;
+ }
+
+ if (localLOGV) Slog.v(
+ TAG, r.intent.getComponent().flattenToShortString()
+ + ": task=" + r.task);
+
+ // If the next one is a different task, generate a new
+ // TaskInfo entry for what we have.
+ if (next == null || next.task != curTask) {
+ ActivityManager.RunningTaskInfo ci
+ = new ActivityManager.RunningTaskInfo();
+ ci.id = curTask.taskId;
+ ci.baseActivity = r.intent.getComponent();
+ ci.topActivity = top.intent.getComponent();
+ if (top.thumbHolder != null) {
+ ci.description = top.thumbHolder.lastDescription;
+ }
+ ci.numActivities = numActivities;
+ ci.numRunning = numRunning;
+ //System.out.println(
+ // "#" + maxNum + ": " + " descr=" + ci.description);
+ if (ci.thumbnail == null && receiver != null) {
+ if (localLOGV) Slog.v(
+ TAG, "State=" + top.state + "Idle=" + top.idle
+ + " app=" + top.app
+ + " thr=" + (top.app != null ? top.app.thread : null));
+ if (top.state == ActivityState.RESUMED
+ || top.state == ActivityState.PAUSING) {
+ if (top.idle && top.app != null
+ && top.app.thread != null) {
+ topRecord = top;
+ topThumbnail = top.app.thread;
+ } else {
+ top.thumbnailNeeded = true;
+ }
+ }
+ if (pending == null) {
+ pending = new PendingThumbnailsRecord(receiver);
+ }
+ pending.pendingRecords.add(top);
+ }
+ list.add(ci);
+ maxNum--;
+ top = null;
+ }
+ }
- if (!pending.pendingRecords.isEmpty()) {
+ if (pending != null) {
mPendingThumbnails.add(pending);
}
}
if (localLOGV) Slog.v(TAG, "We have pending thumbnails: " + pending);
- if (topRecord != null) {
+ if (topThumbnail != null) {
if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
try {
- IApplicationThread topThumbnail = topRecord.app.thread;
topThumbnail.requestThumbnail(topRecord.appToken);
} catch (Exception e) {
Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
return false;
}
+ private final int findAffinityTaskTopLocked(int startIndex, String affinity) {
+ int j;
+ TaskRecord startTask = ((ActivityRecord)mMainStack.mHistory.get(startIndex)).task;
+ TaskRecord jt = startTask;
+
+ // First look backwards
+ for (j=startIndex-1; j>=0; j--) {
+ ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
+ if (r.task != jt) {
+ jt = r.task;
+ if (affinity.equals(jt.affinity)) {
+ return j;
+ }
+ }
+ }
+
+ // Now look forwards
+ final int N = mMainStack.mHistory.size();
+ jt = startTask;
+ for (j=startIndex+1; j<N; j++) {
+ ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(j);
+ if (r.task != jt) {
+ if (affinity.equals(jt.affinity)) {
+ return j;
+ }
+ jt = r.task;
+ }
+ }
+
+ // Might it be at the top?
+ if (affinity.equals(((ActivityRecord)mMainStack.mHistory.get(N-1)).task.affinity)) {
+ return N-1;
+ }
+
+ return -1;
+ }
+
/**
* TODO: Add mController hook
*/
mMainStack.moveTaskToFrontLocked(tr, null, options);
return;
}
- if (mMainStack.findTaskToMoveToFrontLocked(task, flags, options)) {
- return;
+ for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
+ ActivityRecord hr = (ActivityRecord)mMainStack.mHistory.get(i);
+ if (hr.task.taskId == task) {
+ if ((flags&ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
+ mMainStack.mUserLeaving = true;
+ }
+ if ((flags&ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
+ // Caller wants the home activity moved with it. To accomplish this,
+ // we'll just move the home task to the top first.
+ mMainStack.moveHomeToFrontLocked();
+ }
+ mMainStack.moveTaskToFrontLocked(hr.task, null, options);
+ return;
+ }
}
} finally {
Binder.restoreCallingIdentity(origId);
enforceNotIsolatedCaller("moveActivityTaskToBack");
synchronized(this) {
final long origId = Binder.clearCallingIdentity();
- int taskId = mMainStack.getTaskForActivityLocked(token, !nonRoot);
+ int taskId = getTaskForActivityLocked(token, !nonRoot);
if (taskId >= 0) {
return mMainStack.moveTaskToBackLocked(taskId, null);
}
public int getTaskForActivity(IBinder token, boolean onlyRoot) {
synchronized(this) {
- return mMainStack.getTaskForActivityLocked(token, onlyRoot);
+ return getTaskForActivityLocked(token, onlyRoot);
+ }
+ }
+
+ int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
+ final int N = mMainStack.mHistory.size();
+ TaskRecord lastTask = null;
+ for (int i=0; i<N; i++) {
+ ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
+ if (r.appToken == token) {
+ if (!onlyRoot || lastTask != r.task) {
+ return r.task.taskId;
+ }
+ return -1;
+ }
+ lastTask = r.task;
}
+
+ return -1;
}
// =========================================================
"unhandledBack()");
synchronized(this) {
- final long origId = Binder.clearCallingIdentity();
- try {
- mMainStack.unhandledBackLocked();
- } finally {
+ int count = mMainStack.mHistory.size();
+ if (DEBUG_SWITCH) Slog.d(
+ TAG, "Performing unhandledBack(): stack size = " + count);
+ if (count > 1) {
+ final long origId = Binder.clearCallingIdentity();
+ mMainStack.finishActivityLocked((ActivityRecord)mMainStack.mHistory.get(count-1),
+ count-1, Activity.RESULT_CANCELED, null, "unhandled-back", true);
Binder.restoreCallingIdentity(origId);
}
}
+ " has crashed too many times: killing!");
EventLog.writeEvent(EventLogTags.AM_PROCESS_CRASHED_TOO_MUCH,
app.userId, app.info.processName, app.uid);
- mMainStack.handleAppCrashLocked(app);
+ for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
+ ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
+ if (r.app == app) {
+ Slog.w(TAG, " Force finishing activity "
+ + r.intent.getComponent().flattenToShortString());
+ r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
+ null, "crashed", false);
+ }
+ }
if (!app.persistent) {
// We don't want to start this process again until the user
// explicitly does so... but for persistent process, we really
}
mMainStack.resumeTopActivityLocked(null);
} else {
- mMainStack.finishTopRunningActivityLocked(app);
+ ActivityRecord r = mMainStack.topRunningActivityLocked(null);
+ if (r != null && r.app == app) {
+ // If the top running activity is from this crashing
+ // process, then terminate it to avoid getting in a loop.
+ Slog.w(TAG, " Force finishing activity "
+ + r.intent.getComponent().flattenToShortString());
+ int index = mMainStack.indexOfActivityLocked(r);
+ r.stack.finishActivityLocked(r, index,
+ Activity.RESULT_CANCELED, null, "crashed", false);
+ // Also terminate any activities below it that aren't yet
+ // stopped, to avoid a situation where one will get
+ // re-start our crashing activity once it gets resumed again.
+ index--;
+ if (index >= 0) {
+ r = (ActivityRecord)mMainStack.mHistory.get(index);
+ if (r.state == ActivityState.RESUMED
+ || r.state == ActivityState.PAUSING
+ || r.state == ActivityState.PAUSED) {
+ if (!r.isHomeActivity || mHomeProcess != r.app) {
+ Slog.w(TAG, " Force finishing activity "
+ + r.intent.getComponent().flattenToShortString());
+ r.stack.finishActivityLocked(r, index,
+ Activity.RESULT_CANCELED, null, "crashed", false);
+ }
+ }
+ }
+ }
}
// Bump up the crash count of any services currently running in the proc.
int opti, boolean dumpAll, boolean dumpClient, String dumpPackage) {
pw.println("ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)");
pw.println(" Main stack:");
- mMainStack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage);
+ dumpHistoryList(fd, pw, mMainStack.mHistory, " ", "Hist", true, !dumpAll, dumpClient,
+ dumpPackage);
pw.println(" ");
pw.println(" Running activities (most recent first):");
dumpHistoryList(fd, pw, mMainStack.mLRUActivities, " ", "Run", false, !dumpAll, false,
*/
protected boolean dumpActivity(FileDescriptor fd, PrintWriter pw, String name, String[] args,
int opti, boolean dumpAll) {
- ArrayList<ActivityRecord> activities;
-
- synchronized (this) {
- activities = mMainStack.getDumpActivitiesLocked(name);
+ ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
+
+ if ("all".equals(name)) {
+ synchronized (this) {
+ for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
+ activities.add(r1);
+ }
+ }
+ } else if ("top".equals(name)) {
+ synchronized (this) {
+ final int N = mMainStack.mHistory.size();
+ if (N > 0) {
+ activities.add((ActivityRecord)mMainStack.mHistory.get(N-1));
+ }
+ }
+ } else {
+ ItemMatcher matcher = new ItemMatcher();
+ matcher.build(name);
+
+ synchronized (this) {
+ for (ActivityRecord r1 : (ArrayList<ActivityRecord>)mMainStack.mHistory) {
+ if (matcher.match(r1, r1.intent.getComponent())) {
+ activities.add(r1);
+ }
+ }
+ }
}
if (activities.size() <= 0) {
return needSep;
}
- static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List list,
+ private static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List list,
String prefix, String label, boolean complete, boolean brief, boolean client,
String dumpPackage) {
TaskRecord lastTask = null;
public boolean navigateUpTo(IBinder token, Intent destIntent, int resultCode,
Intent resultData) {
+ ComponentName dest = destIntent.getComponent();
synchronized (this) {
ActivityRecord srec = ActivityRecord.forToken(token);
if (srec == null) {
return false;
}
- ActivityStack stack = srec.stack;
- return stack.navigateUpToLocked(srec, destIntent, resultCode, resultData);
+ ArrayList<ActivityRecord> history = srec.stack.mHistory;
+ final int start = history.indexOf(srec);
+ if (start < 0) {
+ // Current activity is not in history stack; do nothing.
+ return false;
+ }
+ int finishTo = start - 1;
+ ActivityRecord parent = null;
+ boolean foundParentInTask = false;
+ if (dest != null) {
+ TaskRecord tr = srec.task;
+ for (int i = start - 1; i >= 0; i--) {
+ ActivityRecord r = history.get(i);
+ if (tr != r.task) {
+ // Couldn't find parent in the same task; stop at the one above this.
+ // (Root of current task; in-app "home" behavior)
+ // Always at least finish the current activity.
+ finishTo = Math.min(start - 1, i + 1);
+ parent = history.get(finishTo);
+ break;
+ } else if (r.info.packageName.equals(dest.getPackageName()) &&
+ r.info.name.equals(dest.getClassName())) {
+ finishTo = i;
+ parent = r;
+ foundParentInTask = true;
+ break;
+ }
+ }
+ }
+
+ if (mController != null) {
+ ActivityRecord next = mMainStack.topRunningActivityLocked(token, 0);
+ if (next != null) {
+ // ask watcher if this is allowed
+ boolean resumeOK = true;
+ try {
+ resumeOK = mController.activityResuming(next.packageName);
+ } catch (RemoteException e) {
+ mController = null;
+ }
+
+ if (!resumeOK) {
+ return false;
+ }
+ }
+ }
+ final long origId = Binder.clearCallingIdentity();
+ for (int i = start; i > finishTo; i--) {
+ ActivityRecord r = history.get(i);
+ mMainStack.requestFinishActivityLocked(r.appToken, resultCode, resultData,
+ "navigate-up", true);
+ // Only return the supplied result for the first activity finished
+ resultCode = Activity.RESULT_CANCELED;
+ resultData = null;
+ }
+
+ if (parent != null && foundParentInTask) {
+ final int parentLaunchMode = parent.info.launchMode;
+ final int destIntentFlags = destIntent.getFlags();
+ if (parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE ||
+ parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK ||
+ parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP ||
+ (destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
+ parent.deliverNewIntentLocked(srec.info.applicationInfo.uid, destIntent);
+ } else {
+ try {
+ ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
+ destIntent.getComponent(), 0, srec.userId);
+ int res = mMainStack.startActivityLocked(srec.app.thread, destIntent,
+ null, aInfo, parent.appToken, null,
+ 0, -1, parent.launchedFromUid, parent.launchedFromPackage,
+ 0, null, true, null);
+ foundParentInTask = res == ActivityManager.START_SUCCESS;
+ } catch (RemoteException e) {
+ foundParentInTask = false;
+ }
+ mMainStack.requestFinishActivityLocked(parent.appToken, resultCode,
+ resultData, "navigate-up", true);
+ }
+ }
+ Binder.restoreCallingIdentity(origId);
+ return foundParentInTask;
}
}
import android.app.Activity;
import android.app.ActivityOptions;
-import android.app.ResultInfo;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
ActivityRecord resultTo; // who started this entry, so will get our reply
final String resultWho; // additional identifier for use by resultTo.
final int requestCode; // code given by requester (resultTo)
- ArrayList<ResultInfo> results; // pending ActivityResult objs we have received
+ ArrayList results; // pending ActivityResult objs we have received
HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act
- ArrayList<Intent> newIntents; // any pending new intents for single-top mode
+ ArrayList newIntents; // any pending new intents for single-top mode
ActivityOptions pendingOptions; // most recently given options
HashSet<ConnectionRecord> connections; // All ConnectionRecord we hold
UriPermissionOwner uriPermissions; // current special URI access perms.
void setTask(TaskRecord newTask, ThumbnailHolder newThumbHolder, boolean isRoot) {
if (inHistory && !finishing) {
if (task != null) {
- // TODO: If this is the last ActivityRecord in task, remove from ActivityStack.
- task.removeActivity(this);
task.numActivities--;
}
if (newTask != null) {
inHistory = false;
if (task != null && !finishing) {
task.numActivities--;
- task = null;
}
clearOptionsLocked();
}
ActivityResult r = new ActivityResult(from, resultWho,
requestCode, resultCode, resultData);
if (results == null) {
- results = new ArrayList<ResultInfo>();
+ results = new ArrayList();
}
results.add(r);
}
StringBuilder sb = new StringBuilder(128);
sb.append("ActivityRecord{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
- sb.append(" t");
- sb.append(task.taskId);
sb.append(" u");
sb.append(userId);
sb.append(' ');
import com.android.internal.app.HeavyWeightSwitcherActivity;
import com.android.internal.os.BatteryStatsImpl;
-import com.android.server.am.ActivityManagerService.ItemMatcher;
import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
import com.android.server.wm.AppTransition;
-import com.android.server.wm.TaskGroup;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.AppGlobals;
-import android.app.IActivityController;
import android.app.IActivityManager;
-import android.app.IThumbnailReceiver;
import android.app.IThumbnailRetriever;
import android.app.IApplicationThread;
import android.app.PendingIntent;
import android.app.ResultInfo;
-import android.app.ActivityManager.RunningTaskInfo;
import android.app.IActivityManager.WaitResult;
import android.content.ComponentName;
import android.content.Context;
import android.graphics.Bitmap.Config;
import android.os.Binder;
import android.os.Bundle;
-import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
-import android.util.SparseArray;
import android.view.Display;
-import java.io.FileDescriptor;
import java.io.IOException;
-import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;
static final boolean DEBUG_APP = false;
static final boolean VALIDATE_TOKENS = ActivityManagerService.VALIDATE_TOKENS;
- static final boolean VALIDATE_TASK_REPLACE = true;
-
+
// How long we wait until giving up on the last activity telling us it
// is idle.
static final int IDLE_TIMEOUT = 10*1000;
// Set to false to disable the preview that is shown while a new activity
// is being started.
static final boolean SHOW_APP_STARTING_PREVIEW = true;
-
+
enum ActivityState {
INITIALIZING,
RESUMED,
final boolean mMainStack;
final Context mContext;
-
- /**
- * The back history of all previous (and possibly still
- * running) activities. It contains #ActivityRecord objects.
- */
- private final ArrayList<ActivityRecord> mHistory = new ArrayList<ActivityRecord>();
-
+
/**
* The back history of all previous (and possibly still
- * running) activities. It contains #TaskRecord objects.
+ * running) activities. It contains HistoryRecord objects.
*/
- private ArrayList<TaskRecord> mTaskHistory = new ArrayList<TaskRecord>();
-
- /**
- * Mapping from taskId to TaskRecord
- */
- private SparseArray<TaskRecord> mTaskIdToTaskRecord = new SparseArray<TaskRecord>();
+ final ArrayList<ActivityRecord> mHistory = new ArrayList<ActivityRecord>();
/**
* Used for validating app tokens with window manager.
*/
- final ArrayList<TaskGroup> mValidateAppTokens = new ArrayList<TaskGroup>();
+ final ArrayList<IBinder> mValidateAppTokens = new ArrayList<IBinder>();
/**
* List of running activities, sorted by recent usage.
private ActivityRecord mLastScreenshotActivity = null;
private Bitmap mLastScreenshotBitmap = null;
- /**
- * List of ActivityRecord objects that have been finished and must
- * still report back to a pending thumbnail receiver.
- */
- private final ArrayList<ActivityRecord> mCancelledThumbnails = new ArrayList<ActivityRecord>();
-
int mThumbnailWidth = -1;
int mThumbnailHeight = -1;
final Handler mHandler;
- String mLastHistoryModifier;
-
final class ActivityStackHandler extends Handler {
//public Handler() {
// if (localLOGV) Slog.v(TAG, "Handler started!");
}
final ActivityRecord topRunningActivityLocked(ActivityRecord notTop) {
- ActivityRecord newAr = newTopRunningActivityLocked(notTop);
-
int i = mHistory.size()-1;
while (i >= 0) {
ActivityRecord r = mHistory.get(i);
if (!r.finishing && r != notTop && okToShow(r)) {
- if (VALIDATE_TASK_REPLACE && newAr != r) logHistories(
- "topRunningActivityLocked", true);
return r;
}
i--;
}
- if (VALIDATE_TASK_REPLACE && newAr != null) Slog.w(TAG,
- "topRunningActivityLocked: mismatch: newAr!=null");
- return null;
- }
-
- final ActivityRecord newTopRunningActivityLocked(ActivityRecord notTop) {
- for (int i = mTaskHistory.size() - 1; i >= 0; --i) {
- final TaskRecord task = mTaskHistory.get(i);
- final ArrayList<ActivityRecord> activities = task.mActivities;
- for (int j = activities.size() - 1; j >= 0; --j) {
- ActivityRecord r = activities.get(j);
- if (!r.finishing && r != notTop && okToShow(r)) {
- return r;
- }
- }
- }
return null;
}
final ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
- ActivityRecord newAr = newTopRunningNonDelayedActivityLocked(notTop);
-
int i = mHistory.size()-1;
while (i >= 0) {
ActivityRecord r = mHistory.get(i);
if (!r.finishing && !r.delayedResume && r != notTop && okToShow(r)) {
- if (VALIDATE_TASK_REPLACE && newAr != r) Slog.w(TAG,
- "topRunningNonDelayedActivityLocked: mismatch: newAr=" + newAr + " r=" + r);
return r;
}
i--;
}
- if (VALIDATE_TASK_REPLACE && newAr != null) Slog.w(TAG,
- "topRunningNonDelayedActivityLocked: mismatch: newAr!=null");
- return null;
- }
-
- final ActivityRecord newTopRunningNonDelayedActivityLocked(ActivityRecord notTop) {
- for (int i = mTaskHistory.size() - 1; i >= 0; --i) {
- final TaskRecord task = mTaskHistory.get(i);
- final ArrayList<ActivityRecord> activities = task.mActivities;
- for (int j = activities.size() - 1; j >= 0; --j) {
- ActivityRecord r = activities.get(j);
- if (!r.finishing && !r.delayedResume && r != notTop && okToShow(r)) {
- return r;
- }
- }
- }
return null;
}
* @return Returns the HistoryRecord of the next activity on the stack.
*/
final ActivityRecord topRunningActivityLocked(IBinder token, int taskId) {
- ActivityRecord newAr = newTopRunningActivityLocked(token, taskId);
-
int i = mHistory.size()-1;
while (i >= 0) {
ActivityRecord r = mHistory.get(i);
// Note: the taskId check depends on real taskId fields being non-zero
if (!r.finishing && (token != r.appToken) && (taskId != r.task.taskId)
&& okToShow(r)) {
- if (VALIDATE_TASK_REPLACE && newAr != r) Slog.w(TAG,
- "topRunningActivityLocked(token): mismatch: newAr=" + newAr + " r=" + r);
return r;
}
i--;
}
- if (VALIDATE_TASK_REPLACE && newAr != null) Slog.w(TAG,
- "topRunningActivityLocked(token): mismatch: newAr!=null");
return null;
}
- final ActivityRecord newTopRunningActivityLocked(IBinder token, int taskId) {
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- TaskRecord task = mTaskHistory.get(taskNdx);
- if (task.taskId == taskId) {
- continue;
- }
- ArrayList<ActivityRecord> activities = task.mActivities;
- for (int i = activities.size() - 1; i >= 0; --i) {
- final ActivityRecord r = activities.get(i);
- // Note: the taskId check depends on real taskId fields being non-zero
- if (!r.finishing && (token != r.appToken) && okToShow(r)) {
- return r;
- }
- }
- }
- return null;
+ final int indexOfTokenLocked(IBinder token) {
+ return mHistory.indexOf(ActivityRecord.forToken(token));
}
- private final int indexOfTokenLocked(IBinder token) {
- return mHistory.indexOf(ActivityRecord.forToken(token));
+ final int indexOfActivityLocked(ActivityRecord r) {
+ return mHistory.indexOf(r);
}
final ActivityRecord isInStackLocked(IBinder token) {
- ActivityRecord newAr = newIsInStackLocked(token);
-
ActivityRecord r = ActivityRecord.forToken(token);
if (mHistory.contains(r)) {
- if (VALIDATE_TASK_REPLACE && newAr != r) Slog.w(TAG,
- "isInStackLocked: mismatch: newAr=" + newAr + " r=" + r);
return r;
}
- if (VALIDATE_TASK_REPLACE && newAr != null) Slog.w(TAG,
- "isInStackLocked: mismatch: newAr!=null");
return null;
}
- final ActivityRecord newIsInStackLocked(IBinder token) {
- final ActivityRecord r = ActivityRecord.forToken(token);
- if (r != null) {
- final TaskRecord task = r.task;
- if (mTaskHistory.contains(task) && task.mActivities.contains(r)) {
- return r;
- }
- }
- return null;
- }
-
- int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
- int newTaskId = newGetTaskForActivityLocked(token, onlyRoot);
-
- TaskRecord lastTask = null;
- final int N = mHistory.size();
- for (int i = 0; i < N; i++) {
- ActivityRecord r = mHistory.get(i);
- if (r.appToken == token) {
- if (!onlyRoot || lastTask != r.task) {
- if (VALIDATE_TASK_REPLACE && newTaskId != r.task.taskId) Slog.w(TAG,
- "getTaskForActivityLocked: mismatch: new=" + newTaskId
- + " taskId=" + r.task.taskId);
- return r.task.taskId;
- }
- if (VALIDATE_TASK_REPLACE && newTaskId != -1) Slog.w(TAG,
- "getTaskForActivityLocked: mismatch: newTaskId=" + newTaskId + " not -1.");
- return -1;
- }
- lastTask = r.task;
- }
-
- if (VALIDATE_TASK_REPLACE && newTaskId != -1) Slog.w(TAG,
- "getTaskForActivityLocked: mismatch at end: newTaskId=" + newTaskId + " not -1.");
- return -1;
- }
-
- int newGetTaskForActivityLocked(IBinder token, boolean onlyRoot) {
- final ActivityRecord r = ActivityRecord.forToken(token);
- if (r == null) {
- 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;
- }
- }
-
private final boolean updateLRUListLocked(ActivityRecord r) {
final boolean hadit = mLRUActivities.remove(r);
mLRUActivities.add(r);
* @return whether there are any activities for the specified user.
*/
final boolean switchUserLocked(int userId, UserStartedState uss) {
- if (VALIDATE_TOKENS) {
- validateAppTokensLocked();
- }
- final boolean newResult = newSwitchUserLocked(userId, uss);
-
mCurrentUser = userId;
mStartingUsers.add(uss);
// Only one activity? Nothing to do...
- if (mHistory.size() < 2) {
- if (VALIDATE_TASK_REPLACE && newResult) Slog.w(TAG,
- "switchUserLocked: mismatch: " + newResult + " " + false);
+ if (mHistory.size() < 2)
return false;
- }
boolean haveActivities = false;
// Check if the top activity is from the new user.
ActivityRecord top = mHistory.get(mHistory.size() - 1);
- if (top.userId == userId) {
- if (VALIDATE_TASK_REPLACE && !newResult) Slog.w(TAG,
- "switchUserLocked: mismatch: " + newResult + " " + true);
- return true;
- }
+ if (top.userId == userId) return true;
// Otherwise, move the user's activities to the top.
int N = mHistory.size();
int i = 0;
}
}
// Transition from the old top to the new top
- if (VALIDATE_TASK_REPLACE) Slog.w(TAG,
- "switchUserLocked: calling resumeTopActivity " + top);
resumeTopActivityLocked(top);
- if (VALIDATE_TASK_REPLACE && (newResult != haveActivities)) Slog.w(TAG,
- "switchUserLocked: mismatch: " + newResult + " " + haveActivities);
- return haveActivities;
- }
-
- /*
- * Move the activities around in the stack to bring a user to the foreground.
- * @return whether there are any activities for the specified user.
- */
- final boolean newSwitchUserLocked(int userId, UserStartedState uss) {
-// mStartingUsers.add(uss);
- if (mCurrentUser == userId) {
- return true;
- }
- mCurrentUser = userId;
-
- // Move userId's tasks to the top.
- boolean haveActivities = false;
- TaskRecord task = null;
- int index = mTaskHistory.size();
- for (int i = 0; i < index; ++i) {
- task = mTaskHistory.get(i);
- if (task.userId == userId) {
- haveActivities = true;
- mTaskHistory.remove(i);
- mTaskHistory.add(task);
- --index;
- }
- }
-
- // task is now the original topmost TaskRecord. Transition from the old top to the new top.
- ActivityRecord top = task != null ? task.getTopActivity() : null;
- if (VALIDATE_TASK_REPLACE) Slog.w(TAG,
- "newSwitchUserLocked: would call resumeTopActivity " + top);
-// resumeTopActivityLocked(top);
return haveActivities;
}
try {
profileFd = profileFd.dup();
} catch (IOException e) {
- if (profileFd != null) {
- try {
- profileFd.close();
- } catch (IOException o) {
- }
- profileFd = null;
- }
+ profileFd = null;
}
}
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
mGoingToSleep.release();
}
// Ensure activities are no longer sleeping.
- if (VALIDATE_TASK_REPLACE) {
- verifyActivityRecords(true);
- }
for (int i=mHistory.size()-1; i>=0; i--) {
ActivityRecord r = mHistory.get(i);
r.setSleeping(false);
// Make sure any stopped but visible activities are now sleeping.
// This ensures that the activity's onStop() is called.
- if (VALIDATE_TASK_REPLACE) {
- verifyActivityRecords(true);
- }
for (int i=mHistory.size()-1; i>=0; i--) {
ActivityRecord r = mHistory.get(i);
if (r.state == ActivityState.STOPPING || r.state == ActivityState.STOPPED) {
ActivityRecord r = null;
synchronized (mService) {
- if (VALIDATE_TASK_REPLACE) {
- verifyActivityRecords(true);
- }
int index = indexOfTokenLocked(token);
if (index >= 0) {
r = mHistory.get(index);
ActivityRecord r = null;
synchronized (mService) {
- if (VALIDATE_TASK_REPLACE) {
- verifyActivityRecords(true);
- }
int index = indexOfTokenLocked(token);
if (index >= 0) {
r = mHistory.get(index);
// If the top activity is not fullscreen, then we need to
// make sure any activities under it are now visible.
- if (VALIDATE_TASK_REPLACE) {
- verifyActivityRecords(true);
- }
final int count = mHistory.size();
int i = count-1;
while (mHistory.get(i) != top) {
try {
// Deliver all pending results.
- ArrayList<ResultInfo> a = next.results;
+ ArrayList a = next.results;
if (a != null) {
final int N = a.size();
if (!next.finishing && N > 0) {
return true;
}
- /** Temporary until startActivityLocked is rewritten for tasks. */
- private int convertAddPos(int addPos) {
- final int taskId = mHistory.get(addPos).task.taskId;
- addPos--;
- int taskOffset = 0;
- while (addPos >= 0 && taskId == mHistory.get(addPos).task.taskId) {
- ++taskOffset;
- --addPos;
- }
- return taskOffset;
- }
-
private final void startActivityLocked(ActivityRecord r, boolean newTask,
boolean doResume, boolean keepCurTransition, Bundle options) {
- mLastHistoryModifier = "startActivityLocked";
final int NH = mHistory.size();
int addPos = -1;
Slog.i(TAG, "Adding activity " + r + " to stack at " + addPos,
here);
}
- r.task.addActivityToTop(r);
mHistory.add(addPos, r);
r.putInHistory();
- mService.mWindowManager.addAppToken(convertAddPos(addPos), r.appToken,
- r.task.taskId, r.info.screenOrientation, r.fullscreen,
+ mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,
+ r.info.screenOrientation, r.fullscreen,
(r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
- verifyActivityRecords(true);
}
ActivityOptions.abort(options);
return;
here.fillInStackTrace();
Slog.i(TAG, "Adding activity " + r + " to stack at " + addPos, here);
}
- r.task.addActivityToTop(r);
mHistory.add(addPos, r);
r.putInHistory();
r.frontOfTask = newTask;
- if (VALIDATE_TASK_REPLACE) {
- if (verifyActivityRecords(false)) {
- Slog.w(TAG, "startActivityLocked: addPos=" + addPos);
- }
- }
if (NH > 0) {
// We want to show the starting preview window if we are
// switching to a new task, or the next activity's process is
mNoAnimActivities.remove(r);
}
r.updateOptionsLocked(options);
- mService.mWindowManager.addAppToken(convertAddPos(addPos),
- r.appToken, r.task.taskId, r.info.screenOrientation, r.fullscreen,
+ mService.mWindowManager.addAppToken(
+ addPos, r.appToken, r.task.taskId, r.info.screenOrientation, r.fullscreen,
(r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
boolean doShow = true;
if (newTask) {
} else {
// If this is the first activity, don't do any fancy animations,
// because there is nothing for it to animate on top of.
- mService.mWindowManager.addAppToken(convertAddPos(addPos), r.appToken, r.task.taskId,
+ mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,
r.info.screenOrientation, r.fullscreen,
(r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
ActivityOptions.abort(options);
if (doResume) {
resumeTopActivityLocked(null);
}
- if (VALIDATE_TASK_REPLACE) {
- if (verifyActivityRecords(true)) {
- Slog.w(TAG, "startActivityLocked: addPos=" + addPos);
- }
- }
}
final void validateAppTokensLocked() {
mValidateAppTokens.clear();
mValidateAppTokens.ensureCapacity(mHistory.size());
- int taskId = Integer.MIN_VALUE;
- TaskGroup task = null;
for (int i=0; i<mHistory.size(); i++) {
- final ActivityRecord r = mHistory.get(i);
- if (taskId != r.task.taskId) {
- taskId = r.task.taskId;
- task = new TaskGroup();
- task.taskId = taskId;
- mValidateAppTokens.add(task);
- }
- task.tokens.add(r.appToken);
+ mValidateAppTokens.add(mHistory.get(i).appToken);
}
mService.mWindowManager.validateAppTokens(mValidateAppTokens);
}
*/
private final ActivityRecord resetTaskIfNeededLocked(ActivityRecord taskTop,
ActivityRecord newActivity) {
- mLastHistoryModifier = "resetTaskIfNeededLocked";
-
boolean forceReset = (newActivity.info.flags
&ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
if (ACTIVITY_INACTIVE_RESET_TIME > 0
if (mService.mCurTask <= 0) {
mService.mCurTask = 1;
}
- target.setTask(createTaskRecord(mService.mCurTask, target.info, null,
- false), null, false);
+ target.setTask(new TaskRecord(mService.mCurTask, target.info, null),
+ null, false);
target.task.affinityIntent = target.intent;
if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
+ " out to new task " + target.task);
}
- mService.mWindowManager.setAppGroupId(target.appToken, target.task.taskId);
+ mService.mWindowManager.setAppGroupId(target.appToken, task.taskId);
if (replyChainEnd < 0) {
replyChainEnd = targetI;
}
int dstPos = 0;
ThumbnailHolder curThumbHolder = target.thumbHolder;
boolean gotOptions = !canMoveOptions;
- final int taskId = target.task.taskId;
for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
p = mHistory.get(srcPos);
if (p.finishing) {
}
mHistory.remove(srcPos);
mHistory.add(dstPos, p);
- mService.mWindowManager.setAppGroupId(p.appToken, taskId);
+ mService.mWindowManager.moveAppToken(dstPos, p.appToken);
+ mService.mWindowManager.setAppGroupId(p.appToken, p.task.taskId);
dstPos++;
+ if (VALIDATE_TOKENS) {
+ validateAppTokensLocked();
+ }
i++;
}
- rebuildTaskHistory();
- mService.mWindowManager.moveTaskToBottom(taskId);
- if (VALIDATE_TOKENS) {
- validateAppTokensLocked();
- }
if (taskTop == p) {
taskTop = below;
}
// like these are all in the reply chain.
replyChainEnd = targetI+1;
while (replyChainEnd < mHistory.size() &&
- (mHistory.get(replyChainEnd)).task == task) {
+ (mHistory.get(
+ replyChainEnd)).task == task) {
replyChainEnd++;
}
replyChainEnd--;
if (replyChainEnd < 0) {
replyChainEnd = targetI;
}
- final int taskId = task.taskId;
if (DEBUG_TASKS) Slog.v(TAG, "Reparenting task at index "
+ targetI + " to " + replyChainEnd);
for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
+ " from " + srcPos + " to " + lastReparentPos
+ " in to resetting task " + task);
- mService.mWindowManager.setAppGroupId(p.appToken, taskId);
- }
- rebuildTaskHistory();
- // TODO: This is wrong because it doesn't take lastReparentPos into account.
- mService.mWindowManager.moveTaskToTop(taskId);
- if (VALIDATE_TOKENS) {
- validateAppTokensLocked();
+ mService.mWindowManager.moveAppToken(lastReparentPos, p.appToken);
+ mService.mWindowManager.setAppGroupId(p.appToken, p.task.taskId);
+ if (VALIDATE_TOKENS) {
+ validateAppTokensLocked();
+ }
}
replyChainEnd = -1;
}
}
- if (VALIDATE_TASK_REPLACE) {
- verifyActivityRecords(true);
- }
return taskTop;
}
if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
&& (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
if (!ret.finishing) {
- int index = mHistory.indexOf(ret);
+ int index = indexOfTokenLocked(ret.appToken);
if (index >= 0) {
finishActivityLocked(ret, index, Activity.RESULT_CANCELED,
null, "clear", false);
*/
private final ActivityRecord moveActivityToFrontLocked(int where) {
ActivityRecord newTop = mHistory.remove(where);
- newMoveActivityToFrontLocked(newTop);
int top = mHistory.size();
ActivityRecord oldTop = mHistory.get(top-1);
if (DEBUG_ADD_REMOVE) {
+ top, here);
}
mHistory.add(top, newTop);
- if (VALIDATE_TASK_REPLACE) {
- verifyActivityRecords(true);
- }
- return newTop;
- }
-
- private final ActivityRecord newMoveActivityToFrontLocked(ActivityRecord newTop) {
- final TaskRecord task = newTop.task;
- ActivityRecord oldTop = task.getTopActivity();
- task.mActivities.remove(newTop);
- task.mActivities.add(newTop);
oldTop.frontOfTask = false;
newTop.frontOfTask = true;
return newTop;
String resultWho, int requestCode,
int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
boolean componentSpecified, ActivityRecord[] outActivity) {
- mLastHistoryModifier = "startActivityLocked(IApplicationThread)";
int err = ActivityManager.START_SUCCESS;
if (mService.mCurTask <= 0) {
mService.mCurTask = 1;
}
- r.setTask(createTaskRecord(mService.mCurTask, r.info, intent, true), null, true);
+ r.setTask(new TaskRecord(mService.mCurTask, r.info, intent), null, true);
if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
+ " in new task " + r.task);
} else {
N > 0 ? mHistory.get(N-1) : null;
r.setTask(prev != null
? prev.task
- : createTaskRecord(mService.mCurTask, r.info, intent, true), null, true);
+ : new TaskRecord(mService.mCurTask, r.info, intent), null, true);
if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
+ " in new guessed " + r.task);
}
}
// Get the activity record.
- int index = mHistory.indexOf(r);
+ int index = indexOfActivityLocked(r);
if (index >= 0) {
res = r;
finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
mFinishingActivities.clear();
}
- if ((NT=mCancelledThumbnails.size()) > 0) {
- thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
- mCancelledThumbnails.clear();
+ if ((NT=mService.mCancelledThumbnails.size()) > 0) {
+ thumbnails = new ArrayList<ActivityRecord>(mService.mCancelledThumbnails);
+ mService.mCancelledThumbnails.clear();
}
if (mMainStack) {
// Stop any activities that are scheduled to do so but have been
// waiting for the next one to start.
for (i=0; i<NS; i++) {
- ActivityRecord r = stops.get(i);
+ ActivityRecord r = (ActivityRecord)stops.get(i);
synchronized (mService) {
if (r.finishing) {
finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false);
// Finish any activities that are scheduled to do so but have been
// waiting for the next one to start.
for (i=0; i<NF; i++) {
- ActivityRecord r = finishes.get(i);
+ ActivityRecord r = (ActivityRecord)finishes.get(i);
synchronized (mService) {
activityRemoved = destroyActivityLocked(r, true, false, "finish-idle");
}
// Report back to any thumbnail receivers.
for (i=0; i<NT; i++) {
- ActivityRecord r = thumbnails.get(i);
+ ActivityRecord r = (ActivityRecord)thumbnails.get(i);
mService.sendPendingThumbnail(r, null, null, null, true);
}
int i;
for (i=mHistory.size()-1; i>=0; i--) {
- ActivityRecord r = mHistory.get(i);
+ ActivityRecord r = (ActivityRecord)mHistory.get(i);
if (r.resultTo == self && r.requestCode == requestCode) {
if ((r.resultWho == null && resultWho == null) ||
(r.resultWho != null && r.resultWho.equals(resultWho))) {
mService.updateOomAdjLocked();
}
- final void finishTopRunningActivityLocked(ProcessRecord app) {
- ActivityRecord r = topRunningActivityLocked(null);
- if (r != null && r.app == app) {
- // If the top running activity is from this crashing
- // process, then terminate it to avoid getting in a loop.
- Slog.w(TAG, " Force finishing activity "
- + r.intent.getComponent().flattenToShortString());
- int index = mHistory.indexOf(r);
- r.stack.finishActivityLocked(r, index,
- Activity.RESULT_CANCELED, null, "crashed", false);
- // Also terminate any activities below it that aren't yet
- // stopped, to avoid a situation where one will get
- // re-start our crashing activity once it gets resumed again.
- index--;
- if (index >= 0) {
- r = mHistory.get(index);
- if (r.state == ActivityState.RESUMED
- || r.state == ActivityState.PAUSING
- || r.state == ActivityState.PAUSED) {
- if (!r.isHomeActivity || mService.mHomeProcess != r.app) {
- Slog.w(TAG, " Force finishing activity "
- + r.intent.getComponent().flattenToShortString());
- r.stack.finishActivityLocked(r, index,
- Activity.RESULT_CANCELED, null, "crashed", false);
- }
- }
- }
- }
- }
-
final boolean finishActivityAffinityLocked(IBinder token) {
int index = indexOfTokenLocked(token);
if (DEBUG_RESULTS) Slog.v(
* @return Returns true if this activity has been removed from the history
* list, or false if it is still in the list and will be removed later.
*/
- final boolean finishActivityLocked(ActivityRecord r,
- int resultCode, Intent resultData, String reason, boolean oomAdj) {
- int index = mHistory.indexOf(r);
- if (index >= 0) {
- return finishActivityLocked(r, index, resultCode, resultData, reason, false, oomAdj);
- }
- return false;
- }
-
- /**
- * @return Returns true if this activity has been removed from the history
- * list, or false if it is still in the list and will be removed later.
- */
final boolean finishActivityLocked(ActivityRecord r, int index,
int resultCode, Intent resultData, String reason, boolean oomAdj) {
return finishActivityLocked(r, index, resultCode, resultData, reason, false, oomAdj);
// There are clients waiting to receive thumbnails so, in case
// this is an activity that someone is waiting for, add it
// to the pending list so we can correctly update the clients.
- mCancelledThumbnails.add(r);
+ mService.mCancelledThumbnails.add(r);
}
if (immediate) {
private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r,
int mode, boolean oomAdj) {
- final int index = mHistory.indexOf(r);
+ final int index = indexOfActivityLocked(r);
if (index < 0) {
return null;
}
resumeTopActivityLocked(null);
}
return activityRemoved ? null : r;
+ } else {
+ // Need to go through the full pause cycle to get this
+ // activity into the stopped state and then finish it.
+ if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
+ mFinishingActivities.add(r);
+ resumeTopActivityLocked(null);
}
-
- // Need to go through the full pause cycle to get this
- // activity into the stopped state and then finish it.
- if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
- mFinishingActivities.add(r);
- resumeTopActivityLocked(null);
return r;
}
- final boolean navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode,
- Intent resultData) {
- final int start = mHistory.indexOf(srec);
- if (start < 0) {
- // Current activity is not in history stack; do nothing.
- return false;
- }
- int finishTo = start - 1;
- ActivityRecord parent = null;
- boolean foundParentInTask = false;
- ComponentName dest = destIntent.getComponent();
- if (dest != null) {
- TaskRecord tr = srec.task;
- for (int i = start - 1; i >= 0; i--) {
- ActivityRecord r = mHistory.get(i);
- if (tr != r.task) {
- // Couldn't find parent in the same task; stop at the one above this.
- // (Root of current task; in-app "home" behavior)
- // Always at least finish the current activity.
- finishTo = Math.min(start - 1, i + 1);
- parent = mHistory.get(finishTo);
- break;
- } else if (r.info.packageName.equals(dest.getPackageName()) &&
- r.info.name.equals(dest.getClassName())) {
- finishTo = i;
- parent = r;
- foundParentInTask = true;
- break;
- }
- }
- }
-
- IActivityController controller = mService.mController;
- if (controller != null) {
- ActivityRecord next = topRunningActivityLocked(srec.appToken, 0);
- if (next != null) {
- // ask watcher if this is allowed
- boolean resumeOK = true;
- try {
- resumeOK = controller.activityResuming(next.packageName);
- } catch (RemoteException e) {
- mService.mController = null;
- }
-
- if (!resumeOK) {
- return false;
- }
- }
- }
- final long origId = Binder.clearCallingIdentity();
- for (int i = start; i > finishTo; i--) {
- ActivityRecord r = mHistory.get(i);
- requestFinishActivityLocked(r.appToken, resultCode, resultData,
- "navigate-up", true);
- // Only return the supplied result for the first activity finished
- resultCode = Activity.RESULT_CANCELED;
- resultData = null;
- }
-
- if (parent != null && foundParentInTask) {
- final int parentLaunchMode = parent.info.launchMode;
- final int destIntentFlags = destIntent.getFlags();
- if (parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE ||
- parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK ||
- parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP ||
- (destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
- parent.deliverNewIntentLocked(srec.info.applicationInfo.uid, destIntent);
- } else {
- try {
- ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
- destIntent.getComponent(), 0, srec.userId);
- int res = startActivityLocked(srec.app.thread, destIntent,
- null, aInfo, parent.appToken, null,
- 0, -1, parent.launchedFromUid, parent.launchedFromPackage,
- 0, null, true, null);
- foundParentInTask = res == ActivityManager.START_SUCCESS;
- } catch (RemoteException e) {
- foundParentInTask = false;
- }
- requestFinishActivityLocked(parent.appToken, resultCode,
- resultData, "navigate-up", true);
- }
- }
- Binder.restoreCallingIdentity(origId);
- return foundParentInTask;
- }
/**
* Perform the common clean-up of an activity record. This is called both
* as part of destroyActivityLocked() (when destroying the client-side
// There are clients waiting to receive thumbnails so, in case
// this is an activity that someone is waiting for, add it
// to the pending list so we can correctly update the clients.
- mCancelledThumbnails.add(r);
+ mService.mCancelledThumbnails.add(r);
}
// Get rid of any pending idle timeouts.
here.fillInStackTrace();
Slog.i(TAG, "Removing activity " + r + " from stack");
}
- final TaskRecord task = r.task;
- if (task != null) {
- task.removeActivity(r);
- }
mHistory.remove(r);
r.takeFromHistory();
removeTimeoutsForActivityLocked(r);
mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
}
- int index = mHistory.indexOf(r);
+ int index = indexOfActivityLocked(r);
if (index >= 0) {
if (r.state == ActivityState.DESTROYING) {
cleanUpActivityLocked(r, true, false);
}
}
- private void removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> list,
- ProcessRecord app, String listName) {
+ private void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app,
+ String listName) {
int i = list.size();
if (DEBUG_CLEANUP) Slog.v(
TAG, "Removing app " + app + " from list " + listName
+ " with " + i + " entries");
while (i > 0) {
i--;
- ActivityRecord r = list.get(i);
+ ActivityRecord r = (ActivityRecord)list.get(i);
if (DEBUG_CLEANUP) Slog.v(TAG, "Record #" + i + " " + r);
if (r.app == app) {
if (DEBUG_CLEANUP) Slog.v(TAG, "---> REMOVING this entry!");
TAG, "Removing app " + app + " from history with " + i + " entries");
while (i > 0) {
i--;
- ActivityRecord r = mHistory.get(i);
+ ActivityRecord r = (ActivityRecord)mHistory.get(i);
if (DEBUG_CLEANUP) Slog.v(
TAG, "Record #" + i + " " + r + ": app=" + r.app);
if (r.app == app) {
* of the stack.
*/
final void moveHomeToFrontLocked() {
- newMoveHomeToFrontLocked();
TaskRecord homeTask = null;
for (int i=mHistory.size()-1; i>=0; i--) {
ActivityRecord hr = mHistory.get(i);
}
}
if (homeTask != null) {
-// moveTaskToFrontLocked(homeTask, null, null);
- }
- }
-
- final void newMoveHomeToFrontLocked() {
- TaskRecord homeTask = null;
- for (int taskNdx = mTaskHistory.size() - 1; homeTask == null && taskNdx >= 0; --taskNdx) {
- final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
- for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
- final ActivityRecord r = activities.get(activityNdx);
- if (r.isHomeActivity) {
- homeTask = r.task;
- break;
- }
- }
- }
- if (homeTask != null) {
moveTaskToFrontLocked(homeTask, null, null);
}
}
mService.mWindowManager.prepareAppTransition(transit, false);
}
- final boolean findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
- for (int i = mHistory.size() - 1; i >= 0; i--) {
- ActivityRecord hr = mHistory.get(i);
- if (hr.task.taskId == taskId) {
- if ((flags & ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
- mUserLeaving = true;
- }
- if ((flags & ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
- // Caller wants the home activity moved with it. To accomplish this,
- // we'll just move the home task to the top first.
- moveHomeToFrontLocked();
- }
- moveTaskToFrontLocked(hr.task, null, options);
- return true;
- }
- }
- return false;
- }
-
final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason, Bundle options) {
+ if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
final int task = tr.taskId;
int top = mHistory.size()-1;
if (top < 0 || (mHistory.get(top)).task.taskId == task) {
// nothing to do!
+ if (reason != null &&
+ (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
+ ActivityOptions.abort(options);
+ } else {
+ updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
+ }
return;
}
+ ArrayList<IBinder> moved = new ArrayList<IBinder>();
+
+ // Applying the affinities may have removed entries from the history,
+ // so get the size again.
+ top = mHistory.size()-1;
+ int pos = top;
// Shift all activities with this task up to the top
// of the stack, keeping them in the same internal order.
- int pos = top;
while (pos >= 0) {
ActivityRecord r = mHistory.get(pos);
if (localLOGV) Slog.v(
}
mHistory.remove(pos);
mHistory.add(top, r);
+ moved.add(0, r.appToken);
top--;
}
pos--;
}
- //
- // Start new code here! Delete everything above.
- //
- if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
-
- final int numTasks = mTaskHistory.size();
- final int index = mTaskHistory.indexOf(tr);
- if (numTasks == 0 || index < 0 || index == numTasks - 1) {
- // nothing to do!
- if (reason != null &&
- (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
- ActivityOptions.abort(options);
- } else {
- updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
- }
- return;
- }
-
- // Shift all activities with this task up to the top
- // of the stack, keeping them in the same internal order.
- mTaskHistory.remove(tr);
- mTaskHistory.add(tr);
- if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare to front transition: task=" + tr);
+ if (DEBUG_TRANSITION) Slog.v(TAG,
+ "Prepare to front transition: task=" + tr);
if (reason != null &&
(reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
- mService.mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
+ mService.mWindowManager.prepareAppTransition(
+ AppTransition.TRANSIT_NONE, false);
ActivityRecord r = topRunningActivityLocked(null);
if (r != null) {
mNoAnimActivities.add(r);
} else {
updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
}
-
- mService.mWindowManager.moveTaskToTop(task);
-
- finishTaskMoveLocked(task);
- EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, task);
-
+
+ mService.mWindowManager.moveAppTokensToTop(moved);
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
}
- if (VALIDATE_TASK_REPLACE) {
- verifyActivityRecords(true);
- }
+
+ finishTaskMoveLocked(task);
+ EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, task);
}
private final void finishTaskMoveLocked(int task) {
*/
final boolean moveTaskToBackLocked(int task, ActivityRecord reason) {
Slog.i(TAG, "moveTaskToBack: " + task);
-
+
// 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.
}
}
+ ArrayList<IBinder> moved = new ArrayList<IBinder>();
+
if (DEBUG_TRANSITION) Slog.v(TAG,
"Prepare to back transition: task=" + task);
-
- final TaskRecord tr = mTaskIdToTaskRecord.get(task);
- mTaskHistory.remove(tr);
- mTaskHistory.add(0, tr);
-
- // BEGIN REGION TO REMOVE.
+
final int N = mHistory.size();
int bottom = 0;
int pos = 0;
}
mHistory.remove(pos);
mHistory.add(bottom, r);
+ moved.add(r.appToken);
bottom++;
}
pos++;
}
- if (VALIDATE_TASK_REPLACE) {
- verifyActivityRecords(true);
- }
- // END REGION TO REMOVE
if (reason != null &&
(reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
- mService.mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
+ mService.mWindowManager.prepareAppTransition(
+ AppTransition.TRANSIT_NONE, false);
ActivityRecord r = topRunningActivityLocked(null);
if (r != null) {
mNoAnimActivities.add(r);
mService.mWindowManager.prepareAppTransition(
AppTransition.TRANSIT_TASK_TO_BACK, false);
}
- mService.mWindowManager.moveTaskToBottom(task);
-
+ mService.mWindowManager.moveAppTokensToBottom(moved);
if (VALIDATE_TOKENS) {
validateAppTokensLocked();
}
TaskAccessInfo info = getTaskAccessInfoLocked(tr.taskId, true);
if (info.numSubThumbbails <= 0) {
return info.mainThumbnail != null ? info.mainThumbnail : tr.lastThumbnail;
+ } else {
+ return info.subtasks.get(info.numSubThumbbails-1).holder.lastThumbnail;
}
- return info.subtasks.get(info.numSubThumbbails-1).holder.lastThumbnail;
}
public ActivityRecord removeTaskActivitiesLocked(int taskId, int subTaskIndex,
}
if (thumbs.numSubThumbbails > 0) {
thumbs.retriever = new IThumbnailRetriever.Stub() {
- @Override
public Bitmap getThumbnail(int index) {
if (index < 0 || index >= thumbs.subtasks.size()) {
return null;
public void dismissKeyguardOnNextActivityLocked() {
mDismissKeyguardOnNextActivity = true;
}
-
- boolean willActivityBeVisibleLocked(IBinder token) {
- int i;
- for (i = mHistory.size() - 1; i >= 0; i--) {
- ActivityRecord r = mHistory.get(i);
- if (r.appToken == token) {
- return true;
- }
- if (r.fullscreen && !r.finishing) {
- return false;
- }
- }
- return true;
- }
-
- void closeSystemDialogsLocked() {
- for (int i = mHistory.size() - 1; i >= 0; i--) {
- ActivityRecord r = mHistory.get(i);
- if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
- r.stack.finishActivityLocked(r, i,
- Activity.RESULT_CANCELED, null, "close-sys", true);
- }
- }
- }
-
- boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
- boolean didSomething = false;
- TaskRecord lastTask = null;
- final int N = mHistory.size();
- for (int i = 0; i < N; i++) {
- ActivityRecord r = mHistory.get(i);
- final boolean samePackage = r.packageName.equals(name)
- || (name == null && r.userId == userId);
- if ((userId == UserHandle.USER_ALL || r.userId == userId)
- && (samePackage || r.task == lastTask)
- && (r.app == null || evenPersistent || !r.app.persistent)) {
- if (!doit) {
- if (r.finishing) {
- // If this activity is just finishing, then it is not
- // interesting as far as something to stop.
- continue;
- }
- return true;
- }
- didSomething = true;
- Slog.i(TAG, " Force finishing activity " + r);
- if (samePackage) {
- if (r.app != null) {
- r.app.removed = true;
- }
- r.app = null;
- }
- lastTask = r.task;
- if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
- null, "force-stop", true)) {
- i--;
- }
- }
- }
- return didSomething;
- }
-
- ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
- PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
- ActivityRecord topRecord = null;
- int pos = mHistory.size() - 1;
- ActivityRecord next = pos >= 0 ? mHistory.get(pos) : null;
- ActivityRecord top = null;
- TaskRecord curTask = null;
- int numActivities = 0;
- int numRunning = 0;
- while (pos >= 0 && maxNum > 0) {
- final ActivityRecord r = next;
- pos--;
- next = pos >= 0 ? mHistory.get(pos) : null;
-
- // Initialize state for next task if needed.
- if (top == null || (top.state == ActivityState.INITIALIZING && top.task == r.task)) {
- top = r;
- curTask = r.task;
- numActivities = numRunning = 0;
- }
-
- // Add 'r' into the current task.
- numActivities++;
- if (r.app != null && r.app.thread != null) {
- numRunning++;
- }
-
- if (localLOGV) Slog.v(
- TAG, r.intent.getComponent().flattenToShortString()
- + ": task=" + r.task);
-
- // If the next one is a different task, generate a new
- // TaskInfo entry for what we have.
- if (next == null || next.task != curTask) {
- RunningTaskInfo ci = new RunningTaskInfo();
- ci.id = curTask.taskId;
- ci.baseActivity = r.intent.getComponent();
- ci.topActivity = top.intent.getComponent();
- if (top.thumbHolder != null) {
- ci.description = top.thumbHolder.lastDescription;
- }
- ci.numActivities = numActivities;
- ci.numRunning = numRunning;
- //System.out.println(
- // "#" + maxNum + ": " + " descr=" + ci.description);
- if (receiver != null) {
- if (localLOGV) Slog.v(
- TAG, "State=" + top.state + "Idle=" + top.idle
- + " app=" + top.app
- + " thr=" + (top.app != null ? top.app.thread : null));
- if (top.state == ActivityState.RESUMED || top.state == ActivityState.PAUSING) {
- if (top.idle && top.app != null && top.app.thread != null) {
- topRecord = top;
- } else {
- top.thumbnailNeeded = true;
- }
- }
- pending.pendingRecords.add(top);
- }
- list.add(ci);
- maxNum--;
- top = null;
- }
- }
- return topRecord;
- }
-
- public void unhandledBackLocked() {
- int top = mHistory.size() - 1;
- if (DEBUG_SWITCH) Slog.d(
- TAG, "Performing unhandledBack(): top activity at " + top);
- if (top > 0) {
- finishActivityLocked(mHistory.get(top),
- top, Activity.RESULT_CANCELED, null, "unhandled-back", true);
- }
- }
-
- void handleAppCrashLocked(ProcessRecord app) {
- for (int i = mHistory.size() - 1; i >= 0; i--) {
- ActivityRecord r = mHistory.get(i);
- if (r.app == app) {
- Slog.w(TAG, " Force finishing activity "
- + r.intent.getComponent().flattenToShortString());
- r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
- null, "crashed", false);
- }
- }
- }
-
- void dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
- boolean dumpClient, String dumpPackage) {
- ActivityManagerService.dumpHistoryList(fd, pw, mHistory, " ", "Hist", true, !dumpAll,
- dumpClient, dumpPackage);
- }
-
- ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
- ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
-
- if ("all".equals(name)) {
- for (ActivityRecord r1 : mHistory) {
- activities.add(r1);
- }
- } else if ("top".equals(name)) {
- final int N = mHistory.size();
- if (N > 0) {
- activities.add(mHistory.get(N-1));
- }
- } else {
- ItemMatcher matcher = new ItemMatcher();
- matcher.build(name);
-
- for (ActivityRecord r1 : mHistory) {
- if (matcher.match(r1, r1.intent.getComponent())) {
- activities.add(r1);
- }
- }
- }
-
- return activities;
- }
-
- ActivityRecord restartPackage(String packageName) {
- ActivityRecord starting = topRunningActivityLocked(null);
-
- // All activities that came from the package must be
- // restarted as if there was a config change.
- for (int i = mHistory.size() - 1; i >= 0; i--) {
- ActivityRecord a = mHistory.get(i);
- if (a.info.packageName.equals(packageName)) {
- a.forceNewConfig = true;
- if (starting != null && a == starting && a.visible) {
- a.startFreezingScreenLocked(starting.app, ActivityInfo.CONFIG_SCREEN_LAYOUT);
- }
- }
- }
-
- return starting;
- }
-
- void rebuildTaskHistory() {
- mTaskHistory.clear();
- final int numActivities = mHistory.size();
- TaskRecord task = null;
- for (int i = 0; i < numActivities; ++i) {
- final ActivityRecord r = mHistory.get(i);
- if (r.task != task) {
- task = r.task;
- task.mActivities.clear();
- mTaskHistory.add(task);
- }
- task.mActivities.add(r);
- }
- }
-
- boolean verifyActivityRecords(boolean rebuild) {
- final int numHistory = mHistory.size();
- int historyNdx = 0;
-
- final int numTasks = mTaskHistory.size();
- int taskNdx;
- for (taskNdx = historyNdx = 0; taskNdx < numTasks; ++taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
- final ArrayList<ActivityRecord> activities = task.mActivities;
- final int numActivities = activities.size();
- int activityNdx;
- for (activityNdx = 0;
- activityNdx < numActivities && historyNdx < numHistory;
- ++activityNdx, ++historyNdx) {
- ActivityRecord r1 = mHistory.get(historyNdx);
- ActivityRecord r2 = activities.get(activityNdx);
- if (r1 != r2) {
- break;
- }
- }
- if (activityNdx != numActivities) {
- // either a mismatch or mHistory ran out before mTaskHistory.
- break;
- }
- }
- if (taskNdx != numTasks || historyNdx != numHistory) {
- logHistories("verifyActivityRecords", rebuild);
- return true;
- }
- return false;
- }
-
- private void logHistories(String caller, boolean rebuild) {
- Slog.w(TAG, "Mismatch! " + caller + " mHistory=" + mHistory);
- ArrayList<ArrayList<ActivityRecord>> nestedRecords =
- new ArrayList<ArrayList<ActivityRecord>>();
- for (TaskRecord task : mTaskHistory) {
- nestedRecords.add(task.mActivities);
- }
- Slog.w(TAG, "Mismatch! " + caller + " mTaskHistory" + nestedRecords);
- Slog.w(TAG, "Mismatch! " + caller + " lastHistoryModifier=" + mLastHistoryModifier
- + " Caller=" + Debug.getCallers(4));
- if (rebuild) {
- rebuildTaskHistory();
- }
- }
-
- private TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
- boolean toTop) {
- TaskRecord oldTask = mTaskIdToTaskRecord.get(taskId);
- if (oldTask != null) {
- Slog.w(TAG, "createTaskRecord: Reusing taskId=" + taskId + " without removing");
- mTaskHistory.remove(oldTask);
- }
- TaskRecord task = new TaskRecord(taskId, info, intent);
- mTaskIdToTaskRecord.put(taskId, task);
- if (toTop) {
- mTaskHistory.add(task);
- } else {
- mTaskHistory.add(0, task);
- }
- return task;
- }
}
Message msg = mHandler.obtainMessage(MSG_WRITE);
mHandler.sendMessageDelayed(msg, 10000);
-
- ActivityRecord starting = mService.mMainStack.restartPackage(packageName);
+ ActivityRecord starting = mService.mMainStack.topRunningActivityLocked(null);
+
+ // All activities that came from the package must be
+ // restarted as if there was a config change.
+ for (int i=mService.mMainStack.mHistory.size()-1; i>=0; i--) {
+ ActivityRecord a = (ActivityRecord)mService.mMainStack.mHistory.get(i);
+ if (a.info.packageName.equals(packageName)) {
+ a.forceNewConfig = true;
+ if (starting != null && a == starting && a.visible) {
+ a.startFreezingScreenLocked(starting.app,
+ ActivityInfo.CONFIG_SCREEN_LAYOUT);
+ }
+ }
+ }
// Tell all processes that loaded this package about the change.
for (int i=mService.mLruProcesses.size()-1; i>=0; i--) {
class PendingThumbnailsRecord
{
final IThumbnailReceiver receiver; // who is waiting.
- final HashSet<ActivityRecord> pendingRecords; // HistoryRecord objects we still wait for.
+ HashSet pendingRecords; // HistoryRecord objects we still wait for.
boolean finished; // Is pendingRecords empty?
PendingThumbnailsRecord(IThumbnailReceiver _receiver)
{
receiver = _receiver;
- pendingRecords = new HashSet<ActivityRecord>();
+ pendingRecords = new HashSet();
finished = false;
}
}
import android.util.Slog;
import java.io.PrintWriter;
-import java.util.ArrayList;
class TaskRecord extends ThumbnailHolder {
final int taskId; // Unique identifier for this task.
String stringName; // caching of toString() result.
int userId; // user for which this task was created
-
- int numFullscreen; // Number of fullscreen activities.
-
- final ArrayList<ActivityRecord> mActivities = new ArrayList<ActivityRecord>();
-
+
TaskRecord(int _taskId, ActivityInfo info, Intent _intent) {
taskId = _taskId;
affinity = info.taskAffinity;
userId = UserHandle.getUserId(info.applicationInfo.uid);
}
}
-
- ActivityRecord getTopActivity() {
- for (int i = mActivities.size() - 1; i >= 0; --i) {
- final ActivityRecord r = mActivities.get(i);
- if (r.finishing) {
- continue;
- }
- return r;
- }
- return null;
- }
-
- void addActivityAtBottom(ActivityRecord r) {
- if (!mActivities.remove(r) && r.fullscreen) {
- // Was not previously in list.
- numFullscreen++;
- }
- mActivities.add(0, r);
- }
-
- void addActivityToTop(ActivityRecord r) {
- if (!mActivities.remove(r) && r.fullscreen) {
- // Was not previously in list.
- numFullscreen++;
- }
- // TODO: This only matters to achieve identical results as mHistory. Later we won't need
- // to skip over finishing activities.
- int i;
- for (i = mActivities.size() - 1; i >= 0; --i) {
- if (!mActivities.get(i).finishing) {
- break;
- }
- }
- if (i >= 0) {
- // Add below finishing activities.
- mActivities.add(i + 1, r);
- } else {
- // All activities are finishing, add to top.
- mActivities.add(r);
- }
- }
-
- /** @return true if this was the last activity in the task */
- boolean removeActivity(ActivityRecord r) {
- if (mActivities.remove(r) && r.fullscreen) {
- // Was previously in list.
- numFullscreen--;
- }
- return mActivities.size() == 0;
- }
-
+
void dump(PrintWriter pw, String prefix) {
if (numActivities != 0 || rootWasReset || userId != 0) {
pw.print(prefix); pw.print("numActivities="); pw.print(numActivities);
pw.print(" rootWasReset="); pw.print(rootWasReset);
- pw.print(" userId="); pw.print(userId);
- pw.print(" numFullscreen="); pw.println(numFullscreen);
+ pw.print(" userId="); pw.println(userId);
}
if (affinity != null) {
pw.print(prefix); pw.print("affinity="); pw.println(affinity);
pw.print(prefix); pw.print("realActivity=");
pw.println(realActivity.flattenToShortString());
}
- pw.print(prefix); pw.print("Activities="); pw.println(mActivities);
if (!askedCompatMode) {
pw.print(prefix); pw.print("askedCompatMode="); pw.println(askedCompatMode);
}
pw.print((getInactiveDuration()/1000)); pw.println("s)");
}
- @Override
public String toString() {
if (stringName != null) {
return stringName;
sb.append(" #");
sb.append(taskId);
if (affinity != null) {
- sb.append(" A=");
+ sb.append(" A ");
sb.append(affinity);
} else if (intent != null) {
- sb.append(" I=");
+ sb.append(" I ");
sb.append(intent.getComponent().flattenToShortString());
} else if (affinityIntent != null) {
- sb.append(" aI=");
+ sb.append(" aI ");
sb.append(affinityIntent.getComponent().flattenToShortString());
} else {
sb.append(" ??");
}
- sb.append(" U=");
+ sb.append(" U ");
sb.append(userId);
- sb.append(" sz=");
- sb.append(mActivities.size());
sb.append('}');
return stringName = sb.toString();
}
import android.view.WindowManager;
import java.io.PrintWriter;
-import java.util.ArrayList;
-
-class AppTokenList extends ArrayList<AppWindowToken> {
-}
/**
* Version of WindowToken that is specifically for a particular application (or
package com.android.server.wm;
-import static com.android.server.wm.WindowManagerService.FORWARD_ITERATOR;
-import static com.android.server.wm.WindowManagerService.REVERSE_ITERATOR;
-
-import android.util.SparseArray;
import android.view.Display;
import android.view.DisplayInfo;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
class DisplayContentList extends ArrayList<DisplayContent> {
}
* WindowManagerService.mWindowMap.
*/
class DisplayContent {
-// private final static String TAG = "DisplayContent";
/** Unique identifier of this stack. */
private final int mDisplayId;
final boolean isDefaultDisplay;
/**
- * Window tokens that are in the process of exiting, but still
- * on screen for animations.
- */
- final ArrayList<WindowToken> mExitingTokens = new ArrayList<WindowToken>();
-
- /**
- * Application tokens that are in the process of exiting, but still
- * on screen for animations.
- */
- final AppTokenList mExitingAppTokens = new AppTokenList();
-
- /**
- * Sorted most recent at top, oldest at [0].
- */
- ArrayList<TaskList> mTaskLists = new ArrayList<TaskList>();
- SparseArray<TaskList> mTaskIdToTaskList = new SparseArray<TaskList>();
-
- private final AppTokenIterator mTmpAppIterator = new AppTokenIterator();
-
- /**
* @param display May not be null.
*/
DisplayContent(Display display) {
mDisplay.getDisplayInfo(mDisplayInfo);
}
- /**
- * Find the location to insert a new AppWindowToken into the window-ordered app token list.
- * @param addPos The location the token was inserted into in mAppTokens.
- * @param wtoken The token to insert.
- */
- void addAppToken(final int addPos, final AppWindowToken wtoken) {
- TaskList task = mTaskIdToTaskList.get(wtoken.groupId);
- if (task == null) {
- task = new TaskList(wtoken, this);
- mTaskIdToTaskList.put(wtoken.groupId, task);
- mTaskLists.add(task);
- } else {
- task.mAppTokens.add(addPos, wtoken);
- }
- }
-
- void removeAppToken(final AppWindowToken wtoken) {
- final int taskId = wtoken.groupId;
- final TaskList task = mTaskIdToTaskList.get(taskId);
- if (task != null) {
- AppTokenList appTokens = task.mAppTokens;
- appTokens.remove(wtoken);
- if (appTokens.size() == 0) {
- mTaskLists.remove(task);
- mTaskIdToTaskList.delete(taskId);
- }
- }
- }
-
- void setAppTaskId(AppWindowToken wtoken, int newTaskId) {
- final int taskId = wtoken.groupId;
- TaskList task = mTaskIdToTaskList.get(taskId);
- if (task != null) {
- AppTokenList appTokens = task.mAppTokens;
- appTokens.remove(wtoken);
- if (appTokens.size() == 0) {
- mTaskIdToTaskList.delete(taskId);
- }
- }
-
- task = mTaskIdToTaskList.get(newTaskId);
- if (task == null) {
- task = new TaskList(wtoken, this);
- mTaskIdToTaskList.put(newTaskId, task);
- } else {
- task.mAppTokens.add(wtoken);
- }
-
- wtoken.groupId = newTaskId;
- }
-
- /**
- * Return the utility iterator so we don't have to construct new iterators every time we
- * iterate.
- * NOTE: Do not ever nest this call or you will have a bad time!
- * @param reverse Direction of iterator.
- * @return The utility iterator.
- */
- AppTokenIterator getTmpAppIterator(boolean reverse) {
- mTmpAppIterator.reset(reverse);
- return mTmpAppIterator;
- }
-
- class AppTokenIterator implements Iterator<AppWindowToken> {
- boolean mReverse;
- int mTasksNdx;
- int mActivityNdx;
- TaskList mTaskList;
-
- public AppTokenIterator() {
- this(FORWARD_ITERATOR);
- }
-
- public AppTokenIterator(boolean reverse) {
- reset(reverse);
- }
-
- void reset(boolean reverse) {
- mReverse = reverse;
- mTasksNdx = reverse ? mTaskLists.size() - 1 : 0;
- getNextTaskList();
- }
-
- private void getNextTaskList() {
- if (mReverse) {
- if (mTasksNdx >= 0) {
- mTaskList = mTaskLists.get(mTasksNdx);
- --mTasksNdx;
- mActivityNdx = mTaskList.mAppTokens.size() - 1;
- }
- } else {
- if (mTasksNdx < mTaskLists.size()) {
- mTaskList = mTaskLists.get(mTasksNdx);
- ++mTasksNdx;
- mActivityNdx = 0;
- }
- }
- }
-
- @Override
- public boolean hasNext() {
- if (mTaskList == null) {
- return false;
- }
- if (mReverse) {
- return mActivityNdx >= 0;
- }
- return mActivityNdx < mTaskList.mAppTokens.size();
- }
-
- @Override
- public AppWindowToken next() {
- if (hasNext()) {
- AppWindowToken wtoken = mTaskList.mAppTokens.get(mActivityNdx);
- mActivityNdx += mReverse ? -1 : 1;
- if (!hasNext()) {
- getNextTaskList();
- }
- return wtoken;
- }
- throw new NoSuchElementException();
- }
-
- @Override
- public void remove() {
- throw new IllegalArgumentException();
- }
-
- int size() {
- int size = 0;
- for (int i = mTaskLists.size() - 1; i >= 0; --i) {
- size += mTaskLists.get(i).mAppTokens.size();
- }
- return size;
- }
-
- @Override public String toString() {
- return mTaskLists.toString();
- }
- }
-
public void dump(String prefix, PrintWriter pw) {
pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
final String subPrefix = " " + prefix;
pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight);
pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
- pw.print(subPrefix); pw.print("layoutNeeded="); pw.println(layoutNeeded);
- AppTokenIterator iterator = getTmpAppIterator(REVERSE_ITERATOR);
- int ndx = iterator.size() - 1;
- if (ndx >= 0) {
- pw.println();
- pw.println(" Application tokens in Z order:");
- while (iterator.hasNext()) {
- AppWindowToken wtoken = iterator.next();
- pw.print(" App #"); pw.print(ndx--);
- pw.print(' '); pw.print(wtoken); pw.println(":");
- wtoken.dump(pw, " ");
- }
- }
- if (mExitingTokens.size() > 0) {
- pw.println();
- pw.println(" Exiting tokens:");
- for (int i=mExitingTokens.size()-1; i>=0; i--) {
- WindowToken token = mExitingTokens.get(i);
- pw.print(" Exiting #"); pw.print(i);
- pw.print(' '); pw.print(token);
- pw.println(':');
- token.dump(pw, " ");
- }
- }
- if (mExitingAppTokens.size() > 0) {
- pw.println();
- pw.println(" Exiting application tokens:");
- for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
- WindowToken token = mExitingAppTokens.get(i);
- pw.print(" Exiting App #"); pw.print(i);
- pw.print(' '); pw.print(token);
- pw.println(':');
- token.dump(pw, " ");
- }
- }
- if (mTaskIdToTaskList.size() > 0) {
- pw.println();
- for (int i = 0; i < mTaskIdToTaskList.size(); ++i) {
- pw.print(" TaskList #"); pw.print(i);
- pw.print(" taskId="); pw.println(mTaskIdToTaskList.keyAt(i));
- pw.print(" mAppTokens=");
- pw.println(mTaskIdToTaskList.valueAt(i).mAppTokens);
- pw.println();
- }
- }
+ pw.print(subPrefix); pw.print("layoutNeeded="); pw.print(layoutNeeded);
pw.println();
}
}
+++ /dev/null
-/*
- * Copyright (C) 2013 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.wm;
-
-import android.view.IApplicationToken;
-
-import java.util.ArrayList;
-
-public class TaskGroup {
- public int taskId = -1;
- public ArrayList<IApplicationToken> tokens = new ArrayList<IApplicationToken>();
-
- @Override
- public String toString() {
- return "id=" + taskId + " tokens=" + tokens;
- }
-}
+++ /dev/null
-/*
- * Copyright (C) 2013 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.wm;
-
-class TaskList {
-// private final String TAG = "TaskGroup";
- DisplayContent mDisplayContent;
- final AppTokenList mAppTokens = new AppTokenList();
- final int taskId;
-
- TaskList(AppWindowToken wtoken, DisplayContent displayContent) {
- taskId = wtoken.groupId;
- mAppTokens.add(wtoken);
- mDisplayContent = displayContent;
- }
-
- @Override
- public String toString() {
- return "id=" + taskId + " appTokens=" + mAppTokens;
- }
-}
import static com.android.server.wm.WindowManagerService.LayoutFields.SET_FORCE_HIDING_CHANGED;
import static com.android.server.wm.WindowManagerService.LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE;
import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_ACTION_PENDING;
-import static com.android.server.wm.WindowManagerService.FORWARD_ITERATOR;
-import static com.android.server.wm.WindowManagerService.REVERSE_ITERATOR;
import android.content.Context;
import android.os.Debug;
import android.view.WindowManagerPolicy;
import android.view.animation.Animation;
-import com.android.server.wm.DisplayContent.AppTokenIterator;
import com.android.server.wm.WindowManagerService.DisplayContentsIterator;
import com.android.server.wm.WindowManagerService.LayoutFields;
}
}
- private void updateAppWindowsLocked(int displayId) {
+ private void updateAppWindowsLocked() {
int i;
- final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
- AppTokenIterator iterator = displayContent.getTmpAppIterator(FORWARD_ITERATOR);
- while (iterator.hasNext()) {
- final AppWindowAnimator appAnimator = iterator.next().mAppAnimator;
+ final ArrayList<AppWindowToken> appTokens = mService.mAnimatingAppTokens;
+ final int NAT = appTokens.size();
+ for (i=0; i<NAT; i++) {
+ final AppWindowAnimator appAnimator = appTokens.get(i).mAppAnimator;
final boolean wasAnimating = appAnimator.animation != null
&& appAnimator.animation != AppWindowAnimator.sDummyAnimation;
if (appAnimator.stepAnimationLocked(mCurrentTime)) {
}
}
- final AppTokenList exitingAppTokens = displayContent.mExitingAppTokens;
- final int NEAT = exitingAppTokens.size();
+ final int NEAT = mService.mExitingAppTokens.size();
for (i=0; i<NEAT; i++) {
- final AppWindowAnimator appAnimator = exitingAppTokens.get(i).mAppAnimator;
+ final AppWindowAnimator appAnimator = mService.mExitingAppTokens.get(i).mAppAnimator;
final boolean wasAnimating = appAnimator.animation != null
&& appAnimator.animation != AppWindowAnimator.sDummyAnimation;
if (appAnimator.stepAnimationLocked(mCurrentTime)) {
/** See if any windows have been drawn, so they (and others associated with them) can now be
* shown. */
- private void testTokenMayBeDrawnLocked(int displayId) {
+ private void testTokenMayBeDrawnLocked() {
// See if any windows have been drawn, so they (and others
// associated with them) can now be shown.
- AppTokenIterator iterator =
- mService.getDisplayContentLocked(displayId).getTmpAppIterator(FORWARD_ITERATOR);
- while (iterator.hasNext()) {
- AppWindowToken wtoken = iterator.next();
+ final ArrayList<AppWindowToken> appTokens = mService.mAnimatingAppTokens;
+ final int NT = appTokens.size();
+ for (int i=0; i<NT; i++) {
+ AppWindowToken wtoken = appTokens.get(i);
AppWindowAnimator appAnimator = wtoken.mAppAnimator;
final boolean allDrawn = wtoken.allDrawn;
if (allDrawn != appAnimator.allDrawn) {
SurfaceControl.openTransaction();
SurfaceControl.setAnimationTransaction();
try {
+ updateAppWindowsLocked();
+
final int numDisplays = mDisplayContentsAnimators.size();
for (int i = 0; i < numDisplays; i++) {
final int displayId = mDisplayContentsAnimators.keyAt(i);
- updateAppWindowsLocked(displayId);
DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
final ScreenRotationAnimation screenRotationAnimation =
}
}
+ testTokenMayBeDrawnLocked();
+
for (int i = 0; i < numDisplays; i++) {
final int displayId = mDisplayContentsAnimators.keyAt(i);
-
- testTokenMayBeDrawnLocked(displayId);
-
DisplayContentsAnimator displayAnimator = mDisplayContentsAnimators.valueAt(i);
final ScreenRotationAnimation screenRotationAnimation =
import com.android.server.input.InputManagerService;
import com.android.server.power.PowerManagerService;
import com.android.server.power.ShutdownThread;
-import com.android.server.wm.DisplayContent.AppTokenIterator;
import android.Manifest;
import android.app.ActivityManagerNative;
static final boolean DEBUG_INPUT_METHOD = false;
static final boolean DEBUG_VISIBILITY = false;
static final boolean DEBUG_WINDOW_MOVEMENT = false;
- static final boolean DEBUG_TOKEN_MOVEMENT = true;
+ static final boolean DEBUG_TOKEN_MOVEMENT = false;
static final boolean DEBUG_ORIENTATION = false;
static final boolean DEBUG_APP_ORIENTATION = false;
static final boolean DEBUG_CONFIGURATION = false;
static final boolean DEBUG_LAYOUT_REPEATS = true;
static final boolean DEBUG_SURFACE_TRACE = false;
static final boolean DEBUG_WINDOW_TRACE = false;
- static final boolean DEBUG_TASK_MOVEMENT = false;
static final boolean SHOW_SURFACE_ALLOC = false;
static final boolean SHOW_TRANSACTIONS = false;
static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS;
static final boolean PROFILE_ORIENTATION = false;
static final boolean localLOGV = DEBUG;
- final static boolean REVERSE_ITERATOR = true;
- final static boolean FORWARD_ITERATOR = false;
-
/** How much to multiply the policy's type layer, to reserve room
* for multiple windows of the same type and Z-ordering adjustment
* with TYPE_LAYER_OFFSET. */
/**
* Mapping from a token IBinder to a WindowToken object.
*/
- final HashMap<IBinder, WindowToken> mTokenMap = new HashMap<IBinder, WindowToken>();
+ final HashMap<IBinder, WindowToken> mTokenMap =
+ new HashMap<IBinder, WindowToken>();
+
+ /**
+ * Window tokens that are in the process of exiting, but still
+ * on screen for animations.
+ */
+ final ArrayList<WindowToken> mExitingTokens = new ArrayList<WindowToken>();
+
+ /**
+ * List controlling the ordering of windows in different applications which must
+ * be kept in sync with ActivityManager.
+ */
+ final ArrayList<AppWindowToken> mAppTokens = new ArrayList<AppWindowToken>();
+
+ /**
+ * AppWindowTokens in the Z order they were in at the start of an animation. Between
+ * animations this list is maintained in the exact order of mAppTokens. If tokens
+ * are added to mAppTokens during an animation an attempt is made to insert them at the same
+ * logical location in this list. Note that this list is always in sync with mWindows.
+ */
+ ArrayList<AppWindowToken> mAnimatingAppTokens = new ArrayList<AppWindowToken>();
+
+ /**
+ * Application tokens that are in the process of exiting, but still
+ * on screen for animations.
+ */
+ final ArrayList<AppWindowToken> mExitingAppTokens = new ArrayList<AppWindowToken>();
/**
* List of window tokens that have finished starting their application,
String mLastANRState;
- /** All DisplayContents in the world, kept here */
+ /** All DisplayDontents in the world, kept here */
private SparseArray<DisplayContent> mDisplayContents = new SparseArray<DisplayContent>();
- private SparseArray<DisplayContent> mTaskIdToDisplayContents =
- new SparseArray<DisplayContent>();
-
- private final AllWindowsIterator mTmpWindowsIterator = new AllWindowsIterator();
int mRotation = 0;
int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
final WindowList windows = win.getWindowList();
final int N = windows.size();
final WindowState attached = win.mAttachedWindow;
+ int i;
WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
if (attached == null) {
int tokenWindowsPos = 0;
+ client.asBinder() + " (token=" + token + ")");
// Figure out where the window should go, based on the
// order of applications.
+ final int NA = mAnimatingAppTokens.size();
WindowState pos = null;
- AppTokenIterator iterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
- while (iterator.hasNext()) {
- AppWindowToken t = iterator.next();
+ for (i=NA-1; i>=0; i--) {
+ AppWindowToken t = mAnimatingAppTokens.get(i);
if (t == token) {
+ i--;
break;
}
} else {
// Continue looking down until we find the first
// token that has windows on this display.
- while (iterator.hasNext()) {
- AppWindowToken t = iterator.next();
- tokenWindowList = getTokenWindowsOnDisplay(t, displayContent);
+ while (i >= 0) {
+ AppWindowToken t = mAnimatingAppTokens.get(i);
+ tokenWindowList = getTokenWindowsOnDisplay(t, win.mDisplayContent);
final int NW = tokenWindowList.size();
if (NW > 0) {
pos = tokenWindowList.get(NW-1);
break;
}
+ i--;
}
if (pos != null) {
// Move in front of any windows attached to this
} else {
// Just search for the start of this layer.
final int myLayer = win.mBaseLayer;
- int i;
- for (i = 0; i < N; i++) {
+ for (i=0; i<N; i++) {
WindowState w = windows.get(i);
if (w.mBaseLayer > myLayer) {
break;
} else {
// Figure out where window should go, based on layer.
final int myLayer = win.mBaseLayer;
- int i;
- for (i = N - 1; i >= 0; i--) {
+ for (i=N-1; i>=0; i--) {
if (windows.get(i).mBaseLayer <= myLayer) {
break;
}
final int sublayer = win.mSubLayer;
int largestSublayer = Integer.MIN_VALUE;
WindowState windowWithLargestSublayer = null;
- int i;
- for (i = 0; i < NA; i++) {
+ for (i=0; i<NA; i++) {
WindowState w = tokenWindowList.get(i);
final int wSublayer = w.mSubLayer;
if (wSublayer >= largestSublayer) {
public void updateAppOpsState() {
synchronized(mWindowMap) {
- mTmpWindowsIterator.reset(FORWARD_ITERATOR);
- while (mTmpWindowsIterator.hasNext()) {
- final WindowState win = mTmpWindowsIterator.next();
- if (win.mAppOp != AppOpsManager.OP_NONE) {
- final int mode = mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(),
- win.getOwningPackage());
- win.setAppOpVisibilityLw(mode == AppOpsManager.MODE_ALLOWED);
+ boolean changed = false;
+ for (int i=0; i<mDisplayContents.size(); i++) {
+ DisplayContent display = mDisplayContents.valueAt(i);
+ WindowList windows = display.getWindowList();
+ for (int j=0; j<windows.size(); j++) {
+ final WindowState win = windows.get(j);
+ if (win.mAppOp != AppOpsManager.OP_NONE) {
+ changed |= win.setAppOpVisibilityLw(mAppOps.checkOpNoThrow(win.mAppOp,
+ win.getOwningUid(),
+ win.getOwningPackage()) == AppOpsManager.MODE_ALLOWED);
+ }
}
}
+ if (changed) {
+ scheduleAnimationLocked();
+ }
}
}
// Application Window Tokens
// -------------------------------------------------------------
- public void validateAppTokens(List<TaskGroup> tasks) {
- synchronized (mWindowMap) {
- int t = tasks.size() - 1;
- if (t < 0) {
- Slog.w(TAG, "validateAppTokens: empty task list");
- return;
+ public void validateAppTokens(List<IBinder> tokens) {
+ int v = tokens.size()-1;
+ int m = mAppTokens.size()-1;
+ while (v >= 0 && m >= 0) {
+ AppWindowToken atoken = mAppTokens.get(m);
+ if (atoken.removed) {
+ m--;
+ continue;
}
-
- TaskGroup task = tasks.get(0);
- int taskId = task.taskId;
- DisplayContent displayContent = mTaskIdToDisplayContents.get(taskId);
- if (displayContent == null) {
- Slog.w(TAG, "validateAppTokens: no Display for taskId=" + taskId);
- return;
+ if (tokens.get(v) != atoken.token) {
+ Slog.w(TAG, "Tokens out of sync: external is " + tokens.get(v)
+ + " @ " + v + ", internal is " + atoken.token + " @ " + m);
}
-
- boolean mismatch = false;
- AppTokenIterator iterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
- for ( ; t >= 0 && !mismatch; --t) {
- task = tasks.get(t);
- List<IApplicationToken> tokens = task.tokens;
- int v = task.tokens.size() - 1;
-
- DisplayContent lastDisplayContent = displayContent;
- displayContent = mTaskIdToDisplayContents.get(taskId);
- if (displayContent != lastDisplayContent) {
- Slog.w(TAG, "validateAppTokens: displayContent changed in TaskGroup list!");
- return;
- }
-
- while (v >= 0) {
- if (!iterator.hasNext()) {
- mismatch = true;
- break;
- }
- AppWindowToken atoken = iterator.next();
- if (atoken.removed) {
- continue;
- }
- if (tokens.get(v) != atoken.token) {
- mismatch = true;
- break;
- }
- v--;
- }
- }
-
- if (mismatch || iterator.hasNext()) {
- Slog.w(TAG, "validateAppTokens: Mismatch! ActivityManager=" + tasks);
- Slog.w(TAG, "validateAppTokens: Mismatch! WindowManager=" + iterator);
- Slog.w(TAG, "validateAppTokens: Mismatch! Callers=" + Debug.getCallers(4));
+ v--;
+ m--;
+ }
+ while (v >= 0) {
+ Slog.w(TAG, "External token not found: " + tokens.get(v) + " @ " + v);
+ v--;
+ }
+ while (m >= 0) {
+ AppWindowToken atoken = mAppTokens.get(m);
+ if (!atoken.removed) {
+ Slog.w(TAG, "Invalid internal atoken: " + atoken.token + " @ " + m);
}
+ m--;
}
}
final long origId = Binder.clearCallingIdentity();
synchronized(mWindowMap) {
- DisplayContent displayContent = null;
WindowToken wtoken = mTokenMap.remove(token);
if (wtoken != null) {
boolean delayed = false;
for (int i=0; i<N; i++) {
WindowState win = wtoken.windows.get(i);
- displayContent = win.mDisplayContent;
if (win.mWinAnimator.isAnimating()) {
delayed = true;
win.mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT,
false);
//TODO (multidisplay): Magnification is supported only for the default
- if (mDisplayMagnifier != null && win.isDefaultDisplay()) {
+ if (mDisplayMagnifier != null
+ && win.getDisplayId() == Display.DEFAULT_DISPLAY) {
mDisplayMagnifier.onWindowTransitionLocked(win,
WindowManagerPolicy.TRANSIT_EXIT);
}
changed = true;
- displayContent.layoutNeeded = true;
+ win.mDisplayContent.layoutNeeded = true;
}
}
}
if (delayed) {
- displayContent.mExitingTokens.add(wtoken);
+ mExitingTokens.add(wtoken);
} else if (wtoken.windowType == TYPE_WALLPAPER) {
mWallpaperTokens.remove(wtoken);
}
Binder.restoreCallingIdentity(origId);
}
+ /**
+ * Find the location to insert a new AppWindowToken into the window-ordered app token list.
+ * Note that mAppTokens.size() == mAnimatingAppTokens.size() + 1.
+ * @param addPos The location the token was inserted into in mAppTokens.
+ * @param atoken The token to insert.
+ */
+ private void addAppTokenToAnimating(final int addPos, final AppWindowToken atoken) {
+ if (addPos == 0 || addPos == mAnimatingAppTokens.size()) {
+ // It was inserted into the beginning or end of mAppTokens. Honor that.
+ mAnimatingAppTokens.add(addPos, atoken);
+ return;
+ }
+ // Find the item immediately above the mAppTokens insertion point and put the token
+ // immediately below that one in mAnimatingAppTokens.
+ final AppWindowToken aboveAnchor = mAppTokens.get(addPos + 1);
+ mAnimatingAppTokens.add(mAnimatingAppTokens.indexOf(aboveAnchor), atoken);
+ }
+
@Override
public void addAppToken(int addPos, IApplicationToken token,
- int taskId, int requestedOrientation, boolean fullscreen, boolean showWhenLocked) {
+ int groupId, int requestedOrientation, boolean fullscreen, boolean showWhenLocked) {
if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
"addAppToken()")) {
throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
}
atoken = new AppWindowToken(this, token);
atoken.inputDispatchingTimeoutNanos = inputDispatchingTimeoutNanos;
- atoken.groupId = taskId;
+ atoken.groupId = groupId;
atoken.appFullscreen = fullscreen;
atoken.showWhenLocked = showWhenLocked;
atoken.requestedOrientation = requestedOrientation;
if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG, "addAppToken: " + atoken
+ " at " + addPos);
-
- DisplayContent displayContent = mTaskIdToDisplayContents.get(taskId);
- if (displayContent == null) {
- displayContent = getDefaultDisplayContentLocked();
- mTaskIdToDisplayContents.put(taskId, displayContent);
- }
- displayContent.addAppToken(addPos, atoken);
+ mAppTokens.add(addPos, atoken);
+ addAppTokenToAnimating(addPos, atoken);
mTokenMap.put(token.asBinder(), atoken);
- mTaskIdToDisplayContents.put(taskId, displayContent);
// Application tokens start out hidden.
atoken.hidden = true;
}
synchronized(mWindowMap) {
- final AppWindowToken atoken = findAppWindowToken(token);
+ AppWindowToken atoken = findAppWindowToken(token);
if (atoken == null) {
Slog.w(TAG, "Attempted to set group id of non-existing app token: " + token);
return;
}
- DisplayContent displayContent = mTaskIdToDisplayContents.get(atoken.groupId);
- if (displayContent == null) {
- Slog.w(TAG, "setAppGroupId: No DisplayContent for taskId=" + atoken.groupId);
- displayContent = getDefaultDisplayContentLocked();
- }
- displayContent.setAppTaskId(atoken, groupId);
+ atoken.groupId = groupId;
}
}
boolean findingBehind = false;
boolean haveGroup = false;
boolean lastFullscreen = false;
- // TODO: Multi window.
- DisplayContent displayContent = getDefaultDisplayContentLocked();
- AppTokenIterator iterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
- while (iterator.hasNext()) {
- AppWindowToken atoken = iterator.next();
+ for (int pos = mAppTokens.size() - 1; pos >= 0; pos--) {
+ AppWindowToken atoken = mAppTokens.get(pos);
if (DEBUG_APP_ORIENTATION) Slog.v(TAG, "Checking app orientation: " + atoken);
TAG, "Removing app " + wtoken + " delayed=" + delayed
+ " animation=" + wtoken.mAppAnimator.animation
+ " animating=" + wtoken.mAppAnimator.animating);
- DisplayContent displayContent = mTaskIdToDisplayContents.get(wtoken.groupId);
if (delayed) {
// set the token aside because it has an active animation to be finished
if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
"removeAppToken make exiting: " + wtoken);
- displayContent.mExitingAppTokens.add(wtoken);
+ mExitingAppTokens.add(wtoken);
} else {
// Make sure there is no animation running on this token,
// so any windows associated with it will be removed as
}
if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
"removeAppToken: " + wtoken);
- displayContent.removeAppToken(wtoken);
+ mAppTokens.remove(wtoken);
+ mAnimatingAppTokens.remove(wtoken);
wtoken.removed = true;
if (wtoken.startingData != null) {
startingToken = wtoken;
}
void dumpAppTokensLocked() {
- DisplayContentsIterator iterator = new DisplayContentsIterator();
- while (iterator.hasNext()) {
- DisplayContent displayContent = iterator.next();
- Slog.v(TAG, " Display " + displayContent.getDisplayId());
- AppTokenIterator appIterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
- int i = appIterator.size();
- while (appIterator.hasNext()) {
- Slog.v(TAG, " #" + --i + ": " + appIterator.next().token);
- }
+ for (int i=mAppTokens.size()-1; i>=0; i--) {
+ Slog.v(TAG, " #" + i + ": " + mAppTokens.get(i).token);
+ }
+ }
+
+ void dumpAnimatingAppTokensLocked() {
+ for (int i=mAnimatingAppTokens.size()-1; i>=0; i--) {
+ Slog.v(TAG, " #" + i + ": " + mAnimatingAppTokens.get(i).token);
}
}
void dumpWindowsLocked() {
int i = 0;
- mTmpWindowsIterator.reset(REVERSE_ITERATOR);
- while (mTmpWindowsIterator.hasNext()) {
- final WindowState w = mTmpWindowsIterator.next();
+ final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR);
+ while (iterator.hasNext()) {
+ final WindowState w = iterator.next();
Slog.v(TAG, " #" + i++ + ": " + w);
}
}
- private int findAppWindowInsertionPointLocked(AppWindowToken target) {
- final int taskId = target.groupId;
- DisplayContent displayContent = mTaskIdToDisplayContents.get(taskId);
- if (displayContent == null) {
- Slog.w(TAG, "findTopAppWindowLocked: no DisplayContent for " + target);
- return 0;
- }
- final WindowList windows = displayContent.getWindowList();
+ private int findWindowOffsetLocked(WindowList windows, int tokenPos) {
final int NW = windows.size();
- AppTokenIterator iterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
- while (iterator.hasNext()) {
- if (iterator.next() == target) {
- break;
+ if (tokenPos >= mAnimatingAppTokens.size()) {
+ int i = NW;
+ while (i > 0) {
+ i--;
+ WindowState win = windows.get(i);
+ if (win.getAppToken() != null) {
+ return i+1;
+ }
}
}
- while (iterator.hasNext()) {
+ while (tokenPos > 0) {
// Find the first app token below the new position that has
// a window displayed.
- final AppWindowToken wtoken = iterator.next();
- if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows in " + wtoken.token);
+ final AppWindowToken wtoken = mAppTokens.get(tokenPos-1);
+ if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows @ "
+ + tokenPos + " -- " + wtoken.token);
if (wtoken.sendingToBottom) {
- if (DEBUG_REORDER) Slog.v(TAG, "Skipping token -- currently sending to bottom");
+ if (DEBUG_REORDER) Slog.v(TAG,
+ "Skipping token -- currently sending to bottom");
+ tokenPos--;
continue;
}
- for (int i = wtoken.windows.size() - 1; i >= 0; --i) {
+ int i = wtoken.windows.size();
+ while (i > 0) {
+ i--;
WindowState win = wtoken.windows.get(i);
- for (int j = win.mChildWindows.size() - 1; j >= 0; --j) {
+ int j = win.mChildWindows.size();
+ while (j > 0) {
+ j--;
WindowState cwin = win.mChildWindows.get(j);
if (cwin.mSubLayer >= 0) {
- for (int pos = NW - 1; pos >= 0; pos--) {
+ for (int pos=NW-1; pos>=0; pos--) {
if (windows.get(pos) == cwin) {
if (DEBUG_REORDER) Slog.v(TAG,
- "Found child win @" + (pos + 1));
- return pos + 1;
+ "Found child win @" + (pos+1));
+ return pos+1;
}
}
}
}
- for (int pos = NW - 1; pos >= 0; pos--) {
+ for (int pos=NW-1; pos>=0; pos--) {
if (windows.get(pos) == win) {
- if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos + 1));
- return pos + 1;
+ if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos+1));
+ return pos+1;
}
}
}
+ tokenPos--;
}
return 0;
return index;
}
- private void moveTaskWindowsLocked(int taskId) {
- DisplayContent displayContent = mTaskIdToDisplayContents.get(taskId);
- if (displayContent == null) {
- Slog.w(TAG, "moveTaskWindowsLocked: can't find DisplayContent for taskId=" + taskId);
- return;
+ @Override
+ public void moveAppToken(int index, IBinder token) {
+ if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
+ "moveAppToken()")) {
+ throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
}
- TaskList taskList = displayContent.mTaskIdToTaskList.get(taskId);
- if (taskList == null) {
- Slog.w(TAG, "moveTaskWindowsLocked: can't find TaskList for taskId=" + taskId);
- return;
+ synchronized(mWindowMap) {
+ if (DEBUG_REORDER) Slog.v(TAG, "Initial app tokens:");
+ if (DEBUG_REORDER) dumpAppTokensLocked();
+ final AppWindowToken wtoken = findAppWindowToken(token);
+ final int oldIndex = mAppTokens.indexOf(wtoken);
+ if (DEBUG_TOKEN_MOVEMENT || DEBUG_REORDER) Slog.v(TAG,
+ "Start moving token " + wtoken + " initially at "
+ + oldIndex);
+ if (oldIndex > index && mAppTransition.isTransitionSet()) {
+ // animation towards back has not started, copy old list for duration of animation.
+ mAnimatingAppTokens.clear();
+ mAnimatingAppTokens.addAll(mAppTokens);
+ }
+ if (wtoken == null || !mAppTokens.remove(wtoken)) {
+ Slog.w(TAG, "Attempting to reorder token that doesn't exist: "
+ + token + " (" + wtoken + ")");
+ return;
+ }
+ mAppTokens.add(index, wtoken);
+ if (DEBUG_REORDER) Slog.v(TAG, "Moved " + token + " to " + index + ":");
+ else if (DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "Moved " + token + " to " + index);
+ if (DEBUG_REORDER) dumpAppTokensLocked();
+ if (!mAppTransition.isTransitionSet()) {
+ // Not animating, bring animating app list in line with mAppTokens.
+ mAnimatingAppTokens.clear();
+ mAnimatingAppTokens.addAll(mAppTokens);
+
+ // Bring window ordering, window focus and input window in line with new app token
+ final long origId = Binder.clearCallingIdentity();
+ if (DEBUG_REORDER) Slog.v(TAG, "Removing windows in " + token + ":");
+ if (DEBUG_REORDER) dumpWindowsLocked();
+ if (tmpRemoveAppWindowsLocked(wtoken)) {
+ if (DEBUG_REORDER) Slog.v(TAG, "Adding windows back in:");
+ if (DEBUG_REORDER) dumpWindowsLocked();
+ DisplayContentsIterator iterator = new DisplayContentsIterator();
+ while(iterator.hasNext()) {
+ final DisplayContent displayContent = iterator.next();
+ final WindowList windows = displayContent.getWindowList();
+ final int pos = findWindowOffsetLocked(windows, index);
+ final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken);
+ if (pos != newPos) {
+ displayContent.layoutNeeded = true;
+ }
+ }
+ if (DEBUG_REORDER) Slog.v(TAG, "Final window list:");
+ if (DEBUG_REORDER) dumpWindowsLocked();
+ updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+ false /*updateInputWindows*/);
+ mInputMonitor.setUpdateInputWindowsNeededLw();
+ performLayoutAndPlaceSurfacesLocked();
+ mInputMonitor.updateInputWindowsLw(false /*force*/);
+ }
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+ }
+
+ private void removeAppTokensLocked(List<IBinder> tokens) {
+ // XXX This should be done more efficiently!
+ // (take advantage of the fact that both lists should be
+ // ordered in the same way.)
+ int N = tokens.size();
+ for (int i=0; i<N; i++) {
+ IBinder token = tokens.get(i);
+ final AppWindowToken wtoken = findAppWindowToken(token);
+ if (DEBUG_REORDER || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
+ "Temporarily removing " + wtoken + " from " + mAppTokens.indexOf(wtoken));
+ if (!mAppTokens.remove(wtoken)) {
+ Slog.w(TAG, "Attempting to reorder token that doesn't exist: "
+ + token + " (" + wtoken + ")");
+ i--;
+ N--;
+ }
}
+ }
+ private void moveAppWindowsLocked(List<IBinder> tokens, int tokenPos) {
// First remove all of the windows from the list.
- for (AppWindowToken wtoken : taskList.mAppTokens) {
- tmpRemoveAppWindowsLocked(wtoken);
+ final int N = tokens.size();
+ int i;
+ for (i=0; i<N; i++) {
+ WindowToken token = mTokenMap.get(tokens.get(i));
+ if (token != null) {
+ tmpRemoveAppWindowsLocked(token);
+ }
}
// And now add them back at the correct place.
- // Where to start adding?
- int pos = findAppWindowInsertionPointLocked(taskList.mAppTokens.get(0));
- for (AppWindowToken wtoken : taskList.mAppTokens) {
- if (wtoken != null) {
- final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken);
- if (newPos != pos) {
- displayContent.layoutNeeded = true;
+ DisplayContentsIterator iterator = new DisplayContentsIterator();
+ while (iterator.hasNext()) {
+ final DisplayContent displayContent = iterator.next();
+ final WindowList windows = displayContent.getWindowList();
+ // Where to start adding?
+ int pos = findWindowOffsetLocked(windows, tokenPos);
+ for (i=0; i<N; i++) {
+ WindowToken token = mTokenMap.get(tokens.get(i));
+ if (token != null) {
+ final int newPos = reAddAppWindowsLocked(displayContent, pos, token);
+ if (newPos != pos) {
+ displayContent.layoutNeeded = true;
+ }
+ pos = newPos;
}
- pos = newPos;
}
- }
- if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
- false /*updateInputWindows*/)) {
- assignLayersLocked(displayContent.getWindowList());
+ if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+ false /*updateInputWindows*/)) {
+ assignLayersLocked(windows);
+ }
}
- updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
- false /*updateInputWindows*/);
mInputMonitor.setUpdateInputWindowsNeededLw();
+
+ // Note that the above updateFocusedWindowLocked used to sit here.
+
performLayoutAndPlaceSurfacesLocked();
mInputMonitor.updateInputWindowsLw(false /*force*/);
//dump();
}
- public void moveTaskToTop(int taskId) {
+ @Override
+ public void moveAppTokensToTop(List<IBinder> tokens) {
+ if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
+ "moveAppTokensToTop()")) {
+ throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
+ }
+
final long origId = Binder.clearCallingIdentity();
- try {
- synchronized(mWindowMap) {
- DisplayContent displayContent = mTaskIdToDisplayContents.get(taskId);
- if (displayContent == null) {
- Slog.e(TAG, "moveTaskToTop: taskId=" + taskId
- + " not found in mTaskIdToDisplayContents");
- return;
- }
- TaskList taskList = displayContent.mTaskIdToTaskList.get(taskId);
- if (taskList == null) {
- Slog.e(TAG, "moveTaskToTop: taskId=" + taskId
- + " not found in mTaskIdToTaskLists");
- return;
- }
- if (!displayContent.mTaskLists.remove(taskList)) {
- Slog.e(TAG, "moveTaskToTop: taskId=" + taskId + " not found in mTaskLists");
+ synchronized(mWindowMap) {
+ removeAppTokensLocked(tokens);
+ final int N = tokens.size();
+ for (int i=0; i<N; i++) {
+ AppWindowToken wt = findAppWindowToken(tokens.get(i));
+ if (wt != null) {
+ if (DEBUG_TOKEN_MOVEMENT || DEBUG_REORDER) Slog.v(TAG,
+ "Adding next to top: " + wt);
+ mAppTokens.add(wt);
+ if (mAppTransition.isTransitionSet()) {
+ wt.sendingToBottom = false;
+ }
}
- displayContent.mTaskLists.add(taskList);
-
- moveTaskWindowsLocked(taskId);
}
- } finally {
- Binder.restoreCallingIdentity(origId);
+
+ mAnimatingAppTokens.clear();
+ mAnimatingAppTokens.addAll(mAppTokens);
+ moveAppWindowsLocked(tokens, mAppTokens.size());
}
+ Binder.restoreCallingIdentity(origId);
}
- public void moveTaskToBottom(int taskId) {
+ @Override
+ public void moveAppTokensToBottom(List<IBinder> tokens) {
+ if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
+ "moveAppTokensToBottom()")) {
+ throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
+ }
+
final long origId = Binder.clearCallingIdentity();
- try {
- synchronized(mWindowMap) {
- DisplayContent displayContent = mTaskIdToDisplayContents.get(taskId);
- if (displayContent == null) {
- Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId
- + " not found in mTaskIdToDisplayContents");
- return;
- }
- TaskList taskList = displayContent.mTaskIdToTaskList.get(taskId);
- if (taskList == null) {
- Slog.e(TAG, "moveTaskToTopBottom: taskId=" + taskId
- + " not found in mTaskIdToTaskLists");
- return;
- }
- if (!displayContent.mTaskLists.remove(taskList)) {
- Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId + " not found in mTaskLists");
+ synchronized(mWindowMap) {
+ final int N = tokens.size();
+ if (N > 0) {
+ // animating towards back, hang onto old list for duration of animation.
+ mAnimatingAppTokens.clear();
+ mAnimatingAppTokens.addAll(mAppTokens);
+ }
+ removeAppTokensLocked(tokens);
+ int pos = 0;
+ for (int i=0; i<N; i++) {
+ AppWindowToken wt = findAppWindowToken(tokens.get(i));
+ if (wt != null) {
+ if (DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
+ "Adding next to bottom: " + wt + " at " + pos);
+ mAppTokens.add(pos, wt);
+ if (mAppTransition.isTransitionSet()) {
+ wt.sendingToBottom = true;
+ }
+ pos++;
}
- displayContent.mTaskLists.add(0, taskList);
-
- moveTaskWindowsLocked(taskId);
}
- } finally {
- Binder.restoreCallingIdentity(origId);
+
+ mAnimatingAppTokens.clear();
+ mAnimatingAppTokens.addAll(mAppTokens);
+ moveAppWindowsLocked(tokens, 0);
}
+ Binder.restoreCallingIdentity(origId);
}
// -------------------------------------------------------------
@Override
public void closeSystemDialogs(String reason) {
synchronized(mWindowMap) {
- mTmpWindowsIterator.reset(FORWARD_ITERATOR);
- while (mTmpWindowsIterator.hasNext()) {
- final WindowState w = mTmpWindowsIterator.next();
+ final AllWindowsIterator iterator = new AllWindowsIterator();
+ while (iterator.hasNext()) {
+ final WindowState w = iterator.next();
if (w.mHasSurface) {
try {
w.mClient.closeSystemDialogs(reason);
// the background..)
if (on) {
boolean isVisible = false;
- mTmpWindowsIterator.reset(FORWARD_ITERATOR);
- while (mTmpWindowsIterator.hasNext()) {
- final WindowState ws = mTmpWindowsIterator.next();
+ final AllWindowsIterator iterator = new AllWindowsIterator();
+ while (iterator.hasNext()) {
+ final WindowState ws = iterator.next();
if (ws.mSession.mPid == pid && ws.isVisibleLw()) {
isVisible = true;
break;
}
synchronized (mWindowMap) {
- mTmpWindowsIterator.reset(FORWARD_ITERATOR);
- while (mTmpWindowsIterator.hasNext()) {
- final WindowState w = mTmpWindowsIterator.next();
+ final AllWindowsIterator iterator = new AllWindowsIterator();
+ while (iterator.hasNext()) {
+ final WindowState w = iterator.next();
if (System.identityHashCode(w) == hashCode) {
return w;
}
// TODO(multidisplay): Call isScreenOn for each display.
private void sendScreenStatusToClientsLocked() {
final boolean on = mPowerManager.isScreenOn();
- mTmpWindowsIterator.reset(FORWARD_ITERATOR);
- while (mTmpWindowsIterator.hasNext()) {
+ final AllWindowsIterator iterator = new AllWindowsIterator();
+ while (iterator.hasNext()) {
try {
- mTmpWindowsIterator.next().mClient.dispatchScreenState(on);
+ iterator.next().mClient.dispatchScreenState(on);
} catch (RemoteException e) {
// Ignored
}
if (mAppTransition.isTransitionSet()) {
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT");
mAppTransition.setTimeout();
+ mAnimatingAppTokens.clear();
+ mAnimatingAppTokens.addAll(mAppTokens);
performLayoutAndPlaceSurfacesLocked();
}
}
case APP_FREEZE_TIMEOUT: {
synchronized (mWindowMap) {
Slog.w(TAG, "App freeze timeout expired.");
- DisplayContent displayContent = getDefaultDisplayContentLocked();
- AppTokenIterator iterator =
- displayContent.getTmpAppIterator(REVERSE_ITERATOR);
- while (iterator.hasNext()) {
- AppWindowToken tok = iterator.next();
+ int i = mAppTokens.size();
+ while (i > 0) {
+ i--;
+ AppWindowToken tok = mAppTokens.get(i);
if (tok.mAppAnimator.freezingScreen) {
Slog.w(TAG, "Force clearing freeze: " + tok);
unsetAppFreezingScreenLocked(tok, true, true);
performLayoutAndPlaceSurfacesLocked();
}
- @Override
public void setOverscan(int displayId, int left, int top, int right, int bottom) {
if (mContext.checkCallingOrSelfPermission(
android.Manifest.permission.WRITE_SECURE_SETTINGS) !=
// in the main app list, but still have windows shown. We put them
// in the back because now that the animation is over we no longer
// will care about them.
- AppTokenList exitingAppTokens = displayContent.mExitingAppTokens;
- int NT = exitingAppTokens.size();
+ int NT = mExitingAppTokens.size();
for (int j=0; j<NT; j++) {
- i = reAddAppWindowsLocked(displayContent, i, exitingAppTokens.get(j));
+ i = reAddAppWindowsLocked(displayContent, i, mExitingAppTokens.get(j));
}
// And add in the still active app tokens in Z order.
- AppTokenIterator iterator = displayContent.getTmpAppIterator(FORWARD_ITERATOR);
- while (iterator.hasNext()) {
- i = reAddAppWindowsLocked(displayContent, i, iterator.next());
+ NT = mAnimatingAppTokens.size();
+ for (int j=0; j<NT; j++) {
+ i = reAddAppWindowsLocked(displayContent, i, mAnimatingAppTokens.get(j));
}
i -= lastBelow;
}
}
Slog.w(TAG, "Current app token list:");
- dumpAppTokensLocked();
+ dumpAnimatingAppTokensLocked();
Slog.w(TAG, "Final window list:");
dumpWindowsLocked();
}
mAppTransition.setIdle();
// Restore window app tokens to the ActivityManager views
- final DisplayContent displayContent = getDefaultDisplayContentLocked();
- AppTokenIterator iterator = displayContent.getTmpAppIterator(FORWARD_ITERATOR);
- while (iterator.hasNext()) {
- iterator.next().sendingToBottom = false;
+ for (int i = mAnimatingAppTokens.size() - 1; i >= 0; i--) {
+ mAnimatingAppTokens.get(i).sendingToBottom = false;
}
+ mAnimatingAppTokens.clear();
+ mAnimatingAppTokens.addAll(mAppTokens);
rebuildAppWindowListLocked();
changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
}
}
- private void updateAllDrawnLocked(DisplayContent displayContent) {
+ private void updateAllDrawnLocked() {
// See if any windows have been drawn, so they (and others
// associated with them) can now be shown.
- AppTokenIterator iterator = displayContent.getTmpAppIterator(FORWARD_ITERATOR);
- while (iterator.hasNext()) {
- AppWindowToken wtoken = iterator.next();
+ final ArrayList<AppWindowToken> appTokens = mAnimatingAppTokens;
+ final int NT = appTokens.size();
+ for (int i=0; i<NT; i++) {
+ AppWindowToken wtoken = appTokens.get(i);
if (!wtoken.allDrawn) {
int numInteresting = wtoken.numInterestingWindows;
if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
}
// Initialize state of exiting tokens.
- DisplayContentsIterator iterator = new DisplayContentsIterator();
- while (iterator.hasNext()) {
- final DisplayContent displayContent = iterator.next();
- for (i=displayContent.mExitingTokens.size()-1; i>=0; i--) {
- displayContent.mExitingTokens.get(i).hasVisible = false;
- }
+ for (i=mExitingTokens.size()-1; i>=0; i--) {
+ mExitingTokens.get(i).hasVisible = false;
+ }
- // Initialize state of exiting applications.
- for (i=displayContent.mExitingAppTokens.size()-1; i>=0; i--) {
- displayContent.mExitingAppTokens.get(i).hasVisible = false;
- }
+ // Initialize state of exiting applications.
+ for (i=mExitingAppTokens.size()-1; i>=0; i--) {
+ mExitingAppTokens.get(i).hasVisible = false;
}
mInnerFields.mHoldScreen = null;
}
boolean focusDisplayed = false;
+ boolean updateAllDrawn = false;
- iterator = new DisplayContentsIterator();
+ DisplayContentsIterator iterator = new DisplayContentsIterator();
while (iterator.hasNext()) {
- boolean updateAllDrawn = false;
final DisplayContent displayContent = iterator.next();
WindowList windows = displayContent.getWindowList();
DisplayInfo displayInfo = displayContent.getDisplayInfo();
if (!mInnerFields.mDimming && mAnimator.isDimmingLocked(displayId)) {
stopDimmingLocked(displayId);
}
+ }
- if (updateAllDrawn) {
- updateAllDrawnLocked(displayContent);
- }
+ if (updateAllDrawn) {
+ updateAllDrawnLocked();
}
if (focusDisplayed) {
}
// Time to remove any exiting tokens?
- iterator = new DisplayContentsIterator();
- while (iterator.hasNext()) {
- final DisplayContent displayContent = iterator.next();
- ArrayList<WindowToken> exitingTokens = displayContent.mExitingTokens;
- for (i = exitingTokens.size() - 1; i >= 0; i--) {
- WindowToken token = exitingTokens.get(i);
- if (!token.hasVisible) {
- exitingTokens.remove(i);
- if (token.windowType == TYPE_WALLPAPER) {
- mWallpaperTokens.remove(token);
- }
+ for (i=mExitingTokens.size()-1; i>=0; i--) {
+ WindowToken token = mExitingTokens.get(i);
+ if (!token.hasVisible) {
+ mExitingTokens.remove(i);
+ if (token.windowType == TYPE_WALLPAPER) {
+ mWallpaperTokens.remove(token);
}
}
+ }
- // Time to remove any exiting applications?
- AppTokenList exitingAppTokens = displayContent.mExitingAppTokens;
- for (i = exitingAppTokens.size() - 1; i >= 0; i--) {
- AppWindowToken token = exitingAppTokens.get(i);
- if (!token.hasVisible && !mClosingApps.contains(token)) {
- // Make sure there is no animation running on this token,
- // so any windows associated with it will be removed as
- // soon as their animations are complete
- token.mAppAnimator.clearAnimation();
- token.mAppAnimator.animating = false;
- if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
- "performLayout: App token exiting now removed" + token);
- displayContent.removeAppToken(token);
- exitingAppTokens.remove(i);
- }
+ // Time to remove any exiting applications?
+ for (i=mExitingAppTokens.size()-1; i>=0; i--) {
+ AppWindowToken token = mExitingAppTokens.get(i);
+ if (!token.hasVisible && !mClosingApps.contains(token)) {
+ // Make sure there is no animation running on this token,
+ // so any windows associated with it will be removed as
+ // soon as their animations are complete
+ token.mAppAnimator.clearAnimation();
+ token.mAppAnimator.animating = false;
+ if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG,
+ "performLayout: App token exiting now removed" + token);
+ mAppTokens.remove(token);
+ mAnimatingAppTokens.remove(token);
+ mExitingAppTokens.remove(i);
}
}
defaultDisplay.layoutNeeded = true;
}
- iterator = new DisplayContentsIterator();
+ DisplayContentsIterator iterator = new DisplayContentsIterator();
while (iterator.hasNext()) {
DisplayContent displayContent = iterator.next();
if (displayContent.pendingLayoutChanges != 0) {
// window list to make sure we haven't left any dangling surfaces
// around.
- mTmpWindowsIterator.reset(FORWARD_ITERATOR);
+ AllWindowsIterator iterator = new AllWindowsIterator();
Slog.i(TAG, "Out of memory for surface! Looking for leaks...");
- while (mTmpWindowsIterator.hasNext()) {
- WindowState ws = mTmpWindowsIterator.next();
+ while (iterator.hasNext()) {
+ WindowState ws = iterator.next();
WindowStateAnimator wsa = ws.mWinAnimator;
if (wsa.mSurfaceControl != null) {
if (!mSessions.contains(wsa.mSession)) {
if (!leakedSurface) {
Slog.w(TAG, "No leaked surfaces; killing applicatons!");
SparseIntArray pidCandidates = new SparseIntArray();
- mTmpWindowsIterator.reset(FORWARD_ITERATOR);
- while (mTmpWindowsIterator.hasNext()) {
- WindowState ws = mTmpWindowsIterator.next();
+ iterator = new AllWindowsIterator();
+ while (iterator.hasNext()) {
+ WindowState ws = iterator.next();
if (mForceRemoves.contains(ws)) {
continue;
}
}
private WindowState findFocusedWindowLocked(DisplayContent displayContent) {
- AppTokenIterator iterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
- WindowToken nextApp = iterator.hasNext() ? iterator.next() : null;
+ int nextAppIndex = mAppTokens.size()-1;
+ WindowToken nextApp = nextAppIndex >= 0 ? mAppTokens.get(nextAppIndex) : null;
final WindowList windows = displayContent.getWindowList();
for (int i = windows.size() - 1; i >= 0; i--) {
// through the app tokens until we find its app.
if (thisApp != null && nextApp != null && thisApp != nextApp
&& win.mAttrs.type != TYPE_APPLICATION_STARTING) {
- final WindowToken origAppToken = nextApp;
- while (iterator.hasNext()) {
+ int origAppIndex = nextAppIndex;
+ while (nextAppIndex > 0) {
if (nextApp == mFocusedApp) {
// Whoops, we are below the focused app... no focus
// for you!
TAG, "Reached focused app: " + mFocusedApp);
return null;
}
- nextApp = iterator.next();
+ nextAppIndex--;
+ nextApp = mAppTokens.get(nextAppIndex);
if (nextApp == thisApp) {
break;
}
// Uh oh, the app token doesn't exist! This shouldn't
// happen, but if it does we can get totally hosed...
// so restart at the original app.
- nextApp = origAppToken;
- iterator = displayContent.new AppTokenIterator(true);
- while (iterator.hasNext()) {
- // return iterator to same place.
- if (iterator.next() == origAppToken) {
- break;
- }
- }
+ nextAppIndex = origAppIndex;
+ nextApp = mAppTokens.get(nextAppIndex);
}
}
}
}
}
+ if (mAppTokens.size() > 0) {
+ pw.println();
+ pw.println(" Application tokens in Z order:");
+ for (int i=mAppTokens.size()-1; i>=0; i--) {
+ pw.print(" App #"); pw.print(i);
+ pw.print(' '); pw.print(mAppTokens.get(i)); pw.println(":");
+ mAppTokens.get(i).dump(pw, " ");
+ }
+ }
if (mFinishedStarting.size() > 0) {
pw.println();
pw.println(" Finishing start of application tokens:");
}
}
}
+ if (mExitingTokens.size() > 0) {
+ pw.println();
+ pw.println(" Exiting tokens:");
+ for (int i=mExitingTokens.size()-1; i>=0; i--) {
+ WindowToken token = mExitingTokens.get(i);
+ pw.print(" Exiting #"); pw.print(i);
+ pw.print(' '); pw.print(token);
+ if (dumpAll) {
+ pw.println(':');
+ token.dump(pw, " ");
+ } else {
+ pw.println();
+ }
+ }
+ }
+ if (mExitingAppTokens.size() > 0) {
+ pw.println();
+ pw.println(" Exiting application tokens:");
+ for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
+ WindowToken token = mExitingAppTokens.get(i);
+ pw.print(" Exiting App #"); pw.print(i);
+ pw.print(' '); pw.print(token);
+ if (dumpAll) {
+ pw.println(':');
+ token.dump(pw, " ");
+ } else {
+ pw.println();
+ }
+ }
+ }
+ if (mAppTransition.isRunning() && mAnimatingAppTokens.size() > 0) {
+ pw.println();
+ pw.println(" Application tokens during animation:");
+ for (int i=mAnimatingAppTokens.size()-1; i>=0; i--) {
+ WindowToken token = mAnimatingAppTokens.get(i);
+ pw.print(" App moving to bottom #"); pw.print(i);
+ pw.print(' '); pw.print(token);
+ if (dumpAll) {
+ pw.println(':');
+ token.dump(pw, " ");
+ } else {
+ pw.println();
+ }
+ }
+ }
if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
pw.println();
if (mOpeningApps.size() > 0) {
void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
ArrayList<WindowState> windows) {
int j = 0;
- mTmpWindowsIterator.reset(REVERSE_ITERATOR);
- while (mTmpWindowsIterator.hasNext()) {
- final WindowState w = mTmpWindowsIterator.next();
+ final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR);
+ while (iterator.hasNext()) {
+ final WindowState w = iterator.next();
if (windows == null || windows.contains(w)) {
pw.print(" Window #"); pw.print(j++); pw.print(' ');
pw.print(w); pw.println(":");
WindowList windows = new WindowList();
if ("visible".equals(name)) {
synchronized(mWindowMap) {
- mTmpWindowsIterator.reset(REVERSE_ITERATOR);
- while (mTmpWindowsIterator.hasNext()) {
- final WindowState w = mTmpWindowsIterator.next();
+ final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR);
+ while (iterator.hasNext()) {
+ final WindowState w = iterator.next();
if (w.mWinAnimator.mSurfaceShown) {
windows.add(w);
}
} catch (RuntimeException e) {
}
synchronized(mWindowMap) {
- mTmpWindowsIterator.reset(REVERSE_ITERATOR);
- while (mTmpWindowsIterator.hasNext()) {
- final WindowState w = mTmpWindowsIterator.next();
+ final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR);
+ while (iterator.hasNext()) {
+ final WindowState w = iterator.next();
if (name != null) {
if (w.mAttrs.getTitle().toString().contains(name)) {
windows.add(w);
class DisplayContentsIterator implements Iterator<DisplayContent> {
private int cur;
- void reset() {
- cur = 0;
- }
-
@Override
public boolean hasNext() {
return cur < mDisplayContents.size();
}
}
+ final static boolean REVERSE_ITERATOR = true;
class AllWindowsIterator implements Iterator<WindowState> {
private DisplayContent mDisplayContent;
private DisplayContentsIterator mDisplayContentsIterator;
private boolean mReverse;
AllWindowsIterator() {
- this(false);
- }
-
- AllWindowsIterator(boolean reverse) {
mDisplayContentsIterator = new DisplayContentsIterator();
- reset(reverse);
+ mDisplayContent = mDisplayContentsIterator.next();
+ mWindowList = mDisplayContent.getWindowList();
}
- void reset(boolean reverse) {
+ AllWindowsIterator(boolean reverse) {
+ this();
mReverse = reverse;
- mDisplayContentsIterator.reset();
- if (mDisplayContentsIterator.hasNext()) {
- mDisplayContent = mDisplayContentsIterator.next();
- mWindowList = mDisplayContent.getWindowList();
- mWindowListIndex = reverse ? mWindowList.size() - 1 : 0;
- } else {
- mDisplayContent = null;
- mWindowList = null;
- mWindowListIndex = 0;
- }
+ mWindowListIndex = reverse ? mWindowList.size() - 1 : 0;
}
@Override
public boolean hasNext() {
- if (mDisplayContent == null) {
- return false;
- }
if (mReverse) {
return mWindowListIndex >= 0;
}
import java.util.ArrayList;
class WindowList extends ArrayList<WindowState> {
- WindowList() {
- super();
- }
- WindowList(WindowList windows) {
- super(windows);
- }
}
/**
return true;
}
- public void setAppOpVisibilityLw(boolean state) {
+ public boolean setAppOpVisibilityLw(boolean state) {
if (mAppOpVisibility != state) {
mAppOpVisibility = state;
if (state) {
// ops modifies they should only be hidden by policy due to the
// lock screen, and the user won't be changing this if locked.
// Plus it will quickly be fixed the next time we do a layout.
- showLw(true, true);
+ showLw(true, false);
} else {
- hideLw(true, true);
+ hideLw(true, false);
}
+ return true;
}
+ return false;
}
@Override
import android.os.IBinder;
import java.io.PrintWriter;
+import java.util.ArrayList;
/**
* Container of a set of related windows in the window manager. Often this
} catch (RemoteException e) {
fail("Unexpected remote exception");
}
- }
+
+ try {
+ mWm.moveAppToken(0, null);
+ fail("IWindowManager.moveAppToken did not throw SecurityException as"
+ + " expected");
+ } catch (SecurityException e) {
+ // expected
+ } catch (RemoteException e) {
+ fail("Unexpected remote exception");
+ }
+
+ try {
+ mWm.moveAppTokensToTop(null);
+ fail("IWindowManager.moveAppTokensToTop did not throw SecurityException as"
+ + " expected");
+ } catch (SecurityException e) {
+ // expected
+ } catch (RemoteException e) {
+ fail("Unexpected remote exception");
+ }
+
+ try {
+ mWm.moveAppTokensToBottom(null);
+ fail("IWindowManager.moveAppTokensToBottom did not throw SecurityException as"
+ + " expected");
+ } catch (SecurityException e) {
+ // expected
+ } catch (RemoteException e) {
+ fail("Unexpected remote exception");
+ }
+ }
@SmallTest
public void testDISABLE_KEYGUARD() {
}
@Override
+ public void moveAppToken(int arg0, IBinder arg1) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void moveAppTokensToBottom(List<IBinder> arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void moveAppTokensToTop(List<IBinder> arg0) throws RemoteException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
public IWindowSession openSession(IInputMethodClient arg0, IInputContext arg1)
throws RemoteException {
// TODO Auto-generated method stub