From 0b46f3c72c324bc9b8890ed9b81951bbeec70fdd Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Mon, 14 Mar 2016 12:21:37 +0100 Subject: [PATCH] Implement transition for docking task in recents #2 - Put window into resizing mode when docking it from recents, so it fills the "void". - Send whole task bitmap window as the thumbnail, to make the transition smoother. Bug: 27607141 Change-Id: Ib647d44d9777f1155deab818d1fd5425c1bdd3d1 --- .../systemui/recents/misc/SystemServicesProxy.java | 5 +- .../recents/views/RecentsTransitionHelper.java | 53 ++++++++++---- .../systemui/recents/views/RecentsView.java | 8 ++- .../systemui/recents/views/TaskStackView.java | 2 +- .../android/server/am/ActivityManagerService.java | 69 ++++-------------- .../android/server/am/ActivityStackSupervisor.java | 81 ++++++++++++++++++++++ .../java/com/android/server/wm/DragResizeMode.java | 53 ++++++++++++++ services/core/java/com/android/server/wm/Task.java | 12 +++- .../java/com/android/server/wm/TaskPositioner.java | 5 +- .../android/server/wm/WindowManagerService.java | 23 +++++- .../java/com/android/server/wm/WindowState.java | 16 +++-- .../com/android/server/wm/WindowStateAnimator.java | 4 +- 12 files changed, 240 insertions(+), 91 deletions(-) create mode 100644 services/core/java/com/android/server/wm/DragResizeMode.java 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 88975dd34e68..9f93dbb278c9 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java @@ -403,13 +403,14 @@ public class SystemServicesProxy { /** Docks a task to the side of the screen and starts it. */ public void startTaskInDockedMode(Context context, View view, int taskId, int createMode, - Handler handler, OnAnimationStartedListener startedListener) { + Bitmap headerBitmap, Handler handler, OnAnimationStartedListener startedListener) { if (mIam == null) return; try { // TODO: Determine what animation we want for the incoming task final ActivityOptions options = ActivityOptions.makeThumbnailAspectScaleUpAnimation( - view, null, 0, 0, view.getWidth(), view.getHeight(), handler, startedListener); + view, headerBitmap, 0, 0, (int) (view.getWidth() * view.getScaleX()), + (int) (view.getHeight() * view.getScaleY()), handler, startedListener); options.setDockCreateMode(createMode); options.setLaunchStackId(DOCKED_STACK_ID); mIam.startActivityFromRecents(taskId, options.toBundle()); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java index 29da476db955..c661a2bbb895 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java @@ -319,6 +319,43 @@ public class RecentsTransitionHelper { return new AppTransitionAnimationSpec(task.key.id, null, taskRect); } + public static Bitmap composeTaskBitmap(TaskView taskView, TaskViewTransform transform) { + float scale = transform.scale; + int fromWidth = (int) (transform.rect.width() * scale); + int fromHeight = (int) (transform.rect.height() * scale); + Bitmap b = Bitmap.createBitmap(fromWidth, fromHeight, + Bitmap.Config.ARGB_8888); + + if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) { + b.eraseColor(0xFFff0000); + } else { + Canvas c = new Canvas(b); + c.scale(scale, scale); + taskView.draw(c); + c.setBitmap(null); + } + return b.createAshmemBitmap(); + } + + private static Bitmap composeHeaderBitmap(TaskView taskView, + TaskViewTransform transform) { + float scale = transform.scale; + int fromHeaderWidth = (int) (transform.rect.width()); + int fromHeaderHeight = (int) (taskView.mHeaderView.getMeasuredHeight() * scale); + Bitmap b = Bitmap.createBitmap(fromHeaderWidth, fromHeaderHeight, + Bitmap.Config.ARGB_8888); + + if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) { + b.eraseColor(0xFFff0000); + } else { + Canvas c = new Canvas(b); + c.scale(scale, scale); + taskView.mHeaderView.draw(c); + c.setBitmap(null); + } + return b.createAshmemBitmap(); + } + /** * Composes a single animation spec for the given {@link TaskView} */ @@ -326,21 +363,7 @@ public class RecentsTransitionHelper { TaskView taskView, TaskViewTransform transform, boolean addHeaderBitmap) { Bitmap b = null; if (addHeaderBitmap) { - float scale = transform.scale; - int fromHeaderWidth = (int) (transform.rect.width()); - int fromHeaderHeight = (int) (taskView.mHeaderView.getMeasuredHeight() * scale); - b = Bitmap.createBitmap(fromHeaderWidth, fromHeaderHeight, - Bitmap.Config.ARGB_8888); - - if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) { - b.eraseColor(0xFFff0000); - } else { - Canvas c = new Canvas(b); - c.scale(scale, scale); - taskView.mHeaderView.draw(c); - c.setBitmap(null); - } - b = b.createAshmemBitmap(); + b = composeHeaderBitmap(taskView, transform); } Rect taskRect = new Rect(); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java index 178b23eea0ad..5a27dfaf8737 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -52,10 +52,8 @@ import com.android.systemui.recents.RecentsActivityLaunchState; import com.android.systemui.recents.RecentsConfiguration; import com.android.systemui.recents.RecentsDebugFlags; import com.android.systemui.recents.events.EventBus; -import com.android.systemui.recents.events.EventBus.Event; import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted; import com.android.systemui.recents.events.activity.DockedFirstAnimationFrameEvent; -import com.android.systemui.recents.events.activity.DockedTopTaskEvent; import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent; import com.android.systemui.recents.events.activity.HideStackActionButtonEvent; import com.android.systemui.recents.events.activity.LaunchTaskEvent; @@ -493,7 +491,7 @@ public class RecentsView extends FrameLayout { stackLayout.getStackTransform(event.task, stackScroller.getStackScroll(), tmpTransform, null); tmpTransform.alpha = 0; - tmpTransform.scale = 1f; + tmpTransform.scale = TaskStackView.DRAG_SCALE_FACTOR; tmpTransform.rect.set(taskViewRect); final OnAnimationStartedListener startedListener = new OnAnimationStartedListener() { @Override @@ -510,8 +508,12 @@ public class RecentsView extends FrameLayout { public void onAnimationEnd(Animator animation) { // Dock the task and launch it SystemServicesProxy ssp = Recents.getSystemServices(); + TaskViewTransform transform = new TaskViewTransform(); + transform.fillIn(event.taskView); ssp.startTaskInDockedMode(getContext(), event.taskView, event.task.key.id, dockState.createMode, + RecentsTransitionHelper.composeTaskBitmap( + event.taskView, transform), mHandler, startedListener); } })); diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java index c9cc1e99977e..bea47f14a6bf 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -109,7 +109,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal public static final int DEFAULT_SYNC_STACK_DURATION = 200; private static final int DRAG_SCALE_DURATION = 175; - private static final float DRAG_SCALE_FACTOR = 1.05f; + static final float DRAG_SCALE_FACTOR = 1.05f; private static final int LAUNCH_NEXT_SCROLL_BASE_DURATION = 216; private static final int LAUNCH_NEXT_SCROLL_INCR_DURATION = 32; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index c28f8abdcfd1..6841ae9bb578 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -4494,65 +4494,14 @@ public final class ActivityManagerService extends ActivityManagerNative } final long origId = Binder.clearCallingIdentity(); try { - return startActivityFromRecentsInner(taskId, bOptions); + synchronized (this) { + return mStackSupervisor.startActivityFromRecentsInner(taskId, bOptions); + } } finally { Binder.restoreCallingIdentity(origId); } } - final int startActivityFromRecentsInner(int taskId, Bundle bOptions) { - final TaskRecord task; - final int callingUid; - final String callingPackage; - final Intent intent; - final int userId; - synchronized (this) { - final ActivityOptions activityOptions = (bOptions != null) - ? new ActivityOptions(bOptions) : null; - final int launchStackId = (activityOptions != null) - ? activityOptions.getLaunchStackId() : INVALID_STACK_ID; - - if (launchStackId == HOME_STACK_ID) { - throw new IllegalArgumentException("startActivityFromRecentsInner: Task " - + taskId + " can't be launch in the home stack."); - } - task = mStackSupervisor.anyTaskForIdLocked(taskId, RESTORE_FROM_RECENTS, launchStackId); - if (task == null) { - throw new IllegalArgumentException( - "startActivityFromRecentsInner: Task " + taskId + " not found."); - } - - if (launchStackId != INVALID_STACK_ID) { - if (launchStackId == DOCKED_STACK_ID && activityOptions != null) { - mWindowManager.setDockedStackCreateState( - activityOptions.getDockCreateMode(), null /* initialBounds */); - mStackSupervisor.deferUpdateBounds(HOME_STACK_ID); - mWindowManager.prepareAppTransition(TRANSIT_DOCK_TASK_FROM_RECENTS, false); - } - if (task.stack.mStackId != launchStackId) { - mStackSupervisor.moveTaskToStackLocked( - taskId, launchStackId, ON_TOP, FORCE_FOCUS, "startActivityFromRecents", - ANIMATE); - } - } - - // If the user must confirm credentials (e.g. when first launching a work app and the - // Work Challenge is present) let startActivityInPackage handle the intercepting. - if (!mUserController.shouldConfirmCredentials(task.userId) - && task.getRootActivity() != null) { - moveTaskToFrontLocked(task.taskId, 0, bOptions); - return ActivityManager.START_TASK_TO_FRONT; - } - callingUid = task.mCallingUid; - callingPackage = task.mCallingPackage; - intent = task.intent; - intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY); - userId = task.userId; - } - return startActivityInPackage(callingUid, callingPackage, intent, null, null, null, 0, 0, - bOptions, userId, null, task); - } - final int startActivityInPackage(int uid, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, Bundle bOptions, int userId, @@ -21053,12 +21002,16 @@ public final class ActivityManagerService extends ActivityManagerNative @Override public void notifyAppTransitionFinished() { - mStackSupervisor.continueUpdateBounds(HOME_STACK_ID); + synchronized (ActivityManagerService.this) { + mStackSupervisor.notifyAppTransitionDone(); + } } @Override public void notifyAppTransitionCancelled() { - mStackSupervisor.continueUpdateBounds(HOME_STACK_ID); + synchronized (ActivityManagerService.this) { + mStackSupervisor.notifyAppTransitionDone(); + } } } @@ -21148,7 +21101,9 @@ public final class ActivityManagerService extends ActivityManagerNative // Will bring task to front if it already has a root activity. final long origId = Binder.clearCallingIdentity(); try { - startActivityFromRecentsInner(mTaskId, null); + synchronized (this) { + mStackSupervisor.startActivityFromRecentsInner(mTaskId, null); + } } finally { Binder.restoreCallingIdentity(origId); } diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 175cba7dd099..22e10b10e149 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -52,6 +52,7 @@ import android.hardware.display.VirtualDisplay; import android.hardware.input.InputManager; import android.hardware.input.InputManagerInternal; import android.os.Binder; +import android.os.Bundle; import android.os.Debug; import android.os.Handler; import android.os.IBinder; @@ -169,6 +170,7 @@ import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE; import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV; import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE; import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_WHITELISTED; +import static com.android.server.wm.AppTransition.TRANSIT_DOCK_TASK_FROM_RECENTS; public final class ActivityStackSupervisor implements DisplayListener { private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStackSupervisor" : TAG_AM; @@ -425,6 +427,11 @@ public final class ActivityStackSupervisor implements DisplayListener { boolean mAppVisibilitiesChangedSinceLastPause; /** + * Set of tasks that are in resizing mode during an app transition to fill the "void". + */ + private final ArraySet mResizingTasksDuringAnimation = new ArraySet<>(); + + /** * Description of a request to start a new activity, which has been held * due to app switches being disabled. */ @@ -1955,6 +1962,17 @@ public final class ActivityStackSupervisor implements DisplayListener { } } + void notifyAppTransitionDone() { + continueUpdateBounds(HOME_STACK_ID); + for (int i = mResizingTasksDuringAnimation.size() - 1; i >= 0; i--) { + final int taskId = mResizingTasksDuringAnimation.valueAt(i); + if (anyTaskForIdLocked(taskId) != null) { + mWindowManager.setTaskDockedResizing(taskId, false); + } + } + mResizingTasksDuringAnimation.clear(); + } + void resizeStackUncheckedLocked(ActivityStack stack, Rect bounds, Rect tempTaskBounds, Rect tempTaskInsetBounds) { bounds = TaskRecord.validateBounds(bounds); @@ -4168,4 +4186,67 @@ public final class ActivityStackSupervisor implements DisplayListener { throw new IllegalStateException("Failed to find a stack behind stack=" + stack + " in=" + stacks); } + + final int startActivityFromRecentsInner(int taskId, Bundle bOptions) { + final TaskRecord task; + final int callingUid; + final String callingPackage; + final Intent intent; + final int userId; + final ActivityOptions activityOptions = (bOptions != null) + ? new ActivityOptions(bOptions) : null; + final int launchStackId = (activityOptions != null) + ? activityOptions.getLaunchStackId() : INVALID_STACK_ID; + + if (launchStackId == HOME_STACK_ID) { + throw new IllegalArgumentException("startActivityFromRecentsInner: Task " + + taskId + " can't be launch in the home stack."); + } + task = anyTaskForIdLocked(taskId, RESTORE_FROM_RECENTS, launchStackId); + if (task == null) { + throw new IllegalArgumentException( + "startActivityFromRecentsInner: Task " + taskId + " not found."); + } + + if (launchStackId != INVALID_STACK_ID) { + if (launchStackId == DOCKED_STACK_ID) { + mWindowManager.setDockedStackCreateState( + activityOptions.getDockCreateMode(), null /* initialBounds */); + + // Defer updating the stack in which recents is until the app transition is done, to + // not run into issues where we still need to draw the task in recents but the + // docked stack is already created. + deferUpdateBounds(HOME_STACK_ID); + mWindowManager.prepareAppTransition(TRANSIT_DOCK_TASK_FROM_RECENTS, false); + } + if (task.stack.mStackId != launchStackId) { + moveTaskToStackLocked( + taskId, launchStackId, ON_TOP, FORCE_FOCUS, "startActivityFromRecents", + ANIMATE); + } + } + + // If the user must confirm credentials (e.g. when first launching a work app and the + // Work Challenge is present) let startActivityInPackage handle the intercepting. + if (!mService.mUserController.shouldConfirmCredentials(task.userId) + && task.getRootActivity() != null) { + mService.moveTaskToFrontLocked(task.taskId, 0, bOptions); + + // If we are launching the task in the docked stack, put it into resizing mode so + // the window renders full-screen with the background filling the void. Also only + // call this at the end to make sure that tasks exists on the window manager side. + if (launchStackId == DOCKED_STACK_ID) { + mResizingTasksDuringAnimation.add(task.taskId); + mWindowManager.setTaskDockedResizing(task.taskId, true); + } + return ActivityManager.START_TASK_TO_FRONT; + } + callingUid = task.mCallingUid; + callingPackage = task.mCallingPackage; + intent = task.intent; + intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY); + userId = task.userId; + return mService.startActivityInPackage(callingUid, callingPackage, intent, null, null, null, + 0, 0, bOptions, userId, null, task); + } } diff --git a/services/core/java/com/android/server/wm/DragResizeMode.java b/services/core/java/com/android/server/wm/DragResizeMode.java new file mode 100644 index 000000000000..08acf9d87229 --- /dev/null +++ b/services/core/java/com/android/server/wm/DragResizeMode.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.server.wm; + +import static android.app.ActivityManager.StackId.DOCKED_STACK_ID; +import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID; +import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID; +import static android.app.ActivityManager.StackId.HOME_STACK_ID; + +/** + * Describes the mode in which a window is drag resizing. + */ +class DragResizeMode { + + /** + * Freeform mode: Client surface is fullscreen, and client is responsible to draw window at + * the correct position. + */ + static final int DRAG_RESIZE_MODE_FREEFORM = 0; + + /** + * Mode for resizing the docked (and adjacent) stack: Client surface is fullscreen, but window + * is drawn at (0, 0), window manager is responsible for positioning the surface when draging. + */ + static final int DRAG_RESIZE_MODE_DOCKED_DIVIDER = 1; + + static boolean isModeAllowedForStack(int stackId, int mode) { + switch (mode) { + case DRAG_RESIZE_MODE_FREEFORM: + return stackId == FREEFORM_WORKSPACE_STACK_ID; + case DRAG_RESIZE_MODE_DOCKED_DIVIDER: + return stackId == DOCKED_STACK_ID + || stackId == FULLSCREEN_WORKSPACE_STACK_ID + || stackId == HOME_STACK_ID; + default: + return false; + } + } +} diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index f63796e71a05..4e8f19e5fbfd 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -101,6 +101,7 @@ class Task implements DimLayer.DimLayerUser { // Whether the task is currently being drag-resized private boolean mDragResizing; + private int mDragResizeMode; private boolean mHomeTask; @@ -507,9 +508,14 @@ class Task implements DimLayer.DimLayerUser { mStack.getDisplayContent().getLogicalDisplayRect(out); } - void setDragResizing(boolean dragResizing) { + void setDragResizing(boolean dragResizing, int dragResizeMode) { if (mDragResizing != dragResizing) { + if (!DragResizeMode.isModeAllowedForStack(mStack.mStackId, dragResizeMode)) { + throw new IllegalArgumentException("Drag resize mode not allow for stack stackId=" + + mStack.mStackId + " dragResizeMode=" + dragResizeMode); + } mDragResizing = dragResizing; + mDragResizeMode = dragResizeMode; resetDragResizingChangeReported(); } } @@ -528,6 +534,10 @@ class Task implements DimLayer.DimLayerUser { return mDragResizing || (mStack != null && mStack.isDragResizing()); } + int getDragResizeMode() { + return mDragResizeMode; + } + void updateDisplayInfo(final DisplayContent displayContent) { if (displayContent == null) { return; diff --git a/services/core/java/com/android/server/wm/TaskPositioner.java b/services/core/java/com/android/server/wm/TaskPositioner.java index 92701dee699d..ae70aa8fa6b7 100644 --- a/services/core/java/com/android/server/wm/TaskPositioner.java +++ b/services/core/java/com/android/server/wm/TaskPositioner.java @@ -29,6 +29,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import static com.android.server.wm.WindowManagerService.dipToPixel; +import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM; import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP; import static com.android.server.wm.WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP; @@ -379,7 +380,7 @@ class TaskPositioner implements DimLayer.DimLayerUser { private void endDragLocked() { mResizing = false; - mTask.setDragResizing(false); + mTask.setDragResizing(false, DRAG_RESIZE_MODE_FREEFORM); } /** Returns true if the move operation should be ended. */ @@ -409,7 +410,7 @@ class TaskPositioner implements DimLayer.DimLayerUser { bottom = Math.max(top + mMinVisibleHeight, bottom + deltaY); } mWindowDragBounds.set(left, top, right, bottom); - mTask.setDragResizing(true); + mTask.setDragResizing(true, DRAG_RESIZE_MODE_FREEFORM); return false; } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 4bbbe2d153b7..63edb7a675c2 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -202,6 +202,8 @@ import static android.view.WindowManagerPolicy.TRANSIT_EXIT; import static android.view.WindowManagerPolicy.TRANSIT_PREVIEW_DONE; import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_END; import static com.android.server.wm.AppWindowAnimator.PROLONG_ANIMATION_AT_START; +import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER; +import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; @@ -2927,9 +2929,9 @@ public class WindowManagerService extends IWindowManager.Stub } } final boolean freeformResizing = win.isDragResizing() - && win.getResizeMode() == WindowState.DRAG_RESIZE_MODE_FREEFORM; + && win.getResizeMode() == DRAG_RESIZE_MODE_FREEFORM; final boolean dockedResizing = win.isDragResizing() - && win.getResizeMode() == WindowState.DRAG_RESIZE_MODE_DOCKED_DIVIDER; + && win.getResizeMode() == DRAG_RESIZE_MODE_DOCKED_DIVIDER; result |= freeformResizing ? WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_FREEFORM : 0; result |= dockedResizing ? WindowManagerGlobal.RELAYOUT_RES_DRAG_RESIZING_DOCKED : 0; if (win.isAnimatingWithSavedSurface()) { @@ -4996,6 +4998,23 @@ public class WindowManagerService extends IWindowManager.Stub } } + /** + * Puts a specific task into docked drag resizing mode. See {@link DragResizeMode}. + * + * @param taskId The id of the task to put into drag resize mode. + * @param resizing Whether to put the task into drag resize mode. + */ + public void setTaskDockedResizing(int taskId, boolean resizing) { + synchronized (mWindowMap) { + Task task = mTaskIdToTask.get(taskId); + if (task == null) { + throw new IllegalArgumentException("setTaskDockedResizing: taskId " + taskId + + " not found."); + } + task.setDragResizing(resizing, DRAG_RESIZE_MODE_DOCKED_DIVIDER); + } + } + public void scrollTask(int taskId, Rect bounds) { synchronized (mWindowMap) { Task task = mTaskIdToTask.get(taskId); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 362f3ff893a6..a302006964a1 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -88,6 +88,8 @@ import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; +import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER; +import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS; @@ -124,9 +126,6 @@ final class WindowState implements WindowManagerPolicy.WindowState { // to capture touch events in that area. static final int RESIZE_HANDLE_WIDTH_IN_DP = 30; - static final int DRAG_RESIZE_MODE_FREEFORM = 0; - static final int DRAG_RESIZE_MODE_DOCKED_DIVIDER = 1; - static final boolean DEBUG_DISABLE_SAVING_SURFACES = false; final WindowManagerService mService; @@ -2278,9 +2277,14 @@ final class WindowState implements WindowManagerPolicy.WindowState { return; } mDragResizing = resizing; - mResizeMode = mDragResizing && mDisplayContent.mDividerControllerLocked.isResizing() - ? DRAG_RESIZE_MODE_DOCKED_DIVIDER - : DRAG_RESIZE_MODE_FREEFORM; + final Task task = getTask(); + if (task != null && task.isDragResizing()) { + mResizeMode = task.getDragResizeMode(); + } else { + mResizeMode = mDragResizing && mDisplayContent.mDividerControllerLocked.isResizing() + ? DRAG_RESIZE_MODE_DOCKED_DIVIDER + : DRAG_RESIZE_MODE_FREEFORM; + } } boolean isDragResizing() { diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 83b61046b7c2..1e103f0573e0 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -20,6 +20,8 @@ import static android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; import static android.view.WindowManager.LayoutParams.FLAG_SCALED; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; +import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER; +import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS; @@ -38,8 +40,6 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER; import static com.android.server.wm.WindowManagerService.localLOGV; import static com.android.server.wm.WindowManagerService.logWithStack; -import static com.android.server.wm.WindowState.DRAG_RESIZE_MODE_DOCKED_DIVIDER; -import static com.android.server.wm.WindowState.DRAG_RESIZE_MODE_FREEFORM; import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE; import static com.android.server.wm.WindowSurfacePlacer.SET_TURN_ON_SCREEN; -- 2.11.0