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

Commit 946a4063 authored by wilsonshih's avatar wilsonshih
Browse files

Allow app to receive onSplashscreenExit even for empty splash screen.

Allow developers to customize the exit animation for empty style splash
screen, there is a target sdk version check to prevents apps from
crash if the app didn't do null pointer check for #getIconView.

Bug: 205907456
Test: atest SplashscreenTests
Change-Id: I235f25fdf42b7177a6e195d3ffc07b92690e6f79
parent 85b897d6
Loading
Loading
Loading
Loading
+16 −4
Original line number Original line Diff line number Diff line
@@ -151,6 +151,7 @@ public final class SplashScreenView extends FrameLayout {
        private Instant mIconAnimationStart;
        private Instant mIconAnimationStart;
        private Duration mIconAnimationDuration;
        private Duration mIconAnimationDuration;
        private Consumer<Runnable> mUiThreadInitTask;
        private Consumer<Runnable> mUiThreadInitTask;
        private boolean mAllowHandleEmpty = true;


        public Builder(@NonNull Context context) {
        public Builder(@NonNull Context context) {
            mContext = context;
            mContext = context;
@@ -257,6 +258,15 @@ public final class SplashScreenView extends FrameLayout {
            return this;
            return this;
        }
        }


        /**
         * Sets whether this view can be copied and transferred to the client if the view is
         * empty style splash screen.
         */
        public Builder setAllowHandleEmpty(boolean allowHandleEmpty) {
            mAllowHandleEmpty = allowHandleEmpty;
            return this;
        }

        /**
        /**
         * Create SplashScreenWindowView object from materials.
         * Create SplashScreenWindowView object from materials.
         */
         */
@@ -303,7 +313,7 @@ public final class SplashScreenView extends FrameLayout {
                }
                }
                view.mIconView = imageView;
                view.mIconView = imageView;
            }
            }
            if (mOverlayDrawable != null || mIconDrawable == null) {
            if (mOverlayDrawable != null || (view.mIconView == null && !mAllowHandleEmpty)) {
                view.setNotCopyable();
                view.setNotCopyable();
            }
            }


@@ -720,13 +730,15 @@ public final class SplashScreenView extends FrameLayout {
        private RemoteCallback mClientCallback;
        private RemoteCallback mClientCallback;


        public SplashScreenViewParcelable(SplashScreenView view) {
        public SplashScreenViewParcelable(SplashScreenView view) {
            mIconSize = view.mIconView.getWidth();
            final View iconView = view.getIconView();
            mIconSize = iconView != null ? iconView.getWidth() : 0;
            mBackgroundColor = view.getInitBackgroundColor();
            mBackgroundColor = view.getInitBackgroundColor();
            mIconBackground = copyDrawable(view.getIconView().getBackground());
            mIconBackground = iconView != null ? copyDrawable(iconView.getBackground()) : null;
            mSurfacePackage = view.mSurfacePackageCopy;
            mSurfacePackage = view.mSurfacePackageCopy;
            if (mSurfacePackage == null) {
            if (mSurfacePackage == null) {
                // We only need to copy the drawable if we are not using a SurfaceView
                // We only need to copy the drawable if we are not using a SurfaceView
                mIconBitmap = copyDrawable(((ImageView) view.getIconView()).getDrawable());
                mIconBitmap = iconView != null
                        ? copyDrawable(((ImageView) view.getIconView()).getDrawable()) : null;
            }
            }
            mBrandingBitmap = copyDrawable(view.getBrandingView().getBackground());
            mBrandingBitmap = copyDrawable(view.getBrandingView().getBackground());


+13 −0
Original line number Original line Diff line number Diff line
@@ -116,6 +116,7 @@ public final class StartingWindowInfo implements Parcelable {
            TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT,
            TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT,
            TYPE_PARAMETER_ACTIVITY_CREATED,
            TYPE_PARAMETER_ACTIVITY_CREATED,
            TYPE_PARAMETER_USE_EMPTY_SPLASH_SCREEN,
            TYPE_PARAMETER_USE_EMPTY_SPLASH_SCREEN,
            TYPE_PARAMETER_ALLOW_HANDLE_EMPTY_SCREEN,
            TYPE_PARAMETER_LEGACY_SPLASH_SCREEN
            TYPE_PARAMETER_LEGACY_SPLASH_SCREEN
    })
    })
    public @interface StartingTypeParams {}
    public @interface StartingTypeParams {}
