diff options
| author | 2024-02-16 12:32:04 +0000 | |
|---|---|---|
| committer | 2024-02-16 12:32:04 +0000 | |
| commit | 09d220d2254b3d3b74d13d266d621c1664475da2 (patch) | |
| tree | 2733a50fe41301bbec56cbaa378dd9f7876f06c9 | |
| parent | 4ad990402ef4df33a1ad20fb8fae88471091c13a (diff) | |
| parent | d29beae786a1af05509828a572ced4d722ca71da (diff) | |
Merge "Expose RRO completion signal" into udc-qpr-dev
12 files changed, 218 insertions, 57 deletions
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 66d04a3132eb..42e0e2df053f 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -5717,6 +5717,25 @@ public class ActivityManager { } /** + * Used by ThemeOverlayController to notify when color + * palette is ready. + * + * @param userId The ID of the user where ThemeOverlayController is ready. + * + * @throws RemoteException + * + * @hide + */ + @RequiresPermission(Manifest.permission.SET_THEME_OVERLAY_CONTROLLER_READY) + public void setThemeOverlayReady(@UserIdInt int userId) { + try { + getService().setThemeOverlayReady(userId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Resets the state of the {@link com.android.server.am.AppErrors} instance. * This is intended for use with CTS only. * @hide diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 32c40df32585..384d7db1aadb 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -1234,4 +1234,11 @@ public abstract class ActivityManagerInternal { */ public abstract boolean clearApplicationUserData(String packageName, boolean keepState, boolean isRestore, IPackageDataObserver observer, int userId); + + /** + * Returns current state of {@link com.android.systemui.theme.ThemeOverlayController} color + * palette readiness. + * @hide + */ + public abstract boolean isThemeOverlayReady(int userId); } diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index 37616e7d76af..30dd3741147e 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -550,6 +550,17 @@ interface IActivityManager { @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) boolean isTopOfTask(in IBinder token); void bootAnimationComplete(); + + /** + * Used by {@link com.android.systemui.theme.ThemeOverlayController} to notify when color + * palette is ready. + * + * @param userId The ID of the user where ThemeOverlayController is ready. + * + * @throws RemoteException + */ + void setThemeOverlayReady(int userId); + @UnsupportedAppUsage void registerTaskStackListener(in ITaskStackListener listener); void unregisterTaskStackListener(in ITaskStackListener listener); diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index cbb6e74bd1ce..fbe678f860fd 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -7302,6 +7302,11 @@ <permission android:name="android.permission.RESET_APP_ERRORS" android:protectionLevel="signature" /> + <!-- @hide Allows ThemeOverlayController to delay launch of Home / SetupWizard on boot, ensuring + Theme Palettes and Colors are ready --> + <permission android:name="android.permission.SET_THEME_OVERLAY_CONTROLLER_READY" + android:protectionLevel="signature|setup" /> + <!-- @hide Allows an application to create/destroy input consumer. --> <permission android:name="android.permission.INPUT_CONSUMER" android:protectionLevel="signature" /> diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 4fd47232a0df..2d9b1eee7165 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -256,6 +256,9 @@ <uses-permission android:name="android.permission.MODIFY_THEME_OVERLAY" /> + <!-- Activity Manager --> + <uses-permission android:name="android.permission.SET_THEME_OVERLAY_CONTROLLER_READY" /> + <!-- accessibility --> <uses-permission android:name="android.permission.MODIFY_ACCESSIBILITY_DATA" /> <uses-permission android:name="android.permission.MANAGE_ACCESSIBILITY" /> diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java index 3376e232e035..91df866c44db 100644 --- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java +++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java @@ -32,6 +32,7 @@ import androidx.annotation.VisibleForTesting; import com.android.systemui.Dumpable; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dump.DumpManager; import com.google.android.collect.Lists; @@ -142,6 +143,7 @@ public class ThemeOverlayApplier implements Dumpable { private final Map<String, String> mCategoryToTargetPackage = new ArrayMap<>(); private final OverlayManager mOverlayManager; private final Executor mBgExecutor; + private final Executor mMainExecutor; private final String mLauncherPackage; private final String mThemePickerPackage; @@ -150,9 +152,11 @@ public class ThemeOverlayApplier implements Dumpable { @Background Executor bgExecutor, @Named(ThemeModule.LAUNCHER_PACKAGE) String launcherPackage, @Named(ThemeModule.THEME_PICKER_PACKAGE) String themePickerPackage, - DumpManager dumpManager) { + DumpManager dumpManager, + @Main Executor mainExecutor) { mOverlayManager = overlayManager; mBgExecutor = bgExecutor; + mMainExecutor = mainExecutor; mLauncherPackage = launcherPackage; mThemePickerPackage = themePickerPackage; mTargetPackageToCategories.put(ANDROID_PACKAGE, Sets.newHashSet( @@ -184,12 +188,21 @@ public class ThemeOverlayApplier implements Dumpable { /** * Apply the set of overlay packages to the set of {@code UserHandle}s provided. Overlays that * affect sysui will also be applied to the system user. + * + * @param categoryToPackage Overlay packages to be applied + * @param pendingCreation Overlays yet to be created + * @param currentUser Current User ID + * @param managedProfiles Profiles get overlays + * @param onComplete Callback for when resources are ready. Runs in the main thread. */ public void applyCurrentUserOverlays( Map<String, OverlayIdentifier> categoryToPackage, FabricatedOverlay[] pendingCreation, int currentUser, - Set<UserHandle> managedProfiles) { + Set<UserHandle> managedProfiles, + Runnable onComplete + ) { + mBgExecutor.execute(() -> { // Disable all overlays that have not been specified in the user setting. @@ -236,6 +249,10 @@ public class ThemeOverlayApplier implements Dumpable { try { mOverlayManager.commit(transaction.build()); + if (onComplete != null) { + Log.d(TAG, "Executing onComplete runnable"); + mMainExecutor.execute(onComplete); + } } catch (SecurityException | IllegalStateException e) { Log.e(TAG, "setEnabled failed", e); } diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java index 5a9f5d5a72d2..8e6949961cbe 100644 --- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java +++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java @@ -30,6 +30,7 @@ import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_COLOR_INDEX import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_COLOR_SOURCE; import static com.android.systemui.theme.ThemeOverlayApplier.TIMESTAMP_FIELD; +import android.app.ActivityManager; import android.app.UiModeManager; import android.app.WallpaperColors; import android.app.WallpaperManager; @@ -137,6 +138,7 @@ public class ThemeOverlayController implements CoreStartable, Dumpable { // Current wallpaper colors associated to a user. private final SparseArray<WallpaperColors> mCurrentColors = new SparseArray<>(); private final WallpaperManager mWallpaperManager; + private final ActivityManager mActivityManager; @VisibleForTesting protected ColorScheme mColorScheme; // If fabricated overlays were already created for the current theme. @@ -395,7 +397,8 @@ public class ThemeOverlayController implements CoreStartable, Dumpable { FeatureFlags featureFlags, @Main Resources resources, WakefulnessLifecycle wakefulnessLifecycle, - UiModeManager uiModeManager) { + UiModeManager uiModeManager, + ActivityManager activityManager) { mContext = context; mIsMonochromaticEnabled = featureFlags.isEnabled(Flags.MONOCHROMATIC_THEME); mIsMonetEnabled = featureFlags.isEnabled(Flags.MONET); @@ -413,6 +416,7 @@ public class ThemeOverlayController implements CoreStartable, Dumpable { mResources = resources; mWakefulnessLifecycle = wakefulnessLifecycle; mUiModeManager = uiModeManager; + mActivityManager = activityManager; dumpManager.registerDumpable(TAG, this); } @@ -764,8 +768,14 @@ public class ThemeOverlayController implements CoreStartable, Dumpable { } } + final Runnable onCompleteCallback = () -> { + Log.d(TAG, "ThemeHomeDelay: ThemeOverlayController ready"); + mActivityManager.setThemeOverlayReady(currentUser); + }; + if (colorSchemeIsApplied(managedProfiles)) { Log.d(TAG, "Skipping overlay creation. Theme was already: " + mColorScheme); + onCompleteCallback.run(); return; } @@ -774,16 +784,20 @@ public class ThemeOverlayController implements CoreStartable, Dumpable { .map(key -> key + " -> " + categoryToPackage.get(key)).collect( Collectors.joining(", "))); } + + FabricatedOverlay[] fOverlays = null; + if (mNeedsOverlayCreation) { mNeedsOverlayCreation = false; - mThemeManager.applyCurrentUserOverlays(categoryToPackage, new FabricatedOverlay[]{ + fOverlays = new FabricatedOverlay[]{ mSecondaryOverlay, mNeutralOverlay, mDynamicOverlay - }, currentUser, managedProfiles); - } else { - mThemeManager.applyCurrentUserOverlays(categoryToPackage, null, currentUser, - managedProfiles); + }; + } + + mThemeManager.applyCurrentUserOverlays(categoryToPackage, fOverlays, currentUser, + managedProfiles, onCompleteCallback); + } - } private Style fetchThemeStyleFromSetting() { // Allow-list of Style objects that can be created from a setting string, i.e. can be diff --git a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayApplierTest.java b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayApplierTest.java index 83439f0fc60d..8f4cbafecbcd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayApplierTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayApplierTest.java @@ -104,9 +104,9 @@ public class ThemeOverlayApplierTest extends SysuiTestCase { @Before public void setup() throws Exception { MockitoAnnotations.initMocks(this); - mManager = new ThemeOverlayApplier(mOverlayManager, - MoreExecutors.directExecutor(), - LAUNCHER_PACKAGE, THEMEPICKER_PACKAGE, mDumpManager) { + mManager = new ThemeOverlayApplier(mOverlayManager, MoreExecutors.directExecutor(), + LAUNCHER_PACKAGE, THEMEPICKER_PACKAGE, mDumpManager, + MoreExecutors.directExecutor()) { @Override protected OverlayManagerTransaction.Builder getTransactionBuilder() { return mTransactionBuilder; @@ -179,7 +179,7 @@ public class ThemeOverlayApplierTest extends SysuiTestCase { @Test public void allCategoriesSpecified_allEnabledExclusively() { mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, null, TEST_USER.getIdentifier(), - TEST_USER_HANDLES); + TEST_USER_HANDLES, null); verify(mOverlayManager).commit(any()); for (OverlayIdentifier overlayPackage : ALL_CATEGORIES_MAP.values()) { @@ -191,7 +191,7 @@ public class ThemeOverlayApplierTest extends SysuiTestCase { @Test public void allCategoriesSpecified_sysuiCategoriesAlsoAppliedToSysuiUser() { mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, null, TEST_USER.getIdentifier(), - TEST_USER_HANDLES); + TEST_USER_HANDLES, null); for (Map.Entry<String, OverlayIdentifier> entry : ALL_CATEGORIES_MAP.entrySet()) { if (SYSTEM_USER_CATEGORIES.contains(entry.getKey())) { @@ -208,7 +208,7 @@ public class ThemeOverlayApplierTest extends SysuiTestCase { public void allCategoriesSpecified_enabledForAllUserHandles() { Set<UserHandle> userHandles = Sets.newHashSet(TEST_USER_HANDLES); mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, null, TEST_USER.getIdentifier(), - userHandles); + userHandles, null); for (OverlayIdentifier overlayPackage : ALL_CATEGORIES_MAP.values()) { verify(mTransactionBuilder).setEnabled(eq(overlayPackage), eq(true), @@ -225,7 +225,7 @@ public class ThemeOverlayApplierTest extends SysuiTestCase { Set<UserHandle> userHandles = Sets.newHashSet(TEST_USER_HANDLES); mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, null, TEST_USER.getIdentifier(), - userHandles); + userHandles, null); for (OverlayIdentifier overlayPackage : ALL_CATEGORIES_MAP.values()) { verify(mTransactionBuilder, never()).setEnabled(eq(overlayPackage), eq(true), @@ -239,7 +239,7 @@ public class ThemeOverlayApplierTest extends SysuiTestCase { mock(FabricatedOverlay.class) }; mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, pendingCreation, - TEST_USER.getIdentifier(), TEST_USER_HANDLES); + TEST_USER.getIdentifier(), TEST_USER_HANDLES, null); for (FabricatedOverlay overlay : pendingCreation) { verify(mTransactionBuilder).registerFabricatedOverlay(eq(overlay)); @@ -253,7 +253,7 @@ public class ThemeOverlayApplierTest extends SysuiTestCase { categoryToPackage.remove(OVERLAY_CATEGORY_ICON_ANDROID); mManager.applyCurrentUserOverlays(categoryToPackage, null, TEST_USER.getIdentifier(), - TEST_USER_HANDLES); + TEST_USER_HANDLES, null); for (OverlayIdentifier overlayPackage : categoryToPackage.values()) { verify(mTransactionBuilder).setEnabled(eq(overlayPackage), eq(true), @@ -270,7 +270,7 @@ public class ThemeOverlayApplierTest extends SysuiTestCase { @Test public void zeroCategoriesSpecified_allDisabled() { mManager.applyCurrentUserOverlays(Maps.newArrayMap(), null, TEST_USER.getIdentifier(), - TEST_USER_HANDLES); + TEST_USER_HANDLES, null); for (String category : THEME_CATEGORIES) { verify(mTransactionBuilder).setEnabled( @@ -285,7 +285,7 @@ public class ThemeOverlayApplierTest extends SysuiTestCase { categoryToPackage.put("blah.category", new OverlayIdentifier("com.example.blah.category")); mManager.applyCurrentUserOverlays(categoryToPackage, null, TEST_USER.getIdentifier(), - TEST_USER_HANDLES); + TEST_USER_HANDLES, null); verify(mTransactionBuilder, never()).setEnabled( eq(new OverlayIdentifier("com.example.blah.category")), eq(false), diff --git a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java index c454b45a7312..8858f0fe8cb9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java @@ -36,6 +36,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; +import android.app.ActivityManager; import android.app.UiModeManager; import android.app.WallpaperColors; import android.app.WallpaperManager; @@ -120,6 +121,8 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { private WakefulnessLifecycle mWakefulnessLifecycle; @Mock private UiModeManager mUiModeManager; + @Mock + private ActivityManager mActivityManager; @Captor private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiver; @Captor @@ -154,7 +157,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { mBroadcastDispatcher, mBgHandler, mMainExecutor, mBgExecutor, mThemeOverlayApplier, mSecureSettings, mWallpaperManager, mUserManager, mDeviceProvisionedController, mUserTracker, mDumpManager, mFeatureFlags, mResources, mWakefulnessLifecycle, - mUiModeManager) { + mUiModeManager, mActivityManager) { @VisibleForTesting protected boolean isNightMode() { return false; @@ -206,7 +209,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { ArgumentCaptor.forClass(Map.class); verify(mThemeOverlayApplier) - .applyCurrentUserOverlays(themeOverlays.capture(), any(), anyInt(), any()); + .applyCurrentUserOverlays(themeOverlays.capture(), any(), anyInt(), any(), any()); // Assert that we received the colors that we were expecting assertThat(themeOverlays.getValue().get(OVERLAY_CATEGORY_SYSTEM_PALETTE)) @@ -231,7 +234,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { mBroadcastReceiver.getValue().onReceive(null, intent); mColorsListener.getValue().onColorsChanged(new WallpaperColors(Color.valueOf(Color.BLACK), null, null), WallpaperManager.FLAG_SYSTEM, USER_SYSTEM); - verify(mThemeOverlayApplier).applyCurrentUserOverlays(any(), any(), anyInt(), any()); + verify(mThemeOverlayApplier).applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); } @Test @@ -245,7 +248,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { ArgumentCaptor.forClass(Map.class); verify(mThemeOverlayApplier) - .applyCurrentUserOverlays(themeOverlays.capture(), any(), anyInt(), any()); + .applyCurrentUserOverlays(themeOverlays.capture(), any(), anyInt(), any(), any()); // Should not change theme after changing wallpapers, if intent doesn't have // WallpaperManager.EXTRA_FROM_FOREGROUND_APP set to true. @@ -254,7 +257,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { mColorsListener.getValue().onColorsChanged(new WallpaperColors(Color.valueOf(Color.BLACK), null, null), WallpaperManager.FLAG_SYSTEM, USER_SYSTEM); verify(mThemeOverlayApplier, never()) - .applyCurrentUserOverlays(any(), any(), anyInt(), any()); + .applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); } @Test @@ -276,7 +279,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { ArgumentCaptor.forClass(Map.class); verify(mThemeOverlayApplier) - .applyCurrentUserOverlays(themeOverlays.capture(), any(), anyInt(), any()); + .applyCurrentUserOverlays(themeOverlays.capture(), any(), anyInt(), any(), any()); // Assert that we received the colors that we were expecting assertThat(themeOverlays.getValue().get(OVERLAY_CATEGORY_SYSTEM_PALETTE)) @@ -315,7 +318,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { .isFalse(); verify(mThemeOverlayApplier) - .applyCurrentUserOverlays(any(), any(), anyInt(), any()); + .applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); } @Test @@ -350,7 +353,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { "android.theme.customization.color_both\":\"0")).isTrue(); verify(mThemeOverlayApplier) - .applyCurrentUserOverlays(any(), any(), anyInt(), any()); + .applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); } @Test @@ -405,7 +408,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { assertThat(updatedSetting.getValue().contains( "android.theme.customization.color_both\":\"1")).isTrue(); verify(mThemeOverlayApplier) - .applyCurrentUserOverlays(any(), any(), anyInt(), any()); + .applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); } @Test @@ -474,7 +477,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { "android.theme.customization.color_both\":\"1")).isTrue(); verify(mThemeOverlayApplier) - .applyCurrentUserOverlays(any(), any(), anyInt(), any()); + .applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); } @Test @@ -505,7 +508,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { assertThat(updatedSetting.getValue().contains("android.theme.customization.color_index")) .isFalse(); verify(mThemeOverlayApplier) - .applyCurrentUserOverlays(any(), any(), anyInt(), any()); + .applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); } @Test @@ -536,7 +539,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { assertThat(updatedSetting.getValue().contains("android.theme.customization.color_index")) .isFalse(); verify(mThemeOverlayApplier) - .applyCurrentUserOverlays(any(), any(), anyInt(), any()); + .applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); } @Test @@ -569,7 +572,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { anyInt()); verify(mThemeOverlayApplier) - .applyCurrentUserOverlays(any(), any(), anyInt(), any()); + .applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); } @Test @@ -602,7 +605,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), updatedSetting.capture()); // Apply overlay by existing theme from secure setting - verify(mThemeOverlayApplier).applyCurrentUserOverlays(any(), any(), anyInt(), any()); + verify(mThemeOverlayApplier).applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); } @Test @@ -635,7 +638,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { verify(mThemeOverlayApplier, never()) - .applyCurrentUserOverlays(any(), any(), anyInt(), any()); + .applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); } @Test @@ -657,7 +660,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { ArgumentCaptor<Map<String, OverlayIdentifier>> themeOverlays = ArgumentCaptor.forClass(Map.class); verify(mThemeOverlayApplier) - .applyCurrentUserOverlays(themeOverlays.capture(), any(), anyInt(), any()); + .applyCurrentUserOverlays(themeOverlays.capture(), any(), anyInt(), any(), any()); // Assert that we received secondary user colors assertThat(themeOverlays.getValue().get(OVERLAY_CATEGORY_SYSTEM_PALETTE)) @@ -670,7 +673,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { public void onProfileAdded_setsTheme() { mBroadcastReceiver.getValue().onReceive(null, new Intent(Intent.ACTION_MANAGED_PROFILE_ADDED)); - verify(mThemeOverlayApplier).applyCurrentUserOverlays(any(), any(), anyInt(), any()); + verify(mThemeOverlayApplier).applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); } @Test @@ -680,7 +683,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { mBroadcastReceiver.getValue().onReceive(null, new Intent(Intent.ACTION_MANAGED_PROFILE_ADDED)); verify(mThemeOverlayApplier) - .applyCurrentUserOverlays(any(), any(), anyInt(), any()); + .applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); } @Test @@ -690,7 +693,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { mBroadcastReceiver.getValue().onReceive(null, new Intent(Intent.ACTION_MANAGED_PROFILE_ADDED)); verify(mThemeOverlayApplier, never()) - .applyCurrentUserOverlays(any(), any(), anyInt(), any()); + .applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); } @Test @@ -703,7 +706,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { mColorsListener.getValue().onColorsChanged(mainColors, WallpaperManager.FLAG_SYSTEM, USER_SYSTEM); - verify(mThemeOverlayApplier).applyCurrentUserOverlays(any(), any(), anyInt(), any()); + verify(mThemeOverlayApplier).applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); // Regression test: null events should not reset the internal state and allow colors to be // applied again. @@ -713,11 +716,11 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { mBroadcastReceiver.getValue().onReceive(null, intent); mColorsListener.getValue().onColorsChanged(null, WallpaperManager.FLAG_SYSTEM, USER_SYSTEM); verify(mThemeOverlayApplier, never()).applyCurrentUserOverlays(any(), any(), anyInt(), - any()); + any(), any()); mColorsListener.getValue().onColorsChanged(new WallpaperColors(Color.valueOf(Color.GREEN), null, null), WallpaperManager.FLAG_SYSTEM, USER_SYSTEM); verify(mThemeOverlayApplier, never()).applyCurrentUserOverlays(any(), any(), anyInt(), - any()); + any(), any()); } @Test @@ -736,7 +739,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { mBroadcastDispatcher, mBgHandler, executor, executor, mThemeOverlayApplier, mSecureSettings, mWallpaperManager, mUserManager, mDeviceProvisionedController, mUserTracker, mDumpManager, mFeatureFlags, mResources, mWakefulnessLifecycle, - mUiModeManager) { + mUiModeManager, mActivityManager) { @VisibleForTesting protected boolean isNightMode() { return false; @@ -757,7 +760,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { verify(mDeviceProvisionedController).addCallback(mDeviceProvisionedListener.capture()); // Colors were applied during controller initialization. - verify(mThemeOverlayApplier).applyCurrentUserOverlays(any(), any(), anyInt(), any()); + verify(mThemeOverlayApplier).applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); clearInvocations(mThemeOverlayApplier); } @@ -776,7 +779,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { mBroadcastDispatcher, mBgHandler, executor, executor, mThemeOverlayApplier, mSecureSettings, mWallpaperManager, mUserManager, mDeviceProvisionedController, mUserTracker, mDumpManager, mFeatureFlags, mResources, mWakefulnessLifecycle, - mUiModeManager) { + mUiModeManager, mActivityManager) { @VisibleForTesting protected boolean isNightMode() { return false; @@ -797,7 +800,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { verify(mDeviceProvisionedController).addCallback(mDeviceProvisionedListener.capture()); // Colors were applied during controller initialization. - verify(mThemeOverlayApplier).applyCurrentUserOverlays(any(), any(), anyInt(), any()); + verify(mThemeOverlayApplier).applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); clearInvocations(mThemeOverlayApplier); WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED), @@ -819,12 +822,12 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { // Defers event because we already have initial colors. verify(mThemeOverlayApplier, never()) - .applyCurrentUserOverlays(any(), any(), anyInt(), any()); + .applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); // Then event happens after setup phase is over. when(mDeviceProvisionedController.isCurrentUserSetup()).thenReturn(true); mDeviceProvisionedListener.getValue().onUserSetupChanged(); - verify(mThemeOverlayApplier).applyCurrentUserOverlays(any(), any(), anyInt(), any()); + verify(mThemeOverlayApplier).applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); } @Test @@ -847,11 +850,11 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { mColorsListener.getValue().onColorsChanged(mainColors, WallpaperManager.FLAG_SYSTEM, USER_SYSTEM); verify(mThemeOverlayApplier, never()) - .applyCurrentUserOverlays(any(), any(), anyInt(), any()); + .applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); mWakefulnessLifecycle.dispatchFinishedGoingToSleep(); verify(mThemeOverlayApplier, never()) - .applyCurrentUserOverlays(any(), any(), anyInt(), any()); + .applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); } @Test @@ -873,10 +876,10 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { mColorsListener.getValue().onColorsChanged(mainColors, WallpaperManager.FLAG_SYSTEM, USER_SYSTEM); verify(mThemeOverlayApplier, never()) - .applyCurrentUserOverlays(any(), any(), anyInt(), any()); + .applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); mWakefulnessLifecycleObserver.getValue().onFinishedGoingToSleep(); - verify(mThemeOverlayApplier).applyCurrentUserOverlays(any(), any(), anyInt(), any()); + verify(mThemeOverlayApplier).applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); } @Test @@ -896,7 +899,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { ArgumentCaptor.forClass(Map.class); verify(mThemeOverlayApplier) - .applyCurrentUserOverlays(themeOverlays.capture(), any(), anyInt(), any()); + .applyCurrentUserOverlays(themeOverlays.capture(), any(), anyInt(), any(), any()); // Assert that we received the colors that we were expecting assertThat(themeOverlays.getValue().get(OVERLAY_CATEGORY_SYSTEM_PALETTE)) @@ -915,19 +918,19 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { mColorsListener.getValue().onColorsChanged(startingColors, WallpaperManager.FLAG_SYSTEM, USER_SYSTEM); verify(mThemeOverlayApplier) - .applyCurrentUserOverlays(any(), any(), anyInt(), any()); + .applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); clearInvocations(mThemeOverlayApplier); // Set to the same colors. mColorsListener.getValue().onColorsChanged(sameColors, WallpaperManager.FLAG_SYSTEM, USER_SYSTEM); verify(mThemeOverlayApplier, never()) - .applyCurrentUserOverlays(any(), any(), anyInt(), any()); + .applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); // Verify that no change resulted. mWakefulnessLifecycleObserver.getValue().onFinishedGoingToSleep(); verify(mThemeOverlayApplier, never()).applyCurrentUserOverlays(any(), any(), anyInt(), - any()); + any(), any()); } @Test @@ -941,7 +944,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { ArgumentCaptor.forClass(FabricatedOverlay[].class); verify(mThemeOverlayApplier) - .applyCurrentUserOverlays(any(), themeOverlays.capture(), anyInt(), any()); + .applyCurrentUserOverlays(any(), themeOverlays.capture(), anyInt(), any(), any()); FabricatedOverlay[] overlays = themeOverlays.getValue(); FabricatedOverlay accents = overlays[0]; diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 4dad2d560526..ec80445ea09a 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -513,6 +513,7 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiFunction; import java.util.function.Consumer; @@ -910,6 +911,16 @@ public class ActivityManagerService extends IActivityManager.Stub @GuardedBy("this") final ComponentAliasResolver mComponentAliasResolver; + private static final long HOME_LAUNCH_TIMEOUT_MS = 15000; + private final AtomicBoolean mHasHomeDelay = new AtomicBoolean(false); + + /** + * Tracks all users with computed color resources by ThemeOverlaycvontroller + */ + @GuardedBy("this") + private final Set<Integer> mThemeOverlayReadyUsers = new HashSet<>(); + + /** * Tracks association information for a particular package along with debuggability. * <p> Associations for a package A are allowed to package B if B is part of the @@ -2269,6 +2280,7 @@ public class ActivityManagerService extends IActivityManager.Stub mService.startBroadcastObservers(); } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { mService.mPackageWatchdog.onPackagesReady(); + mService.scheduleHomeTimeout(); } } @@ -5235,6 +5247,61 @@ public class ActivityManagerService extends IActivityManager.Stub } } + /** + * Starts Home if there is no completion signal from ThemeOverlayController + */ + private void scheduleHomeTimeout() { + if (mHasHomeDelay.compareAndSet(false, true)) { + int userId = mUserController.getCurrentUserId(); + mHandler.postDelayed(() -> { + if (!isThemeOverlayReady(userId)) { + Slog.d(TAG, + "ThemeHomeDelay: ThemeOverlayController not responding, launching " + + "Home after " + + HOME_LAUNCH_TIMEOUT_MS + "ms"); + setThemeOverlayReady(userId); + } + }, HOME_LAUNCH_TIMEOUT_MS); + } + } + + /** + * Used by ThemeOverlayController to notify when color + * palette is ready. + * + * @param userId The ID of the user where ThemeOverlayController is ready. + * + * @throws RemoteException + * + * @hide + */ + @Override + public void setThemeOverlayReady(@UserIdInt int userId) { + enforceCallingPermission(Manifest.permission.SET_THEME_OVERLAY_CONTROLLER_READY, + "setThemeOverlayReady"); + + boolean updateUser; + synchronized (mThemeOverlayReadyUsers) { + updateUser = mThemeOverlayReadyUsers.add(userId); + } + + if (updateUser) { + mAtmInternal.startHomeOnAllDisplays(userId, "setThemeOverlayReady"); + } + } + + /** + * Returns current state of ThemeOverlayController color + * palette readiness. + * + * @hide + */ + public boolean isThemeOverlayReady(int userId) { + synchronized (mThemeOverlayReadyUsers) { + return mThemeOverlayReadyUsers.contains(userId); + } + } + final void ensureBootCompleted() { boolean booting; boolean enableScreen; @@ -17612,6 +17679,10 @@ public class ActivityManagerService extends IActivityManager.Stub mAtmInternal.onUserStopped(userId); // Clean up various services by removing the user mBatteryStatsService.onUserRemoved(userId); + + synchronized (mThemeOverlayReadyUsers) { + mThemeOverlayReadyUsers.remove(userId); + } } @Override @@ -18966,6 +19037,11 @@ public class ActivityManagerService extends IActivityManager.Stub return ActivityManagerService.this.clearApplicationUserData(packageName, keepState, isRestore, observer, userId); } + + @Override + public boolean isThemeOverlayReady(int userId) { + return ActivityManagerService.this.isThemeOverlayReady(userId); + } } long inputDispatchingTimedOut(int pid, final boolean aboveSystem, TimeoutRecord timeoutRecord) { diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index d4fdc1290649..29db204d0f49 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -1452,6 +1452,11 @@ class RootWindowContainer extends WindowContainer<DisplayContent> return false; } + if (!mService.mAmInternal.isThemeOverlayReady(userId)) { + Slog.d(TAG, "ThemeHomeDelay: Home launch was deferred."); + return false; + } + // Updates the home component of the intent. homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name)); homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK); diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java index 7edfd9a3ecb3..0f765a726869 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java +++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java @@ -311,6 +311,7 @@ public class SystemServicesTestRule implements TestRule { doReturn(true).when(amInternal).hasStartedUserState(anyInt()); doReturn(false).when(amInternal).shouldConfirmCredentials(anyInt()); doReturn(false).when(amInternal).isActivityStartsLoggingEnabled(); + doReturn(true).when(amInternal).isThemeOverlayReady(anyInt()); LocalServices.addService(ActivityManagerInternal.class, amInternal); final ActivityManagerService amService = |