summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Vadim Caen <caen@google.com> 2021-07-05 15:35:01 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2021-07-05 15:35:01 +0000
commit2be72d030be57907622bbf61af3b69b61d20d521 (patch)
treebe14175d8304e3a2fc811daea614e22aea8c254e
parent52a1d139ae9a60561369f5b0b410a1d2c465f53f (diff)
parentf08dae31587a342b64057340ea6b27e61c48a7e5 (diff)
Merge "Implement the legacy splash screen behavior" into sc-dev
-rw-r--r--core/java/android/window/SplashScreenView.java19
-rw-r--r--core/java/android/window/StartingWindowInfo.java14
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java94
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java68
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java21
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java30
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java16
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java18
-rw-r--r--services/core/java/com/android/server/wm/StartingSurfaceController.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java38
10 files changed, 243 insertions, 81 deletions
diff --git a/core/java/android/window/SplashScreenView.java b/core/java/android/window/SplashScreenView.java
index 148986a558e7..1efd2e381289 100644
--- a/core/java/android/window/SplashScreenView.java
+++ b/core/java/android/window/SplashScreenView.java
@@ -133,6 +133,8 @@ public final class SplashScreenView extends FrameLayout {
private @ColorInt int mIconBackground;
private Bitmap mParceledIconBitmap;
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 RemoteCallback mClientCallback;
private int mBrandingImageWidth;
@@ -193,6 +195,14 @@ public final class SplashScreenView extends FrameLayout {
}
/**
+ * 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.
*/
public Builder setCenterViewDrawable(@Nullable Drawable drawable) {
@@ -236,7 +246,11 @@ public final class SplashScreenView extends FrameLayout {
layoutInflater.inflate(R.layout.splash_screen_view, null, false);
view.mInitBackgroundColor = mBackgroundColor;
view.mInitIconBackgroundColor = mIconBackground;
- view.setBackgroundColor(mBackgroundColor);
+ if (mOverlayDrawable != null) {
+ view.setBackground(mOverlayDrawable);
+ } else {
+ view.setBackgroundColor(mBackgroundColor);
+ }
view.mClientCallback = mClientCallback;
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) {
view.mParceledIconBitmap = mParceledIconBitmap;
diff --git a/core/java/android/window/StartingWindowInfo.java b/core/java/android/window/StartingWindowInfo.java
index 8bc2177b42e1..566f154fba3b 100644
--- a/core/java/android/window/StartingWindowInfo.java
+++ b/core/java/android/window/StartingWindowInfo.java
@@ -55,6 +55,9 @@ public final class StartingWindowInfo implements Parcelable {
*/
public static final int STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN = 3;
+ /** @hide **/
+ public static final int STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN = 4;
+
/**
* @hide
*/
@@ -62,7 +65,8 @@ public final class StartingWindowInfo implements Parcelable {
STARTING_WINDOW_TYPE_NONE,
STARTING_WINDOW_TYPE_SPLASH_SCREEN,
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 {}
@@ -103,7 +107,8 @@ public final class StartingWindowInfo implements Parcelable {
TYPE_PARAMETER_PROCESS_RUNNING,
TYPE_PARAMETER_ALLOW_TASK_SNAPSHOT,
TYPE_PARAMETER_ACTIVITY_CREATED,
- TYPE_PARAMETER_USE_EMPTY_SPLASH_SCREEN
+ TYPE_PARAMETER_USE_EMPTY_SPLASH_SCREEN,
+ TYPE_PARAMETER_LEGACY_SPLASH_SCREEN
})
public @interface StartingTypeParams {}
@@ -122,6 +127,11 @@ public final class StartingWindowInfo implements Parcelable {
public static final int TYPE_PARAMETER_ACTIVITY_CREATED = 0x00000010;
/** @hide */
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.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
index b09d0d89a6b9..75dd561ffc61 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
@@ -18,6 +18,9 @@ package com.android.wm.shell.startingsurface;
import static android.os.Process.THREAD_PRIORITY_TOP_APP_BOOST;
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.NonNull;
@@ -47,6 +50,7 @@ import android.util.Slog;
import android.view.SurfaceControl;
import android.view.View;
import android.window.SplashScreenView;
+import android.window.StartingWindowInfo.StartingWindowType;
import com.android.internal.R;
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
* 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
* on splash screen thread. Note that the view can be null if failed.
*/
- void createContentView(Context context, boolean emptyView, ActivityInfo info, int taskId,
- Consumer<SplashScreenView> consumer) {
+ void createContentView(Context context, @StartingWindowType int suggestType, ActivityInfo info,
+ int taskId, Consumer<SplashScreenView> consumer) {
mSplashscreenWorkerHandler.post(() -> {
SplashScreenView contentView;
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "makeSplashScreenContentView");
- contentView = makeSplashScreenContentView(context, info, emptyView);
+ contentView = makeSplashScreenContentView(context, info, suggestType);
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
} catch (RuntimeException e) {
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,
- boolean emptyView) {
+ @StartingWindowType int suggestType) {
updateDensity();
getWindowAttrs(context, mTmpAttrs);
mLastPackageContextConfigHash = context.getResources().getConfiguration().hashCode();
- final int themeBGColor = mColorCache.getWindowColor(ai.packageName,
- mLastPackageContextConfigHash, mTmpAttrs.mWindowBgColor, mTmpAttrs.mWindowBgResId,
- () -> peekWindowBGColor(context, mTmpAttrs)).mBgColor;
- // TODO (b/173975965) Tracking the performance on improved splash screen.
+
+ final Drawable legacyDrawable = suggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN
+ ? peekLegacySplashscreenContent(context, mTmpAttrs) : null;
+ final int themeBGColor = legacyDrawable != null
+ ? getBGColorFromCache(ai, () -> estimateWindowBGColor(legacyDrawable))
+ : getBGColorFromCache(ai, () -> peekWindowBGColor(context, mTmpAttrs));
return new StartingWindowViewBuilder(context, ai)
.setWindowBGColor(themeBGColor)
- .makeEmptyView(emptyView)
+ .overlayDrawable(legacyDrawable)
+ .chooseStyle(suggestType)
.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) {
try {
return getMethod.apply(def);
@@ -267,7 +294,8 @@ public class SplashscreenContentDrawer {
private final Context mContext;
private final ActivityInfo mActivityInfo;
- private boolean mEmptyView;
+ private Drawable mOverlayDrawable;
+ private int mSuggestType;
private int mThemeColor;
private Drawable mFinalIconDrawable;
private int mFinalIconSize = mIconSize;
@@ -282,16 +310,22 @@ public class SplashscreenContentDrawer {
return this;
}
- StartingWindowViewBuilder makeEmptyView(boolean empty) {
- mEmptyView = empty;
+ StartingWindowViewBuilder overlayDrawable(Drawable overlay) {
+ mOverlayDrawable = overlay;
+ return this;
+ }
+
+ StartingWindowViewBuilder chooseStyle(int suggestType) {
+ mSuggestType = suggestType;
return this;
}
SplashScreenView build() {
Drawable iconDrawable;
final int animationDuration;
- if (mEmptyView) {
- // empty splash screen case
+ if (mSuggestType == STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN
+ || mSuggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) {
+ // empty or legacy splash screen case
animationDuration = 0;
mFinalIconSize = 0;
} else if (mTmpAttrs.mSplashScreenIcon != null) {
@@ -403,13 +437,15 @@ public class SplashscreenContentDrawer {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "fillViewWithIcon");
final SplashScreenView.Builder builder = new SplashScreenView.Builder(mContext);
builder.setBackgroundColor(mThemeColor);
+ builder.setOverlayDrawable(mOverlayDrawable);
if (iconDrawable != null) {
builder.setIconSize(iconSize)
.setIconBackground(mTmpAttrs.mIconBgColor)
.setCenterViewDrawable(iconDrawable)
.setAnimationDurationMillis(animationDuration);
}
- if (mTmpAttrs.mBrandingImage != null) {
+ if (mSuggestType == STARTING_WINDOW_TYPE_SPLASH_SCREEN
+ && mTmpAttrs.mBrandingImage != null) {
builder.setBrandingDrawable(mTmpAttrs.mBrandingImage, mBrandingImageWidth,
mBrandingImageHeight);
}
@@ -417,20 +453,22 @@ public class SplashscreenContentDrawer {
if (DEBUG) {
Slog.d(TAG, "fillViewWithIcon surfaceWindowView " + splashScreenView);
}
- if (mEmptyView) {
- splashScreenView.setNotCopyable();
+ 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) {
+ }
+ });
}
- 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;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
index 670af963230a..3cbce9c38f12 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
@@ -20,6 +20,8 @@ import static android.content.Context.CONTEXT_RESTRICTED;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Choreographer.CALLBACK_INSETS_ANIMATION;
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.app.ActivityManager.RunningTaskInfo;
@@ -32,7 +34,6 @@ import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.PixelFormat;
import android.graphics.Rect;
-import android.graphics.drawable.ColorDrawable;
import android.hardware.display.DisplayManager;
import android.os.IBinder;
import android.os.RemoteCallback;
@@ -50,6 +51,7 @@ import android.widget.FrameLayout;
import android.window.SplashScreenView;
import android.window.SplashScreenView.SplashScreenViewParcelable;
import android.window.StartingWindowInfo;
+import android.window.StartingWindowInfo.StartingWindowType;
import android.window.TaskSnapshot;
import com.android.internal.R;
@@ -149,10 +151,11 @@ public class StartingSurfaceDrawer {
/**
* 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,
- boolean emptyView) {
+ @StartingWindowType int suggestType) {
final RunningTaskInfo taskInfo = windowInfo.taskInfo;
final ActivityInfo activityInfo = taskInfo.topActivityInfo;
if (activityInfo == null) {
@@ -173,7 +176,8 @@ public class StartingSurfaceDrawer {
: com.android.internal.R.style.Theme_DeviceDefault_DayNight;
if (DEBUG_SPLASH_SCREEN) {
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.
@@ -231,13 +235,19 @@ public class StartingSurfaceDrawer {
params.setFitInsetsTypes(0);
params.format = PixelFormat.TRANSLUCENT;
int windowFlags = WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
- | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
final TypedArray a = context.obtainStyledAttributes(R.styleable.Window);
if (a.getBoolean(R.styleable.Window_windowShowWallpaper, false)) {
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(
R.styleable.Window_windowLayoutInDisplayCutoutMode,
params.layoutInDisplayCutoutMode);
@@ -311,12 +321,12 @@ public class StartingSurfaceDrawer {
}
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
};
- mSplashscreenContentDrawer.createContentView(context, emptyView, activityInfo, taskId,
+ mSplashscreenContentDrawer.createContentView(context, suggestType, activityInfo, taskId,
viewSupplier::setView);
try {
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
// the window, as otherwise Choreographer#doFrame might be delayed on this thread.
// And since Choreographer#doFrame won't happen immediately after adding the window,
@@ -336,8 +346,10 @@ public class StartingSurfaceDrawer {
int getStartingWindowBackgroundColorForTask(int taskId) {
StartingWindowRecord startingWindowRecord = mStartingWindowRecords.get(taskId);
- if (startingWindowRecord == null || startingWindowRecord.mContentView == null) return 0;
- return ((ColorDrawable) startingWindowRecord.mContentView.getBackground()).getColor();
+ if (startingWindowRecord == null || startingWindowRecord.mContentView == null) {
+ return 0;
+ }
+ return startingWindowRecord.mContentView.getInitBackgroundColor();
}
private static class SplashScreenViewSupplier implements Supplier<SplashScreenView> {
@@ -379,7 +391,7 @@ public class StartingSurfaceDrawer {
return;
}
final StartingWindowRecord tView = new StartingWindowRecord(appToken,
- null/* decorView */, surface);
+ null/* decorView */, surface, STARTING_WINDOW_TYPE_SNAPSHOT);
mStartingWindowRecords.put(taskId, tView);
}
@@ -449,7 +461,7 @@ public class StartingSurfaceDrawer {
}
protected boolean addWindow(int taskId, IBinder appToken, View view, WindowManager wm,
- WindowManager.LayoutParams params) {
+ WindowManager.LayoutParams params, @StartingWindowType int suggestType) {
boolean shouldSaveView = true;
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "addRootView");
@@ -469,14 +481,15 @@ public class StartingSurfaceDrawer {
}
if (shouldSaveView) {
removeWindowNoAnimate(taskId);
- saveSplashScreenRecord(appToken, taskId, view);
+ saveSplashScreenRecord(appToken, taskId, view, suggestType);
}
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,
- null/* TaskSnapshotWindow */);
+ null/* TaskSnapshotWindow */, suggestType);
mStartingWindowRecords.put(taskId, tView);
}
@@ -493,14 +506,18 @@ public class StartingSurfaceDrawer {
Slog.v(TAG, "Removing splash screen window for task: " + taskId);
}
if (record.mContentView != null) {
- if (playRevealAnimation) {
- mSplashscreenContentDrawer.applyExitAnimation(record.mContentView,
- leash, frame,
- () -> removeWindowInner(record.mDecorView, true));
+ if (record.mSuggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) {
+ removeWindowInner(record.mDecorView, false);
} else {
- // the SplashScreenView has been copied to client, hide the view to skip
- // default exit animation
- removeWindowInner(record.mDecorView, true);
+ if (playRevealAnimation) {
+ mSplashscreenContentDrawer.applyExitAnimation(record.mContentView,
+ 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 {
// shouldn't happen
@@ -537,6 +554,7 @@ public class StartingSurfaceDrawer {
private final TaskSnapshotWindow mTaskSnapshotWindow;
private SplashScreenView mContentView;
private boolean mSetSplashScreen;
+ private @StartingWindowType int mSuggestType;
StartingWindowRecord(IBinder appToken, View decorView,
TaskSnapshotWindow taskSnapshotWindow) {
@@ -545,6 +563,14 @@ public class StartingSurfaceDrawer {
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) {
if (mSetSplashScreen) {
return;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
index 9c1dde925762..eaa89d8e3ab5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
@@ -17,6 +17,7 @@ package com.android.wm.shell.startingsurface;
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_SNAPSHOT;
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
@@ -31,6 +32,7 @@ import android.os.Trace;
import android.util.Slog;
import android.view.SurfaceControl;
import android.window.StartingWindowInfo;
+import android.window.StartingWindowInfo.StartingWindowType;
import android.window.TaskOrganizer;
import android.window.TaskSnapshot;
@@ -106,10 +108,6 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo
mTaskLaunchingCallback = listener;
}
- private boolean shouldSendToListener(int suggestionType) {
- return suggestionType != STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN;
- }
-
/**
* Called when a task need a starting window.
*/
@@ -120,12 +118,9 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo
final int suggestionType = mStartingWindowTypeAlgorithm.getSuggestedWindowType(
windowInfo);
final RunningTaskInfo runningTaskInfo = windowInfo.taskInfo;
- if (suggestionType == STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
- mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, appToken,
- false /* emptyView */);
- } else if (suggestionType == STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN) {
+ if (isSplashScreenType(suggestionType)) {
mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, appToken,
- true /* emptyView */);
+ suggestionType);
} else if (suggestionType == STARTING_WINDOW_TYPE_SNAPSHOT) {
final TaskSnapshot snapshot = windowInfo.mTaskSnapshot;
mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, appToken,
@@ -133,7 +128,7 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo
} else /* suggestionType == STARTING_WINDOW_TYPE_NONE */ {
// Don't add a staring window.
}
- if (mTaskLaunchingCallback != null && shouldSendToListener(suggestionType)) {
+ if (mTaskLaunchingCallback != null && isSplashScreenType(suggestionType)) {
int taskId = runningTaskInfo.taskId;
int color = mStartingSurfaceDrawer.getStartingWindowBackgroundColorForTask(taskId);
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) {
mSplashScreenExecutor.execute(() -> {
mStartingSurfaceDrawer.copySplashScreenView(taskId);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java
index 5a134b806745..848eff4b56f3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java
@@ -18,11 +18,13 @@ package com.android.wm.shell.startingsurface.phone;
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_LEGACY_SPLASH_SCREEN;
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_SPLASH_SCREEN;
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_LEGACY_SPLASH_SCREEN;
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_TASK_SWITCH;
@@ -54,30 +56,38 @@ public class PhoneStartingWindowTypeAlgorithm implements StartingWindowTypeAlgor
final boolean activityCreated = (parameter & TYPE_PARAMETER_ACTIVITY_CREATED) != 0;
final boolean useEmptySplashScreen =
(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;
if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
- Slog.d(TAG, "preferredStartingWindowType newTask " + newTask
- + " taskSwitch " + taskSwitch
- + " processRunning " + processRunning
- + " allowTaskSnapshot " + allowTaskSnapshot
- + " activityCreated " + activityCreated
- + " useEmptySplashScreen " + useEmptySplashScreen
- + " topIsHome " + topIsHome);
+ Slog.d(TAG, "preferredStartingWindowType newTask:" + newTask
+ + " taskSwitch:" + taskSwitch
+ + " processRunning:" + processRunning
+ + " allowTaskSnapshot:" + allowTaskSnapshot
+ + " activityCreated:" + activityCreated
+ + " useEmptySplashScreen:" + useEmptySplashScreen
+ + " legacySplashScreen:" + legacySplashScreen
+ + " topIsHome:" + topIsHome);
}
+
+ final int visibleSplashScreenType = legacySplashScreen
+ ? STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN
+ : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
+
if (!topIsHome) {
if (!processRunning) {
return useEmptySplashScreen
? STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN
- : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
+ : visibleSplashScreenType;
}
if (newTask) {
return useEmptySplashScreen
? STARTING_WINDOW_TYPE_EMPTY_SPLASH_SCREEN
- : STARTING_WINDOW_TYPE_SPLASH_SCREEN;
+ : visibleSplashScreenType;
}
if (taskSwitch && !activityCreated) {
- return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
+ return visibleSplashScreenType;
}
}
if (taskSwitch && allowTaskSnapshot) {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
index 903e63ad6554..5061b2369bb2 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
@@ -15,6 +15,8 @@
*/
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.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
@@ -91,7 +93,7 @@ public class StartingSurfaceDrawerTests {
@Override
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
mAddWindowForTask = taskId;
mViewThemeResId = view.getContext().getThemeResId();
@@ -145,9 +147,11 @@ public class StartingSurfaceDrawerTests {
final int taskId = 1;
final StartingWindowInfo windowInfo =
createWindowInfo(taskId, android.R.style.Theme);
- mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder, false);
+ mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder,
+ STARTING_WINDOW_TYPE_SPLASH_SCREEN);
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);
mStartingSurfaceDrawer.removeStartingWindow(windowInfo.taskInfo.taskId, null, null, false);
@@ -161,9 +165,11 @@ public class StartingSurfaceDrawerTests {
final int taskId = 1;
final StartingWindowInfo windowInfo =
createWindowInfo(taskId, 0);
- mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder, false);
+ mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder,
+ STARTING_WINDOW_TYPE_SPLASH_SCREEN);
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);
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index d551f66c7387..64b5fc77dea7 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -257,6 +257,7 @@ import android.content.Intent;
import android.content.LocusId;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -1929,12 +1930,23 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
final TaskSnapshot snapshot =
mWmService.mTaskSnapshotController.getSnapshot(task.mTaskId, task.mUserId,
false /* restoreFromDisk */, false /* isLowResolution */);
- final int typeParameter = mWmService.mStartingSurfaceController
- .makeStartingWindowTypeParameter(newTask, taskSwitch, processRunning,
- allowTaskSnapshot, activityCreated, useEmpty);
final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
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 (isActivityTypeHome()) {
// The snapshot of home is only used once because it won't be updated while screen
diff --git a/services/core/java/com/android/server/wm/StartingSurfaceController.java b/services/core/java/com/android/server/wm/StartingSurfaceController.java
index da257477b1d8..45b53a1a99b9 100644
--- a/services/core/java/com/android/server/wm/StartingSurfaceController.java
+++ b/services/core/java/com/android/server/wm/StartingSurfaceController.java
@@ -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_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_PROCESS_RUNNING;
import static android.window.StartingWindowInfo.TYPE_PARAMETER_TASK_SWITCH;
@@ -85,7 +86,7 @@ public class StartingSurfaceController {
int makeStartingWindowTypeParameter(boolean newTask, boolean taskSwitch,
boolean processRunning, boolean allowTaskSnapshot, boolean activityCreated,
- boolean useEmpty) {
+ boolean useEmpty, boolean useLegacy) {
int parameter = 0;
if (newTask) {
parameter |= TYPE_PARAMETER_NEW_TASK;
@@ -105,6 +106,9 @@ public class StartingSurfaceController {
if (useEmpty) {
parameter |= TYPE_PARAMETER_USE_EMPTY_SPLASH_SCREEN;
}
+ if (useLegacy) {
+ parameter |= TYPE_PARAMETER_LEGACY_SPLASH_SCREEN;
+ }
return parameter;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index b7713a9338de..a1f1610d95db 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -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.TRANSIT_CLOSE;
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;
@@ -111,11 +112,13 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Rect;
+import android.os.Build;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
+import android.provider.DeviceConfig;
import android.util.MergedConfiguration;
import android.util.MutableBoolean;
import android.view.DisplayInfo;
@@ -135,6 +138,7 @@ import androidx.test.filters.MediumTest;
import com.android.internal.R;
import com.android.server.wm.Task.ActivityState;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -2457,6 +2461,40 @@ public class ActivityRecordTests extends WindowTestsBase {
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
public void testTransferStartingWindow() {
registerTestStartingWindowOrganizer();