From ba41f4b9e3629c097cdd7b6538c5bcf4602728b8 Mon Sep 17 00:00:00 2001 From: Jorim Jaggi Date: Wed, 14 Dec 2016 17:43:07 -0800 Subject: [PATCH] Clean up starting window to prepare for saved surfaces - Move all starting window logic to AppWindowContainerController - Use startingView to hold any kind of contents for startingWindow - Remove some conflicting code which looks very old and doesn't apply anymore. Test: Make sure starting window still works. Bug: 31339431 Change-Id: I018dd013ab7e64a44932b6d54ae9bb4a47f315d3 --- core/java/android/view/WindowManagerPolicy.java | 27 ++-- .../android/server/policy/PhoneWindowManager.java | 36 ++--- .../android/server/policy/SplashScreenSurface.java | 38 +++++ .../server/wm/AppWindowContainerController.java | 144 ++++++++++++++++-- .../java/com/android/server/wm/AppWindowToken.java | 65 ++++---- .../com/android/server/wm/RootWindowContainer.java | 5 +- .../android/server/wm/WindowManagerService.java | 165 --------------------- .../com/android/server/wm/WindowStateAnimator.java | 11 +- .../com/android/server/wm/WindowSurfacePlacer.java | 5 +- .../android/server/wm/TestWindowManagerPolicy.java | 52 ++++--- 10 files changed, 268 insertions(+), 280 deletions(-) create mode 100644 services/core/java/com/android/server/policy/SplashScreenSurface.java diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index caa09cccbab1..dd852567360f 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -437,6 +437,15 @@ public interface WindowManagerPolicy { } /** + * Holds the contents of a starting window. {@link #addSplashScreen} needs to wrap the + * contents of the starting window into an class implementing this interface, which then will be + * held by WM and passed into {@link #removeSplashScreen} when the starting window is no + * longer needed. + */ + interface StartingSurface { + } + + /** * Interface for calling back in to the window manager that is private * between it and the policy. */ @@ -738,17 +747,17 @@ public interface WindowManagerPolicy { * context to for resources. * * @return Optionally you can return the View that was used to create the - * window, for easy removal in removeStartingWindow. + * window, for easy removal in removeSplashScreen. * - * @see #removeStartingWindow + * @see #removeSplashScreen */ - public View addStartingWindow(IBinder appToken, String packageName, - int theme, CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, - int labelRes, int icon, int logo, int windowFlags, Configuration overrideConfig); + public StartingSurface addSplashScreen(IBinder appToken, String packageName, int theme, + CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon, + int logo, int windowFlags, Configuration overrideConfig); /** * Called when the first window of an application has been displayed, while - * {@link #addStartingWindow} has created a temporary initial window for + * {@link #addSplashScreen} has created a temporary initial window for * that application. You should at this point remove the window from the * window manager. This is called without the window manager locked so * that you can call back into it. @@ -759,11 +768,11 @@ public interface WindowManagerPolicy { * even if you previously returned one. * * @param appToken Token of the application that has started. - * @param window Window View that was returned by createStartingWindow. + * @param surface Surface that was returned by {@link #addSplashScreen}. * - * @see #addStartingWindow + * @see #addSplashScreen */ - public void removeStartingWindow(IBinder appToken, View window); + public void removeSplashScreen(IBinder appToken, StartingSurface surface); /** * Prepare for a window being added to the window manager. You can throw an diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index fa1d991fa39a..0a312f0ad7ee 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -251,9 +251,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { static final boolean DEBUG_INPUT = false; static final boolean DEBUG_KEYGUARD = false; static final boolean DEBUG_LAYOUT = false; - static final boolean DEBUG_STARTING_WINDOW = false; + static final boolean DEBUG_SPLASH_SCREEN = false; static final boolean DEBUG_WAKEUP = false; - static final boolean SHOW_STARTING_ANIMATIONS = true; + static final boolean SHOW_SPLASH_SCREENS = true; // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key. // No longer recommended for desk docks; @@ -2794,10 +2794,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ @Override - public View addStartingWindow(IBinder appToken, String packageName, int theme, - CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, - int icon, int logo, int windowFlags, Configuration overrideConfig) { - if (!SHOW_STARTING_ANIMATIONS) { + public StartingSurface addSplashScreen(IBinder appToken, String packageName, int theme, + CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon, + int logo, int windowFlags, Configuration overrideConfig) { + if (!SHOW_SPLASH_SCREENS) { return null; } if (packageName == null) { @@ -2809,7 +2809,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { try { Context context = mContext; - if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow " + packageName + if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen " + packageName + ": nonLocalizedLabel=" + nonLocalizedLabel + " theme=" + Integer.toHexString(theme)); if (theme != context.getThemeResId() || labelRes != 0) { @@ -2822,8 +2822,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { } if (overrideConfig != null && !overrideConfig.equals(EMPTY)) { - if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow: creating context based" - + " on overrideConfig" + overrideConfig + " for starting window"); + if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen: creating context based" + + " on overrideConfig" + overrideConfig + " for splash screen"); final Context overrideContext = context.createConfigurationContext(overrideConfig); overrideContext.setTheme(theme); final TypedArray typedArray = overrideContext.obtainStyledAttributes( @@ -2833,7 +2833,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // We want to use the windowBackground for the override context if it is // available, otherwise we use the default one to make sure a themed starting // window is displayed for the app. - if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "addStartingWindow: apply overrideConfig" + if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen: apply overrideConfig" + overrideConfig + " to starting window resId=" + resId); context = overrideContext; } @@ -2895,19 +2895,19 @@ public class PhoneWindowManager implements WindowManagerPolicy { params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; } - params.setTitle("Starting " + packageName); + params.setTitle("Splash Screen " + packageName); wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); view = win.getDecorView(); - if (DEBUG_STARTING_WINDOW) Slog.d(TAG, "Adding starting window for " + if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "Adding splash screen window for " + packageName + " / " + appToken + ": " + (view.getParent() != null ? view : null)); wm.addView(view, params); // Only return the view if it was successfully added to the // window manager... which we can tell by it having a parent. - return view.getParent() != null ? view : null; + return view.getParent() != null ? new SplashScreenSurface(view) : null; } catch (WindowManager.BadTokenException e) { // ignore Log.w(TAG, appToken + " already running, starting window not displayed. " + @@ -2929,13 +2929,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ @Override - public void removeStartingWindow(IBinder appToken, View window) { - if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Removing starting window for " + appToken + ": " - + window + " Callers=" + Debug.getCallers(4)); + public void removeSplashScreen(IBinder appToken, StartingSurface surface) { + if (DEBUG_SPLASH_SCREEN) Slog.v(TAG, "Removing splash screen window for " + appToken + ": " + + surface + " Callers=" + Debug.getCallers(4)); - if (window != null) { + if (surface != null) { WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE); - wm.removeView(window); + wm.removeView(((SplashScreenSurface) surface).view); } } diff --git a/services/core/java/com/android/server/policy/SplashScreenSurface.java b/services/core/java/com/android/server/policy/SplashScreenSurface.java new file mode 100644 index 000000000000..d4212915c0a6 --- /dev/null +++ b/services/core/java/com/android/server/policy/SplashScreenSurface.java @@ -0,0 +1,38 @@ +/* + * 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.policy; + +import android.view.View; +import android.view.WindowManagerPolicy; +import android.view.WindowManagerPolicy.StartingSurface; + +import com.android.internal.policy.DecorView; +import com.android.internal.policy.PhoneWindow; + +/** + * Holds the contents of a splash screen starting window, i.e. the {@link DecorView} of a + * {@link PhoneWindow}. This is just a wrapper such that we can return it from + * {@link WindowManagerPolicy#addSplashScreen}. + */ +class SplashScreenSurface implements StartingSurface { + + final View view; + + SplashScreenSurface(View view) { + this.view = view; + } +} diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java index 35004c295681..cab39b56c3e9 100644 --- a/services/core/java/com/android/server/wm/AppWindowContainerController.java +++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java @@ -27,21 +27,21 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WIND import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; -import static com.android.server.wm.WindowManagerService.H.ADD_STARTING; - -import android.graphics.Bitmap; -import android.os.Trace; -import com.android.server.AttributeCache; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; +import android.graphics.Bitmap; import android.os.Binder; import android.os.Debug; +import android.os.Handler; import android.os.IBinder; -import android.os.Message; +import android.os.Looper; +import android.os.Trace; import android.util.Slog; import android.view.IApplicationToken; +import android.view.WindowManagerPolicy.StartingSurface; +import com.android.server.AttributeCache; /** * Controller for the app window token container. This is created by activity manager to link * activity records to the app window token container they use in window manager. @@ -52,6 +52,7 @@ public class AppWindowContainerController extends WindowContainerController { private final IApplicationToken mToken; + private final Handler mHandler = new Handler(Looper.getMainLooper()); private final Runnable mOnWindowsDrawn = () -> { if (mListener == null) { @@ -80,6 +81,94 @@ public class AppWindowContainerController mListener.onWindowsGone(); }; + private final Runnable mAddStartingWindow = () -> { + final StartingData startingData; + final Configuration mergedOverrideConfiguration; + + synchronized (mWindowMap) { + startingData = mContainer.startingData; + mergedOverrideConfiguration = mContainer.getMergedOverrideConfiguration(); + } + + if (startingData == null) { + // Animation has been canceled... do nothing. + return; + } + + if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Add starting " + + this + ": pkg=" + mContainer.startingData.pkg); + + StartingSurface contents = null; + try { + contents = mService.mPolicy.addSplashScreen(mContainer.token, startingData.pkg, + startingData.theme, startingData.compatInfo, startingData.nonLocalizedLabel, + startingData.labelRes, startingData.icon, startingData.logo, + startingData.windowFlags, mergedOverrideConfiguration); + } catch (Exception e) { + Slog.w(TAG_WM, "Exception when adding starting window", e); + } + if (contents != null) { + boolean abort = false; + + synchronized(mWindowMap) { + if (mContainer.removed || mContainer.startingData == null) { + // If the window was successfully added, then + // we need to remove it. + if (mContainer.startingWindow != null) { + if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, + "Aborted starting " + mContainer + + ": removed=" + mContainer.removed + + " startingData=" + mContainer.startingData); + mContainer.startingWindow = null; + mContainer.startingData = null; + abort = true; + } + } else { + mContainer.startingSurface = contents; + } + if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG_WM, + "Added starting " + mContainer + + ": startingWindow=" + + mContainer.startingWindow + " startingView=" + + mContainer.startingSurface); + } + + if (abort) { + try { + mService.mPolicy.removeSplashScreen(mContainer.token, contents); + } catch (Exception e) { + Slog.w(TAG_WM, "Exception when removing starting window", e); + } + } + } + }; + + private final Runnable mRemoveStartingWindow = () -> { + IBinder token = null; + StartingSurface contents = null; + synchronized (mWindowMap) { + if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Remove starting " + + mContainer + ": startingWindow=" + + mContainer.startingWindow + " startingView=" + + mContainer.startingSurface); + if (mContainer.startingWindow != null) { + contents = mContainer.startingSurface; + token = mContainer.token; + mContainer.startingData = null; + mContainer.startingSurface = null; + mContainer.startingWindow = null; + mContainer.startingDisplayed = false; + } + } + if (contents != null) { + try { + mService.mPolicy.removeSplashScreen(token, contents); + } catch (Exception e) { + Slog.w(TAG_WM, "Exception when removing starting window", e); + } + } + }; + public AppWindowContainerController(IApplicationToken token, AppWindowContainerListener listener, int taskId, int index, int requestedOrientation, boolean fullscreen, boolean showForAllUsers, int configChanges, @@ -393,19 +482,42 @@ public class AppWindowContainerController if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Creating StartingData"); mContainer.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags); - final Message m = mService.mH.obtainMessage(ADD_STARTING, mContainer); - // 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.mH.sendMessageAtFrontOfQueue(m); + scheduleAddStartingWindow(); } return true; } + void scheduleAddStartingWindow() { + + // 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"); + mHandler.postAtFrontOfQueue(mAddStartingWindow); + } + public void removeStartingWindow() { synchronized (mWindowMap) { - mService.scheduleRemoveStartingWindowLocked(mContainer); + if (mHandler.hasCallbacks(mRemoveStartingWindow)) { + // Already scheduled. + return; + } + + if (mContainer.startingWindow == null) { + if (mContainer.startingData != null) { + // Starting window has not been added yet, but it is scheduled to be added. + // Go ahead and cancel the request. + if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, + "Clearing startingData for token=" + mContainer); + mContainer.startingData = null; + } + return; + } + + if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, Debug.getCallers(1) + + ": Schedule remove starting " + mContainer + + " startingWindow=" + mContainer.startingWindow); + mHandler.post(mRemoveStartingWindow); } } @@ -508,15 +620,15 @@ public class AppWindowContainerController void reportWindowsDrawn() { - mService.mH.post(mOnWindowsDrawn); + mHandler.post(mOnWindowsDrawn); } void reportWindowsVisible() { - mService.mH.post(mOnWindowsVisible); + mHandler.post(mOnWindowsVisible); } void reportWindowsGone() { - mService.mH.post(mOnWindowsGone); + mHandler.post(mOnWindowsGone); } /** Calls directly into activity manager so window manager lock shouldn't held. */ diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index 0a4875810aba..f4fa2206a22a 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -29,9 +29,9 @@ import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM; import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; import static com.android.server.wm.AppTransition.TRANSIT_UNSET; +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; -import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION; @@ -47,22 +47,21 @@ import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES; import static com.android.server.wm.WindowManagerService.logWithStack; -import android.os.Debug; -import com.android.internal.util.ToBooleanFunction; -import com.android.server.input.InputApplicationHandle; -import com.android.server.wm.WindowManagerService.H; - import android.annotation.NonNull; import android.content.res.Configuration; import android.graphics.Rect; import android.os.Binder; +import android.os.Debug; import android.os.IBinder; -import android.os.Message; import android.os.SystemClock; import android.util.Slog; import android.view.IApplicationToken; -import android.view.View; import android.view.WindowManager; +import android.view.WindowManagerPolicy.StartingSurface; + +import com.android.internal.util.ToBooleanFunction; +import com.android.server.input.InputApplicationHandle; +import com.android.server.wm.WindowManagerService.H; import java.io.PrintWriter; import java.util.ArrayDeque; @@ -138,7 +137,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree // Information about an application starting window if displayed. StartingData startingData; WindowState startingWindow; - View startingView; + StartingSurface startingSurface; boolean startingDisplayed; boolean startingMoved; boolean firstWindowDrawn; @@ -213,8 +212,9 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree // it from behind the starting window, so there is no need for it to also be doing its // own stuff. winAnimator.clearAnimation(); - winAnimator.mService.mFinishedStarting.add(this); - winAnimator.mService.mH.sendEmptyMessage(H.FINISHED_STARTING); + if (getController() != null) { + getController().removeStartingWindow(); + } } updateReportedVisibilityLocked(); } @@ -439,8 +439,6 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree } void onRemovedFromDisplay() { - AppWindowToken startingToken = null; - if (DEBUG_APP_TRANSITIONS) Slog.v(TAG_WM, "Removing app token: " + this); boolean delayed = setVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction); @@ -461,6 +459,10 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree if (DEBUG_ADD_REMOVE || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG_WM, "removeAppToken: " + this + " delayed=" + delayed + " Callers=" + Debug.getCallers(4)); + if (startingData != null && getController() != null) { + getController().removeStartingWindow(); + } + final TaskStack stack = mTask.mStack; if (delayed && !isEmpty()) { // set the token aside because it has an active animation to be finished @@ -477,9 +479,6 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree } removed = true; - if (startingData != null) { - startingToken = this; - } stopFreezingScreen(true, true); if (mService.mFocusedApp == this) { if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Removing focused app token:" + this); @@ -491,9 +490,6 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree if (!delayed) { updateReportedVisibilityLocked(); } - - // Will only remove if startingToken non null. - mService.scheduleRemoveStartingWindowLocked(startingToken); } void clearAnimatingFlags() { @@ -557,7 +553,9 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree mAppStopped = true; destroySurfaces(); // Remove any starting window that was added for this app if they are still around. - mTask.mService.scheduleRemoveStartingWindowLocked(this); + if (getController() != null) { + getController().removeStartingWindow(); + } } /** @@ -667,16 +665,20 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree // TODO: Something smells about the code below...Is there a better way? if (startingWindow == win) { if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Notify removed startingWindow " + win); - mService.scheduleRemoveStartingWindowLocked(this); + if (getController() != null) { + getController().removeStartingWindow(); + } } else if (mChildren.size() == 0 && startingData != null) { // If this is the last window and we had requested a starting transition window, // well there is no point now. if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Nulling last startingWindow"); startingData = null; - } else if (mChildren.size() == 1 && startingView != null) { + } else if (mChildren.size() == 1 && startingSurface != null) { // If this is the last window except for a starting transition window, // we need to get rid of the starting transition. - mService.scheduleRemoveStartingWindowLocked(this); + if (getController() != null) { + getController().removeStartingWindow(); + } } } @@ -1015,7 +1017,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree } final WindowState tStartingWindow = fromToken.startingWindow; - if (tStartingWindow != null && fromToken.startingView != null) { + if (tStartingWindow != null && fromToken.startingSurface != null) { // In this case, the starting icon has already been displayed, so start // letting windows get shown immediately without any more transitions. mService.mSkipAppTransitionAnimation = true; @@ -1027,13 +1029,13 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree // Transfer the starting window over to the new token. startingData = fromToken.startingData; - startingView = fromToken.startingView; + startingSurface = fromToken.startingSurface; startingDisplayed = fromToken.startingDisplayed; fromToken.startingDisplayed = false; startingWindow = tStartingWindow; reportedVisible = fromToken.reportedVisible; fromToken.startingData = null; - fromToken.startingView = null; + fromToken.startingSurface = null; fromToken.startingWindow = null; fromToken.startingMoved = true; tStartingWindow.mToken = this; @@ -1080,10 +1082,9 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree startingData = fromToken.startingData; fromToken.startingData = null; fromToken.startingMoved = true; - final Message m = mService.mH.obtainMessage(H.ADD_STARTING, this); - // Note: we really want to do sendMessageAtFrontOfQueue() because we want to process the - // message ASAP, before any other queued messages. - mService.mH.sendMessageAtFrontOfQueue(m); + if (getController() != null) { + getController().scheduleAddStartingWindow(); + } return true; } @@ -1421,10 +1422,10 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn); pw.print(" mIsExiting="); pw.println(mIsExiting); } - if (startingWindow != null || startingView != null + if (startingWindow != null || startingSurface != null || startingDisplayed || startingMoved) { pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow); - pw.print(" startingView="); pw.print(startingView); + pw.print(" startingSurface="); pw.print(startingSurface); pw.print(" startingDisplayed="); pw.print(startingDisplayed); pw.print(" startingMoved="); pw.println(startingMoved); } diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index dc06d129c5bb..775d8a0862f9 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -498,7 +498,10 @@ class RootWindowContainer extends WindowContainer { if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) logSurface(winAnimator.mWin, "RECOVER DESTROY", false); winAnimator.destroySurface(); - mService.scheduleRemoveStartingWindowLocked(winAnimator.mWin.mAppToken); + if (winAnimator.mWin.mAppToken != null + && winAnimator.mWin.mAppToken.getController() != null) { + winAnimator.mWin.mAppToken.getController().removeStartingWindow(); + } } try { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 38cb54320a1b..4e259354ae2a 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2851,33 +2851,6 @@ public class WindowManagerService extends IWindowManager.Stub } } - void scheduleRemoveStartingWindowLocked(AppWindowToken wtoken) { - if (wtoken == null) { - return; - } - if (mH.hasMessages(H.REMOVE_STARTING, wtoken)) { - // Already scheduled. - return; - } - - if (wtoken.startingWindow == null) { - if (wtoken.startingData != null) { - // Starting window has not been added yet, but it is scheduled to be added. - // Go ahead and cancel the request. - if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, - "Clearing startingData for token=" + wtoken); - wtoken.startingData = null; - } - return; - } - - if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, Debug.getCallers(1) + - ": Schedule remove starting " + wtoken + (wtoken != null ? - " startingWindow=" + wtoken.startingWindow : "")); - Message m = mH.obtainMessage(H.REMOVE_STARTING, wtoken); - mH.sendMessage(m); - } - public void moveTaskToTop(int taskId) { final long origId = Binder.clearCallingIdentity(); try { @@ -5578,9 +5551,6 @@ public class WindowManagerService extends IWindowManager.Stub public static final int REPORT_FOCUS_CHANGE = 2; public static final int REPORT_LOSING_FOCUS = 3; public static final int DO_TRAVERSAL = 4; - public static final int ADD_STARTING = 5; - public static final int REMOVE_STARTING = 6; - public static final int FINISHED_STARTING = 7; public static final int WINDOW_FREEZE_TIMEOUT = 11; public static final int APP_TRANSITION_TIMEOUT = 13; @@ -5722,126 +5692,6 @@ public class WindowManagerService extends IWindowManager.Stub } } break; - case ADD_STARTING: { - final AppWindowToken wtoken = (AppWindowToken)msg.obj; - final StartingData sd = wtoken.startingData; - - if (sd == null) { - // Animation has been canceled... do nothing. - return; - } - - if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Add starting " - + wtoken + ": pkg=" + sd.pkg); - - View view = null; - try { - view = mPolicy.addStartingWindow(wtoken.token, sd.pkg, sd.theme, - sd.compatInfo, sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.logo, - sd.windowFlags, wtoken.getMergedOverrideConfiguration()); - } catch (Exception e) { - Slog.w(TAG_WM, "Exception when adding starting window", e); - } - - if (view != null) { - boolean abort = false; - - synchronized(mWindowMap) { - if (wtoken.removed || wtoken.startingData == null) { - // If the window was successfully added, then - // we need to remove it. - if (wtoken.startingWindow != null) { - if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, - "Aborted starting " + wtoken - + ": removed=" + wtoken.removed - + " startingData=" + wtoken.startingData); - wtoken.startingWindow = null; - wtoken.startingData = null; - abort = true; - } - } else { - wtoken.startingView = view; - } - if (DEBUG_STARTING_WINDOW && !abort) Slog.v(TAG_WM, - "Added starting " + wtoken - + ": startingWindow=" - + wtoken.startingWindow + " startingView=" - + wtoken.startingView); - } - - if (abort) { - try { - mPolicy.removeStartingWindow(wtoken.token, view); - } catch (Exception e) { - Slog.w(TAG_WM, "Exception when removing starting window", e); - } - } - } - } break; - - case REMOVE_STARTING: { - final AppWindowToken wtoken = (AppWindowToken)msg.obj; - IBinder token = null; - View view = null; - synchronized (mWindowMap) { - if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Remove starting " - + wtoken + ": startingWindow=" - + wtoken.startingWindow + " startingView=" - + wtoken.startingView); - if (wtoken.startingWindow != null) { - view = wtoken.startingView; - token = wtoken.token; - wtoken.startingData = null; - wtoken.startingView = null; - wtoken.startingWindow = null; - wtoken.startingDisplayed = false; - } - } - if (view != null) { - try { - mPolicy.removeStartingWindow(token, view); - } catch (Exception e) { - Slog.w(TAG_WM, "Exception when removing starting window", e); - } - } - } break; - - case FINISHED_STARTING: { - IBinder token = null; - View view = null; - while (true) { - synchronized (mWindowMap) { - final int N = mFinishedStarting.size(); - if (N <= 0) { - break; - } - AppWindowToken wtoken = mFinishedStarting.remove(N-1); - - if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, - "Finished starting " + wtoken - + ": startingWindow=" + wtoken.startingWindow - + " startingView=" + wtoken.startingView); - - if (wtoken.startingWindow == null) { - continue; - } - - view = wtoken.startingView; - token = wtoken.token; - wtoken.startingData = null; - wtoken.startingView = null; - wtoken.startingWindow = null; - wtoken.startingDisplayed = false; - } - - try { - mPolicy.removeStartingWindow(token, view); - } catch (Exception e) { - Slog.w(TAG_WM, "Exception when removing starting window", e); - } - } - } break; - case WINDOW_FREEZE_TIMEOUT: { // TODO(multidisplay): Can non-default displays rotate? synchronized (mWindowMap) { @@ -7348,21 +7198,6 @@ public class WindowManagerService extends IWindowManager.Stub private void dumpTokensLocked(PrintWriter pw, boolean dumpAll) { pw.println("WINDOW MANAGER TOKENS (dumpsys window tokens)"); mRoot.dumpTokens(pw, dumpAll); - if (!mFinishedStarting.isEmpty()) { - pw.println(); - pw.println(" Finishing start of application tokens:"); - for (int i=mFinishedStarting.size()-1; i>=0; i--) { - WindowToken token = mFinishedStarting.get(i); - pw.print(" Finished Starting #"); pw.print(i); - pw.print(' '); pw.print(token); - if (dumpAll) { - pw.println(':'); - token.dump(pw, " "); - } else { - pw.println(); - } - } - } if (!mOpeningApps.isEmpty() || !mClosingApps.isEmpty()) { pw.println(); if (mOpeningApps.size() > 0) { diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index e5ed18d118ad..19ef44cace33 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -461,16 +461,7 @@ class WindowStateAnimator { mStackClip = STACK_CLIP_BEFORE_ANIM; mWin.checkPolicyVisibilityChange(); mTransformation.clear(); - if (mDrawState == HAS_DRAWN - && mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING - && mWin.mAppToken != null - && mWin.mAppToken.firstWindowDrawn - && mWin.mAppToken.startingData != null) { - if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Finish starting " - + mWin.mToken + ": first real window done animating"); - mService.mFinishedStarting.add(mWin.mAppToken); - mService.mH.sendEmptyMessage(H.FINISHED_STARTING); - } else if (mAttrType == LayoutParams.TYPE_STATUS_BAR && mWin.mPolicyVisibility) { + if (mAttrType == LayoutParams.TYPE_STATUS_BAR && mWin.mPolicyVisibility) { // Upon completion of a not-visible to visible status bar animation a relayout is // required. if (displayContent != null) { diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java index 1aabd5ea66f9..4df100105bcb 100644 --- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java +++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java @@ -441,8 +441,9 @@ class WindowSurfacePlacer { wtoken.deferClearAllDrawn = false; // Ensure that apps that are mid-starting are also scheduled to have their // starting windows removed after the animation is complete - if (wtoken.startingWindow != null && !wtoken.startingWindow.mAnimatingExit) { - mService.scheduleRemoveStartingWindowLocked(wtoken); + if (wtoken.startingWindow != null && !wtoken.startingWindow.mAnimatingExit + && wtoken.getController() != null) { + wtoken.getController().removeStartingWindow(); } mService.mAnimator.mAppWindowAnimating |= appAnimator.isAnimating(); diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java index 1853a653ed1a..c4fd7221d3f4 100644 --- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java +++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java @@ -16,29 +16,6 @@ package com.android.server.wm; -import com.android.internal.policy.IKeyguardDismissCallback; -import com.android.internal.policy.IShortcutService; -import com.android.server.input.InputManagerService; - -import android.annotation.Nullable; -import android.content.Context; -import android.content.res.CompatibilityInfo; -import android.content.res.Configuration; -import android.graphics.Rect; -import android.os.Bundle; -import android.os.IBinder; -import android.os.RemoteException; -import android.util.Log; -import android.view.Display; -import android.view.IWindowManager; -import android.view.KeyEvent; -import android.view.View; -import android.view.WindowManager; -import android.view.WindowManagerPolicy; -import android.view.animation.Animation; - -import java.io.PrintWriter; - import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY; @@ -62,8 +39,8 @@ import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL; import static android.view.WindowManager.LayoutParams.TYPE_PHONE; import static android.view.WindowManager.LayoutParams.TYPE_POINTER; -import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE; import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION; +import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE; import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION; import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT; @@ -81,9 +58,30 @@ import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION; import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING; import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; - import static org.mockito.Mockito.mock; +import android.annotation.Nullable; +import android.content.Context; +import android.content.res.CompatibilityInfo; +import android.content.res.Configuration; +import android.graphics.Rect; +import android.os.Bundle; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; +import android.view.Display; +import android.view.IWindowManager; +import android.view.KeyEvent; +import android.view.WindowManager; +import android.view.WindowManagerPolicy; +import android.view.animation.Animation; + +import com.android.internal.policy.IKeyguardDismissCallback; +import com.android.internal.policy.IShortcutService; +import com.android.server.input.InputManagerService; + +import java.io.PrintWriter; + class TestWindowManagerPolicy implements WindowManagerPolicy { private static final String TAG = "TestWindowManagerPolicy"; @@ -308,14 +306,14 @@ class TestWindowManagerPolicy implements WindowManagerPolicy { } @Override - public View addStartingWindow(IBinder appToken, String packageName, int theme, + public StartingSurface addSplashScreen(IBinder appToken, String packageName, int theme, CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags, Configuration overrideConfig) { return null; } @Override - public void removeStartingWindow(IBinder appToken, View window) { + public void removeSplashScreen(IBinder appToken, StartingSurface surface) { } -- 2.11.0