From d92645873e72dd1675423953ef774d61e9579bb5 Mon Sep 17 00:00:00 2001 From: wilsonshih Date: Wed, 30 Mar 2022 19:02:24 +0800 Subject: [PATCH] Clear the system bars color when removing the splash screen window. There can reset the system bars color once the splash screen window is going to be removed, so the real system bars color can be controlled by app, without waiting for the reveal animation. Also clear this effect when transfer splash screen to client, so client can control the color on their own. Bug: 196550450 Test: verify no status bar color changed when playing reveal animation. Change-Id: Ibb353d350fa2921188c8c4b54f8e029ee3869c16 --- core/java/android/app/ActivityThread.java | 2 +- .../java/android/window/SplashScreenView.java | 73 +------------------ .../SplashscreenContentDrawer.java | 17 ----- .../StartingSurfaceDrawer.java | 60 ++++++++++++++- 4 files changed, 62 insertions(+), 90 deletions(-) diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 3b843a9c622a9..2e919638120a7 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -4109,8 +4109,8 @@ public final class ActivityThread extends ClientTransactionHandler @NonNull SurfaceControl startingWindowLeash) { final SplashScreenView.Builder builder = new SplashScreenView.Builder(r.activity); final SplashScreenView view = builder.createFromParcel(parcelable).build(); + view.attachHostWindow(r.window); decorView.addView(view); - view.attachHostActivityAndSetSystemUIColors(r.activity, r.window); view.requestLayout(); view.getViewTreeObserver().addOnDrawListener(new ViewTreeObserver.OnDrawListener() { diff --git a/core/java/android/window/SplashScreenView.java b/core/java/android/window/SplashScreenView.java index a791cfab84e22..83f4097324773 100644 --- a/core/java/android/window/SplashScreenView.java +++ b/core/java/android/window/SplashScreenView.java @@ -16,9 +16,6 @@ package android.window; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; -import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; -import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION; -import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS; import static com.android.internal.jank.InteractionJankMonitor.CUJ_SPLASHSCREEN_AVD; @@ -29,11 +26,9 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; import android.annotation.UiThread; -import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; -import android.graphics.Color; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; @@ -52,15 +47,12 @@ import android.view.SurfaceView; import android.view.View; import android.view.ViewGroup; import android.view.Window; -import android.view.WindowInsetsController; -import android.view.WindowManager; import android.widget.FrameLayout; import android.widget.ImageView; import com.android.internal.R; import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.policy.DecorView; -import com.android.internal.util.ContrastColorUtil; import java.time.Duration; import java.time.Instant; @@ -87,12 +79,6 @@ public final class SplashScreenView extends FrameLayout { private static final String TAG = SplashScreenView.class.getSimpleName(); private static final boolean DEBUG = Build.IS_DEBUGGABLE; - private static final int LIGHT_BARS_MASK = - WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS - | WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; - private static final int WINDOW_FLAG_MASK = FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS - | FLAG_TRANSLUCENT_NAVIGATION | FLAG_TRANSLUCENT_STATUS; - private boolean mNotCopyable; private boolean mIsCopied; private int mInitBackgroundColor; @@ -107,9 +93,6 @@ public final class SplashScreenView extends FrameLayout { private final Rect mTmpRect = new Rect(); private final int[] mTmpPos = new int[2]; - // The host activity when transfer view to it. - private Activity mHostActivity; - @Nullable private SurfaceControlViewHost.SurfacePackage mSurfacePackageCopy; @Nullable @@ -123,14 +106,7 @@ public final class SplashScreenView extends FrameLayout { // cache original window and status private Window mWindow; - private int mAppWindowFlags; - private int mStatusBarColor; - private int mNavigationBarColor; - private int mSystemBarsAppearance; private boolean mHasRemoved; - private boolean mNavigationContrastEnforced; - private boolean mStatusContrastEnforced; - private boolean mDecorFitsSystemWindows; /** * Internal builder to create a SplashScreenView object. @@ -568,7 +544,6 @@ public final class SplashScreenView extends FrameLayout { if (decorView != null) { decorView.removeView(this); } - restoreSystemUIColors(); mWindow = null; } mHasRemoved = true; @@ -649,56 +624,12 @@ public final class SplashScreenView extends FrameLayout { } /** - * Called when this view is attached to an activity. This also makes SystemUI colors - * transparent so the content of splash screen view can draw fully. + * Called when this view is attached to a window of an activity. * * @hide */ - public void attachHostActivityAndSetSystemUIColors(Activity activity, Window window) { - mHostActivity = activity; + public void attachHostWindow(Window window) { mWindow = window; - final WindowManager.LayoutParams attr = window.getAttributes(); - mAppWindowFlags = attr.flags; - mStatusBarColor = window.getStatusBarColor(); - mNavigationBarColor = window.getNavigationBarColor(); - mSystemBarsAppearance = window.getInsetsController().getSystemBarsAppearance(); - mNavigationContrastEnforced = window.isNavigationBarContrastEnforced(); - mStatusContrastEnforced = window.isStatusBarContrastEnforced(); - mDecorFitsSystemWindows = window.decorFitsSystemWindows(); - - applySystemBarsContrastColor(window.getInsetsController(), mInitBackgroundColor); - // Let app draw the background of bars. - window.addFlags(FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); - // Use specified bar colors instead of window background. - window.clearFlags(FLAG_TRANSLUCENT_STATUS | FLAG_TRANSLUCENT_NAVIGATION); - window.setStatusBarColor(Color.TRANSPARENT); - window.setNavigationBarColor(Color.TRANSPARENT); - window.setDecorFitsSystemWindows(false); - window.setStatusBarContrastEnforced(false); - window.setNavigationBarContrastEnforced(false); - } - - /** Called when this view is removed from the host activity. */ - private void restoreSystemUIColors() { - mWindow.setFlags(mAppWindowFlags, WINDOW_FLAG_MASK); - mWindow.setStatusBarColor(mStatusBarColor); - mWindow.setNavigationBarColor(mNavigationBarColor); - mWindow.getInsetsController().setSystemBarsAppearance(mSystemBarsAppearance, - LIGHT_BARS_MASK); - mWindow.setDecorFitsSystemWindows(mDecorFitsSystemWindows); - mWindow.setStatusBarContrastEnforced(mStatusContrastEnforced); - mWindow.setNavigationBarContrastEnforced(mNavigationContrastEnforced); - } - - /** - * Makes the icon color of system bars contrast. - * @hide - */ - public static void applySystemBarsContrastColor(WindowInsetsController windowInsetsController, - int backgroundColor) { - final int lightBarAppearance = ContrastColorUtil.isColorLight(backgroundColor) - ? LIGHT_BARS_MASK : 0; - windowInsetsController.setSystemBarsAppearance(lightBarAppearance, LIGHT_BARS_MASK); } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java index b6c8cffb9699a..326806c3a4fc7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java @@ -56,7 +56,6 @@ import android.util.ArrayMap; import android.util.Slog; import android.view.ContextThemeWrapper; import android.view.SurfaceControl; -import android.view.View; import android.window.SplashScreenView; import android.window.StartingWindowInfo; import android.window.StartingWindowInfo.StartingWindowType; @@ -536,22 +535,6 @@ public class SplashscreenContentDrawer { mBrandingImageHeight); } final SplashScreenView splashScreenView = builder.build(); - if (mSuggestType != STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) { - splashScreenView.addOnAttachStateChangeListener( - new View.OnAttachStateChangeListener() { - @Override - public void onViewAttachedToWindow(View v) { - SplashScreenView.applySystemBarsContrastColor( - v.getWindowInsetsController(), - splashScreenView.getInitBackgroundColor()); - } - - @Override - public void onViewDetachedFromWindow(View v) { - } - }); - } - Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); return splashScreenView; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java index 04d6ef7f95051..1a0688c4f1ee7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java @@ -50,6 +50,7 @@ import android.view.Choreographer; import android.view.Display; import android.view.SurfaceControlViewHost; import android.view.View; +import android.view.WindowInsetsController; import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.widget.FrameLayout; @@ -63,6 +64,7 @@ import android.window.TaskSnapshot; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.protolog.common.ProtoLog; +import com.android.internal.util.ContrastColorUtil; import com.android.launcher3.icons.IconProvider; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.TransactionPool; @@ -121,6 +123,9 @@ public class StartingSurfaceDrawer { private StartingSurface.SysuiProxy mSysuiProxy; private final StartingWindowRemovalInfo mTmpRemovalInfo = new StartingWindowRemovalInfo(); + private static final int LIGHT_BARS_MASK = + WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS + | WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; /** * The minimum duration during which the splash screen is shown when the splash screen icon is * animated. @@ -361,9 +366,27 @@ public class StartingSurfaceDrawer { // the window before first round relayoutWindow, which will happen after insets // animation. mChoreographer.postCallback(CALLBACK_INSETS_ANIMATION, setViewSynchronized, null); - // Block until we get the background color. final StartingWindowRecord record = mStartingWindowRecords.get(taskId); + record.parseAppSystemBarColor(context); + // Block until we get the background color. final SplashScreenView contentView = viewSupplier.get(); + if (suggestType != STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) { + contentView.addOnAttachStateChangeListener( + new View.OnAttachStateChangeListener() { + @Override + public void onViewAttachedToWindow(View v) { + final int lightBarAppearance = ContrastColorUtil.isColorLight( + contentView.getInitBackgroundColor()) + ? LIGHT_BARS_MASK : 0; + contentView.getWindowInsetsController().setSystemBarsAppearance( + lightBarAppearance, LIGHT_BARS_MASK); + } + + @Override + public void onViewDetachedFromWindow(View v) { + } + }); + } record.mBGColor = contentView.getInitBackgroundColor(); } else { // release the icon view host @@ -613,6 +636,7 @@ public class StartingSurfaceDrawer { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW, "Removing splash screen window for task: %d", taskId); if (record.mContentView != null) { + record.clearSystemBarColor(); if (immediately || record.mSuggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) { removeWindowInner(record.mDecorView, false); @@ -670,6 +694,8 @@ public class StartingSurfaceDrawer { private @StartingWindowType int mSuggestType; private int mBGColor; private final long mCreateTime; + private int mSystemBarAppearance; + private boolean mDrawsSystemBarBackgrounds; StartingWindowRecord(IBinder appToken, View decorView, TaskSnapshotWindow taskSnapshotWindow, @StartingWindowType int suggestType) { @@ -690,5 +716,37 @@ public class StartingSurfaceDrawer { mContentView = splashScreenView; mSetSplashScreen = true; } + + private void parseAppSystemBarColor(Context context) { + final TypedArray a = context.obtainStyledAttributes(R.styleable.Window); + mDrawsSystemBarBackgrounds = a.getBoolean( + R.styleable.Window_windowDrawsSystemBarBackgrounds, false); + if (a.getBoolean(R.styleable.Window_windowLightStatusBar, false)) { + mSystemBarAppearance |= WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; + } + if (a.getBoolean(R.styleable.Window_windowLightNavigationBar, false)) { + mSystemBarAppearance |= WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS; + } + a.recycle(); + } + + // Reset the system bar color which set by splash screen, make it align to the app. + private void clearSystemBarColor() { + if (mDecorView == null) { + return; + } + if (mDecorView.getLayoutParams() instanceof WindowManager.LayoutParams) { + final WindowManager.LayoutParams lp = + (WindowManager.LayoutParams) mDecorView.getLayoutParams(); + if (mDrawsSystemBarBackgrounds) { + lp.flags |= WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; + } else { + lp.flags &= ~WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS; + } + mDecorView.setLayoutParams(lp); + } + mDecorView.getWindowInsetsController().setSystemBarsAppearance( + mSystemBarAppearance, LIGHT_BARS_MASK); + } } }