Merge "Allow app to receive onSplashscreenExit even for empty splash screen."

This commit is contained in:
Wei Sheng Shih
2022-01-26 01:33:58 +00:00
committed by Android (Google) Code Review
6 changed files with 73 additions and 15 deletions

View File

@@ -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());

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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)) {

View File

@@ -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()) {

View File

@@ -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;
}