summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCraig Mautner <cmautner@google.com>2013-04-17 01:58:15 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2013-04-17 01:58:15 +0000
commit53078b25c91660e30849861e88da1a33998c554f (patch)
tree7a953bff348848c49c1582ecb2c961fa9fe01537
parente76dd37bdb75e7ed757e1284249c64f0c58e869d (diff)
parent967212cb542e6eeb308678367b53381bff984c31 (diff)
downloadframeworks_base-53078b25c91660e30849861e88da1a33998c554f.zip
frameworks_base-53078b25c91660e30849861e88da1a33998c554f.tar.gz
frameworks_base-53078b25c91660e30849861e88da1a33998c554f.tar.bz2
Merge "Implement stack splitting and task movement."
-rw-r--r--cmds/am/src/com/android/commands/am/Am.java94
-rw-r--r--core/java/android/app/ActivityManager.java72
-rw-r--r--core/java/android/app/ActivityManagerNative.java25
-rw-r--r--core/java/android/app/IActivityManager.java5
-rw-r--r--core/java/android/view/WindowManagerPolicy.java8
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindowManager.java26
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java56
-rw-r--r--services/java/com/android/server/am/ActivityStack.java4
-rw-r--r--services/java/com/android/server/am/ActivityStackSupervisor.java14
-rw-r--r--services/java/com/android/server/wm/DimLayer.java14
-rw-r--r--services/java/com/android/server/wm/DisplayContent.java37
-rw-r--r--services/java/com/android/server/wm/StackBox.java203
-rw-r--r--services/java/com/android/server/wm/TaskStack.java14
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java51
-rw-r--r--services/java/com/android/server/wm/WindowState.java15
15 files changed, 503 insertions, 135 deletions
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index ccb9e1f..5f5c337 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -74,6 +74,7 @@ public class Am extends BaseCommand {
(new Am()).run(args);
}
+ @Override
public void onShowUsage(PrintStream out) {
out.println(
"usage: am [subcommand] [options]\n" +
@@ -99,6 +100,9 @@ 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 <RELATIVE_STACK_ID> <POSITION> <WEIGHT>\n" +
+ " am stack movetask <STACK_ID> <TASK_ID> [true|false]\n" +
+ " am stack dump\n" +
"\n" +
"am start: start an Activity. Options are:\n" +
" -D: enable debugging\n" +
@@ -181,6 +185,16 @@ public class Am extends BaseCommand {
"am stop-user: stop execution of USER_ID, not allowing it to run any\n" +
" code until a later explicit switch to it.\n" +
"\n" +
+ "am stack create: create a new stack relative to an existing one.\n" +
+ " <RELATIVE_STACK_ID>: existing stack's id.\n" +
+ " <POSITION>: 0: to left of, 1: to right of, 2: above, 3: below\n" +
+ " <WEIGHT>: float between 0.2 and 0.8 inclusive.\n" +
+ "\n" +
+ "am stack movetask: move <TASK_ID> from its current stack to the top (true) or" +
+ " bottom (false) of <STACK_ID>.\n" +
+ "\n" +
+ "am stack dump: list the hierarchy of stacks.\n" +
+ "\n" +
"<INTENT> specifications include these flags and arguments:\n" +
" [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +
" [-c <CATEGORY> [-c <CATEGORY>] ...]\n" +
@@ -213,6 +227,7 @@ public class Am extends BaseCommand {
);
}
+ @Override
public void onRun() throws Exception {
mAm = ActivityManagerNative.getDefault();
@@ -259,6 +274,8 @@ public class Am extends BaseCommand {
runSwitchUser();
} else if (op.equals("stop-user")) {
runStopUser();
+ } else if (op.equals("stack")) {
+ runStack();
} else {
showError("Error: unknown command '" + op + "'");
}
@@ -1029,7 +1046,7 @@ public class Am extends BaseCommand {
}
@Override
- public boolean activityResuming(String pkg) throws RemoteException {
+ public boolean activityResuming(String pkg) {
synchronized (this) {
System.out.println("** Activity resuming: " + pkg);
}
@@ -1037,7 +1054,7 @@ public class Am extends BaseCommand {
}
@Override
- public boolean activityStarting(Intent intent, String pkg) throws RemoteException {
+ public boolean activityStarting(Intent intent, String pkg) {
synchronized (this) {
System.out.println("** Activity starting: " + pkg);
}
@@ -1046,7 +1063,7 @@ public class Am extends BaseCommand {
@Override
public boolean appCrashed(String processName, int pid, String shortMsg, String longMsg,
- long timeMillis, String stackTrace) throws RemoteException {
+ long timeMillis, String stackTrace) {
synchronized (this) {
System.out.println("** ERROR: PROCESS CRASHED");
System.out.println("processName: " + processName);
@@ -1063,8 +1080,7 @@ public class Am extends BaseCommand {
}
@Override
- public int appEarlyNotResponding(String processName, int pid, String annotation)
- throws RemoteException {
+ public int appEarlyNotResponding(String processName, int pid, String annotation) {
synchronized (this) {
System.out.println("** ERROR: EARLY PROCESS NOT RESPONDING");
System.out.println("processName: " + processName);
@@ -1077,8 +1093,7 @@ public class Am extends BaseCommand {
}
@Override
- public int appNotResponding(String processName, int pid, String processStats)
- throws RemoteException {
+ public int appNotResponding(String processName, int pid, String processStats) {
synchronized (this) {
System.out.println("** ERROR: PROCESS NOT RESPONDING");
System.out.println("processName: " + processName);
@@ -1326,7 +1341,7 @@ public class Am extends BaseCommand {
@Override
public void performReceive(Intent intent, int resultCode, String data, Bundle extras,
- boolean ordered, boolean sticky, int sendingUser) throws RemoteException {
+ boolean ordered, boolean sticky, int sendingUser) {
String line = "Broadcast completed: result=" + resultCode;
if (data != null) line = line + ", data=\"" + data + "\"";
if (extras != null) line = line + ", extras: " + extras;
@@ -1359,6 +1374,7 @@ public class Am extends BaseCommand {
mRawMode = rawMode;
}
+ @Override
public void instrumentationStatus(ComponentName name, int resultCode, Bundle results) {
synchronized (this) {
// pretty printer mode?
@@ -1381,6 +1397,7 @@ public class Am extends BaseCommand {
}
}
+ @Override
public void instrumentationFinished(ComponentName name, int resultCode,
Bundle results) {
synchronized (this) {
@@ -1421,4 +1438,65 @@ public class Am extends BaseCommand {
return true;
}
}
+
+ private void runStack() throws Exception {
+ String op = nextArgRequired();
+ if (op.equals("create")) {
+ runStackCreate();
+ } else if (op.equals("movetask")) {
+ runStackMoveTask();
+ } else if (op.equals("dump")) {
+ runStackDump();
+ } else {
+ showError("Error: unknown command '" + op + "'");
+ return;
+ }
+ }
+
+ private void runStackCreate() throws Exception {
+ String relativeToStr = nextArgRequired();
+ int relativeTo = Integer.valueOf(relativeToStr);
+ String positionStr = nextArgRequired();
+ int position = Integer.valueOf(positionStr);
+ String weightStr = nextArgRequired();
+ float weight = Float.valueOf(weightStr);
+
+ try {
+ int stackId = mAm.createStack(relativeTo, position, weight);
+ System.out.println("createStack returned " + stackId + "\n\n");
+ } catch (RemoteException e) {
+ }
+ }
+
+ private void runStackMoveTask() throws Exception {
+ String taskIdStr = nextArgRequired();
+ int taskId = Integer.valueOf(taskIdStr);
+ String stackIdStr = nextArgRequired();
+ int stackId = Integer.valueOf(stackIdStr);
+ String toTopStr = nextArgRequired();
+ final boolean toTop;
+ if ("true".equals(toTopStr)) {
+ toTop = true;
+ } else if ("false".equals(toTopStr)) {
+ toTop = false;
+ } else {
+ System.err.println("Error: bad toTop arg: " + toTopStr);
+ return;
+ }
+
+ try {
+ mAm.moveTaskToStack(taskId, stackId, toTop);
+ } catch (RemoteException e) {
+ }
+ }
+
+ private void runStackDump() throws Exception {
+ try {
+ List<ActivityManager.StackInfo> stacks = mAm.getStacks();
+ for (ActivityManager.StackInfo stack : stacks) {
+ System.out.println(stack);
+ }
+ } catch (RemoteException e) {
+ }
+ }
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index bb9e19f..729ebd7 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -31,9 +31,8 @@ import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Point;
-import android.hardware.display.DisplayManager;
+import android.graphics.Rect;
import android.hardware.display.DisplayManagerGlobal;
-import android.os.Binder;
import android.os.Bundle;
import android.os.Debug;
import android.os.Handler;
@@ -1229,7 +1228,74 @@ public class ActivityManager {
} catch (RemoteException e) {
}
}
-
+
+
+ /**
+ * Information you can retrieve about an ActivityStack in the system.
+ * @hide
+ */
+ public static class StackInfo implements Parcelable {
+ public int stackId;
+ public Rect bounds;
+ public int[] taskIds;
+ public String[] taskNames;
+
+ public StackInfo() {
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(stackId);
+ dest.writeInt(bounds.left);
+ dest.writeInt(bounds.top);
+ dest.writeInt(bounds.right);
+ dest.writeInt(bounds.bottom);
+ dest.writeIntArray(taskIds);
+ dest.writeStringArray(taskNames);
+ }
+
+ public void readFromParcel(Parcel source) {
+ stackId = source.readInt();
+ bounds = new Rect(
+ source.readInt(), source.readInt(), source.readInt(), source.readInt());
+ taskIds = source.createIntArray();
+ taskNames = source.createStringArray();
+ }
+
+ public static final Creator<StackInfo> CREATOR = new Creator<StackInfo>() {
+ @Override
+ public StackInfo createFromParcel(Parcel source) {
+ return new StackInfo(source);
+ }
+ @Override
+ public StackInfo[] newArray(int size) {
+ return new StackInfo[size];
+ }
+ };
+
+ private StackInfo(Parcel source) {
+ readFromParcel(source);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(256);
+ sb.append("Stack id="); sb.append(stackId);
+ sb.append(" bounds="); sb.append(bounds.toShortString()); sb.append("\n");
+ final String prefix = " ";
+ for (int i = 0; i < taskIds.length; ++i) {
+ sb.append(prefix); sb.append("taskId="); sb.append(taskIds[i]);
+ sb.append(": "); sb.append(taskNames[i]); sb.append("\n");
+ }
+ return sb.toString();
+ }
+ }
+
/**
* @hide
*/
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index f35584b..b089e2a 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -639,6 +639,14 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
+ case GET_STACKS_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ List<ActivityManager.StackInfo> list = getStacks();
+ reply.writeNoException();
+ reply.writeTypedList(list);
+ return true;
+ }
+
case GET_TASK_FOR_ACTIVITY_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder token = data.readStrongBinder();
@@ -2591,6 +2599,7 @@ class ActivityManagerProxy implements IActivityManager
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
data.writeInt(position);
data.writeInt(relativeStackId);
data.writeFloat(weight);
@@ -2606,6 +2615,7 @@ class ActivityManagerProxy implements IActivityManager
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
data.writeInt(taskId);
data.writeInt(stackId);
data.writeInt(toTop ? 1 : 0);
@@ -2619,6 +2629,7 @@ class ActivityManagerProxy implements IActivityManager
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
data.writeInt(stackId);
data.writeFloat(weight);
mRemote.transact(RESIZE_STACK_TRANSACTION, data, reply, 0);
@@ -2626,6 +2637,20 @@ class ActivityManagerProxy implements IActivityManager
data.recycle();
reply.recycle();
}
+ @Override
+ public List<ActivityManager.StackInfo> getStacks() throws RemoteException
+ {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ mRemote.transact(GET_STACKS_TRANSACTION, data, reply, 0);
+ reply.readException();
+ ArrayList<ActivityManager.StackInfo> list
+ = reply.createTypedArrayList(ActivityManager.StackInfo.CREATOR);
+ data.recycle();
+ reply.recycle();
+ return list;
+ }
public int getTaskForActivity(IBinder token, boolean onlyRoot) throws RemoteException
{
Parcel data = Parcel.obtain();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 1e74c60..c52a35a 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -18,6 +18,7 @@ package android.app;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityManager.RunningServiceInfo;
+import android.app.ActivityManager.StackInfo;
import android.content.ComponentName;
import android.content.ContentProviderNative;
import android.content.IContentProvider;
@@ -114,9 +115,10 @@ 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 position, int relativeStackId, float weight) throws RemoteException;
+ public int createStack(int relativeStackId, int position, float weight) throws RemoteException;
public void moveTaskToStack(int taskId, int stackId, boolean toTop) throws RemoteException;
public void resizeStack(int stackId, float weight) throws RemoteException;
+ public List<StackInfo> getStacks() throws RemoteException;
public int getTaskForActivity(IBinder token, boolean onlyRoot) throws RemoteException;
/* oneway */
public void reportThumbnail(IBinder token,
@@ -646,4 +648,5 @@ public interface IActivityManager extends IInterface {
int MOVE_TASK_TO_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+166;
int RESIZE_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+167;
int SET_USER_IS_MONKEY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+168;
+ int GET_STACKS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+169;
}
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index c0044b6..b9f9e80 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -816,6 +816,14 @@ public interface WindowManagerPolicy {
public int getSystemDecorRectLw(Rect systemRect);
/**
+ * Return the rectangle of the screen that is available for applications to run in.
+ * This will be called immediately after {@link #beginLayoutLw}.
+ *
+ * @param r The rectangle to be filled with the boundaries available to applications.
+ */
+ public void getContentRectLw(Rect r);
+
+ /**
* Called for each window attached to the window manager as layout is
* proceeding. The implementation of this function must take care of
* setting the window's frame, either here or in finishLayout().
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 2988727..0f719db 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -87,7 +87,6 @@ import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import android.view.WindowManagerPolicy;
import android.view.accessibility.AccessibilityEvent;
-import android.view.accessibility.AccessibilityManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
@@ -204,13 +203,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// Vibrator pattern for haptic feedback of virtual key press.
long[] mVirtualKeyVibePattern;
-
+
// Vibrator pattern for a short vibration.
long[] mKeyboardTapVibePattern;
// Vibrator pattern for haptic feedback during boot when safe mode is disabled.
long[] mSafeModeDisabledVibePattern;
-
+
// Vibrator pattern for haptic feedback during boot when safe mode is enabled.
long[] mSafeModeEnabledVibePattern;
@@ -277,7 +276,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
boolean mOrientationSensorEnabled = false;
int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
boolean mHasSoftInput = false;
-
+
int mPointerLocationMode = 0; // guarded by mLock
// The last window we were told about in focusChanged.
@@ -374,7 +373,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
static final Rect mTmpContentFrame = new Rect();
static final Rect mTmpVisibleFrame = new Rect();
static final Rect mTmpNavigationFrame = new Rect();
-
+
WindowState mTopFullscreenOpaqueWindowState;
boolean mTopIsFullscreen;
boolean mForceStatusBar;
@@ -532,12 +531,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
updateRotation(false);
}
}
-
+
class MyOrientationListener extends WindowOrientationListener {
MyOrientationListener(Context context, Handler handler) {
super(context, handler);
}
-
+
@Override
public void onProposedRotationChanged(int rotation) {
if (localLOGV) Log.v(TAG, "onProposedRotationChanged, rotation=" + rotation);
@@ -1283,6 +1282,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
!= PackageManager.PERMISSION_GRANTED;
}
+ @Override
public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
switch (attrs.type) {
case TYPE_SYSTEM_OVERLAY:
@@ -1311,11 +1311,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
- private boolean isBuiltInKeyboardVisible() {
- return mHaveBuiltInKeyboard && !isHidden(mLidKeyboardAccessibility);
- }
-
/** {@inheritDoc} */
+ @Override
public void adjustConfigurationLw(Configuration config, int keyboardPresence,
int navigationPresence) {
mHaveBuiltInKeyboard = (keyboardPresence & PRESENCE_INTERNAL) != 0;
@@ -1340,6 +1337,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
/** {@inheritDoc} */
+ @Override
public int windowTypeToLayerLw(int type) {
if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
return 2;
@@ -2776,6 +2774,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
/** {@inheritDoc} */
+ @Override
public int getSystemDecorRectLw(Rect systemRect) {
systemRect.left = mSystemLeft;
systemRect.top = mSystemTop;
@@ -2786,6 +2785,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return 0;
}
+ @Override
+ public void getContentRectLw(Rect r) {
+ r.set(mContentLeft, mContentTop, mContentRight, mContentBottom);
+ }
+
void setAttachedWindowFrames(WindowState win, int fl, int adjust, WindowState attached,
boolean insetDecors, Rect pf, Rect df, Rect of, Rect cf, Rect vf) {
if (win.getSurfaceLayer() > mDockLayer && attached.getSurfaceLayer() < mDockLayer) {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 3d81135..52b933f 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -2866,11 +2866,11 @@ public final class ActivityManagerService extends ActivityManagerNative
/**
* This is the internal entry point for handling Activity.finish().
- *
+ *
* @param token The Binder token referencing the Activity we want to finish.
* @param resultCode Result code, if any, from this Activity.
* @param resultData Result data (Intent), if any, from this Activity.
- *
+ *
* @return Returns true if the activity successfully finished, or false if it is still running.
*/
@Override
@@ -2896,7 +2896,7 @@ public final class ActivityManagerService extends ActivityManagerNative
} catch (RemoteException e) {
mController = null;
}
-
+
if (!resumeOK) {
return false;
}
@@ -2921,12 +2921,12 @@ public final class ActivityManagerService extends ActivityManagerNative
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
-
+
synchronized(this) {
if (mHeavyWeightProcess == null) {
return;
}
-
+
ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>(
mHeavyWeightProcess.activities);
for (int i=0; i<activities.size(); i++) {
@@ -2936,13 +2936,13 @@ public final class ActivityManagerService extends ActivityManagerNative
null, "finish-heavy", true);
}
}
-
+
mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
mHeavyWeightProcess.userId, 0));
mHeavyWeightProcess = null;
}
}
-
+
@Override
public void crashApplication(int uid, int initialPid, String packageName,
String message) {
@@ -4632,6 +4632,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
+ @Override
public String getCallingPackage(IBinder token) {
synchronized (this) {
ActivityRecord r = getCallingRecordLocked(token);
@@ -4639,6 +4640,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
+ @Override
public ComponentName getCallingActivity(IBinder token) {
synchronized (this) {
ActivityRecord r = getCallingRecordLocked(token);
@@ -4665,6 +4667,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
+ @Override
public String getPackageForToken(IBinder token) {
synchronized(this) {
ActivityRecord r = ActivityRecord.isInStackLocked(token);
@@ -4675,6 +4678,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
+ @Override
public IIntentSender getIntentSender(int type,
String packageName, IBinder token, String resultWho,
int requestCode, Intent[] intents, String[] resolvedTypes,
@@ -5961,6 +5965,7 @@ public final class ActivityManagerService extends ActivityManagerNative
return list;
}
+ @Override
public List<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum,
int flags, int userId) {
userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
@@ -6262,7 +6267,10 @@ public final class ActivityManagerService extends ActivityManagerNative
@Override
public int createStack(int relativeStackId, int position, float weight) {
synchronized (this) {
- int stackId = mStackSupervisor.createStack(relativeStackId, position, weight);
+ if (mStackSupervisor.getStack(relativeStackId) == null) {
+ return -1;
+ }
+ int stackId = mStackSupervisor.createStack();
mWindowManager.createStack(stackId, relativeStackId, position, weight);
return stackId;
}
@@ -6271,8 +6279,8 @@ public final class ActivityManagerService extends ActivityManagerNative
@Override
public void moveTaskToStack(int taskId, int stackId, boolean toTop) {
synchronized (this) {
- mStackSupervisor.moveTaskToStack(taskId, stackId, toTop);
mWindowManager.moveTaskToStack(taskId, stackId, toTop);
+ mStackSupervisor.moveTaskToStack(taskId, stackId, toTop);
}
}
@@ -6282,6 +6290,36 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
+ public List<ActivityManager.StackInfo> getStacks() {
+ synchronized (this) {
+ ArrayList<ActivityManager.StackInfo> list = new ArrayList<ActivityManager.StackInfo>();
+ ArrayList<ActivityStack> stacks = mStackSupervisor.getStacks();
+ for (ActivityStack stack : stacks) {
+ ActivityManager.StackInfo stackInfo = new ActivityManager.StackInfo();
+ int stackId = stack.mStackId;
+ stackInfo.stackId = stackId;
+ stackInfo.bounds = mWindowManager.getStackBounds(stackId);
+ 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";
+ }
+ stackInfo.taskIds = taskIds;
+ stackInfo.taskNames = taskNames;
+ list.add(stackInfo);
+ }
+ return list;
+ }
+ }
+
+ @Override
public int getTaskForActivity(IBinder token, boolean onlyRoot) {
synchronized(this) {
return ActivityRecord.getTaskForActivityLocked(token, onlyRoot);
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 568689f..0ca5db5 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -1358,7 +1358,7 @@ final class ActivityStack {
// We need to start pausing the current activity so the top one
// can be resumed...
final ActivityStack lastStack = mStackSupervisor.getLastStack();
- if (lastStack.mResumedActivity != null) {
+ if ((isHomeStack() ^ lastStack.isHomeStack()) && lastStack.mResumedActivity != null) {
if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
// At this point we want to put the upcoming activity's process
// at the top of the LRU list, since we know we will be needing it
@@ -1464,7 +1464,7 @@ final class ActivityStack {
mService.mWindowManager.setAppWillBeHidden(prev.appToken);
mService.mWindowManager.setAppVisibility(prev.appToken, false);
}
- } else if (numActivities() > 1) {
+ } else {
if (DEBUG_TRANSITION) Slog.v(TAG,
"Prepare open transition: no previous");
if (mNoAnimActivities.contains(next)) {
diff --git a/services/java/com/android/server/am/ActivityStackSupervisor.java b/services/java/com/android/server/am/ActivityStackSupervisor.java
index d3e5b48..7b8ad43 100644
--- a/services/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/java/com/android/server/am/ActivityStackSupervisor.java
@@ -167,7 +167,7 @@ public class ActivityStackSupervisor {
}
boolean isFrontStack(ActivityStack stack) {
- return stack == getTopStack();
+ return !(stack.isHomeStack() ^ getTopStack().isHomeStack());
}
boolean homeIsInFront() {
@@ -299,10 +299,9 @@ public class ActivityStackSupervisor {
}
boolean allResumedActivitiesComplete() {
- final boolean homeInBack = !homeIsInFront();
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = mStacks.get(stackNdx);
- if (stack.isHomeStack() ^ homeInBack) {
+ if (isFrontStack(stack)) {
final ActivityRecord r = stack.mResumedActivity;
if (r != null && r.state != ActivityState.RESUMED) {
return false;
@@ -1512,7 +1511,7 @@ public class ActivityStackSupervisor {
}
}
- private ActivityStack getStack(int stackId) {
+ ActivityStack getStack(int stackId) {
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = mStacks.get(stackNdx);
if (stack.getStackId() == stackId) {
@@ -1522,7 +1521,11 @@ public class ActivityStackSupervisor {
return null;
}
- int createStack(int relativeStackId, int position, float weight) {
+ ArrayList<ActivityStack> getStacks() {
+ return new ArrayList<ActivityStack>(mStacks);
+ }
+
+ int createStack() {
synchronized (this) {
while (true) {
if (++mLastStackId <= HOME_STACK_ID) {
@@ -1545,6 +1548,7 @@ public class ActivityStackSupervisor {
return;
}
stack.moveTask(taskId, toTop);
+ stack.resumeTopActivityLocked(null);
}
ActivityRecord findTaskLocked(Intent intent, ActivityInfo info) {
diff --git a/services/java/com/android/server/wm/DimLayer.java b/services/java/com/android/server/wm/DimLayer.java
index 9bd36ba..91d6995 100644
--- a/services/java/com/android/server/wm/DimLayer.java
+++ b/services/java/com/android/server/wm/DimLayer.java
@@ -6,7 +6,6 @@ import android.graphics.PixelFormat;
import android.os.SystemClock;
import android.util.Slog;
import android.view.DisplayInfo;
-import android.view.Surface;
import android.view.SurfaceControl;
import java.io.PrintWriter;
@@ -255,15 +254,16 @@ public class DimLayer {
}
public void printTo(String prefix, PrintWriter pw) {
- pw.print(prefix); pw.print("mDimSurface="); pw.println(mDimSurface);
- pw.print(prefix); pw.print(" mLayer="); pw.print(mLayer);
+ pw.print(prefix); pw.print("mDimSurface="); pw.print(mDimSurface);
+ pw.print(" mLayer="); pw.print(mLayer);
pw.print(" mAlpha="); pw.println(mAlpha);
pw.print(prefix); pw.print("mLastDimWidth="); pw.print(mLastDimWidth);
- pw.print(" mLastDimWidth="); pw.println(mLastDimWidth);
- pw.print(prefix); pw.print("Last animation: mStartTime="); pw.print(mStartTime);
+ pw.print(" mLastDimHeight="); pw.println(mLastDimHeight);
+ pw.print(prefix); pw.print("Last animation: ");
pw.print(" mDuration="); pw.print(mDuration);
+ pw.print(" mStartTime="); pw.print(mStartTime);
pw.print(" curTime="); pw.println(SystemClock.uptimeMillis());
- pw.print(" mStartAlpha="); pw.println(mStartAlpha);
- pw.print(" mTargetAlpha="); pw.print(mTargetAlpha);
+ pw.print(prefix); pw.print(" mStartAlpha="); pw.print(mStartAlpha);
+ pw.print(" mTargetAlpha="); pw.println(mTargetAlpha);
}
}
diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java
index 5b2cf50..edf3d3b 100644
--- a/services/java/com/android/server/wm/DisplayContent.java
+++ b/services/java/com/android/server/wm/DisplayContent.java
@@ -167,10 +167,10 @@ class DisplayContent {
throw new IllegalArgumentException("createStack: First stackId not "
+ HOME_STACK_ID);
}
- StackBox newBox = new StackBox(this, new Rect(0, 0, mDisplayInfo.logicalWidth,
- mDisplayInfo.logicalHeight));
+ StackBox newBox = new StackBox(this, null);
mStackBoxes.add(newBox);
- newStack = new TaskStack(stackId, newBox);
+ newStack = new TaskStack(stackId, this);
+ newStack.mStackBox = newBox;
newBox.mStack = newStack;
mHomeStack = newStack;
} else {
@@ -181,8 +181,9 @@ class DisplayContent {
|| position == StackBox.TASK_STACK_GOES_UNDER) {
// Position indicates a new box is added at top level only.
if (box.contains(relativeStackId)) {
- StackBox newBox = new StackBox(this, box.mBounds);
- newStack = new TaskStack(stackId, newBox);
+ StackBox newBox = new StackBox(this, null);
+ newStack = new TaskStack(stackId, this);
+ newStack.mStackBox = newBox;
newBox.mStack = newStack;
final int offset = position == StackBox.TASK_STACK_GOES_OVER ? 1 : 0;
if (DEBUG_STACK) Slog.d(TAG, "createStack: inserting stack at " +
@@ -203,13 +204,15 @@ class DisplayContent {
+ " not found.");
}
}
+ if (newStack != null) {
+ layoutNeeded = true;
+ }
return newStack;
}
/** Refer to {@link WindowManagerService#resizeStack(int, float)} */
boolean resizeStack(int stackId, float weight) {
- int stackBoxNdx;
- for (stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
+ for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
final StackBox box = mStackBoxes.get(stackBoxNdx);
if (box.resize(stackId, weight)) {
return true;
@@ -250,6 +253,26 @@ class DisplayContent {
}
}
+ /**
+ * Propagate the new bounds to all child stack boxes, applying weights as we move down.
+ * @param contentRect The bounds to apply at the top level.
+ */
+ void setStackBoxSize(Rect contentRect) {
+ for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
+ mStackBoxes.get(stackBoxNdx).setStackBoxSizes(contentRect);
+ }
+ }
+
+ Rect getStackBounds(int stackId) {
+ for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
+ Rect bounds = mStackBoxes.get(stackBoxNdx).getStackBounds(stackId);
+ if (bounds != null) {
+ return bounds;
+ }
+ }
+ return null;
+ }
+
public void dump(String prefix, PrintWriter pw) {
pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
final String subPrefix = " " + prefix;
diff --git a/services/java/com/android/server/wm/StackBox.java b/services/java/com/android/server/wm/StackBox.java
index 9525d7c..bcc5137 100644
--- a/services/java/com/android/server/wm/StackBox.java
+++ b/services/java/com/android/server/wm/StackBox.java
@@ -24,12 +24,17 @@ import java.io.PrintWriter;
import java.util.ArrayList;
public class StackBox {
- /** For use with {@link WindowManagerService#createStack} */
- public static final int TASK_STACK_GOES_BEFORE = 0;
+ /** Used with {@link WindowManagerService#createStack}. To left of, lower l/r Rect values. */
+ public static final int TASK_STACK_GOES_BEFORE = 0; //
+ /** Used with {@link WindowManagerService#createStack}. To right of, higher l/r Rect values. */
public static final int TASK_STACK_GOES_AFTER = 1;
+ /** Used with {@link WindowManagerService#createStack}. Vertical: lower t/b Rect values. */
public static final int TASK_STACK_GOES_ABOVE = 2;
+ /** Used with {@link WindowManagerService#createStack}. Vertical: higher t/b Rect values. */
public static final int TASK_STACK_GOES_BELOW = 3;
+ /** Used with {@link WindowManagerService#createStack}. Put on a higher layer on display. */
public static final int TASK_STACK_GOES_OVER = 4;
+ /** Used with {@link WindowManagerService#createStack}. Put on a lower layer on display. */
public static final int TASK_STACK_GOES_UNDER = 5;
/** The display this box sits in. */
@@ -37,7 +42,7 @@ public class StackBox {
/** Non-null indicates this is mFirst or mSecond of a parent StackBox. Null indicates this
* is this entire size of mDisplayContent. */
- StackBox mParent;
+ final StackBox mParent;
/** First child, this is null exactly when mStack is non-null. */
StackBox mFirst;
@@ -49,20 +54,26 @@ public class StackBox {
TaskStack mStack;
/** Content limits relative to the DisplayContent this sits in. */
- Rect mBounds;
+ Rect mBounds = new Rect();
/** Relative orientation of mFirst and mSecond. */
boolean mVertical;
+ /** Fraction of mBounds to devote to mFirst, remainder goes to mSecond */
+ float mWeight;
+
/** Dirty flag. Something inside this or some descendant of this has changed. */
boolean layoutNeeded;
/** Used to keep from reallocating a temporary array to hold the list of Tasks below */
ArrayList<Task> mTmpTasks = new ArrayList<Task>();
- StackBox(DisplayContent displayContent, Rect bounds) {
+ /** Used to keep from reallocating a temporary Rect for propagating bounds to child boxes */
+ Rect mTmpRect = new Rect();
+
+ StackBox(DisplayContent displayContent, StackBox parent) {
mDisplayContent = displayContent;
- mBounds = bounds;
+ mParent = parent;
}
/** Propagate #layoutNeeded bottom up. */
@@ -83,7 +94,7 @@ public class StackBox {
}
/**
- * Detremine if a particular TaskStack is in this StackBox or any of its descendants.
+ * Determine if a particular TaskStack is in this StackBox or any of its descendants.
* @param stackId The TaskStack being considered.
* @return true if the specified TaskStack is in this box or its descendants. False otherwise.
*/
@@ -94,6 +105,30 @@ public class StackBox {
return mFirst.contains(stackId) || mSecond.contains(stackId);
}
+ /** Determine if the specified stack is the first child or second child. Presumes that this
+ * is called on mParent of the specified stack.
+ * @param stack the stack to determine.
+ * @return true if stack is the first child.
+ */
+ boolean isFirstChild(TaskStack stack) {
+ return mFirst.mStack == stack;
+ }
+
+ /** Returns the bounds of the specified TaskStack if it is contained in this StackBox.
+ * @param stackId the TaskStack to find the bounds of.
+ * @return a new Rect with the bounds of stackId if it is within this StackBox, null otherwise.
+ */
+ Rect getStackBounds(int stackId) {
+ if (mStack != null) {
+ return mStack.mStackId == stackId ? new Rect(mBounds) : null;
+ }
+ Rect bounds = mFirst.getStackBounds(stackId);
+ if (bounds != null) {
+ return bounds;
+ }
+ return mSecond.getStackBounds(stackId);
+ }
+
/**
* Create a new TaskStack relative to a specified one by splitting the StackBox containing
* the specified TaskStack into two children. The size and position each of the new StackBoxes
@@ -105,65 +140,65 @@ public class StackBox {
* @return The new TaskStack.
*/
TaskStack split(int stackId, int relativeStackId, int position, float weight) {
- if (mStack != null) {
- if (mStack.mStackId == relativeStackId) {
- // Found it!
- TaskStack stack = new TaskStack(stackId, this);
- TaskStack firstStack;
- TaskStack secondStack;
- int width, height, split;
- switch (position) {
- default:
- case TASK_STACK_GOES_BEFORE:
- case TASK_STACK_GOES_AFTER:
- mVertical = false;
- width = (int)(weight * mBounds.width());
- height = mBounds.height();
- if (position == TASK_STACK_GOES_BEFORE) {
- firstStack = stack;
- secondStack = mStack;
- split = mBounds.left + width;
- } else {
- firstStack = mStack;
- secondStack = stack;
- split = mBounds.right - width;
- }
- break;
- case TASK_STACK_GOES_ABOVE:
- case TASK_STACK_GOES_BELOW:
- mVertical = true;
- width = mBounds.width();
- height = (int)(weight * mBounds.height());
- if (position == TASK_STACK_GOES_ABOVE) {
- firstStack = stack;
- secondStack = mStack;
- split = mBounds.top + height;
- } else {
- firstStack = mStack;
- secondStack = stack;
- split = mBounds.bottom - height;
- }
- break;
- }
- mFirst = new StackBox(mDisplayContent, new Rect(mBounds.left, mBounds.top,
- mVertical ? mBounds.right : split, mVertical ? split : mBounds.bottom));
- mFirst.mStack = firstStack;
- mSecond = new StackBox(mDisplayContent, new Rect(mVertical ? mBounds.left : split,
- mVertical ? split : mBounds.top, mBounds.right, mBounds.bottom));
- mSecond.mStack = secondStack;
- mStack = null;
+ if (mStack == null) {
+ // Propagate the split to see if the target task stack is in either sub box.
+ TaskStack stack = mFirst.split(stackId, relativeStackId, position, weight);
+ if (stack != null) {
return stack;
}
- // Not the intended TaskStack.
+ return mSecond.split(stackId, relativeStackId, position, weight);
+ }
+
+ // This StackBox contains just a TaskStack.
+ if (mStack.mStackId != relativeStackId) {
+ // Barking down the wrong stack.
return null;
}
- // Propagate the split to see if the target task stack is in either sub box.
- TaskStack stack = mFirst.split(stackId, relativeStackId, position, weight);
- if (stack != null) {
- return stack;
+ // Found it!
+ TaskStack stack = new TaskStack(stackId, mDisplayContent);
+ TaskStack firstStack;
+ TaskStack secondStack;
+ switch (position) {
+ default:
+ case TASK_STACK_GOES_AFTER:
+ case TASK_STACK_GOES_BEFORE:
+ mVertical = false;
+ if (position == TASK_STACK_GOES_BEFORE) {
+ mWeight = weight;
+ firstStack = stack;
+ secondStack = mStack;
+ } else {
+ mWeight = 1.0f - weight;
+ firstStack = mStack;
+ secondStack = stack;
+ }
+ break;
+ case TASK_STACK_GOES_ABOVE:
+ case TASK_STACK_GOES_BELOW:
+ mVertical = true;
+ if (position == TASK_STACK_GOES_ABOVE) {
+ mWeight = weight;
+ firstStack = stack;
+ secondStack = mStack;
+ } else {
+ mWeight = 1.0f - weight;
+ firstStack = mStack;
+ secondStack = stack;
+ }
+ break;
}
- return mSecond.split(stackId, relativeStackId, position, weight);
+
+ mFirst = new StackBox(mDisplayContent, this);
+ firstStack.mStackBox = mFirst;
+ mFirst.mStack = firstStack;
+
+ mSecond = new StackBox(mDisplayContent, this);
+ secondStack.mStackBox = mSecond;
+ mSecond.mStack = secondStack;
+
+ mStack = null;
+ return stack;
}
/**
@@ -215,20 +250,57 @@ public class StackBox {
return mParent.getStackId();
}
- /** TODO: */
boolean resize(int stackId, float weight) {
+ if (mStack == null) {
+ return mFirst.resize(stackId, weight) || mSecond.resize(stackId, weight);
+ }
+ if (mStack.mStackId == stackId) {
+ mParent.mWeight = mParent.isFirstChild(mStack) ? weight : 1.0f - weight;
+ return true;
+ }
return false;
}
+ /** If this is a terminal StackBox (contains a TaskStack) set the bounds.
+ * @param bounds The rectangle to set the bounds to.
+ * @return True if the bounds changed, false otherwise. */
+ boolean setStackBoxSizes(Rect bounds) {
+ boolean change;
+ if (mStack != null) {
+ change = !mBounds.equals(bounds);
+ mBounds.set(bounds);
+ } else {
+ mTmpRect.set(bounds);
+ if (mVertical) {
+ final int height = bounds.height();
+ int firstHeight = (int)(height * mWeight);
+ mTmpRect.bottom = bounds.top + firstHeight;
+ change = mFirst.setStackBoxSizes(mTmpRect);
+ mTmpRect.top = mTmpRect.bottom;
+ mTmpRect.bottom = bounds.top + height;
+ change |= mSecond.setStackBoxSizes(mTmpRect);
+ } else {
+ final int width = bounds.width();
+ int firstWidth = (int)(width * mWeight);
+ mTmpRect.right = bounds.left + firstWidth;
+ change = mFirst.setStackBoxSizes(mTmpRect);
+ mTmpRect.left = mTmpRect.right;
+ mTmpRect.right = bounds.left + width;
+ change |= mSecond.setStackBoxSizes(mTmpRect);
+ }
+ }
+ return change;
+ }
+
public void dump(String prefix, PrintWriter pw) {
pw.print(prefix); pw.print("mParent="); pw.println(mParent);
pw.print(prefix); pw.print("mBounds="); pw.print(mBounds.toShortString());
pw.print(" mVertical="); pw.print(mVertical);
pw.print(" layoutNeeded="); pw.println(layoutNeeded);
if (mFirst != null) {
- pw.print(prefix); pw.print("mFirst="); pw.println(mStack);
+ pw.print(prefix); pw.print("mFirst="); pw.println(System.identityHashCode(mFirst));
mFirst.dump(prefix + " ", pw);
- pw.print(prefix); pw.print("mSecond="); pw.println(mStack);
+ pw.print(prefix); pw.print("mSecond="); pw.println(System.identityHashCode(mSecond));
mSecond.dump(prefix + " ", pw);
} else {
pw.print(prefix); pw.print("mStack="); pw.println(mStack);
@@ -241,7 +313,8 @@ public class StackBox {
if (mStack != null) {
return "Box{" + hashCode() + " stack=" + mStack.mStackId + "}";
}
- return "Box{" + hashCode() + " parent=" + mParent.hashCode()
- + " first=" + mFirst.hashCode() + " second=" + mSecond.hashCode() + "}";
+ return "Box{" + hashCode() + " parent=" + System.identityHashCode(mParent)
+ + " first=" + System.identityHashCode(mFirst)
+ + " second=" + System.identityHashCode(mSecond) + "}";
}
}
diff --git a/services/java/com/android/server/wm/TaskStack.java b/services/java/com/android/server/wm/TaskStack.java
index 3e5a933..1c49e7d 100644
--- a/services/java/com/android/server/wm/TaskStack.java
+++ b/services/java/com/android/server/wm/TaskStack.java
@@ -33,12 +33,11 @@ public class TaskStack {
private ArrayList<Task> mTasks = new ArrayList<Task>();
/** The StackBox this sits in. */
- private final StackBox mParent;
+ StackBox mStackBox;
- TaskStack(int stackId, StackBox parent) {
+ TaskStack(int stackId, DisplayContent displayContent) {
mStackId = stackId;
- mParent = parent;
- mDisplayContent = mParent.mDisplayContent;
+ mDisplayContent = displayContent;
}
DisplayContent getDisplayContent() {
@@ -66,8 +65,9 @@ public class TaskStack {
* @param toTop Whether to add it to the top or bottom.
*/
boolean addTask(Task task, boolean toTop) {
- mParent.makeDirty();
+ mStackBox.makeDirty();
mTasks.add(toTop ? mTasks.size() : 0, task);
+ task.mStack = this;
return mDisplayContent.moveHomeStackBox(mStackId == HOME_STACK_ID);
}
@@ -87,12 +87,12 @@ public class TaskStack {
* @param task The Task to delete.
*/
void removeTask(Task task) {
- mParent.makeDirty();
+ mStackBox.makeDirty();
mTasks.remove(task);
}
int remove() {
- return mParent.removeStack();
+ return mStackBox.removeStack();
}
int numTokens() {
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index ad49d0a..a00fb7b 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -261,6 +261,12 @@ public class WindowManagerService extends IWindowManager.Stub
// Default input dispatching timeout in nanoseconds.
static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L;
+ /** Minimum value for createStack and resizeStack weight value */
+ public static final float STACK_WEIGHT_MIN = 0.2f;
+
+ /** Maximum value for createStack and resizeStack weight value */
+ public static final float STACK_WEIGHT_MAX = 0.8f;
+
static final int UPDATE_FOCUS_NORMAL = 0;
static final int UPDATE_FOCUS_WILL_ASSIGN_LAYERS = 1;
static final int UPDATE_FOCUS_PLACING_SURFACES = 2;
@@ -4708,11 +4714,22 @@ public class WindowManagerService extends IWindowManager.Stub
* @param weight Relative weight for determining how big to make the new TaskStack.
*/
public void createStack(int stackId, int relativeStackId, int position, float weight) {
- // TODO: Create a stack on other displays.
synchronized (mWindowMap) {
- TaskStack stack = getDefaultDisplayContentLocked().createStack(stackId,
- relativeStackId, position, weight);
- mStackIdToStack.put(stackId, stack);
+ if (position <= StackBox.TASK_STACK_GOES_BELOW &&
+ (weight < STACK_WEIGHT_MIN || weight > STACK_WEIGHT_MAX)) {
+ throw new IllegalArgumentException(
+ "createStack: weight must be between " + STACK_WEIGHT_MIN + " and " +
+ STACK_WEIGHT_MAX + ", weight=" + weight);
+ }
+ final TaskStack relativeStack = mStackIdToStack.get(relativeStackId);
+ DisplayContent displayContent = relativeStack != null ?
+ relativeStack.getDisplayContent() : getDefaultDisplayContentLocked();
+ TaskStack stack = displayContent.createStack(stackId, relativeStackId, position,
+ weight);
+ if (stack != null) {
+ mStackIdToStack.put(stackId, stack);
+ performLayoutAndPlaceSurfacesLocked();
+ }
}
}
@@ -4720,7 +4737,10 @@ public class WindowManagerService extends IWindowManager.Stub
final TaskStack stack = mStackIdToStack.get(stackId);
if (stack != null) {
mStackIdToStack.delete(stackId);
- return stack.remove();
+ int nextStackId = stack.remove();
+ stack.getDisplayContent().layoutNeeded = true;
+ performLayoutAndPlaceSurfacesLocked();
+ return nextStackId;
}
return HOME_STACK_ID;
}
@@ -4731,11 +4751,17 @@ public class WindowManagerService extends IWindowManager.Stub
task.mStack.removeTask(task);
TaskStack newStack = mStackIdToStack.get(stackId);
newStack.addTask(task, toTop);
+ newStack.getDisplayContent().layoutNeeded = true;
performLayoutAndPlaceSurfacesLocked();
}
}
public void resizeStack(int stackId, float weight) {
+ if (weight < STACK_WEIGHT_MIN || weight > STACK_WEIGHT_MAX) {
+ throw new IllegalArgumentException(
+ "resizeStack: weight must be between " + STACK_WEIGHT_MIN + " and " +
+ STACK_WEIGHT_MAX + ", weight=" + weight);
+ }
synchronized (mWindowMap) {
Task task = null;
DisplayContentsIterator iterator = new DisplayContentsIterator();
@@ -4750,6 +4776,17 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ public Rect getStackBounds(int stackId) {
+ DisplayContentsIterator iterator = new DisplayContentsIterator();
+ while (iterator.hasNext()) {
+ Rect bounds = iterator.next().getStackBounds(stackId);
+ if (bounds != null) {
+ return bounds;
+ }
+ }
+ return null;
+ }
+
// -------------------------------------------------------------
// Misc IWindowSession methods
// -------------------------------------------------------------
@@ -7935,6 +7972,10 @@ public class WindowManagerService extends IWindowManager.Stub
mScreenRect.set(0, 0, dw, dh);
}
+ Rect contentRect = new Rect();
+ mPolicy.getContentRectLw(contentRect);
+ displayContent.setStackBoxSize(contentRect);
+
int seq = mLayoutSeq+1;
if (seq < 0) seq = 0;
mLayoutSeq = seq;
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index 7ea36ef..8be424b 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -440,14 +440,19 @@ final class WindowState implements WindowManagerPolicy.WindowState {
public void computeFrameLw(Rect pf, Rect df, Rect of, Rect cf, Rect vf) {
mHaveFrame = true;
- final Rect container = mContainingFrame;
- container.set(pf);
+ final int type = mAttrs.type;
+ if (mAppToken != null) {
+ StackBox stack = mService.mTaskIdToTask.get(mAppToken.groupId).mStack.mStackBox;
+ mContainingFrame.set(stack.mBounds);
+ } else {
+ mContainingFrame.set(pf);
+ }
final Rect display = mDisplayFrame;
display.set(df);
- final int pw = container.right - container.left;
- final int ph = container.bottom - container.top;
+ final int pw = mContainingFrame.width();
+ final int ph = mContainingFrame.height();
int w,h;
if ((mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0) {
@@ -519,7 +524,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
y = mAttrs.y;
}
- Gravity.apply(mAttrs.gravity, w, h, container,
+ Gravity.apply(mAttrs.gravity, w, h, mContainingFrame,
(int) (x + mAttrs.horizontalMargin * pw),
(int) (y + mAttrs.verticalMargin * ph), frame);