Merge "Allow app to receive onSplashscreenExit even for empty splash screen."
This commit is contained in:
committed by
Android (Google) Code Review
commit
e8e313d496
@@ -151,6 +151,7 @@ public final class SplashScreenView extends FrameLayout {
|
||||
private Instant mIconAnimationStart;
|
||||
private Duration mIconAnimationDuration;
|
||||
private Consumer<Runnable> mUiThreadInitTask;
|
||||
private boolean mAllowHandleEmpty = true;
|
||||
|
||||
public Builder(@NonNull Context context) {
|
||||
mContext = context;
|
||||
@@ -257,6 +258,15 @@ public final class SplashScreenView extends FrameLayout {
|
||||
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.
|
||||
*/
|
||||
@@ -303,7 +313,7 @@ public final class SplashScreenView extends FrameLayout {
|
||||
}
|
||||
view.mIconView = imageView;
|
||||
}
|
||||
if (mOverlayDrawable != null || mIconDrawable == null) {
|
||||
if (mOverlayDrawable != null || (view.mIconView == null && !mAllowHandleEmpty)) {
|
||||
view.setNotCopyable();
|
||||
}
|
||||
|
||||
@@ -720,13 +730,15 @@ public final class SplashScreenView extends FrameLayout {
|
||||
private RemoteCallback mClientCallback;
|
||||
|
||||
public SplashScreenViewParcelable(SplashScreenView view) {
|
||||
mIconSize = view.mIconView.getWidth();
|
||||
final View iconView = view.getIconView();
|
||||
mIconSize = iconView != null ? iconView.getWidth() : 0;
|
||||
mBackgroundColor = view.getInitBackgroundColor();
|
||||
mIconBackground = copyDrawable(view.getIconView().getBackground());
|
||||
mIconBackground = iconView != null ? copyDrawable(iconView.getBackground()) : null;
|
||||
mSurfacePackage = view.mSurfacePackageCopy;
|
||||
if (mSurfacePackage == null) {
|
||||
// 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());
|
||||
|
||||
|
||||
@@ -116,6 +116,7 @@ public final class StartingWindowInfo implements Parcelable {
|
||||
TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT,
|
||||
TYPE_PARAMETER_ACTIVITY_CREATED,
|
||||
TYPE_PARAMETER_USE_EMPTY_SPLASH_SCREEN,
|
||||
TYPE_PARAMETER_ALLOW_HANDLE_EMPTY_SCREEN,
|
||||
TYPE_PARAMETER_LEGACY_SPLASH_SCREEN
|
||||
})
|
||||
public @interface StartingTypeParams {}
|
||||
@@ -140,6 +141,11 @@ public final class StartingWindowInfo implements Parcelable {
|
||||
* @hide
|
||||
*/
|
||||
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
|
||||
* @hide
|
||||
@@ -185,6 +191,13 @@ public final class StartingWindowInfo implements Parcelable {
|
||||
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
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
|
||||
@@ -54,6 +54,7 @@ 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;
|
||||
|
||||
import com.android.internal.R;
|
||||
@@ -138,8 +139,8 @@ public class SplashscreenContentDrawer {
|
||||
* executed on splash screen thread. Note that the view can be
|
||||
* null if failed.
|
||||
*/
|
||||
void createContentView(Context context, @StartingWindowType int suggestType, ActivityInfo info,
|
||||
int taskId, Consumer<SplashScreenView> splashScreenViewConsumer,
|
||||
void createContentView(Context context, @StartingWindowType int suggestType,
|
||||
StartingWindowInfo info, Consumer<SplashScreenView> splashScreenViewConsumer,
|
||||
Consumer<Runnable> uiThreadInitConsumer) {
|
||||
mSplashscreenWorkerHandler.post(() -> {
|
||||
SplashScreenView contentView;
|
||||
@@ -150,7 +151,7 @@ public class SplashscreenContentDrawer {
|
||||
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
|
||||
} catch (RuntimeException e) {
|
||||
Slog.w(TAG, "failed creating starting window content at taskId: "
|
||||
+ taskId, e);
|
||||
+ info.taskInfo.taskId, e);
|
||||
contentView = null;
|
||||
}
|
||||
splashScreenViewConsumer.accept(contentView);
|
||||
@@ -241,7 +242,7 @@ public class SplashscreenContentDrawer {
|
||||
return null;
|
||||
}
|
||||
|
||||
private SplashScreenView makeSplashScreenContentView(Context context, ActivityInfo ai,
|
||||
private SplashScreenView makeSplashScreenContentView(Context context, StartingWindowInfo info,
|
||||
@StartingWindowType int suggestType, Consumer<Runnable> uiThreadInitConsumer) {
|
||||
updateDensity();
|
||||
|
||||
@@ -250,6 +251,9 @@ public class SplashscreenContentDrawer {
|
||||
|
||||
final Drawable legacyDrawable = suggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN
|
||||
? peekLegacySplashscreenContent(context, mTmpAttrs) : null;
|
||||
final ActivityInfo ai = info.targetActivityInfo != null
|
||||
? info.targetActivityInfo
|
||||
: info.taskInfo.topActivityInfo;
|
||||
final int themeBGColor = legacyDrawable != null
|
||||
? getBGColorFromCache(ai, () -> estimateWindowBGColor(legacyDrawable))
|
||||
: getBGColorFromCache(ai, () -> peekWindowBGColor(context, mTmpAttrs));
|
||||
@@ -258,6 +262,7 @@ public class SplashscreenContentDrawer {
|
||||
.overlayDrawable(legacyDrawable)
|
||||
.chooseStyle(suggestType)
|
||||
.setUiThreadInitConsumer(uiThreadInitConsumer)
|
||||
.setAllowHandleEmpty(info.allowHandleEmptySplashScreen())
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -327,6 +332,7 @@ public class SplashscreenContentDrawer {
|
||||
private Drawable[] mFinalIconDrawables;
|
||||
private int mFinalIconSize = mIconSize;
|
||||
private Consumer<Runnable> mUiThreadInitTask;
|
||||
private boolean mAllowHandleEmpty;
|
||||
|
||||
StartingWindowViewBuilder(@NonNull Context context, @NonNull ActivityInfo aInfo) {
|
||||
mContext = context;
|
||||
@@ -353,6 +359,11 @@ public class SplashscreenContentDrawer {
|
||||
return this;
|
||||
}
|
||||
|
||||
StartingWindowViewBuilder setAllowHandleEmpty(boolean allowHandleEmpty) {
|
||||
mAllowHandleEmpty = allowHandleEmpty;
|
||||
return this;
|
||||
}
|
||||
|
||||
SplashScreenView build() {
|
||||
Drawable iconDrawable;
|
||||
final int animationDuration;
|
||||
@@ -491,7 +502,8 @@ public class SplashscreenContentDrawer {
|
||||
.setIconBackground(background)
|
||||
.setCenterViewDrawable(foreground)
|
||||
.setAnimationDurationMillis(animationDuration)
|
||||
.setUiThreadInitConsumer(uiThreadInitTask);
|
||||
.setUiThreadInitConsumer(uiThreadInitTask)
|
||||
.setAllowHandleEmpty(mAllowHandleEmpty);
|
||||
|
||||
if (mSuggestType == STARTING_WINDOW_TYPE_SPLASH_SCREEN
|
||||
&& mTmpAttrs.mBrandingImage != null) {
|
||||
|
||||
@@ -328,7 +328,7 @@ public class StartingSurfaceDrawer {
|
||||
if (mSysuiProxy != null) {
|
||||
mSysuiProxy.requestTopUi(true, TAG);
|
||||
}
|
||||
mSplashscreenContentDrawer.createContentView(context, suggestType, activityInfo, taskId,
|
||||
mSplashscreenContentDrawer.createContentView(context, suggestType, windowInfo,
|
||||
viewSupplier::setView, viewSupplier::setUiThreadInitTask);
|
||||
try {
|
||||
if (addWindow(taskId, appToken, rootLayout, display, params, suggestType)) {
|
||||
|
||||
@@ -395,9 +395,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
// 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 STARTING_WINDOW_TYPE_NONE = 0;
|
||||
private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
|
||||
private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
|
||||
static final int STARTING_WINDOW_TYPE_NONE = 0;
|
||||
static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
|
||||
static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
|
||||
|
||||
static final int INVALID_PID = -1;
|
||||
|
||||
@@ -2149,7 +2149,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
|
||||
final int typeParameter = StartingSurfaceController
|
||||
.makeStartingWindowTypeParameter(newTask, taskSwitch, processRunning,
|
||||
allowTaskSnapshot, activityCreated, useEmpty, useLegacy, activityAllDrawn);
|
||||
allowTaskSnapshot, activityCreated, useEmpty, useLegacy, activityAllDrawn,
|
||||
type, packageName, mUserId);
|
||||
|
||||
if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
|
||||
if (isActivityTypeHome()) {
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.server.wm;
|
||||
|
||||
import static android.window.StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED;
|
||||
import static android.window.StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_DRAWN;
|
||||
import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_HANDLE_EMPTY_SCREEN;
|
||||
import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT;
|
||||
import static android.window.StartingWindowInfo.TYPE_PARAMETER_LEGACY_SPLASH_SCREEN;
|
||||
import static android.window.StartingWindowInfo.TYPE_PARAMETER_NEW_TASK;
|
||||
@@ -25,12 +26,17 @@ import static android.window.StartingWindowInfo.TYPE_PARAMETER_PROCESS_RUNNING;
|
||||
import static android.window.StartingWindowInfo.TYPE_PARAMETER_TASK_SWITCH;
|
||||
import static android.window.StartingWindowInfo.TYPE_PARAMETER_USE_EMPTY_SPLASH_SCREEN;
|
||||
|
||||
import static com.android.server.wm.ActivityRecord.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
|
||||
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.compat.CompatChanges;
|
||||
import android.compat.annotation.ChangeId;
|
||||
import android.compat.annotation.EnabledSince;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Slog;
|
||||
import android.window.TaskSnapshot;
|
||||
|
||||
@@ -43,6 +49,14 @@ import java.util.function.Supplier;
|
||||
public class StartingSurfaceController {
|
||||
private static final String TAG = TAG_WITH_CLASS_NAME
|
||||
? StartingSurfaceController.class.getSimpleName() : TAG_WM;
|
||||
/**
|
||||
* Allow the empty style splash screen view can be copy and transfer to another process if
|
||||
* the app targeting to {@link android.os.Build.VERSION_CODES#TIRAMISU} or higher.
|
||||
*/
|
||||
@ChangeId
|
||||
@EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.TIRAMISU)
|
||||
private static final long ALLOW_COPY_EMPTY_VIEW = 205907456L;
|
||||
|
||||
private final WindowManagerService mService;
|
||||
private final SplashScreenExceptionList mSplashScreenExceptionsList;
|
||||
|
||||
@@ -81,7 +95,8 @@ public class StartingSurfaceController {
|
||||
|
||||
static int makeStartingWindowTypeParameter(boolean newTask, boolean taskSwitch,
|
||||
boolean processRunning, boolean allowTaskSnapshot, boolean activityCreated,
|
||||
boolean useEmpty, boolean useLegacy, boolean activityDrawn) {
|
||||
boolean useEmpty, boolean useLegacy, boolean activityDrawn, int startingWindowType,
|
||||
String packageName, int userId) {
|
||||
int parameter = 0;
|
||||
if (newTask) {
|
||||
parameter |= TYPE_PARAMETER_NEW_TASK;
|
||||
@@ -107,6 +122,11 @@ public class StartingSurfaceController {
|
||||
if (activityDrawn) {
|
||||
parameter |= TYPE_PARAMETER_ACTIVITY_DRAWN;
|
||||
}
|
||||
if (startingWindowType == STARTING_WINDOW_TYPE_SPLASH_SCREEN
|
||||
&& CompatChanges.isChangeEnabled(ALLOW_COPY_EMPTY_VIEW, packageName,
|
||||
UserHandle.of(userId))) {
|
||||
parameter |= TYPE_PARAMETER_ALLOW_HANDLE_EMPTY_SCREEN;
|
||||
}
|
||||
return parameter;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user