diff options
| author | 2024-02-08 13:10:54 +0000 | |
|---|---|---|
| committer | 2024-02-08 13:10:54 +0000 | |
| commit | c89fa236be583ac37e0069cace2ad429d742a8a9 (patch) | |
| tree | f0dafdc6d049e26c928f898c4ba109f1eb45769b | |
| parent | b640ff839e877033375014e5b67343fdf9782622 (diff) | |
| parent | 2637324fef7f684853fb1ba5f086c6e519e98ef1 (diff) | |
Merge "Expose RRO completion signal" into main
13 files changed, 217 insertions, 61 deletions
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 084c71f47603..a8d183a1d6dd 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -5954,6 +5954,20 @@ public class ActivityManager { } /** + * Used by {@link com.android.systemui.theme.ThemeOverlayController} to notify of color + * palette readiness. + * @hide + */ + @RequiresPermission(Manifest.permission.SET_THEME_OVERLAY_CONTROLLER_READY) + public void setThemeOverlayReady(boolean readiness) { + try { + getService().setThemeOverlayReady(readiness); + } 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 232fc926a802..0ae2e01a45fa 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -1258,4 +1258,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 getThemeOverlayReadiness(); } diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index b063d04655f5..ceeaf5dea7d3 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -17,7 +17,6 @@ package android.app; import android.app.ActivityManager; -import android.app.ActivityManager.PendingIntentInfo; import android.app.ActivityTaskManager; import android.app.ApplicationStartInfo; import android.app.ApplicationErrorReport; @@ -553,6 +552,14 @@ interface IActivityManager { @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) boolean isTopOfTask(in IBinder token); void bootAnimationComplete(); + + /** + * Used by {@link com.android.systemui.theme.ThemeOverlayController} to notify of color + * palette readiness. + * @throws RemoteException + */ + void setThemeOverlayReady(boolean readiness); + @UnsupportedAppUsage void registerTaskStackListener(in ITaskStackListener listener); void unregisterTaskStackListener(in ITaskStackListener listener); diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 5c764e2f0e7d..374c31222b97 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -7562,6 +7562,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/SettingsLib/SettingsTheme/res/values-v31/styles.xml b/packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml index f44b16104f99..aed985ec1218 100644 --- a/packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml +++ b/packages/SettingsLib/SettingsTheme/res/values-v31/styles.xml @@ -14,10 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. --> -<resources> +<resources xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"> <style name="TextAppearance.PreferenceTitle.SettingsLib" parent="@android:style/TextAppearance.Material.Subhead"> - <item name="android:textColor">@color/settingslib_text_color_primary</item> + <item name="android:textColor">?androidprv:attr/materialColorOnSurface</item> <item name="android:fontFamily">@string/settingslib_config_headlineFontFamily</item> <item name="android:textSize">20sp</item> </style> diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index f877d7a89b92..12e8f574e906 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -262,6 +262,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..147e158bd393 100644 --- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java +++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayApplier.java @@ -15,6 +15,8 @@ */ package com.android.systemui.theme; +import static com.android.systemui.shared.Flags.enableHomeDelay; + import android.annotation.AnyThread; import android.content.om.FabricatedOverlay; import android.content.om.OverlayIdentifier; @@ -32,6 +34,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 +145,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 +154,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 +190,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 +251,10 @@ public class ThemeOverlayApplier implements Dumpable { try { mOverlayManager.commit(transaction.build()); + if (enableHomeDelay() && 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 2b9ad50c1257..585ab72dd963 100644 --- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java +++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java @@ -20,6 +20,7 @@ import static android.util.TypedValue.TYPE_INT_COLOR_ARGB8; import static com.android.systemui.Flags.themeOverlayControllerWakefulnessDeprecation; import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP; +import static com.android.systemui.shared.Flags.enableHomeDelay; import static com.android.systemui.theme.ThemeOverlayApplier.COLOR_SOURCE_HOME; import static com.android.systemui.theme.ThemeOverlayApplier.COLOR_SOURCE_LOCK; import static com.android.systemui.theme.ThemeOverlayApplier.COLOR_SOURCE_PRESET; @@ -31,6 +32,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; @@ -140,6 +142,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. @@ -414,7 +417,8 @@ public class ThemeOverlayController implements CoreStartable, Dumpable { WakefulnessLifecycle wakefulnessLifecycle, JavaAdapter javaAdapter, KeyguardTransitionInteractor keyguardTransitionInteractor, - UiModeManager uiModeManager) { + UiModeManager uiModeManager, + ActivityManager activityManager) { mContext = context; mIsMonetEnabled = featureFlags.isEnabled(Flags.MONET); mIsFidelityEnabled = featureFlags.isEnabled(Flags.COLOR_FIDELITY); @@ -433,6 +437,7 @@ public class ThemeOverlayController implements CoreStartable, Dumpable { mJavaAdapter = javaAdapter; mKeyguardTransitionInteractor = keyguardTransitionInteractor; mUiModeManager = uiModeManager; + mActivityManager = activityManager; dumpManager.registerDumpable(TAG, this); } @@ -806,8 +811,16 @@ public class ThemeOverlayController implements CoreStartable, Dumpable { } } + final Runnable onCompleteCallback = !enableHomeDelay() + ? () -> {} + : () -> { + Log.d(TAG, "ThemeHomeDelay: ThemeOverlayController ready"); + mActivityManager.setThemeOverlayReady(true); + }; + if (colorSchemeIsApplied(managedProfiles)) { Log.d(TAG, "Skipping overlay creation. Theme was already: " + mColorScheme); + onCompleteCallback.run(); return; } @@ -816,15 +829,19 @@ 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() { 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 b58a41c89a4e..c02583ae6f0b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java @@ -37,6 +37,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; @@ -129,6 +130,8 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { private WakefulnessLifecycle mWakefulnessLifecycle; @Mock private UiModeManager mUiModeManager; + @Mock + private ActivityManager mActivityManager; @Captor private ArgumentCaptor<BroadcastReceiver> mBroadcastReceiver; @Captor @@ -164,7 +167,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { mBroadcastDispatcher, mBgHandler, mMainExecutor, mBgExecutor, mThemeOverlayApplier, mSecureSettings, mWallpaperManager, mUserManager, mDeviceProvisionedController, mUserTracker, mDumpManager, mFeatureFlags, mResources, mWakefulnessLifecycle, - mJavaAdapter, mKeyguardTransitionInteractor, mUiModeManager) { + mJavaAdapter, mKeyguardTransitionInteractor, mUiModeManager, mActivityManager) { @VisibleForTesting protected boolean isNightMode() { return false; @@ -224,7 +227,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)) @@ -249,7 +252,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 @@ -263,7 +266,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. @@ -272,7 +275,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 @@ -294,7 +297,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)) @@ -333,7 +336,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { .isFalse(); verify(mThemeOverlayApplier) - .applyCurrentUserOverlays(any(), any(), anyInt(), any()); + .applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); } @Test @@ -367,8 +370,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { assertThat(updatedSetting.getValue().contains( "android.theme.customization.color_both\":\"0")).isTrue(); - verify(mThemeOverlayApplier) - .applyCurrentUserOverlays(any(), any(), anyInt(), any()); + verify(mThemeOverlayApplier).applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); } @Test @@ -423,7 +425,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 @@ -492,7 +494,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 @@ -523,7 +525,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 @@ -554,7 +556,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 @@ -587,7 +589,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { anyInt()); verify(mThemeOverlayApplier) - .applyCurrentUserOverlays(any(), any(), anyInt(), any()); + .applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); } @Test @@ -620,7 +622,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 @@ -653,7 +655,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { verify(mThemeOverlayApplier, never()) - .applyCurrentUserOverlays(any(), any(), anyInt(), any()); + .applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); } @Test @@ -675,7 +677,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)) @@ -689,7 +691,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { mBroadcastReceiver.getValue().onReceive(null, new Intent(Intent.ACTION_PROFILE_ADDED) .putExtra(Intent.EXTRA_USER, MANAGED_USER_HANDLE)); - verify(mThemeOverlayApplier).applyCurrentUserOverlays(any(), any(), anyInt(), any()); + verify(mThemeOverlayApplier).applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); } @Test @@ -700,7 +702,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { new Intent(Intent.ACTION_PROFILE_ADDED) .putExtra(Intent.EXTRA_USER, MANAGED_USER_HANDLE)); verify(mThemeOverlayApplier) - .applyCurrentUserOverlays(any(), any(), anyInt(), any()); + .applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); } @Test @@ -711,7 +713,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { new Intent(Intent.ACTION_PROFILE_ADDED) .putExtra(Intent.EXTRA_USER, MANAGED_USER_HANDLE)); verify(mThemeOverlayApplier, never()) - .applyCurrentUserOverlays(any(), any(), anyInt(), any()); + .applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); } @Test @@ -723,7 +725,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { (new Intent(Intent.ACTION_PROFILE_ADDED)) .putExtra(Intent.EXTRA_USER, PRIVATE_USER_HANDLE)); verify(mThemeOverlayApplier, never()) - .applyCurrentUserOverlays(any(), any(), anyInt(), any()); + .applyCurrentUserOverlays(any(), any(), anyInt(), any(), any()); } @@ -737,7 +739,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. @@ -747,11 +749,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 @@ -770,7 +772,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { mBroadcastDispatcher, mBgHandler, executor, executor, mThemeOverlayApplier, mSecureSettings, mWallpaperManager, mUserManager, mDeviceProvisionedController, mUserTracker, mDumpManager, mFeatureFlags, mResources, mWakefulnessLifecycle, - mJavaAdapter, mKeyguardTransitionInteractor, mUiModeManager) { + mJavaAdapter, mKeyguardTransitionInteractor, mUiModeManager, mActivityManager) { @VisibleForTesting protected boolean isNightMode() { return false; @@ -791,7 +793,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); } @@ -810,7 +812,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase { mBroadcastDispatcher, mBgHandler, executor, executor, mThemeOverlayApplier, mSecureSettings, mWallpaperManager, mUserManager, mDeviceProvisionedController, mUserTracker, mDumpManager, mFeatureFlags, mResources, mWakefulnessLifecycle, - mJavaAdapter, mKeyguardTransitionInteractor, mUiModeManager) { + mJavaAdapter, mKeyguardTransitionInteractor, mUiModeManager, mActivityManager) { @VisibleForTesting protected boolean isNightMode() { return false; @@ -831,7 +833,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), @@ -853,12 +855,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 @@ -881,11 +883,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 @@ -907,10 +909,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 @@ -930,7 +932,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)) @@ -949,19 +951,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 @@ -975,7 +977,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 a5531ae65bbe..2750344b487e 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -187,6 +187,7 @@ import static com.android.server.wm.ActivityTaskManagerService.DUMP_TOP_RESUMED_ import static com.android.server.wm.ActivityTaskManagerService.DUMP_VISIBLE_ACTIVITIES; import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE; import static com.android.server.wm.ActivityTaskManagerService.relaunchReasonToString; +import static com.android.systemui.shared.Flags.enableHomeDelay; import android.Manifest; import android.Manifest.permission; @@ -521,6 +522,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; @@ -921,6 +923,15 @@ 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> mThemeOverlayReadiness = 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 @@ -2332,6 +2343,7 @@ public class ActivityManagerService extends IActivityManager.Stub mService.startBroadcastObservers(); } else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) { mService.mPackageWatchdog.onPackagesReady(); + mService.setHomeTimeout(); } } @@ -5304,6 +5316,59 @@ public class ActivityManagerService extends IActivityManager.Stub } } + /** + * Starts Home if there is no completion signal from ThemeOverlayController + */ + private void setHomeTimeout() { + if (enableHomeDelay() && mHasHomeDelay.compareAndSet(false, true)) { + mHandler.postDelayed(() -> { + if (!getThemeOverlayReadiness()) { + Slog.d(TAG, + "ThemeHomeDelay: ThemeOverlayController not responding, launching " + + "Home after " + + HOME_LAUNCH_TIMEOUT_MS + "ms"); + setThemeOverlayReady(true); + } + }, HOME_LAUNCH_TIMEOUT_MS); + } + } + + /** + * Used by ThemeOverlayController to notify all listeners for + * color palette readiness. + * @hide + */ + @Override + public void setThemeOverlayReady(boolean readiness) { + enforceCallingPermission(Manifest.permission.SET_THEME_OVERLAY_CONTROLLER_READY, + "setThemeOverlayReady"); + + int currentUserId = mUserController.getCurrentUserId(); + + boolean updateReadiness; + synchronized (mThemeOverlayReadiness) { + updateReadiness = readiness ? mThemeOverlayReadiness.add(currentUserId) + : mThemeOverlayReadiness.remove(currentUserId); + } + + if (updateReadiness && readiness && enableHomeDelay()) { + mAtmInternal.startHomeOnAllDisplays(currentUserId, "setThemeOverlayReady"); + } + } + + /** + * Returns current state of ThemeOverlayController color + * palette readiness. + * + * @hide + */ + public boolean getThemeOverlayReadiness() { + int uid = mUserController.getCurrentUserId(); + synchronized (mThemeOverlayReadiness) { + return mThemeOverlayReadiness.contains(uid); + } + } + final void ensureBootCompleted() { boolean booting; boolean enableScreen; @@ -18033,6 +18098,10 @@ public class ActivityManagerService extends IActivityManager.Stub mAtmInternal.onUserStopped(userId); // Clean up various services by removing the user mBatteryStatsService.onUserRemoved(userId); + + synchronized (mThemeOverlayReadiness) { + mThemeOverlayReadiness.remove(userId); + } } @Override @@ -19391,6 +19460,11 @@ public class ActivityManagerService extends IActivityManager.Stub return ActivityManagerService.this.clearApplicationUserData(packageName, keepState, isRestore, observer, userId); } + + @Override + public boolean getThemeOverlayReadiness() { + return ActivityManagerService.this.getThemeOverlayReadiness(); + } } 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 25646f19c461..609ad1e76370 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -83,6 +83,7 @@ import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_NONE; import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION; import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING; +import static com.android.systemui.shared.Flags.enableHomeDelay; import static java.lang.Integer.MAX_VALUE; @@ -1444,6 +1445,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> aInfo = info.first; homeIntent = info.second; } + if (aInfo == null || homeIntent == null) { return false; } @@ -1452,6 +1454,11 @@ class RootWindowContainer extends WindowContainer<DisplayContent> return false; } + if (enableHomeDelay() && !mService.mAmInternal.getThemeOverlayReadiness()) { + 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 90493d4dc95f..295b124c06e0 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java +++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java @@ -346,6 +346,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).getThemeOverlayReadiness(); LocalServices.addService(ActivityManagerInternal.class, amInternal); final ActivityManagerService amService = |