Merge "Implement the legacy splash screen behavior" into sc-dev
This commit is contained in:
@@ -133,6 +133,8 @@ public final class SplashScreenView extends FrameLayout {
|
|||||||
private @ColorInt int mIconBackground;
|
private @ColorInt int mIconBackground;
|
||||||
private Bitmap mParceledIconBitmap;
|
private Bitmap mParceledIconBitmap;
|
||||||
private Drawable mIconDrawable;
|
private Drawable mIconDrawable;
|
||||||
|
// It is only set for legacy splash screen which won't be sent across processes.
|
||||||
|
private Drawable mOverlayDrawable;
|
||||||
private SurfaceControlViewHost.SurfacePackage mSurfacePackage;
|
private SurfaceControlViewHost.SurfacePackage mSurfacePackage;
|
||||||
private RemoteCallback mClientCallback;
|
private RemoteCallback mClientCallback;
|
||||||
private int mBrandingImageWidth;
|
private int mBrandingImageWidth;
|
||||||
@@ -192,6 +194,14 @@ public final class SplashScreenView extends FrameLayout {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the Drawable object to fill entire view
|
||||||
|
*/
|
||||||
|
public Builder setOverlayDrawable(@Nullable Drawable drawable) {
|
||||||
|
mOverlayDrawable = drawable;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the Drawable object to fill the center view.
|
* Set the Drawable object to fill the center view.
|
||||||
*/
|
*/
|
||||||
@@ -236,7 +246,11 @@ public final class SplashScreenView extends FrameLayout {
|
|||||||
layoutInflater.inflate(R.layout.splash_screen_view, null, false);
|
layoutInflater.inflate(R.layout.splash_screen_view, null, false);
|
||||||
view.mInitBackgroundColor = mBackgroundColor;
|
view.mInitBackgroundColor = mBackgroundColor;
|
||||||
view.mInitIconBackgroundColor = mIconBackground;
|
view.mInitIconBackgroundColor = mIconBackground;
|
||||||
view.setBackgroundColor(mBackgroundColor);
|
if (mOverlayDrawable != null) {
|
||||||
|
view.setBackground(mOverlayDrawable);
|
||||||
|
} else {
|
||||||
|
view.setBackgroundColor(mBackgroundColor);
|
||||||
|
}
|
||||||
view.mClientCallback = mClientCallback;
|
view.mClientCallback = mClientCallback;
|
||||||
|
|
||||||
view.mBrandingImageView = view.findViewById(R.id.splashscreen_branding_view);
|
view.mBrandingImageView = view.findViewById(R.id.splashscreen_branding_view);
|
||||||
@@ -261,6 +275,9 @@ public final class SplashScreenView extends FrameLayout {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (mOverlayDrawable != null || mIconDrawable == null) {
|
||||||
|
view.setNotCopyable();
|
||||||
|
}
|
||||||
|
|
||||||
if (mParceledIconBitmap != null) {
|
if (mParceledIconBitmap != null) {
|
||||||
view.mParceledIconBitmap = mParceledIconBitmap;
|
view.mParceledIconBitmap = mParceledIconBitmap;
|
||||||
|
|||||||
@@ -55,6 +55,9 @@ public final class StartingWindowInfo implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
public static final int STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN = 3;
|
public static final int STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN = 3;
|
||||||
|
|
||||||
|
/** @hide **/
|
||||||
|
public static final int STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN = 4;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
@@ -62,7 +65,8 @@ public final class StartingWindowInfo implements Parcelable {
|
|||||||
STARTING_WINDOW_TYPE_NONE,
|
STARTING_WINDOW_TYPE_NONE,
|
||||||
STARTING_WINDOW_TYPE_SPLASH_SCREEN,
|
STARTING_WINDOW_TYPE_SPLASH_SCREEN,
|
||||||
STARTING_WINDOW_TYPE_SNAPSHOT,
|
STARTING_WINDOW_TYPE_SNAPSHOT,
|
||||||
STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN
|
STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN,
|
||||||
|
STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN
|
||||||
})
|
})
|
||||||
public @interface StartingWindowType {}
|
public @interface StartingWindowType {}
|
||||||
|
|
||||||
@@ -103,7 +107,8 @@ public final class StartingWindowInfo implements Parcelable {
|
|||||||
TYPE_PARAMETER_PROCESS_RUNNING,
|
TYPE_PARAMETER_PROCESS_RUNNING,
|
||||||
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_LEGACY_SPLASH_SCREEN
|
||||||
})
|
})
|
||||||
public @interface StartingTypeParams {}
|
public @interface StartingTypeParams {}
|
||||||
|
|
||||||
@@ -122,6 +127,11 @@ public final class StartingWindowInfo implements Parcelable {
|
|||||||
public static final int TYPE_PARAMETER_ACTIVITY_CREATED = 0x00000010;
|
public static final int TYPE_PARAMETER_ACTIVITY_CREATED = 0x00000010;
|
||||||
/** @hide */
|
/** @hide */
|
||||||
public static final int TYPE_PARAMETER_USE_EMPTY_SPLASH_SCREEN = 0x00000020;
|
public static final int TYPE_PARAMETER_USE_EMPTY_SPLASH_SCREEN = 0x00000020;
|
||||||
|
/**
|
||||||
|
* Application is allowed to use the legacy splash screen
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final int TYPE_PARAMETER_LEGACY_SPLASH_SCREEN = 0x80000000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The parameters which effect the starting window type.
|
* The parameters which effect the starting window type.
|
||||||
|
|||||||
@@ -18,6 +18,9 @@ package com.android.wm.shell.startingsurface;
|
|||||||
|
|
||||||
import static android.os.Process.THREAD_PRIORITY_TOP_APP_BOOST;
|
import static android.os.Process.THREAD_PRIORITY_TOP_APP_BOOST;
|
||||||
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
|
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
|
||||||
|
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN;
|
||||||
|
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN;
|
||||||
|
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
|
||||||
|
|
||||||
import android.annotation.ColorInt;
|
import android.annotation.ColorInt;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
@@ -47,6 +50,7 @@ import android.util.Slog;
|
|||||||
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.StartingWindowType;
|
||||||
|
|
||||||
import com.android.internal.R;
|
import com.android.internal.R;
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
@@ -122,17 +126,17 @@ public class SplashscreenContentDrawer {
|
|||||||
* view on background thread so the view and the drawable can be create and pre-draw in
|
* view on background thread so the view and the drawable can be create and pre-draw in
|
||||||
* parallel.
|
* parallel.
|
||||||
*
|
*
|
||||||
* @param emptyView Create a splash screen view without icon on it.
|
* @param suggestType Suggest type to create the splash screen view.
|
||||||
* @param consumer Receiving the SplashScreenView object, which will also be executed
|
* @param consumer Receiving the SplashScreenView object, which will also be executed
|
||||||
* on splash screen thread. Note that the view can be null if failed.
|
* on splash screen thread. Note that the view can be null if failed.
|
||||||
*/
|
*/
|
||||||
void createContentView(Context context, boolean emptyView, ActivityInfo info, int taskId,
|
void createContentView(Context context, @StartingWindowType int suggestType, ActivityInfo info,
|
||||||
Consumer<SplashScreenView> consumer) {
|
int taskId, Consumer<SplashScreenView> consumer) {
|
||||||
mSplashscreenWorkerHandler.post(() -> {
|
mSplashscreenWorkerHandler.post(() -> {
|
||||||
SplashScreenView contentView;
|
SplashScreenView contentView;
|
||||||
try {
|
try {
|
||||||
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "makeSplashScreenContentView");
|
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "makeSplashScreenContentView");
|
||||||
contentView = makeSplashScreenContentView(context, info, emptyView);
|
contentView = makeSplashScreenContentView(context, info, suggestType);
|
||||||
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: "
|
||||||
@@ -199,22 +203,45 @@ public class SplashscreenContentDrawer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Drawable peekLegacySplashscreenContent(Context context,
|
||||||
|
SplashScreenWindowAttrs attrs) {
|
||||||
|
final TypedArray a = context.obtainStyledAttributes(R.styleable.Window);
|
||||||
|
final int resId = safeReturnAttrDefault((def) ->
|
||||||
|
a.getResourceId(R.styleable.Window_windowSplashscreenContent, def), 0);
|
||||||
|
a.recycle();
|
||||||
|
if (resId != 0) {
|
||||||
|
return context.getDrawable(resId);
|
||||||
|
}
|
||||||
|
if (attrs.mWindowBgResId != 0) {
|
||||||
|
return context.getDrawable(attrs.mWindowBgResId);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private SplashScreenView makeSplashScreenContentView(Context context, ActivityInfo ai,
|
private SplashScreenView makeSplashScreenContentView(Context context, ActivityInfo ai,
|
||||||
boolean emptyView) {
|
@StartingWindowType int suggestType) {
|
||||||
updateDensity();
|
updateDensity();
|
||||||
|
|
||||||
getWindowAttrs(context, mTmpAttrs);
|
getWindowAttrs(context, mTmpAttrs);
|
||||||
mLastPackageContextConfigHash = context.getResources().getConfiguration().hashCode();
|
mLastPackageContextConfigHash = context.getResources().getConfiguration().hashCode();
|
||||||
final int themeBGColor = mColorCache.getWindowColor(ai.packageName,
|
|
||||||
mLastPackageContextConfigHash, mTmpAttrs.mWindowBgColor, mTmpAttrs.mWindowBgResId,
|
final Drawable legacyDrawable = suggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN
|
||||||
() -> peekWindowBGColor(context, mTmpAttrs)).mBgColor;
|
? peekLegacySplashscreenContent(context, mTmpAttrs) : null;
|
||||||
// TODO (b/173975965) Tracking the performance on improved splash screen.
|
final int themeBGColor = legacyDrawable != null
|
||||||
|
? getBGColorFromCache(ai, () -> estimateWindowBGColor(legacyDrawable))
|
||||||
|
: getBGColorFromCache(ai, () -> peekWindowBGColor(context, mTmpAttrs));
|
||||||
return new StartingWindowViewBuilder(context, ai)
|
return new StartingWindowViewBuilder(context, ai)
|
||||||
.setWindowBGColor(themeBGColor)
|
.setWindowBGColor(themeBGColor)
|
||||||
.makeEmptyView(emptyView)
|
.overlayDrawable(legacyDrawable)
|
||||||
|
.chooseStyle(suggestType)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getBGColorFromCache(ActivityInfo ai, IntSupplier windowBgColorSupplier) {
|
||||||
|
return mColorCache.getWindowColor(ai.packageName, mLastPackageContextConfigHash,
|
||||||
|
mTmpAttrs.mWindowBgColor, mTmpAttrs.mWindowBgResId, windowBgColorSupplier).mBgColor;
|
||||||
|
}
|
||||||
|
|
||||||
private static <T> T safeReturnAttrDefault(UnaryOperator<T> getMethod, T def) {
|
private static <T> T safeReturnAttrDefault(UnaryOperator<T> getMethod, T def) {
|
||||||
try {
|
try {
|
||||||
return getMethod.apply(def);
|
return getMethod.apply(def);
|
||||||
@@ -267,7 +294,8 @@ public class SplashscreenContentDrawer {
|
|||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final ActivityInfo mActivityInfo;
|
private final ActivityInfo mActivityInfo;
|
||||||
|
|
||||||
private boolean mEmptyView;
|
private Drawable mOverlayDrawable;
|
||||||
|
private int mSuggestType;
|
||||||
private int mThemeColor;
|
private int mThemeColor;
|
||||||
private Drawable mFinalIconDrawable;
|
private Drawable mFinalIconDrawable;
|
||||||
private int mFinalIconSize = mIconSize;
|
private int mFinalIconSize = mIconSize;
|
||||||
@@ -282,16 +310,22 @@ public class SplashscreenContentDrawer {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
StartingWindowViewBuilder makeEmptyView(boolean empty) {
|
StartingWindowViewBuilder overlayDrawable(Drawable overlay) {
|
||||||
mEmptyView = empty;
|
mOverlayDrawable = overlay;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
StartingWindowViewBuilder chooseStyle(int suggestType) {
|
||||||
|
mSuggestType = suggestType;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
SplashScreenView build() {
|
SplashScreenView build() {
|
||||||
Drawable iconDrawable;
|
Drawable iconDrawable;
|
||||||
final int animationDuration;
|
final int animationDuration;
|
||||||
if (mEmptyView) {
|
if (mSuggestType == STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN
|
||||||
// empty splash screen case
|
|| mSuggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) {
|
||||||
|
// empty or legacy splash screen case
|
||||||
animationDuration = 0;
|
animationDuration = 0;
|
||||||
mFinalIconSize = 0;
|
mFinalIconSize = 0;
|
||||||
} else if (mTmpAttrs.mSplashScreenIcon != null) {
|
} else if (mTmpAttrs.mSplashScreenIcon != null) {
|
||||||
@@ -403,13 +437,15 @@ public class SplashscreenContentDrawer {
|
|||||||
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "fillViewWithIcon");
|
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "fillViewWithIcon");
|
||||||
final SplashScreenView.Builder builder = new SplashScreenView.Builder(mContext);
|
final SplashScreenView.Builder builder = new SplashScreenView.Builder(mContext);
|
||||||
builder.setBackgroundColor(mThemeColor);
|
builder.setBackgroundColor(mThemeColor);
|
||||||
|
builder.setOverlayDrawable(mOverlayDrawable);
|
||||||
if (iconDrawable != null) {
|
if (iconDrawable != null) {
|
||||||
builder.setIconSize(iconSize)
|
builder.setIconSize(iconSize)
|
||||||
.setIconBackground(mTmpAttrs.mIconBgColor)
|
.setIconBackground(mTmpAttrs.mIconBgColor)
|
||||||
.setCenterViewDrawable(iconDrawable)
|
.setCenterViewDrawable(iconDrawable)
|
||||||
.setAnimationDurationMillis(animationDuration);
|
.setAnimationDurationMillis(animationDuration);
|
||||||
}
|
}
|
||||||
if (mTmpAttrs.mBrandingImage != null) {
|
if (mSuggestType == STARTING_WINDOW_TYPE_SPLASH_SCREEN
|
||||||
|
&& mTmpAttrs.mBrandingImage != null) {
|
||||||
builder.setBrandingDrawable(mTmpAttrs.mBrandingImage, mBrandingImageWidth,
|
builder.setBrandingDrawable(mTmpAttrs.mBrandingImage, mBrandingImageWidth,
|
||||||
mBrandingImageHeight);
|
mBrandingImageHeight);
|
||||||
}
|
}
|
||||||
@@ -417,20 +453,22 @@ public class SplashscreenContentDrawer {
|
|||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Slog.d(TAG, "fillViewWithIcon surfaceWindowView " + splashScreenView);
|
Slog.d(TAG, "fillViewWithIcon surfaceWindowView " + splashScreenView);
|
||||||
}
|
}
|
||||||
if (mEmptyView) {
|
if (mSuggestType != STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) {
|
||||||
splashScreenView.setNotCopyable();
|
splashScreenView.addOnAttachStateChangeListener(
|
||||||
}
|
new View.OnAttachStateChangeListener() {
|
||||||
splashScreenView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
|
@Override
|
||||||
@Override
|
public void onViewAttachedToWindow(View v) {
|
||||||
public void onViewAttachedToWindow(View v) {
|
SplashScreenView.applySystemBarsContrastColor(
|
||||||
SplashScreenView.applySystemBarsContrastColor(v.getWindowInsetsController(),
|
v.getWindowInsetsController(),
|
||||||
splashScreenView.getInitBackgroundColor());
|
splashScreenView.getInitBackgroundColor());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onViewDetachedFromWindow(View v) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onViewDetachedFromWindow(View v) {
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
|
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
|
||||||
return splashScreenView;
|
return splashScreenView;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ import static android.content.Context.CONTEXT_RESTRICTED;
|
|||||||
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
|
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
|
||||||
import static android.view.Choreographer.CALLBACK_INSETS_ANIMATION;
|
import static android.view.Choreographer.CALLBACK_INSETS_ANIMATION;
|
||||||
import static android.view.Display.DEFAULT_DISPLAY;
|
import static android.view.Display.DEFAULT_DISPLAY;
|
||||||
|
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN;
|
||||||
|
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SNAPSHOT;
|
||||||
|
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.app.ActivityManager.RunningTaskInfo;
|
import android.app.ActivityManager.RunningTaskInfo;
|
||||||
@@ -32,7 +34,6 @@ import android.content.res.Resources;
|
|||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
import android.graphics.PixelFormat;
|
import android.graphics.PixelFormat;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.drawable.ColorDrawable;
|
|
||||||
import android.hardware.display.DisplayManager;
|
import android.hardware.display.DisplayManager;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.RemoteCallback;
|
import android.os.RemoteCallback;
|
||||||
@@ -50,6 +51,7 @@ import android.widget.FrameLayout;
|
|||||||
import android.window.SplashScreenView;
|
import android.window.SplashScreenView;
|
||||||
import android.window.SplashScreenView.SplashScreenViewParcelable;
|
import android.window.SplashScreenView.SplashScreenViewParcelable;
|
||||||
import android.window.StartingWindowInfo;
|
import android.window.StartingWindowInfo;
|
||||||
|
import android.window.StartingWindowInfo.StartingWindowType;
|
||||||
import android.window.TaskSnapshot;
|
import android.window.TaskSnapshot;
|
||||||
|
|
||||||
import com.android.internal.R;
|
import com.android.internal.R;
|
||||||
@@ -149,10 +151,11 @@ public class StartingSurfaceDrawer {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a task need a splash screen starting window.
|
* Called when a task need a splash screen starting window.
|
||||||
* @param emptyView Whether drawing an empty frame without anything on it.
|
*
|
||||||
|
* @param suggestType The suggestion type to draw the splash screen.
|
||||||
*/
|
*/
|
||||||
void addSplashScreenStartingWindow(StartingWindowInfo windowInfo, IBinder appToken,
|
void addSplashScreenStartingWindow(StartingWindowInfo windowInfo, IBinder appToken,
|
||||||
boolean emptyView) {
|
@StartingWindowType int suggestType) {
|
||||||
final RunningTaskInfo taskInfo = windowInfo.taskInfo;
|
final RunningTaskInfo taskInfo = windowInfo.taskInfo;
|
||||||
final ActivityInfo activityInfo = taskInfo.topActivityInfo;
|
final ActivityInfo activityInfo = taskInfo.topActivityInfo;
|
||||||
if (activityInfo == null) {
|
if (activityInfo == null) {
|
||||||
@@ -173,7 +176,8 @@ public class StartingSurfaceDrawer {
|
|||||||
: com.android.internal.R.style.Theme_DeviceDefault_DayNight;
|
: com.android.internal.R.style.Theme_DeviceDefault_DayNight;
|
||||||
if (DEBUG_SPLASH_SCREEN) {
|
if (DEBUG_SPLASH_SCREEN) {
|
||||||
Slog.d(TAG, "addSplashScreen " + activityInfo.packageName
|
Slog.d(TAG, "addSplashScreen " + activityInfo.packageName
|
||||||
+ " theme=" + Integer.toHexString(theme) + " task= " + taskInfo.taskId);
|
+ " theme=" + Integer.toHexString(theme) + " task=" + taskInfo.taskId
|
||||||
|
+ " suggestType=" + suggestType);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtain proper context to launch on the right display.
|
// Obtain proper context to launch on the right display.
|
||||||
@@ -231,13 +235,19 @@ public class StartingSurfaceDrawer {
|
|||||||
params.setFitInsetsTypes(0);
|
params.setFitInsetsTypes(0);
|
||||||
params.format = PixelFormat.TRANSLUCENT;
|
params.format = PixelFormat.TRANSLUCENT;
|
||||||
int windowFlags = WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
|
int windowFlags = WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
|
||||||
| WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
|
|
||||||
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
|
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
|
||||||
| WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
|
| WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
|
||||||
final TypedArray a = context.obtainStyledAttributes(R.styleable.Window);
|
final TypedArray a = context.obtainStyledAttributes(R.styleable.Window);
|
||||||
if (a.getBoolean(R.styleable.Window_windowShowWallpaper, false)) {
|
if (a.getBoolean(R.styleable.Window_windowShowWallpaper, false)) {
|
||||||
windowFlags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
|
windowFlags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
|
||||||
}
|
}
|
||||||
|
if (suggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) {
|
||||||
|
if (a.getBoolean(R.styleable.Window_windowDrawsSystemBarBackgrounds, false)) {
|
||||||
|
windowFlags |= WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
windowFlags |= WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
|
||||||
|
}
|
||||||
params.layoutInDisplayCutoutMode = a.getInt(
|
params.layoutInDisplayCutoutMode = a.getInt(
|
||||||
R.styleable.Window_windowLayoutInDisplayCutoutMode,
|
R.styleable.Window_windowLayoutInDisplayCutoutMode,
|
||||||
params.layoutInDisplayCutoutMode);
|
params.layoutInDisplayCutoutMode);
|
||||||
@@ -311,12 +321,12 @@ public class StartingSurfaceDrawer {
|
|||||||
}
|
}
|
||||||
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
|
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
|
||||||
};
|
};
|
||||||
mSplashscreenContentDrawer.createContentView(context, emptyView, activityInfo, taskId,
|
mSplashscreenContentDrawer.createContentView(context, suggestType, activityInfo, taskId,
|
||||||
viewSupplier::setView);
|
viewSupplier::setView);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final WindowManager wm = context.getSystemService(WindowManager.class);
|
final WindowManager wm = context.getSystemService(WindowManager.class);
|
||||||
if (addWindow(taskId, appToken, rootLayout, wm, params)) {
|
if (addWindow(taskId, appToken, rootLayout, wm, params, suggestType)) {
|
||||||
// We use the splash screen worker thread to create SplashScreenView while adding
|
// We use the splash screen worker thread to create SplashScreenView while adding
|
||||||
// the window, as otherwise Choreographer#doFrame might be delayed on this thread.
|
// the window, as otherwise Choreographer#doFrame might be delayed on this thread.
|
||||||
// And since Choreographer#doFrame won't happen immediately after adding the window,
|
// And since Choreographer#doFrame won't happen immediately after adding the window,
|
||||||
@@ -336,8 +346,10 @@ public class StartingSurfaceDrawer {
|
|||||||
|
|
||||||
int getStartingWindowBackgroundColorForTask(int taskId) {
|
int getStartingWindowBackgroundColorForTask(int taskId) {
|
||||||
StartingWindowRecord startingWindowRecord = mStartingWindowRecords.get(taskId);
|
StartingWindowRecord startingWindowRecord = mStartingWindowRecords.get(taskId);
|
||||||
if (startingWindowRecord == null || startingWindowRecord.mContentView == null) return 0;
|
if (startingWindowRecord == null || startingWindowRecord.mContentView == null) {
|
||||||
return ((ColorDrawable) startingWindowRecord.mContentView.getBackground()).getColor();
|
return 0;
|
||||||
|
}
|
||||||
|
return startingWindowRecord.mContentView.getInitBackgroundColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class SplashScreenViewSupplier implements Supplier<SplashScreenView> {
|
private static class SplashScreenViewSupplier implements Supplier<SplashScreenView> {
|
||||||
@@ -379,7 +391,7 @@ public class StartingSurfaceDrawer {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final StartingWindowRecord tView = new StartingWindowRecord(appToken,
|
final StartingWindowRecord tView = new StartingWindowRecord(appToken,
|
||||||
null/* decorView */, surface);
|
null/* decorView */, surface, STARTING_WINDOW_TYPE_SNAPSHOT);
|
||||||
mStartingWindowRecords.put(taskId, tView);
|
mStartingWindowRecords.put(taskId, tView);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -449,7 +461,7 @@ public class StartingSurfaceDrawer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected boolean addWindow(int taskId, IBinder appToken, View view, WindowManager wm,
|
protected boolean addWindow(int taskId, IBinder appToken, View view, WindowManager wm,
|
||||||
WindowManager.LayoutParams params) {
|
WindowManager.LayoutParams params, @StartingWindowType int suggestType) {
|
||||||
boolean shouldSaveView = true;
|
boolean shouldSaveView = true;
|
||||||
try {
|
try {
|
||||||
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "addRootView");
|
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "addRootView");
|
||||||
@@ -469,14 +481,15 @@ public class StartingSurfaceDrawer {
|
|||||||
}
|
}
|
||||||
if (shouldSaveView) {
|
if (shouldSaveView) {
|
||||||
removeWindowNoAnimate(taskId);
|
removeWindowNoAnimate(taskId);
|
||||||
saveSplashScreenRecord(appToken, taskId, view);
|
saveSplashScreenRecord(appToken, taskId, view, suggestType);
|
||||||
}
|
}
|
||||||
return shouldSaveView;
|
return shouldSaveView;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveSplashScreenRecord(IBinder appToken, int taskId, View view) {
|
private void saveSplashScreenRecord(IBinder appToken, int taskId, View view,
|
||||||
|
@StartingWindowType int suggestType) {
|
||||||
final StartingWindowRecord tView = new StartingWindowRecord(appToken, view,
|
final StartingWindowRecord tView = new StartingWindowRecord(appToken, view,
|
||||||
null/* TaskSnapshotWindow */);
|
null/* TaskSnapshotWindow */, suggestType);
|
||||||
mStartingWindowRecords.put(taskId, tView);
|
mStartingWindowRecords.put(taskId, tView);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -493,14 +506,18 @@ public class StartingSurfaceDrawer {
|
|||||||
Slog.v(TAG, "Removing splash screen window for task: " + taskId);
|
Slog.v(TAG, "Removing splash screen window for task: " + taskId);
|
||||||
}
|
}
|
||||||
if (record.mContentView != null) {
|
if (record.mContentView != null) {
|
||||||
if (playRevealAnimation) {
|
if (record.mSuggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) {
|
||||||
mSplashscreenContentDrawer.applyExitAnimation(record.mContentView,
|
removeWindowInner(record.mDecorView, false);
|
||||||
leash, frame,
|
|
||||||
() -> removeWindowInner(record.mDecorView, true));
|
|
||||||
} else {
|
} else {
|
||||||
// the SplashScreenView has been copied to client, hide the view to skip
|
if (playRevealAnimation) {
|
||||||
// default exit animation
|
mSplashscreenContentDrawer.applyExitAnimation(record.mContentView,
|
||||||
removeWindowInner(record.mDecorView, true);
|
leash, frame,
|
||||||
|
() -> removeWindowInner(record.mDecorView, true));
|
||||||
|
} else {
|
||||||
|
// the SplashScreenView has been copied to client, hide the view to skip
|
||||||
|
// default exit animation
|
||||||
|
removeWindowInner(record.mDecorView, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// shouldn't happen
|
// shouldn't happen
|
||||||
@@ -537,6 +554,7 @@ public class StartingSurfaceDrawer {
|
|||||||
private final TaskSnapshotWindow mTaskSnapshotWindow;
|
private final TaskSnapshotWindow mTaskSnapshotWindow;
|
||||||
private SplashScreenView mContentView;
|
private SplashScreenView mContentView;
|
||||||
private boolean mSetSplashScreen;
|
private boolean mSetSplashScreen;
|
||||||
|
private @StartingWindowType int mSuggestType;
|
||||||
|
|
||||||
StartingWindowRecord(IBinder appToken, View decorView,
|
StartingWindowRecord(IBinder appToken, View decorView,
|
||||||
TaskSnapshotWindow taskSnapshotWindow) {
|
TaskSnapshotWindow taskSnapshotWindow) {
|
||||||
@@ -545,6 +563,14 @@ public class StartingSurfaceDrawer {
|
|||||||
mTaskSnapshotWindow = taskSnapshotWindow;
|
mTaskSnapshotWindow = taskSnapshotWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StartingWindowRecord(IBinder appToken, View decorView,
|
||||||
|
TaskSnapshotWindow taskSnapshotWindow, @StartingWindowType int suggestType) {
|
||||||
|
mAppToken = appToken;
|
||||||
|
mDecorView = decorView;
|
||||||
|
mTaskSnapshotWindow = taskSnapshotWindow;
|
||||||
|
mSuggestType = suggestType;
|
||||||
|
}
|
||||||
|
|
||||||
private void setSplashScreenView(SplashScreenView splashScreenView) {
|
private void setSplashScreenView(SplashScreenView splashScreenView) {
|
||||||
if (mSetSplashScreen) {
|
if (mSetSplashScreen) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package com.android.wm.shell.startingsurface;
|
|||||||
|
|
||||||
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
|
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
|
||||||
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN;
|
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN;
|
||||||
|
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN;
|
||||||
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SNAPSHOT;
|
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SNAPSHOT;
|
||||||
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
|
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
|
||||||
|
|
||||||
@@ -31,6 +32,7 @@ import android.os.Trace;
|
|||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
import android.window.StartingWindowInfo;
|
import android.window.StartingWindowInfo;
|
||||||
|
import android.window.StartingWindowInfo.StartingWindowType;
|
||||||
import android.window.TaskOrganizer;
|
import android.window.TaskOrganizer;
|
||||||
import android.window.TaskSnapshot;
|
import android.window.TaskSnapshot;
|
||||||
|
|
||||||
@@ -106,10 +108,6 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo
|
|||||||
mTaskLaunchingCallback = listener;
|
mTaskLaunchingCallback = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean shouldSendToListener(int suggestionType) {
|
|
||||||
return suggestionType != STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a task need a starting window.
|
* Called when a task need a starting window.
|
||||||
*/
|
*/
|
||||||
@@ -120,12 +118,9 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo
|
|||||||
final int suggestionType = mStartingWindowTypeAlgorithm.getSuggestedWindowType(
|
final int suggestionType = mStartingWindowTypeAlgorithm.getSuggestedWindowType(
|
||||||
windowInfo);
|
windowInfo);
|
||||||
final RunningTaskInfo runningTaskInfo = windowInfo.taskInfo;
|
final RunningTaskInfo runningTaskInfo = windowInfo.taskInfo;
|
||||||
if (suggestionType == STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
|
if (isSplashScreenType(suggestionType)) {
|
||||||
mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, appToken,
|
mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, appToken,
|
||||||
false /* emptyView */);
|
suggestionType);
|
||||||
} else if (suggestionType == STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN) {
|
|
||||||
mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, appToken,
|
|
||||||
true /* emptyView */);
|
|
||||||
} else if (suggestionType == STARTING_WINDOW_TYPE_SNAPSHOT) {
|
} else if (suggestionType == STARTING_WINDOW_TYPE_SNAPSHOT) {
|
||||||
final TaskSnapshot snapshot = windowInfo.mTaskSnapshot;
|
final TaskSnapshot snapshot = windowInfo.mTaskSnapshot;
|
||||||
mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, appToken,
|
mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, appToken,
|
||||||
@@ -133,7 +128,7 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo
|
|||||||
} else /* suggestionType == STARTING_WINDOW_TYPE_NONE */ {
|
} else /* suggestionType == STARTING_WINDOW_TYPE_NONE */ {
|
||||||
// Don't add a staring window.
|
// Don't add a staring window.
|
||||||
}
|
}
|
||||||
if (mTaskLaunchingCallback != null && shouldSendToListener(suggestionType)) {
|
if (mTaskLaunchingCallback != null && isSplashScreenType(suggestionType)) {
|
||||||
int taskId = runningTaskInfo.taskId;
|
int taskId = runningTaskInfo.taskId;
|
||||||
int color = mStartingSurfaceDrawer.getStartingWindowBackgroundColorForTask(taskId);
|
int color = mStartingSurfaceDrawer.getStartingWindowBackgroundColorForTask(taskId);
|
||||||
mTaskLaunchingCallback.accept(taskId, suggestionType, color);
|
mTaskLaunchingCallback.accept(taskId, suggestionType, color);
|
||||||
@@ -143,6 +138,12 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isSplashScreenType(@StartingWindowType int suggestionType) {
|
||||||
|
return suggestionType == STARTING_WINDOW_TYPE_SPLASH_SCREEN
|
||||||
|
|| suggestionType == STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN
|
||||||
|
|| suggestionType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN;
|
||||||
|
}
|
||||||
|
|
||||||
public void copySplashScreenView(int taskId) {
|
public void copySplashScreenView(int taskId) {
|
||||||
mSplashScreenExecutor.execute(() -> {
|
mSplashScreenExecutor.execute(() -> {
|
||||||
mStartingSurfaceDrawer.copySplashScreenView(taskId);
|
mStartingSurfaceDrawer.copySplashScreenView(taskId);
|
||||||
|
|||||||
@@ -18,11 +18,13 @@ package com.android.wm.shell.startingsurface.phone;
|
|||||||
|
|
||||||
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
|
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
|
||||||
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN;
|
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN;
|
||||||
|
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN;
|
||||||
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_NONE;
|
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_NONE;
|
||||||
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SNAPSHOT;
|
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SNAPSHOT;
|
||||||
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
|
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
|
||||||
import static android.window.StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED;
|
import static android.window.StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED;
|
||||||
import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT;
|
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;
|
import static android.window.StartingWindowInfo.TYPE_PARAMETER_NEW_TASK;
|
||||||
import static android.window.StartingWindowInfo.TYPE_PARAMETER_PROCESS_RUNNING;
|
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_TASK_SWITCH;
|
||||||
@@ -54,30 +56,38 @@ public class PhoneStartingWindowTypeAlgorithm implements StartingWindowTypeAlgor
|
|||||||
final boolean activityCreated = (parameter & TYPE_PARAMETER_ACTIVITY_CREATED) != 0;
|
final boolean activityCreated = (parameter & TYPE_PARAMETER_ACTIVITY_CREATED) != 0;
|
||||||
final boolean useEmptySplashScreen =
|
final boolean useEmptySplashScreen =
|
||||||
(parameter & TYPE_PARAMETER_USE_EMPTY_SPLASH_SCREEN) != 0;
|
(parameter & TYPE_PARAMETER_USE_EMPTY_SPLASH_SCREEN) != 0;
|
||||||
|
final boolean legacySplashScreen =
|
||||||
|
((parameter & TYPE_PARAMETER_LEGACY_SPLASH_SCREEN) != 0);
|
||||||
final boolean topIsHome = windowInfo.taskInfo.topActivityType == ACTIVITY_TYPE_HOME;
|
final boolean topIsHome = windowInfo.taskInfo.topActivityType == ACTIVITY_TYPE_HOME;
|
||||||
|
|
||||||
if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
|
if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
|
||||||
Slog.d(TAG, "preferredStartingWindowType newTask " + newTask
|
Slog.d(TAG, "preferredStartingWindowType newTask:" + newTask
|
||||||
+ " taskSwitch " + taskSwitch
|
+ " taskSwitch:" + taskSwitch
|
||||||
+ " processRunning " + processRunning
|
+ " processRunning:" + processRunning
|
||||||
+ " allowTaskSnapshot " + allowTaskSnapshot
|
+ " allowTaskSnapshot:" + allowTaskSnapshot
|
||||||
+ " activityCreated " + activityCreated
|
+ " activityCreated:" + activityCreated
|
||||||
+ " useEmptySplashScreen " + useEmptySplashScreen
|
+ " useEmptySplashScreen:" + useEmptySplashScreen
|
||||||
+ " topIsHome " + topIsHome);
|
+ " legacySplashScreen:" + legacySplashScreen
|
||||||
|
+ " topIsHome:" + topIsHome);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final int visibleSplashScreenType = legacySplashScreen
|
||||||
|
? STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN
|
||||||
|
: STARTING_WINDOW_TYPE_SPLASH_SCREEN;
|
||||||
|
|
||||||
if (!topIsHome) {
|
if (!topIsHome) {
|
||||||
if (!processRunning) {
|
if (!processRunning) {
|
||||||
return useEmptySplashScreen
|
return useEmptySplashScreen
|
||||||
? STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN
|
? STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN
|
||||||
: STARTING_WINDOW_TYPE_SPLASH_SCREEN;
|
: visibleSplashScreenType;
|
||||||
}
|
}
|
||||||
if (newTask) {
|
if (newTask) {
|
||||||
return useEmptySplashScreen
|
return useEmptySplashScreen
|
||||||
? STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN
|
? STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN
|
||||||
: STARTING_WINDOW_TYPE_SPLASH_SCREEN;
|
: visibleSplashScreenType;
|
||||||
}
|
}
|
||||||
if (taskSwitch && !activityCreated) {
|
if (taskSwitch && !activityCreated) {
|
||||||
return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
|
return visibleSplashScreenType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (taskSwitch && allowTaskSnapshot) {
|
if (taskSwitch && allowTaskSnapshot) {
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.wm.shell.startingsurface;
|
package com.android.wm.shell.startingsurface;
|
||||||
|
|
||||||
|
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
|
||||||
|
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
|
||||||
@@ -91,7 +93,7 @@ public class StartingSurfaceDrawerTests {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean addWindow(int taskId, IBinder appToken,
|
protected boolean addWindow(int taskId, IBinder appToken,
|
||||||
View view, WindowManager wm, WindowManager.LayoutParams params) {
|
View view, WindowManager wm, WindowManager.LayoutParams params, int suggestType) {
|
||||||
// listen for addView
|
// listen for addView
|
||||||
mAddWindowForTask = taskId;
|
mAddWindowForTask = taskId;
|
||||||
mViewThemeResId = view.getContext().getThemeResId();
|
mViewThemeResId = view.getContext().getThemeResId();
|
||||||
@@ -145,9 +147,11 @@ public class StartingSurfaceDrawerTests {
|
|||||||
final int taskId = 1;
|
final int taskId = 1;
|
||||||
final StartingWindowInfo windowInfo =
|
final StartingWindowInfo windowInfo =
|
||||||
createWindowInfo(taskId, android.R.style.Theme);
|
createWindowInfo(taskId, android.R.style.Theme);
|
||||||
mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder, false);
|
mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder,
|
||||||
|
STARTING_WINDOW_TYPE_SPLASH_SCREEN);
|
||||||
waitHandlerIdle(mTestHandler);
|
waitHandlerIdle(mTestHandler);
|
||||||
verify(mStartingSurfaceDrawer).addWindow(eq(taskId), eq(mBinder), any(), any(), any());
|
verify(mStartingSurfaceDrawer).addWindow(eq(taskId), eq(mBinder), any(), any(), any(),
|
||||||
|
eq(STARTING_WINDOW_TYPE_SPLASH_SCREEN));
|
||||||
assertEquals(mStartingSurfaceDrawer.mAddWindowForTask, taskId);
|
assertEquals(mStartingSurfaceDrawer.mAddWindowForTask, taskId);
|
||||||
|
|
||||||
mStartingSurfaceDrawer.removeStartingWindow(windowInfo.taskInfo.taskId, null, null, false);
|
mStartingSurfaceDrawer.removeStartingWindow(windowInfo.taskInfo.taskId, null, null, false);
|
||||||
@@ -161,9 +165,11 @@ public class StartingSurfaceDrawerTests {
|
|||||||
final int taskId = 1;
|
final int taskId = 1;
|
||||||
final StartingWindowInfo windowInfo =
|
final StartingWindowInfo windowInfo =
|
||||||
createWindowInfo(taskId, 0);
|
createWindowInfo(taskId, 0);
|
||||||
mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder, false);
|
mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder,
|
||||||
|
STARTING_WINDOW_TYPE_SPLASH_SCREEN);
|
||||||
waitHandlerIdle(mTestHandler);
|
waitHandlerIdle(mTestHandler);
|
||||||
verify(mStartingSurfaceDrawer).addWindow(eq(taskId), eq(mBinder), any(), any(), any());
|
verify(mStartingSurfaceDrawer).addWindow(eq(taskId), eq(mBinder), any(), any(), any(),
|
||||||
|
eq(STARTING_WINDOW_TYPE_SPLASH_SCREEN));
|
||||||
assertNotEquals(mStartingSurfaceDrawer.mViewThemeResId, 0);
|
assertNotEquals(mStartingSurfaceDrawer.mViewThemeResId, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -257,6 +257,7 @@ import android.content.Intent;
|
|||||||
import android.content.LocusId;
|
import android.content.LocusId;
|
||||||
import android.content.pm.ActivityInfo;
|
import android.content.pm.ActivityInfo;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
import android.content.res.CompatibilityInfo;
|
import android.content.res.CompatibilityInfo;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
@@ -1929,12 +1930,23 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
|||||||
final TaskSnapshot snapshot =
|
final TaskSnapshot snapshot =
|
||||||
mWmService.mTaskSnapshotController.getSnapshot(task.mTaskId, task.mUserId,
|
mWmService.mTaskSnapshotController.getSnapshot(task.mTaskId, task.mUserId,
|
||||||
false /* restoreFromDisk */, false /* isLowResolution */);
|
false /* restoreFromDisk */, false /* isLowResolution */);
|
||||||
final int typeParameter = mWmService.mStartingSurfaceController
|
|
||||||
.makeStartingWindowTypeParameter(newTask, taskSwitch, processRunning,
|
|
||||||
allowTaskSnapshot, activityCreated, useEmpty);
|
|
||||||
final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
|
final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
|
||||||
allowTaskSnapshot, activityCreated, snapshot);
|
allowTaskSnapshot, activityCreated, snapshot);
|
||||||
|
|
||||||
|
//TODO(191787740) Remove for T
|
||||||
|
final boolean useLegacy = type == STARTING_WINDOW_TYPE_SPLASH_SCREEN
|
||||||
|
&& mWmService.mStartingSurfaceController.isExceptionApp(packageName, mTargetSdk,
|
||||||
|
() -> {
|
||||||
|
ActivityInfo activityInfo = intent.resolveActivityInfo(
|
||||||
|
mAtmService.mContext.getPackageManager(),
|
||||||
|
PackageManager.GET_META_DATA);
|
||||||
|
return activityInfo != null ? activityInfo.applicationInfo : null;
|
||||||
|
});
|
||||||
|
|
||||||
|
final int typeParameter = mWmService.mStartingSurfaceController
|
||||||
|
.makeStartingWindowTypeParameter(newTask, taskSwitch, processRunning,
|
||||||
|
allowTaskSnapshot, activityCreated, useEmpty, useLegacy);
|
||||||
|
|
||||||
if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
|
if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
|
||||||
if (isActivityTypeHome()) {
|
if (isActivityTypeHome()) {
|
||||||
// The snapshot of home is only used once because it won't be updated while screen
|
// The snapshot of home is only used once because it won't be updated while screen
|
||||||
|
|||||||
@@ -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_CREATED;
|
||||||
import static android.window.StartingWindowInfo.TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT;
|
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;
|
import static android.window.StartingWindowInfo.TYPE_PARAMETER_NEW_TASK;
|
||||||
import static android.window.StartingWindowInfo.TYPE_PARAMETER_PROCESS_RUNNING;
|
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_TASK_SWITCH;
|
||||||
@@ -85,7 +86,7 @@ public class StartingSurfaceController {
|
|||||||
|
|
||||||
int makeStartingWindowTypeParameter(boolean newTask, boolean taskSwitch,
|
int makeStartingWindowTypeParameter(boolean newTask, boolean taskSwitch,
|
||||||
boolean processRunning, boolean allowTaskSnapshot, boolean activityCreated,
|
boolean processRunning, boolean allowTaskSnapshot, boolean activityCreated,
|
||||||
boolean useEmpty) {
|
boolean useEmpty, boolean useLegacy) {
|
||||||
int parameter = 0;
|
int parameter = 0;
|
||||||
if (newTask) {
|
if (newTask) {
|
||||||
parameter |= TYPE_PARAMETER_NEW_TASK;
|
parameter |= TYPE_PARAMETER_NEW_TASK;
|
||||||
@@ -105,6 +106,9 @@ public class StartingSurfaceController {
|
|||||||
if (useEmpty) {
|
if (useEmpty) {
|
||||||
parameter |= TYPE_PARAMETER_USE_EMPTY_SPLASH_SCREEN;
|
parameter |= TYPE_PARAMETER_USE_EMPTY_SPLASH_SCREEN;
|
||||||
}
|
}
|
||||||
|
if (useLegacy) {
|
||||||
|
parameter |= TYPE_PARAMETER_LEGACY_SPLASH_SCREEN;
|
||||||
|
}
|
||||||
return parameter;
|
return parameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
|
|||||||
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
|
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
|
||||||
import static android.view.WindowManager.TRANSIT_CLOSE;
|
import static android.view.WindowManager.TRANSIT_CLOSE;
|
||||||
import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
|
import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
|
||||||
|
import static android.window.StartingWindowInfo.TYPE_PARAMETER_LEGACY_SPLASH_SCREEN;
|
||||||
|
|
||||||
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
|
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
|
||||||
|
|
||||||
@@ -111,11 +112,13 @@ import android.content.res.Configuration;
|
|||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.PersistableBundle;
|
import android.os.PersistableBundle;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.platform.test.annotations.Presubmit;
|
import android.platform.test.annotations.Presubmit;
|
||||||
|
import android.provider.DeviceConfig;
|
||||||
import android.util.MergedConfiguration;
|
import android.util.MergedConfiguration;
|
||||||
import android.util.MutableBoolean;
|
import android.util.MutableBoolean;
|
||||||
import android.view.DisplayInfo;
|
import android.view.DisplayInfo;
|
||||||
@@ -135,6 +138,7 @@ import androidx.test.filters.MediumTest;
|
|||||||
import com.android.internal.R;
|
import com.android.internal.R;
|
||||||
import com.android.server.wm.Task.ActivityState;
|
import com.android.server.wm.Task.ActivityState;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@@ -2457,6 +2461,40 @@ public class ActivityRecordTests extends WindowTestsBase {
|
|||||||
assertNoStartingWindow(activity);
|
assertNoStartingWindow(activity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void testLegacySplashScreen(int targetSdk, int verifyType) {
|
||||||
|
final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
|
||||||
|
activity.mTargetSdk = targetSdk;
|
||||||
|
activity.addStartingWindow(mPackageName,
|
||||||
|
android.R.style.Theme, null, "Test", 0, 0, 0, 0, null, true, true, false, true,
|
||||||
|
false, false);
|
||||||
|
waitUntilHandlersIdle();
|
||||||
|
assertHasStartingWindow(activity);
|
||||||
|
assertEquals(activity.mStartingData.mTypeParams & TYPE_PARAMETER_LEGACY_SPLASH_SCREEN,
|
||||||
|
verifyType);
|
||||||
|
activity.removeStartingWindow();
|
||||||
|
waitUntilHandlersIdle();
|
||||||
|
assertNoStartingWindow(activity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreateRemoveLegacySplashScreenWindow() {
|
||||||
|
registerTestStartingWindowOrganizer();
|
||||||
|
DeviceConfig.Properties properties = DeviceConfig.getProperties(
|
||||||
|
DeviceConfig.NAMESPACE_WINDOW_MANAGER);
|
||||||
|
try {
|
||||||
|
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
|
||||||
|
"splash_screen_exception_list", DEFAULT_COMPONENT_PACKAGE_NAME, false);
|
||||||
|
testLegacySplashScreen(Build.VERSION_CODES.R, TYPE_PARAMETER_LEGACY_SPLASH_SCREEN);
|
||||||
|
testLegacySplashScreen(Build.VERSION_CODES.S, 0);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
DeviceConfig.setProperties(properties);
|
||||||
|
} catch (DeviceConfig.BadConfigException e) {
|
||||||
|
Assert.fail(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTransferStartingWindow() {
|
public void testTransferStartingWindow() {
|
||||||
registerTestStartingWindowOrganizer();
|
registerTestStartingWindowOrganizer();
|
||||||
|
|||||||
Reference in New Issue
Block a user