diff options
6 files changed, 83 insertions, 8 deletions
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 0b22bd4edadc..80a75ce74312 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -1868,6 +1868,9 @@ public final class ActivityStackSupervisor implements DisplayListener { mTmpInsetBounds.put(task.taskId, tempTaskInsetBounds); } } + + // We might trigger a configuration change. Save the current task bounds for freezing. + mWindowManager.prepareFreezingTaskBounds(stack.mStackId); stack.mFullscreen = mWindowManager.resizeStack(stack.mStackId, bounds, mTmpConfigs, mTmpBounds, mTmpInsetBounds); stack.setBounds(bounds); diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index 9b9f14bee982..573aaec034cf 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -31,6 +31,7 @@ import com.android.server.wm.WindowManagerService.H; import android.annotation.NonNull; import android.content.pm.ActivityInfo; +import android.graphics.Rect; import android.os.Message; import android.os.RemoteException; import android.util.Slog; @@ -39,6 +40,7 @@ import android.view.View; import android.view.WindowManager; import java.io.PrintWriter; +import java.util.ArrayDeque; import java.util.ArrayList; class AppTokenList extends ArrayList<AppWindowToken> { @@ -126,6 +128,8 @@ class AppWindowToken extends WindowToken { boolean mAlwaysFocusable; + ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>(); + AppWindowToken(WindowManagerService _service, IApplicationToken _token, boolean _voiceInteraction) { super(_service, _token.asBinder(), @@ -437,6 +441,23 @@ class AppWindowToken extends WindowToken { } } + /** + * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds + * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even + * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen + * with a queue. + */ + void freezeBounds() { + mFrozenBounds.offer(new Rect(mTask.mPreparedFrozenBounds)); + } + + /** + * Unfreezes the previously frozen bounds. See {@link #freezeBounds}. + */ + void unfreezeBounds() { + mFrozenBounds.remove(); + } + @Override void dump(PrintWriter pw, String prefix) { super.dump(pw, prefix); @@ -483,6 +504,9 @@ class AppWindowToken extends WindowToken { pw.print(" startingDisplayed="); pw.print(startingDisplayed); pw.print(" startingMoved"); pw.println(startingMoved); } + if (!mFrozenBounds.isEmpty()) { + pw.print(prefix); pw.print("mFrozenBounds="); pw.print(mFrozenBounds); + } } @Override diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 6e65ac19589c..223e03ad4cc4 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -61,6 +61,7 @@ class Task implements DimLayer.DimLayerUser { // Content limits relative to the DisplayContent this sits in. private Rect mBounds = new Rect(); + final Rect mPreparedFrozenBounds = new Rect(); // Bounds used to calculate the insets. private final Rect mTempInsetBounds = new Rect(); @@ -200,8 +201,7 @@ class Task implements DimLayer.DimLayerUser { boolean removeAppToken(AppWindowToken wtoken) { boolean removed = mAppTokens.remove(wtoken); if (mAppTokens.size() == 0) { - EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, - "removeAppToken: last token"); + EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "removeAppToken: last token"); if (mDeferRemoval) { removeLocked(); } @@ -314,6 +314,14 @@ class Task implements DimLayer.DimLayerUser { return true; } + /** + * Prepares the task bounds to be frozen with the current size. See + * {@link AppWindowToken#freezeBounds}. + */ + void prepareFreezingBounds() { + mPreparedFrozenBounds.set(mBounds); + } + boolean scrollLocked(Rect bounds) { // shift the task bound if it doesn't fully cover the stack area mStack.getDimBounds(mTmpRect); @@ -601,5 +609,6 @@ class Task implements DimLayer.DimLayerUser { pw.print(prefix + prefix); pw.print("mBounds="); pw.println(mBounds.toShortString()); pw.print(prefix + prefix); pw.print("mdr="); pw.println(mDeferRemoval); pw.print(prefix + prefix); pw.print("appTokens="); pw.println(mAppTokens); + pw.print(prefix + prefix); pw.print("mTempInsetBounds="); pw.println(mTempInsetBounds); } } diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index e481d116a69f..67debe6e3773 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -148,6 +148,13 @@ public class TaskStack implements DimLayer.DimLayerUser { return true; } + void prepareFreezingTaskBounds() { + for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) { + final Task task = mTasks.get(taskNdx); + task.prepareFreezingBounds(); + } + } + boolean isFullscreenBounds(Rect bounds) { if (mDisplayContent == null || bounds == null) { return true; diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index ccde6061d6d6..be753354a6f8 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -203,7 +203,6 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEYGUARD; -import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RESIZE; @@ -4843,6 +4842,17 @@ public class WindowManagerService extends IWindowManager.Stub } } + public void prepareFreezingTaskBounds(int stackId) { + synchronized (mWindowMap) { + final TaskStack stack = mStackIdToStack.get(stackId); + if (stack == null) { + throw new IllegalArgumentException("prepareFreezingTaskBounds: stackId " + stackId + + " not found."); + } + stack.prepareFreezingTaskBounds(); + } + } + public void positionTaskInStack(int taskId, int stackId, int position, Rect bounds, Configuration config) { synchronized (mWindowMap) { @@ -9472,8 +9482,8 @@ public class WindowManagerService extends IWindowManager.Stub public void notifyAppRelaunching(IBinder token) { synchronized (mWindowMap) { AppWindowToken appWindow = findAppWindowToken(token); - if (appWindow != null) { - // TODO: Do something useful + if (canFreezeBounds(appWindow)) { + appWindow.freezeBounds(); } } } @@ -9481,12 +9491,20 @@ public class WindowManagerService extends IWindowManager.Stub public void notifyAppRelaunchingFinished(IBinder token) { synchronized (mWindowMap) { AppWindowToken appWindow = findAppWindowToken(token); - if (appWindow != null) { - // TODO: Do something useful + if (canFreezeBounds(appWindow)) { + appWindow.unfreezeBounds(); } } } + private boolean canFreezeBounds(AppWindowToken appWindow) { + + // For freeform windows, we can't freeze the bounds at the moment because this would make + // the resizing unresponsive. + return appWindow != null && appWindow.mTask != null + && !appWindow.mTask.inFreeformWorkspace(); + } + void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) { pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)"); mPolicy.dump(" ", pw, args); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 0eb1c6e7d9d9..e51080e7f230 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -624,6 +624,14 @@ final class WindowState implements WindowManagerPolicy.WindowState { } else { task.getBounds(mContainingFrame); task.getTempInsetBounds(mInsetFrame); + if (mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) { + + // If the bounds are frozen, we still want to translate the window freely and only + // freeze the size. + Rect frozen = mAppToken.mFrozenBounds.peek(); + mContainingFrame.right = mContainingFrame.left + frozen.width(); + mContainingFrame.bottom = mContainingFrame.top + frozen.height(); + } final WindowState imeWin = mService.mInputMethodWindow; if (imeWin != null && imeWin.isVisibleNow() && mService.mInputMethodTarget == this && mContainingFrame.bottom > cf.bottom) { @@ -2029,7 +2037,13 @@ final class WindowState implements WindowManagerPolicy.WindowState { if (task.isDragResizing()) { return true; } - return mDisplayContent.mDividerControllerLocked.isResizing() && + + // If the bounds are currently frozen, it means that the layout size that the app sees + // and the bounds we clip this window to might be different. In order to avoid holes, we + // simulate that we are still resizing so the app fills the hole with the resizing + // background. + return (mDisplayContent.mDividerControllerLocked.isResizing() + || mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) && !task.inFreeformWorkspace() && !task.isFullscreen(); } |