From d8665f2327ad9e0b2f723e21d1857893111fed9c Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Tue, 10 Apr 2018 00:34:24 +0200 Subject: [PATCH] Fix issues with duplicate starting window add requests There might be cases where we have multiple requests to add a starting window. To protect against this, we a) Check for existing startingWindow when adding starting window b) Don't send the message if we already an add request pending c) Remove any pending requests when we handle one request There was already existing logic in place that checked whether we have a starting window. However, that doesn't cover the case when requests are pending, but the window hasn't been added yet. Test: Open settings, open any sub-activity, go home, kill settings, reopen settings. This generates a duplicate add request almost guaranteed. Test: go/wm-smoke Fixes: 75030092 Change-Id: I5cb7fc0a4e7ab13dce3766be6afe1aa4f85df2e7 --- .../server/wm/AppWindowContainerController.java | 118 ++++++++++++--------- .../android/server/wm/WindowManagerService.java | 4 + 2 files changed, 69 insertions(+), 53 deletions(-) diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java index 1575694dc825..165a409028d6 100644 --- a/services/core/java/com/android/server/wm/AppWindowContainerController.java +++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java @@ -113,63 +113,73 @@ public class AppWindowContainerController mListener.onWindowsGone(); }; - private final Runnable mAddStartingWindow = () -> { - final StartingData startingData; - final AppWindowToken container; + private final Runnable mAddStartingWindow = new Runnable() { - synchronized (mWindowMap) { - if (mContainer == null) { - if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "mContainer was null while trying to" - + " add starting window"); - return; - } - startingData = mContainer.startingData; - container = mContainer; - } + @Override + public void run() { + final StartingData startingData; + final AppWindowToken container; + + synchronized (mWindowMap) { + if (mContainer == null) { + if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "mContainer was null while trying to" + + " add starting window"); + return; + } - if (startingData == null) { - // Animation has been canceled... do nothing. - if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "startingData was nulled out before handling" - + " mAddStartingWindow: " + mContainer); - return; - } + // There can only be one adding request, silly caller! + mService.mAnimationHandler.removeCallbacks(this); - if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Add starting " - + this + ": startingData=" + container.startingData); + startingData = mContainer.startingData; + container = mContainer; + } - StartingSurface surface = null; - try { - surface = startingData.createStartingSurface(container); - } catch (Exception e) { - Slog.w(TAG_WM, "Exception when adding starting window", e); - } - if (surface != null) { - boolean abort = false; - synchronized(mWindowMap) { - // If the window was successfully added, then - // we need to remove it. - if (container.removed || container.startingData == null) { - if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, - "Aborted starting " + container - + ": removed=" + container.removed - + " startingData=" + container.startingData); - container.startingWindow = null; - container.startingData = null; - abort = true; - } else { - container.startingSurface = surface; - } - if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG_WM, - "Added starting " + mContainer - + ": startingWindow=" - + container.startingWindow + " startingView=" - + container.startingSurface); + if (startingData == null) { + // Animation has been canceled... do nothing. + if (DEBUG_STARTING_WINDOW) + Slog.v(TAG_WM, "startingData was nulled out before handling" + + " mAddStartingWindow: " + mContainer); + return; } - if (abort) { - surface.remove(); + + if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Add starting " + + AppWindowContainerController.this + ": startingData=" + + container.startingData); + + StartingSurface surface = null; + try { + surface = startingData.createStartingSurface(container); + } catch (Exception e) { + Slog.w(TAG_WM, "Exception when adding starting window", e); + } + if (surface != null) { + boolean abort = false; + synchronized (mWindowMap) { + // If the window was successfully added, then + // we need to remove it. + if (container.removed || container.startingData == null) { + if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, + "Aborted starting " + container + + ": removed=" + container.removed + + " startingData=" + container.startingData); + container.startingWindow = null; + container.startingData = null; + abort = true; + } else { + container.startingSurface = surface; + } + if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG_WM, + "Added starting " + mContainer + + ": startingWindow=" + + container.startingWindow + " startingView=" + + container.startingSurface); + } + if (abort) { + surface.remove(); + } + } else if (DEBUG_STARTING_WINDOW) { + Slog.v(TAG_WM, "Surface returned was null: " + mContainer); } - } else if (DEBUG_STARTING_WINDOW) { - Slog.v(TAG_WM, "Surface returned was null: " + mContainer); } }; @@ -558,8 +568,10 @@ public class AppWindowContainerController // Note: we really want to do sendMessageAtFrontOfQueue() because we // want to process the message ASAP, before any other queued // messages. - if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Enqueueing ADD_STARTING"); - mService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow); + if (!mService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) { + if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Enqueueing ADD_STARTING"); + mService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow); + } } private boolean createSnapshot(TaskSnapshot snapshot) { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index bfe8c59674d7..ec6dca36eb9a 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -1224,6 +1224,10 @@ public class WindowManagerService extends IWindowManager.Stub Slog.w(TAG_WM, "Attempted to add window with exiting application token " + token + ". Aborting."); return WindowManagerGlobal.ADD_APP_EXITING; + } else if (type == TYPE_APPLICATION_STARTING && atoken.startingWindow != null) { + Slog.w(TAG_WM, "Attempted to add starting window to token with already existing" + + " starting window"); + return WindowManagerGlobal.ADD_DUPLICATE_ADD; } } else if (rootType == TYPE_INPUT_METHOD) { if (token.windowType != TYPE_INPUT_METHOD) { -- 2.11.0