Merge "Draw splashscreen edge to edge" into sc-dev
This commit is contained in:
@@ -970,8 +970,7 @@ public class Activity extends ContextThemeWrapper
|
||||
private UiTranslationController mUiTranslationController;
|
||||
|
||||
private SplashScreen mSplashScreen;
|
||||
/** @hide */
|
||||
SplashScreenView mSplashScreenView;
|
||||
private SplashScreenView mSplashScreenView;
|
||||
|
||||
private final WindowControllerCallback mWindowControllerCallback =
|
||||
new WindowControllerCallback() {
|
||||
@@ -1631,16 +1630,14 @@ public class Activity extends ContextThemeWrapper
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the splash screen view if exist.
|
||||
* @hide
|
||||
*/
|
||||
public void detachSplashScreenView() {
|
||||
synchronized (this) {
|
||||
if (mSplashScreenView != null) {
|
||||
mSplashScreenView = null;
|
||||
}
|
||||
}
|
||||
/** @hide */
|
||||
public void setSplashScreenView(SplashScreenView v) {
|
||||
mSplashScreenView = v;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
SplashScreenView getSplashScreenView() {
|
||||
return mSplashScreenView;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4051,10 +4051,7 @@ public final class ActivityThread extends ClientTransactionHandler
|
||||
final SplashScreenView.Builder builder = new SplashScreenView.Builder(r.activity);
|
||||
final SplashScreenView view = builder.createFromParcel(parcelable).build();
|
||||
decorView.addView(view);
|
||||
view.cacheRootWindow(r.window);
|
||||
view.makeSystemUIColorsTransparent();
|
||||
r.activity.mSplashScreenView = view;
|
||||
view.attachHostActivity(r.activity);
|
||||
view.attachHostActivityAndSetSystemUIColors(r.activity, r.window);
|
||||
view.requestLayout();
|
||||
// Ensure splash screen view is shown before remove the splash screen window.
|
||||
final ViewRootImpl impl = decorView.getViewRootImpl();
|
||||
@@ -4096,12 +4093,13 @@ public final class ActivityThread extends ClientTransactionHandler
|
||||
|
||||
@Override
|
||||
public void handOverSplashScreenView(@NonNull ActivityClientRecord r) {
|
||||
if (r.activity.mSplashScreenView != null) {
|
||||
synchronized (this) {
|
||||
if (mSplashScreenGlobal != null) {
|
||||
mSplashScreenGlobal.dispatchOnExitAnimation(r.token,
|
||||
r.activity.mSplashScreenView);
|
||||
}
|
||||
final SplashScreenView v = r.activity.getSplashScreenView();
|
||||
if (v == null) {
|
||||
return;
|
||||
}
|
||||
synchronized (this) {
|
||||
if (mSplashScreenGlobal != null) {
|
||||
mSplashScreenGlobal.dispatchOnExitAnimation(r.token, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1354,6 +1354,11 @@ public abstract class Window {
|
||||
public void setDecorFitsSystemWindows(boolean decorFitsSystemWindows) {
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public boolean decorFitsSystemWindows() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify custom window attributes. <strong>PLEASE NOTE:</strong> the
|
||||
* layout params you give here should generally be from values previously
|
||||
|
||||
@@ -17,6 +17,8 @@ package android.window;
|
||||
|
||||
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
|
||||
|
||||
import android.annotation.ColorInt;
|
||||
import android.annotation.NonNull;
|
||||
@@ -40,11 +42,13 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.WindowInsetsController;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.policy.DecorView;
|
||||
import com.android.internal.util.ContrastColorUtil;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
@@ -69,6 +73,12 @@ public final class SplashScreenView extends FrameLayout {
|
||||
private static final String TAG = SplashScreenView.class.getSimpleName();
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final int LIGHT_BARS_MASK =
|
||||
WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS
|
||||
| WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
|
||||
private static final int WINDOW_FLAG_MASK = FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS
|
||||
| FLAG_TRANSLUCENT_NAVIGATION | FLAG_TRANSLUCENT_STATUS;
|
||||
|
||||
private boolean mNotCopyable;
|
||||
private boolean mRevealAnimationSupported = true;
|
||||
private int mInitBackgroundColor;
|
||||
@@ -84,10 +94,14 @@ public final class SplashScreenView extends FrameLayout {
|
||||
private Activity mHostActivity;
|
||||
// cache original window and status
|
||||
private Window mWindow;
|
||||
private boolean mDrawBarBackground;
|
||||
private int mAppWindowFlags;
|
||||
private int mStatusBarColor;
|
||||
private int mNavigationBarColor;
|
||||
private int mSystemBarsAppearance;
|
||||
private boolean mHasRemoved;
|
||||
private boolean mNavigationContrastEnforced;
|
||||
private boolean mStatusContrastEnforced;
|
||||
private boolean mDecorFitsSystemWindows;
|
||||
|
||||
/**
|
||||
* Internal builder to create a SplashScreenView object.
|
||||
@@ -347,54 +361,63 @@ public final class SplashScreenView extends FrameLayout {
|
||||
mWindow = null;
|
||||
}
|
||||
if (mHostActivity != null) {
|
||||
mHostActivity.detachSplashScreenView();
|
||||
mHostActivity.setSplashScreenView(null);
|
||||
mHostActivity = null;
|
||||
}
|
||||
mHasRemoved = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when this view is attached to an activity.
|
||||
* Called when this view is attached to an activity. This also makes SystemUI colors
|
||||
* transparent so the content of splash screen view can draw fully.
|
||||
* @hide
|
||||
*/
|
||||
public void attachHostActivity(Activity activity) {
|
||||
public void attachHostActivityAndSetSystemUIColors(Activity activity, Window window) {
|
||||
activity.setSplashScreenView(this);
|
||||
mHostActivity = activity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache the root window.
|
||||
* @hide
|
||||
*/
|
||||
public void cacheRootWindow(Window window) {
|
||||
mWindow = window;
|
||||
final WindowManager.LayoutParams attr = window.getAttributes();
|
||||
mAppWindowFlags = attr.flags;
|
||||
mStatusBarColor = window.getStatusBarColor();
|
||||
mNavigationBarColor = window.getNavigationBarColor();
|
||||
mSystemBarsAppearance = window.getInsetsController().getSystemBarsAppearance();
|
||||
mNavigationContrastEnforced = window.isNavigationBarContrastEnforced();
|
||||
mStatusContrastEnforced = window.isStatusBarContrastEnforced();
|
||||
mDecorFitsSystemWindows = window.decorFitsSystemWindows();
|
||||
|
||||
applySystemBarsContrastColor(window.getInsetsController(), mInitBackgroundColor);
|
||||
// Let app draw the background of bars.
|
||||
window.addFlags(FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||
// Use specified bar colors instead of window background.
|
||||
window.clearFlags(FLAG_TRANSLUCENT_STATUS | FLAG_TRANSLUCENT_NAVIGATION);
|
||||
window.setStatusBarColor(Color.TRANSPARENT);
|
||||
window.setNavigationBarColor(Color.TRANSPARENT);
|
||||
window.setDecorFitsSystemWindows(false);
|
||||
window.setStatusBarContrastEnforced(false);
|
||||
window.setNavigationBarContrastEnforced(false);
|
||||
}
|
||||
|
||||
/** Called when this view is removed from the host activity. */
|
||||
private void restoreSystemUIColors() {
|
||||
mWindow.setFlags(mAppWindowFlags, WINDOW_FLAG_MASK);
|
||||
mWindow.setStatusBarColor(mStatusBarColor);
|
||||
mWindow.setNavigationBarColor(mNavigationBarColor);
|
||||
mWindow.getInsetsController().setSystemBarsAppearance(mSystemBarsAppearance,
|
||||
LIGHT_BARS_MASK);
|
||||
mWindow.setDecorFitsSystemWindows(mDecorFitsSystemWindows);
|
||||
mWindow.setStatusBarContrastEnforced(mStatusContrastEnforced);
|
||||
mWindow.setNavigationBarContrastEnforced(mNavigationContrastEnforced);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after SplashScreenView has added on the root window.
|
||||
* Makes the icon color of system bars contrast.
|
||||
* @hide
|
||||
*/
|
||||
public void makeSystemUIColorsTransparent() {
|
||||
if (mWindow != null) {
|
||||
final WindowManager.LayoutParams attr = mWindow.getAttributes();
|
||||
mDrawBarBackground = (attr.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
|
||||
mWindow.addFlags(FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||
mStatusBarColor = mWindow.getStatusBarColor();
|
||||
mNavigationBarColor = mWindow.getNavigationBarDividerColor();
|
||||
mWindow.setStatusBarColor(Color.TRANSPARENT);
|
||||
mWindow.setNavigationBarColor(Color.TRANSPARENT);
|
||||
}
|
||||
setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
|
||||
}
|
||||
|
||||
private void restoreSystemUIColors() {
|
||||
if (mWindow != null) {
|
||||
if (!mDrawBarBackground) {
|
||||
mWindow.clearFlags(FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||
}
|
||||
mWindow.setStatusBarColor(mStatusBarColor);
|
||||
mWindow.setNavigationBarColor(mNavigationBarColor);
|
||||
}
|
||||
public static void applySystemBarsContrastColor(WindowInsetsController windowInsetsController,
|
||||
int backgroundColor) {
|
||||
final int lightBarAppearance = ContrastColorUtil.isColorLight(backgroundColor)
|
||||
? LIGHT_BARS_MASK : 0;
|
||||
windowInsetsController.setSystemBarsAppearance(lightBarAppearance, LIGHT_BARS_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3931,6 +3931,11 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
applyDecorFitsSystemWindows();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean decorFitsSystemWindows() {
|
||||
return mDecorFitsSystemWindows;
|
||||
}
|
||||
|
||||
private void applyDecorFitsSystemWindows() {
|
||||
ViewRootImpl impl = getViewRootImplOrNull();
|
||||
if (impl != null) {
|
||||
|
||||
@@ -39,6 +39,7 @@ import android.os.HandlerThread;
|
||||
import android.os.Trace;
|
||||
import android.util.Slog;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.View;
|
||||
import android.window.SplashScreenView;
|
||||
|
||||
import com.android.internal.R;
|
||||
@@ -398,7 +399,17 @@ public class SplashscreenContentDrawer {
|
||||
splashScreenView.setNotCopyable();
|
||||
splashScreenView.setRevealAnimationSupported(false);
|
||||
}
|
||||
splashScreenView.makeSystemUIColorsTransparent();
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -25,12 +25,10 @@ import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.app.ActivityTaskManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.os.IBinder;
|
||||
@@ -43,13 +41,13 @@ import android.view.Display;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.FrameLayout;
|
||||
import android.window.SplashScreenView;
|
||||
import android.window.SplashScreenView.SplashScreenViewParcelable;
|
||||
import android.window.StartingWindowInfo;
|
||||
import android.window.TaskSnapshot;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.policy.PhoneWindow;
|
||||
import com.android.wm.shell.common.ShellExecutor;
|
||||
import com.android.wm.shell.common.TransactionPool;
|
||||
|
||||
@@ -152,14 +150,6 @@ public class StartingSurfaceDrawer {
|
||||
return;
|
||||
}
|
||||
|
||||
CharSequence nonLocalizedLabel = activityInfo.nonLocalizedLabel;
|
||||
int labelRes = activityInfo.labelRes;
|
||||
if (activityInfo.nonLocalizedLabel == null && activityInfo.labelRes == 0) {
|
||||
ApplicationInfo app = activityInfo.applicationInfo;
|
||||
nonLocalizedLabel = app.nonLocalizedLabel;
|
||||
labelRes = app.labelRes;
|
||||
}
|
||||
|
||||
final int taskId = taskInfo.taskId;
|
||||
Context context = mContext;
|
||||
// replace with the default theme if the application didn't set
|
||||
@@ -169,8 +159,7 @@ public class StartingSurfaceDrawer {
|
||||
: com.android.internal.R.style.Theme_DeviceDefault_DayNight;
|
||||
if (DEBUG_SPLASH_SCREEN) {
|
||||
Slog.d(TAG, "addSplashScreen " + activityInfo.packageName
|
||||
+ ": nonLocalizedLabel=" + nonLocalizedLabel + " theme="
|
||||
+ Integer.toHexString(theme) + " task= " + taskInfo.taskId);
|
||||
+ " theme=" + Integer.toHexString(theme) + " task= " + taskInfo.taskId);
|
||||
}
|
||||
|
||||
// Obtain proper context to launch on the right display.
|
||||
@@ -180,7 +169,7 @@ public class StartingSurfaceDrawer {
|
||||
return;
|
||||
}
|
||||
context = displayContext;
|
||||
if (theme != context.getThemeResId() || labelRes != 0) {
|
||||
if (theme != context.getThemeResId()) {
|
||||
try {
|
||||
context = context.createPackageContextAsUser(activityInfo.packageName,
|
||||
CONTEXT_RESTRICTED, UserHandle.of(taskInfo.userId));
|
||||
@@ -222,23 +211,22 @@ public class StartingSurfaceDrawer {
|
||||
typedArray.recycle();
|
||||
}
|
||||
|
||||
final PhoneWindow win = new PhoneWindow(context);
|
||||
win.setIsStartingWindow(true);
|
||||
|
||||
final Resources res = context.getResources();
|
||||
final CharSequence label = res.getText(labelRes, null);
|
||||
// Only change the accessibility title if the label is localized
|
||||
if (label != null) {
|
||||
win.setTitle(label, true);
|
||||
} else {
|
||||
win.setTitle(nonLocalizedLabel, false);
|
||||
}
|
||||
|
||||
int windowFlags = WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
|
||||
final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
|
||||
WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
|
||||
params.setFitInsetsSides(0);
|
||||
params.setFitInsetsTypes(0);
|
||||
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;
|
||||
}
|
||||
params.layoutInDisplayCutoutMode = a.getInt(
|
||||
R.styleable.Window_windowLayoutInDisplayCutoutMode,
|
||||
params.layoutInDisplayCutoutMode);
|
||||
params.windowAnimations = a.getResourceId(R.styleable.Window_windowAnimationStyle, 0);
|
||||
a.recycle();
|
||||
|
||||
// Assumes it's safe to show starting windows of launched apps while
|
||||
@@ -256,28 +244,15 @@ public class StartingSurfaceDrawer {
|
||||
windowFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
|
||||
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
||||
| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
|
||||
win.setFlags(windowFlags, windowFlags);
|
||||
|
||||
final int iconRes = activityInfo.getIconResource();
|
||||
final int logoRes = activityInfo.getLogoResource();
|
||||
win.setDefaultIcon(iconRes);
|
||||
win.setDefaultLogo(logoRes);
|
||||
|
||||
final WindowManager.LayoutParams params = win.getAttributes();
|
||||
params.type = WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
|
||||
params.width = WindowManager.LayoutParams.MATCH_PARENT;
|
||||
params.height = WindowManager.LayoutParams.MATCH_PARENT;
|
||||
params.flags = windowFlags;
|
||||
params.token = appToken;
|
||||
params.packageName = activityInfo.packageName;
|
||||
params.windowAnimations = win.getWindowStyle().getResourceId(
|
||||
com.android.internal.R.styleable.Window_windowAnimationStyle, 0);
|
||||
params.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
|
||||
// Setting as trusted overlay to let touches pass through. This is safe because this
|
||||
// window is controlled by the system.
|
||||
params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
|
||||
params.format = PixelFormat.RGBA_8888;
|
||||
|
||||
if (!res.getCompatibilityInfo().supportsScreen()) {
|
||||
if (!context.getResources().getCompatibilityInfo().supportsScreen()) {
|
||||
params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
|
||||
}
|
||||
|
||||
@@ -297,6 +272,7 @@ public class StartingSurfaceDrawer {
|
||||
// Record whether create splash screen view success, notify to current thread after
|
||||
// create splash screen view finished.
|
||||
final SplashScreenViewSupplier viewSupplier = new SplashScreenViewSupplier();
|
||||
final FrameLayout rootLayout = new FrameLayout(context);
|
||||
final Runnable setViewSynchronized = () -> {
|
||||
// waiting for setContentView before relayoutWindow
|
||||
SplashScreenView contentView = viewSupplier.get();
|
||||
@@ -306,8 +282,7 @@ public class StartingSurfaceDrawer {
|
||||
// if view == null then creation of content view was failed.
|
||||
if (contentView != null) {
|
||||
try {
|
||||
win.setContentView(contentView);
|
||||
contentView.cacheRootWindow(win);
|
||||
rootLayout.addView(contentView);
|
||||
} catch (RuntimeException e) {
|
||||
Slog.w(TAG, "failed set content view to starting window "
|
||||
+ "at taskId: " + taskId, e);
|
||||
@@ -321,9 +296,8 @@ public class StartingSurfaceDrawer {
|
||||
viewSupplier::setView);
|
||||
|
||||
try {
|
||||
final View view = win.getDecorView();
|
||||
final WindowManager wm = context.getSystemService(WindowManager.class);
|
||||
postAddWindow(taskId, appToken, view, wm, params);
|
||||
postAddWindow(taskId, appToken, rootLayout, wm, params);
|
||||
|
||||
// We use the splash screen worker thread to create SplashScreenView while adding the
|
||||
// window, as otherwise Choreographer#doFrame might be delayed on this thread.
|
||||
|
||||
Reference in New Issue
Block a user