diff options
| author | 2015-06-30 08:40:31 -0700 | |
|---|---|---|
| committer | 2015-07-31 11:59:20 -0700 | |
| commit | e4a0c5722b1d8db95dfc842d716452dbbf02c86d (patch) | |
| tree | d88e6846602e0de3441ca5959cc2141c723d8cc6 | |
| parent | 905d51a2f83768663f9c026080a003cf8ef78a82 (diff) | |
Allow stacks to hold tasks on various sizes.
Tasks are now resizeable just like stacks. Adjusting the size
of a stack will also adjust the size of all it's containing
tasks. This model allows us to be more flexible
in using stacks as workspaces (like you would have in a
desktop environment) and tasks as the resizeable windows
within the workspace.
Also added "adb shell dumpsys window visible-apps" for
getting the list of visible app windows.
Bug: 22068114
Bug: 19182363
Change-Id: I5bf77063252a5abae4e327f6fc42e607091749f9
24 files changed, 835 insertions, 567 deletions
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index b2f068b56903..5974fcfe949a 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -1789,6 +1789,7 @@ public class ActivityManager { public Rect bounds = new Rect(); public int[] taskIds; public String[] taskNames; + public Rect[] taskBounds; public int displayId; @Override @@ -1805,6 +1806,14 @@ public class ActivityManager { dest.writeInt(bounds.bottom); dest.writeIntArray(taskIds); dest.writeStringArray(taskNames); + final int boundsCount = taskBounds == null ? 0 : taskBounds.length; + dest.writeInt(boundsCount); + for (int i = 0; i < boundsCount; i++) { + dest.writeInt(taskBounds[i].left); + dest.writeInt(taskBounds[i].top); + dest.writeInt(taskBounds[i].right); + dest.writeInt(taskBounds[i].bottom); + } dest.writeInt(displayId); } @@ -1814,6 +1823,17 @@ public class ActivityManager { source.readInt(), source.readInt(), source.readInt(), source.readInt()); taskIds = source.createIntArray(); taskNames = source.createStringArray(); + final int boundsCount = source.readInt(); + if (boundsCount > 0) { + taskBounds = new Rect[boundsCount]; + for (int i = 0; i < boundsCount; i++) { + taskBounds[i] = new Rect(); + taskBounds[i].set( + source.readInt(), source.readInt(), source.readInt(), source.readInt()); + } + } else { + taskBounds = null; + } displayId = source.readInt(); } @@ -1844,7 +1864,11 @@ public class ActivityManager { prefix = 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"); + sb.append(": "); sb.append(taskNames[i]); + if (taskBounds != null) { + sb.append(" bounds="); sb.append(taskBounds[i].toShortString()); + } + sb.append("\n"); } return sb.toString(); } diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index e83d635e8771..facaee4b4ca5 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -799,6 +799,14 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } + case SET_FOCUSED_TASK_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + int taskId = data.readInt(); + setFocusedStack(taskId); + reply.writeNoException(); + return true; + } + case REGISTER_TASK_STACK_LISTENER_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); IBinder token = data.readStrongBinder(); @@ -2429,6 +2437,15 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } + case GET_TASK_BOUNDS_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + int taskId = data.readInt(); + Rect r = getTaskBounds(taskId); + reply.writeNoException(); + r.writeToParcel(reply, 0); + return true; + } + case GET_TASK_DESCRIPTION_ICON_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); String filename = data.readString(); @@ -3520,6 +3537,18 @@ class ActivityManagerProxy implements IActivityManager return focusedStackId; } @Override + public void setFocusedTask(int taskId) throws RemoteException + { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeInt(taskId); + mRemote.transact(SET_FOCUSED_TASK_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } + @Override public void registerTaskStackListener(ITaskStackListener listener) throws RemoteException { Parcel data = Parcel.obtain(); @@ -5790,6 +5819,21 @@ class ActivityManagerProxy implements IActivityManager } @Override + public Rect getTaskBounds(int taskId) throws RemoteException + { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeInt(taskId); + mRemote.transact(GET_TASK_BOUNDS_TRANSACTION, data, reply, 0); + reply.readException(); + Rect rect = Rect.CREATOR.createFromParcel(reply); + data.recycle(); + reply.recycle(); + return rect; + } + + @Override public Bitmap getTaskDescriptionIcon(String filename) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 55cf3462c5e9..c3e55f1b566e 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -144,6 +144,7 @@ public interface IActivityManager extends IInterface { public boolean isInHomeStack(int taskId) throws RemoteException; public void setFocusedStack(int stackId) throws RemoteException; public int getFocusedStackId() throws RemoteException; + public void setFocusedTask(int taskId) throws RemoteException; public void registerTaskStackListener(ITaskStackListener listener) throws RemoteException; public int getTaskForActivity(IBinder token, boolean onlyRoot) throws RemoteException; public ContentProviderHolder getContentProvider(IApplicationThread caller, @@ -486,6 +487,7 @@ public interface IActivityManager extends IInterface { throws RemoteException; public void setTaskResizeable(int taskId, boolean resizeable) throws RemoteException; public void resizeTask(int taskId, Rect bounds) throws RemoteException; + public Rect getTaskBounds(int taskId) throws RemoteException; public Bitmap getTaskDescriptionIcon(String filename) throws RemoteException; public void startInPlaceAnimationOnFrontMostApplication(ActivityOptions opts) @@ -752,7 +754,7 @@ public interface IActivityManager extends IInterface { int GET_PACKAGE_ASK_SCREEN_COMPAT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+127; int SET_PACKAGE_ASK_SCREEN_COMPAT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+128; int SWITCH_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+129; - int ___AVAILABLE_1___ = IBinder.FIRST_CALL_TRANSACTION+130; + int SET_FOCUSED_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+130; int REMOVE_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+131; int REGISTER_PROCESS_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+132; int UNREGISTER_PROCESS_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+133; @@ -804,7 +806,7 @@ public interface IActivityManager extends IInterface { int RELEASE_PERSISTABLE_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+180; int GET_PERSISTED_URI_PERMISSIONS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+181; int APP_NOT_RESPONDING_VIA_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+182; - // Available + int GET_TASK_BOUNDS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+183; int GET_ACTIVITY_DISPLAY_ID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+184; int DELETE_ACTIVITY_CONTAINER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+185; int SET_PROCESS_MEMORY_TRIM_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+186; diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java index 17db4718bd26..6e3a29da7e69 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java @@ -70,6 +70,7 @@ import com.android.systemui.R; import com.android.systemui.recents.Constants; import com.android.systemui.recents.Recents; import com.android.systemui.recents.RecentsAppWidgetHost; +import com.android.systemui.recents.RecentsConfiguration; import java.io.IOException; import java.util.ArrayList; @@ -255,42 +256,31 @@ public class SystemServicesProxy { return false; } - /** Get the bounds of a stack / task. */ - public Rect getTaskBounds(int stackId) { - ActivityManager.StackInfo info = getAllStackInfos().get(stackId); - if (info != null) - return info.bounds; - return new Rect(); - } - - /** Resize a given task. */ - public void resizeTask(int taskId, Rect bounds) { - if (mIam == null) return; + /** Get the bounds of a task. */ + public Rect getTaskBounds(int taskId) { + if (mIam == null) return null; try { - mIam.resizeTask(taskId, bounds); + return mIam.getTaskBounds(taskId); } catch (RemoteException e) { e.printStackTrace(); } + return null; } - /** Returns the stack info for all stacks. */ - public SparseArray<ActivityManager.StackInfo> getAllStackInfos() { - if (mIam == null) return new SparseArray<ActivityManager.StackInfo>(); + /** Resize a given task. */ + public void resizeTask(int taskId, Rect bounds) { + if (mIam == null) return; try { - SparseArray<ActivityManager.StackInfo> stacks = - new SparseArray<ActivityManager.StackInfo>(); - List<ActivityManager.StackInfo> infos = mIam.getAllStackInfos(); - int stackCount = infos.size(); - for (int i = 0; i < stackCount; i++) { - ActivityManager.StackInfo info = infos.get(i); - stacks.put(info.stackId, info); + if (RecentsConfiguration.getInstance().multiStackEnabled) { + // In debug mode, we force all task to be resizeable regardless of the + // current app configuration. + mIam.setTaskResizeable(taskId, true); } - return stacks; + mIam.resizeTask(taskId, bounds); } catch (RemoteException e) { e.printStackTrace(); - return new SparseArray<ActivityManager.StackInfo>(); } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java index f40c58dfdfeb..b8015c09a585 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java @@ -172,19 +172,13 @@ public class RecentsTaskLoadPlan { } // Initialize the stacks - SparseArray<ActivityManager.StackInfo> stackInfos = mSystemServicesProxy.getAllStackInfos(); mStacks.clear(); int stackCount = stacksTasks.size(); for (int i = 0; i < stackCount; i++) { int stackId = stacksTasks.keyAt(i); - ActivityManager.StackInfo info = stackInfos.get(stackId); ArrayList<Task> stackTasks = stacksTasks.valueAt(i); TaskStack stack = new TaskStack(stackId); - if (Constants.DebugFlags.App.EnableMultiStackToSingleStack) { - stack.setBounds(displayBounds, displayBounds); - } else { - stack.setBounds(info.bounds, displayBounds); - } + stack.setBounds(displayBounds, displayBounds); stack.setTasks(stackTasks); stack.createAffiliatedGroupings(mConfig); mStacks.put(stackId, stack); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java index 6db4020e25c1..353bcbe640f0 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java @@ -224,7 +224,7 @@ public class TaskViewHeader extends FrameLayout { /** Updates the resize task bar button. */ void updateResizeTaskBarIcon(Task t) { Rect display = mSsp.getWindowRect(); - Rect taskRect = mSsp.getTaskBounds(t.key.stackId); + Rect taskRect = mSsp.getTaskBounds(t.key.id); int resId = R.drawable.star; if (display.equals(taskRect) || taskRect.isEmpty()) { resId = R.drawable.vector_drawable_place_fullscreen; diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags index daf17519a8e7..13b3f8da8ff0 100644 --- a/services/core/java/com/android/server/EventLogTags.logtags +++ b/services/core/java/com/android/server/EventLogTags.logtags @@ -158,7 +158,7 @@ option java_package com.android.server # Task removed with source explanation. 31003 wm_task_removed (TaskId|1|5),(Reason|3) # Stack created. -31004 wm_stack_created (StackId|1|5),(RelativeBoxId|1|5),(Position|1),(Weight|1|6) +31004 wm_stack_created (StackId|1|5) # Home stack moved to top (1) or bottom (0). 31005 wm_home_stack_moved (ToTop|1) # Stack removed. diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 755d7a0d9ff5..266e3c71c2f6 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -2695,6 +2695,21 @@ public final class ActivityManagerService extends ActivityManagerNative } } + @Override + public void setFocusedTask(int taskId) { + if (DEBUG_FOCUS) Slog.d(TAG_FOCUS, "setFocusedTask: taskId=" + taskId); + synchronized (ActivityManagerService.this) { + TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId); + if (task != null) { + ActivityRecord r = task.topRunningActivityLocked(null); + if (r != null) { + setFocusedActivityLocked(r, "setFocusedTask"); + mStackSupervisor.resumeTopActivitiesLocked(task.stack, null, null); + } + } + } + } + /** Sets the task stack listener that gets callbacks when a task stack changes. */ @Override public void registerTaskStackListener(ITaskStackListener listener) throws RemoteException { @@ -8575,6 +8590,27 @@ public final class ActivityManagerService extends ActivityManagerNative } @Override + public Rect getTaskBounds(int taskId) { + enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS, + "getTaskBounds()"); + long ident = Binder.clearCallingIdentity(); + Rect rect = new Rect(); + try { + synchronized (this) { + TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId); + if (task == null) { + Slog.w(TAG, "getTaskBounds: taskId=" + taskId + " not found"); + return rect; + } + mWindowManager.getTaskBounds(task.taskId, rect); + } + } finally { + Binder.restoreCallingIdentity(ident); + } + return rect; + } + + @Override public Bitmap getTaskDescriptionIcon(String filename) { if (!FileUtils.isValidExtFilename(filename) || !filename.contains(ActivityRecord.ACTIVITY_ICON_SUFFIX)) { diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 0957eb5af120..9b1044c467dd 100755 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -130,10 +130,10 @@ final class ActivityRecord { long pauseTime; // last time we started pausing the activity long launchTickTime; // base time for launch tick messages Configuration configuration; // configuration activity was last running in - // Overridden configuration by the activity stack - // WARNING: Reference points to {@link ActivityStack#mOverrideConfig}, so its internal state + // Overridden configuration by the activity task + // WARNING: Reference points to {@link TaskRecord#mOverrideConfig}, so its internal state // should never be altered directly. - Configuration stackConfigOverride; + Configuration taskConfigOverride; CompatibilityInfo compat;// last used compatibility mode ActivityRecord resultTo; // who started this entry, so will get our reply final String resultWho; // additional identifier for use by resultTo. @@ -212,7 +212,7 @@ final class ActivityRecord { pw.print(" icon=0x"); pw.print(Integer.toHexString(icon)); pw.print(" theme=0x"); pw.println(Integer.toHexString(theme)); pw.print(prefix); pw.print("config="); pw.println(configuration); - pw.print(prefix); pw.print("stackConfigOverride="); pw.println(stackConfigOverride); + pw.print(prefix); pw.print("taskConfigOverride="); pw.println(taskConfigOverride); if (resultTo != null || resultWho != null) { pw.print(prefix); pw.print("resultTo="); pw.print(resultTo); pw.print(" resultWho="); pw.print(resultWho); @@ -445,8 +445,7 @@ final class ActivityRecord { resolvedType = _resolvedType; componentSpecified = _componentSpecified; configuration = _configuration; - stackConfigOverride = (container != null) - ? container.mStack.mOverrideConfig : Configuration.EMPTY; + taskConfigOverride = Configuration.EMPTY; resultTo = _resultTo; resultWho = _resultWho; requestCode = _reqCode; diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 2b763ed23048..431b4338552b 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -113,11 +113,11 @@ final class ActivityStack { // How long we wait for the activity to tell us it has stopped before // giving up. This is a good amount of time because we really need this // from the application in order to get its saved state. - static final int STOP_TIMEOUT = 10*1000; + static final int STOP_TIMEOUT = 10 * 1000; // How long we wait until giving up on an activity telling us it has // finished destroying itself. - static final int DESTROY_TIMEOUT = 10*1000; + static final int DESTROY_TIMEOUT = 10 * 1000; // How long until we reset a task when the user returns to it. Currently // disabled. @@ -125,7 +125,7 @@ final class ActivityStack { // How long between activity launches that we consider safe to not warn // the user about an unexpected activity being launched on top. - static final long START_WARN_TIME = 5*1000; + static final long START_WARN_TIME = 5 * 1000; // Set to false to disable the preview that is shown while a new activity // is being started. @@ -214,8 +214,7 @@ final class ActivityStack { // Activity.onTranslucentConversionComplete(false). If a timeout occurs prior to the last // background activity being drawn then the same call will be made with a true value. ActivityRecord mTranslucentActivityWaiting = null; - private ArrayList<ActivityRecord> mUndrawnActivitiesBelowTopTranslucent = - new ArrayList<ActivityRecord>(); + private ArrayList<ActivityRecord> mUndrawnActivitiesBelowTopTranslucent = new ArrayList<>(); /** * Set when we know we are going to be calling updateConfiguration() @@ -223,7 +222,7 @@ final class ActivityStack { */ boolean mConfigWillChange; - // Whether or not this stack covers the entire screen; by default stacks are full screen + // Whether or not this stack covers the entire screen; by default stacks are fullscreen boolean mFullscreen = true; long mLaunchStartTime = 0; @@ -241,11 +240,6 @@ final class ActivityStack { /** Run all ActivityStacks through this */ final ActivityStackSupervisor mStackSupervisor; - Configuration mOverrideConfig; - /** True if the stack was forced to full screen because {@link TaskRecord#mResizeable} is false - * and the stack was previously resized. */ - private boolean mForcedFullscreen = false; - static final int PAUSE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 1; static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 2; static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 3; @@ -361,7 +355,6 @@ final class ActivityStack { mStackId = activityContainer.mStackId; mCurrentUser = mService.mCurrentUserId; mRecentTasks = recentTasks; - mOverrideConfig = Configuration.EMPTY; } boolean okToShowLocked(ActivityRecord r) { @@ -1165,16 +1158,18 @@ final class ActivityStack { final int numStacks = mStacks.size(); while (stackNdx < numStacks) { - ActivityStack historyStack = mStacks.get(stackNdx); + final ActivityStack historyStack = mStacks.get(stackNdx); tasks = historyStack.mTaskHistory; final int numTasks = tasks.size(); while (taskNdx < numTasks) { - activities = tasks.get(taskNdx).mActivities; + final TaskRecord currentTask = tasks.get(taskNdx); + activities = currentTask.mActivities; final int numActivities = activities.size(); while (activityNdx < numActivities) { final ActivityRecord activity = activities.get(activityNdx); if (!activity.finishing) { - return historyStack.mFullscreen && activity.fullscreen ? null : activity; + return historyStack.mFullscreen + && currentTask.mFullscreen && activity.fullscreen ? null : activity; } ++activityNdx; } @@ -1222,16 +1217,18 @@ final class ActivityStack { * wallpaper to be shown behind it. */ for (int i = mStacks.indexOf(this) + 1; i < mStacks.size(); i++) { - ActivityStack stack = mStacks.get(i); - // stack above isn't full screen, so, we assume we're still visible. at some point - // we should look at the stack bounds to see if we're occluded even if the stack - // isn't fullscreen + final ActivityStack stack = mStacks.get(i); + // stack above isn't fullscreen, so, we assume we're still visible. if (!stack.mFullscreen) { continue; } final ArrayList<TaskRecord> tasks = stack.getAllTasks(); for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { final TaskRecord task = tasks.get(taskNdx); + // task above isn't fullscreen, so, we assume we're still visible. + if (!task.mFullscreen) { + continue; + } final ArrayList<ActivityRecord> activities = task.mActivities; for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { final ActivityRecord r = activities.get(activityNdx); @@ -1285,6 +1282,10 @@ final class ActivityStack { for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { final TaskRecord task = mTaskHistory.get(taskNdx); final ArrayList<ActivityRecord> activities = task.mActivities; + // Set to true if an activity in this task is fullscreen thereby hiding other + // activities in the same task. Initialized to the same value as behindFullscreen + // which represent if the entire task/stack is behind another fullscreen task/stack. + boolean behindFullscreenActivity = behindFullscreen; for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { final ActivityRecord r = activities.get(activityNdx); if (r.finishing) { @@ -1296,7 +1297,7 @@ final class ActivityStack { aboveTop = false; // mLaunchingBehind: Activities launching behind are at the back of the task stack // but must be drawn initially for the animation as though they were visible. - if (!behindFullscreen || r.mLaunchTaskBehind) { + if (!behindFullscreenActivity || r.mLaunchTaskBehind) { if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make visible? " + r + " finishing=" + r.finishing + " state=" + r.state); @@ -1379,17 +1380,22 @@ final class ActivityStack { configChanges |= r.configChangeFlags; if (r.fullscreen) { - // At this point, nothing else needs to be shown - if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r); - behindFullscreen = true; + // At this point, nothing else needs to be shown in this task. + behindFullscreenActivity = true; + if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r + + " behindFullscreen=" + behindFullscreen + + " behindFullscreenActivity=" + behindFullscreenActivity); } else if (!isHomeStack() && r.frontOfTask && task.isOverHomeStack()) { - if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Showing home: at " + r); - behindFullscreen = true; + behindFullscreenActivity = true; + if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Showing home: at " + r + + " behindFullscreen=" + behindFullscreen + + " behindFullscreenActivity=" + behindFullscreenActivity); } } else { if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, - "Make invisible? " + r + " finishing=" + r.finishing - + " state=" + r.state + " behindFullscreen=" + behindFullscreen); + "Make invisible? " + r + " finishing=" + r.finishing + + " state=" + r.state + " behindFullscreen=" + behindFullscreen + + " behindFullscreenActivity=" + behindFullscreenActivity); // Now for any activities that aren't visible to the user, make // sure they no longer are keeping the screen frozen. if (r.visible) { @@ -1436,6 +1442,9 @@ final class ActivityStack { } } } + // Factoring if the previous task is fullscreen there by affecting the visibility of + // task behind it. + behindFullscreen |= task.mFullscreen; } if (mTranslucentActivityWaiting != null && @@ -3818,29 +3827,12 @@ final class ActivityStack { if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Ensuring correct configuration: " + r); - // Make sure the current stack override configuration is supported by the top task - // before continuing. - final TaskRecord topTask = topTask(); - if (topTask != null && ((topTask.mResizeable && mForcedFullscreen) - || (!topTask.mResizeable && !mFullscreen))) { - final boolean prevFullscreen = mFullscreen; - final Configuration newOverrideConfig = - mWindowManager.forceStackToFullscreen(mStackId, !topTask.mResizeable); - updateOverrideConfiguration(newOverrideConfig); - mForcedFullscreen = !prevFullscreen && mFullscreen; - if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, - "Updated stack config to support task=" + topTask - + " resizeable=" + topTask.mResizeable - + " mForcedFullscreen=" + mForcedFullscreen - + " prevFullscreen=" + prevFullscreen - + " mFullscreen=" + mFullscreen); - } - // Short circuit: if the two configurations are the exact same // object (the common case), then there is nothing to do. - Configuration newConfig = mService.mConfiguration; + final Configuration newConfig = mService.mConfiguration; + final Configuration taskConfig = r.task.mOverrideConfig; if (r.configuration == newConfig - && r.stackConfigOverride == mOverrideConfig + && r.taskConfigOverride == taskConfig && !r.forceNewConfig) { if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Configuration unchanged in " + r); @@ -3858,30 +3850,30 @@ final class ActivityStack { // Okay we now are going to make this activity have the new config. // But then we need to figure out how it needs to deal with that. final Configuration oldConfig = r.configuration; - final Configuration oldStackOverride = r.stackConfigOverride; + final Configuration oldTaskOverride = r.taskConfigOverride; r.configuration = newConfig; - r.stackConfigOverride = mOverrideConfig; + r.taskConfigOverride = taskConfig; // Determine what has changed. May be nothing, if this is a config // that has come back from the app after going idle. In that case // we just want to leave the official config object now in the // activity and do nothing else. - int stackChanges = oldStackOverride.diff(mOverrideConfig); - if (stackChanges == 0) { + int taskChanges = oldTaskOverride.diff(taskConfig); + if (taskChanges == 0) { // {@link Configuration#diff} doesn't catch changes from unset values. // Check for changes we care about. - if (oldStackOverride.orientation != mOverrideConfig.orientation) { - stackChanges |= ActivityInfo.CONFIG_ORIENTATION; + if (oldTaskOverride.orientation != taskConfig.orientation) { + taskChanges |= ActivityInfo.CONFIG_ORIENTATION; } - if (oldStackOverride.screenHeightDp != mOverrideConfig.screenHeightDp - || oldStackOverride.screenWidthDp != mOverrideConfig.screenWidthDp) { - stackChanges |= ActivityInfo.CONFIG_SCREEN_SIZE; + if (oldTaskOverride.screenHeightDp != taskConfig.screenHeightDp + || oldTaskOverride.screenWidthDp != taskConfig.screenWidthDp) { + taskChanges |= ActivityInfo.CONFIG_SCREEN_SIZE; } - if (oldStackOverride.smallestScreenWidthDp != mOverrideConfig.smallestScreenWidthDp) { - stackChanges |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE; + if (oldTaskOverride.smallestScreenWidthDp != taskConfig.smallestScreenWidthDp) { + taskChanges |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE; } } - final int changes = oldConfig.diff(newConfig) | stackChanges; + final int changes = oldConfig.diff(newConfig) | taskChanges; if (changes == 0 && !r.forceNewConfig) { if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Configuration no differences in " + r); @@ -3943,14 +3935,14 @@ final class ActivityStack { } // Default case: the activity can handle this new configuration, so hand it over. - // NOTE: We only forward the stack override configuration as the system level configuration + // NOTE: We only forward the task override configuration as the system level configuration // changes is always sent to all processes when they happen so it can just use whatever // system level configuration it last got. if (r.app != null && r.app.thread != null) { try { if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Sending new config to " + r); r.app.thread.scheduleActivityConfigurationChanged( - r.appToken, new Configuration(mOverrideConfig)); + r.appToken, new Configuration(taskConfig)); } catch (RemoteException e) { // If process died, whatever. } @@ -3984,7 +3976,7 @@ final class ActivityStack { r.forceNewConfig = false; r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents, changes, !andResume, new Configuration(mService.mConfiguration), - new Configuration(mOverrideConfig)); + new Configuration(r.task.mOverrideConfig)); // Note: don't need to call pauseIfSleepingLocked() here, because // the caller will only pass in 'andResume' if this activity is // currently resumed, which implies we aren't sleeping. @@ -4381,16 +4373,6 @@ final class ActivityStack { + " stackId=" + mStackId + ", " + mTaskHistory.size() + " tasks}"; } - boolean updateOverrideConfiguration(Configuration newConfig) { - Configuration oldConfig = mOverrideConfig; - mOverrideConfig = (newConfig == null) ? Configuration.EMPTY : newConfig; - // We override the configuration only when the stack's dimensions are different from - // the display. In this manner, we know that if the override configuration is empty, - // the stack is necessarily full screen. - mFullscreen = Configuration.EMPTY.equals(mOverrideConfig); - return !mOverrideConfig.equals(oldConfig); - } - void onLockTaskPackagesUpdatedLocked() { for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { mTaskHistory.get(taskNdx).setLockTaskAuth(); diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index b1ac7ee0a8b3..e7f28c5cd3df 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -99,6 +99,7 @@ import android.service.voice.IVoiceInteractionSession; import android.util.ArrayMap; import android.util.ArraySet; import android.util.EventLog; +import android.util.IntArray; import android.util.Slog; import android.util.SparseArray; @@ -1283,7 +1284,7 @@ public final class ActivityStackSupervisor implements DisplayListener { app.forceProcessStateUpTo(mService.mTopProcessState); app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken, System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration), - new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage, + new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results, newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo); @@ -2871,60 +2872,63 @@ public final class ActivityStackSupervisor implements DisplayListener { return; } - final Configuration overrideConfig = mWindowManager.resizeStack(stackId, bounds); - if (stack.updateOverrideConfiguration(overrideConfig)) { - if (r != null) { - final boolean updated = stack.ensureActivityConfigurationLocked(r, 0); - // And we need to make sure at this point that all other activities - // are made visible with the correct configuration. - ensureActivitiesVisibleLocked(r, 0); - if (!updated) { - resumeTopActivitiesLocked(stack, null, null); - } + final IntArray changedTaskIds = new IntArray(stack.numTasks()); + final List<Configuration> newTaskConfigs = new ArrayList<>(stack.numTasks()); + stack.mFullscreen = + mWindowManager.resizeStack(stackId, bounds, changedTaskIds, newTaskConfigs); + for (int i = changedTaskIds.size() - 1; i >= 0; i--) { + final TaskRecord task = anyTaskForIdLocked(changedTaskIds.get(i), false); + if (task == null) { + Slog.wtf(TAG, "Task in WindowManager, but not in ActivityManager???"); + continue; + } + task.updateOverrideConfiguration(newTaskConfigs.get(i)); + } + + if (r != null) { + final boolean updated = stack.ensureActivityConfigurationLocked(r, 0); + // And we need to make sure at this point that all other activities + // are made visible with the correct configuration. + ensureActivitiesVisibleLocked(r, 0); + if (!updated) { + resumeTopActivitiesLocked(stack, null, null); } } } - /** Makes sure the input task is in a stack with the specified bounds by either resizing the - * current task stack if it only has one entry, moving the task to a stack that matches the - * bounds, or creating a new stack with the required bounds. Also, makes the task resizeable.*/ void resizeTaskLocked(TaskRecord task, Rect bounds) { - task.mResizeable = true; - final ActivityStack currentStack = task.stack; - if (currentStack.isHomeStack()) { - // Can't move task off the home stack. Sorry! + if (!task.mResizeable) { + Slog.w(TAG, "resizeTask: task " + task + " not resizeable."); return; } - final int matchingStackId = mWindowManager.getStackIdWithBounds(bounds); - if (matchingStackId != -1) { - // There is already a stack with the right bounds! - if (currentStack != null && currentStack.mStackId == matchingStackId) { - // Nothing to do here. Already in the right stack... - return; - } - // Move task to stack with matching bounds. - moveTaskToStackLocked(task.taskId, matchingStackId, true); + if (task.mBounds != null && task.mBounds.equals(bounds)) { + // Nothing to do here... return; } - if (currentStack != null && currentStack.numTasks() == 1) { - // Just resize the current stack since this is the task in it. - resizeStackLocked(currentStack.mStackId, bounds); + task.mBounds = new Rect(bounds); + + if (!mWindowManager.isValidTaskId(task.taskId)) { + // Task doesn't exist in window manager yet (e.g. was restored from recents). + // No need to do anything else until we add the task to window manager. return; } - // Create new stack and move the task to it. - final int displayId = (currentStack != null && currentStack.mDisplayId != -1) - ? currentStack.mDisplayId : Display.DEFAULT_DISPLAY; - ActivityStack newStack = createStackOnDisplay(getNextStackId(), displayId); - - if (newStack == null) { - Slog.e(TAG, "resizeTaskLocked: Can't create stack for task=" + task); - return; + final Configuration overrideConfig = mWindowManager.resizeTask(task.taskId, bounds); + if (task.updateOverrideConfiguration(overrideConfig)) { + ActivityRecord r = task.topRunningActivityLocked(null); + if (r != null) { + final ActivityStack stack = task.stack; + final boolean updated = stack.ensureActivityConfigurationLocked(r, 0); + // And we need to make sure at this point that all other activities + // are made visible with the correct configuration. + ensureActivitiesVisibleLocked(r, 0); + if (!updated) { + resumeTopActivitiesLocked(stack, null, null); + } + } } - moveTaskToStackLocked(task.taskId, newStack.mStackId, true); - resizeStackLocked(newStack.mStackId, bounds); } ActivityStack createStackOnDisplay(int stackId, int displayId) { @@ -2962,7 +2966,7 @@ public final class ActivityStackSupervisor implements DisplayListener { final ArrayList<ActivityStack> homeDisplayStacks = mHomeStack.mStacks; for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack tmpStack = homeDisplayStacks.get(stackNdx); - if (!tmpStack.isHomeStack() && tmpStack.mFullscreen) { + if (!tmpStack.isHomeStack()) { stack = tmpStack; break; } @@ -3789,6 +3793,7 @@ public final class ActivityStackSupervisor implements DisplayListener { final int numTasks = tasks.size(); int[] taskIds = new int[numTasks]; String[] taskNames = new String[numTasks]; + Rect[] taskBounds = new Rect[numTasks]; for (int i = 0; i < numTasks; ++i) { final TaskRecord task = tasks.get(i); taskIds[i] = task.taskId; @@ -3796,6 +3801,8 @@ public final class ActivityStackSupervisor implements DisplayListener { : task.realActivity != null ? task.realActivity.flattenToString() : task.getTopActivity() != null ? task.getTopActivity().packageName : "unknown"; + taskBounds[i] = new Rect(); + mWindowManager.getTaskBounds(task.taskId, taskBounds[i]); } info.taskIds = taskIds; info.taskNames = taskNames; @@ -3811,7 +3818,7 @@ public final class ActivityStackSupervisor implements DisplayListener { } ArrayList<StackInfo> getAllStackInfosLocked() { - ArrayList<StackInfo> list = new ArrayList<StackInfo>(); + ArrayList<StackInfo> list = new ArrayList<>(); for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) { ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; for (int ndx = stacks.size() - 1; ndx >= 0; --ndx) { diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index 7e2ad2969843..a892c7d41ed0 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -40,7 +40,9 @@ import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; +import android.content.res.Configuration; import android.graphics.Bitmap; +import android.graphics.Rect; import android.os.Debug; import android.os.ParcelFileDescriptor; import android.os.RemoteException; @@ -92,6 +94,7 @@ final class TaskRecord { private static final String ATTR_CALLING_PACKAGE = "calling_package"; private static final String ATTR_RESIZEABLE = "resizeable"; private static final String ATTR_PRIVILEGED = "privileged"; + private static final String ATTR_BOUNDS = "bounds"; private static final String TASK_THUMBNAIL_SUFFIX = "_task_thumbnail"; @@ -199,6 +202,14 @@ final class TaskRecord { final ActivityManagerService mService; + // Whether or not this task covers the entire screen; by default tasks are fullscreen. + boolean mFullscreen = true; + + // Bounds of the Task. null for fullscreen tasks. + Rect mBounds = null; + + Configuration mOverrideConfig = Configuration.EMPTY; + TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent, IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor) { mService = service; @@ -252,7 +263,8 @@ final class TaskRecord { long _firstActiveTime, long _lastActiveTime, long lastTimeMoved, boolean neverRelinquishIdentity, TaskDescription _lastTaskDescription, int taskAffiliation, int prevTaskId, int nextTaskId, int taskAffiliationColor, - int callingUid, String callingPackage, boolean resizeable, boolean privileged) { + int callingUid, String callingPackage, boolean resizeable, boolean privileged, + Rect bounds) { mService = service; mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX + TaskPersister.IMAGE_EXTENSION; @@ -289,6 +301,7 @@ final class TaskRecord { mCallingPackage = callingPackage; mResizeable = resizeable; mPrivileged = privileged; + mBounds = bounds; } void touchActiveTime() { @@ -950,6 +963,9 @@ final class TaskRecord { out.attribute(null, ATTR_CALLING_PACKAGE, mCallingPackage == null ? "" : mCallingPackage); out.attribute(null, ATTR_RESIZEABLE, String.valueOf(mResizeable)); out.attribute(null, ATTR_PRIVILEGED, String.valueOf(mPrivileged)); + if (mBounds != null) { + out.attribute(null, ATTR_BOUNDS, mBounds.flattenToString()); + } if (affinityIntent != null) { out.startTag(null, TAG_AFFINITYINTENT); @@ -1010,6 +1026,7 @@ final class TaskRecord { String callingPackage = ""; boolean resizeable = false; boolean privileged = false; + Rect bounds = null; for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) { final String attrName = in.getAttributeName(attrNdx); @@ -1067,6 +1084,8 @@ final class TaskRecord { resizeable = Boolean.valueOf(attrValue); } else if (ATTR_PRIVILEGED.equals(attrName)) { privileged = Boolean.valueOf(attrValue); + } else if (ATTR_BOUNDS.equals(attrName)) { + bounds = Rect.unflattenFromString(attrValue); } else { Slog.w(TAG, "TaskRecord: Unknown attribute=" + attrName); } @@ -1126,7 +1145,7 @@ final class TaskRecord { autoRemoveRecents, askedCompatMode, taskType, userId, effectiveUid, lastDescription, activities, firstActiveTime, lastActiveTime, lastTimeOnTop, neverRelinquishIdentity, taskDescription, taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor, - callingUid, callingPackage, resizeable, privileged); + callingUid, callingPackage, resizeable, privileged, bounds); for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) { activities.get(activityNdx).task = task; @@ -1136,6 +1155,16 @@ final class TaskRecord { return task; } + boolean updateOverrideConfiguration(Configuration newConfig) { + Configuration oldConfig = mOverrideConfig; + mOverrideConfig = (newConfig == null) ? Configuration.EMPTY : newConfig; + // We override the configuration only when the task's dimensions are different from the + // display. In this manner, we know that if the override configuration is empty, the task + // is necessarily fullscreen. + mFullscreen = Configuration.EMPTY.equals(mOverrideConfig); + return !mOverrideConfig.equals(oldConfig); + } + void dump(PrintWriter pw, String prefix) { pw.print(prefix); pw.print("userId="); pw.print(userId); pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid); diff --git a/services/core/java/com/android/server/wm/DimLayer.java b/services/core/java/com/android/server/wm/DimLayer.java index e385be3f3551..538d6b846d46 100644 --- a/services/core/java/com/android/server/wm/DimLayer.java +++ b/services/core/java/com/android/server/wm/DimLayer.java @@ -29,9 +29,6 @@ public class DimLayer { private static final String TAG = "DimLayer"; private static final boolean DEBUG = false; - /** Reference to the owner of this object. */ - final DisplayContent mDisplayContent; - /** Actual surface that dims */ SurfaceControl mDimSurface; @@ -62,13 +59,18 @@ public class DimLayer { /** Time in milliseconds to take to transition from mStartAlpha to mTargetAlpha */ long mDuration; - /** Owning stack */ - final TaskStack mStack; + /** Interface implemented by users of the dim layer */ + interface DimLayerUser { + /** Returns true if the user of the dim layer is fullscreen. */ + boolean isFullscreen(); + /** Returns the display info. of the dim layer user. */ + DisplayInfo getDisplayInfo(); + } + /** The user of this dim layer. */ + final DimLayerUser mUser; - DimLayer(WindowManagerService service, TaskStack stack, DisplayContent displayContent) { - mStack = stack; - mDisplayContent = displayContent; - final int displayId = mDisplayContent.getDisplayId(); + DimLayer(WindowManagerService service, DimLayerUser user, int displayId) { + mUser = user; if (DEBUG) Slog.v(TAG, "Ctor: displayId=" + displayId); SurfaceControl.openTransaction(); try { @@ -145,14 +147,14 @@ public class DimLayer { private void adjustBounds() { final int dw, dh; final float xPos, yPos; - if (!mStack.isFullscreen()) { + if (!mUser.isFullscreen()) { dw = mBounds.width(); dh = mBounds.height(); xPos = mBounds.left; yPos = mBounds.top; } else { // Set surface size to screen size. - final DisplayInfo info = mDisplayContent.getDisplayInfo(); + final DisplayInfo info = mUser.getDisplayInfo(); // Multiply by 1.5 so that rotating a frozen surface that includes this does not expose // a corner. dw = (int) (info.logicalWidth * 1.5); diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 5d6df2679b81..d9786c813c31 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -89,8 +89,8 @@ class DisplayContent { * (except a future lockscreen TaskStack) moves to the top. */ private TaskStack mHomeStack = null; - /** Detect user tapping outside of current focused stack bounds .*/ - StackTapPointerEventListener mTapDetector; + /** Detect user tapping outside of current focused task bounds .*/ + TaskTapPointerEventListener mTapDetector; /** Detect user tapping outside of current focused stack bounds .*/ Region mTouchExcludeRegion = new Region(); @@ -219,24 +219,27 @@ class DisplayContent { mContentRect.set(contentRect); } - int stackIdFromPoint(int x, int y) { + int taskIdFromPoint(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; + final ArrayList<Task> tasks = mStacks.get(stackNdx).getTasks(); + for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { + final Task task = tasks.get(taskNdx); + task.getBounds(mTmpRect); + if (mTmpRect.contains(x, y)) { + return task.mTaskId; + } } } return -1; } - void setTouchExcludeRegion(TaskStack focusedStack) { + void setTouchExcludeRegion(Task focusedTask) { mTouchExcludeRegion.set(mBaseDisplayRect); WindowList windows = getWindowList(); for (int i = windows.size() - 1; i >= 0; --i) { final WindowState win = windows.get(i); - final TaskStack stack = win.getStack(); - if (win.isVisibleLw() && stack != null && stack != focusedStack) { + final Task task = win.getTask(); + if (win.isVisibleLw() && task != null && task != focusedTask) { mTmpRect.set(win.mVisibleFrame); // If no intersection, we need mTmpRect to be unmodified. mTmpRect.intersect(win.mVisibleInsets); @@ -273,21 +276,37 @@ class DisplayContent { boolean animateDimLayers() { boolean result = false; for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - result |= mStacks.get(stackNdx).animateDimLayers(); + final ArrayList<Task> tasks = mStacks.get(stackNdx).getTasks(); + for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { + final Task task = tasks.get(taskNdx); + result |= task.animateDimLayers(); + if (task.isFullscreen()) { + // No point in continuing as this task covers the entire screen. + // Also, fullscreen tasks all share the same dim layer, so we don't want + // processing of fullscreen task below this one affecting the dim layer state. + return result; + } + } } return result; } void resetDimming() { for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - mStacks.get(stackNdx).resetDimmingTag(); + final ArrayList<Task> tasks = mStacks.get(stackNdx).getTasks(); + for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { + tasks.get(taskNdx).clearContinueDimming(); + } } } boolean isDimming() { for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - if (mStacks.get(stackNdx).isDimming()) { - return true; + final ArrayList<Task> tasks = mStacks.get(stackNdx).getTasks(); + for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { + if (tasks.get(taskNdx).isDimming()) { + return true; + } } } return false; @@ -295,7 +314,10 @@ class DisplayContent { void stopDimmingIfNeeded() { for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { - mStacks.get(stackNdx).stopDimmingIfNeeded(); + final ArrayList<Task> tasks = mStacks.get(stackNdx).getTasks(); + for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { + tasks.get(taskNdx).stopDimmingIfNeeded(); + } } } diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java index 1a125d4bfae2..222945c2f594 100644 --- a/services/core/java/com/android/server/wm/DragState.java +++ b/services/core/java/com/android/server/wm/DragState.java @@ -413,7 +413,7 @@ class DragState { continue; } - child.getStackBounds(mTmpRect); + child.getTaskBounds(mTmpRect); if (!mTmpRect.contains(x, y)) { // outside of this window's activity stack == don't tell about drags continue; diff --git a/services/core/java/com/android/server/wm/FocusedStackFrame.java b/services/core/java/com/android/server/wm/FocusedTaskFrame.java index 826fe97a66a4..d8e1095a16b9 100644 --- a/services/core/java/com/android/server/wm/FocusedStackFrame.java +++ b/services/core/java/com/android/server/wm/FocusedTaskFrame.java @@ -33,8 +33,8 @@ import android.view.SurfaceSession; import com.android.server.wm.WindowStateAnimator.SurfaceTrace; -class FocusedStackFrame { - private static final String TAG = "FocusedStackFrame"; +class FocusedTaskFrame { + private static final String TAG = "FocusedTaskFrame"; private static final boolean DEBUG = false; private static final int THICKNESS = 2; private static final float ALPHA = 0.3f; @@ -47,14 +47,14 @@ class FocusedStackFrame { private final Rect mLastBounds = new Rect(); private int mLayer = -1; - public FocusedStackFrame(Display display, SurfaceSession session) { + public FocusedTaskFrame(Display display, SurfaceSession session) { SurfaceControl ctrl = null; try { if (DEBUG_SURFACE_TRACE) { - ctrl = new SurfaceTrace(session, "FocusedStackFrame", + ctrl = new SurfaceTrace(session, "FocusedTaskFrame", 1, 1, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); } else { - ctrl = new SurfaceControl(session, "FocusedStackFrame", + ctrl = new SurfaceControl(session, "FocusedTaskFrame", 1, 1, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); } ctrl.setLayerStack(display.getLayerStack()); @@ -122,11 +122,11 @@ class FocusedStackFrame { } } - void setVisibility(TaskStack stack) { - if (stack == null || stack.isFullscreen()) { + void setVisibility(Task task) { + if (task == null || task.isFullscreen()) { setupSurface(false); } else { - stack.getBounds(mBounds); + task.getBounds(mBounds); setupSurface(true); if (!mBounds.equals(mLastBounds)) { draw(); diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java index ae442e5f8610..21e92c9f3036 100644 --- a/services/core/java/com/android/server/wm/InputMonitor.java +++ b/services/core/java/com/android/server/wm/InputMonitor.java @@ -177,7 +177,7 @@ 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; - child.getStackBounds(mTmpRect); + child.getTaskBounds(mTmpRect); inputWindowHandle.touchableRegion.set(mTmpRect); } else { // Not modal or full screen modal diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 0c3cf65705f2..09d70d88cdef 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -17,13 +17,29 @@ package com.android.server.wm; import static com.android.server.wm.WindowManagerService.TAG; +import static com.android.server.wm.WindowManagerService.DEBUG_RESIZE; import static com.android.server.wm.WindowManagerService.DEBUG_STACK; +import android.content.res.Configuration; +import android.graphics.Rect; +import android.util.DisplayMetrics; import android.util.EventLog; import android.util.Slog; +import android.util.SparseArray; +import android.util.TypedValue; +import android.view.DisplayInfo; +import android.view.Surface; + import com.android.server.EventLogTags; -class Task { +import java.io.PrintWriter; +import java.util.ArrayList; + +class Task implements DimLayer.DimLayerUser { + /** Amount of time in milliseconds to animate the dim surface from one value to another, + * when no window animation is driving it. */ + private static final int DEFAULT_DIM_DURATION = 200; + TaskStack mStack; final AppTokenList mAppTokens = new AppTokenList(); final int mTaskId; @@ -31,11 +47,41 @@ class Task { boolean mDeferRemoval = false; final WindowManagerService mService; + // Content limits relative to the DisplayContent this sits in. + private Rect mBounds = new Rect(); + + // Device rotation as of the last time {@link #mBounds} was set. + int mRotation; + + // Whether mBounds is fullscreen + private boolean mFullscreen = true; + + // Contains configurations settings that are different from the global configuration due to + // stack specific operations. E.g. {@link #setBounds}. + Configuration mOverrideConfig; + + // For comparison with DisplayContent bounds. + private Rect mTmpRect = new Rect(); + // For handling display rotations. + private Rect mTmpRect2 = new Rect(); + + // The particular window with FLAG_DIM_BEHIND set. If null, hide mDimLayer. + WindowStateAnimator mDimWinAnimator; + // Used to support {@link android.view.WindowManager.LayoutParams#FLAG_DIM_BEHIND} + private DimLayer mDimLayer; + // Set to false at the start of performLayoutAndPlaceSurfaces. If it is still false by the end + // then stop any dimming. + private boolean mContinueDimming; + // Shared dim layer for fullscreen tasks. {@link #mDimLayer} will point to this instead + // of creating a new object per fullscreen task on a display. + private static final SparseArray<DimLayer> sSharedFullscreenDimLayers = new SparseArray<>(); + Task(int taskId, TaskStack stack, int userId, WindowManagerService service) { mTaskId = taskId; mStack = stack; mUserId = userId; mService = service; + mOverrideConfig = Configuration.EMPTY; } DisplayContent getDisplayContent() { @@ -107,13 +153,290 @@ class Task { } } + /** Set the task bounds. Passing in null sets the bounds to fullscreen. */ + boolean setBounds(Rect bounds) { + boolean oldFullscreen = mFullscreen; + int rotation = Surface.ROTATION_0; + final DisplayContent displayContent = mStack.getDisplayContent(); + if (displayContent != null) { + displayContent.getLogicalDisplayRect(mTmpRect); + rotation = displayContent.getDisplayInfo().rotation; + if (bounds == null) { + bounds = mTmpRect; + mFullscreen = true; + } else { + // ensure bounds are entirely within the display rect + if (!bounds.intersect(mTmpRect)) { + // Can't set bounds outside the containing display...Sorry! + return false; + } + mFullscreen = mTmpRect.equals(bounds); + } + } + + if (bounds == null) { + // Can't set to fullscreen if we don't have a display to get bounds from... + return false; + } + if (mBounds.equals(bounds) && oldFullscreen == mFullscreen && mRotation == rotation) { + return false; + } + + mBounds.set(bounds); + mRotation = rotation; + updateDimLayer(); + updateOverrideConfiguration(); + return true; + } + + void getBounds(Rect out) { + out.set(mBounds); + } + + private void updateOverrideConfiguration() { + final Configuration serviceConfig = mService.mCurConfiguration; + if (mFullscreen) { + mOverrideConfig = Configuration.EMPTY; + return; + } + + if (mOverrideConfig == Configuration.EMPTY) { + mOverrideConfig = new Configuration(); + } + + // TODO(multidisplay): Update Dp to that of display stack is on. + final float density = serviceConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE; + mOverrideConfig.screenWidthDp = + Math.min((int)(mBounds.width() / density), serviceConfig.screenWidthDp); + mOverrideConfig.screenHeightDp = + Math.min((int)(mBounds.height() / density), serviceConfig.screenHeightDp); + mOverrideConfig.smallestScreenWidthDp = + Math.min(mOverrideConfig.screenWidthDp, mOverrideConfig.screenHeightDp); + mOverrideConfig.orientation = + (mOverrideConfig.screenWidthDp <= mOverrideConfig.screenHeightDp) + ? Configuration.ORIENTATION_PORTRAIT : Configuration.ORIENTATION_LANDSCAPE; + } + + void updateDisplayInfo(final DisplayContent displayContent) { + if (displayContent == null) { + return; + } + if (mFullscreen) { + setBounds(null); + return; + } + final int newRotation = displayContent.getDisplayInfo().rotation; + if (mRotation == newRotation) { + return; + } + + // Device rotation changed. We don't want the task to move around on the screen when + // this happens, so update the task bounds so it stays in the same place. + final int rotationDelta = DisplayContent.deltaRotation(mRotation, newRotation); + displayContent.getLogicalDisplayRect(mTmpRect); + switch (rotationDelta) { + case Surface.ROTATION_0: + mTmpRect2.set(mBounds); + break; + case Surface.ROTATION_90: + mTmpRect2.top = mTmpRect.bottom - mBounds.right; + mTmpRect2.left = mBounds.top; + mTmpRect2.right = mTmpRect2.left + mBounds.height(); + mTmpRect2.bottom = mTmpRect2.top + mBounds.width(); + break; + case Surface.ROTATION_180: + mTmpRect2.top = mTmpRect.bottom - mBounds.bottom; + mTmpRect2.left = mTmpRect.right - mBounds.right; + mTmpRect2.right = mTmpRect2.left + mBounds.width(); + mTmpRect2.bottom = mTmpRect2.top + mBounds.height(); + break; + case Surface.ROTATION_270: + mTmpRect2.top = mBounds.left; + mTmpRect2.left = mTmpRect.right - mBounds.bottom; + mTmpRect2.right = mTmpRect2.left + mBounds.height(); + mTmpRect2.bottom = mTmpRect2.top + mBounds.width(); + break; + } + setBounds(mTmpRect2); + } + + /** Updates the dim layer bounds, recreating it if needed. */ + private void updateDimLayer() { + DimLayer newDimLayer; + final boolean previousFullscreen = + mDimLayer != null && sSharedFullscreenDimLayers.indexOfValue(mDimLayer) > -1; + final int displayId = mStack.getDisplayContent().getDisplayId(); + if (mFullscreen) { + if (previousFullscreen) { + // Nothing to do here... + return; + } + // Use shared fullscreen dim layer + newDimLayer = sSharedFullscreenDimLayers.get(displayId); + if (newDimLayer == null) { + if (mDimLayer != null) { + // Re-purpose the previous dim layer. + newDimLayer = mDimLayer; + } else { + // Create new full screen dim layer. + newDimLayer = new DimLayer(mService, this, displayId); + } + newDimLayer.setBounds(mBounds); + sSharedFullscreenDimLayers.put(displayId, newDimLayer); + } else if (mDimLayer != null) { + mDimLayer.destroySurface(); + } + } else { + newDimLayer = (mDimLayer == null || previousFullscreen) + ? new DimLayer(mService, this, displayId) : mDimLayer; + newDimLayer.setBounds(mBounds); + } + mDimLayer = newDimLayer; + } + + boolean animateDimLayers() { + final int dimLayer; + final float dimAmount; + if (mDimWinAnimator == null) { + dimLayer = mDimLayer.getLayer(); + dimAmount = 0; + } else { + dimLayer = mDimWinAnimator.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM; + dimAmount = mDimWinAnimator.mWin.mAttrs.dimAmount; + } + final float targetAlpha = mDimLayer.getTargetAlpha(); + if (targetAlpha != dimAmount) { + if (mDimWinAnimator == null) { + mDimLayer.hide(DEFAULT_DIM_DURATION); + } else { + long duration = (mDimWinAnimator.mAnimating && mDimWinAnimator.mAnimation != null) + ? mDimWinAnimator.mAnimation.computeDurationHint() + : DEFAULT_DIM_DURATION; + if (targetAlpha > dimAmount) { + duration = getDimBehindFadeDuration(duration); + } + mDimLayer.show(dimLayer, dimAmount, duration); + } + } else if (mDimLayer.getLayer() != dimLayer) { + mDimLayer.setLayer(dimLayer); + } + if (mDimLayer.isAnimating()) { + if (!mService.okToDisplay()) { + // Jump to the end of the animation. + mDimLayer.show(); + } else { + return mDimLayer.stepAnimation(); + } + } + return false; + } + + private long getDimBehindFadeDuration(long duration) { + TypedValue tv = new TypedValue(); + mService.mContext.getResources().getValue( + com.android.internal.R.fraction.config_dimBehindFadeDuration, tv, true); + if (tv.type == TypedValue.TYPE_FRACTION) { + duration = (long)tv.getFraction(duration, duration); + } else if (tv.type >= TypedValue.TYPE_FIRST_INT && tv.type <= TypedValue.TYPE_LAST_INT) { + duration = tv.data; + } + return duration; + } + + void clearContinueDimming() { + mContinueDimming = false; + } + + void setContinueDimming() { + mContinueDimming = true; + } + + boolean getContinueDimming() { + return mContinueDimming; + } + + boolean isDimming() { + return mDimLayer.isDimming(); + } + + boolean isDimming(WindowStateAnimator winAnimator) { + return mDimWinAnimator == winAnimator && isDimming(); + } + + void startDimmingIfNeeded(WindowStateAnimator newWinAnimator) { + // Only set dim params on the highest dimmed layer. + // Don't turn on for an unshown surface, or for any layer but the highest dimmed layer. + if (newWinAnimator.mSurfaceShown && (mDimWinAnimator == null + || !mDimWinAnimator.mSurfaceShown + || mDimWinAnimator.mAnimLayer < newWinAnimator.mAnimLayer)) { + mDimWinAnimator = newWinAnimator; + if (mDimWinAnimator.mWin.mAppToken == null + && !mFullscreen && mStack.getDisplayContent() != null) { + // Dim should cover the entire screen for system windows. + mStack.getDisplayContent().getLogicalDisplayRect(mTmpRect); + mDimLayer.setBounds(mTmpRect); + } + } + } + + void stopDimmingIfNeeded() { + if (!mContinueDimming && isDimming()) { + mDimWinAnimator = null; + mDimLayer.setBounds(mBounds); + } + } + + void close() { + if (mDimLayer != null) { + mDimLayer.destroySurface(); + mDimLayer = null; + } + } + + void resizeWindows() { + final ArrayList<WindowState> resizingWindows = mService.mResizingWindows; + for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) { + final ArrayList<WindowState> windows = mAppTokens.get(activityNdx).allAppWindows; + for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) { + final WindowState win = windows.get(winNdx); + if (!resizingWindows.contains(win)) { + if (DEBUG_RESIZE) Slog.d(TAG, "setBounds: Resizing " + win); + resizingWindows.add(win); + } + } + } + } + boolean showForAllUsers() { final int tokensCount = mAppTokens.size(); return (tokensCount != 0) && mAppTokens.get(tokensCount - 1).showForAllUsers; } @Override + public boolean isFullscreen() { + return mFullscreen; + } + + @Override + public DisplayInfo getDisplayInfo() { + return mStack.getDisplayContent().getDisplayInfo(); + } + + @Override public String toString() { return "{taskId=" + mTaskId + " appTokens=" + mAppTokens + " mdr=" + mDeferRemoval + "}"; } + + public void printTo(String prefix, PrintWriter pw) { + pw.print(prefix); pw.print("taskId="); pw.print(mTaskId); + pw.print(prefix); pw.print("appTokens="); pw.print(mAppTokens); + pw.print(prefix); pw.print("mdr="); pw.println(mDeferRemoval); + if (mDimLayer.isDimming()) { + pw.print(prefix); pw.println("mDimLayer:"); + mDimLayer.printTo(prefix + " ", pw); + pw.print(prefix); pw.print("mDimWinAnimator="); pw.println(mDimWinAnimator); + } else { + pw.println(); + } + } } diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index 45450320828b..90a173ab8ccc 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -22,22 +22,18 @@ import static com.android.server.wm.WindowManagerService.TAG; import android.content.res.Configuration; import android.graphics.Rect; import android.os.Debug; -import android.util.DisplayMetrics; import android.util.EventLog; +import android.util.IntArray; import android.util.Slog; -import android.util.TypedValue; -import android.view.Surface; +import android.view.DisplayInfo; import com.android.server.EventLogTags; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.List; -public class TaskStack { - /** Amount of time in milliseconds to animate the dim surface from one value to another, - * when no window animation is driving it. */ - private static final int DEFAULT_DIM_DURATION = 200; - +public class TaskStack implements DimLayer.DimLayerUser { /** Unique identifier */ final int mStackId; @@ -49,12 +45,10 @@ public class TaskStack { /** The Tasks that define this stack. Oldest Tasks are at the bottom. The ordering must match * mTaskHistory in the ActivityStack with the same mStackId */ - private final ArrayList<Task> mTasks = new ArrayList<Task>(); + private final ArrayList<Task> mTasks = new ArrayList<>(); /** For comparison with DisplayContent bounds. */ private Rect mTmpRect = new Rect(); - /** For handling display rotations. */ - private Rect mTmpRect2 = new Rect(); /** Content limits relative to the DisplayContent this sits in. */ private Rect mBounds = new Rect(); @@ -62,49 +56,22 @@ public class TaskStack { /** Whether mBounds is fullscreen */ private boolean mFullscreen = true; - /** Used to support {@link android.view.WindowManager.LayoutParams#FLAG_DIM_BEHIND} */ - private DimLayer mDimLayer; - - /** The particular window with FLAG_DIM_BEHIND set. If null, hide mDimLayer. */ - WindowStateAnimator mDimWinAnimator; - /** Support for non-zero {@link android.view.animation.Animation#getBackgroundColor()} */ DimLayer mAnimationBackgroundSurface; /** The particular window with an Animation with non-zero background color. */ WindowStateAnimator mAnimationBackgroundAnimator; - /** Set to false at the start of performLayoutAndPlaceSurfaces. If it is still false by the end - * then stop any dimming. */ - boolean mDimmingTag; - /** Application tokens that are exiting, but still on screen for animations. */ final AppTokenList mExitingAppTokens = new AppTokenList(); /** Detach this stack from its display when animation completes. */ boolean mDeferDetach; - // Contains configurations settings that are different from the global configuration due to - // stack specific operations. E.g. {@link #setBounds}. - Configuration mOverrideConfig; - // True if the stack was forced to fullscreen disregarding the override configuration. - private boolean mForceFullscreen; - // The {@link #mBounds} before the stack was forced to fullscreen. Will be restored as the - // stack bounds once the stack is no longer forced to fullscreen. - final private Rect mPreForceFullscreenBounds; - - // Device rotation as of the last time {@link #mBounds} was set. - int mRotation; - TaskStack(WindowManagerService service, int stackId) { mService = service; mStackId = stackId; - mOverrideConfig = Configuration.EMPTY; - mForceFullscreen = false; - mPreForceFullscreenBounds = new Rect(); - // TODO: remove bounds from log, they are always 0. - EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId, mBounds.left, mBounds.top, - mBounds.right, mBounds.bottom); + EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId); } DisplayContent getDisplayContent() { @@ -116,30 +83,39 @@ public class TaskStack { } void resizeWindows() { - 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); - } - } + mTasks.get(taskNdx).resizeWindows(); + } + } + + /** + * Set the bounds of the stack and its containing tasks. + * @param bounds New stack bounds. Passing in null sets the bounds to fullscreen. + * @param changedTaskIds Output list of Ids of tasks that changed in bounds. + * @param newTaskConfigs Output list of new Configuation of the tasks that changed. + * @return True if the stack bounds was changed. + * */ + boolean setBounds(Rect bounds, IntArray changedTaskIds, List<Configuration> newTaskConfigs) { + if (!setBounds(bounds)) { + return false; + } + + // Update bounds of containing tasks. + final Rect newBounds = mFullscreen ? null : mBounds; + for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) { + final Task task = mTasks.get(taskNdx); + if (task.setBounds(newBounds)) { + changedTaskIds.add(task.mTaskId); + newTaskConfigs.add(task.mOverrideConfig); } } + return true; } - /** Set the stack bounds. Passing in null sets the bounds to fullscreen. */ - boolean setBounds(Rect bounds) { + private boolean setBounds(Rect bounds) { boolean oldFullscreen = mFullscreen; - int rotation = Surface.ROTATION_0; if (mDisplayContent != null) { mDisplayContent.getLogicalDisplayRect(mTmpRect); - rotation = mDisplayContent.getDisplayInfo().rotation; if (bounds == null) { bounds = mTmpRect; mFullscreen = true; @@ -157,15 +133,12 @@ public class TaskStack { // Can't set to fullscreen if we don't have a display to get bounds from... return false; } - if (mBounds.equals(bounds) && oldFullscreen == mFullscreen && mRotation == rotation) { + if (mBounds.equals(bounds) && oldFullscreen == mFullscreen) { return false; } - mDimLayer.setBounds(bounds); mAnimationBackgroundSurface.setBounds(bounds); mBounds.set(bounds); - mRotation = rotation; - updateOverrideConfiguration(); return true; } @@ -173,93 +146,13 @@ public class TaskStack { out.set(mBounds); } - private void updateOverrideConfiguration() { - final Configuration serviceConfig = mService.mCurConfiguration; - if (mFullscreen) { - mOverrideConfig = Configuration.EMPTY; - return; - } - - if (mOverrideConfig == Configuration.EMPTY) { - mOverrideConfig = new Configuration(); - } - - // TODO(multidisplay): Update Dp to that of display stack is on. - final float density = serviceConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE; - mOverrideConfig.screenWidthDp = - Math.min((int)(mBounds.width() / density), serviceConfig.screenWidthDp); - mOverrideConfig.screenHeightDp = - Math.min((int)(mBounds.height() / density), serviceConfig.screenHeightDp); - mOverrideConfig.smallestScreenWidthDp = - Math.min(mOverrideConfig.screenWidthDp, mOverrideConfig.screenHeightDp); - mOverrideConfig.orientation = - (mOverrideConfig.screenWidthDp <= mOverrideConfig.screenHeightDp) - ? Configuration.ORIENTATION_PORTRAIT : Configuration.ORIENTATION_LANDSCAPE; - } - void updateDisplayInfo() { - if (mFullscreen) { - setBounds(null); - } else if (mDisplayContent != null) { - final int newRotation = mDisplayContent.getDisplayInfo().rotation; - if (mRotation == newRotation) { - return; - } - - // Device rotation changed. We don't want the stack to move around on the screen when - // this happens, so update the stack bounds so it stays in the same place. - final int rotationDelta = DisplayContent.deltaRotation(mRotation, newRotation); + if (mDisplayContent != null) { mDisplayContent.getLogicalDisplayRect(mTmpRect); - switch (rotationDelta) { - case Surface.ROTATION_0: - mTmpRect2.set(mBounds); - break; - case Surface.ROTATION_90: - mTmpRect2.top = mTmpRect.bottom - mBounds.right; - mTmpRect2.left = mBounds.top; - mTmpRect2.right = mTmpRect2.left + mBounds.height(); - mTmpRect2.bottom = mTmpRect2.top + mBounds.width(); - break; - case Surface.ROTATION_180: - mTmpRect2.top = mTmpRect.bottom - mBounds.bottom; - mTmpRect2.left = mTmpRect.right - mBounds.right; - mTmpRect2.right = mTmpRect2.left + mBounds.width(); - mTmpRect2.bottom = mTmpRect2.top + mBounds.height(); - break; - case Surface.ROTATION_270: - mTmpRect2.top = mBounds.left; - mTmpRect2.left = mTmpRect.right - mBounds.bottom; - mTmpRect2.right = mTmpRect2.left + mBounds.height(); - mTmpRect2.bottom = mTmpRect2.top + mBounds.width(); - break; - } - setBounds(mTmpRect2); - } - } - - boolean isFullscreen() { - return mFullscreen; - } - - /** Forces the stack to fullscreen if input is true, else un-forces the stack from fullscreen. - * Returns true if something happened. - */ - boolean forceFullscreen(boolean forceFullscreen) { - if (mForceFullscreen == forceFullscreen) { - return false; - } - mForceFullscreen = forceFullscreen; - if (forceFullscreen) { - if (mFullscreen) { - return false; - } - mPreForceFullscreenBounds.set(mBounds); - return setBounds(null); - } else { - if (!mFullscreen || mPreForceFullscreenBounds.isEmpty()) { - return false; + mAnimationBackgroundSurface.setBounds(mTmpRect); + for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) { + mTasks.get(taskNdx).updateDisplayInfo(mDisplayContent); } - return setBounds(mPreForceFullscreenBounds); } } @@ -313,6 +206,7 @@ public class TaskStack { mTasks.add(stackNdx, task); task.mStack = this; + task.updateDisplayInfo(mDisplayContent); if (toTop) { mDisplayContent.moveStack(this, true); } @@ -361,8 +255,7 @@ public class TaskStack { } mDisplayContent = displayContent; - mDimLayer = new DimLayer(mService, this, displayContent); - mAnimationBackgroundSurface = new DimLayer(mService, this, displayContent); + mAnimationBackgroundSurface = new DimLayer(mService, this, mDisplayContent.getDisplayId()); updateDisplayInfo(); } @@ -394,98 +287,6 @@ public class TaskStack { mAnimationBackgroundSurface.hide(); } - private long getDimBehindFadeDuration(long duration) { - TypedValue tv = new TypedValue(); - mService.mContext.getResources().getValue( - com.android.internal.R.fraction.config_dimBehindFadeDuration, tv, true); - if (tv.type == TypedValue.TYPE_FRACTION) { - duration = (long)tv.getFraction(duration, duration); - } else if (tv.type >= TypedValue.TYPE_FIRST_INT && tv.type <= TypedValue.TYPE_LAST_INT) { - duration = tv.data; - } - return duration; - } - - boolean animateDimLayers() { - final int dimLayer; - final float dimAmount; - if (mDimWinAnimator == null) { - dimLayer = mDimLayer.getLayer(); - dimAmount = 0; - } else { - dimLayer = mDimWinAnimator.mAnimLayer - WindowManagerService.LAYER_OFFSET_DIM; - dimAmount = mDimWinAnimator.mWin.mAttrs.dimAmount; - } - final float targetAlpha = mDimLayer.getTargetAlpha(); - if (targetAlpha != dimAmount) { - if (mDimWinAnimator == null) { - mDimLayer.hide(DEFAULT_DIM_DURATION); - } else { - long duration = (mDimWinAnimator.mAnimating && mDimWinAnimator.mAnimation != null) - ? mDimWinAnimator.mAnimation.computeDurationHint() - : DEFAULT_DIM_DURATION; - if (targetAlpha > dimAmount) { - duration = getDimBehindFadeDuration(duration); - } - mDimLayer.show(dimLayer, dimAmount, duration); - } - } else if (mDimLayer.getLayer() != dimLayer) { - mDimLayer.setLayer(dimLayer); - } - if (mDimLayer.isAnimating()) { - if (!mService.okToDisplay()) { - // Jump to the end of the animation. - mDimLayer.show(); - } else { - return mDimLayer.stepAnimation(); - } - } - return false; - } - - void resetDimmingTag() { - mDimmingTag = false; - } - - void setDimmingTag() { - mDimmingTag = true; - } - - boolean testDimmingTag() { - return mDimmingTag; - } - - boolean isDimming() { - return mDimLayer.isDimming(); - } - - boolean isDimming(WindowStateAnimator winAnimator) { - return mDimWinAnimator == winAnimator && mDimLayer.isDimming(); - } - - void startDimmingIfNeeded(WindowStateAnimator newWinAnimator) { - // Only set dim params on the highest dimmed layer. - // Don't turn on for an unshown surface, or for any layer but the highest dimmed layer. - if (newWinAnimator.mSurfaceShown && (mDimWinAnimator == null - || !mDimWinAnimator.mSurfaceShown - || mDimWinAnimator.mAnimLayer < newWinAnimator.mAnimLayer)) { - mDimWinAnimator = newWinAnimator; - if (mDimWinAnimator.mWin.mAppToken == null - && !mFullscreen && mDisplayContent != null) { - // Dim should cover the entire screen for system windows. - mDisplayContent.getLogicalDisplayRect(mTmpRect); - mDimLayer.setBounds(mTmpRect); - } - } - } - - void stopDimmingIfNeeded() { - if (!mDimmingTag && isDimming()) { - mDimWinAnimator = null; - mDimLayer.setBounds(mBounds); - } - } - void setAnimationBackground(WindowStateAnimator winAnimator, int color) { int animLayer = winAnimator.mAnimLayer; if (mAnimationBackgroundAnimator == null @@ -514,9 +315,8 @@ public class TaskStack { mAnimationBackgroundSurface.destroySurface(); mAnimationBackgroundSurface = null; } - if (mDimLayer != null) { - mDimLayer.destroySurface(); - mDimLayer = null; + for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) { + mTasks.get(taskNdx).close(); } } @@ -524,21 +324,17 @@ public class TaskStack { pw.print(prefix); pw.print("mStackId="); pw.println(mStackId); pw.print(prefix); pw.print("mDeferDetach="); pw.println(mDeferDetach); for (int taskNdx = 0; taskNdx < mTasks.size(); ++taskNdx) { - pw.print(prefix); pw.println(mTasks.get(taskNdx)); + pw.print(prefix); + mTasks.get(taskNdx).printTo(prefix + " ", pw); } if (mAnimationBackgroundSurface.isDimming()) { pw.print(prefix); pw.println("mWindowAnimationBackgroundSurface:"); mAnimationBackgroundSurface.printTo(prefix + " ", pw); } - if (mDimLayer.isDimming()) { - pw.print(prefix); pw.println("mDimLayer:"); - mDimLayer.printTo(prefix + " ", pw); - pw.print(prefix); pw.print("mDimWinAnimator="); pw.println(mDimWinAnimator); - } if (!mExitingAppTokens.isEmpty()) { pw.println(); pw.println(" Exiting application tokens:"); - for (int i=mExitingAppTokens.size()-1; i>=0; i--) { + for (int i = mExitingAppTokens.size() - 1; i >= 0; i--) { WindowToken token = mExitingAppTokens.get(i); pw.print(" Exiting App #"); pw.print(i); pw.print(' '); pw.print(token); @@ -549,6 +345,16 @@ public class TaskStack { } @Override + public boolean isFullscreen() { + return mFullscreen; + } + + @Override + public DisplayInfo getDisplayInfo() { + return mDisplayContent.getDisplayInfo(); + } + + @Override public String toString() { return "{stackId=" + mStackId + " tasks=" + mTasks + "}"; } diff --git a/services/core/java/com/android/server/wm/StackTapPointerEventListener.java b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java index 1a85993b69af..c97d12f374ad 100644 --- a/services/core/java/com/android/server/wm/StackTapPointerEventListener.java +++ b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java @@ -23,7 +23,7 @@ import android.view.WindowManagerPolicy.PointerEventListener; import com.android.server.wm.WindowManagerService.H; -public class StackTapPointerEventListener implements PointerEventListener { +public class TaskTapPointerEventListener implements PointerEventListener { private static final int TAP_TIMEOUT_MSEC = 300; private static final float TAP_MOTION_SLOP_INCHES = 0.125f; @@ -35,7 +35,7 @@ public class StackTapPointerEventListener implements PointerEventListener { private final WindowManagerService mService; private final DisplayContent mDisplayContent; - public StackTapPointerEventListener(WindowManagerService service, + public TaskTapPointerEventListener(WindowManagerService service, DisplayContent displayContent) { mService = service; mDisplayContent = displayContent; @@ -77,7 +77,7 @@ public class StackTapPointerEventListener implements PointerEventListener { && Math.abs(x - mDownX) < mMotionSlop && Math.abs(y - mDownY) < mMotionSlop && !mTouchExcludeRegion.contains(x, y)) { - mService.mH.obtainMessage(H.TAP_OUTSIDE_STACK, x, y, + mService.mH.obtainMessage(H.TAP_OUTSIDE_TASK, x, y, mDisplayContent).sendToTarget(); } } diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java index 85a962471656..b9740af0d47c 100644 --- a/services/core/java/com/android/server/wm/WindowAnimator.java +++ b/services/core/java/com/android/server/wm/WindowAnimator.java @@ -709,7 +709,7 @@ public class WindowAnimator { mService.scheduleAnimationLocked(); } - mService.setFocusedStackLayer(); + mService.setFocusedTaskLayer(); if (mService.mWatermark != null) { mService.mWatermark.drawIfNeeded(); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 2647244b1e44..320edbe6bf8c 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -70,6 +70,7 @@ import android.provider.Settings; import android.util.ArraySet; import android.util.DisplayMetrics; import android.util.EventLog; +import android.util.IntArray; import android.util.Log; import android.util.Pair; import android.util.Slog; @@ -155,7 +156,6 @@ import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND; -import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; import static android.view.WindowManager.LayoutParams.FLAG_SECURE; @@ -184,7 +184,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR; import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; -import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID; /** {@hide} */ public class WindowManagerService extends IWindowManager.Stub @@ -251,9 +250,9 @@ public class WindowManagerService extends IWindowManager.Stub static final int LAYER_OFFSET_DIM = 1; /** - * FocusedStackFrame layer is immediately above focused window. + * FocusedTaskFrame layer is immediately above focused window. */ - static final int LAYER_OFFSET_FOCUSED_STACK = 1; + static final int LAYER_OFFSET_FOCUSED_TASK = 1; /** * Animation thumbnail is as far as possible below the window above @@ -446,9 +445,9 @@ public class WindowManagerService extends IWindowManager.Stub StrictModeFlash mStrictModeFlash; CircularDisplayMask mCircularDisplayMask; EmulatorDisplayOverlay mEmulatorDisplayOverlay; - FocusedStackFrame mFocusedStackFrame; + FocusedTaskFrame mFocusedTaskFrame; - int mFocusedStackLayer; + int mFocusedTaskLayer; final float[] mTmpFloats = new float[9]; final Rect mTmpContentRect = new Rect(); @@ -991,7 +990,7 @@ public class WindowManagerService extends IWindowManager.Stub SurfaceControl.openTransaction(); try { createWatermarkInTransaction(); - mFocusedStackFrame = new FocusedStackFrame( + mFocusedTaskFrame = new FocusedTaskFrame( getDefaultDisplayContentLocked().getDisplay(), mFxSession); } finally { SurfaceControl.closeTransaction(); @@ -4063,37 +4062,33 @@ public class WindowManagerService extends IWindowManager.Stub } /** Call while in a Surface transaction. */ - void setFocusedStackLayer() { - mFocusedStackLayer = 0; + void setFocusedTaskLayer() { + mFocusedTaskLayer = 0; if (mFocusedApp != null) { final WindowList windows = mFocusedApp.allAppWindows; for (int i = windows.size() - 1; i >= 0; --i) { final WindowState win = windows.get(i); final int animLayer = win.mWinAnimator.mAnimLayer; if (win.mAttachedWindow == null && win.isVisibleLw() && - animLayer > mFocusedStackLayer) { - mFocusedStackLayer = animLayer + LAYER_OFFSET_FOCUSED_STACK; + animLayer > mFocusedTaskLayer) { + mFocusedTaskLayer = animLayer + LAYER_OFFSET_FOCUSED_TASK; } } } - if (DEBUG_LAYERS) Slog.v(TAG, "Setting FocusedStackFrame to layer=" + - mFocusedStackLayer); - mFocusedStackFrame.setLayer(mFocusedStackLayer); + if (DEBUG_LAYERS) Slog.v(TAG, "Setting FocusedTaskFrame to layer=" + mFocusedTaskLayer); + mFocusedTaskFrame.setLayer(mFocusedTaskLayer); } - void setFocusedStackFrame() { - final TaskStack stack; + void setFocusedTaskFrame() { + Task task = null; if (mFocusedApp != null) { - final Task task = mFocusedApp.mTask; - stack = task.mStack; + task = mFocusedApp.mTask; final DisplayContent displayContent = task.getDisplayContent(); if (displayContent != null) { - displayContent.setTouchExcludeRegion(stack); + displayContent.setTouchExcludeRegion(task); } - } else { - stack = null; } - mFocusedStackFrame.setVisibility(stack); + mFocusedTaskFrame.setVisibility(task); } @Override @@ -4121,11 +4116,11 @@ public class WindowManagerService extends IWindowManager.Stub if (changed) { mFocusedApp = newFocus; mInputMonitor.setFocusedAppLw(newFocus); - setFocusedStackFrame(); + setFocusedTaskFrame(); if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setFocusedApp"); SurfaceControl.openTransaction(); try { - setFocusedStackLayer(); + setFocusedTaskLayer(); } finally { SurfaceControl.closeTransaction(); if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> CLOSE TRANSACTION setFocusedApp"); @@ -5233,71 +5228,78 @@ public class WindowManagerService extends IWindowManager.Stub } } + public void getStackBounds(int stackId, Rect bounds) { + synchronized (mWindowMap) { + final TaskStack stack = mStackIdToStack.get(stackId); + if (stack != null) { + stack.getBounds(bounds); + return; + } + bounds.setEmpty(); + } + } + /** - * Re-sizes the specified stack and its containing windows. - * Returns a {@link Configuration} object that contains configurations settings - * that should be overridden due to the operation. - */ - public Configuration resizeStack(int stackId, Rect bounds) { + * Re-sizes a stack and its containing tasks. + * @param stackId Id of stack to resize. + * @param bounds New stack bounds. Passing in null sets the bounds to fullscreen. + * @param changedTaskIds Output list of Ids of tasks that changed in bounds due to resize. + * @param newTaskConfigs Output list of new Configuation of the tasks that changed. + * @return True if the stack is now fullscreen. + * */ + public boolean resizeStack( + int stackId, Rect bounds, IntArray changedTaskIds, List<Configuration> newTaskConfigs) { synchronized (mWindowMap) { final TaskStack stack = mStackIdToStack.get(stackId); if (stack == null) { throw new IllegalArgumentException("resizeStack: stackId " + stackId + " not found."); } - if (stack.setBounds(bounds)) { + if (stack.setBounds(bounds, changedTaskIds, newTaskConfigs)) { stack.resizeWindows(); stack.getDisplayContent().layoutNeeded = true; performLayoutAndPlaceSurfacesLocked(); } - return new Configuration(stack.mOverrideConfig); + return stack.isFullscreen(); } } - public void getStackBounds(int stackId, Rect bounds) { - final TaskStack stack = mStackIdToStack.get(stackId); - if (stack != null) { - stack.getBounds(bounds); - return; + /** + * Re-sizes the specified task and its containing windows. + * Returns a {@link Configuration} object that contains configurations settings + * that should be overridden due to the operation. + */ + public Configuration resizeTask(int taskId, Rect bounds) { + synchronized (mWindowMap) { + Task task = mTaskIdToTask.get(taskId); + if (task == null) { + throw new IllegalArgumentException("resizeTask: taskId " + taskId + + " not found."); + } + if (task.setBounds(bounds)) { + task.resizeWindows(); + task.getDisplayContent().layoutNeeded = true; + performLayoutAndPlaceSurfacesLocked(); + } + return new Configuration(task.mOverrideConfig); } - bounds.setEmpty(); } - /** Returns the id of an application (non-home stack) stack that match the input bounds. - * -1 if no stack matches.*/ - public int getStackIdWithBounds(Rect bounds) { - Rect stackBounds = new Rect(); + public void getTaskBounds(int taskId, Rect bounds) { synchronized (mWindowMap) { - for (int i = mStackIdToStack.size() - 1; i >= 0; --i) { - TaskStack stack = mStackIdToStack.valueAt(i); - if (stack.mStackId != HOME_STACK_ID) { - stack.getBounds(stackBounds); - if (stackBounds.equals(bounds)) { - return stack.mStackId; - } - } + Task task = mTaskIdToTask.get(taskId); + if (task != null) { + task.getBounds(bounds); + return; } + bounds.setEmpty(); } - return -1; } - /** Forces the stack to fullscreen if input is true, else un-forces the stack from fullscreen. - * Returns a {@link Configuration} object that contains configurations settings - * that should be overridden due to the operation. - */ - public Configuration forceStackToFullscreen(int stackId, boolean forceFullscreen) { + /** Return true if the input task id represents a valid window manager task. */ + public boolean isValidTaskId(int taskId) { synchronized (mWindowMap) { - final TaskStack stack = mStackIdToStack.get(stackId); - if (stack == null) { - throw new IllegalArgumentException("resizeStack: stackId " + stackId - + " not found."); - } - if (stack.forceFullscreen(forceFullscreen)) { - stack.resizeWindows(); - stack.getDisplayContent().layoutNeeded = true; - performLayoutAndPlaceSurfacesLocked(); - } - return new Configuration(stack.mOverrideConfig); + return mTaskIdToTask.get(taskId) != null; } } @@ -6249,7 +6251,7 @@ public class WindowManagerService extends IWindowManager.Stub int right = wf.right - cr.right; int bottom = wf.bottom - cr.bottom; frame.union(left, top, right, bottom); - ws.getStackBounds(stackBounds); + ws.getTaskBounds(stackBounds); if (!frame.intersect(stackBounds)) { // Set frame empty if there's no intersection. frame.setEmpty(); @@ -7708,7 +7710,7 @@ public class WindowManagerService extends IWindowManager.Stub public static final int DO_DISPLAY_CHANGED = 29; public static final int CLIENT_FREEZE_TIMEOUT = 30; - public static final int TAP_OUTSIDE_STACK = 31; + public static final int TAP_OUTSIDE_TASK = 31; public static final int NOTIFY_ACTIVITY_DRAWN = 32; public static final int ALL_WINDOWS_DRAWN = 33; @@ -8170,14 +8172,14 @@ public class WindowManagerService extends IWindowManager.Stub } break; - case TAP_OUTSIDE_STACK: { - int stackId; + case TAP_OUTSIDE_TASK: { + int taskId; synchronized (mWindowMap) { - stackId = ((DisplayContent)msg.obj).stackIdFromPoint(msg.arg1, msg.arg2); + taskId = ((DisplayContent)msg.obj).taskIdFromPoint(msg.arg1, msg.arg2); } - if (stackId >= 0) { + if (taskId >= 0) { try { - mActivityManager.setFocusedStack(stackId); + mActivityManager.setFocusedTask(taskId); } catch (RemoteException e) { } } @@ -8877,8 +8879,8 @@ public class WindowManagerService extends IWindowManager.Stub layerChanged = true; anyLayerChanged = true; } - final TaskStack stack = w.getStack(); - if (layerChanged && stack != null && stack.isDimming(winAnimator)) { + final Task task = w.getTask(); + if (layerChanged && task != null && task.isDimming(winAnimator)) { // Force an animation pass just to update the mDimLayer layer. scheduleAnimationLocked(); } @@ -9768,14 +9770,14 @@ public class WindowManagerService extends IWindowManager.Stub && w.isDisplayedLw() && !w.mExiting) { final WindowStateAnimator winAnimator = w.mWinAnimator; - final TaskStack stack = w.getStack(); - if (stack == null) { + final Task task = w.getTask(); + if (task == null) { return; } - stack.setDimmingTag(); - if (!stack.isDimming(winAnimator)) { + task.setContinueDimming(); + if (!task.isDimming(winAnimator)) { if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming."); - stack.startDimmingIfNeeded(winAnimator); + task.startDimmingIfNeeded(winAnimator); } } } @@ -9927,7 +9929,7 @@ public class WindowManagerService extends IWindowManager.Stub } // FIRST LOOP: Perform a layout, if needed. - if (repeats < 4) { + if (repeats < LAYOUT_REPEAT_THRESHOLD) { performLayoutLockedInner(displayContent, repeats == 1, false /*updateInputWindows*/); } else { @@ -9962,8 +9964,8 @@ public class WindowManagerService extends IWindowManager.Stub final int N = windows.size(); for (i=N-1; i>=0; i--) { WindowState w = windows.get(i); - final TaskStack stack = w.getStack(); - if (stack == null && w.getAttrs().type != TYPE_PRIVATE_PRESENTATION) { + final Task task = w.getTask(); + if (task == null && w.getAttrs().type != TYPE_PRIVATE_PRESENTATION) { continue; } @@ -9975,7 +9977,7 @@ public class WindowManagerService extends IWindowManager.Stub handleNotObscuredLocked(w, innerDw, innerDh); } - if (stack != null && !stack.testDimmingTag()) { + if (task != null && !task.getContinueDimming()) { handleFlagDimBehind(w); } @@ -10369,7 +10371,7 @@ public class WindowManagerService extends IWindowManager.Stub if (updateInputWindowsNeeded) { mInputMonitor.updateInputWindowsLw(false /*force*/); } - setFocusedStackFrame(); + setFocusedTaskFrame(); // Check to see if we are now in a state where the screen should // be enabled, because the window obscured flags have changed. @@ -11428,7 +11430,8 @@ public class WindowManagerService extends IWindowManager.Stub boolean dumpWindows(PrintWriter pw, String name, String[] args, int opti, boolean dumpAll) { WindowList windows = new WindowList(); - if ("visible".equals(name)) { + if ("visible".equals(name) || "visible-apps".equals(name)) { + final boolean appsOnly = "visible-apps".equals(name); synchronized(mWindowMap) { final int numDisplays = mDisplayContents.size(); for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { @@ -11436,7 +11439,8 @@ public class WindowManagerService extends IWindowManager.Stub mDisplayContents.valueAt(displayNdx).getWindowList(); for (int winNdx = windowList.size() - 1; winNdx >= 0; --winNdx) { final WindowState w = windowList.get(winNdx); - if (w.mWinAnimator.mSurfaceShown) { + if (w.mWinAnimator.mSurfaceShown + && (!appsOnly || (appsOnly && w.mAppToken != null))) { windows.add(w); } } @@ -11561,6 +11565,7 @@ public class WindowManagerService extends IWindowManager.Stub pw.println(" Window hex object identifier, or"); pw.println(" \"all\" for all windows, or"); pw.println(" \"visible\" for the visible windows."); + pw.println(" \"visible-apps\" for the visible app windows."); pw.println(" -a: include all available server state."); return; } else { @@ -11711,7 +11716,7 @@ public class WindowManagerService extends IWindowManager.Stub // TODO: Create an input channel for each display with touch capability. if (displayId == Display.DEFAULT_DISPLAY) { - displayContent.mTapDetector = new StackTapPointerEventListener(this, displayContent); + displayContent.mTapDetector = new TaskTapPointerEventListener(this, displayContent); registerPointerEventListener(displayContent.mTapDetector); } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index c2548de64ec2..f7bf6e4b5a4a 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -535,10 +535,10 @@ final class WindowState implements WindowManagerPolicy.WindowState { Rect osf) { mHaveFrame = true; - final TaskStack stack = mAppToken != null ? getStack() : null; - final boolean nonFullscreenStack = stack != null && !stack.isFullscreen(); - if (nonFullscreenStack) { - stack.getBounds(mContainingFrame); + final Task task = mAppToken != null ? getTask() : null; + final boolean nonFullscreenTask = task != null && !task.isFullscreen(); + if (nonFullscreenTask) { + task.getBounds(mContainingFrame); final WindowState imeWin = mService.mInputMethodWindow; if (imeWin != null && imeWin.isVisibleNow() && mService.mInputMethodTarget == this && mContainingFrame.bottom > cf.bottom) { @@ -626,7 +626,7 @@ final class WindowState implements WindowManagerPolicy.WindowState { y = mAttrs.y; } - if (nonFullscreenStack) { + if (nonFullscreenTask) { // Make sure window fits in containing frame since it is in a non-fullscreen stack as // required by {@link Gravity#apply} call. w = Math.min(w, pw); @@ -856,27 +856,33 @@ final class WindowState implements WindowManagerPolicy.WindowState { return displayContent.getDisplayId(); } - TaskStack getStack() { + Task getTask() { AppWindowToken wtoken = mAppToken == null ? mService.mFocusedApp : mAppToken; - if (wtoken != null) { - Task task = wtoken.mTask; - if (task != null) { - if (task.mStack != null) { - return task.mStack; - } - Slog.e(TAG, "getStack: mStack null for task=" + task); - } else { - Slog.e(TAG, "getStack: " + this + " couldn't find task for " + wtoken - + " Callers=" + Debug.getCallers(4)); + if (wtoken == null) { + Slog.e(TAG, "getTask: " + this + " null wtoken " + " Callers=" + Debug.getCallers(5)); + return null; + } + final Task task = wtoken.mTask; + if (task == null) Slog.e(TAG, "getStack: " + this + " couldn't find task for " + wtoken + + " Callers=" + Debug.getCallers(5)); + return task; + } + + TaskStack getStack() { + Task task = getTask(); + if (task != null) { + if (task.mStack != null) { + return task.mStack; } + Slog.e(TAG, "getStack: mStack null for task=" + task); } return mDisplayContent.getHomeStack(); } - void getStackBounds(Rect bounds) { - final TaskStack stack = getStack(); - if (stack != null) { - stack.getBounds(bounds); + void getTaskBounds(Rect bounds) { + final Task task = getTask(); + if (task != null) { + task.getBounds(bounds); return; } bounds.set(mFrame); @@ -1139,9 +1145,9 @@ final class WindowState implements WindowManagerPolicy.WindowState { } boolean isConfigChanged() { - final TaskStack stack = getStack(); + final Task task = getTask(); final Configuration overrideConfig = - (stack != null) ? stack.mOverrideConfig : Configuration.EMPTY; + (task != null) ? task.mOverrideConfig : Configuration.EMPTY; final Configuration serviceConfig = mService.mCurConfiguration; boolean configChanged = (mConfiguration != serviceConfig && mConfiguration.diff(serviceConfig) != 0) @@ -1387,11 +1393,11 @@ final class WindowState implements WindowManagerPolicy.WindowState { @Override public boolean isDimming() { - TaskStack stack = getStack(); - if (stack == null) { + Task task = getTask(); + if (task == null) { return false; } - return stack.isDimming(mWinAnimator); + return task.isDimming(mWinAnimator); } public void setShowToOwnerOnlyLocked(boolean showToOwnerOnly) { @@ -1489,9 +1495,9 @@ final class WindowState implements WindowManagerPolicy.WindowState { if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, "Reporting new frame to " + this + ": " + mCompatFrame); boolean configChanged = isConfigChanged(); - final TaskStack stack = getStack(); + final Task task = getTask(); final Configuration overrideConfig = - (stack != null) ? stack.mOverrideConfig : Configuration.EMPTY; + (task != null) ? task.mOverrideConfig : Configuration.EMPTY; if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) && configChanged) { Slog.i(TAG, "Sending new config to window " + this + ": " + mWinAnimator.mSurfaceW + "x" + mWinAnimator.mSurfaceH + " / config=" diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 3251a56d860e..31ee869245b2 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -169,9 +169,6 @@ class WindowStateAnimator { /** Set when the window has been shown in the screen the first time. */ static final int HAS_DRAWN = 4; - private static final int SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN = - View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; - String drawStateToString() { switch (mDrawState) { case NO_SURFACE: return "NO_SURFACE"; @@ -1418,9 +1415,9 @@ class WindowStateAnimator { mAnimator.setPendingLayoutChanges(w.getDisplayId(), WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); if ((w.mAttrs.flags & LayoutParams.FLAG_DIM_BEHIND) != 0) { - final TaskStack stack = w.getStack(); - if (stack != null) { - stack.startDimmingIfNeeded(this); + final Task task = w.getTask(); + if (task != null) { + task.startDimmingIfNeeded(this); } } } catch (RuntimeException e) { |