DO NOT MERGE: Eliminate StackBox.

StackBox is too constraining. Adding size and position to TaskStacks
directly makes stack positioning and management more flexible and
prepares for ActivityView.

Change-Id: I33c6b4e1c23a5a8069fd507c160bcb34e4d287b2
This commit is contained in:
Craig Mautner
2013-12-02 14:08:25 -08:00
committed by Mike Lockwood
parent 09e9cdcece
commit bdc748af8c
14 changed files with 318 additions and 945 deletions

View File

@@ -19,7 +19,7 @@
package com.android.commands.am;
import android.app.ActivityManager;
import android.app.ActivityManager.StackBoxInfo;
import android.app.ActivityManager.StackInfo;
import android.app.ActivityManagerNative;
import android.app.IActivityController;
import android.app.IActivityManager;
@@ -31,6 +31,7 @@ import android.content.IIntentReceiver;
import android.content.Intent;
import android.content.pm.IPackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -106,11 +107,11 @@ 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> <RELATIVE_STACK_BOX_ID> <POSITION> <WEIGHT>\n" +
" am stack create <TASK_ID>\n" +
" am stack movetask <TASK_ID> <STACK_ID> [true|false]\n" +
" am stack resize <STACK_ID> <WEIGHT>\n" +
" am stack boxes\n" +
" am stack box <STACK_BOX_ID>\n" +
" am stack resize <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" +
" am stack list\n" +
" am stack info <STACK_ID>\n" +
"\n" +
"am start: start an Activity. Options are:\n" +
" -D: enable debugging\n" +
@@ -204,24 +205,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" +
" <TASK_ID>: the task to populate the new stack with. Must exist.\n" +
" <RELATIVE_STACK_BOX_ID>: existing stack box's id.\n" +
" <POSITION>: 0: before <RELATIVE_STACK_BOX_ID>, per RTL/LTR configuration,\n" +
" 1: after <RELATIVE_STACK_BOX_ID>, per RTL/LTR configuration,\n" +
" 2: to left of <RELATIVE_STACK_BOX_ID>,\n" +
" 3: to right of <RELATIVE_STACK_BOX_ID>," +
" 4: above <RELATIVE_STACK_BOX_ID>, 5: below <RELATIVE_STACK_BOX_ID>\n" +
" <WEIGHT>: float between 0.2 and 0.8 inclusive.\n" +
"am stack create: create a new stack containing <TASK_ID> which must exist\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 resize: change <STACK_ID> relative size to new <WEIGHT>.\n" +
"am stack resize: change <STACK_ID> size and position to <LEFT,TOP,RIGHT,BOTTOM>.\n" +
"\n" +
"am stack boxes: list the hierarchy of stack boxes and their contents.\n" +
"am stack list: list all of the activity stacks and their sizes.\n" +
"\n" +
"am stack box: list the hierarchy of stack boxes rooted at <STACK_BOX_ID>.\n" +
"am stack info: display the information about activity stack <STACK_ID>.\n" +
"\n" +
"<INTENT> specifications include these flags and arguments:\n" +
" [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +
@@ -1551,11 +1544,11 @@ public class Am extends BaseCommand {
} else if (op.equals("movetask")) {
runStackMoveTask();
} else if (op.equals("resize")) {
runStackBoxResize();
} else if (op.equals("boxes")) {
runStackBoxes();
} else if (op.equals("box")) {
runStackBoxInfo();
runStackResize();
} else if (op.equals("list")) {
runStackList();
} else if (op.equals("info")) {
runStackInfo();
} else {
showError("Error: unknown command '" + op + "'");
return;
@@ -1565,15 +1558,9 @@ public class Am extends BaseCommand {
private void runStackCreate() throws Exception {
String taskIdStr = nextArgRequired();
int taskId = Integer.valueOf(taskIdStr);
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(taskId, relativeTo, position, weight);
int stackId = mAm.createStack(taskId);
System.out.println("createStack returned new stackId=" + stackId + "\n\n");
} catch (RemoteException e) {
}
@@ -1601,34 +1588,40 @@ public class Am extends BaseCommand {
}
}
private void runStackBoxResize() throws Exception {
String stackBoxIdStr = nextArgRequired();
int stackBoxId = Integer.valueOf(stackBoxIdStr);
String weightStr = nextArgRequired();
float weight = Float.valueOf(weightStr);
private void runStackResize() throws Exception {
String stackIdStr = nextArgRequired();
int stackId = Integer.valueOf(stackIdStr);
String leftStr = nextArgRequired();
int left = Integer.valueOf(leftStr);
String topStr = nextArgRequired();
int top = Integer.valueOf(topStr);
String rightStr = nextArgRequired();
int right = Integer.valueOf(rightStr);
String bottomStr = nextArgRequired();
int bottom = Integer.valueOf(bottomStr);
try {
mAm.resizeStackBox(stackBoxId, weight);
mAm.resizeStack(stackId, new Rect(left, top, right, bottom));
} catch (RemoteException e) {
}
}
private void runStackBoxes() throws Exception {
private void runStackList() throws Exception {
try {
List<StackBoxInfo> stackBoxes = mAm.getStackBoxes();
for (StackBoxInfo info : stackBoxes) {
List<StackInfo> stacks = mAm.getAllStackInfos();
for (StackInfo info : stacks) {
System.out.println(info);
}
} catch (RemoteException e) {
}
}
private void runStackBoxInfo() throws Exception {
private void runStackInfo() throws Exception {
try {
String stackBoxIdStr = nextArgRequired();
int stackBoxId = Integer.valueOf(stackBoxIdStr);
StackBoxInfo stackBoxInfo = mAm.getStackBoxInfo(stackBoxId);
System.out.println(stackBoxInfo);
String stackIdStr = nextArgRequired();
int stackId = Integer.valueOf(stackIdStr);
StackInfo info = mAm.getStackInfo(stackId);
System.out.println(info);
} catch (RemoteException e) {
}
}

View File

@@ -1288,107 +1288,16 @@ public class ActivityManager {
}
}
/**
* Information you can retrieve about the WindowManager StackBox hierarchy.
* @hide
*/
public static class StackBoxInfo implements Parcelable {
public int stackBoxId;
public float weight;
public boolean vertical;
public Rect bounds;
public StackBoxInfo[] children;
public int stackId;
public StackInfo stack;
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(stackBoxId);
dest.writeFloat(weight);
dest.writeInt(vertical ? 1 : 0);
bounds.writeToParcel(dest, flags);
dest.writeInt(stackId);
if (children != null) {
children[0].writeToParcel(dest, flags);
children[1].writeToParcel(dest, flags);
} else {
stack.writeToParcel(dest, flags);
}
}
public void readFromParcel(Parcel source) {
stackBoxId = source.readInt();
weight = source.readFloat();
vertical = source.readInt() == 1;
bounds = Rect.CREATOR.createFromParcel(source);
stackId = source.readInt();
if (stackId == -1) {
children = new StackBoxInfo[2];
children[0] = StackBoxInfo.CREATOR.createFromParcel(source);
children[1] = StackBoxInfo.CREATOR.createFromParcel(source);
} else {
stack = StackInfo.CREATOR.createFromParcel(source);
}
}
public static final Creator<StackBoxInfo> CREATOR =
new Creator<ActivityManager.StackBoxInfo>() {
@Override
public StackBoxInfo createFromParcel(Parcel source) {
return new StackBoxInfo(source);
}
@Override
public StackBoxInfo[] newArray(int size) {
return new StackBoxInfo[size];
}
};
public StackBoxInfo() {
}
public StackBoxInfo(Parcel source) {
readFromParcel(source);
}
public String toString(String prefix) {
StringBuilder sb = new StringBuilder(256);
sb.append(prefix); sb.append("Box id=" + stackBoxId); sb.append(" weight=" + weight);
sb.append(" vertical=" + vertical); sb.append(" bounds=" + bounds.toShortString());
sb.append("\n");
if (children != null) {
sb.append(prefix); sb.append("First child=\n");
sb.append(children[0].toString(prefix + " "));
sb.append(prefix); sb.append("Second child=\n");
sb.append(children[1].toString(prefix + " "));
} else {
sb.append(prefix); sb.append("Stack=\n");
sb.append(stack.toString(prefix + " "));
}
return sb.toString();
}
@Override
public String toString() {
return toString("");
}
}
/**
* Information you can retrieve about an ActivityStack in the system.
* @hide
*/
public static class StackInfo implements Parcelable {
public int stackId;
public Rect bounds;
public Rect bounds = new Rect();
public int[] taskIds;
public String[] taskNames;
public int displayId;
@Override
public int describeContents() {
@@ -1404,6 +1313,7 @@ public class ActivityManager {
dest.writeInt(bounds.bottom);
dest.writeIntArray(taskIds);
dest.writeStringArray(taskNames);
dest.writeInt(displayId);
}
public void readFromParcel(Parcel source) {
@@ -1412,6 +1322,7 @@ public class ActivityManager {
source.readInt(), source.readInt(), source.readInt(), source.readInt());
taskIds = source.createIntArray();
taskNames = source.createStringArray();
displayId = source.readInt();
}
public static final Creator<StackInfo> CREATOR = new Creator<StackInfo>() {
@@ -1435,7 +1346,9 @@ public class ActivityManager {
public String toString(String prefix) {
StringBuilder sb = new StringBuilder(256);
sb.append(prefix); sb.append("Stack id="); sb.append(stackId);
sb.append(" bounds="); sb.append(bounds.toShortString()); sb.append("\n");
sb.append(" bounds="); sb.append(bounds.toShortString());
sb.append(" displayId="); sb.append(displayId);
sb.append("\n");
prefix = prefix + " ";
for (int i = 0; i < taskIds.length; ++i) {
sb.append(prefix); sb.append("taskId="); sb.append(taskIds[i]);

View File

@@ -16,7 +16,7 @@
package android.app;
import android.app.ActivityManager.StackBoxInfo;
import android.app.ActivityManager.StackInfo;
import android.content.ComponentName;
import android.content.IIntentReceiver;
import android.content.IIntentSender;
@@ -31,6 +31,7 @@ import android.content.pm.ParceledListSlice;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -614,10 +615,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
case CREATE_STACK_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
int taskId = data.readInt();
int relativeStackId = data.readInt();
int position = data.readInt();
float weight = data.readFloat();
int res = createStack(taskId, relativeStackId, position, weight);
int res = createStack(taskId);
reply.writeNoException();
reply.writeInt(res);
return true;
@@ -635,25 +633,26 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
case RESIZE_STACK_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
int stackBoxId = data.readInt();
int stackId = data.readInt();
float weight = data.readFloat();
resizeStackBox(stackBoxId, weight);
Rect r = Rect.CREATOR.createFromParcel(data);
resizeStack(stackId, r);
reply.writeNoException();
return true;
}
case GET_STACK_BOXES_TRANSACTION: {
case GET_ALL_STACK_INFOS_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
List<StackBoxInfo> list = getStackBoxes();
List<StackInfo> list = getAllStackInfos();
reply.writeNoException();
reply.writeTypedList(list);
return true;
}
case GET_STACK_BOX_INFO_TRANSACTION: {
case GET_STACK_INFO_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
int stackBoxId = data.readInt();
StackBoxInfo info = getStackBoxInfo(stackBoxId);
int stackId = data.readInt();
StackInfo info = getStackInfo(stackId);
reply.writeNoException();
if (info != null) {
reply.writeInt(1);
@@ -2715,16 +2714,12 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
}
@Override
public int createStack(int taskId, int relativeStackBoxId, int position, float weight)
throws RemoteException
public int createStack(int taskId) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeInt(taskId);
data.writeInt(relativeStackBoxId);
data.writeInt(position);
data.writeFloat(weight);
mRemote.transact(CREATE_STACK_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
@@ -2747,44 +2742,44 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
}
@Override
public void resizeStackBox(int stackBoxId, float weight) throws RemoteException
public void resizeStack(int stackBoxId, Rect r) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeInt(stackBoxId);
data.writeFloat(weight);
r.writeToParcel(data, 0);
mRemote.transact(RESIZE_STACK_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
reply.readException();
data.recycle();
reply.recycle();
}
@Override
public List<StackBoxInfo> getStackBoxes() throws RemoteException
public List<StackInfo> getAllStackInfos() throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
mRemote.transact(GET_STACK_BOXES_TRANSACTION, data, reply, 0);
mRemote.transact(GET_ALL_STACK_INFOS_TRANSACTION, data, reply, 0);
reply.readException();
ArrayList<StackBoxInfo> list = reply.createTypedArrayList(StackBoxInfo.CREATOR);
ArrayList<StackInfo> list = reply.createTypedArrayList(StackInfo.CREATOR);
data.recycle();
reply.recycle();
return list;
}
@Override
public StackBoxInfo getStackBoxInfo(int stackBoxId) throws RemoteException
public StackInfo getStackInfo(int stackId) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeInt(stackBoxId);
mRemote.transact(GET_STACK_BOX_INFO_TRANSACTION, data, reply, 0);
data.writeInt(stackId);
mRemote.transact(GET_STACK_INFO_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
StackBoxInfo info = null;
StackInfo info = null;
if (res != 0) {
info = StackBoxInfo.CREATOR.createFromParcel(reply);
info = StackInfo.CREATOR.createFromParcel(reply);
}
data.recycle();
reply.recycle();

View File

@@ -18,7 +18,7 @@ package android.app;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityManager.RunningServiceInfo;
import android.app.ActivityManager.StackBoxInfo;
import android.app.ActivityManager.StackInfo;
import android.content.ComponentName;
import android.content.ContentProviderNative;
import android.content.IContentProvider;
@@ -36,6 +36,7 @@ import android.content.pm.ProviderInfo;
import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Bundle;
import android.os.Debug;
@@ -117,12 +118,11 @@ 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, int relativeStackBoxId, int position, float weight)
throws RemoteException;
public int createStack(int taskId) throws RemoteException;
public void moveTaskToStack(int taskId, int stackId, boolean toTop) throws RemoteException;
public void resizeStackBox(int stackBoxId, float weight) throws RemoteException;
public List<StackBoxInfo> getStackBoxes() throws RemoteException;
public StackBoxInfo getStackBoxInfo(int stackBoxId) throws RemoteException;
public void resizeStack(int stackId, Rect bounds) throws RemoteException;
public List<StackInfo> getAllStackInfos() throws RemoteException;
public StackInfo getStackInfo(int stackId) throws RemoteException;
public void setFocusedStack(int stackId) throws RemoteException;
public int getTaskForActivity(IBinder token, boolean onlyRoot) throws RemoteException;
/* oneway */
@@ -681,9 +681,9 @@ public interface IActivityManager extends IInterface {
int CREATE_STACK_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_STACK_BOXES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+170;
int GET_ALL_STACK_INFOS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+170;
int SET_FOCUSED_STACK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+171;
int GET_STACK_BOX_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+172;
int GET_STACK_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+172;
int CONVERT_FROM_TRANSLUCENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+173;
int CONVERT_TO_TRANSLUCENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+174;
int NOTIFY_ACTIVITY_DRAWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+175;

View File

@@ -29,7 +29,9 @@ import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
import android.app.AppOpsManager;
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;
@@ -52,7 +54,6 @@ import com.android.server.am.ActivityStack.ActivityState;
import com.android.server.firewall.IntentFirewall;
import com.android.server.pm.UserManagerService;
import com.android.server.wm.AppTransition;
import com.android.server.wm.StackBox;
import com.android.server.wm.WindowManagerService;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
@@ -68,7 +69,6 @@ import org.xmlpull.v1.XmlSerializer;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityManager.StackBoxInfo;
import android.app.ActivityManager.StackInfo;
import android.app.ActivityManagerNative;
import android.app.ActivityOptions;
@@ -1770,7 +1770,7 @@ public final class ActivityManagerService extends ActivityManagerNative
public void setWindowManager(WindowManagerService wm) {
mWindowManager = wm;
mStackSupervisor.setWindowManager(wm);
wm.createStack(HOME_STACK_ID, -1, StackBox.TASK_STACK_GOES_OVER, 1.0f);
wm.createStack(HOME_STACK_ID, Display.DEFAULT_DISPLAY);
}
public void startObservingNativeCrashes() {
@@ -7096,16 +7096,15 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
public int createStack(int taskId, int relativeStackBoxId, int position, float weight) {
public int createStack(int taskId) {
enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
"createStack()");
if (DEBUG_STACK) Slog.d(TAG, "createStack: taskId=" + taskId + " relStackBoxId=" +
relativeStackBoxId + " position=" + position + " weight=" + weight);
if (DEBUG_STACK) Slog.d(TAG, "createStack: taskId=" + taskId);
synchronized (this) {
long ident = Binder.clearCallingIdentity();
try {
int stackId = mStackSupervisor.createStack();
mWindowManager.createStack(stackId, relativeStackBoxId, position, weight);
mWindowManager.createStack(stackId, Display.DEFAULT_DISPLAY);
if (taskId > 0) {
moveTaskToStack(taskId, stackId, true);
}
@@ -7137,99 +7136,40 @@ public final class ActivityManagerService extends ActivityManagerNative
}
@Override
public void resizeStackBox(int stackBoxId, float weight) {
public void resizeStack(int stackBoxId, Rect bounds) {
enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
"resizeStackBox()");
long ident = Binder.clearCallingIdentity();
try {
mWindowManager.resizeStackBox(stackBoxId, weight);
mWindowManager.resizeStack(stackBoxId, bounds);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
private ArrayList<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;
}
}
private void addStackInfoToStackBoxInfo(StackBoxInfo stackBoxInfo, List<StackInfo> stackInfos) {
final int stackId = stackBoxInfo.stackId;
if (stackId >= 0) {
for (StackInfo stackInfo : stackInfos) {
if (stackId == stackInfo.stackId) {
stackBoxInfo.stack = stackInfo;
stackInfos.remove(stackInfo);
return;
}
}
} else {
addStackInfoToStackBoxInfo(stackBoxInfo.children[0], stackInfos);
addStackInfoToStackBoxInfo(stackBoxInfo.children[1], stackInfos);
}
}
@Override
public List<StackBoxInfo> getStackBoxes() {
public List<StackInfo> getAllStackInfos() {
enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
"getStackBoxes()");
long ident = Binder.clearCallingIdentity();
try {
List<StackBoxInfo> stackBoxInfos = mWindowManager.getStackBoxInfos();
synchronized (this) {
List<StackInfo> stackInfos = getStacks();
for (StackBoxInfo stackBoxInfo : stackBoxInfos) {
addStackInfoToStackBoxInfo(stackBoxInfo, stackInfos);
}
return mStackSupervisor.getAllStackInfos();
}
return stackBoxInfos;
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override
public StackBoxInfo getStackBoxInfo(int stackBoxId) {
public StackInfo getStackInfo(int stackId) {
enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
"getStackBoxInfo()");
"getStackInfo()");
long ident = Binder.clearCallingIdentity();
try {
List<StackBoxInfo> stackBoxInfos = mWindowManager.getStackBoxInfos();
StackBoxInfo info = null;
synchronized (this) {
List<StackInfo> stackInfos = getStacks();
for (StackBoxInfo stackBoxInfo : stackBoxInfos) {
addStackInfoToStackBoxInfo(stackBoxInfo, stackInfos);
if (stackBoxInfo.stackBoxId == stackBoxId) {
info = stackBoxInfo;
}
}
return mStackSupervisor.getStackInfo(stackId);
}
return info;
} finally {
Binder.restoreCallingIdentity(ident);
}

View File

@@ -34,6 +34,7 @@ import static com.android.server.am.ActivityManagerService.TAG;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.StackInfo;
import android.app.ActivityOptions;
import android.app.AppGlobals;
import android.app.IActivityManager;
@@ -70,11 +71,11 @@ import android.util.EventLog;
import android.util.Slog;
import android.util.SparseIntArray;
import android.view.Display;
import com.android.internal.app.HeavyWeightSwitcherActivity;
import com.android.internal.os.TransferPipe;
import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
import com.android.server.am.ActivityStack.ActivityState;
import com.android.server.wm.StackBox;
import com.android.server.wm.WindowManagerService;
import java.io.FileDescriptor;
@@ -1288,8 +1289,7 @@ public final class ActivityStackSupervisor {
}
// Time to create the first app stack for this user.
int stackId =
mService.createStack(-1, HOME_STACK_ID, StackBox.TASK_STACK_GOES_OVER, 1.0f);
int stackId = mService.createStack(-1);
if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, "adjustStackFocus: New stack r=" + r +
" stackId=" + stackId);
mFocusedStack = getStack(stackId);
@@ -2644,4 +2644,43 @@ public final class ActivityStackSupervisor {
}
}
}
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 getStackInfo(int stackId) {
ActivityStack stack = getStack(stackId);
if (stack != null) {
return getStackInfo(stack);
}
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)));
}
return list;
}
}

View File

@@ -166,7 +166,7 @@ public class DimLayer {
final int dw, dh;
final float xPos, yPos;
if (mStack.hasSibling()) {
if (!mStack.isFullscreen()) {
dw = mBounds.width();
dh = mBounds.height();
xPos = mBounds.left;

View File

@@ -21,10 +21,8 @@ import static com.android.server.wm.WindowManagerService.DEBUG_STACK;
import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerService.TAG;
import android.app.ActivityManager.StackBoxInfo;
import android.graphics.Rect;
import android.graphics.Region;
import android.os.Debug;
import android.util.EventLog;
import android.util.Slog;
import android.view.Display;
@@ -74,6 +72,7 @@ class DisplayContent {
private final Display mDisplay;
Rect mBaseDisplayRect = new Rect();
Rect mContentRect = new Rect();
// Accessed directly by all users.
boolean layoutNeeded;
@@ -92,11 +91,12 @@ class DisplayContent {
*/
final AppTokenList mExitingAppTokens = new AppTokenList();
/** Array containing the home StackBox and possibly one more which would contain apps. Array
/** Array containing all TaskStacks on this display. Array
* is stored in display order with the current bottom stack at 0. */
private ArrayList<StackBox> mStackBoxes = new ArrayList<StackBox>();
private ArrayList<TaskStack> mStacks = new ArrayList<TaskStack>();
/** True when the home StackBox is at the top of mStackBoxes, false otherwise. */
/** A special TaskStack with id==HOME_STACK_ID that moves to the bottom whenever any TaskStack
* (except a future lockscreen TaskStack) moves to the top. */
private TaskStack mHomeStack = null;
/** Detect user tapping outside of current focused stack bounds .*/
@@ -123,13 +123,6 @@ class DisplayContent {
display.getDisplayInfo(mDisplayInfo);
isDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY;
mService = service;
StackBox newBox = new StackBox(service, this, null);
mStackBoxes.add(newBox);
TaskStack newStack = new TaskStack(service, HOME_STACK_ID, this);
newStack.mStackBox = newBox;
newBox.mStack = newStack;
mHomeStack = newStack;
}
int getDisplayId() {
@@ -155,10 +148,6 @@ class DisplayContent {
return mDisplay.hasAccess(uid);
}
boolean homeOnTop() {
return mStackBoxes.get(0).mStack != mHomeStack;
}
public boolean isPrivate() {
return (mDisplay.getFlags() & Display.FLAG_PRIVATE) != 0;
}
@@ -205,7 +194,18 @@ class DisplayContent {
}
void updateDisplayInfo() {
// Save old size.
int oldWidth = mDisplayInfo.logicalWidth;
int oldHeight = mDisplayInfo.logicalHeight;
mDisplay.getDisplayInfo(mDisplayInfo);
for (int i = mStacks.size() - 1; i >= 0; --i) {
final TaskStack stack = mStacks.get(i);
if (!stack.isFullscreen()) {
stack.resizeBounds(oldWidth, oldHeight, mDisplayInfo.logicalWidth,
mDisplayInfo.logicalHeight);
}
}
}
void getLogicalDisplayRect(Rect out) {
@@ -227,159 +227,58 @@ class DisplayContent {
return count;
}
/** Refer to {@link WindowManagerService#createStack(int, int, int, float)} */
TaskStack createStack(int stackId, int relativeStackBoxId, int position, float weight) {
TaskStack newStack = null;
if (DEBUG_STACK) Slog.d(TAG, "createStack: stackId=" + stackId + " relativeStackBoxId="
+ relativeStackBoxId + " position=" + position + " weight=" + weight);
/** Refer to {@link WindowManagerService#createStack(int, int)} */
TaskStack createStack(int stackId) {
if (DEBUG_STACK) Slog.d(TAG, "createStack: stackId=" + stackId);
TaskStack newStack = new TaskStack(mService, stackId, this);
if (stackId == HOME_STACK_ID) {
if (mStackBoxes.size() != 1) {
if (mHomeStack != null) {
throw new IllegalArgumentException("createStack: HOME_STACK_ID (0) not first.");
}
newStack = mHomeStack;
} else {
int stackBoxNdx;
for (stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
final StackBox box = mStackBoxes.get(stackBoxNdx);
if (position == StackBox.TASK_STACK_GOES_OVER
|| position == StackBox.TASK_STACK_GOES_UNDER) {
// Position indicates a new box is added at top level only.
if (box.contains(relativeStackBoxId)) {
StackBox newBox = new StackBox(mService, this, null);
newStack = new TaskStack(mService, 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 " +
(stackBoxNdx + offset));
mStackBoxes.add(stackBoxNdx + offset, newBox);
break;
}
} else {
// Remaining position values indicate a box must be split.
newStack = box.split(stackId, relativeStackBoxId, position, weight);
if (newStack != null) {
break;
}
}
}
if (stackBoxNdx < 0) {
throw new IllegalArgumentException("createStack: stackBoxId " + relativeStackBoxId
+ " not found.");
}
mHomeStack = newStack;
}
if (newStack != null) {
layoutNeeded = true;
}
EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId, relativeStackBoxId, position,
(int)(weight * 100 + 0.5));
mStacks.add(newStack);
layoutNeeded = true;
return newStack;
}
/** Refer to {@link WindowManagerService#resizeStackBox(int, float)} */
boolean resizeStack(int stackBoxId, float weight) {
for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
final StackBox box = mStackBoxes.get(stackBoxNdx);
if (box.resize(stackBoxId, weight)) {
layoutNeeded = true;
void moveStack(TaskStack stack, boolean toTop) {
mStacks.remove(stack);
mStacks.add(toTop ? mStacks.size() : 0, stack);
}
TaskStack topStack() {
return mStacks.get(mStacks.size() - 1);
}
/**
* Propagate the new bounds to all child stacks.
* @param contentRect The bounds to apply at the top level.
*/
void resize(Rect contentRect) {
mContentRect.set(contentRect);
}
boolean getStackBounds(int stackId, Rect bounds) {
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
final TaskStack stack = mStacks.get(stackNdx);
if (stackId == stack.mStackId) {
bounds.set(stack.mBounds);
return true;
}
}
return false;
}
void addStackBox(StackBox box, boolean toTop) {
if (mStackBoxes.size() >= 2) {
throw new RuntimeException("addStackBox: Too many toplevel StackBoxes!");
}
mStackBoxes.add(toTop ? mStackBoxes.size() : 0, box);
}
void removeStackBox(StackBox box) {
if (DEBUG_STACK) Slog.d(TAG, "removeStackBox: box=" + box);
final TaskStack stack = box.mStack;
if (stack != null && stack.mStackId == HOME_STACK_ID) {
// Never delete the home stack, even if it is empty.
if (DEBUG_STACK) Slog.d(TAG, "removeStackBox: Not deleting home stack.");
return;
}
mStackBoxes.remove(box);
}
StackBoxInfo getStackBoxInfo(StackBox box) {
StackBoxInfo info = new StackBoxInfo();
info.stackBoxId = box.mStackBoxId;
info.weight = box.mWeight;
info.vertical = box.mVertical;
info.bounds = new Rect(box.mBounds);
if (box.mStack != null) {
info.stackId = box.mStack.mStackId;
// ActivityManagerService will fill in the StackInfo.
} else {
info.stackId = -1;
info.children = new StackBoxInfo[2];
info.children[0] = getStackBoxInfo(box.mFirst);
info.children[1] = getStackBoxInfo(box.mSecond);
}
return info;
}
ArrayList<StackBoxInfo> getStackBoxInfos() {
ArrayList<StackBoxInfo> list = new ArrayList<StackBoxInfo>();
for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
list.add(getStackBoxInfo(mStackBoxes.get(stackBoxNdx)));
}
return list;
}
/**
* Move the home StackBox to the top or bottom of mStackBoxes. That is the only place
* it is allowed to be. This is a nop if the home StackBox is already in the correct position.
* @param toTop Move home to the top of mStackBoxes if true, to the bottom if false.
* @return true if a change was made, false otherwise.
*/
boolean moveHomeStackBox(boolean toTop) {
if (DEBUG_STACK) Slog.d(TAG, "moveHomeStackBox: toTop=" + toTop + " Callers=" +
Debug.getCallers(4));
EventLog.writeEvent(EventLogTags.WM_HOME_STACK_MOVED, toTop ? 1 : 0);
switch (mStackBoxes.size()) {
case 0: throw new RuntimeException("moveHomeStackBox: No home StackBox!");
case 1: return false; // Only the home StackBox exists.
case 2:
if (homeOnTop() ^ toTop) {
mStackBoxes.add(mStackBoxes.remove(0));
return true;
}
return false;
default: throw new RuntimeException("moveHomeStackBox: Too many toplevel StackBoxes!");
}
}
/**
* 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.
*/
boolean setStackBoxSize(Rect contentRect) {
boolean change = false;
for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
change |= mStackBoxes.get(stackBoxNdx).setStackBoxSizes(contentRect, true);
}
return change;
}
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;
int stackIdFromPoint(int x, int y) {
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
final TaskStack stack = mStacks.get(stackNdx);
stack.getBounds(mTmpRect);
if (mTmpRect.contains(x, y)) {
return stack.mStackId;
}
}
return null;
}
int stackIdFromPoint(int x, int y) {
StackBox topBox = mStackBoxes.get(mStackBoxes.size() - 1);
return topBox.stackIdFromPoint(x, y);
return -1;
}
void setTouchExcludeRegion(TaskStack focusedStack) {
@@ -408,48 +307,48 @@ class DisplayContent {
}
}
for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
mStackBoxes.get(stackBoxNdx).switchUserStacks(newUserId);
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
mStacks.get(stackNdx).switchUser(newUserId);
}
}
void resetAnimationBackgroundAnimator() {
for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
mStackBoxes.get(stackBoxNdx).resetAnimationBackgroundAnimator();
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
mStacks.get(stackNdx).resetAnimationBackgroundAnimator();
}
}
boolean animateDimLayers() {
boolean result = false;
for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
result |= mStackBoxes.get(stackBoxNdx).animateDimLayers();
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
result |= mStacks.get(stackNdx).animateDimLayers();
}
return result;
}
void resetDimming() {
for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
mStackBoxes.get(stackBoxNdx).resetDimming();
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
mStacks.get(stackNdx).resetDimmingTag();
}
}
boolean isDimming() {
boolean result = false;
for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
result |= mStackBoxes.get(stackBoxNdx).isDimming();
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
result |= mStacks.get(stackNdx).isDimming();
}
return result;
}
void stopDimmingIfNeeded() {
for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
mStackBoxes.get(stackBoxNdx).stopDimmingIfNeeded();
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
mStacks.get(stackNdx).stopDimmingIfNeeded();
}
}
void close() {
for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
mStackBoxes.get(stackBoxNdx).close();
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
mStacks.get(stackNdx).close();
}
}
@@ -477,9 +376,10 @@ class DisplayContent {
pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
pw.print(subPrefix); pw.print("layoutNeeded="); pw.println(layoutNeeded);
for (int boxNdx = 0; boxNdx < mStackBoxes.size(); ++boxNdx) {
pw.print(prefix); pw.print("StackBox #"); pw.println(boxNdx);
mStackBoxes.get(boxNdx).dump(prefix + " ", pw);
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
final TaskStack stack = mStacks.get(stackNdx);
pw.print(prefix); pw.print("mStacks[" + stackNdx + "]"); pw.println(stack.mStackId);
stack.dump(prefix + " ", pw);
}
int ndx = numTokens();
if (ndx > 0) {

View File

@@ -41,7 +41,7 @@ class FocusedStackFrame {
private final SurfaceControl mSurfaceControl;
private final Surface mSurface = new Surface();
private final Rect mLastBounds = new Rect();
private final Rect mBounds = new Rect();
final Rect mBounds = new Rect();
private final Rect mTmpDrawRect = new Rect();
public FocusedStackFrame(Display display, SurfaceSession session) {
@@ -131,9 +131,9 @@ class FocusedStackFrame {
}
}
public void setBounds(Rect bounds) {
if (false && DEBUG_STACK) Slog.i(TAG, "setBounds: bounds=" + bounds);
mBounds.set(bounds);
public void setBounds(TaskStack stack) {
stack.getBounds(mBounds);
if (false && DEBUG_STACK) Slog.i(TAG, "setBounds: bounds=" + mBounds);
}
public void setLayer(int layer) {

View File

@@ -58,6 +58,8 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
private final Object mInputDevicesReadyMonitor = new Object();
private boolean mInputDevicesReady;
Rect mTmpRect = new Rect();
public InputMonitor(WindowManagerService service) {
mService = service;
}
@@ -175,7 +177,8 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
if (modal && child.mAppToken != null) {
// Limit the outer touch to the activity stack region.
flags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
inputWindowHandle.touchableRegion.set(child.getStackBounds());
child.getStackBounds(mTmpRect);
inputWindowHandle.touchableRegion.set(mTmpRect);
} else {
// Not modal or full screen modal
child.getTouchableRegion(inputWindowHandle.touchableRegion);

View File

@@ -1,414 +0,0 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.wm;
import android.graphics.Rect;
import android.util.Slog;
import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
import static com.android.server.wm.WindowManagerService.DEBUG_STACK;
import static com.android.server.wm.WindowManagerService.TAG;
import java.io.PrintWriter;
public class StackBox {
/** Used with {@link WindowManagerService#createStack}. Dependent on Configuration LTR/RTL. */
public static final int TASK_STACK_GOES_BEFORE = 0;
/** Used with {@link WindowManagerService#createStack}. Dependent on Configuration LTR/RTL. */
public static final int TASK_STACK_GOES_AFTER = 1;
/** Used with {@link WindowManagerService#createStack}. Horizontal to left of. */
public static final int TASK_STACK_TO_LEFT_OF = 2;
/** Used with {@link WindowManagerService#createStack}. Horizontal to right of. */
public static final int TASK_STACK_TO_RIGHT_OF = 3;
/** Used with {@link WindowManagerService#createStack}. Vertical: lower t/b Rect values. */
public static final int TASK_STACK_GOES_ABOVE = 4;
/** Used with {@link WindowManagerService#createStack}. Vertical: higher t/b Rect values. */
public static final int TASK_STACK_GOES_BELOW = 5;
/** Used with {@link WindowManagerService#createStack}. Put on a higher layer on display. */
public static final int TASK_STACK_GOES_OVER = 6;
/** Used with {@link WindowManagerService#createStack}. Put on a lower layer on display. */
public static final int TASK_STACK_GOES_UNDER = 7;
static int sCurrentBoxId = 0;
/** Unique id for this box */
final int mStackBoxId;
/** The service */
final WindowManagerService mService;
/** The display this box sits in. */
final DisplayContent mDisplayContent;
/** Non-null indicates this is mFirst or mSecond of a parent StackBox. Null indicates this
* is this entire size of mDisplayContent. */
StackBox mParent;
/** First child, this is null exactly when mStack is non-null. */
StackBox mFirst;
/** Second child, this is null exactly when mStack is non-null. */
StackBox mSecond;
/** Stack of Tasks, this is null exactly when mFirst and mSecond are non-null. */
TaskStack mStack;
/** Content limits relative to the DisplayContent this sits in. */
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;
/** True if this StackBox sits below the Status Bar. */
boolean mUnderStatusBar;
/** Used to keep from reallocating a temporary Rect for propagating bounds to child boxes */
Rect mTmpRect = new Rect();
StackBox(WindowManagerService service, DisplayContent displayContent, StackBox parent) {
synchronized (StackBox.class) {
mStackBoxId = sCurrentBoxId++;
}
mService = service;
mDisplayContent = displayContent;
mParent = parent;
}
/** Propagate #layoutNeeded bottom up. */
void makeDirty() {
layoutNeeded = true;
if (mParent != null) {
mParent.makeDirty();
}
}
/**
* Determine if a particular StackBox is this one or a descendant of this one.
* @param stackBoxId The StackBox being searched for.
* @return true if the specified StackBox matches this or one of its descendants.
*/
boolean contains(int stackBoxId) {
return mStackBoxId == stackBoxId ||
(mStack == null && (mFirst.contains(stackBoxId) || mSecond.contains(stackBoxId)));
}
/**
* Return the stackId of the stack that intersects the passed point.
* @param x coordinate of point.
* @param y coordinate of point.
* @return -1 if point is outside of mBounds, otherwise the stackId of the containing stack.
*/
int stackIdFromPoint(int x, int y) {
if (!mBounds.contains(x, y)) {
return -1;
}
if (mStack != null) {
return mStack.mStackId;
}
int stackId = mFirst.stackIdFromPoint(x, y);
if (stackId >= 0) {
return stackId;
}
return mSecond.stackIdFromPoint(x, y);
}
/** Determine if this StackBox is the first child or second child.
* @return true if this is the first child.
*/
boolean isFirstChild() {
return mParent != null && mParent.mFirst == this;
}
/** 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
* is determined by the passed parameters.
* @param stackId The id of the new TaskStack to create.
* @param relativeStackBoxId The id of the StackBox to place the new TaskStack next to.
* @param position One of the static TASK_STACK_GOES_xxx positions defined in this class.
* @param weight The percentage size of the parent StackBox to devote to the new TaskStack.
* @return The new TaskStack.
*/
TaskStack split(int stackId, int relativeStackBoxId, int position, float weight) {
if (mStackBoxId != relativeStackBoxId) {
// This is not the targeted StackBox.
if (mStack != null) {
return null;
}
// Propagate the split to see if the targeted StackBox is in either sub box.
TaskStack stack = mFirst.split(stackId, relativeStackBoxId, position, weight);
if (stack != null) {
return stack;
}
return mSecond.split(stackId, relativeStackBoxId, position, weight);
}
// Found it!
TaskStack stack = new TaskStack(mService, stackId, mDisplayContent);
TaskStack firstStack;
TaskStack secondStack;
if (position == TASK_STACK_GOES_BEFORE) {
// TODO: Test Configuration here for LTR/RTL.
position = TASK_STACK_TO_LEFT_OF;
} else if (position == TASK_STACK_GOES_AFTER) {
// TODO: Test Configuration here for LTR/RTL.
position = TASK_STACK_TO_RIGHT_OF;
}
switch (position) {
default:
case TASK_STACK_TO_LEFT_OF:
case TASK_STACK_TO_RIGHT_OF:
mVertical = false;
if (position == TASK_STACK_TO_LEFT_OF) {
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;
}
mFirst = new StackBox(mService, mDisplayContent, this);
firstStack.mStackBox = mFirst;
mFirst.mStack = firstStack;
mSecond = new StackBox(mService, mDisplayContent, this);
secondStack.mStackBox = mSecond;
mSecond.mStack = secondStack;
mStack = null;
return stack;
}
/** Return the stackId of the first mFirst StackBox with a non-null mStack */
int getStackId() {
if (mStack != null) {
return mStack.mStackId;
}
return mFirst.getStackId();
}
/** Remove this box and propagate its sibling's content up to their parent.
* @return The first stackId of the resulting StackBox. */
int remove() {
mDisplayContent.layoutNeeded = true;
if (mParent == null) {
// This is the top-plane stack.
if (DEBUG_STACK) Slog.i(TAG, "StackBox.remove: removing top plane.");
mDisplayContent.removeStackBox(this);
return HOME_STACK_ID;
}
StackBox sibling = isFirstChild() ? mParent.mSecond : mParent.mFirst;
StackBox grandparent = mParent.mParent;
sibling.mParent = grandparent;
if (grandparent == null) {
// mParent is a top-plane stack. Now sibling will be.
if (DEBUG_STACK) Slog.i(TAG, "StackBox.remove: grandparent null");
mDisplayContent.removeStackBox(mParent);
mDisplayContent.addStackBox(sibling, true);
} else {
if (DEBUG_STACK) Slog.i(TAG, "StackBox.remove: grandparent getting sibling");
if (mParent.isFirstChild()) {
grandparent.mFirst = sibling;
} else {
grandparent.mSecond = sibling;
}
}
return sibling.getStackId();
}
boolean resize(int stackBoxId, float weight) {
if (mStackBoxId != stackBoxId) {
return mStack == null &&
(mFirst.resize(stackBoxId, weight) || mSecond.resize(stackBoxId, weight));
}
// Don't change weight on topmost stack.
if (mParent != null) {
mParent.mWeight = isFirstChild() ? weight : 1.0f - weight;
}
return true;
}
/** If this is a terminal StackBox (contains a TaskStack) set the bounds.
* @param bounds The rectangle to set the bounds to.
* @param underStatusBar True if the StackBox is directly below the Status Bar.
* @return True if the bounds changed, false otherwise. */
boolean setStackBoxSizes(Rect bounds, boolean underStatusBar) {
boolean change = false;
if (mUnderStatusBar != underStatusBar) {
change = true;
mUnderStatusBar = underStatusBar;
}
if (mStack != null) {
change |= !mBounds.equals(bounds);
if (change) {
mBounds.set(bounds);
mStack.setBounds(bounds, underStatusBar);
}
} 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, underStatusBar);
mTmpRect.top = mTmpRect.bottom;
mTmpRect.bottom = bounds.top + height;
change |= mSecond.setStackBoxSizes(mTmpRect, false);
} else {
final int width = bounds.width();
int firstWidth = (int)(width * mWeight);
mTmpRect.right = bounds.left + firstWidth;
change |= mFirst.setStackBoxSizes(mTmpRect, underStatusBar);
mTmpRect.left = mTmpRect.right;
mTmpRect.right = bounds.left + width;
change |= mSecond.setStackBoxSizes(mTmpRect, underStatusBar);
}
}
return change;
}
void resetAnimationBackgroundAnimator() {
if (mStack != null) {
mStack.resetAnimationBackgroundAnimator();
return;
}
mFirst.resetAnimationBackgroundAnimator();
mSecond.resetAnimationBackgroundAnimator();
}
boolean animateDimLayers() {
if (mStack != null) {
return mStack.animateDimLayers();
}
boolean result = mFirst.animateDimLayers();
result |= mSecond.animateDimLayers();
return result;
}
void resetDimming() {
if (mStack != null) {
mStack.resetDimmingTag();
return;
}
mFirst.resetDimming();
mSecond.resetDimming();
}
boolean isDimming() {
if (mStack != null) {
return mStack.isDimming();
}
boolean result = mFirst.isDimming();
result |= mSecond.isDimming();
return result;
}
void stopDimmingIfNeeded() {
if (mStack != null) {
mStack.stopDimmingIfNeeded();
return;
}
mFirst.stopDimmingIfNeeded();
mSecond.stopDimmingIfNeeded();
}
void switchUserStacks(int userId) {
if (mStack != null) {
mStack.switchUser(userId);
return;
}
mFirst.switchUserStacks(userId);
mSecond.switchUserStacks(userId);
}
void close() {
if (mStack != null) {
mStack.mDimLayer.mDimSurface.destroy();
mStack.mAnimationBackgroundSurface.mDimSurface.destroy();
return;
}
mFirst.close();
mSecond.close();
}
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(System.identityHashCode(mFirst));
mFirst.dump(prefix + " ", pw);
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);
mStack.dump(prefix + " ", pw);
}
}
@Override
public String toString() {
if (mStack != null) {
return "Box{" + hashCode() + " stack=" + mStack.mStackId + "}";
}
return "Box{" + hashCode() + " parent=" + System.identityHashCode(mParent)
+ " first=" + System.identityHashCode(mFirst)
+ " second=" + System.identityHashCode(mSecond) + "}";
}
}

View File

@@ -26,8 +26,6 @@ import android.util.Slog;
import android.util.TypedValue;
import com.android.server.EventLogTags;
import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -49,8 +47,9 @@ public class TaskStack {
* mTaskHistory in the ActivityStack with the same mStackId */
private final ArrayList<Task> mTasks = new ArrayList<Task>();
/** The StackBox this sits in. */
StackBox mStackBox;
/** Content limits relative to the DisplayContent this sits in. Empty indicates fullscreen,
* Nonempty is size of this TaskStack but is also used to scale if DisplayContent changes. */
Rect mBounds = new Rect();
/** Used to support {@link android.view.WindowManager.LayoutParams#FLAG_DIM_BEHIND} */
final DimLayer mDimLayer;
@@ -74,6 +73,9 @@ public class TaskStack {
mDisplayContent = displayContent;
mDimLayer = new DimLayer(service, this);
mAnimationBackgroundSurface = new DimLayer(service, this);
// TODO: remove bounds from log, they are always 0.
EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId, mBounds.left, mBounds.top,
mBounds.right, mBounds.bottom);
}
DisplayContent getDisplayContent() {
@@ -84,12 +86,64 @@ public class TaskStack {
return mTasks;
}
boolean isHomeStack() {
return mStackId == HOME_STACK_ID;
private void resizeWindows() {
final boolean underStatusBar = mBounds.top == 0;
final ArrayList<WindowState> resizingWindows = mService.mResizingWindows;
for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
final ArrayList<AppWindowToken> activities = mTasks.get(taskNdx).mAppTokens;
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
final ArrayList<WindowState> windows = activities.get(activityNdx).allAppWindows;
for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
final WindowState win = windows.get(winNdx);
if (!resizingWindows.contains(win)) {
if (WindowManagerService.DEBUG_RESIZE) Slog.d(TAG,
"setBounds: Resizing " + win);
resizingWindows.add(win);
}
win.mUnderStatusBar = underStatusBar;
}
}
}
}
boolean hasSibling() {
return mStackBox.mParent != null;
boolean setBounds(Rect bounds) {
if (mBounds.equals(bounds)) {
return false;
}
mDimLayer.setBounds(bounds);
mAnimationBackgroundSurface.setBounds(bounds);
mBounds.set(bounds);
resizeWindows();
return true;
}
void getBounds(Rect out) {
if (mBounds.isEmpty()) {
mDisplayContent.getLogicalDisplayRect(out);
} else {
out.set(mBounds);
}
out.intersect(mDisplayContent.mContentRect);
}
boolean isFullscreen() {
return mBounds.isEmpty();
}
void resizeBounds(float oldWidth, float oldHeight, float newWidth, float newHeight) {
if (oldWidth == newWidth && oldHeight == newHeight) {
return;
}
float widthScale = newWidth / oldWidth;
float heightScale = newHeight / oldHeight;
mBounds.left = (int)(mBounds.left * widthScale + 0.5);
mBounds.top = (int)(mBounds.top * heightScale + 0.5);
mBounds.right = (int)(mBounds.right * widthScale + 0.5);
mBounds.bottom = (int)(mBounds.bottom * heightScale + 0.5);
resizeWindows();
}
/**
@@ -97,9 +151,7 @@ public class TaskStack {
* @param task The task to add.
* @param toTop Whether to add it to the top or bottom.
*/
boolean addTask(Task task, boolean toTop) {
mStackBox.makeDirty();
void addTask(Task task, boolean toTop) {
int stackNdx;
if (!toTop) {
stackNdx = 0;
@@ -122,20 +174,20 @@ public class TaskStack {
task.mStack = this;
mDisplayContent.addTask(task, toTop);
return mDisplayContent.moveHomeStackBox(mStackId == HOME_STACK_ID);
mDisplayContent.moveStack(this, true);
}
boolean moveTaskToTop(Task task) {
void moveTaskToTop(Task task) {
if (DEBUG_TASK_MOVEMENT) Slog.d(TAG, "moveTaskToTop: task=" + task + " Callers="
+ Debug.getCallers(6));
mTasks.remove(task);
return addTask(task, true);
addTask(task, true);
}
boolean moveTaskToBottom(Task task) {
void moveTaskToBottom(Task task) {
if (DEBUG_TASK_MOVEMENT) Slog.d(TAG, "moveTaskToBottom: task=" + task);
mTasks.remove(task);
return addTask(task, false);
addTask(task, false);
}
/**
@@ -145,7 +197,6 @@ public class TaskStack {
*/
void removeTask(Task task) {
if (DEBUG_TASK_MOVEMENT) Slog.d(TAG, "removeTask: task=" + task);
mStackBox.makeDirty();
mTasks.remove(task);
mDisplayContent.removeTask(task);
}
@@ -154,7 +205,7 @@ public class TaskStack {
mAnimationBackgroundSurface.destroySurface();
mDimLayer.destroySurface();
EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId);
return mStackBox.remove();
return mDisplayContent.topStack().mStackId;
}
void resetAnimationBackgroundAnimator() {
@@ -259,28 +310,6 @@ public class TaskStack {
}
}
void setBounds(Rect bounds, boolean underStatusBar) {
mDimLayer.setBounds(bounds);
mAnimationBackgroundSurface.setBounds(bounds);
final ArrayList<WindowState> resizingWindows = mService.mResizingWindows;
for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
final ArrayList<AppWindowToken> activities = mTasks.get(taskNdx).mAppTokens;
for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
final ArrayList<WindowState> windows = activities.get(activityNdx).allAppWindows;
for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
final WindowState win = windows.get(winNdx);
if (!resizingWindows.contains(win)) {
if (WindowManagerService.DEBUG_RESIZE) Slog.d(TAG,
"setBounds: Resizing " + win);
resizingWindows.add(win);
}
win.mUnderStatusBar = underStatusBar;
}
}
}
}
void switchUser(int userId) {
int top = mTasks.size();
for (int taskNdx = 0; taskNdx < top; ++taskNdx) {
@@ -293,6 +322,11 @@ public class TaskStack {
}
}
void close() {
mDimLayer.mDimSurface.destroy();
mAnimationBackgroundSurface.mDimSurface.destroy();
}
public void dump(String prefix, PrintWriter pw) {
pw.print(prefix); pw.print("mStackId="); pw.println(mStackId);
for (int taskNdx = 0; taskNdx < mTasks.size(); ++taskNdx) {

View File

@@ -45,7 +45,6 @@ import com.android.server.power.PowerManagerService;
import com.android.server.power.ShutdownThread;
import android.Manifest;
import android.app.ActivityManager.StackBoxInfo;
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
import android.app.StatusBarManager;
@@ -3775,10 +3774,8 @@ public class WindowManagerService extends IWindowManager.Stub
if (stack == null) {
mFocusedStackFrame.setVisibility(false);
} else {
final StackBox box = stack.mStackBox;
final Rect bounds = box.mBounds;
final boolean multipleStacks = box.mParent != null;
mFocusedStackFrame.setBounds(bounds);
mFocusedStackFrame.setBounds(stack);
final boolean multipleStacks = !stack.isFullscreen();
mFocusedStackFrame.setVisibility(multipleStacks);
}
} finally {
@@ -4785,10 +4782,12 @@ public class WindowManagerService extends IWindowManager.Stub
}
final TaskStack stack = task.mStack;
final DisplayContent displayContent = task.getDisplayContent();
final boolean isHomeStackTask = stack.isHomeStack();
if (isHomeStackTask != displayContent.homeOnTop()) {
// First move the stack itself.
displayContent.moveHomeStackBox(isHomeStackTask);
displayContent.moveStack(stack, true);
final TaskStack homeStack = displayContent.getHomeStack();
if (homeStack != stack) {
// When a non-home stack moves to the top, the home stack moves to the
// bottom.
displayContent.moveStack(homeStack, false);
}
stack.moveTaskToTop(task);
}
@@ -4819,36 +4818,19 @@ public class WindowManagerService extends IWindowManager.Stub
/**
* Create a new TaskStack and place it next to an existing stack.
* @param stackId The unique identifier of the new stack.
* @param relativeStackBoxId The existing stack that this stack goes before or after.
* @param position One of:
* {@link StackBox#TASK_STACK_GOES_BEFORE}
* {@link StackBox#TASK_STACK_GOES_AFTER}
* {@link StackBox#TASK_STACK_GOES_ABOVE}
* {@link StackBox#TASK_STACK_GOES_BELOW}
* {@link StackBox#TASK_STACK_GOES_UNDER}
* {@link StackBox#TASK_STACK_GOES_OVER}
* @param weight Relative weight for determining how big to make the new TaskStack.
*/
public void createStack(int stackId, int relativeStackBoxId, int position, float weight) {
public void createStack(int stackId, int displayId) {
synchronized (mWindowMap) {
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 int numDisplays = mDisplayContents.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx);
TaskStack stack = displayContent.createStack(stackId, relativeStackBoxId, position,
weight);
if (stack != null) {
if (displayContent.getDisplayId() == displayId) {
TaskStack stack = displayContent.createStack(stackId);
mStackIdToStack.put(stackId, stack);
performLayoutAndPlaceSurfacesLocked();
return;
}
}
Slog.e(TAG, "createStack: Unable to find relativeStackBoxId=" + relativeStackBoxId);
}
}
@@ -4895,40 +4877,27 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
public void resizeStackBox(int stackBoxId, 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);
}
public void resizeStack(int stackId, Rect bounds) {
synchronized (mWindowMap) {
final int numDisplays = mDisplayContents.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
if (mDisplayContents.valueAt(displayNdx).resizeStack(stackBoxId, weight)) {
performLayoutAndPlaceSurfacesLocked();
return;
}
final TaskStack stack = mStackIdToStack.get(stackId);
if (stack == null) {
throw new IllegalArgumentException("resizeStack: stackId " + stackId
+ " not found.");
}
if (stack.setBounds(bounds)) {
stack.getDisplayContent().layoutNeeded = true;
performLayoutAndPlaceSurfacesLocked();
}
}
throw new IllegalArgumentException("resizeStack: stackBoxId " + stackBoxId
+ " not found.");
}
public ArrayList<StackBoxInfo> getStackBoxInfos() {
synchronized(mWindowMap) {
return getDefaultDisplayContentLocked().getStackBoxInfos();
}
}
public Rect getStackBounds(int stackId) {
final int numDisplays = mDisplayContents.size();
for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
Rect bounds = mDisplayContents.valueAt(displayNdx).getStackBounds(stackId);
if (bounds != null) {
return bounds;
}
public void getStackBounds(int stackId, Rect bounds) {
final TaskStack stack = mStackIdToStack.get(stackId);
if (stack != null) {
stack.getBounds(bounds);
return;
}
return null;
bounds.setEmpty();
}
// -------------------------------------------------------------
@@ -5585,7 +5554,7 @@ public class WindowManagerService extends IWindowManager.Stub
continue;
}
appWin = ws;
stackBounds.set(ws.getStackBounds());
ws.getStackBounds(stackBounds);
}
}
@@ -8214,7 +8183,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
mPolicy.getContentRectLw(mTmpContentRect);
displayContent.setStackBoxSize(mTmpContentRect);
displayContent.resize(mTmpContentRect);
int seq = mLayoutSeq+1;
if (seq < 0) seq = 0;

View File

@@ -463,8 +463,8 @@ final class WindowState implements WindowManagerPolicy.WindowState {
mHaveFrame = true;
TaskStack stack = mAppToken != null ? getStack() : null;
if (stack != null && stack.hasSibling()) {
mContainingFrame.set(getStackBounds(stack));
if (stack != null && !stack.isFullscreen()) {
getStackBounds(stack, mContainingFrame);
if (mUnderStatusBar) {
mContainingFrame.top = pf.top;
}
@@ -723,15 +723,16 @@ final class WindowState implements WindowManagerPolicy.WindowState {
return mDisplayContent.getHomeStack();
}
Rect getStackBounds() {
return getStackBounds(getStack());
void getStackBounds(Rect bounds) {
getStackBounds(getStack(), bounds);
}
private Rect getStackBounds(TaskStack stack) {
private void getStackBounds(TaskStack stack, Rect bounds) {
if (stack != null) {
return stack.mStackBox.mBounds;
stack.getBounds(bounds);
return;
}
return mFrame;
bounds.set(mFrame);
}
public long getInputDispatchingTimeoutNanos() {