diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 33970a244a40c..ea3ef650f1930 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -21,15 +21,12 @@ import static android.Manifest.permission.SYSTEM_ALERT_WINDOW; import static android.Manifest.permission.SYSTEM_APPLICATION_OVERLAY; import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW; import static android.app.AppOpsManager.OP_TOAST_WINDOW; -import static android.content.Context.CONTEXT_RESTRICTED; -import static android.content.Context.WINDOW_SERVICE; import static android.content.pm.PackageManager.FEATURE_AUTOMOTIVE; import static android.content.pm.PackageManager.FEATURE_HDMI_CEC; import static android.content.pm.PackageManager.FEATURE_LEANBACK; import static android.content.pm.PackageManager.FEATURE_PICTURE_IN_PICTURE; import static android.content.pm.PackageManager.FEATURE_WATCH; import static android.content.pm.PackageManager.PERMISSION_GRANTED; -import static android.content.res.Configuration.EMPTY; import static android.os.Build.VERSION_CODES.M; import static android.os.Build.VERSION_CODES.O; import static android.provider.Settings.Secure.VOLUME_HUSH_OFF; @@ -47,7 +44,6 @@ import static android.view.KeyEvent.KEYCODE_VOLUME_UP; import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW; -import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.LAST_SYSTEM_WINDOW; @@ -117,13 +113,10 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; -import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.content.res.Resources; -import android.content.res.TypedArray; import android.database.ContentObserver; import android.graphics.Rect; -import android.graphics.drawable.Drawable; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManagerInternal; import android.hardware.hdmi.HdmiAudioSystemClient; @@ -182,7 +175,6 @@ import android.view.KeyCharacterMap; import android.view.KeyCharacterMap.FallbackAction; import android.view.KeyEvent; import android.view.MotionEvent; -import android.view.View; import android.view.ViewConfiguration; import android.view.WindowManager; import android.view.WindowManagerGlobal; @@ -249,9 +241,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { static final boolean localLOGV = false; static final boolean DEBUG_INPUT = false; static final boolean DEBUG_KEYGUARD = false; - static final boolean DEBUG_SPLASH_SCREEN = false; static final boolean DEBUG_WAKEUP = false; - 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; @@ -2354,7 +2344,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { POWER_BUTTON_SUPPRESSION_DELAY_DEFAULT_MILLIS); if (!mContext.getResources() .getBoolean(com.android.internal.R.bool.config_volumeHushGestureEnabled)) { - mRingerToggleChord = Settings.Secure.VOLUME_HUSH_OFF; + mRingerToggleChord = VOLUME_HUSH_OFF; } // Configure wake gesture. @@ -2572,191 +2562,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { return attrs.type == TYPE_NOTIFICATION_SHADE; } - /** {@inheritDoc} */ - @Override - public StartingSurface addSplashScreen(IBinder appToken, int userId, String packageName, - int theme, CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, - int icon, int logo, int windowFlags, Configuration overrideConfig, int displayId) { - if (!SHOW_SPLASH_SCREENS) { - return null; - } - if (packageName == null) { - return null; - } - - WindowManager wm = null; - View view = null; - - try { - Context context = mContext; - if (DEBUG_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen " + packageName - + ": nonLocalizedLabel=" + nonLocalizedLabel + " theme=" - + Integer.toHexString(theme)); - - // Obtain proper context to launch on the right display. - final Context displayContext = getDisplayContext(context, displayId); - if (displayContext == null) { - // Can't show splash screen on requested display, so skip showing at all. - return null; - } - context = displayContext; - - if (theme != context.getThemeResId() || labelRes != 0) { - try { - context = context.createPackageContextAsUser(packageName, CONTEXT_RESTRICTED, - UserHandle.of(userId)); - context.setTheme(theme); - } catch (PackageManager.NameNotFoundException e) { - Slog.w(TAG, "Failed creating package context with package name " - + packageName + " for user " + userId, e); - } - } - - if (overrideConfig != null && !overrideConfig.equals(EMPTY)) { - 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( - com.android.internal.R.styleable.Window); - final int resId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0); - if (resId != 0 && overrideContext.getDrawable(resId) != null) { - // 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_SPLASH_SCREEN) Slog.d(TAG, "addSplashScreen: apply overrideConfig" - + overrideConfig + " to starting window resId=" + resId); - context = overrideContext; - } - typedArray.recycle(); - } - - final PhoneWindow win = new PhoneWindow(context); - win.setIsStartingWindow(true); - - CharSequence label = context.getResources().getText(labelRes, null); - // Only change the accessibility title if the label is localized - if (label != null) { - win.setTitle(label, true); - } else { - win.setTitle(nonLocalizedLabel, false); - } - - win.setType( - WindowManager.LayoutParams.TYPE_APPLICATION_STARTING); - - synchronized (mWindowManagerFuncs.getWindowManagerLock()) { - // Assumes it's safe to show starting windows of launched apps while - // the keyguard is being hidden. This is okay because starting windows never show - // secret information. - // TODO(b/113840485): Occluded may not only happen on default display - if (displayId == DEFAULT_DISPLAY && isKeyguardOccluded()) { - windowFlags |= FLAG_SHOW_WHEN_LOCKED; - } - } - - // Force the window flags: this is a fake window, so it is not really - // touchable or focusable by the user. We also add in the ALT_FOCUSABLE_IM - // flag because we do know that the next window will take input - // focus, so we want to get the IME window up on top of us right away. - win.setFlags( - windowFlags| - WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE| - WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| - WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM, - windowFlags| - WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE| - WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| - WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); - - win.setDefaultIcon(icon); - win.setDefaultLogo(logo); - - win.setLayout(WindowManager.LayoutParams.MATCH_PARENT, - WindowManager.LayoutParams.MATCH_PARENT); - - final WindowManager.LayoutParams params = win.getAttributes(); - params.token = appToken; - params.packageName = packageName; - params.windowAnimations = win.getWindowStyle().getResourceId( - com.android.internal.R.styleable.Window_windowAnimationStyle, 0); - params.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS; - // Setting as trusted overlay to let touches pass through. This is safe because this - // window is controlled by the system. - params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY; - - if (!compatInfo.supportsScreen()) { - params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; - } - - params.setTitle("Splash Screen " + packageName); - addSplashscreenContent(win, context); - - wm = (WindowManager) context.getSystemService(WINDOW_SERVICE); - view = win.getDecorView(); - - 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 ? new SplashScreenSurface(view, appToken) : null; - } catch (WindowManager.BadTokenException e) { - // ignore - Log.w(TAG, appToken + " already running, starting window not displayed. " + - e.getMessage()); - } catch (RuntimeException e) { - // don't crash if something else bad happens, for example a - // failure loading resources because we are loading from an app - // on external storage that has been unmounted. - Log.w(TAG, appToken + " failed creating starting window", e); - } finally { - if (view != null && view.getParent() == null) { - Log.w(TAG, "view not successfully added to wm, removing view"); - wm.removeViewImmediate(view); - } - } - - return null; - } - - private void addSplashscreenContent(PhoneWindow win, Context ctx) { - final TypedArray a = ctx.obtainStyledAttributes(R.styleable.Window); - final int resId = a.getResourceId(R.styleable.Window_windowSplashscreenContent, 0); - a.recycle(); - if (resId == 0) { - return; - } - final Drawable drawable = ctx.getDrawable(resId); - if (drawable == null) { - return; - } - - // We wrap this into a view so the system insets get applied to the drawable. - final View v = new View(ctx); - v.setBackground(drawable); - win.setContentView(v); - } - - /** Obtain proper context for showing splash screen on the provided display. */ - private Context getDisplayContext(Context context, int displayId) { - if (displayId == DEFAULT_DISPLAY) { - // The default context fits. - return context; - } - - final Display targetDisplay = mDisplayManager.getDisplay(displayId); - if (targetDisplay == null) { - // Failed to obtain the non-default display where splash screen should be shown, - // lets not show at all. - return null; - } - - return context.createDisplayContext(targetDisplay); - } - @Override public Animation createHiddenByKeyguardExit(boolean onWallpaper, boolean goingToNotificationShade, boolean subtleAnimation) { diff --git a/services/core/java/com/android/server/policy/SplashScreenSurface.java b/services/core/java/com/android/server/policy/SplashScreenSurface.java deleted file mode 100644 index 72933a0ad3093..0000000000000 --- a/services/core/java/com/android/server/policy/SplashScreenSurface.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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 static com.android.server.policy.PhoneWindowManager.DEBUG_SPLASH_SCREEN; - -import android.os.Debug; -import android.os.IBinder; -import android.util.Slog; -import android.view.View; -import android.view.WindowManager; - -import com.android.internal.policy.DecorView; -import com.android.internal.policy.PhoneWindow; -import com.android.server.policy.WindowManagerPolicy.StartingSurface; - -/** - * 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 { - - private static final String TAG = PhoneWindowManager.TAG; - private final View mView; - private final IBinder mAppToken; - - SplashScreenSurface(View view, IBinder appToken) { - mView = view; - mAppToken = appToken; - } - - @Override - public void remove(boolean animate) { - if (DEBUG_SPLASH_SCREEN) Slog.v(TAG, "Removing splash screen window for " + mAppToken + ": " - + this + " Callers=" + Debug.getCallers(4)); - - final WindowManager wm = mView.getContext().getSystemService(WindowManager.class); - wm.removeView(mView); - } -} diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java index 4895c0b2df79e..0992d00f1e8a3 100644 --- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java +++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java @@ -69,7 +69,6 @@ import android.annotation.IntDef; import android.annotation.NonNull; 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; @@ -223,21 +222,6 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { boolean canShowWhenLocked(); } - /** - * 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 released with {@link #remove} when no longer needed. - */ - interface StartingSurface { - - /** - * Removes the starting window surface. Do not hold the window manager lock when calling - * this method! - * @param animate Whether need to play the default exit animation for starting window. - */ - void remove(boolean animate); - } - /** * Interface for calling back in to the window manager that is private * between it and the policy. @@ -692,33 +676,6 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { } } - /** - * Called when the system would like to show a UI to indicate that an - * application is starting. You can use this to add a - * APPLICATION_STARTING_TYPE window with the given appToken to the window - * manager (using the normal window manager APIs) that will be shown until - * the application displays its own window. This is called without the - * window manager locked so that you can call back into it. - * - * @param appToken Token of the application being started. - * @param packageName The name of the application package being started. - * @param theme Resource defining the application's overall visual theme. - * @param nonLocalizedLabel The default title label of the application if - * no data is found in the resource. - * @param labelRes The resource ID the application would like to use as its name. - * @param icon The resource ID the application would like to use as its icon. - * @param windowFlags Window layout flags. - * @param overrideConfig override configuration to consider when generating - * context to for resources. - * @param displayId Id of the display to show the splash screen at. - * - * @return The starting surface. - * - */ - StartingSurface addSplashScreen(IBinder appToken, int userId, String packageName, - int theme, CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, - int icon, int logo, int windowFlags, Configuration overrideConfig, int displayId); - /** * Create and return an animation to re-display a window that was force hidden by Keyguard. */ diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 2a15409808dab..7fea29c7d010c 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -103,7 +103,6 @@ import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; import static android.view.SurfaceControl.getGlobalTransaction; import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD; -import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER; import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; @@ -333,7 +332,6 @@ import com.android.server.am.AppTimeTracker; import com.android.server.am.PendingIntentRecord; import com.android.server.contentcapture.ContentCaptureManagerInternal; import com.android.server.display.color.ColorDisplayService; -import com.android.server.policy.WindowManagerPolicy; import com.android.server.uri.NeededUriGrants; import com.android.server.uri.UriPermissionOwner; import com.android.server.wm.ActivityMetricsLogger.TransitionInfoSnapshot; @@ -451,9 +449,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A private CharSequence nonLocalizedLabel; // the label information from the package mgr. private int labelRes; // the label information from the package mgr. private int icon; // resource identifier of activity's icon. - private int logo; // resource identifier of activity's logo. private int theme; // resource identifier of activity's theme. - private int windowFlags; // custom window flags for preview window. private Task task; // the task this is in. private long createTime = System.currentTimeMillis(); long lastVisibleTime; // last time this activity became visible @@ -735,7 +731,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // Note: these are de-referenced before the starting window animates away. StartingData mStartingData; WindowState mStartingWindow; - WindowManagerPolicy.StartingSurface mStartingSurface; + StartingSurfaceController.StartingSurface mStartingSurface; boolean startingDisplayed; boolean startingMoved; @@ -1742,11 +1738,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A labelRes = app.labelRes; } icon = aInfo.getIconResource(); - logo = aInfo.getLogoResource(); theme = aInfo.getThemeResource(); - if ((aInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) { - windowFlags |= LayoutParams.FLAG_HARDWARE_ACCELERATED; - } if ((aInfo.flags & FLAG_MULTIPROCESS) != 0 && _caller != null && (aInfo.applicationInfo.uid == SYSTEM_UID || aInfo.applicationInfo.uid == _caller.mInfo.uid)) { @@ -1979,33 +1971,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return true; } - private void applyStartingWindowTheme(String pkg, int theme) { - if (theme != 0) { - AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme, - com.android.internal.R.styleable.Window, - mWmService.mCurrentUserId); - if (ent == null) { - return; - } - final boolean windowShowWallpaper = ent.array.getBoolean( - com.android.internal.R.styleable.Window_windowShowWallpaper, false); - if (windowShowWallpaper && getDisplayContent().mWallpaperController - .getWallpaperTarget() == null) { - // If this theme is requesting a wallpaper, and the wallpaper - // is not currently visible, then this effectively serves as - // an opaque window and our starting window transition animation - // can still work. We just need to make sure the starting window - // is also showing the wallpaper. - windowFlags |= FLAG_SHOW_WALLPAPER; - } - } - } - @VisibleForTesting - boolean addStartingWindow(String pkg, int resolvedTheme, CompatibilityInfo compatInfo, - CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags, - ActivityRecord from, boolean newTask, boolean taskSwitch, boolean processRunning, - boolean allowTaskSnapshot, boolean activityCreated, boolean useEmpty, + boolean addStartingWindow(String pkg, int resolvedTheme, ActivityRecord from, boolean newTask, + boolean taskSwitch, boolean processRunning, boolean allowTaskSnapshot, + boolean activityCreated, boolean useEmpty, boolean activityAllDrawn) { // If the display is frozen, we won't do anything until the actual window is // displayed so there is no reason to put in the starting window. @@ -2062,7 +2031,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (resolvedTheme == 0 && theme != 0) { return false; } - applyStartingWindowTheme(pkg, resolvedTheme); if (from != null && transferStartingWindow(from)) { return true; @@ -2075,9 +2043,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SplashScreenStartingData"); - mStartingData = new SplashScreenStartingData(mWmService, pkg, - resolvedTheme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags, - getMergedOverrideConfiguration(), typeParameter); + mStartingData = new SplashScreenStartingData(mWmService, resolvedTheme, typeParameter); scheduleAddStartingWindow(); return true; } @@ -2099,17 +2065,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } void scheduleAddStartingWindow() { - if (StartingSurfaceController.DEBUG_ENABLE_SHELL_DRAWER) { - mAddStartingWindow.run(); - } else { - // Note: we really want to do sendMessageAtFrontOfQueue() because we - // want to process the message ASAP, before any other queued - // messages. - if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) { - ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Enqueueing ADD_STARTING"); - mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow); - } - } + mAddStartingWindow.run(); } private class AddStartingWindow implements Runnable { @@ -2120,9 +2076,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A final StartingData startingData; synchronized (mWmService.mGlobalLock) { // There can only be one adding request, silly caller! - if (!StartingSurfaceController.DEBUG_ENABLE_SHELL_DRAWER) { - mWmService.mAnimationHandler.removeCallbacks(this); - } if (mStartingData == null) { // Animation has been canceled... do nothing. @@ -2137,7 +2090,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Add starting %s: startingData=%s", this, startingData); - WindowManagerPolicy.StartingSurface surface = null; + StartingSurfaceController.StartingSurface surface = null; try { surface = startingData.createStartingSurface(ActivityRecord.this); } catch (Exception e) { @@ -2250,9 +2203,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } private boolean transferSplashScreenIfNeeded() { - if (!mWmService.mStartingSurfaceController.DEBUG_ENABLE_SHELL_DRAWER) { - return false; - } if (!mHandleExitSplashScreen || mStartingSurface == null || mStartingWindow == null || mTransferringSplashScreenState == TRANSFER_SPLASH_SCREEN_FINISH) { return false; @@ -2393,7 +2343,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return; } - final WindowManagerPolicy.StartingSurface surface; + final StartingSurfaceController.StartingSurface surface; final StartingData startingData = mStartingData; if (mStartingData != null) { surface = mStartingSurface; @@ -2427,13 +2377,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } }; - if (StartingSurfaceController.DEBUG_ENABLE_SHELL_DRAWER) { - removeSurface.run(); - } else { - // Use the same thread to remove the window as we used to add it, as otherwise we end up - // with things in the view hierarchy being called from different threads. - mWmService.mAnimationHandler.post(removeSurface); - } + removeSurface.run(); } /** @@ -6540,9 +6484,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return; } - final CompatibilityInfo compatInfo = - mAtmService.compatibilityInfoForPackageLocked(info.applicationInfo); - mSplashScreenStyleEmpty = shouldUseEmptySplashScreen(sourceRecord, startActivity); final int splashScreenTheme = startActivity ? getSplashscreenTheme() : 0; @@ -6557,7 +6498,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A && task.getActivity((r) -> !r.finishing && r != this) == null; final boolean scheduled = addStartingWindow(packageName, resolvedTheme, - compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags, prev, newTask || newSingleActivity, taskSwitch, isProcessRunning(), allowTaskSnapshot(), activityCreated, mSplashScreenStyleEmpty, allDrawn); if (DEBUG_STARTING_WINDOW_VERBOSE && scheduled) { diff --git a/services/core/java/com/android/server/wm/SnapshotStartingData.java b/services/core/java/com/android/server/wm/SnapshotStartingData.java index b6cf91a584a9f..727fa52cfff54 100644 --- a/services/core/java/com/android/server/wm/SnapshotStartingData.java +++ b/services/core/java/com/android/server/wm/SnapshotStartingData.java @@ -18,7 +18,7 @@ package com.android.server.wm; import android.window.TaskSnapshot; -import com.android.server.policy.WindowManagerPolicy.StartingSurface; +import com.android.server.wm.StartingSurfaceController.StartingSurface; /** * Represents starting data for snapshot starting windows. diff --git a/services/core/java/com/android/server/wm/SplashScreenStartingData.java b/services/core/java/com/android/server/wm/SplashScreenStartingData.java index c659c05dceda8..d8d16e1adb920 100644 --- a/services/core/java/com/android/server/wm/SplashScreenStartingData.java +++ b/services/core/java/com/android/server/wm/SplashScreenStartingData.java @@ -16,47 +16,25 @@ package com.android.server.wm; -import android.content.res.CompatibilityInfo; -import android.content.res.Configuration; - -import com.android.server.policy.WindowManagerPolicy.StartingSurface; +import com.android.server.wm.StartingSurfaceController.StartingSurface; /** * Represents starting data for splash screens, i.e. "traditional" starting windows. */ class SplashScreenStartingData extends StartingData { - private final String mPkg; private final int mTheme; - private final CompatibilityInfo mCompatInfo; - private final CharSequence mNonLocalizedLabel; - private final int mLabelRes; - private final int mIcon; - private final int mLogo; - private final int mWindowFlags; - private final Configuration mMergedOverrideConfiguration; - SplashScreenStartingData(WindowManagerService service, String pkg, int theme, - CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon, - int logo, int windowFlags, Configuration mergedOverrideConfiguration, int typeParams) { + SplashScreenStartingData(WindowManagerService service, int theme, + int typeParams) { super(service, typeParams); - mPkg = pkg; mTheme = theme; - mCompatInfo = compatInfo; - mNonLocalizedLabel = nonLocalizedLabel; - mLabelRes = labelRes; - mIcon = icon; - mLogo = logo; - mWindowFlags = windowFlags; - mMergedOverrideConfiguration = mergedOverrideConfiguration; } @Override StartingSurface createStartingSurface(ActivityRecord activity) { return mService.mStartingSurfaceController.createSplashScreenStartingSurface( - activity, mPkg, mTheme, mCompatInfo, mNonLocalizedLabel, mLabelRes, mIcon, - mLogo, mWindowFlags, mMergedOverrideConfiguration, - activity.getDisplayContent().getDisplayId()); + activity, mTheme); } @Override diff --git a/services/core/java/com/android/server/wm/StartingData.java b/services/core/java/com/android/server/wm/StartingData.java index 8b1befbefd990..fbee343f09b5d 100644 --- a/services/core/java/com/android/server/wm/StartingData.java +++ b/services/core/java/com/android/server/wm/StartingData.java @@ -16,7 +16,7 @@ package com.android.server.wm; -import com.android.server.policy.WindowManagerPolicy.StartingSurface; +import com.android.server.wm.StartingSurfaceController.StartingSurface; /** * Represents the model about how a starting window should be constructed. diff --git a/services/core/java/com/android/server/wm/StartingSurfaceController.java b/services/core/java/com/android/server/wm/StartingSurfaceController.java index 8b2a425883926..5fe40766fb66a 100644 --- a/services/core/java/com/android/server/wm/StartingSurfaceController.java +++ b/services/core/java/com/android/server/wm/StartingSurfaceController.java @@ -31,14 +31,9 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.pm.ApplicationInfo; -import android.content.res.CompatibilityInfo; -import android.content.res.Configuration; -import android.os.SystemProperties; import android.util.Slog; import android.window.TaskSnapshot; -import com.android.server.policy.WindowManagerPolicy.StartingSurface; - import java.util.function.Supplier; /** @@ -47,9 +42,6 @@ import java.util.function.Supplier; public class StartingSurfaceController { private static final String TAG = TAG_WITH_CLASS_NAME ? StartingSurfaceController.class.getSimpleName() : TAG_WM; - /** Set to {@code true} to enable shell starting surface drawer. */ - static final boolean DEBUG_ENABLE_SHELL_DRAWER = - SystemProperties.getBoolean("persist.debug.shell_starting_surface", true); private final WindowManagerService mService; private final SplashScreenExceptionList mSplashScreenExceptionsList; @@ -58,20 +50,13 @@ public class StartingSurfaceController { mSplashScreenExceptionsList = new SplashScreenExceptionList(wm.mContext.getMainExecutor()); } - StartingSurface createSplashScreenStartingSurface(ActivityRecord activity, String packageName, - int theme, CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, - int icon, int logo, int windowFlags, Configuration overrideConfig, int displayId) { - if (!DEBUG_ENABLE_SHELL_DRAWER) { - return mService.mPolicy.addSplashScreen(activity.token, activity.mUserId, packageName, - theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags, - overrideConfig, displayId); - } + StartingSurface createSplashScreenStartingSurface(ActivityRecord activity, int theme) { synchronized (mService.mGlobalLock) { final Task task = activity.getTask(); if (task != null && mService.mAtmService.mTaskOrganizerController.addStartingWindow( task, activity, theme, null /* taskSnapshot */)) { - return new ShellStartingSurface(task); + return new StartingSurface(task); } } return null; @@ -151,24 +136,25 @@ public class StartingSurfaceController { activity.mDisplayContent.handleTopActivityLaunchingInDifferentOrientation( topFullscreenActivity, false /* checkOpening */); } - if (DEBUG_ENABLE_SHELL_DRAWER) { mService.mAtmService.mTaskOrganizerController.addStartingWindow(task, activity, 0 /* launchTheme */, taskSnapshot); - return new ShellStartingSurface(task); - } + return new StartingSurface(task); } - return mService.mTaskSnapshotController.createStartingSurface(activity, taskSnapshot); } - private final class ShellStartingSurface implements StartingSurface { + final class StartingSurface { private final Task mTask; - ShellStartingSurface(Task task) { + StartingSurface(Task task) { mTask = task; } - @Override + /** + * Removes the starting window surface. Do not hold the window manager lock when calling + * this method! + * @param animate Whether need to play the default exit animation for starting window. + */ public void remove(boolean animate) { synchronized (mService.mGlobalLock) { mService.mAtmService.mTaskOrganizerController.removeStartingWindow(mTask, animate); diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java index 63246aca25878..6aa707c38e9f9 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotController.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java @@ -16,14 +16,29 @@ package com.android.server.wm; +import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS; +import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; +import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION; +import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; +import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS; + +import static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES; +import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES; +import static com.android.internal.policy.DecorView.getNavigationBarRect; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.ActivityManager; +import android.app.ActivityThread; +import android.content.Context; import android.content.pm.PackageManager; import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.RecordingCanvas; @@ -44,11 +59,11 @@ import android.view.WindowInsetsController.Appearance; import android.view.WindowManager.LayoutParams; import android.window.TaskSnapshot; +import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.graphics.ColorUtils; +import com.android.internal.policy.DecorView; import com.android.server.policy.WindowManagerPolicy.ScreenOffListener; -import com.android.server.policy.WindowManagerPolicy.StartingSurface; -import com.android.server.wm.TaskSnapshotSurface.SystemBarBackgroundPainter; import com.android.server.wm.utils.InsetUtils; import com.google.android.collect.Sets; @@ -241,15 +256,6 @@ class TaskSnapshotController { mCache.clearRunningCache(); } - /** - * Creates a starting surface for {@param token} with {@param snapshot}. DO NOT HOLD THE WINDOW - * MANAGER LOCK WHEN CALLING THIS METHOD! - */ - StartingSurface createStartingSurface(ActivityRecord activity, - TaskSnapshot snapshot) { - return TaskSnapshotSurface.create(mService, activity, snapshot); - } - /** * Find the window for a given task to take a snapshot. Top child of the task is usually the one * we're looking for, but during app transitions, trampoline activities can appear in the @@ -374,12 +380,6 @@ class TaskSnapshotController { return taskSnapshot; } - @Nullable - SurfaceControl.ScreenshotHardwareBuffer createTaskSnapshot(@NonNull Task task, - float scaleFraction, TaskSnapshot.Builder builder) { - return createTaskSnapshot(task, scaleFraction, PixelFormat.RGBA_8888, null, builder); - } - @Nullable private SurfaceControl.ScreenshotHardwareBuffer createImeSnapshot(@NonNull Task task, int pixelFormat) { @@ -573,7 +573,7 @@ class TaskSnapshotController { final RecordingCanvas c = node.start(width, height); c.drawColor(color); decorPainter.setInsets(systemBarInsets); - decorPainter.drawDecors(c, null /* statusBarExcludeFrame */); + decorPainter.drawDecors(c /* statusBarExcludeFrame */); node.end(c); final Bitmap hwBitmap = ThreadedRenderer.createHardwareBitmap(node, width, height); if (hwBitmap == null) { @@ -704,4 +704,92 @@ class TaskSnapshotController { pw.println(prefix + "mTaskSnapshotEnabled=" + mTaskSnapshotEnabled); mCache.dump(pw, prefix); } + + /** + * Helper class to draw the background of the system bars in regions the task snapshot isn't + * filling the window. + */ + static class SystemBarBackgroundPainter { + + private final Paint mStatusBarPaint = new Paint(); + private final Paint mNavigationBarPaint = new Paint(); + private final int mStatusBarColor; + private final int mNavigationBarColor; + private final int mWindowFlags; + private final int mWindowPrivateFlags; + private final float mScale; + private final InsetsState mInsetsState; + private final Rect mSystemBarInsets = new Rect(); + + SystemBarBackgroundPainter(int windowFlags, int windowPrivateFlags, int appearance, + ActivityManager.TaskDescription taskDescription, float scale, + InsetsState insetsState) { + mWindowFlags = windowFlags; + mWindowPrivateFlags = windowPrivateFlags; + mScale = scale; + final Context context = ActivityThread.currentActivityThread().getSystemUiContext(); + final int semiTransparent = context.getColor( + R.color.system_bar_background_semi_transparent); + mStatusBarColor = DecorView.calculateBarColor(windowFlags, FLAG_TRANSLUCENT_STATUS, + semiTransparent, taskDescription.getStatusBarColor(), appearance, + APPEARANCE_LIGHT_STATUS_BARS, + taskDescription.getEnsureStatusBarContrastWhenTransparent()); + mNavigationBarColor = DecorView.calculateBarColor(windowFlags, + FLAG_TRANSLUCENT_NAVIGATION, semiTransparent, + taskDescription.getNavigationBarColor(), appearance, + APPEARANCE_LIGHT_NAVIGATION_BARS, + taskDescription.getEnsureNavigationBarContrastWhenTransparent() + && context.getResources().getBoolean(R.bool.config_navBarNeedsScrim)); + mStatusBarPaint.setColor(mStatusBarColor); + mNavigationBarPaint.setColor(mNavigationBarColor); + mInsetsState = insetsState; + } + + void setInsets(Rect systemBarInsets) { + mSystemBarInsets.set(systemBarInsets); + } + + int getStatusBarColorViewHeight() { + final boolean forceBarBackground = + (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0; + if (STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible( + mInsetsState, mStatusBarColor, mWindowFlags, forceBarBackground)) { + return (int) (mSystemBarInsets.top * mScale); + } else { + return 0; + } + } + + private boolean isNavigationBarColorViewVisible() { + final boolean forceBarBackground = + (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0; + return NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES.isVisible( + mInsetsState, mNavigationBarColor, mWindowFlags, forceBarBackground); + } + + void drawDecors(Canvas c) { + drawStatusBarBackground(c, getStatusBarColorViewHeight()); + drawNavigationBarBackground(c); + } + + @VisibleForTesting + void drawStatusBarBackground(Canvas c, + int statusBarHeight) { + if (statusBarHeight > 0 && Color.alpha(mStatusBarColor) != 0) { + final int rightInset = (int) (mSystemBarInsets.right * mScale); + c.drawRect(0, 0, c.getWidth() - rightInset, statusBarHeight, mStatusBarPaint); + } + } + + @VisibleForTesting + void drawNavigationBarBackground(Canvas c) { + final Rect navigationBarRect = new Rect(); + getNavigationBarRect(c.getWidth(), c.getHeight(), mSystemBarInsets, navigationBarRect, + mScale); + final boolean visible = isNavigationBarColorViewVisible(); + if (visible && Color.alpha(mNavigationBarColor) != 0 && !navigationBarRect.isEmpty()) { + c.drawRect(navigationBarRect, mNavigationBarPaint); + } + } + } } diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java deleted file mode 100644 index 059eb876ad949..0000000000000 --- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java +++ /dev/null @@ -1,620 +0,0 @@ -/* - * 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.WindowConfiguration.ACTIVITY_TYPE_HOME; -import static android.graphics.Color.WHITE; -import static android.graphics.Color.alpha; -import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS; -import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; -import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; -import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; -import static android.view.WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES; -import static android.view.WindowManager.LayoutParams.FLAG_LOCAL_FOCUS_MODE; -import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; -import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; -import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL; -import static android.view.WindowManager.LayoutParams.FLAG_SCALED; -import static android.view.WindowManager.LayoutParams.FLAG_SECURE; -import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY; -import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH; -import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION; -import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; -import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_USE_BLAST; -import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING; - -import static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES; -import static com.android.internal.policy.DecorView.STATUS_BAR_COLOR_VIEW_ATTRIBUTES; -import static com.android.internal.policy.DecorView.getNavigationBarRect; -import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW; -import static com.android.server.wm.TaskSnapshotController.getSystemBarInsets; -import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; -import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; - -import android.annotation.Nullable; -import android.app.ActivityManager.TaskDescription; -import android.app.ActivityThread; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.GraphicBuffer; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.PixelFormat; -import android.graphics.Point; -import android.graphics.Rect; -import android.graphics.RectF; -import android.hardware.HardwareBuffer; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.os.RemoteException; -import android.os.SystemClock; -import android.util.MergedConfiguration; -import android.util.Slog; -import android.view.IWindowSession; -import android.view.InsetsSourceControl; -import android.view.InsetsState; -import android.view.InsetsVisibilities; -import android.view.SurfaceControl; -import android.view.SurfaceSession; -import android.view.View; -import android.view.ViewGroup.LayoutParams; -import android.view.WindowManager; -import android.view.WindowManagerGlobal; -import android.window.ClientWindowFrames; -import android.window.TaskSnapshot; - -import com.android.internal.R; -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.policy.DecorView; -import com.android.internal.protolog.common.ProtoLog; -import com.android.internal.view.BaseIWindow; -import com.android.server.policy.WindowManagerPolicy.StartingSurface; - -/** - * This class represents a starting window that shows a snapshot. - *
- * DO NOT HOLD THE WINDOW MANAGER LOCK WHEN CALLING METHODS OF THIS CLASS!
- */
-class TaskSnapshotSurface implements StartingSurface {
-
- private static final long SIZE_MISMATCH_MINIMUM_TIME_MS = 450;
-
- /**
- * When creating the starting window, we use the exact same layout flags such that we end up
- * with a window with the exact same dimensions etc. However, these flags are not used in layout
- * and might cause other side effects so we exclude them.
- */
- static final int FLAG_INHERIT_EXCLUDES = FLAG_NOT_FOCUSABLE
- | FLAG_NOT_TOUCHABLE
- | FLAG_NOT_TOUCH_MODAL
- | FLAG_ALT_FOCUSABLE_IM
- | FLAG_NOT_FOCUSABLE
- | FLAG_HARDWARE_ACCELERATED
- | FLAG_IGNORE_CHEEK_PRESSES
- | FLAG_LOCAL_FOCUS_MODE
- | FLAG_SLIPPERY
- | FLAG_WATCH_OUTSIDE_TOUCH
- | FLAG_SPLIT_TOUCH
- | FLAG_SCALED
- | FLAG_SECURE;
-
- private static final int PRIVATE_FLAG_INHERITS = PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
-
- private static final String TAG = TAG_WITH_CLASS_NAME ? "SnapshotStartingWindow" : TAG_WM;
- private static final int MSG_REPORT_DRAW = 0;
- private static final String TITLE_FORMAT = "SnapshotStartingWindow for taskId=%s";
-
- //tmp vars for unused relayout params
- private static final Point sTmpSurfaceSize = new Point();
-
- private final Window mWindow;
- private final SurfaceControl mSurfaceControl;
- private final IWindowSession mSession;
- private final WindowManagerService mService;
- private final int mDisplayId;
- private final Rect mTaskBounds;
- private final Rect mFrame = new Rect();
- private final Rect mSystemBarInsets = new Rect();
- private TaskSnapshot mSnapshot;
- private final RectF mTmpSnapshotSize = new RectF();
- private final RectF mTmpDstFrame = new RectF();
- private final CharSequence mTitle;
- private boolean mHasDrawn;
- private long mShownTime;
- private final Handler mHandler;
- private boolean mSizeMismatch;
- private final Paint mBackgroundPaint = new Paint();
- private final int mActivityType;
- private final int mStatusBarColor;
- @VisibleForTesting final SystemBarBackgroundPainter mSystemBarBackgroundPainter;
- private final int mOrientationOnCreation;
- private final SurfaceControl.Transaction mTransaction;
- private final Matrix mSnapshotMatrix = new Matrix();
- private final float[] mTmpFloat9 = new float[9];
-
- static TaskSnapshotSurface create(WindowManagerService service, ActivityRecord activity,
- TaskSnapshot snapshot) {
- return create(service, activity, snapshot, WindowManagerGlobal.getWindowSession());
- }
-
- @VisibleForTesting
- static TaskSnapshotSurface create(WindowManagerService service, ActivityRecord activity,
- TaskSnapshot snapshot, IWindowSession session) {
-
- final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
- final Window window = new Window();
- window.setSession(session);
- final SurfaceControl surfaceControl = new SurfaceControl();
- final ClientWindowFrames tmpFrames = new ClientWindowFrames();
- final Rect taskBounds;
- final InsetsState mTmpInsetsState = new InsetsState();
- final InsetsVisibilities mRequestedVisibilities = new InsetsVisibilities();
- final InsetsSourceControl[] mTempControls = new InsetsSourceControl[0];
- final MergedConfiguration tmpMergedConfiguration = new MergedConfiguration();
- final TaskDescription taskDescription = new TaskDescription();
- taskDescription.setBackgroundColor(WHITE);
- final WindowState topFullscreenOpaqueWindow;
- final int appearance;
- final int windowFlags;
- final int windowPrivateFlags;
- final int currentOrientation;
- final int activityType;
- final InsetsState insetsState;
- synchronized (service.mGlobalLock) {
- final WindowState mainWindow = activity.findMainWindow();
- final Task task = activity.getTask();
- final ActivityRecord topFullscreenActivity =
- activity.getTask().getTopFullscreenActivity();
- // Already check the nullity in StartingSurfaceController#createTaskSnapshotSurface
- topFullscreenOpaqueWindow = topFullscreenActivity.getTopFullscreenOpaqueWindow();
- WindowManager.LayoutParams attrs = topFullscreenOpaqueWindow.mAttrs;
- appearance = attrs.insetsFlags.appearance;
- windowFlags = attrs.flags;
- windowPrivateFlags = attrs.privateFlags;
-
- layoutParams.packageName = mainWindow.getAttrs().packageName;
- layoutParams.windowAnimations = mainWindow.getAttrs().windowAnimations;
- layoutParams.dimAmount = mainWindow.getAttrs().dimAmount;
- layoutParams.type = TYPE_APPLICATION_STARTING;
- layoutParams.format = snapshot.getHardwareBuffer().getFormat();
- layoutParams.flags = (windowFlags & ~FLAG_INHERIT_EXCLUDES)
- | FLAG_NOT_FOCUSABLE
- | FLAG_NOT_TOUCHABLE;
- // Setting as trusted overlay to let touches pass through. This is safe because this
- // window is controlled by the system.
- layoutParams.privateFlags = (windowPrivateFlags & PRIVATE_FLAG_INHERITS)
- | PRIVATE_FLAG_TRUSTED_OVERLAY | PRIVATE_FLAG_USE_BLAST;
- layoutParams.token = activity.token;
- layoutParams.width = LayoutParams.MATCH_PARENT;
- layoutParams.height = LayoutParams.MATCH_PARENT;
- layoutParams.insetsFlags.appearance = appearance;
- layoutParams.insetsFlags.behavior = attrs.insetsFlags.behavior;
- layoutParams.layoutInDisplayCutoutMode = attrs.layoutInDisplayCutoutMode;
- layoutParams.setFitInsetsTypes(attrs.getFitInsetsTypes());
- layoutParams.setFitInsetsSides(attrs.getFitInsetsSides());
- layoutParams.setFitInsetsIgnoringVisibility(attrs.isFitInsetsIgnoringVisibility());
-
- layoutParams.setTitle(String.format(TITLE_FORMAT, task.mTaskId));
-
- final TaskDescription td = task.getTaskDescription();
- if (td != null) {
- taskDescription.copyFromPreserveHiddenFields(td);
- }
- taskBounds = new Rect();
- task.getBounds(taskBounds);
- currentOrientation = topFullscreenOpaqueWindow.getConfiguration().orientation;
- activityType = activity.getActivityType();
- insetsState = topFullscreenOpaqueWindow.getInsetsStateWithVisibilityOverride();
-
- }
- int displayId = activity.getDisplayContent().getDisplayId();
- try {
- final int res = session.addToDisplay(window, layoutParams, View.GONE, displayId,
- mRequestedVisibilities, null /* outInputChannel */, mTmpInsetsState,
- mTempControls);
- if (res < 0) {
- Slog.w(TAG, "Failed to add snapshot starting window res=" + res);
- return null;
- }
- } catch (RemoteException e) {
- // Local call.
- }
- final TaskSnapshotSurface snapshotSurface = new TaskSnapshotSurface(service, displayId,
- window, surfaceControl, snapshot, layoutParams.getTitle(), taskDescription,
- appearance, windowFlags, windowPrivateFlags, taskBounds, currentOrientation,
- activityType, insetsState);
- window.setOuter(snapshotSurface);
- try {
- session.relayout(window, layoutParams, -1, -1, View.VISIBLE, 0, -1,
- tmpFrames, tmpMergedConfiguration, surfaceControl, mTmpInsetsState,
- mTempControls, sTmpSurfaceSize);
- } catch (RemoteException e) {
- // Local call.
- }
-
- final Rect systemBarInsets = getSystemBarInsets(tmpFrames.frame, insetsState);
- snapshotSurface.setFrames(tmpFrames.frame, systemBarInsets);
- snapshotSurface.drawSnapshot();
- return snapshotSurface;
- }
-
- @VisibleForTesting
- TaskSnapshotSurface(WindowManagerService service, int displayId, Window window,
- SurfaceControl surfaceControl, TaskSnapshot snapshot, CharSequence title,
- TaskDescription taskDescription, int appearance, int windowFlags,
- int windowPrivateFlags, Rect taskBounds, int currentOrientation, int activityType,
- InsetsState insetsState) {
- mService = service;
- mDisplayId = displayId;
- mHandler = new Handler(mService.mH.getLooper());
- mSession = WindowManagerGlobal.getWindowSession();
- mWindow = window;
- mSurfaceControl = surfaceControl;
- mSnapshot = snapshot;
- mTitle = title;
- int backgroundColor = taskDescription.getBackgroundColor();
- mBackgroundPaint.setColor(backgroundColor != 0 ? backgroundColor : WHITE);
- mTaskBounds = taskBounds;
- mSystemBarBackgroundPainter = new SystemBarBackgroundPainter(windowFlags,
- windowPrivateFlags, appearance, taskDescription, 1f, insetsState);
- mStatusBarColor = taskDescription.getStatusBarColor();
- mOrientationOnCreation = currentOrientation;
- mActivityType = activityType;
- mTransaction = mService.mTransactionFactory.get();
- }
-
- @Override
- public void remove(boolean animate) {
- synchronized (mService.mGlobalLock) {
- final long now = SystemClock.uptimeMillis();
- if (mSizeMismatch && now - mShownTime < SIZE_MISMATCH_MINIMUM_TIME_MS
- // Show the latest content as soon as possible for unlocking to home.
- && mActivityType != ACTIVITY_TYPE_HOME) {
- mHandler.postAtTime(() -> remove(false /* prepareAnimation */),
- mShownTime + SIZE_MISMATCH_MINIMUM_TIME_MS);
- ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
- "Defer removing snapshot surface in %dms", (now - mShownTime));
-
- return;
- }
- }
- try {
- ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Removing snapshot surface");
- mSession.remove(mWindow);
- } catch (RemoteException e) {
- // Local call.
- }
- }
-
- @VisibleForTesting
- void setFrames(Rect frame, Rect systemBarInsets) {
- mFrame.set(frame);
- mSystemBarInsets.set(systemBarInsets);
- final HardwareBuffer snapshot = mSnapshot.getHardwareBuffer();
- mSizeMismatch = (mFrame.width() != snapshot.getWidth()
- || mFrame.height() != snapshot.getHeight());
- mSystemBarBackgroundPainter.setInsets(systemBarInsets);
- }
-
- private void drawSnapshot() {
- ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Drawing snapshot surface sizeMismatch=%b",
- mSizeMismatch);
- if (mSizeMismatch) {
- // The dimensions of the buffer and the window don't match, so attaching the buffer
- // will fail. Better create a child window with the exact dimensions and fill the parent
- // window with the background color!
- drawSizeMismatchSnapshot();
- } else {
- drawSizeMatchSnapshot();
- }
- synchronized (mService.mGlobalLock) {
- mShownTime = SystemClock.uptimeMillis();
- mHasDrawn = true;
- }
- reportDrawn();
-
- // In case window manager leaks us, make sure we don't retain the snapshot.
- mSnapshot = null;
- }
-
- private void drawSizeMatchSnapshot() {
- GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer(
- mSnapshot.getHardwareBuffer());
- mTransaction.setBuffer(mSurfaceControl, graphicBuffer)
- .setColorSpace(mSurfaceControl, mSnapshot.getColorSpace())
- .apply();
- }
-
- private void drawSizeMismatchSnapshot() {
- final HardwareBuffer buffer = mSnapshot.getHardwareBuffer();
- final SurfaceSession session = new SurfaceSession();
- // We consider nearly matched dimensions as there can be rounding errors and the user won't
- // notice very minute differences from scaling one dimension more than the other
- final boolean aspectRatioMismatch = Math.abs(
- ((float) buffer.getWidth() / buffer.getHeight())
- - ((float) mFrame.width() / mFrame.height())) > 0.01f;
-
- // Keep a reference to it such that it doesn't get destroyed when finalized.
- final String name = mTitle + " - task-snapshot-surface";
- SurfaceControl childSurfaceControl = mService.mSurfaceControlFactory.apply(session)
- .setName(name)
- .setBLASTLayer()
- .setFormat(buffer.getFormat())
- .setParent(mSurfaceControl)
- .setCallsite("TaskSnapshotSurface.drawSizeMismatchSnapshot")
- .build();
-
- final Rect frame;
- // We can just show the surface here as it will still be hidden as the parent is
- // still hidden.
- mTransaction.show(childSurfaceControl);
- if (aspectRatioMismatch) {
- // Clip off ugly navigation bar.
- final Rect crop = calculateSnapshotCrop();
- frame = calculateSnapshotFrame(crop);
- mTransaction.setWindowCrop(childSurfaceControl, crop);
- mTransaction.setPosition(childSurfaceControl, frame.left, frame.top);
- mTmpSnapshotSize.set(crop);
- mTmpDstFrame.set(frame);
- } else {
- frame = null;
- mTmpSnapshotSize.set(0, 0, buffer.getWidth(), buffer.getHeight());
- mTmpDstFrame.set(mFrame);
- mTmpDstFrame.offsetTo(0, 0);
- }
-
- // Scale the mismatch dimensions to fill the task bounds
- mSnapshotMatrix.setRectToRect(mTmpSnapshotSize, mTmpDstFrame, Matrix.ScaleToFit.FILL);
- mTransaction.setMatrix(childSurfaceControl, mSnapshotMatrix, mTmpFloat9);
-
- GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer(
- mSnapshot.getHardwareBuffer());
- mTransaction.setColorSpace(childSurfaceControl, mSnapshot.getColorSpace());
- mTransaction.setBuffer(childSurfaceControl, graphicBuffer);
- // This is the way to tell the input system to exclude this surface from occlusion
- // detection since we don't have a window for it. We do this because this window is
- // generated by the system as well as its content (the snapshot of the app).
- InputMonitor.setTrustedOverlayInputInfo(childSurfaceControl, mTransaction, mDisplayId,
- name);
-
- if (aspectRatioMismatch) {
- GraphicBuffer background = GraphicBuffer.create(mFrame.width(), mFrame.height(),
- PixelFormat.RGBA_8888,
- GraphicBuffer.USAGE_HW_TEXTURE | GraphicBuffer.USAGE_HW_COMPOSER
- | GraphicBuffer.USAGE_SW_WRITE_RARELY);
- final Canvas c = background.lockCanvas();
- drawBackgroundAndBars(c, frame);
- background.unlockCanvasAndPost(c);
- mTransaction.setBuffer(mSurfaceControl, background);
- }
- mTransaction.apply();
- }
-
- /**
- * Calculates the snapshot crop in snapshot coordinate space.
- *
- * @return crop rect in snapshot coordinate space.
- */
- @VisibleForTesting
- Rect calculateSnapshotCrop() {
- final Rect rect = new Rect();
- final HardwareBuffer snapshot = mSnapshot.getHardwareBuffer();
- rect.set(0, 0, snapshot.getWidth(), snapshot.getHeight());
- final Rect insets = mSnapshot.getContentInsets();
-
- final float scaleX = (float) snapshot.getWidth() / mSnapshot.getTaskSize().x;
- final float scaleY = (float) snapshot.getHeight() / mSnapshot.getTaskSize().y;
-
- // Let's remove all system decorations except the status bar, but only if the task is at the
- // very top of the screen.
- final boolean isTop = mTaskBounds.top == 0 && mFrame.top == 0;
- rect.inset((int) (insets.left * scaleX),
- isTop ? 0 : (int) (insets.top * scaleY),
- (int) (insets.right * scaleX),
- (int) (insets.bottom * scaleY));
- return rect;
- }
-
- /**
- * Calculates the snapshot frame in window coordinate space from crop.
- *
- * @param crop rect that is in snapshot coordinate space.
- */
- @VisibleForTesting
- Rect calculateSnapshotFrame(Rect crop) {
- final HardwareBuffer snapshot = mSnapshot.getHardwareBuffer();
- final float scaleX = (float) snapshot.getWidth() / mSnapshot.getTaskSize().x;
- final float scaleY = (float) snapshot.getHeight() / mSnapshot.getTaskSize().y;
-
- // Rescale the frame from snapshot to window coordinate space
- final Rect frame = new Rect(0, 0,
- (int) (crop.width() / scaleX + 0.5f),
- (int) (crop.height() / scaleY + 0.5f)
- );
-
- // However, we also need to make space for the navigation bar on the left side.
- frame.offset(mSystemBarInsets.left, 0);
- return frame;
- }
-
- @VisibleForTesting
- void drawBackgroundAndBars(Canvas c, Rect frame) {
- final int statusBarHeight = mSystemBarBackgroundPainter.getStatusBarColorViewHeight();
- final boolean fillHorizontally = c.getWidth() > frame.right;
- final boolean fillVertically = c.getHeight() > frame.bottom;
- if (fillHorizontally) {
- c.drawRect(frame.right, alpha(mStatusBarColor) == 0xFF ? statusBarHeight : 0,
- c.getWidth(), fillVertically
- ? frame.bottom
- : c.getHeight(),
- mBackgroundPaint);
- }
- if (fillVertically) {
- c.drawRect(0, frame.bottom, c.getWidth(), c.getHeight(), mBackgroundPaint);
- }
- mSystemBarBackgroundPainter.drawDecors(c, frame);
- }
-
- private void reportDrawn() {
- try {
- mSession.finishDrawing(mWindow, null /* postDrawTransaction */);
- } catch (RemoteException e) {
- // Local call.
- }
- }
-
- private static Handler sHandler = new Handler(Looper.getMainLooper()) {
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_REPORT_DRAW:
- final boolean hasDrawn;
- final TaskSnapshotSurface surface = (TaskSnapshotSurface) msg.obj;
- synchronized (surface.mService.mGlobalLock) {
- hasDrawn = surface.mHasDrawn;
- }
- if (hasDrawn) {
- surface.reportDrawn();
- }
- break;
- }
- }
- };
-
- @VisibleForTesting
- static class Window extends BaseIWindow {
-
- private TaskSnapshotSurface mOuter;
-
- public void setOuter(TaskSnapshotSurface outer) {
- mOuter = outer;
- }
-
- @Override
- public void resized(ClientWindowFrames frames, boolean reportDraw,
- MergedConfiguration mergedConfiguration, boolean forceLayout,
- boolean alwaysConsumeSystemBars, int displayId) {
- if (mergedConfiguration != null && mOuter != null
- && mOuter.mOrientationOnCreation
- != mergedConfiguration.getMergedConfiguration().orientation) {
-
- // The orientation of the screen is changing. We better remove the snapshot ASAP as
- // we are going to wait on the new window in any case to unfreeze the screen, and
- // the starting window is not needed anymore.
- sHandler.post(() -> mOuter.remove(false /* prepareAnimation */));
- }
- if (reportDraw) {
- sHandler.obtainMessage(MSG_REPORT_DRAW, mOuter).sendToTarget();
- }
- }
- }
-
- /**
- * Helper class to draw the background of the system bars in regions the task snapshot isn't
- * filling the window.
- */
- static class SystemBarBackgroundPainter {
-
- private final Paint mStatusBarPaint = new Paint();
- private final Paint mNavigationBarPaint = new Paint();
- private final int mStatusBarColor;
- private final int mNavigationBarColor;
- private final int mWindowFlags;
- private final int mWindowPrivateFlags;
- private final float mScale;
- private final InsetsState mInsetsState;
- private final Rect mSystemBarInsets = new Rect();
-
- SystemBarBackgroundPainter(int windowFlags, int windowPrivateFlags, int appearance,
- TaskDescription taskDescription, float scale, InsetsState insetsState) {
- mWindowFlags = windowFlags;
- mWindowPrivateFlags = windowPrivateFlags;
- mScale = scale;
- final Context context = ActivityThread.currentActivityThread().getSystemUiContext();
- final int semiTransparent = context.getColor(
- R.color.system_bar_background_semi_transparent);
- mStatusBarColor = DecorView.calculateBarColor(windowFlags, FLAG_TRANSLUCENT_STATUS,
- semiTransparent, taskDescription.getStatusBarColor(), appearance,
- APPEARANCE_LIGHT_STATUS_BARS,
- taskDescription.getEnsureStatusBarContrastWhenTransparent());
- mNavigationBarColor = DecorView.calculateBarColor(windowFlags,
- FLAG_TRANSLUCENT_NAVIGATION, semiTransparent,
- taskDescription.getNavigationBarColor(), appearance,
- APPEARANCE_LIGHT_NAVIGATION_BARS,
- taskDescription.getEnsureNavigationBarContrastWhenTransparent()
- && context.getResources().getBoolean(R.bool.config_navBarNeedsScrim));
- mStatusBarPaint.setColor(mStatusBarColor);
- mNavigationBarPaint.setColor(mNavigationBarColor);
- mInsetsState = insetsState;
- }
-
- void setInsets(Rect systemBarInsets) {
- mSystemBarInsets.set(systemBarInsets);
- }
-
- int getStatusBarColorViewHeight() {
- final boolean forceBarBackground =
- (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0;
- if (STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
- mInsetsState, mStatusBarColor, mWindowFlags, forceBarBackground)) {
- return (int) (mSystemBarInsets.top * mScale);
- } else {
- return 0;
- }
- }
-
- private boolean isNavigationBarColorViewVisible() {
- final boolean forceBarBackground =
- (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0;
- return NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
- mInsetsState, mNavigationBarColor, mWindowFlags, forceBarBackground);
- }
-
- void drawDecors(Canvas c, @Nullable Rect alreadyDrawnFrame) {
- drawStatusBarBackground(c, alreadyDrawnFrame, getStatusBarColorViewHeight());
- drawNavigationBarBackground(c);
- }
-
- @VisibleForTesting
- void drawStatusBarBackground(Canvas c, @Nullable Rect alreadyDrawnFrame,
- int statusBarHeight) {
- if (statusBarHeight > 0 && Color.alpha(mStatusBarColor) != 0
- && (alreadyDrawnFrame == null || c.getWidth() > alreadyDrawnFrame.right)) {
- final int rightInset = (int) (mSystemBarInsets.right * mScale);
- final int left = alreadyDrawnFrame != null ? alreadyDrawnFrame.right : 0;
- c.drawRect(left, 0, c.getWidth() - rightInset, statusBarHeight, mStatusBarPaint);
- }
- }
-
- @VisibleForTesting
- void drawNavigationBarBackground(Canvas c) {
- final Rect navigationBarRect = new Rect();
- getNavigationBarRect(c.getWidth(), c.getHeight(), mSystemBarInsets, navigationBarRect,
- mScale);
- final boolean visible = isNavigationBarColorViewVisible();
- if (visible && Color.alpha(mNavigationBarColor) != 0 && !navigationBarRect.isEmpty()) {
- c.drawRect(navigationBarRect, mNavigationBarPaint);
- }
- }
- }
-}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 83d819f284d00..5327dee56e605 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -2490,9 +2490,8 @@ public class ActivityRecordTests extends WindowTestsBase {
public void testCreateRemoveStartingWindow() {
registerTestStartingWindowOrganizer();
final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
- activity.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
- false, false, false);
+ activity.addStartingWindow(mPackageName, android.R.style.Theme, null, true, true, false,
+ true, false, false, false);
waitUntilHandlersIdle();
assertHasStartingWindow(activity);
activity.removeStartingWindow();
@@ -2503,9 +2502,8 @@ public class ActivityRecordTests extends WindowTestsBase {
private void testLegacySplashScreen(int targetSdk, int verifyType) {
final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
activity.mTargetSdk = targetSdk;
- activity.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
- false, false, false);
+ activity.addStartingWindow(mPackageName, android.R.style.Theme, null, true, true, false,
+ true, false, false, false);
waitUntilHandlersIdle();
assertHasStartingWindow(activity);
assertEquals(activity.mStartingData.mTypeParams & TYPE_PARAMETER_LEGACY_SPLASH_SCREEN,
@@ -2541,13 +2539,11 @@ public class ActivityRecordTests extends WindowTestsBase {
.setVisible(false).build();
final ActivityRecord activity2 = new ActivityBuilder(mAtm).setCreateTask(true)
.setVisible(false).build();
- activity1.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
- false, false, false);
+ activity1.addStartingWindow(mPackageName, android.R.style.Theme, null, true, true, false,
+ true, false, false, false);
waitUntilHandlersIdle();
- activity2.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, activity1,
- true, true, false, true, false, false, false);
+ activity2.addStartingWindow(mPackageName, android.R.style.Theme, activity1, true, true,
+ false, true, false, false, false);
waitUntilHandlersIdle();
assertFalse(mDisplayContent.mSkipAppTransitionAnimation);
assertNoStartingWindow(activity1);
@@ -2562,14 +2558,11 @@ public class ActivityRecordTests extends WindowTestsBase {
organizer.setRunnableWhenAddingSplashScreen(
() -> {
// Surprise, ...! Transfer window in the middle of the creation flow.
- activity2.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0,
- activity1, true, true, false,
- true, false, false, false);
+ activity2.addStartingWindow(mPackageName, android.R.style.Theme, activity1,
+ true, true, false, true, false, false, false);
});
- activity1.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
- false, false, false);
+ activity1.addStartingWindow(mPackageName, android.R.style.Theme, null, true, true, false,
+ true, false, false, false);
waitUntilHandlersIdle();
assertNoStartingWindow(activity1);
assertHasStartingWindow(activity2);
@@ -2580,13 +2573,11 @@ public class ActivityRecordTests extends WindowTestsBase {
registerTestStartingWindowOrganizer();
final ActivityRecord activity1 = new ActivityBuilder(mAtm).setCreateTask(true).build();
final ActivityRecord activity2 = new ActivityBuilder(mAtm).setCreateTask(true).build();
- activity1.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
- false, false, false);
+ activity1.addStartingWindow(mPackageName, android.R.style.Theme, null, true, true, false,
+ true, false, false, false);
waitUntilHandlersIdle();
- activity2.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, activity1,
- true, true, false, true, false, false, false);
+ activity2.addStartingWindow(mPackageName, android.R.style.Theme, activity1, true, true,
+ false, true, false, false, false);
waitUntilHandlersIdle();
assertNoStartingWindow(activity1);
assertHasStartingWindow(activity2);
@@ -2624,11 +2615,10 @@ public class ActivityRecordTests extends WindowTestsBase {
registerTestStartingWindowOrganizer();
final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
final Task task = activity.getTask();
- activity.addStartingWindow(mPackageName, android.R.style.Theme, null /* compatInfo */,
- "Test", 0 /* labelRes */, 0 /* icon */, 0 /* logo */, 0 /* windowFlags */,
- null /* transferFrom */, true /* newTask */, true /* taskSwitch */,
- false /* processRunning */, false /* allowTaskSnapshot */,
- false /* activityCreate */, false /* suggestEmpty */, false /* activityAllDrawn */);
+ activity.addStartingWindow(mPackageName, android.R.style.Theme, null /* transferFrom */,
+ true /* newTask */, true /* taskSwitch */, false /* processRunning */,
+ false /* allowTaskSnapshot */, false /* activityCreate */, false /* suggestEmpty
+ */, false /* activityAllDrawn */);
waitUntilHandlersIdle();
assertHasStartingWindow(activity);
@@ -2674,9 +2664,8 @@ public class ActivityRecordTests extends WindowTestsBase {
final ActivityRecord topActivity = new ActivityBuilder(mAtm).setTask(task).build();
topActivity.setVisible(false);
task.positionChildAt(topActivity, POSITION_TOP);
- activity.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
- false, false, false);
+ activity.addStartingWindow(mPackageName, android.R.style.Theme, null, true, true, false,
+ true, false, false, false);
waitUntilHandlersIdle();
// Make activities to have different rotation from it display and set fixed rotation
@@ -2691,9 +2680,8 @@ public class ActivityRecordTests extends WindowTestsBase {
doReturn(true).when(activity).isAnimating(anyInt());
// Make sure the fixed rotation transform linked to activity2 when adding starting window
// on activity2.
- topActivity.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, activity,
- false, false, false, true, false, false, false);
+ topActivity.addStartingWindow(mPackageName, android.R.style.Theme, activity, false, false,
+ false, true, false, false, false);
waitUntilHandlersIdle();
assertTrue(topActivity.hasFixedRotationTransform());
}
@@ -2707,9 +2695,8 @@ public class ActivityRecordTests extends WindowTestsBase {
activityTop.getTask().addChild(activityBottom, 0);
// Add a starting window.
- activityTop.addStartingWindow(mPackageName,
- android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
- false, false, false);
+ activityTop.addStartingWindow(mPackageName, android.R.style.Theme, null, true, true, false,
+ true, false, false, false);
waitUntilHandlersIdle();
// Make the top one invisible, and try transferring the starting window from the top to the
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java
index af21e02ce27cf..525888df7c784 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java
@@ -85,7 +85,7 @@ public class DisplayAreaPolicyBuilderTest {
@Rule
public final SystemServicesTestRule mSystemServices = new SystemServicesTestRule();
- private TestWindowManagerPolicy mPolicy = new TestWindowManagerPolicy(null, null);
+ private TestWindowManagerPolicy mPolicy = new TestWindowManagerPolicy();
private WindowManagerService mWms;
private RootDisplayArea mRoot;
private DisplayArea.Tokens mImeContainer;
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 5bc45d7c3d170..db60b98a7785e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -99,7 +99,6 @@ public class SystemServicesTestRule implements TestRule {
private static final String TAG = SystemServicesTestRule.class.getSimpleName();
static int sNextDisplayId = DEFAULT_DISPLAY + 100;
- static int sNextTaskId = 100;
private static final int[] TEST_USER_PROFILE_IDS = {};
@@ -109,8 +108,6 @@ public class SystemServicesTestRule implements TestRule {
private ActivityManagerService mAmService;
private ActivityTaskManagerService mAtmService;
private WindowManagerService mWmService;
- private TestWindowManagerPolicy mWMPolicy;
- private TestDisplayWindowSettingsProvider mTestDisplayWindowSettingsProvider;
private WindowState.PowerManagerWrapper mPowerManagerWrapper;
private InputManagerService mImService;
private InputChannel mInputChannel;
@@ -283,14 +280,14 @@ public class SystemServicesTestRule implements TestRule {
private void setUpWindowManagerService() {
mPowerManagerWrapper = mock(WindowState.PowerManagerWrapper.class);
- mWMPolicy = new TestWindowManagerPolicy(this::getWindowManagerService,
- mPowerManagerWrapper);
- mTestDisplayWindowSettingsProvider = new TestDisplayWindowSettingsProvider();
+ TestWindowManagerPolicy wmPolicy = new TestWindowManagerPolicy();
+ TestDisplayWindowSettingsProvider testDisplayWindowSettingsProvider =
+ new TestDisplayWindowSettingsProvider();
// Suppress StrictMode violation (DisplayWindowSettings) to avoid log flood.
DisplayThread.getHandler().post(StrictMode::allowThreadDiskWritesMask);
mWmService = WindowManagerService.main(
- mContext, mImService, false, false, mWMPolicy, mAtmService,
- mTestDisplayWindowSettingsProvider, StubTransaction::new,
+ mContext, mImService, false, false, wmPolicy, mAtmService,
+ testDisplayWindowSettingsProvider, StubTransaction::new,
() -> mSurfaceFactory.get(), (unused) -> new MockSurfaceControlBuilder());
spyOn(mWmService);
spyOn(mWmService.mRoot);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
deleted file mode 100644
index 9372530f0e80c..0000000000000
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotSurfaceTest.java
+++ /dev/null
@@ -1,336 +0,0 @@
-/*
- * Copyright (C) 2017 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.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
-import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
-
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.argThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
-
-import android.app.ActivityManager.TaskDescription;
-import android.content.ComponentName;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.ColorSpace;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.hardware.HardwareBuffer;
-import android.platform.test.annotations.Presubmit;
-import android.view.Display;
-import android.view.IWindowSession;
-import android.view.InsetsState;
-import android.view.Surface;
-import android.view.SurfaceControl;
-import android.view.WindowManager;
-import android.window.TaskSnapshot;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.server.wm.TaskSnapshotSurface.Window;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-/**
- * Test class for {@link TaskSnapshotSurface}.
- *
- * Build/Install/Run:
- * atest WmTests:TaskSnapshotSurfaceTest
- */
-@SmallTest
-@Presubmit
-@RunWith(WindowTestRunner.class)
-public class TaskSnapshotSurfaceTest extends WindowTestsBase {
-
- private TaskSnapshotSurface mSurface;
-
- private void setupSurface(int width, int height, Rect contentInsets, int sysuiVis,
- int windowFlags, Rect taskBounds) {
- // Previously when constructing TaskSnapshots for this test, scale was 1.0f, so to mimic
- // this behavior set the taskSize to be the same as the taskBounds width and height. The
- // taskBounds passed here are assumed to be the same task bounds as when the snapshot was
- // taken. We assume there is no aspect ratio mismatch between the screenshot and the
- // taskBounds
- assertEquals(width, taskBounds.width());
- assertEquals(height, taskBounds.height());
- Point taskSize = new Point(taskBounds.width(), taskBounds.height());
-
- final TaskSnapshot snapshot = createTaskSnapshot(width, height, taskSize, contentInsets);
- mSurface = new TaskSnapshotSurface(mWm, Display.DEFAULT_DISPLAY, new Window(),
- new SurfaceControl(), snapshot, "Test", createTaskDescription(Color.WHITE,
- Color.RED, Color.BLUE), sysuiVis, windowFlags, 0, taskBounds, ORIENTATION_PORTRAIT,
- ACTIVITY_TYPE_STANDARD, new InsetsState());
- }
-
- private TaskSnapshot createTaskSnapshot(int width, int height,
- Point taskSize, Rect contentInsets) {
- final HardwareBuffer buffer = HardwareBuffer.create(width, height, HardwareBuffer.RGBA_8888,
- 1, HardwareBuffer.USAGE_CPU_READ_RARELY);
- return new TaskSnapshot(
- System.currentTimeMillis(),
- new ComponentName("", ""), buffer,
- ColorSpace.get(ColorSpace.Named.SRGB), ORIENTATION_PORTRAIT,
- Surface.ROTATION_0, taskSize, contentInsets, false,
- true /* isRealSnapshot */, WINDOWING_MODE_FULLSCREEN,
- 0 /* systemUiVisibility */, false /* isTranslucent */, false /* hasImeSurface */);
- }
-
- private static TaskDescription createTaskDescription(int background, int statusBar,
- int navigationBar) {
- final TaskDescription td = new TaskDescription();
- td.setBackgroundColor(background);
- td.setStatusBarColor(statusBar);
- td.setNavigationBarColor(navigationBar);
- return td;
- }
-
- private void setupSurface(int width, int height) {
- setupSurface(width, height, new Rect(), 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
- new Rect(0, 0, width, height));
- }
-
- private boolean isTrustedOverlay(WindowManager.LayoutParams params) {
- return (params.privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) != 0;
- }
-
- @Before
- public void setUp() throws Exception {
- mSystemServicesTestRule.setSurfaceFactory(() -> {
- Surface surface = mock(Surface.class);
- when(surface.isValid()).thenReturn(true);
- return surface;
- });
- }
-
- @Test
- public void createSurface_asTrustedOverlay() throws Exception {
- Point task = new Point(200, 100);
- ActivityRecord activityRecord = createActivityRecord(mDisplayContent);
- createWindow(null, TYPE_BASE_APPLICATION, activityRecord, "window");
- TaskSnapshot taskSnapshot = createTaskSnapshot(task.x, task.y, task, new Rect());
- IWindowSession session = mock(IWindowSession.class);
-
- TaskSnapshotSurface surface = TaskSnapshotSurface.create(mWm, activityRecord, taskSnapshot,
- session);
-
- assertThat(surface).isNotNull();
- verify(session).addToDisplay(any(), argThat(this::isTrustedOverlay), anyInt(), anyInt(),
- any(), any(), any(), any());
- }
-
- @Test
- public void fillEmptyBackground_fillHorizontally() {
- setupSurface(200, 100);
- final Canvas mockCanvas = mock(Canvas.class);
- when(mockCanvas.getWidth()).thenReturn(200);
- when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 100, 200));
- verify(mockCanvas).drawRect(eq(100.0f), eq(0.0f), eq(200.0f), eq(100.0f), any());
- }
-
- @Test
- public void fillEmptyBackground_fillVertically() {
- setupSurface(100, 200);
- final Canvas mockCanvas = mock(Canvas.class);
- when(mockCanvas.getWidth()).thenReturn(100);
- when(mockCanvas.getHeight()).thenReturn(200);
- mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 200, 100));
- verify(mockCanvas).drawRect(eq(0.0f), eq(100.0f), eq(100.0f), eq(200.0f), any());
- }
-
- @Test
- public void fillEmptyBackground_fillBoth() {
- setupSurface(200, 200);
- final Canvas mockCanvas = mock(Canvas.class);
- when(mockCanvas.getWidth()).thenReturn(200);
- when(mockCanvas.getHeight()).thenReturn(200);
- mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 100, 100));
- verify(mockCanvas).drawRect(eq(100.0f), eq(0.0f), eq(200.0f), eq(100.0f), any());
- verify(mockCanvas).drawRect(eq(0.0f), eq(100.0f), eq(200.0f), eq(200.0f), any());
- }
-
- @Test
- public void fillEmptyBackground_dontFill_sameSize() {
- setupSurface(100, 100);
- final Canvas mockCanvas = mock(Canvas.class);
- when(mockCanvas.getWidth()).thenReturn(100);
- when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 100, 100));
- verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
- }
-
- @Test
- public void fillEmptyBackground_dontFill_bitmapLarger() {
- setupSurface(100, 100);
- final Canvas mockCanvas = mock(Canvas.class);
- when(mockCanvas.getWidth()).thenReturn(100);
- when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.drawBackgroundAndBars(mockCanvas, new Rect(0, 0, 200, 200));
- verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
- }
-
- @Test
- public void testCalculateSnapshotCrop() {
- setupSurface(100, 100, new Rect(0, 10, 0, 10), 0, 0, new Rect(0, 0, 100, 100));
- assertEquals(new Rect(0, 0, 100, 90), mSurface.calculateSnapshotCrop());
- }
-
- @Test
- public void testCalculateSnapshotCrop_taskNotOnTop() {
- setupSurface(100, 100, new Rect(0, 10, 0, 10), 0, 0, new Rect(0, 50, 100, 150));
- assertEquals(new Rect(0, 10, 100, 90), mSurface.calculateSnapshotCrop());
- }
-
- @Test
- public void testCalculateSnapshotCrop_navBarLeft() {
- setupSurface(100, 100, new Rect(10, 10, 0, 0), 0, 0, new Rect(0, 0, 100, 100));
- assertEquals(new Rect(10, 0, 100, 100), mSurface.calculateSnapshotCrop());
- }
-
- @Test
- public void testCalculateSnapshotCrop_navBarRight() {
- setupSurface(100, 100, new Rect(0, 10, 10, 0), 0, 0, new Rect(0, 0, 100, 100));
- assertEquals(new Rect(0, 0, 90, 100), mSurface.calculateSnapshotCrop());
- }
-
- @Test
- public void testCalculateSnapshotCrop_waterfall() {
- setupSurface(100, 100, new Rect(5, 10, 5, 10), 0, 0, new Rect(0, 0, 100, 100));
- assertEquals(new Rect(5, 0, 95, 90), mSurface.calculateSnapshotCrop());
- }
-
- @Test
- public void testCalculateSnapshotFrame() {
- setupSurface(100, 100);
- final Rect insets = new Rect(0, 10, 0, 10);
- mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
- assertEquals(new Rect(0, 0, 100, 80),
- mSurface.calculateSnapshotFrame(new Rect(0, 10, 100, 90)));
- }
-
- @Test
- public void testCalculateSnapshotFrame_navBarLeft() {
- setupSurface(100, 100);
- final Rect insets = new Rect(10, 10, 0, 0);
- mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
- assertEquals(new Rect(10, 0, 100, 90),
- mSurface.calculateSnapshotFrame(new Rect(10, 10, 100, 100)));
- }
-
- @Test
- public void testCalculateSnapshotFrame_waterfall() {
- setupSurface(100, 100, new Rect(5, 10, 5, 10), 0, 0, new Rect(0, 0, 100, 100));
- final Rect insets = new Rect(0, 10, 0, 10);
- mSurface.setFrames(new Rect(5, 0, 95, 100), insets);
- assertEquals(new Rect(0, 0, 90, 90),
- mSurface.calculateSnapshotFrame(new Rect(5, 0, 95, 90)));
- }
-
- @Test
- public void testDrawStatusBarBackground() {
- setupSurface(100, 100);
- final Rect insets = new Rect(0, 10, 10, 0);
- mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
- final Canvas mockCanvas = mock(Canvas.class);
- when(mockCanvas.getWidth()).thenReturn(100);
- when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.mSystemBarBackgroundPainter.drawStatusBarBackground(
- mockCanvas, new Rect(0, 0, 50, 100), 10);
- verify(mockCanvas).drawRect(eq(50.0f), eq(0.0f), eq(90.0f), eq(10.0f), any());
- }
-
- @Test
- public void testDrawStatusBarBackground_nullFrame() {
- setupSurface(100, 100);
- final Rect insets = new Rect(0, 10, 10, 0);
- mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
- final Canvas mockCanvas = mock(Canvas.class);
- when(mockCanvas.getWidth()).thenReturn(100);
- when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.mSystemBarBackgroundPainter.drawStatusBarBackground(
- mockCanvas, null, 10);
- verify(mockCanvas).drawRect(eq(0.0f), eq(0.0f), eq(90.0f), eq(10.0f), any());
- }
-
- @Test
- public void testDrawStatusBarBackground_nope() {
- setupSurface(100, 100);
- final Rect insets = new Rect(0, 10, 10, 0);
- mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
- final Canvas mockCanvas = mock(Canvas.class);
- when(mockCanvas.getWidth()).thenReturn(100);
- when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.mSystemBarBackgroundPainter.drawStatusBarBackground(
- mockCanvas, new Rect(0, 0, 100, 100), 10);
- verify(mockCanvas, never()).drawRect(anyInt(), anyInt(), anyInt(), anyInt(), any());
- }
-
- @Test
- public void testDrawNavigationBarBackground() {
- final Rect insets = new Rect(0, 10, 0, 10);
- setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
- new Rect(0, 0, 100, 100));
- mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
- final Canvas mockCanvas = mock(Canvas.class);
- when(mockCanvas.getWidth()).thenReturn(100);
- when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.mSystemBarBackgroundPainter.drawNavigationBarBackground(mockCanvas);
- verify(mockCanvas).drawRect(eq(new Rect(0, 90, 100, 100)), any());
- }
-
- @Test
- public void testDrawNavigationBarBackground_left() {
- final Rect insets = new Rect(10, 10, 0, 0);
- setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
- new Rect(0, 0, 100, 100));
- mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
- final Canvas mockCanvas = mock(Canvas.class);
- when(mockCanvas.getWidth()).thenReturn(100);
- when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.mSystemBarBackgroundPainter.drawNavigationBarBackground(mockCanvas);
- verify(mockCanvas).drawRect(eq(new Rect(0, 0, 10, 100)), any());
- }
-
- @Test
- public void testDrawNavigationBarBackground_right() {
- final Rect insets = new Rect(0, 10, 10, 0);
- setupSurface(100, 100, insets, 0, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
- new Rect(0, 0, 100, 100));
- mSurface.setFrames(new Rect(0, 0, 100, 100), insets);
- final Canvas mockCanvas = mock(Canvas.class);
- when(mockCanvas.getWidth()).thenReturn(100);
- when(mockCanvas.getHeight()).thenReturn(100);
- mSurface.mSystemBarBackgroundPainter.drawNavigationBarBackground(mockCanvas);
- verify(mockCanvas).drawRect(eq(new Rect(90, 0, 100, 100)), any());
- }
-}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 9001578cf37ae..f570005f99ccd 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -16,23 +16,16 @@
package com.android.server.wm;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
-
import android.annotation.Nullable;
import android.content.Context;
-import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.IBinder;
import android.os.PowerManager.GoToSleepReason;
import android.os.PowerManager.WakeReason;
-import android.os.RemoteException;
import android.util.proto.ProtoOutputStream;
-import android.view.IWindow;
import android.view.IWindowManager;
import android.view.KeyEvent;
import android.view.WindowManager;
@@ -41,30 +34,19 @@ import android.view.animation.Animation;
import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IShortcutService;
import com.android.server.policy.WindowManagerPolicy;
-import com.android.server.wm.WindowState.PowerManagerWrapper;
import java.io.PrintWriter;
-import java.util.function.Supplier;
class TestWindowManagerPolicy implements WindowManagerPolicy {
- private final Supplier