@@ -140,6 +141,11 @@ public final class StartingWindowInfo implements Parcelable {
     * @hide
     * @hide
     */
     */
    public static final int TYPE_PARAMETER_ACTIVITY_DRAWN = 0x00000040;
    public static final int TYPE_PARAMETER_ACTIVITY_DRAWN = 0x00000040;
    /**
     * Application is allowed to handle empty splash screen.
     * @hide
     */
    public static final int TYPE_PARAMETER_ALLOW_HANDLE_EMPTY_SCREEN = 0x00000080;
    /**
    /**
     * Application is allowed to use the legacy splash screen
     * Application is allowed to use the legacy splash screen
     * @hide
     * @hide
@@ -185,6 +191,13 @@ public final class StartingWindowInfo implements Parcelable {
        readFromParcel(source);
        readFromParcel(source);
    }
    }


    /**
     * Return whether the application allow to handle the empty style splash screen.
     */
    public boolean allowHandleEmptySplashScreen() {
        return (startingWindowTypeParameter & TYPE_PARAMETER_ALLOW_HANDLE_EMPTY_SCREEN) != 0;
    }

    @Override
    @Override
    public int describeContents() {
    public int describeContents() {
        return 0;
        return 0;
+17 −5
Original line number Original line Diff line number Diff line
@@ -54,6 +54,7 @@ import android.view.ContextThemeWrapper;
import android.view.SurfaceControl;
import android.view.SurfaceControl;
import android.view.View;
import android.view.View;
import android.window.SplashScreenView;
import android.window.SplashScreenView;
import android.window.StartingWindowInfo;
import android.window.StartingWindowInfo.StartingWindowType;
import android.window.StartingWindowInfo.StartingWindowType;


import com.android.internal.R;
import com.android.internal.R;
@@ -138,8 +139,8 @@ public class SplashscreenContentDrawer {
     *                                 executed on splash screen thread. Note that the view can be
     *                                 executed on splash screen thread. Note that the view can be
     *                                 null if failed.
     *                                 null if failed.
     */
     */
    void createContentView(Context context, @StartingWindowType int suggestType, ActivityInfo info,
    void createContentView(Context context, @StartingWindowType int suggestType,
            int taskId, Consumer<SplashScreenView> splashScreenViewConsumer,
            StartingWindowInfo info, Consumer<SplashScreenView> splashScreenViewConsumer,
            Consumer<Runnable> uiThreadInitConsumer) {
            Consumer<Runnable> uiThreadInitConsumer) {
        mSplashscreenWorkerHandler.post(() -> {
        mSplashscreenWorkerHandler.post(() -> {
            SplashScreenView contentView;
            SplashScreenView contentView;
@@ -150,7 +151,7 @@ public class SplashscreenContentDrawer {
                Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
                Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
            } catch (RuntimeException e) {
            } catch (RuntimeException e) {
                Slog.w(TAG, "failed creating starting window content at taskId: "
                Slog.w(TAG, "failed creating starting window content at taskId: "
                        + taskId, e);
                        + info.taskInfo.taskId, e);
                contentView = null;
                contentView = null;
            }
            }
            splashScreenViewConsumer.accept(contentView);
            splashScreenViewConsumer.accept(contentView);
@@ -241,7 +242,7 @@ public class SplashscreenContentDrawer {
        return null;
        return null;
    }
    }


    private SplashScreenView makeSplashScreenContentView(Context context, ActivityInfo ai,
    private SplashScreenView makeSplashScreenContentView(Context context, StartingWindowInfo info,
            @StartingWindowType int suggestType, Consumer<Runnable> uiThreadInitConsumer) {
            @StartingWindowType int suggestType, Consumer<Runnable> uiThreadInitConsumer) {
        updateDensity();
        updateDensity();


@@ -250,6 +251,9 @@ public class SplashscreenContentDrawer {


        final Drawable legacyDrawable = suggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN
        final Drawable legacyDrawable = suggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN
                ? peekLegacySplashscreenContent(context, mTmpAttrs) : null;
                ? peekLegacySplashscreenContent(context, mTmpAttrs) : null;
        final ActivityInfo ai = info.targetActivityInfo != null
                ? info.targetActivityInfo
                : info.taskInfo.topActivityInfo;
        final int themeBGColor = legacyDrawable != null
        final int themeBGColor = legacyDrawable != null
                ? getBGColorFromCache(ai, () -> estimateWindowBGColor(legacyDrawable))
                ? getBGColorFromCache(ai, () -> estimateWindowBGColor(legacyDrawable))
                : getBGColorFromCache(ai, () -> peekWindowBGColor(context, mTmpAttrs));
                : getBGColorFromCache(ai, () -> peekWindowBGColor(context, mTmpAttrs));
@@ -258,6 +262,7 @@ public class SplashscreenContentDrawer {
                .overlayDrawable(legacyDrawable)
                .overlayDrawable(legacyDrawable)
                .chooseStyle(suggestType)
                .chooseStyle(suggestType)
                .setUiThreadInitConsumer(uiThreadInitConsumer)
                .setUiThreadInitConsumer(uiThreadInitConsumer)
                .setAllowHandleEmpty(info.allowHandleEmptySplashScreen())
                .build();
                .build();
    }
    }


@@ -327,6 +332,7 @@ public class SplashscreenContentDrawer {
        private Drawable[] mFinalIconDrawables;
        private Drawable[] mFinalIconDrawables;
        private int mFinalIconSize = mIconSize;
        private int mFinalIconSize = mIconSize;
        private Consumer<Runnable> mUiThreadInitTask;
        private Consumer<Runnable> mUiThreadInitTask;
        private boolean mAllowHandleEmpty;


        StartingWindowViewBuilder(@NonNull Context context, @NonNull ActivityInfo aInfo) {
        StartingWindowViewBuilder(@NonNull Context context, @NonNull ActivityInfo aInfo) {
            mContext = context;
            mContext = context;
@@ -353,6 +359,11 @@ public class SplashscreenContentDrawer {
            return this;
            return this;
        }
        }


        StartingWindowViewBuilder setAllowHandleEmpty(boolean allowHandleEmpty) {
            mAllowHandleEmpty = allowHandleEmpty;
            return this;
        }

        SplashScreenView build() {
        SplashScreenView build() {
            Drawable iconDrawable;
            Drawable iconDrawable;
            final int animationDuration;
            final int animationDuration;
@@ -491,7 +502,8 @@ public class SplashscreenContentDrawer {
                    .setIconBackground(background)
                    .setIconBackground(background)
                    .setCenterViewDrawable(foreground)
                    .setCenterViewDrawable(foreground)
                    .setAnimationDurationMillis(animationDuration)
                    .setAnimationDurationMillis(animationDuration)
                    .setUiThreadInitConsumer(uiThreadInitTask);
                    .setUiThreadInitConsumer(uiThreadInitTask)
                    .setAllowHandleEmpty(mAllowHandleEmpty);


            if (mSuggestType == STARTING_WINDOW_TYPE_SPLASH_SCREEN
            if (mSuggestType == STARTING_WINDOW_TYPE_SPLASH_SCREEN
                    && mTmpAttrs.mBrandingImage != null) {
                    && mTmpAttrs.mBrandingImage != null) {
+1 −1
Original line number Original line Diff line number Diff line
@@ -328,7 +328,7 @@ public class StartingSurfaceDrawer {
        if (mSysuiProxy != null) {
        if (mSysuiProxy != null) {
            mSysuiProxy.requestTopUi(true, TAG);
            mSysuiProxy.requestTopUi(true, TAG);
        }
        }
        mSplashscreenContentDrawer.createContentView(context, suggestType, activityInfo, taskId,
        mSplashscreenContentDrawer.createContentView(context, suggestType, windowInfo,
                viewSupplier::setView, viewSupplier::setUiThreadInitTask);
                viewSupplier::setView, viewSupplier::setUiThreadInitTask);
        try {
        try {
            if (addWindow(taskId, appToken, rootLayout, display, params, suggestType)) {
            if (addWindow(taskId, appToken, rootLayout, display, params, suggestType)) {
+5 −4
Original line number Original line Diff line number Diff line
@@ -394,9 +394,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
    // How many activities have to be scheduled to stop to force a stop pass.
    // How many activities have to be scheduled to stop to force a stop pass.
    private static final int MAX_STOPPING_TO_FORCE = 3;
    private static final int MAX_STOPPING_TO_FORCE = 3;


    private static final int STARTING_WINDOW_TYPE_NONE = 0;
    static final int STARTING_WINDOW_TYPE_NONE = 0;
    private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
    static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
    private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
    static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;


    static final int INVALID_PID = -1;
    static final int INVALID_PID = -1;


@@ -2148,7 +2148,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A


        final int typeParameter = StartingSurfaceController
        final int typeParameter = StartingSurfaceController
                .makeStartingWindowTypeParameter(newTask, taskSwitch, processRunning,
                .makeStartingWindowTypeParameter(newTask, taskSwitch, processRunning,
                        allowTaskSnapshot, activityCreated, useEmpty, useLegacy, activityAllDrawn);
                        allowTaskSnapshot, activityCreated, useEmpty, useLegacy, activityAllDrawn,
                        type, packageName, mUserId);


        if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
        if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
            if (isActivityTypeHome()) {
            if (isActivityTypeHome()) {
Loading