summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
author wilsonshih <wilsonshih@google.com> 2021-06-17 20:10:42 +0800
committer wilsonshih <wilsonshih@google.com> 2021-07-13 18:53:19 +0800
commit3be521ad485453c144e94309d718b2701b47cf17 (patch)
tree754cb5555cd1568763b9b65d695d61398926f4d9 /libs
parenta70e4ce80a26e7525ab58efe77ab6cbb8cfe50bf (diff)
Get starting window background color directly.
SystemUI does not need to re-calculate background color of starting window because Shell library is bound to SystemUI, so status bar can get background color directly, also this can support to get the background color from snapshot starting window. Also fix the starting window listener did not receiveing background color successful because makeSplashScreenContentView is execute on another background thread, so there should block the splash screen thread until the background color is estimated. Bug: 192213918 Bug: 192659309 Test: manual launch apps from Notification and Launcher, ensure the color is correctly send to SystemUI or Launcher. Change-Id: I626cb23d7aebfe4e032fad285bfad374c0e11cea
Diffstat (limited to 'libs')
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java29
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java9
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java76
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java55
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java4
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java3
6 files changed, 143 insertions, 33 deletions
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 75dd561ffc61..107a3f880354 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
@@ -127,11 +127,13 @@ public class SplashscreenContentDrawer {
* parallel.
*
* @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.
+ * @param splashScreenViewConsumer Receiving the SplashScreenView object, which will also be
+ * 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,
- int taskId, Consumer<SplashScreenView> consumer) {
+ int taskId, Consumer<SplashScreenView> splashScreenViewConsumer) {
mSplashscreenWorkerHandler.post(() -> {
SplashScreenView contentView;
try {
@@ -143,7 +145,7 @@ public class SplashscreenContentDrawer {
+ taskId, e);
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);
}
- private static int getSystemBGColor() {
+ /**
+ * @return Current system background color.
+ */
+ public static int getSystemBGColor() {
final Context systemContext = ActivityThread.currentApplication();
if (systemContext == null) {
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);
}
+ /**
+ * 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() {
return new ColorDrawable(getSystemBGColor());
}
/** 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");
final Drawable themeBGDrawable;
if (attrs.mWindowBgColor != 0) {
@@ -255,7 +270,7 @@ public class SplashscreenContentDrawer {
* Get the {@link SplashScreenWindowAttrs} from {@code context} and fill them into
* {@code attrs}.
*/
- public static void getWindowAttrs(Context context, SplashScreenWindowAttrs attrs) {
+ private static void getWindowAttrs(Context context, SplashScreenWindowAttrs attrs) {
final TypedArray typedArray = context.obtainStyledAttributes(
com.android.internal.R.styleable.Window);
attrs.mWindowBgResId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java
index 079d68973852..01c9b6630fa6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurface.java
@@ -16,6 +16,8 @@
package com.android.wm.shell.startingsurface;
+import android.app.TaskInfo;
+import android.graphics.Color;
/**
* Interface to engage starting window feature.
*/
@@ -27,4 +29,11 @@ public interface StartingSurface {
default IStartingWindow createExternalInterface() {
return null;
}
+
+ /**
+ * Returns the background color for a starting window if existing.
+ */
+ default int getBackgroundColor(TaskInfo taskInfo) {
+ return Color.BLACK;
+ }
}
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 4dc5447cbe65..243751fe13e8 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
@@ -26,17 +26,22 @@ import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SNAPSHOT;
import android.annotation.Nullable;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.ActivityTaskManager;
+import android.app.ActivityThread;
+import android.app.TaskInfo;
import android.content.Context;
import android.content.pm.ActivityInfo;
+import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
+import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.os.IBinder;
import android.os.RemoteCallback;
+import android.os.RemoteException;
import android.os.Trace;
import android.os.UserHandle;
import android.util.Slog;
@@ -149,6 +154,12 @@ public class StartingSurfaceDrawer {
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.
*
@@ -170,10 +181,7 @@ public class StartingSurfaceDrawer {
final int taskId = taskInfo.taskId;
Context context = mContext;
// replace with the default theme if the application didn't set
- final int theme = windowInfo.splashScreenThemeResId != 0
- ? windowInfo.splashScreenThemeResId
- : activityInfo.getThemeResource() != 0 ? activityInfo.getThemeResource()
- : com.android.internal.R.style.Theme_DeviceDefault_DayNight;
+ final int theme = getSplashScreenTheme(windowInfo.splashScreenThemeResId, activityInfo);
if (DEBUG_SPLASH_SCREEN) {
Slog.d(TAG, "addSplashScreen " + activityInfo.packageName
+ " 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
// animation.
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) {
// don't crash if something else bad happens, for example a
@@ -346,11 +358,11 @@ public class StartingSurfaceDrawer {
}
int getStartingWindowBackgroundColorForTask(int taskId) {
- StartingWindowRecord startingWindowRecord = mStartingWindowRecords.get(taskId);
- if (startingWindowRecord == null || startingWindowRecord.mContentView == null) {
- return 0;
+ final StartingWindowRecord startingWindowRecord = mStartingWindowRecords.get(taskId);
+ if (startingWindowRecord == null) {
+ return Color.TRANSPARENT;
}
- return startingWindowRecord.mContentView.getInitBackgroundColor();
+ return startingWindowRecord.mBGColor;
}
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.
*/
@@ -556,19 +605,16 @@ public class StartingSurfaceDrawer {
private SplashScreenView mContentView;
private boolean mSetSplashScreen;
private @StartingWindowType int mSuggestType;
-
- StartingWindowRecord(IBinder appToken, View decorView,
- TaskSnapshotWindow taskSnapshotWindow) {
- mAppToken = appToken;
- mDecorView = decorView;
- mTaskSnapshotWindow = taskSnapshotWindow;
- }
+ private int mBGColor;
StartingWindowRecord(IBinder appToken, View decorView,
TaskSnapshotWindow taskSnapshotWindow, @StartingWindowType int suggestType) {
mAppToken = appToken;
mDecorView = decorView;
mTaskSnapshotWindow = taskSnapshotWindow;
+ if (mTaskSnapshotWindow != null) {
+ mBGColor = mTaskSnapshotWindow.getBackgroundColor();
+ }
mSuggestType = suggestType;
}
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 eaa89d8e3ab5..e84d498a9258 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
@@ -18,18 +18,23 @@ 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_NONE;
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SNAPSHOT;
import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
import android.app.ActivityManager.RunningTaskInfo;
+import android.app.TaskInfo;
import android.content.Context;
+import android.graphics.Color;
import android.graphics.Rect;
+import android.os.Build;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.Trace;
import android.util.Slog;
+import android.util.SparseIntArray;
import android.view.SurfaceControl;
import android.window.StartingWindowInfo;
import android.window.StartingWindowInfo.StartingWindowType;
@@ -38,6 +43,7 @@ import android.window.TaskSnapshot;
import androidx.annotation.BinderThread;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.function.TriConsumer;
import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
@@ -62,10 +68,11 @@ import com.android.wm.shell.common.TransactionPool;
public class StartingWindowController implements RemoteCallable<StartingWindowController> {
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 = true;
+ public static final boolean DEBUG_SPLASH_SCREEN = Build.isDebuggable();
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 StartingWindowTypeAlgorithm mStartingWindowTypeAlgorithm;
@@ -73,6 +80,11 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo
private final StartingSurfaceImpl mImpl = new StartingSurfaceImpl();
private final Context mContext;
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,
StartingWindowTypeAlgorithm startingWindowTypeAlgorithm, TransactionPool pool) {
@@ -125,13 +137,19 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo
final TaskSnapshot snapshot = windowInfo.mTaskSnapshot;
mStartingSurfaceDrawer.makeTaskSnapshotWindow(windowInfo, appToken,
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 color = mStartingSurfaceDrawer.getStartingWindowBackgroundColorForTask(taskId);
- mTaskLaunchingCallback.accept(taskId, suggestionType, color);
+ int color = mStartingSurfaceDrawer
+ .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);
@@ -163,9 +181,13 @@ public class StartingWindowController implements RemoteCallable<StartingWindowCo
*/
public void removeStartingWindow(int taskId, SurfaceControl leash, Rect frame,
boolean playRevealAnimation) {
- mSplashScreenExecutor.execute(() -> {
- mStartingSurfaceDrawer.removeStartingWindow(taskId, leash, frame, playRevealAnimation);
- });
+ mSplashScreenExecutor.execute(() -> mStartingSurfaceDrawer.removeStartingWindow(
+ 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);
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();
+ }
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
index 382d5806e3c2..6052d3dee891 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
@@ -283,6 +283,10 @@ public class TaskSnapshotWindow {
mClearWindowHandler = clearWindowHandler;
}
+ int getBackgroundColor() {
+ return mBackgroundPaint.getColor();
+ }
+
/**
* Ask system bar background painter to draw status bar background.
* @hide
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 5061b2369bb2..284f384a3d26 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
@@ -97,7 +97,8 @@ public class StartingSurfaceDrawerTests {
// listen for addView
mAddWindowForTask = taskId;
mViewThemeResId = view.getContext().getThemeResId();
- return true;
+ // Do not wait for background color
+ return false;
}
@Override