Merge "Get starting window background color directly." into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
a9a861134d
@@ -127,11 +127,13 @@ public class SplashscreenContentDrawer {
|
|||||||
* parallel.
|
* parallel.
|
||||||
*
|
*
|
||||||
* @param suggestType Suggest type to create the splash screen view.
|
* @param suggestType Suggest type to create the splash screen view.
|
||||||
* @param consumer Receiving the SplashScreenView object, which will also be executed
|
* @param splashScreenViewConsumer Receiving the SplashScreenView object, which will also be
|
||||||
* on splash screen thread. Note that the view can be null if failed.
|
* executed on splash screen thread. Note that the view can be
|
||||||
|
* null if failed.
|
||||||
|
* @param bgColorConsumer Receiving the background color once it's estimated complete.
|
||||||
*/
|
*/
|
||||||
void createContentView(Context context, @StartingWindowType int suggestType, ActivityInfo info,
|
void createContentView(Context context, @StartingWindowType int suggestType, ActivityInfo info,
|
||||||
int taskId, Consumer<SplashScreenView> consumer) {
|
int taskId, Consumer<SplashScreenView> splashScreenViewConsumer) {
|
||||||
mSplashscreenWorkerHandler.post(() -> {
|
mSplashscreenWorkerHandler.post(() -> {
|
||||||
SplashScreenView contentView;
|
SplashScreenView contentView;
|
||||||
try {
|
try {
|
||||||
@@ -143,7 +145,7 @@ public class SplashscreenContentDrawer {
|
|||||||
+ taskId, e);
|
+ taskId, e);
|
||||||
contentView = null;
|
contentView = null;
|
||||||
}
|
}
|
||||||
consumer.accept(contentView);
|
splashScreenViewConsumer.accept(contentView);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,7 +162,10 @@ public class SplashscreenContentDrawer {
|
|||||||
com.android.wm.shell.R.dimen.starting_surface_exit_animation_window_shift_length);
|
com.android.wm.shell.R.dimen.starting_surface_exit_animation_window_shift_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getSystemBGColor() {
|
/**
|
||||||
|
* @return Current system background color.
|
||||||
|
*/
|
||||||
|
public static int getSystemBGColor() {
|
||||||
final Context systemContext = ActivityThread.currentApplication();
|
final Context systemContext = ActivityThread.currentApplication();
|
||||||
if (systemContext == null) {
|
if (systemContext == null) {
|
||||||
Slog.e(TAG, "System context does not exist!");
|
Slog.e(TAG, "System context does not exist!");
|
||||||
@@ -170,12 +175,22 @@ public class SplashscreenContentDrawer {
|
|||||||
return res.getColor(com.android.wm.shell.R.color.splash_window_background_default);
|
return res.getColor(com.android.wm.shell.R.color.splash_window_background_default);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Estimate the background color of the app splash screen, this may take a while so use it only
|
||||||
|
* if there is no starting window exists for that context.
|
||||||
|
**/
|
||||||
|
int estimateTaskBackgroundColor(Context context) {
|
||||||
|
final SplashScreenWindowAttrs windowAttrs = new SplashScreenWindowAttrs();
|
||||||
|
getWindowAttrs(context, windowAttrs);
|
||||||
|
return peekWindowBGColor(context, windowAttrs);
|
||||||
|
}
|
||||||
|
|
||||||
private static Drawable createDefaultBackgroundDrawable() {
|
private static Drawable createDefaultBackgroundDrawable() {
|
||||||
return new ColorDrawable(getSystemBGColor());
|
return new ColorDrawable(getSystemBGColor());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Extract the window background color from {@code attrs}. */
|
/** Extract the window background color from {@code attrs}. */
|
||||||
public static int peekWindowBGColor(Context context, SplashScreenWindowAttrs attrs) {
|
private static int peekWindowBGColor(Context context, SplashScreenWindowAttrs attrs) {
|
||||||
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "peekWindowBGColor");
|
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "peekWindowBGColor");
|
||||||
final Drawable themeBGDrawable;
|
final Drawable themeBGDrawable;
|
||||||
if (attrs.mWindowBgColor != 0) {
|
if (attrs.mWindowBgColor != 0) {
|
||||||
@@ -255,7 +270,7 @@ public class SplashscreenContentDrawer {
|
|||||||
* Get the {@link SplashScreenWindowAttrs} from {@code context} and fill them into
|
* Get the {@link SplashScreenWindowAttrs} from {@code context} and fill them into
|
||||||
* {@code attrs}.
|
* {@code attrs}.
|
||||||
*/
|
*/
|
||||||
public static void getWindowAttrs(Context context, SplashScreenWindowAttrs attrs) {
|
private static void getWindowAttrs(Context context, SplashScreenWindowAttrs attrs) {
|
||||||
final TypedArray typedArray = context.obtainStyledAttributes(
|
final TypedArray typedArray = context.obtainStyledAttributes(
|
||||||
com.android.internal.R.styleable.Window);
|
com.android.internal.R.styleable.Window);
|
||||||
attrs.mWindowBgResId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0);
|
attrs.mWindowBgResId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0);
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package com.android.wm.shell.startingsurface;
|
package com.android.wm.shell.startingsurface;
|
||||||
|
|
||||||
|
import android.app.TaskInfo;
|
||||||
|
import android.graphics.Color;
|
||||||
/**
|
/**
|
||||||
* Interface to engage starting window feature.
|
* Interface to engage starting window feature.
|
||||||
*/
|
*/
|
||||||
@@ -27,4 +29,11 @@ public interface StartingSurface {
|
|||||||
default IStartingWindow createExternalInterface() {
|
default IStartingWindow createExternalInterface() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the background color for a starting window if existing.
|
||||||
|
*/
|
||||||
|
default int getBackgroundColor(TaskInfo taskInfo) {
|
||||||
|
return Color.BLACK;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,17 +26,22 @@ 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;
|
||||||
import android.app.ActivityTaskManager;
|
import android.app.ActivityTaskManager;
|
||||||
|
import android.app.ActivityThread;
|
||||||
|
import android.app.TaskInfo;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.ActivityInfo;
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.content.pm.IPackageManager;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
|
import android.graphics.Color;
|
||||||
import android.graphics.PixelFormat;
|
import android.graphics.PixelFormat;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
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;
|
||||||
|
import android.os.RemoteException;
|
||||||
import android.os.Trace;
|
import android.os.Trace;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
@@ -149,6 +154,12 @@ public class StartingSurfaceDrawer {
|
|||||||
return context.createDisplayContext(targetDisplay);
|
return context.createDisplayContext(targetDisplay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getSplashScreenTheme(int splashScreenThemeResId, ActivityInfo activityInfo) {
|
||||||
|
return splashScreenThemeResId != 0
|
||||||
|
? splashScreenThemeResId
|
||||||
|
: activityInfo.getThemeResource() != 0 ? activityInfo.getThemeResource()
|
||||||
|
: com.android.internal.R.style.Theme_DeviceDefault_DayNight;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Called when a task need a splash screen starting window.
|
* Called when a task need a splash screen starting window.
|
||||||
*
|
*
|
||||||
@@ -170,10 +181,7 @@ public class StartingSurfaceDrawer {
|
|||||||
final int taskId = taskInfo.taskId;
|
final int taskId = taskInfo.taskId;
|
||||||
Context context = mContext;
|
Context context = mContext;
|
||||||
// replace with the default theme if the application didn't set
|
// replace with the default theme if the application didn't set
|
||||||
final int theme = windowInfo.splashScreenThemeResId != 0
|
final int theme = getSplashScreenTheme(windowInfo.splashScreenThemeResId, activityInfo);
|
||||||
? windowInfo.splashScreenThemeResId
|
|
||||||
: activityInfo.getThemeResource() != 0 ? activityInfo.getThemeResource()
|
|
||||||
: 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
|
||||||
@@ -336,6 +344,10 @@ public class StartingSurfaceDrawer {
|
|||||||
// the window before first round relayoutWindow, which will happen after insets
|
// the window before first round relayoutWindow, which will happen after insets
|
||||||
// animation.
|
// animation.
|
||||||
mChoreographer.postCallback(CALLBACK_INSETS_ANIMATION, setViewSynchronized, null);
|
mChoreographer.postCallback(CALLBACK_INSETS_ANIMATION, setViewSynchronized, null);
|
||||||
|
// Block until we get the background color.
|
||||||
|
final StartingWindowRecord record = mStartingWindowRecords.get(taskId);
|
||||||
|
final SplashScreenView contentView = viewSupplier.get();
|
||||||
|
record.mBGColor = contentView.getInitBackgroundColor();
|
||||||
}
|
}
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
// don't crash if something else bad happens, for example a
|
// don't crash if something else bad happens, for example a
|
||||||
@@ -346,11 +358,11 @@ public class StartingSurfaceDrawer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int getStartingWindowBackgroundColorForTask(int taskId) {
|
int getStartingWindowBackgroundColorForTask(int taskId) {
|
||||||
StartingWindowRecord startingWindowRecord = mStartingWindowRecords.get(taskId);
|
final StartingWindowRecord startingWindowRecord = mStartingWindowRecords.get(taskId);
|
||||||
if (startingWindowRecord == null || startingWindowRecord.mContentView == null) {
|
if (startingWindowRecord == null) {
|
||||||
return 0;
|
return Color.TRANSPARENT;
|
||||||
}
|
}
|
||||||
return startingWindowRecord.mContentView.getInitBackgroundColor();
|
return startingWindowRecord.mBGColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class SplashScreenViewSupplier implements Supplier<SplashScreenView> {
|
private static class SplashScreenViewSupplier implements Supplier<SplashScreenView> {
|
||||||
@@ -378,6 +390,43 @@ public class StartingSurfaceDrawer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int estimateTaskBackgroundColor(TaskInfo taskInfo) {
|
||||||
|
if (taskInfo.topActivityInfo == null) {
|
||||||
|
return Color.TRANSPARENT;
|
||||||
|
}
|
||||||
|
final ActivityInfo activityInfo = taskInfo.topActivityInfo;
|
||||||
|
final String packageName = activityInfo.packageName;
|
||||||
|
final int userId = taskInfo.userId;
|
||||||
|
final Context windowContext;
|
||||||
|
try {
|
||||||
|
windowContext = mContext.createPackageContextAsUser(
|
||||||
|
packageName, Context.CONTEXT_RESTRICTED, UserHandle.of(userId));
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
Slog.w(TAG, "Failed creating package context with package name "
|
||||||
|
+ packageName + " for user " + taskInfo.userId, e);
|
||||||
|
return Color.TRANSPARENT;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
final IPackageManager packageManager = ActivityThread.getPackageManager();
|
||||||
|
final String splashScreenThemeName = packageManager.getSplashScreenTheme(packageName,
|
||||||
|
userId);
|
||||||
|
final int splashScreenThemeId = splashScreenThemeName != null
|
||||||
|
? windowContext.getResources().getIdentifier(splashScreenThemeName, null, null)
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
final int theme = getSplashScreenTheme(splashScreenThemeId, activityInfo);
|
||||||
|
|
||||||
|
if (theme != windowContext.getThemeResId()) {
|
||||||
|
windowContext.setTheme(theme);
|
||||||
|
}
|
||||||
|
return mSplashscreenContentDrawer.estimateTaskBackgroundColor(windowContext);
|
||||||
|
} catch (RuntimeException | RemoteException e) {
|
||||||
|
Slog.w(TAG, "failed get starting window background color at taskId: "
|
||||||
|
+ taskInfo.taskId, e);
|
||||||
|
}
|
||||||
|
return Color.TRANSPARENT;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when a task need a snapshot starting window.
|
* Called when a task need a snapshot starting window.
|
||||||
*/
|
*/
|
||||||
@@ -556,19 +605,16 @@ public class StartingSurfaceDrawer {
|
|||||||
private SplashScreenView mContentView;
|
private SplashScreenView mContentView;
|
||||||
private boolean mSetSplashScreen;
|
private boolean mSetSplashScreen;
|
||||||
private @StartingWindowType int mSuggestType;
|
private @StartingWindowType int mSuggestType;
|
||||||
|
private int mBGColor;
|
||||||
StartingWindowRecord(IBinder appToken, View decorView,
|
|
||||||
TaskSnapshotWindow taskSnapshotWindow) {
|
|
||||||
mAppToken = appToken;
|
|
||||||
mDecorView = decorView;
|
|
||||||
mTaskSnapshotWindow = taskSnapshotWindow;
|
|
||||||
}
|
|
||||||
|
|
||||||
StartingWindowRecord(IBinder appToken, View decorView,
|
StartingWindowRecord(IBinder appToken, View decorView,
|
||||||
TaskSnapshotWindow taskSnapshotWindow, @StartingWindowType int suggestType) {
|
TaskSnapshotWindow taskSnapshotWindow, @StartingWindowType int suggestType) {
|
||||||
mAppToken = appToken;
|
mAppToken = appToken;
|
||||||
mDecorView = decorView;
|
mDecorView = decorView;
|
||||||
mTaskSnapshotWindow = taskSnapshotWindow;
|
mTaskSnapshotWindow = taskSnapshotWindow;
|
||||||
|
if (mTaskSnapshotWindow != null) {
|
||||||
|
mBGColor = mTaskSnapshotWindow.getBackgroundColor();
|
||||||
|
}
|
||||||
mSuggestType = suggestType;
|
mSuggestType = suggestType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,18 +18,23 @@ 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_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_SNAPSHOT;
|
||||||
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
|
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
|
||||||
|
|
||||||
import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
|
import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
|
||||||
|
|
||||||
import android.app.ActivityManager.RunningTaskInfo;
|
import android.app.ActivityManager.RunningTaskInfo;
|
||||||
|
import android.app.TaskInfo;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.Color;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.Trace;
|
import android.os.Trace;
|
||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
|
import android.util.SparseIntArray;
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
import android.window.StartingWindowInfo;
|
import android.window.StartingWindowInfo;
|
||||||
import android.window.StartingWindowInfo.StartingWindowType;
|
import android.window.StartingWindowInfo.StartingWindowType;
|
||||||
@@ -38,6 +43,7 @@ import android.window.TaskSnapshot;
|
|||||||
|
|
||||||
import androidx.annotation.BinderThread;
|
import androidx.annotation.BinderThread;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.GuardedBy;
|
||||||
import com.android.internal.util.function.TriConsumer;
|
import com.android.internal.util.function.TriConsumer;
|
||||||
import com.android.wm.shell.common.RemoteCallable;
|
import com.android.wm.shell.common.RemoteCallable;
|
||||||
import com.android.wm.shell.common.ShellExecutor;
|
import com.android.wm.shell.common.ShellExecutor;
|
||||||
@@ -62,10 +68,11 @@ import com.android.wm.shell.common.TransactionPool;
|
|||||||
public class StartingWindowController implements RemoteCallable<StartingWindowController> {
|
public class StartingWindowController implements RemoteCallable<StartingWindowController> {
|
||||||
private static final String TAG = StartingWindowController.class.getSimpleName();
|
private static final String TAG = StartingWindowController.class.getSimpleName();
|
||||||
|
|
||||||
// TODO b/183150443 Keep this flag open for a while, several things might need to adjust.
|
public static final boolean DEBUG_SPLASH_SCREEN = Build.isDebuggable();
|
||||||
public static final boolean DEBUG_SPLASH_SCREEN = true;
|
|
||||||
public static final boolean DEBUG_TASK_SNAPSHOT = false;
|
public static final boolean DEBUG_TASK_SNAPSHOT = false;
|
||||||
|
|
||||||
|
private static final long TASK_BG_COLOR_RETAIN_TIME_MS = 5000;
|
||||||
|
|
||||||
private final StartingSurfaceDrawer mStartingSurfaceDrawer;
|
private final StartingSurfaceDrawer mStartingSurfaceDrawer;
|
||||||
private final StartingWindowTypeAlgorithm mStartingWindowTypeAlgorithm;
|
private final StartingWindowTypeAlgorithm mStartingWindowTypeAlgorithm;
|
||||||
|
|
||||||
@@ -73,6 +80,11 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo
|
|||||||
private final StartingSurfaceImpl mImpl = new StartingSurfaceImpl();
|
private final StartingSurfaceImpl mImpl = new StartingSurfaceImpl();
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final ShellExecutor mSplashScreenExecutor;
|
private final ShellExecutor mSplashScreenExecutor;
|
||||||
|
/**
|
||||||
|
* Need guarded because it has exposed to StartingSurface
|
||||||
|
*/
|
||||||
|
@GuardedBy("mTaskBackgroundColors")
|
||||||
|
private final SparseIntArray mTaskBackgroundColors = new SparseIntArray();
|
||||||
|
|
||||||
public StartingWindowController(Context context, ShellExecutor splashScreenExecutor,
|
public StartingWindowController(Context context, ShellExecutor splashScreenExecutor,
|
||||||
StartingWindowTypeAlgorithm startingWindowTypeAlgorithm, TransactionPool pool) {
|
StartingWindowTypeAlgorithm startingWindowTypeAlgorithm, TransactionPool pool) {
|
||||||
@@ -125,13 +137,19 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo
|
|||||||
final TaskSnapshot snapshot = windowInfo.mTaskSnapshot;
|
final TaskSnapshot snapshot = windowInfo.mTaskSnapshot;
|
||||||
mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, appToken,
|
mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, appToken,
|
||||||
snapshot);
|
snapshot);
|
||||||
} else /* suggestionType == STARTING_WINDOW_TYPE_NONE */ {
|
|
||||||
// Don't add a staring window.
|
|
||||||
}
|
}
|
||||||
if (mTaskLaunchingCallback != null && isSplashScreenType(suggestionType)) {
|
if (suggestionType != STARTING_WINDOW_TYPE_NONE) {
|
||||||
int taskId = runningTaskInfo.taskId;
|
int taskId = runningTaskInfo.taskId;
|
||||||
int color = mStartingSurfaceDrawer.getStartingWindowBackgroundColorForTask(taskId);
|
int color = mStartingSurfaceDrawer
|
||||||
mTaskLaunchingCallback.accept(taskId, suggestionType, color);
|
.getStartingWindowBackgroundColorForTask(taskId);
|
||||||
|
if (color != Color.TRANSPARENT) {
|
||||||
|
synchronized (mTaskBackgroundColors) {
|
||||||
|
mTaskBackgroundColors.append(taskId, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mTaskLaunchingCallback != null && isSplashScreenType(suggestionType)) {
|
||||||
|
mTaskLaunchingCallback.accept(taskId, suggestionType, color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
|
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
|
||||||
@@ -163,9 +181,13 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo
|
|||||||
*/
|
*/
|
||||||
public void removeStartingWindow(int taskId, SurfaceControl leash, Rect frame,
|
public void removeStartingWindow(int taskId, SurfaceControl leash, Rect frame,
|
||||||
boolean playRevealAnimation) {
|
boolean playRevealAnimation) {
|
||||||
mSplashScreenExecutor.execute(() -> {
|
mSplashScreenExecutor.execute(() -> mStartingSurfaceDrawer.removeStartingWindow(
|
||||||
mStartingSurfaceDrawer.removeStartingWindow(taskId, leash, frame, playRevealAnimation);
|
taskId, leash, frame, playRevealAnimation));
|
||||||
});
|
mSplashScreenExecutor.executeDelayed(() -> {
|
||||||
|
synchronized (mTaskBackgroundColors) {
|
||||||
|
mTaskBackgroundColors.delete(taskId);
|
||||||
|
}
|
||||||
|
}, TASK_BG_COLOR_RETAIN_TIME_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -182,6 +204,19 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo
|
|||||||
mIStartingWindow = new IStartingWindowImpl(StartingWindowController.this);
|
mIStartingWindow = new IStartingWindowImpl(StartingWindowController.this);
|
||||||
return mIStartingWindow;
|
return mIStartingWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBackgroundColor(TaskInfo taskInfo) {
|
||||||
|
synchronized (mTaskBackgroundColors) {
|
||||||
|
final int index = mTaskBackgroundColors.indexOfKey(taskInfo.taskId);
|
||||||
|
if (index >= 0) {
|
||||||
|
return mTaskBackgroundColors.valueAt(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final int color = mStartingSurfaceDrawer.estimateTaskBackgroundColor(taskInfo);
|
||||||
|
return color != Color.TRANSPARENT
|
||||||
|
? color : SplashscreenContentDrawer.getSystemBGColor();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -283,6 +283,10 @@ public class TaskSnapshotWindow {
|
|||||||
mClearWindowHandler = clearWindowHandler;
|
mClearWindowHandler = clearWindowHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getBackgroundColor() {
|
||||||
|
return mBackgroundPaint.getColor();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ask system bar background painter to draw status bar background.
|
* Ask system bar background painter to draw status bar background.
|
||||||
* @hide
|
* @hide
|
||||||
|
|||||||
@@ -97,7 +97,8 @@ public class StartingSurfaceDrawerTests {
|
|||||||
// listen for addView
|
// listen for addView
|
||||||
mAddWindowForTask = taskId;
|
mAddWindowForTask = taskId;
|
||||||
mViewThemeResId = view.getContext().getThemeResId();
|
mViewThemeResId = view.getContext().getThemeResId();
|
||||||
return true;
|
// Do not wait for background color
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import android.graphics.RectF
|
|||||||
import android.graphics.drawable.GradientDrawable
|
import android.graphics.drawable.GradientDrawable
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.os.RemoteException
|
import android.os.RemoteException
|
||||||
import android.os.UserHandle
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.util.MathUtils
|
import android.util.MathUtils
|
||||||
import android.view.IRemoteAnimationFinishedCallback
|
import android.view.IRemoteAnimationFinishedCallback
|
||||||
@@ -32,7 +31,7 @@ import android.view.animation.PathInterpolator
|
|||||||
import com.android.internal.annotations.VisibleForTesting
|
import com.android.internal.annotations.VisibleForTesting
|
||||||
import com.android.internal.policy.ScreenDecorationsUtils
|
import com.android.internal.policy.ScreenDecorationsUtils
|
||||||
import com.android.wm.shell.startingsurface.SplashscreenContentDrawer
|
import com.android.wm.shell.startingsurface.SplashscreenContentDrawer
|
||||||
import com.android.wm.shell.startingsurface.SplashscreenContentDrawer.SplashScreenWindowAttrs
|
import com.android.wm.shell.startingsurface.StartingSurface
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,6 +40,7 @@ import kotlin.math.roundToInt
|
|||||||
*/
|
*/
|
||||||
class ActivityLaunchAnimator(
|
class ActivityLaunchAnimator(
|
||||||
private val keyguardHandler: KeyguardHandler,
|
private val keyguardHandler: KeyguardHandler,
|
||||||
|
private val startingSurface: StartingSurface?,
|
||||||
context: Context
|
context: Context
|
||||||
) {
|
) {
|
||||||
private val TAG = this::class.java.simpleName
|
private val TAG = this::class.java.simpleName
|
||||||
@@ -474,7 +474,12 @@ class ActivityLaunchAnimator(
|
|||||||
// which is usually the same color of the app background. We first fade in this layer
|
// which is usually the same color of the app background. We first fade in this layer
|
||||||
// to hide the expanding view, then we fade it out with SRC mode to draw a hole in the
|
// to hide the expanding view, then we fade it out with SRC mode to draw a hole in the
|
||||||
// launch container and reveal the opening window.
|
// launch container and reveal the opening window.
|
||||||
val windowBackgroundColor = extractSplashScreenBackgroundColor(window)
|
val windowBackgroundColor = if (startingSurface != null) {
|
||||||
|
startingSurface.getBackgroundColor(window.taskInfo)
|
||||||
|
} else {
|
||||||
|
Log.w(TAG, "No starting surface, defaulting to SystemBGColor")
|
||||||
|
SplashscreenContentDrawer.getSystemBGColor()
|
||||||
|
}
|
||||||
val windowBackgroundLayer = GradientDrawable().apply {
|
val windowBackgroundLayer = GradientDrawable().apply {
|
||||||
setColor(windowBackgroundColor)
|
setColor(windowBackgroundColor)
|
||||||
alpha = 0
|
alpha = 0
|
||||||
@@ -553,36 +558,6 @@ class ActivityLaunchAnimator(
|
|||||||
animator.start()
|
animator.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Extract the background color of the app splash screen. */
|
|
||||||
private fun extractSplashScreenBackgroundColor(window: RemoteAnimationTarget): Int {
|
|
||||||
val taskInfo = window.taskInfo
|
|
||||||
val windowPackage = taskInfo.topActivity.packageName
|
|
||||||
val userId = taskInfo.userId
|
|
||||||
val windowContext = context.createPackageContextAsUser(
|
|
||||||
windowPackage, Context.CONTEXT_RESTRICTED, UserHandle.of(userId))
|
|
||||||
val activityInfo = taskInfo.topActivityInfo
|
|
||||||
val splashScreenThemeName = packageManager.getSplashScreenTheme(windowPackage, userId)
|
|
||||||
val splashScreenThemeId = if (splashScreenThemeName != null) {
|
|
||||||
windowContext.resources.getIdentifier(splashScreenThemeName, null, null)
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
val themeResId = when {
|
|
||||||
splashScreenThemeId != 0 -> splashScreenThemeId
|
|
||||||
activityInfo.themeResource != 0 -> activityInfo.themeResource
|
|
||||||
else -> com.android.internal.R.style.Theme_DeviceDefault_DayNight
|
|
||||||
}
|
|
||||||
|
|
||||||
if (themeResId != windowContext.themeResId) {
|
|
||||||
windowContext.setTheme(themeResId)
|
|
||||||
}
|
|
||||||
|
|
||||||
val windowAttrs = SplashScreenWindowAttrs()
|
|
||||||
SplashscreenContentDrawer.getWindowAttrs(windowContext, windowAttrs)
|
|
||||||
return SplashscreenContentDrawer.peekWindowBGColor(windowContext, windowAttrs)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun applyStateToWindow(window: RemoteAnimationTarget, state: State) {
|
private fun applyStateToWindow(window: RemoteAnimationTarget, state: State) {
|
||||||
val screenBounds = window.screenSpaceBounds
|
val screenBounds = window.screenSpaceBounds
|
||||||
val centerX = (screenBounds.left + screenBounds.right) / 2f
|
val centerX = (screenBounds.left + screenBounds.right) / 2f
|
||||||
|
|||||||
@@ -247,6 +247,7 @@ import com.android.systemui.volume.VolumeComponent;
|
|||||||
import com.android.systemui.wmshell.BubblesManager;
|
import com.android.systemui.wmshell.BubblesManager;
|
||||||
import com.android.wm.shell.bubbles.Bubbles;
|
import com.android.wm.shell.bubbles.Bubbles;
|
||||||
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
|
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
|
||||||
|
import com.android.wm.shell.startingsurface.StartingSurface;
|
||||||
|
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
@@ -703,6 +704,7 @@ public class StatusBar extends SystemUI implements DemoMode,
|
|||||||
private final Optional<BubblesManager> mBubblesManagerOptional;
|
private final Optional<BubblesManager> mBubblesManagerOptional;
|
||||||
private final Optional<Bubbles> mBubblesOptional;
|
private final Optional<Bubbles> mBubblesOptional;
|
||||||
private final Bubbles.BubbleExpandListener mBubbleExpandListener;
|
private final Bubbles.BubbleExpandListener mBubbleExpandListener;
|
||||||
|
private final Optional<StartingSurface> mStartingSurfaceOptional;
|
||||||
|
|
||||||
private ActivityIntentHelper mActivityIntentHelper;
|
private ActivityIntentHelper mActivityIntentHelper;
|
||||||
private NotificationStackScrollLayoutController mStackScrollerController;
|
private NotificationStackScrollLayoutController mStackScrollerController;
|
||||||
@@ -802,7 +804,8 @@ public class StatusBar extends SystemUI implements DemoMode,
|
|||||||
LockscreenShadeTransitionController lockscreenShadeTransitionController,
|
LockscreenShadeTransitionController lockscreenShadeTransitionController,
|
||||||
FeatureFlags featureFlags,
|
FeatureFlags featureFlags,
|
||||||
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
|
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
|
||||||
UnlockedScreenOffAnimationController unlockedScreenOffAnimationController) {
|
UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
|
||||||
|
Optional<StartingSurface> startingSurfaceOptional) {
|
||||||
super(context);
|
super(context);
|
||||||
mNotificationsController = notificationsController;
|
mNotificationsController = notificationsController;
|
||||||
mLightBarController = lightBarController;
|
mLightBarController = lightBarController;
|
||||||
@@ -889,6 +892,7 @@ public class StatusBar extends SystemUI implements DemoMode,
|
|||||||
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
|
mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
|
||||||
|
|
||||||
mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
|
mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
|
||||||
|
mStartingSurfaceOptional = startingSurfaceOptional;
|
||||||
lockscreenShadeTransitionController.setStatusbar(this);
|
lockscreenShadeTransitionController.setStatusbar(this);
|
||||||
|
|
||||||
mExpansionChangedListeners = new ArrayList<>();
|
mExpansionChangedListeners = new ArrayList<>();
|
||||||
@@ -1417,7 +1421,9 @@ public class StatusBar extends SystemUI implements DemoMode,
|
|||||||
|
|
||||||
private void setUpPresenter() {
|
private void setUpPresenter() {
|
||||||
// Set up the initial notification state.
|
// Set up the initial notification state.
|
||||||
mActivityLaunchAnimator = new ActivityLaunchAnimator(this, mContext);
|
mActivityLaunchAnimator = new ActivityLaunchAnimator(this,
|
||||||
|
mStartingSurfaceOptional.orElse(null),
|
||||||
|
mContext);
|
||||||
mNotificationAnimationProvider = new NotificationLaunchAnimatorControllerProvider(
|
mNotificationAnimationProvider = new NotificationLaunchAnimatorControllerProvider(
|
||||||
mNotificationShadeWindowViewController,
|
mNotificationShadeWindowViewController,
|
||||||
mStackScrollerController.getNotificationListContainer(),
|
mStackScrollerController.getNotificationListContainer(),
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ import com.android.systemui.volume.VolumeComponent;
|
|||||||
import com.android.systemui.wmshell.BubblesManager;
|
import com.android.systemui.wmshell.BubblesManager;
|
||||||
import com.android.wm.shell.bubbles.Bubbles;
|
import com.android.wm.shell.bubbles.Bubbles;
|
||||||
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
|
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
|
||||||
|
import com.android.wm.shell.startingsurface.StartingSurface;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
@@ -218,7 +219,8 @@ public interface StatusBarPhoneModule {
|
|||||||
LockscreenShadeTransitionController transitionController,
|
LockscreenShadeTransitionController transitionController,
|
||||||
FeatureFlags featureFlags,
|
FeatureFlags featureFlags,
|
||||||
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
|
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
|
||||||
UnlockedScreenOffAnimationController unlockedScreenOffAnimationController) {
|
UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
|
||||||
|
Optional<StartingSurface> startingSurfaceOptional) {
|
||||||
return new StatusBar(
|
return new StatusBar(
|
||||||
context,
|
context,
|
||||||
notificationsController,
|
notificationsController,
|
||||||
@@ -306,6 +308,7 @@ public interface StatusBarPhoneModule {
|
|||||||
transitionController,
|
transitionController,
|
||||||
featureFlags,
|
featureFlags,
|
||||||
keyguardUnlockAnimationController,
|
keyguardUnlockAnimationController,
|
||||||
unlockedScreenOffAnimationController);
|
unlockedScreenOffAnimationController,
|
||||||
|
startingSurfaceOptional);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import androidx.test.filters.SmallTest
|
|||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
import com.android.systemui.util.mockito.any
|
import com.android.systemui.util.mockito.any
|
||||||
import com.android.systemui.util.mockito.eq
|
import com.android.systemui.util.mockito.eq
|
||||||
|
import com.android.wm.shell.startingsurface.StartingSurface
|
||||||
import junit.framework.Assert.assertFalse
|
import junit.framework.Assert.assertFalse
|
||||||
import junit.framework.Assert.assertNotNull
|
import junit.framework.Assert.assertNotNull
|
||||||
import junit.framework.Assert.assertNull
|
import junit.framework.Assert.assertNull
|
||||||
@@ -47,13 +48,14 @@ class ActivityLaunchAnimatorTest : SysuiTestCase() {
|
|||||||
@Mock lateinit var keyguardHandler: ActivityLaunchAnimator.KeyguardHandler
|
@Mock lateinit var keyguardHandler: ActivityLaunchAnimator.KeyguardHandler
|
||||||
@Spy private val controller = TestLaunchAnimatorController(launchContainer)
|
@Spy private val controller = TestLaunchAnimatorController(launchContainer)
|
||||||
@Mock lateinit var iCallback: IRemoteAnimationFinishedCallback
|
@Mock lateinit var iCallback: IRemoteAnimationFinishedCallback
|
||||||
|
@Mock lateinit var startingSurface: StartingSurface
|
||||||
|
|
||||||
private lateinit var activityLaunchAnimator: ActivityLaunchAnimator
|
private lateinit var activityLaunchAnimator: ActivityLaunchAnimator
|
||||||
@get:Rule val rule = MockitoJUnit.rule()
|
@get:Rule val rule = MockitoJUnit.rule()
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setup() {
|
fun setup() {
|
||||||
activityLaunchAnimator = ActivityLaunchAnimator(keyguardHandler, mContext)
|
activityLaunchAnimator = ActivityLaunchAnimator(keyguardHandler, startingSurface, mContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startIntentWithAnimation(
|
private fun startIntentWithAnimation(
|
||||||
@@ -117,7 +119,7 @@ class ActivityLaunchAnimatorTest : SysuiTestCase() {
|
|||||||
@Test
|
@Test
|
||||||
fun animatesIfActivityIsAlreadyOpenAndIsOnKeyguard() {
|
fun animatesIfActivityIsAlreadyOpenAndIsOnKeyguard() {
|
||||||
`when`(keyguardHandler.isOnKeyguard()).thenReturn(true)
|
`when`(keyguardHandler.isOnKeyguard()).thenReturn(true)
|
||||||
val animator = ActivityLaunchAnimator(keyguardHandler, context)
|
val animator = ActivityLaunchAnimator(keyguardHandler, startingSurface, context)
|
||||||
|
|
||||||
val willAnimateCaptor = ArgumentCaptor.forClass(Boolean::class.java)
|
val willAnimateCaptor = ArgumentCaptor.forClass(Boolean::class.java)
|
||||||
var animationAdapter: RemoteAnimationAdapter? = null
|
var animationAdapter: RemoteAnimationAdapter? = null
|
||||||
|
|||||||
@@ -152,6 +152,7 @@ import com.android.systemui.volume.VolumeComponent;
|
|||||||
import com.android.systemui.wmshell.BubblesManager;
|
import com.android.systemui.wmshell.BubblesManager;
|
||||||
import com.android.wm.shell.bubbles.Bubbles;
|
import com.android.wm.shell.bubbles.Bubbles;
|
||||||
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
|
import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
|
||||||
|
import com.android.wm.shell.startingsurface.StartingSurface;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -273,6 +274,7 @@ public class StatusBarTest extends SysuiTestCase {
|
|||||||
@Mock private IWallpaperManager mWallpaperManager;
|
@Mock private IWallpaperManager mWallpaperManager;
|
||||||
@Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
|
@Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
|
||||||
@Mock private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
|
@Mock private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
|
||||||
|
@Mock private StartingSurface mStartingSurface;
|
||||||
private ShadeController mShadeController;
|
private ShadeController mShadeController;
|
||||||
private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
|
private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
|
||||||
private InitController mInitController = new InitController();
|
private InitController mInitController = new InitController();
|
||||||
@@ -443,7 +445,8 @@ public class StatusBarTest extends SysuiTestCase {
|
|||||||
mLockscreenTransitionController,
|
mLockscreenTransitionController,
|
||||||
mFeatureFlags,
|
mFeatureFlags,
|
||||||
mKeyguardUnlockAnimationController,
|
mKeyguardUnlockAnimationController,
|
||||||
mUnlockedScreenOffAnimationController);
|
mUnlockedScreenOffAnimationController,
|
||||||
|
Optional.of(mStartingSurface));
|
||||||
when(mKeyguardViewMediator.registerStatusBar(any(StatusBar.class), any(ViewGroup.class),
|
when(mKeyguardViewMediator.registerStatusBar(any(StatusBar.class), any(ViewGroup.class),
|
||||||
any(NotificationPanelViewController.class), any(BiometricUnlockController.class),
|
any(NotificationPanelViewController.class), any(BiometricUnlockController.class),
|
||||||
any(ViewGroup.class), any(KeyguardBypassController.class)))
|
any(ViewGroup.class), any(KeyguardBypassController.class)))
|
||||||
|
|||||||
Reference in New Issue
Block a user