Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d9264587 authored by wilsonshih's avatar wilsonshih
Browse files

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
parent 94d1958d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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() {
+2 −71
Original line number Diff line number Diff line
@@ -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);
    }

    /**
+0 −17
Original line number Diff line number Diff line
@@ -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;
        }
+59 −1
Original line number Diff line number Diff line
@@ -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);
        }
    }
}