summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCraig Mautner <cmautner@google.com>2013-12-04 16:14:06 -0800
committerCraig Mautner <cmautner@google.com>2013-12-18 15:08:15 -0800
commit4a1cb22056112f7ffd5f4fad8b7a092b96e7cc7b (patch)
tree2a30eb0760369a59905895e88f8325fbf9934414
parent3bcdbd6b2d96427d7cee835e9ed79aeed51de267 (diff)
downloadframeworks_base-4a1cb22056112f7ffd5f4fad8b7a092b96e7cc7b.zip
frameworks_base-4a1cb22056112f7ffd5f4fad8b7a092b96e7cc7b.tar.gz
frameworks_base-4a1cb22056112f7ffd5f4fad8b7a092b96e7cc7b.tar.bz2
Pair ActivityStacks with Displays
- Introduce concept of ActivityStacks residing on Displays and able to be decoupled and moved around. - Add a new interface, IActivityContainer for clients to handle ActivityStacks. - Abandon ordering of stacks based on mStackState and instead use ActivityDisplayInfo.stacks<ActivityStack> ordering. Progress towards closing bug 12078972. Change-Id: I7785b61c26dc17f432a4803eebee07c7415fcc1f
-rw-r--r--Android.mk2
-rw-r--r--cmds/am/src/com/android/commands/am/Am.java14
-rw-r--r--core/java/android/app/ActivityManagerNative.java71
-rw-r--r--core/java/android/app/IActivityContainer.aidl29
-rw-r--r--core/java/android/app/IActivityContainerCallback.aidl24
-rw-r--r--core/java/android/app/IActivityManager.java9
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java73
-rw-r--r--services/java/com/android/server/am/ActivityRecord.java2
-rw-r--r--services/java/com/android/server/am/ActivityStack.java48
-rw-r--r--services/java/com/android/server/am/ActivityStackSupervisor.java974
-rw-r--r--services/java/com/android/server/wm/DisplayContent.java18
-rw-r--r--services/java/com/android/server/wm/TaskStack.java6
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java7
13 files changed, 837 insertions, 440 deletions
diff --git a/Android.mk b/Android.mk
index 3a3169c..ade5e38 100644
--- a/Android.mk
+++ b/Android.mk
@@ -59,6 +59,8 @@ LOCAL_SRC_FILES += \
core/java/android/accounts/IAccountManagerResponse.aidl \
core/java/android/accounts/IAccountAuthenticator.aidl \
core/java/android/accounts/IAccountAuthenticatorResponse.aidl \
+ core/java/android/app/IActivityContainer.aidl \
+ core/java/android/app/IActivityContainerCallback.aidl \
core/java/android/app/IActivityController.aidl \
core/java/android/app/IActivityPendingResult.aidl \
core/java/android/app/IAlarmManager.aidl \
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index f3432a0..7adf5ec 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -21,6 +21,7 @@ package com.android.commands.am;
import android.app.ActivityManager;
import android.app.ActivityManager.StackInfo;
import android.app.ActivityManagerNative;
+import android.app.IActivityContainer;
import android.app.IActivityController;
import android.app.IActivityManager;
import android.app.IInstrumentationWatcher;
@@ -35,6 +36,7 @@ import android.graphics.Rect;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
+import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -107,7 +109,7 @@ public class Am extends BaseCommand {
" am to-intent-uri [INTENT]\n" +
" am switch-user <USER_ID>\n" +
" am stop-user <USER_ID>\n" +
- " am stack create <TASK_ID>\n" +
+ " am stack create <TASK_ID> <DISPLAY_ID>\n" +
" am stack movetask <TASK_ID> <STACK_ID> [true|false]\n" +
" am stack resize <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" +
" am stack list\n" +
@@ -1558,10 +1560,16 @@ public class Am extends BaseCommand {
private void runStackCreate() throws Exception {
String taskIdStr = nextArgRequired();
int taskId = Integer.valueOf(taskIdStr);
+ String displayIdStr = nextArgRequired();
+ int displayId = Integer.valueOf(displayIdStr);
try {
- int stackId = mAm.createStack(taskId);
- System.out.println("createStack returned new stackId=" + stackId + "\n\n");
+ IBinder homeActivityToken = mAm.getHomeActivityToken();
+ IActivityContainer container = mAm.createActivityContainer(homeActivityToken, null);
+ final int stackId = container.getStackId();
+ System.out.println("createStack returned new stackId=" + stackId + "\n");
+ container.attachToDisplay(displayId);
+ mAm.moveTaskToStack(taskId, stackId, true);
} catch (RemoteException e) {
}
}
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index f0c4c93..0f38095 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -612,15 +612,6 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
- case CREATE_STACK_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- int taskId = data.readInt();
- int res = createStack(taskId);
- reply.writeNoException();
- reply.writeInt(res);
- return true;
- }
-
case MOVE_TASK_TO_STACK_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
int taskId = data.readInt();
@@ -2027,6 +2018,26 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
reply.writeNoException();
return true;
}
+
+ case CREATE_ACTIVITY_CONTAINER_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IBinder parentActivityToken = data.readStrongBinder();
+ IActivityContainerCallback callback =
+ (IActivityContainerCallback) data.readStrongBinder();
+ IActivityContainer activityContainer =
+ createActivityContainer(parentActivityToken, callback);
+ reply.writeNoException();
+ reply.writeStrongBinder(activityContainer.asBinder());
+ return true;
+ }
+
+ case GET_HOME_ACTIVITY_TOKEN_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ IBinder homeActivityToken = getHomeActivityToken();
+ reply.writeNoException();
+ reply.writeStrongBinder(homeActivityToken);
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
@@ -2714,20 +2725,6 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
}
@Override
- public int createStack(int taskId) throws RemoteException
- {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeInt(taskId);
- mRemote.transact(CREATE_STACK_TRANSACTION, data, reply, 0);
- reply.readException();
- int res = reply.readInt();
- data.recycle();
- reply.recycle();
- return res;
- }
- @Override
public void moveTaskToStack(int taskId, int stackId, boolean toTop) throws RemoteException
{
Parcel data = Parcel.obtain();
@@ -4655,5 +4652,33 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
}
+ public IActivityContainer createActivityContainer(IBinder parentActivityToken,
+ IActivityContainerCallback callback) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(parentActivityToken);
+ data.writeStrongBinder((IBinder)callback);
+ mRemote.transact(CREATE_ACTIVITY_CONTAINER_TRANSACTION, data, reply, 0);
+ reply.readException();
+ IActivityContainer res =
+ IActivityContainer.Stub.asInterface(reply.readStrongBinder());
+ data.recycle();
+ reply.recycle();
+ return res;
+ }
+
+ public IBinder getHomeActivityToken() throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ mRemote.transact(GET_HOME_ACTIVITY_TOKEN_TRANSACTION, data, reply, 0);
+ reply.readException();
+ IBinder res = reply.readStrongBinder();
+ data.recycle();
+ reply.recycle();
+ return res;
+ }
+
private IBinder mRemote;
}
diff --git a/core/java/android/app/IActivityContainer.aidl b/core/java/android/app/IActivityContainer.aidl
new file mode 100644
index 0000000..2883d25
--- /dev/null
+++ b/core/java/android/app/IActivityContainer.aidl
@@ -0,0 +1,29 @@
+/**
+ * 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 android.app;
+
+import android.app.IActivityContainerCallback;
+import android.content.Intent;
+import android.os.IBinder;
+
+/** @hide */
+interface IActivityContainer {
+ void attachToDisplay(int displayId);
+ int getStackId();
+ void detachFromDisplay();
+ void startActivity(in Intent intent);
+}
diff --git a/core/java/android/app/IActivityContainerCallback.aidl b/core/java/android/app/IActivityContainerCallback.aidl
new file mode 100644
index 0000000..55c2001
--- /dev/null
+++ b/core/java/android/app/IActivityContainerCallback.aidl
@@ -0,0 +1,24 @@
+/**
+ * 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 android.app;
+
+import android.os.IBinder;
+
+/** @hide */
+interface IActivityContainerCallback {
+ oneway void onLastActivityRemoved(IBinder container);
+}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 631d9b1..4be1945 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -118,7 +118,6 @@ public interface IActivityManager extends IInterface {
public void moveTaskToBack(int task) throws RemoteException;
public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) throws RemoteException;
public void moveTaskBackwards(int task) throws RemoteException;
- public int createStack(int taskId) throws RemoteException;
public void moveTaskToStack(int taskId, int stackId, boolean toTop) throws RemoteException;
public void resizeStack(int stackId, Rect bounds) throws RemoteException;
public List<StackInfo> getAllStackInfos() throws RemoteException;
@@ -408,6 +407,11 @@ public interface IActivityManager extends IInterface {
public void performIdleMaintenance() throws RemoteException;
+ public IActivityContainer createActivityContainer(IBinder parentActivityToken,
+ IActivityContainerCallback callback) throws RemoteException;
+
+ public IBinder getHomeActivityToken() throws RemoteException;
+
/*
* Private non-Binder interfaces
*/
@@ -678,7 +682,7 @@ public interface IActivityManager extends IInterface {
int KILL_UID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+164;
int SET_USER_IS_MONKEY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+165;
int HANG_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+166;
- int CREATE_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+167;
+ int CREATE_ACTIVITY_CONTAINER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+167;
int MOVE_TASK_TO_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+168;
int RESIZE_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+169;
int GET_ALL_STACK_INFOS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+170;
@@ -694,4 +698,5 @@ public interface IActivityManager extends IInterface {
int RELEASE_PERSISTABLE_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+180;
int GET_PERSISTED_URI_PERMISSIONS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+181;
int APP_NOT_RESPONDING_VIA_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+182;
+ int GET_HOME_ACTIVITY_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+183;
}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 05666b4..4540c1c 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -28,13 +28,15 @@ import static org.xmlpull.v1.XmlPullParser.START_TAG;
import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
import android.app.AppOpsManager;
+import android.app.IActivityContainer;
+import android.app.IActivityContainerCallback;
import android.appwidget.AppWidgetManager;
import android.graphics.Rect;
import android.util.ArrayMap;
-import android.view.Display;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IAppOpsService;
+import com.android.internal.app.ProcessMap;
import com.android.internal.app.ProcessStats;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.BatteryStatsImpl;
@@ -47,7 +49,6 @@ import com.android.internal.util.Preconditions;
import com.android.server.AppOpsService;
import com.android.server.AttributeCache;
import com.android.server.IntentResolver;
-import com.android.internal.app.ProcessMap;
import com.android.server.SystemServer;
import com.android.server.Watchdog;
import com.android.server.am.ActivityStack.ActivityState;
@@ -1770,7 +1771,6 @@ public final class ActivityManagerService extends ActivityManagerNative
public void setWindowManager(WindowManagerService wm) {
mWindowManager = wm;
mStackSupervisor.setWindowManager(wm);
- wm.createStack(HOME_STACK_ID, Display.DEFAULT_DISPLAY);
}
public void startObservingNativeCrashes() {
@@ -1801,7 +1801,7 @@ public final class ActivityManagerService extends ActivityManagerNative
m.mFactoryTest = factoryTest;
m.mIntentFirewall = new IntentFirewall(m.new IntentFirewallInterface());
- m.mStackSupervisor = new ActivityStackSupervisor(m, context, thr.mLooper);
+ m.mStackSupervisor = new ActivityStackSupervisor(m);
m.mBatteryStatsService.publish(context);
m.mUsageStatsService.publish(context);
@@ -7096,22 +7096,28 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
- public int createStack(int taskId) {
+ public IBinder getHomeActivityToken() throws RemoteException {
enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
- "createStack()");
- if (DEBUG_STACK) Slog.d(TAG, "createStack: taskId=" + taskId);
+ "getHomeActivityToken()");
synchronized (this) {
- long ident = Binder.clearCallingIdentity();
- try {
- int stackId = mStackSupervisor.createStack();
- mWindowManager.createStack(stackId, Display.DEFAULT_DISPLAY);
- if (taskId > 0) {
- moveTaskToStack(taskId, stackId, true);
- }
- return stackId;
- } finally {
- Binder.restoreCallingIdentity(ident);
+ return mStackSupervisor.getHomeActivityToken();
+ }
+ }
+
+ @Override
+ public IActivityContainer createActivityContainer(IBinder parentActivityToken,
+ IActivityContainerCallback callback) throws RemoteException {
+ enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
+ "createActivityContainer()");
+ synchronized (this) {
+ if (parentActivityToken == null) {
+ throw new IllegalArgumentException("parent token must not be null");
}
+ ActivityRecord r = ActivityRecord.forToken(parentActivityToken);
+ if (r == null) {
+ return null;
+ }
+ return mStackSupervisor.createActivityContainer(r, callback);
}
}
@@ -7150,11 +7156,11 @@ public final class ActivityManagerService extends ActivityManagerNative
@Override
public List<StackInfo> getAllStackInfos() {
enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
- "getStackBoxes()");
+ "getAllStackInfos()");
long ident = Binder.clearCallingIdentity();
try {
synchronized (this) {
- return mStackSupervisor.getAllStackInfos();
+ return mStackSupervisor.getAllStackInfosLocked();
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -7168,7 +7174,7 @@ public final class ActivityManagerService extends ActivityManagerNative
long ident = Binder.clearCallingIdentity();
try {
synchronized (this) {
- return mStackSupervisor.getStackInfo(stackId);
+ return mStackSupervisor.getStackInfoLocked(stackId);
}
} finally {
Binder.restoreCallingIdentity(ident);
@@ -14049,18 +14055,21 @@ public final class ActivityManagerService extends ActivityManagerNative
boolean kept = true;
final ActivityStack mainStack = mStackSupervisor.getFocusedStack();
- if (changes != 0 && starting == null) {
- // If the configuration changed, and the caller is not already
- // in the process of starting an activity, then find the top
- // activity to check if its configuration needs to change.
- starting = mainStack.topRunningActivityLocked(null);
- }
-
- if (starting != null) {
- kept = mainStack.ensureActivityConfigurationLocked(starting, changes);
- // And we need to make sure at this point that all other activities
- // are made visible with the correct configuration.
- mStackSupervisor.ensureActivitiesVisibleLocked(starting, changes);
+ // mainStack is null during startup.
+ if (mainStack != null) {
+ if (changes != 0 && starting == null) {
+ // If the configuration changed, and the caller is not already
+ // in the process of starting an activity, then find the top
+ // activity to check if its configuration needs to change.
+ starting = mainStack.topRunningActivityLocked(null);
+ }
+
+ if (starting != null) {
+ kept = mainStack.ensureActivityConfigurationLocked(starting, changes);
+ // And we need to make sure at this point that all other activities
+ // are made visible with the correct configuration.
+ mStackSupervisor.ensureActivitiesVisibleLocked(starting, changes);
+ }
}
if (values != null && mWindowManager != null) {
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index 49f29fe..38b01df 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -21,6 +21,7 @@ import com.android.internal.R.styleable;
import com.android.internal.app.ResolverActivity;
import com.android.server.AttributeCache;
import com.android.server.am.ActivityStack.ActivityState;
+import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
import android.app.ActivityOptions;
import android.app.ResultInfo;
@@ -138,6 +139,7 @@ final class ActivityRecord {
boolean forceNewConfig; // force re-create with new config next time
int launchCount; // count of launches since last state
long lastLaunchTime; // time of last lauch of this activity
+ ArrayList<ActivityStack> mChildContainers = new ArrayList<ActivityStack>();
String stringName; // for caching of toString().
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 82d29a9..690574c 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -39,6 +39,7 @@ import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
import com.android.internal.os.BatteryStatsImpl;
import com.android.server.Watchdog;
import com.android.server.am.ActivityManagerService.ItemMatcher;
+import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
import com.android.server.wm.AppTransition;
import com.android.server.wm.TaskGroup;
import com.android.server.wm.WindowManagerService;
@@ -52,7 +53,6 @@ import android.app.IThumbnailReceiver;
import android.app.ResultInfo;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.ComponentName;
-import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
@@ -139,8 +139,6 @@ final class ActivityStack {
final ActivityManagerService mService;
final WindowManagerService mWindowManager;
- final Context mContext;
-
/**
* The back history of all previous (and possibly still
* running) activities. It contains #TaskRecord objects.
@@ -230,6 +228,8 @@ final class ActivityStack {
final int mStackId;
+ final ActivityContainer mActivityContainer;
+
/** Run all ActivityStacks through this */
final ActivityStackSupervisor mStackSupervisor;
@@ -327,14 +327,14 @@ final class ActivityStack {
return count;
}
- ActivityStack(ActivityManagerService service, Context context, Looper looper, int stackId) {
- mHandler = new ActivityStackHandler(looper);
- mService = service;
- mWindowManager = service.mWindowManager;
- mStackSupervisor = service.mStackSupervisor;
- mContext = context;
- mStackId = stackId;
- mCurrentUser = service.mCurrentUserId;
+ ActivityStack(ActivityStackSupervisor.ActivityContainer activityContainer) {
+ mActivityContainer = activityContainer;
+ mStackSupervisor = activityContainer.getOuter();
+ mService = mStackSupervisor.mService;
+ mHandler = new ActivityStackHandler(mService.mHandler.getLooper());
+ mWindowManager = mService.mWindowManager;
+ mStackId = activityContainer.mStackId;
+ mCurrentUser = mService.mCurrentUserId;
}
boolean okToShow(ActivityRecord r) {
@@ -436,25 +436,6 @@ final class ActivityStack {
return null;
}
- boolean containsApp(ProcessRecord app) {
- if (app == null) {
- return false;
- }
- for (int taskNdx = mTaskHistory.size() - 1; 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.finishing) {
- continue;
- }
- if (r.app == app) {
- return true;
- }
- }
- }
- return false;
- }
-
final boolean updateLRUListLocked(ActivityRecord r) {
final boolean hadit = mLRUActivities.remove(r);
mLRUActivities.add(r);
@@ -465,6 +446,13 @@ final class ActivityStack {
return mStackId == HOME_STACK_ID;
}
+ ArrayList<ActivityStack> getStacksLocked() {
+ if (mActivityContainer.isAttached()) {
+ return mActivityContainer.mActivityDisplayInfo.stacks;
+ }
+ return null;
+ }
+
/**
* Returns the top activity in any existing task matching the given
* Intent. Returns null if no such task is found.
diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java
index 4a46288..f1ac7fe 100644
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/java/com/android/server/am/ActivityStackSupervisor.java
@@ -37,6 +37,8 @@ import android.app.ActivityManager;
import android.app.ActivityManager.StackInfo;
import android.app.ActivityOptions;
import android.app.AppGlobals;
+import android.app.IActivityContainer;
+import android.app.IActivityContainerCallback;
import android.app.IActivityManager;
import android.app.IApplicationThread;
import android.app.IThumbnailReceiver;
@@ -54,6 +56,9 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
+import android.graphics.Point;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManager.DisplayListener;
import android.os.Binder;
import android.os.Bundle;
import android.os.Debug;
@@ -69,9 +74,11 @@ import android.os.SystemClock;
import android.os.UserHandle;
import android.util.EventLog;
import android.util.Slog;
-import android.util.SparseIntArray;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
import android.view.Display;
+import android.view.DisplayInfo;
import com.android.internal.app.HeavyWeightSwitcherActivity;
import com.android.internal.os.TransferPipe;
import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
@@ -84,7 +91,7 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
-public final class ActivityStackSupervisor {
+public final class ActivityStackSupervisor implements DisplayListener {
static final boolean DEBUG = ActivityManagerService.DEBUG || false;
static final boolean DEBUG_ADD_REMOVE = DEBUG || false;
static final boolean DEBUG_APP = DEBUG || false;
@@ -108,19 +115,22 @@ public final class ActivityStackSupervisor {
static final int RESUME_TOP_ACTIVITY_MSG = FIRST_SUPERVISOR_STACK_MSG + 2;
static final int SLEEP_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 3;
static final int LAUNCH_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 4;
+ static final int HANDLE_DISPLAY_ADDED = FIRST_SUPERVISOR_STACK_MSG + 5;
+ static final int HANDLE_DISPLAY_CHANGED = FIRST_SUPERVISOR_STACK_MSG + 6;
+ static final int HANDLE_DISPLAY_REMOVED = FIRST_SUPERVISOR_STACK_MSG + 7;
+
// For debugging to make sure the caller when acquiring/releasing our
// wake lock is the system process.
static final boolean VALIDATE_WAKE_LOCK_CALLER = false;
final ActivityManagerService mService;
- final Context mContext;
- final Looper mLooper;
final ActivityStackSupervisorHandler mHandler;
/** Short cut */
WindowManagerService mWindowManager;
+ DisplayManager mDisplayManager;
/** Dismiss the keyguard after the next activity is displayed? */
boolean mDismissKeyguardOnNextActivity = false;
@@ -143,14 +153,10 @@ public final class ActivityStackSupervisor {
* DO NOT ACCESS DIRECTLY - It may be null, use getFocusedStack() */
private ActivityStack mFocusedStack;
- /** All the non-launcher stacks */
- private ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
-
- private static final int STACK_STATE_HOME_IN_FRONT = 0;
- private static final int STACK_STATE_HOME_TO_BACK = 1;
- private static final int STACK_STATE_HOME_IN_BACK = 2;
- private static final int STACK_STATE_HOME_TO_FRONT = 3;
- private int mStackState = STACK_STATE_HOME_IN_FRONT;
+ /** If this is the same as mFocusedStack then the activity on the top of the focused stack has
+ * been resumed. If stacks are changing position this will hold the old stack until the new
+ * stack becomes resumed after which it will be set to the new stack. */
+ private ActivityStack mLastFocusedStack;
/** List of activities that are waiting for a new activity to become visible before completing
* whatever operation they are supposed to do. */
@@ -207,14 +213,17 @@ public final class ActivityStackSupervisor {
/** Stack id of the front stack when user switched, indexed by userId. */
SparseIntArray mUserStackInFront = new SparseIntArray(2);
- public ActivityStackSupervisor(ActivityManagerService service, Context context,
- Looper looper) {
+ /** Mapping from (ActivityStack/TaskStack).mStackId to their current state */
+ SparseArray<ActivityContainer> mActivityContainers = new SparseArray<ActivityContainer>();
+
+ /** Mapping from displayId to display current state */
+ SparseArray<ActivityDisplayInfo> mDisplayInfos = new SparseArray<ActivityDisplayInfo>();
+
+ public ActivityStackSupervisor(ActivityManagerService service) {
mService = service;
- mContext = context;
- mLooper = looper;
- PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+ PowerManager pm = (PowerManager)mService.mContext.getSystemService(Context.POWER_SERVICE);
mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
- mHandler = new ActivityStackSupervisorHandler(looper);
+ mHandler = new ActivityStackSupervisorHandler(mService.mHandler.getLooper());
if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
throw new IllegalStateException("Calling must be system uid");
}
@@ -224,9 +233,23 @@ public final class ActivityStackSupervisor {
}
void setWindowManager(WindowManagerService wm) {
- mWindowManager = wm;
- mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID);
- mStacks.add(mHomeStack);
+ synchronized (mService) {
+ mWindowManager = wm;
+
+ mDisplayManager =
+ (DisplayManager)mService.mContext.getSystemService(Context.DISPLAY_SERVICE);
+ mDisplayManager.registerDisplayListener(this, null);
+
+ Display[] displays = mDisplayManager.getDisplays();
+ for (int displayNdx = displays.length - 1; displayNdx >= 0; --displayNdx) {
+ final int displayId = displays[displayNdx].getDisplayId();
+ ActivityDisplayInfo info = new ActivityDisplayInfo(displayId);
+ mDisplayInfos.put(displayId, info);
+ }
+
+ createStackOnDisplay(null, HOME_STACK_ID, Display.DEFAULT_DISPLAY);
+ mHomeStack = mFocusedStack = mLastFocusedStack = getStack(HOME_STACK_ID);
+ }
}
void dismissKeyguard() {
@@ -238,43 +261,38 @@ public final class ActivityStackSupervisor {
}
ActivityStack getFocusedStack() {
- if (mFocusedStack == null) {
- return mHomeStack;
- }
- switch (mStackState) {
- case STACK_STATE_HOME_IN_FRONT:
- case STACK_STATE_HOME_TO_FRONT:
- return mHomeStack;
- case STACK_STATE_HOME_IN_BACK:
- case STACK_STATE_HOME_TO_BACK:
- default:
- return mFocusedStack;
- }
+ return mFocusedStack;
}
ActivityStack getLastStack() {
- switch (mStackState) {
- case STACK_STATE_HOME_IN_FRONT:
- case STACK_STATE_HOME_TO_BACK:
- return mHomeStack;
- case STACK_STATE_HOME_TO_FRONT:
- case STACK_STATE_HOME_IN_BACK:
- default:
- return mFocusedStack;
- }
+ return mLastFocusedStack;
}
+ // TODO: Split into two methods isFrontStack for any visible stack and isFrontmostStack for the
+ // top of all visible stacks.
boolean isFrontStack(ActivityStack stack) {
- return !(stack.isHomeStack() ^ getFocusedStack().isHomeStack());
+ ArrayList<ActivityStack> stacks = stack.getStacksLocked();
+ if (stacks != null && !stacks.isEmpty()) {
+ return stack == stacks.get(stacks.size() - 1);
+ }
+ return false;
}
void moveHomeStack(boolean toFront) {
- final boolean homeInFront = isFrontStack(mHomeStack);
- if (homeInFront ^ toFront) {
- if (DEBUG_STACK) Slog.d(TAG, "moveHomeTask: mStackState old=" +
- stackStateToString(mStackState) + " new=" + stackStateToString(homeInFront ?
- STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT));
- mStackState = homeInFront ? STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT;
+ ArrayList<ActivityStack> stacks = mHomeStack.getStacksLocked();
+ int topNdx = stacks.size() - 1;
+ if (topNdx <= 0) {
+ return;
+ }
+ ActivityStack topStack = stacks.get(topNdx);
+ final boolean homeInFront = topStack == mHomeStack;
+ if (homeInFront != toFront) {
+ mLastFocusedStack = topStack;
+ stacks.remove(mHomeStack);
+ stacks.add(toFront ? topNdx : 0, mHomeStack);
+ mFocusedStack = stacks.get(topNdx);
+ if (DEBUG_STACK) Slog.d(TAG, "moveHomeTask: topStack old=" + topStack + " new="
+ + mFocusedStack);
}
}
@@ -302,21 +320,29 @@ public final class ActivityStackSupervisor {
}
TaskRecord anyTaskForIdLocked(int id) {
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- ActivityStack stack = mStacks.get(stackNdx);
- TaskRecord task = stack.taskForIdLocked(id);
- if (task != null) {
- return task;
+ int numDisplays = mDisplayInfos.size();
+ for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+ ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ ActivityStack stack = stacks.get(stackNdx);
+ TaskRecord task = stack.taskForIdLocked(id);
+ if (task != null) {
+ return task;
+ }
}
}
return null;
}
ActivityRecord isInAnyStackLocked(IBinder token) {
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityRecord r = mStacks.get(stackNdx).isInStackLocked(token);
- if (r != null) {
- return r;
+ int numDisplays = mDisplayInfos.size();
+ for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+ ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityRecord r = stacks.get(stackNdx).isInStackLocked(token);
+ if (r != null) {
+ return r;
+ }
}
}
return null;
@@ -341,14 +367,11 @@ public final class ActivityStackSupervisor {
}
if (stack.removeTask(task) && !stack.isHomeStack()) {
if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing stack " + stack);
- mStacks.remove(stack);
+ stack.mActivityContainer.detachLocked();
final int stackId = stack.mStackId;
final int nextStackId = mWindowManager.removeStack(stackId);
// TODO: Perhaps we need to let the ActivityManager determine the next focus...
- if (mFocusedStack == null || mFocusedStack.mStackId == stackId) {
- // If this is the last app stack, set mFocusedStack to null.
- mFocusedStack = nextStackId == HOME_STACK_ID ? null : getStack(nextStackId);
- }
+ mFocusedStack = getStack(nextStackId);
}
}
@@ -368,25 +391,28 @@ public final class ActivityStackSupervisor {
}
boolean attachApplicationLocked(ProcessRecord app) throws Exception {
- boolean didSomething = false;
final String processName = app.processName;
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- if (!isFrontStack(stack)) {
- continue;
- }
- ActivityRecord hr = stack.topRunningActivityLocked(null);
- if (hr != null) {
- if (hr.app == null && app.uid == hr.info.applicationInfo.uid
- && processName.equals(hr.processName)) {
- try {
- if (realStartActivityLocked(hr, app, true, true)) {
- didSomething = true;
+ boolean didSomething = false;
+ for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
+ ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ if (!isFrontStack(stack)) {
+ continue;
+ }
+ ActivityRecord hr = stack.topRunningActivityLocked(null);
+ if (hr != null) {
+ if (hr.app == null && app.uid == hr.info.applicationInfo.uid
+ && processName.equals(hr.processName)) {
+ try {
+ if (realStartActivityLocked(hr, app, true, true)) {
+ didSomething = true;
+ }
+ } catch (Exception e) {
+ Slog.w(TAG, "Exception in new application when starting activity "
+ + hr.intent.getComponent().flattenToShortString(), e);
+ throw e;
}
- } catch (Exception e) {
- Slog.w(TAG, "Exception in new application when starting activity "
- + hr.intent.getComponent().flattenToShortString(), e);
- throw e;
}
}
}
@@ -398,53 +424,52 @@ public final class ActivityStackSupervisor {
}
boolean allResumedActivitiesIdle() {
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- if (!isFrontStack(stack)) {
- continue;
- }
- final ActivityRecord resumedActivity = stack.mResumedActivity;
- if (resumedActivity == null || !resumedActivity.idle) {
- return false;
+ for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
+ ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ if (!isFrontStack(stack)) {
+ continue;
+ }
+ final ActivityRecord resumedActivity = stack.mResumedActivity;
+ if (resumedActivity == null || !resumedActivity.idle) {
+ return false;
+ }
}
}
return true;
}
boolean allResumedActivitiesComplete() {
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- if (isFrontStack(stack)) {
- final ActivityRecord r = stack.mResumedActivity;
- if (r != null && r.state != ActivityState.RESUMED) {
- return false;
+ for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
+ ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ if (isFrontStack(stack)) {
+ final ActivityRecord r = stack.mResumedActivity;
+ if (r != null && r.state != ActivityState.RESUMED) {
+ return false;
+ }
}
}
}
// TODO: Not sure if this should check if all Paused are complete too.
- switch (mStackState) {
- case STACK_STATE_HOME_TO_BACK:
- if (DEBUG_STACK) Slog.d(TAG, "allResumedActivitiesComplete: mStackState old=" +
- stackStateToString(STACK_STATE_HOME_TO_BACK) + " new=" +
- stackStateToString(STACK_STATE_HOME_IN_BACK));
- mStackState = STACK_STATE_HOME_IN_BACK;
- break;
- case STACK_STATE_HOME_TO_FRONT:
- if (DEBUG_STACK) Slog.d(TAG, "allResumedActivitiesComplete: mStackState old=" +
- stackStateToString(STACK_STATE_HOME_TO_FRONT) + " new=" +
- stackStateToString(STACK_STATE_HOME_IN_FRONT));
- mStackState = STACK_STATE_HOME_IN_FRONT;
- break;
- }
+ if (DEBUG_STACK) Slog.d(TAG,
+ "allResumedActivitiesComplete: mLastFocusedStack changing from=" +
+ mLastFocusedStack + " to=" + mFocusedStack);
+ mLastFocusedStack = mFocusedStack;
return true;
}
boolean allResumedActivitiesVisible() {
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- final ActivityRecord r = stack.mResumedActivity;
- if (r != null && (!r.nowVisible || r.waitingVisible)) {
- return false;
+ for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
+ ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityRecord r = stack.mResumedActivity;
+ if (r != null && (!r.nowVisible || r.waitingVisible)) {
+ return false;
+ }
}
}
return true;
@@ -457,13 +482,16 @@ public final class ActivityStackSupervisor {
*/
boolean pauseBackStacks(boolean userLeaving) {
boolean someActivityPaused = false;
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- if (!isFrontStack(stack) && stack.mResumedActivity != null) {
- if (DEBUG_STATES) Slog.d(TAG, "pauseBackStacks: stack=" + stack +
- " mResumedActivity=" + stack.mResumedActivity);
- stack.startPausingLocked(userLeaving, false);
- someActivityPaused = true;
+ for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
+ ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ if (!isFrontStack(stack) && stack.mResumedActivity != null) {
+ if (DEBUG_STATES) Slog.d(TAG, "pauseBackStacks: stack=" + stack +
+ " mResumedActivity=" + stack.mResumedActivity);
+ stack.startPausingLocked(userLeaving, false);
+ someActivityPaused = true;
+ }
}
}
return someActivityPaused;
@@ -471,17 +499,20 @@ public final class ActivityStackSupervisor {
boolean allPausedActivitiesComplete() {
boolean pausing = true;
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- final ActivityRecord r = stack.mPausingActivity;
- if (r != null && r.state != ActivityState.PAUSED
- && r.state != ActivityState.STOPPED
- && r.state != ActivityState.STOPPING) {
- if (DEBUG_STATES) {
- Slog.d(TAG, "allPausedActivitiesComplete: r=" + r + " state=" + r.state);
- pausing = false;
- } else {
- return false;
+ for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
+ ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ final ActivityRecord r = stack.mPausingActivity;
+ if (r != null && r.state != ActivityState.PAUSED
+ && r.state != ActivityState.STOPPED
+ && r.state != ActivityState.STOPPING) {
+ if (DEBUG_STATES) {
+ Slog.d(TAG, "allPausedActivitiesComplete: r=" + r + " state=" + r.state);
+ pausing = false;
+ } else {
+ return false;
+ }
}
}
}
@@ -523,8 +554,10 @@ public final class ActivityStackSupervisor {
return r;
}
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
+ // Return to the home stack.
+ final ArrayList<ActivityStack> stacks = mHomeStack.getStacksLocked();
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
if (stack != focusedStack && isFrontStack(stack)) {
r = stack.topRunningActivityLocked(null);
if (r != null) {
@@ -540,15 +573,19 @@ public final class ActivityStackSupervisor {
ActivityRecord r = null;
// Gather all of the running tasks for each stack into runningTaskLists.
- final int numStacks = mStacks.size();
- ArrayList<RunningTaskInfo>[] runningTaskLists = new ArrayList[numStacks];
- for (int stackNdx = numStacks - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- ArrayList<RunningTaskInfo> stackTaskList = new ArrayList<RunningTaskInfo>();
- runningTaskLists[stackNdx] = stackTaskList;
- final ActivityRecord ar = stack.getTasksLocked(receiver, pending, stackTaskList);
- if (isFrontStack(stack)) {
- r = ar;
+ ArrayList<ArrayList<RunningTaskInfo>> runningTaskLists =
+ new ArrayList<ArrayList<RunningTaskInfo>>();
+ final int numDisplays = mDisplayInfos.size();
+ for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+ ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ ArrayList<RunningTaskInfo> stackTaskList = new ArrayList<RunningTaskInfo>();
+ runningTaskLists.add(stackTaskList);
+ final ActivityRecord ar = stack.getTasksLocked(receiver, pending, stackTaskList);
+ if (r == null && isFrontStack(stack)) {
+ r = ar;
+ }
}
}
@@ -557,8 +594,9 @@ public final class ActivityStackSupervisor {
while (maxNum > 0) {
long mostRecentActiveTime = Long.MIN_VALUE;
ArrayList<RunningTaskInfo> selectedStackList = null;
- for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- ArrayList<RunningTaskInfo> stackTaskList = runningTaskLists[stackNdx];
+ final int numTaskLists = runningTaskLists.size();
+ for (int stackNdx = 0; stackNdx < numTaskLists; ++stackNdx) {
+ ArrayList<RunningTaskInfo> stackTaskList = runningTaskLists.get(stackNdx);
if (!stackTaskList.isEmpty()) {
final long lastActiveTime = stackTaskList.get(0).lastActiveTime;
if (lastActiveTime > mostRecentActiveTime) {
@@ -1264,7 +1302,7 @@ public final class ActivityStackSupervisor {
if (mFocusedStack != taskStack) {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
"adjustStackFocus: Setting focused stack to r=" + r + " task=" + task);
- mFocusedStack = taskStack.isHomeStack() ? null : taskStack;
+ mFocusedStack = taskStack;
} else {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
"adjustStackFocus: Focused stack already=" + mFocusedStack);
@@ -1272,24 +1310,28 @@ public final class ActivityStackSupervisor {
return taskStack;
}
- if (mFocusedStack != null) {
+ if (mFocusedStack != mHomeStack) {
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
"adjustStackFocus: Have a focused stack=" + mFocusedStack);
return mFocusedStack;
}
- for (int stackNdx = mStacks.size() - 1; stackNdx > 0; --stackNdx) {
- ActivityStack stack = mStacks.get(stackNdx);
- if (!stack.isHomeStack()) {
- if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
- "adjustStackFocus: Setting focused stack=" + stack);
- mFocusedStack = stack;
- return mFocusedStack;
+ int numDisplays = mDisplayInfos.size();
+ for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
+ ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ ActivityStack stack = stacks.get(stackNdx);
+ if (!stack.isHomeStack()) {
+ if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
+ "adjustStackFocus: Setting focused stack=" + stack);
+ mFocusedStack = stack;
+ return mFocusedStack;
+ }
}
}
- // Time to create the first app stack for this user.
- int stackId = mService.createStack(-1);
+ // Need to create an app stack for this user.
+ int stackId = createStackOnDisplay(null, getNextStackId(), Display.DEFAULT_DISPLAY);
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, "adjustStackFocus: New stack r=" + r +
" stackId=" + stackId);
mFocusedStack = getStack(stackId);
@@ -1299,30 +1341,10 @@ public final class ActivityStackSupervisor {
}
void setFocusedStack(ActivityRecord r) {
- if (r == null) {
- return;
- }
- if (!r.isApplicationActivity() || (r.task != null && !r.task.isApplicationTask())) {
- if (mStackState != STACK_STATE_HOME_IN_FRONT) {
- if (DEBUG_STACK || DEBUG_FOCUS) Slog.d(TAG, "setFocusedStack: mStackState old=" +
- stackStateToString(mStackState) + " new=" +
- stackStateToString(STACK_STATE_HOME_TO_FRONT) +
- " Callers=" + Debug.getCallers(3));
- mStackState = STACK_STATE_HOME_TO_FRONT;
- }
- } else {
- if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
- "setFocusedStack: Setting focused stack to r=" + r + " task=" + r.task +
- " Callers=" + Debug.getCallers(3));
- final ActivityStack taskStack = r.task.stack;
- mFocusedStack = taskStack.isHomeStack() ? null : taskStack;
- if (mStackState != STACK_STATE_HOME_IN_BACK) {
- if (DEBUG_STACK) Slog.d(TAG, "setFocusedStack: mStackState old=" +
- stackStateToString(mStackState) + " new=" +
- stackStateToString(STACK_STATE_HOME_TO_BACK) +
- " Callers=" + Debug.getCallers(3));
- mStackState = STACK_STATE_HOME_TO_BACK;
- }
+ if (r != null) {
+ final boolean isHomeActivity =
+ !r.isApplicationActivity() || (r.task != null && !r.task.isApplicationTask());
+ moveHomeStack(isHomeActivity);
}
}
@@ -1938,17 +1960,21 @@ public final class ActivityStackSupervisor {
boolean handleAppDiedLocked(ProcessRecord app) {
boolean hasVisibleActivities = false;
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- hasVisibleActivities |= mStacks.get(stackNdx).handleAppDiedLocked(app);
+ for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ hasVisibleActivities |= stacks.get(stackNdx).handleAppDiedLocked(app);
+ }
}
return hasVisibleActivities;
}
void closeSystemDialogsLocked() {
- final int numStacks = mStacks.size();
- for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- stack.closeSystemDialogsLocked();
+ for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ stacks.get(stackNdx).closeSystemDialogsLocked();
+ }
}
}
@@ -1961,11 +1987,14 @@ public final class ActivityStackSupervisor {
*/
boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
boolean didSomething = false;
- final int numStacks = mStacks.size();
- for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
- didSomething = true;
+ for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ final int numStacks = stacks.size();
+ for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
+ didSomething = true;
+ }
}
}
return didSomething;
@@ -1980,15 +2009,18 @@ public final class ActivityStackSupervisor {
// we don't blow away the previous app if this activity is being
// hosted by the process that is actually still the foreground.
ProcessRecord fgApp = null;
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- if (isFrontStack(stack)) {
- if (stack.mResumedActivity != null) {
- fgApp = stack.mResumedActivity.app;
- } else if (stack.mPausingActivity != null) {
- fgApp = stack.mPausingActivity.app;
+ for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ if (isFrontStack(stack)) {
+ if (stack.mResumedActivity != null) {
+ fgApp = stack.mResumedActivity.app;
+ } else if (stack.mPausingActivity != null) {
+ fgApp = stack.mPausingActivity.app;
+ }
+ break;
}
- break;
}
}
@@ -2012,13 +2044,16 @@ public final class ActivityStackSupervisor {
targetStack = getFocusedStack();
}
boolean result = false;
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- if (isFrontStack(stack)) {
- if (stack == targetStack) {
- result = stack.resumeTopActivityLocked(target, targetOptions);
- } else {
- stack.resumeTopActivityLocked(null);
+ for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ if (isFrontStack(stack)) {
+ if (stack == targetStack) {
+ result = stack.resumeTopActivityLocked(target, targetOptions);
+ } else {
+ stack.resumeTopActivityLocked(null);
+ }
}
}
}
@@ -2026,38 +2061,91 @@ public final class ActivityStackSupervisor {
}
void finishTopRunningActivityLocked(ProcessRecord app) {
- final int numStacks = mStacks.size();
- for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- stack.finishTopRunningActivityLocked(app);
+ for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ final int numStacks = stacks.size();
+ for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ stack.finishTopRunningActivityLocked(app);
+ }
}
}
void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
- if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack=" +
- mStacks.get(stackNdx));
- return;
+ for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ if (stacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
+ if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack="
+ + stacks.get(stackNdx));
+ return;
+ }
}
}
}
ActivityStack getStack(int stackId) {
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- if (stack.getStackId() == stackId) {
- return stack;
- }
+ ActivityContainer activityContainer = mActivityContainers.get(stackId);
+ if (activityContainer != null) {
+ return activityContainer.mStack;
}
return null;
}
ArrayList<ActivityStack> getStacks() {
- return new ArrayList<ActivityStack>(mStacks);
+ ArrayList<ActivityStack> allStacks = new ArrayList<ActivityStack>();
+ for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
+ allStacks.addAll(mDisplayInfos.valueAt(displayNdx).stacks);
+ }
+ return allStacks;
+ }
+
+ IBinder getHomeActivityToken() {
+ final ArrayList<TaskRecord> tasks = mHomeStack.getAllTasks();
+ for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = tasks.get(taskNdx);
+ if (task.isHomeTask()) {
+ final ArrayList<ActivityRecord> activities = task.mActivities;
+ for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
+ final ActivityRecord r = activities.get(activityNdx);
+ if (r.isHomeActivity()) {
+ return r.appToken;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ ActivityContainer createActivityContainer(ActivityRecord parentActivity, int stackId,
+ IActivityContainerCallback callback) {
+ ActivityContainer activityContainer = new ActivityContainer(parentActivity, stackId,
+ callback);
+ mActivityContainers.put(stackId, activityContainer);
+ if (parentActivity != null) {
+ parentActivity.mChildContainers.add(activityContainer.mStack);
+ }
+ return activityContainer;
+ }
+
+ ActivityContainer createActivityContainer(ActivityRecord parentActivity,
+ IActivityContainerCallback callback) {
+ return createActivityContainer(parentActivity, getNextStackId(), callback);
+ }
+
+ private int createStackOnDisplay(ActivityRecord parentActivity, int stackId, int displayId) {
+ ActivityDisplayInfo displayInfo = mDisplayInfos.get(displayId);
+ if (displayInfo == null) {
+ return -1;
+ }
+
+ ActivityContainer activityContainer =
+ createActivityContainer(parentActivity, stackId, null);
+ activityContainer.attachToDisplayLocked(displayInfo);
+ return stackId;
}
- int createStack() {
+ int getNextStackId() {
while (true) {
if (++mLastStackId <= HOME_STACK_ID) {
mLastStackId = HOME_STACK_ID + 1;
@@ -2066,7 +2154,6 @@ public final class ActivityStackSupervisor {
break;
}
}
- mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId));
return mLastStackId;
}
@@ -2088,15 +2175,18 @@ public final class ActivityStackSupervisor {
ActivityRecord findTaskLocked(ActivityRecord r) {
if (DEBUG_TASKS) Slog.d(TAG, "Looking for task of " + r);
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- if (!r.isApplicationActivity() && !stack.isHomeStack()) {
- if (DEBUG_TASKS) Slog.d(TAG, "Skipping stack: " + stack);
- continue;
- }
- final ActivityRecord ar = stack.findTaskLocked(r);
- if (ar != null) {
- return ar;
+ for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ if (!r.isApplicationActivity() && !stack.isHomeStack()) {
+ if (DEBUG_TASKS) Slog.d(TAG, "Skipping stack: " + stack);
+ continue;
+ }
+ final ActivityRecord ar = stack.findTaskLocked(r);
+ if (ar != null) {
+ return ar;
+ }
}
}
if (DEBUG_TASKS) Slog.d(TAG, "No task found");
@@ -2104,10 +2194,13 @@ public final class ActivityStackSupervisor {
}
ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityRecord ar = mStacks.get(stackNdx).findActivityLocked(intent, info);
- if (ar != null) {
- return ar;
+ for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityRecord ar = stacks.get(stackNdx).findActivityLocked(intent, info);
+ if (ar != null) {
+ return ar;
+ }
}
}
return null;
@@ -2135,8 +2228,11 @@ public final class ActivityStackSupervisor {
final long endTime = System.currentTimeMillis() + timeout;
while (true) {
boolean cantShutdown = false;
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- cantShutdown |= mStacks.get(stackNdx).checkReadyForSleepLocked();
+ for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ cantShutdown |= stacks.get(stackNdx).checkReadyForSleepLocked();
+ }
}
if (cantShutdown) {
long timeRemaining = endTime - System.currentTimeMillis();
@@ -2167,11 +2263,14 @@ public final class ActivityStackSupervisor {
if (mGoingToSleep.isHeld()) {
mGoingToSleep.release();
}
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- stack.awakeFromSleepingLocked();
- if (isFrontStack(stack)) {
- resumeTopActivitiesLocked();
+ for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ stack.awakeFromSleepingLocked();
+ if (isFrontStack(stack)) {
+ resumeTopActivitiesLocked();
+ }
}
}
mGoingToSleepActivities.clear();
@@ -2190,8 +2289,11 @@ public final class ActivityStackSupervisor {
if (!mSleepTimeout) {
boolean dontSleep = false;
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- dontSleep |= mStacks.get(stackNdx).checkReadyForSleepLocked();
+ for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ dontSleep |= stacks.get(stackNdx).checkReadyForSleepLocked();
+ }
}
if (mStoppingActivities.size() > 0) {
@@ -2214,8 +2316,11 @@ public final class ActivityStackSupervisor {
}
}
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- mStacks.get(stackNdx).goToSleep();
+ for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ stacks.get(stackNdx).goToSleep();
+ }
}
removeSleepTimeouts();
@@ -2242,37 +2347,45 @@ public final class ActivityStackSupervisor {
}
void handleAppCrashLocked(ProcessRecord app) {
- final int numStacks = mStacks.size();
- for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- stack.handleAppCrashLocked(app);
+ for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ final int numStacks = stacks.size();
+ for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ stack.handleAppCrashLocked(app);
+ }
}
}
void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
// First the front stacks. In case any are not fullscreen and are in front of home.
boolean showHomeBehindStack = false;
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- if (isFrontStack(stack)) {
- showHomeBehindStack =
- stack.ensureActivitiesVisibleLocked(starting, configChanges);
- }
- }
- // Now do back stacks.
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- if (!isFrontStack(stack)) {
- stack.ensureActivitiesVisibleLocked(starting, configChanges, showHomeBehindStack);
+ for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ final int topStackNdx = stacks.size() - 1;
+ for (int stackNdx = topStackNdx; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ if (stackNdx == topStackNdx) {
+ // Top stack.
+ showHomeBehindStack =
+ stack.ensureActivitiesVisibleLocked(starting, configChanges);
+ } else {
+ // Back stack.
+ stack.ensureActivitiesVisibleLocked(starting, configChanges,
+ showHomeBehindStack);
+ }
}
}
}
void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
- final int numStacks = mStacks.size();
- for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- stack.scheduleDestroyActivities(app, false, reason);
+ for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ final int numStacks = stacks.size();
+ for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ stack.scheduleDestroyActivities(app, false, reason);
+ }
}
}
@@ -2282,8 +2395,11 @@ public final class ActivityStackSupervisor {
mCurrentUser = userId;
mStartingUsers.add(uss);
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- mStacks.get(stackNdx).switchUserLocked(userId);
+ for (int displayNdx = mDisplayInfos.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ stacks.get(stackNdx).switchUserLocked(userId);
+ }
}
ActivityStack stack = getStack(restoreStackId);
@@ -2337,8 +2453,9 @@ public final class ActivityStackSupervisor {
}
void validateTopActivitiesLocked() {
- for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
+ // FIXME
+/* for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
final ActivityRecord r = stack.topRunningActivityLocked(null);
final ActivityState state = r == null ? ActivityState.DESTROYED : r.state;
if (isFrontStack(stack)) {
@@ -2368,23 +2485,14 @@ public final class ActivityStackSupervisor {
}
}
}
- }
-
- private static String stackStateToString(int stackState) {
- switch (stackState) {
- case STACK_STATE_HOME_IN_FRONT: return "STACK_STATE_HOME_IN_FRONT";
- case STACK_STATE_HOME_TO_BACK: return "STACK_STATE_HOME_TO_BACK";
- case STACK_STATE_HOME_IN_BACK: return "STACK_STATE_HOME_IN_BACK";
- case STACK_STATE_HOME_TO_FRONT: return "STACK_STATE_HOME_TO_FRONT";
- default: return "Unknown stackState=" + stackState;
- }
+*/
}
public void dump(PrintWriter pw, String prefix) {
pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity=");
pw.println(mDismissKeyguardOnNextActivity);
pw.print(prefix); pw.print("mFocusedStack=" + mFocusedStack);
- pw.print(" mStackState="); pw.println(stackStateToString(mStackState));
+ pw.print(" mLastFocusedStack="); pw.println(mLastFocusedStack);
pw.print(prefix); pw.println("mSleepTimeout=" + mSleepTimeout);
pw.print(prefix); pw.println("mCurTaskId=" + mCurTaskId);
pw.print(prefix); pw.println("mUserStackInFront=" + mUserStackInFront);
@@ -2413,42 +2521,48 @@ public final class ActivityStackSupervisor {
boolean dumpClient, String dumpPackage) {
boolean printed = false;
boolean needSep = false;
- final int numStacks = mStacks.size();
- for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
- final ActivityStack stack = mStacks.get(stackNdx);
- StringBuilder stackHeader = new StringBuilder(128);
- stackHeader.append(" Stack #");
- stackHeader.append(mStacks.indexOf(stack));
- stackHeader.append(":");
- printed |= stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage, needSep,
- stackHeader.toString());
- printed |= dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll,
- false, dumpPackage, true, " Running activities (most recent first):", null);
-
- needSep = printed;
- boolean pr = printThisActivity(pw, stack.mPausingActivity, dumpPackage, needSep,
- " mPausingActivity: ");
- if (pr) {
- printed = true;
- needSep = false;
- }
- pr = printThisActivity(pw, stack.mResumedActivity, dumpPackage, needSep,
- " mResumedActivity: ");
- if (pr) {
- printed = true;
- needSep = false;
- }
- if (dumpAll) {
- pr = printThisActivity(pw, stack.mLastPausedActivity, dumpPackage, needSep,
- " mLastPausedActivity: ");
+ for (int displayNdx = 0; displayNdx < mDisplayInfos.size(); ++displayNdx) {
+ ActivityDisplayInfo info = mDisplayInfos.valueAt(displayNdx);
+ pw.print("Display #"); pw.println(info.mDisplayId);
+ ArrayList<ActivityStack> stacks = info.stacks;
+ final int numStacks = stacks.size();
+ for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ StringBuilder stackHeader = new StringBuilder(128);
+ stackHeader.append(" Stack #");
+ stackHeader.append(stack.mStackId);
+ stackHeader.append(":");
+ printed |= stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage,
+ needSep, stackHeader.toString());
+ printed |= dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false,
+ !dumpAll, false, dumpPackage, true,
+ " Running activities (most recent first):", null);
+
+ needSep = printed;
+ boolean pr = printThisActivity(pw, stack.mPausingActivity, dumpPackage, needSep,
+ " mPausingActivity: ");
+ if (pr) {
+ printed = true;
+ needSep = false;
+ }
+ pr = printThisActivity(pw, stack.mResumedActivity, dumpPackage, needSep,
+ " mResumedActivity: ");
if (pr) {
printed = true;
- needSep = true;
+ needSep = false;
+ }
+ if (dumpAll) {
+ pr = printThisActivity(pw, stack.mLastPausedActivity, dumpPackage, needSep,
+ " mLastPausedActivity: ");
+ if (pr) {
+ printed = true;
+ needSep = true;
+ }
+ printed |= printThisActivity(pw, stack.mLastNoHistoryActivity, dumpPackage,
+ needSep, " mLastNoHistoryActivity: ");
}
- printed |= printThisActivity(pw, stack.mLastNoHistoryActivity, dumpPackage,
- needSep, " mLastNoHistoryActivity: ");
+ needSep = printed;
}
- needSep = printed;
}
printed |= dumpHistoryList(fd, pw, mFinishingActivities, " ", "Fin", false, !dumpAll,
@@ -2578,6 +2692,95 @@ public final class ActivityStackSupervisor {
mHandler.sendEmptyMessageDelayed(SLEEP_TIMEOUT_MSG, SLEEP_TIMEOUT);
}
+ @Override
+ public void onDisplayAdded(int displayId) {
+ mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_ADDED, displayId, 0));
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_REMOVED, displayId, 0));
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_CHANGED, displayId, 0));
+ }
+
+ public void handleDisplayAddedLocked(int displayId) {
+ synchronized (mService) {
+ ActivityDisplayInfo info = new ActivityDisplayInfo(displayId);
+ mDisplayInfos.put(displayId, info);
+ }
+ mWindowManager.onDisplayAdded(displayId);
+ }
+
+ public void handleDisplayRemovedLocked(int displayId) {
+ synchronized (mService) {
+ ActivityDisplayInfo info = mDisplayInfos.get(displayId);
+ if (info != null) {
+ ArrayList<ActivityStack> stacks = info.stacks;
+ for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
+ info.detachActivities(stacks.get(stackNdx));
+ }
+ mDisplayInfos.remove(displayId);
+ }
+ }
+ mWindowManager.onDisplayRemoved(displayId);
+ }
+
+ public void handleDisplayChangedLocked(int displayId) {
+ synchronized (mService) {
+ ActivityDisplayInfo info = mDisplayInfos.get(displayId);
+ if (info != null) {
+ // TODO: Update the bounds.
+ }
+ }
+ mWindowManager.onDisplayChanged(displayId);
+ }
+
+ StackInfo getStackInfo(ActivityStack stack) {
+ StackInfo info = new StackInfo();
+ mWindowManager.getStackBounds(stack.mStackId, info.bounds);
+ info.displayId = Display.DEFAULT_DISPLAY;
+ info.stackId = stack.mStackId;
+
+ ArrayList<TaskRecord> tasks = stack.getAllTasks();
+ final int numTasks = tasks.size();
+ int[] taskIds = new int[numTasks];
+ String[] taskNames = new String[numTasks];
+ for (int i = 0; i < numTasks; ++i) {
+ final TaskRecord task = tasks.get(i);
+ taskIds[i] = task.taskId;
+ taskNames[i] = task.origActivity != null ? task.origActivity.flattenToString()
+ : task.realActivity != null ? task.realActivity.flattenToString()
+ : task.getTopActivity() != null ? task.getTopActivity().packageName
+ : "unknown";
+ }
+ info.taskIds = taskIds;
+ info.taskNames = taskNames;
+ return info;
+ }
+
+ StackInfo getStackInfoLocked(int stackId) {
+ ActivityStack stack = getStack(stackId);
+ if (stack != null) {
+ return getStackInfo(stack);
+ }
+ return null;
+ }
+
+ ArrayList<StackInfo> getAllStackInfosLocked() {
+ ArrayList<StackInfo> list = new ArrayList<StackInfo>();
+ for (int displayNdx = 0; displayNdx < mDisplayInfos.size(); ++displayNdx) {
+ ArrayList<ActivityStack> stacks = mDisplayInfos.valueAt(displayNdx).stacks;
+ for (int ndx = stacks.size() - 1; ndx >= 0; --ndx) {
+ list.add(getStackInfo(stacks.get(ndx)));
+ }
+ }
+ return list;
+ }
+
private final class ActivityStackSupervisorHandler extends Handler {
public ActivityStackSupervisorHandler(Looper looper) {
@@ -2641,46 +2844,131 @@ public final class ActivityStackSupervisor {
}
}
} break;
+ case HANDLE_DISPLAY_ADDED: {
+ handleDisplayAddedLocked(msg.arg1);
+ } break;
+ case HANDLE_DISPLAY_CHANGED: {
+ handleDisplayChangedLocked(msg.arg1);
+ } break;
+ case HANDLE_DISPLAY_REMOVED: {
+ handleDisplayRemovedLocked(msg.arg1);
+ } break;
}
}
}
- StackInfo getStackInfo(ActivityStack stack) {
- StackInfo info = new StackInfo();
- mWindowManager.getStackBounds(stack.mStackId, info.bounds);
- info.displayId = Display.DEFAULT_DISPLAY;
- info.stackId = stack.mStackId;
+ class ActivityContainer extends IActivityContainer.Stub {
+ final int mStackId;
+ final IActivityContainerCallback mCallback;
+ final ActivityStack mStack;
+ final ActivityRecord mParentActivity;
- ArrayList<TaskRecord> tasks = stack.getAllTasks();
- final int numTasks = tasks.size();
- int[] taskIds = new int[numTasks];
- String[] taskNames = new String[numTasks];
- for (int i = 0; i < numTasks; ++i) {
- final TaskRecord task = tasks.get(i);
- taskIds[i] = task.taskId;
- taskNames[i] = task.origActivity != null ? task.origActivity.flattenToString()
- : task.realActivity != null ? task.realActivity.flattenToString()
- : task.getTopActivity() != null ? task.getTopActivity().packageName
- : "unknown";
+ /** Display this ActivityStack is currently on. Null if not attached to a Display. */
+ ActivityDisplayInfo mActivityDisplayInfo;
+
+ ActivityContainer(ActivityRecord parentActivity, int stackId,
+ IActivityContainerCallback callback) {
+ synchronized (mService) {
+ mStackId = stackId;
+ mStack = new ActivityStack(this);
+ mParentActivity = parentActivity;
+ mCallback = callback;
+ }
}
- info.taskIds = taskIds;
- info.taskNames = taskNames;
- return info;
- }
- StackInfo getStackInfo(int stackId) {
- ActivityStack stack = getStack(stackId);
- if (stack != null) {
- return getStackInfo(stack);
+ void attachToDisplayLocked(ActivityDisplayInfo displayInfo) {
+ mActivityDisplayInfo = displayInfo;
+ displayInfo.attachActivities(mStack);
+ mWindowManager.createStack(mStackId, displayInfo.mDisplayId);
+ }
+
+ @Override
+ public void attachToDisplay(int displayId) throws RemoteException {
+ synchronized (mService) {
+ ActivityDisplayInfo displayInfo = mDisplayInfos.get(displayId);
+ if (displayInfo == null) {
+ return;
+ }
+ attachToDisplayLocked(displayInfo);
+ }
+ }
+
+ @Override
+ public int getStackId() throws RemoteException {
+ return mStack.mStackId;
+ }
+
+ void detachLocked() {
+ if (mActivityDisplayInfo != null) {
+ mActivityDisplayInfo.detachActivities(mStack);
+ mActivityDisplayInfo = null;
+ }
+ }
+
+ @Override
+ public void detachFromDisplay() throws RemoteException {
+ synchronized (mService) {
+ detachLocked();
+ }
+ }
+
+ @Override
+ public void startActivity(Intent intent) throws RemoteException {
+
+ }
+
+ @Override
+ public IBinder asBinder() {
+ return this;
+ }
+
+ ActivityStackSupervisor getOuter() {
+ return ActivityStackSupervisor.this;
+ }
+
+ boolean isAttached() {
+ return mActivityDisplayInfo != null;
+ }
+
+ void getBounds(Point outBounds) {
+ if (mActivityDisplayInfo != null) {
+ mActivityDisplayInfo.getBounds(outBounds);
+ } else {
+ outBounds.set(0, 0);
+ }
}
- return null;
}
- ArrayList<StackInfo> getAllStackInfos() {
- ArrayList<StackInfo> list = new ArrayList<StackInfo>();
- for (int ndx = mStacks.size() - 1; ndx >= 0; --ndx) {
- list.add(getStackInfo(mStacks.get(ndx)));
+ /** Exactly one of these classes per Display in the system. Capable of holding zero or more
+ * attached {@link ActivityStack}s */
+ final class ActivityDisplayInfo {
+ /** Actual Display this object tracks. */
+ final int mDisplayId;
+ final Display mDisplay;
+ final DisplayInfo mDisplayInfo = new DisplayInfo();
+
+ /** All of the stacks on this display. Order matters, topmost stack is in front of all other
+ * stacks, bottommost behind. Accessed directly by ActivityManager package classes */
+ final ArrayList<ActivityStack> stacks = new ArrayList<ActivityStack>();
+
+ ActivityDisplayInfo(int displayId) {
+ mDisplayId = displayId;
+ mDisplay = mDisplayManager.getDisplay(displayId);
+ mDisplay.getDisplayInfo(mDisplayInfo);
+ }
+
+ void attachActivities(ActivityStack stack) {
+ stacks.add(stack);
+ }
+
+ void detachActivities(ActivityStack stack) {
+ stacks.remove(stack);
+ }
+
+ void getBounds(Point bounds) {
+ mDisplay.getDisplayInfo(mDisplayInfo);
+ bounds.x = mDisplayInfo.appWidth;
+ bounds.y = mDisplayInfo.appHeight;
}
- return list;
}
}
diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java
index 4352ece..4064377 100644
--- a/services/java/com/android/server/wm/DisplayContent.java
+++ b/services/java/com/android/server/wm/DisplayContent.java
@@ -27,6 +27,7 @@ import android.util.EventLog;
import android.util.Slog;
import android.view.Display;
import android.view.DisplayInfo;
+import android.view.Surface;
import com.android.server.EventLogTags;
import java.io.PrintWriter;
@@ -211,10 +212,15 @@ class DisplayContent {
void getLogicalDisplayRect(Rect out) {
updateDisplayInfo();
// Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked.
+ final int orientation = mDisplayInfo.rotation;
+ boolean rotated = (orientation == Surface.ROTATION_90
+ || orientation == Surface.ROTATION_270);
+ final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
+ final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
int width = mDisplayInfo.logicalWidth;
- int left = (mBaseDisplayWidth - width) / 2;
+ int left = (physWidth - width) / 2;
int height = mDisplayInfo.logicalHeight;
- int top = (mBaseDisplayHeight - height) / 2;
+ int top = (physHeight - height) / 2;
out.set(left, top, left + width, top + height);
}
@@ -247,8 +253,12 @@ class DisplayContent {
mStacks.add(toTop ? mStacks.size() : 0, stack);
}
- TaskStack topStack() {
- return mStacks.get(mStacks.size() - 1);
+ TaskStack removeStack(TaskStack stack) {
+ mStacks.remove(stack);
+ if (!mStacks.isEmpty()) {
+ return mStacks.get(mStacks.size() - 1);
+ }
+ return null;
}
/**
diff --git a/services/java/com/android/server/wm/TaskStack.java b/services/java/com/android/server/wm/TaskStack.java
index df1d108..ef245f9 100644
--- a/services/java/com/android/server/wm/TaskStack.java
+++ b/services/java/com/android/server/wm/TaskStack.java
@@ -205,7 +205,11 @@ public class TaskStack {
mAnimationBackgroundSurface.destroySurface();
mDimLayer.destroySurface();
EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId);
- return mDisplayContent.topStack().mStackId;
+ TaskStack next = mDisplayContent.removeStack(this);
+ if (next != null) {
+ return next.mStackId;
+ }
+ return -1;
}
void resetAnimationBackgroundAnimator() {
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index e50d61f..04129e2 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -4842,7 +4842,9 @@ public class WindowManagerService extends IWindowManager.Stub
int nextStackId = stack.remove();
stack.getDisplayContent().layoutNeeded = true;
requestTraversalLocked();
- return nextStackId;
+ if (nextStackId > HOME_STACK_ID) {
+ return nextStackId;
+ }
}
if (DEBUG_STACK) Slog.i(TAG, "removeStack: could not find stackId=" + stackId);
}
@@ -8778,7 +8780,8 @@ public class WindowManagerService extends IWindowManager.Stub
if (canBeSeen) {
// This function assumes that the contents of the default display are
// processed first before secondary displays.
- if (w.mDisplayContent.isDefaultDisplay) {
+ final DisplayContent displayContent = w.mDisplayContent;
+ if (displayContent.isDefaultDisplay) {
// While a dream or keyguard is showing, obscure ordinary application
// content on secondary displays (by forcibly enabling mirroring unless
// there is other content we want to show) but still allow opaque