Move DozeParameters content provider registrations to bg

This uses new async API to register content providers.

Bug: 351766769
Flag: com.android.systemui.register_content_observers_async
Test: unit tests, perfetto trace
Change-Id: Ie7445d396588d302805e8e6b8b713176cb4e404e
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index 6e6e4b2..b580eb1 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -1171,3 +1171,12 @@
   bug: "345227709"
 }
 
+flag {
+  namespace: "systemui"
+  name: "register_content_observers_async"
+  description: "Use new Async API to register content observers"
+  bug: "316922634"
+  metadata {
+    purpose: PURPOSE_BUGFIX
+  }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index a11cbc3..98869be 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -37,6 +37,7 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.systemui.Dumpable;
+import com.android.systemui.Flags;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
@@ -54,6 +55,7 @@
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.unfold.FoldAodAnimationController;
 import com.android.systemui.unfold.SysUIUnfoldComponent;
+import com.android.systemui.util.settings.SecureSettings;
 
 import java.io.PrintWriter;
 import java.util.Optional;
@@ -86,6 +88,7 @@
     private final FoldAodAnimationController mFoldAodAnimationController;
     private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
     private final UserTracker mUserTracker;
+    private final SecureSettings mSecureSettings;
 
     private boolean mDozeAlwaysOn;
     private boolean mControlScreenOffAnimation;
@@ -130,7 +133,8 @@
             ConfigurationController configurationController,
             StatusBarStateController statusBarStateController,
             UserTracker userTracker,
-            DozeInteractor dozeInteractor) {
+            DozeInteractor dozeInteractor,
+            SecureSettings secureSettings) {
         mResources = resources;
         mAmbientDisplayConfiguration = ambientDisplayConfiguration;
         mAlwaysOnPolicy = alwaysOnDisplayPolicy;
@@ -144,6 +148,7 @@
         mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
         mUserTracker = userTracker;
         mDozeInteractor = dozeInteractor;
+        mSecureSettings = secureSettings;
 
         keyguardUpdateMonitor.registerCallback(mKeyguardVisibilityCallback);
         tunerService.addTunable(
@@ -160,7 +165,8 @@
             mFoldAodAnimationController.addCallback(this);
         }
 
-        SettingsObserver quickPickupSettingsObserver = new SettingsObserver(context, handler);
+        SettingsObserver quickPickupSettingsObserver =
+                new SettingsObserver(context, handler, mSecureSettings);
         quickPickupSettingsObserver.observe();
 
         batteryController.addCallback(new BatteryStateChangeCallback() {
@@ -479,18 +485,36 @@
                 Settings.Secure.getUriFor(Settings.Secure.DOZE_ALWAYS_ON);
         private final Context mContext;
 
-        SettingsObserver(Context context, Handler handler) {
+        private final Handler mHandler;
+        private final SecureSettings mSecureSettings;
+
+        SettingsObserver(Context context, Handler handler, SecureSettings secureSettings) {
             super(handler);
             mContext = context;
+            mHandler = handler;
+            mSecureSettings = secureSettings;
         }
 
         void observe() {
-            ContentResolver resolver = mContext.getContentResolver();
-            resolver.registerContentObserver(mQuickPickupGesture, false, this,
-                    UserHandle.USER_ALL);
-            resolver.registerContentObserver(mPickupGesture, false, this, UserHandle.USER_ALL);
-            resolver.registerContentObserver(mAlwaysOnEnabled, false, this, UserHandle.USER_ALL);
-            update(null);
+            if (Flags.registerContentObserversAsync()) {
+                mSecureSettings.registerContentObserverForUserAsync(mQuickPickupGesture,
+                        this, UserHandle.USER_ALL);
+                mSecureSettings.registerContentObserverForUserAsync(mPickupGesture,
+                        this, UserHandle.USER_ALL);
+                mSecureSettings.registerContentObserverForUserAsync(mAlwaysOnEnabled,
+                        this, UserHandle.USER_ALL,
+                        // The register calls are called in order, so this ensures that update()
+                        // is called after them all and value retrieval isn't racy.
+                        () -> mHandler.post(() -> update(null)));
+            } else {
+                ContentResolver resolver = mContext.getContentResolver();
+                resolver.registerContentObserver(mQuickPickupGesture, false, this,
+                        UserHandle.USER_ALL);
+                resolver.registerContentObserver(mPickupGesture, false, this, UserHandle.USER_ALL);
+                resolver.registerContentObserver(mAlwaysOnEnabled, false, this,
+                        UserHandle.USER_ALL);
+                update(null);
+            }
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/util/settings/UserSettingsProxy.kt b/packages/SystemUI/src/com/android/systemui/util/settings/UserSettingsProxy.kt
index 3bf5b65..025354b 100644
--- a/packages/SystemUI/src/com/android/systemui/util/settings/UserSettingsProxy.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/settings/UserSettingsProxy.kt
@@ -21,6 +21,7 @@
 import android.net.Uri
 import android.os.UserHandle
 import android.provider.Settings.SettingNotFoundException
+import androidx.annotation.WorkerThread
 import com.android.app.tracing.TraceUtils.trace
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.util.settings.SettingsProxy.Companion.parseFloat
@@ -199,6 +200,24 @@
         }
 
     /**
+     * Convenience wrapper around [ContentResolver.registerContentObserver].'
+     *
+     * API corresponding to [registerContentObserverForUser] for Java usage. After registration is
+     * complete, the callback block is called on the <b>background thread</b> to allow for update of
+     * value.
+     */
+    fun registerContentObserverForUserAsync(
+        uri: Uri,
+        settingsObserver: ContentObserver,
+        userHandle: Int,
+        @WorkerThread registered: Runnable
+    ) =
+        CoroutineScope(backgroundDispatcher).launch {
+            registerContentObserverForUserSync(uri, settingsObserver, userHandle)
+            registered.run()
+        }
+
+    /**
      * Convenience wrapper around [ContentResolver.registerContentObserver]
      *
      * Implicitly calls [getUriFor] on the passed in name.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
index 7cb41f1..10d07a0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
@@ -35,8 +35,8 @@
 import android.os.PowerManager;
 import android.provider.Settings;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
 
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.SysuiTestCase;
@@ -52,6 +52,7 @@
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.unfold.FoldAodAnimationController;
 import com.android.systemui.unfold.SysUIUnfoldComponent;
+import com.android.systemui.util.settings.FakeSettings;
 
 import org.junit.Assert;
 import org.junit.Before;
@@ -130,7 +131,8 @@
             mConfigurationController,
             mStatusBarStateController,
             mUserTracker,
-            mDozeInteractor
+            mDozeInteractor,
+            new FakeSettings()
         );
 
         verify(mBatteryController).addCallback(mBatteryStateChangeCallback.capture());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/settings/UserSettingsProxyTest.kt b/packages/SystemUI/tests/src/com/android/systemui/util/settings/UserSettingsProxyTest.kt
index e3e20c8..5f7420d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/settings/UserSettingsProxyTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/settings/UserSettingsProxyTest.kt
@@ -31,9 +31,11 @@
 import com.android.systemui.settings.UserTracker
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.test.StandardTestDispatcher
 import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.advanceUntilIdle
 import kotlinx.coroutines.test.runTest
 import org.junit.Assert.assertThrows
 import org.junit.Before
@@ -65,20 +67,21 @@
     }
 
     @Test
-    fun registerContentObserverForUser_inputString_success() {
-        mSettings.registerContentObserverForUserSync(
-            TEST_SETTING,
-            mContentObserver,
-            mUserTracker.userId
-        )
-        verify(mSettings.getContentResolver())
-            .registerContentObserver(
-                eq(TEST_SETTING_URI),
-                eq(false),
-                eq(mContentObserver),
-                eq(MAIN_USER_ID)
+    fun registerContentObserverForUser_inputString_success() =
+        testScope.runTest {
+            mSettings.registerContentObserverForUserSync(
+                TEST_SETTING,
+                mContentObserver,
+                mUserTracker.userId
             )
-    }
+            verify(mSettings.getContentResolver())
+                .registerContentObserver(
+                    eq(TEST_SETTING_URI),
+                    eq(false),
+                    eq(mContentObserver),
+                    eq(MAIN_USER_ID)
+                )
+        }
 
     @Test
     fun registerContentObserverForUserSuspend_inputString_success() =
@@ -98,13 +101,14 @@
         }
 
     @Test
-    fun registerContentObserverForUserAsync_inputString_success() {
-        mSettings.registerContentObserverForUserAsync(
-            TEST_SETTING,
-            mContentObserver,
-            mUserTracker.userId
-        )
-        testScope.launch {
+    fun registerContentObserverForUserAsync_inputString_success() =
+        testScope.runTest {
+            mSettings.registerContentObserverForUserAsync(
+                TEST_SETTING,
+                mContentObserver,
+                mUserTracker.userId
+            )
+            testScope.advanceUntilIdle()
             verify(mSettings.getContentResolver())
                 .registerContentObserver(
                     eq(TEST_SETTING_URI),
@@ -113,24 +117,24 @@
                     eq(MAIN_USER_ID)
                 )
         }
-    }
 
     @Test
-    fun registerContentObserverForUser_inputString_notifyForDescendants_true() {
-        mSettings.registerContentObserverForUserSync(
-            TEST_SETTING,
-            notifyForDescendants = true,
-            mContentObserver,
-            mUserTracker.userId
-        )
-        verify(mSettings.getContentResolver())
-            .registerContentObserver(
-                eq(TEST_SETTING_URI),
-                eq(true),
-                eq(mContentObserver),
-                eq(MAIN_USER_ID)
+    fun registerContentObserverForUser_inputString_notifyForDescendants_true() =
+        testScope.runTest {
+            mSettings.registerContentObserverForUserSync(
+                TEST_SETTING,
+                notifyForDescendants = true,
+                mContentObserver,
+                mUserTracker.userId
             )
-    }
+            verify(mSettings.getContentResolver())
+                .registerContentObserver(
+                    eq(TEST_SETTING_URI),
+                    eq(true),
+                    eq(mContentObserver),
+                    eq(MAIN_USER_ID)
+                )
+        }
 
     @Test
     fun registerContentObserverForUserSuspend_inputString_notifyForDescendants_true() =
@@ -153,14 +157,15 @@
         }
 
     @Test
-    fun registerContentObserverForUserAsync_inputString_notifyForDescendants_true() {
-        mSettings.registerContentObserverForUserAsync(
-            TEST_SETTING,
-            notifyForDescendants = true,
-            mContentObserver,
-            mUserTracker.userId
-        )
-        testScope.launch {
+    fun registerContentObserverForUserAsync_inputString_notifyForDescendants_true() =
+        testScope.runTest {
+            mSettings.registerContentObserverForUserAsync(
+                TEST_SETTING,
+                notifyForDescendants = true,
+                mContentObserver,
+                mUserTracker.userId
+            )
+            testScope.advanceUntilIdle()
             verify(mSettings.getContentResolver())
                 .registerContentObserver(
                     eq(TEST_SETTING_URI),
@@ -169,23 +174,23 @@
                     eq(MAIN_USER_ID)
                 )
         }
-    }
 
     @Test
-    fun registerContentObserverForUser_inputUri_success() {
-        mSettings.registerContentObserverForUserSync(
-            TEST_SETTING_URI,
-            mContentObserver,
-            mUserTracker.userId
-        )
-        verify(mSettings.getContentResolver())
-            .registerContentObserver(
-                eq(TEST_SETTING_URI),
-                eq(false),
-                eq(mContentObserver),
-                eq(MAIN_USER_ID)
+    fun registerContentObserverForUser_inputUri_success() =
+        testScope.runTest {
+            mSettings.registerContentObserverForUserSync(
+                TEST_SETTING_URI,
+                mContentObserver,
+                mUserTracker.userId
             )
-    }
+            verify(mSettings.getContentResolver())
+                .registerContentObserver(
+                    eq(TEST_SETTING_URI),
+                    eq(false),
+                    eq(mContentObserver),
+                    eq(MAIN_USER_ID)
+                )
+        }
 
     @Test
     fun registerContentObserverForUserSuspend_inputUri_success() =
@@ -205,13 +210,15 @@
         }
 
     @Test
-    fun registerContentObserverForUserAsync_inputUri_success() {
-        mSettings.registerContentObserverForUserAsync(
-            TEST_SETTING_URI,
-            mContentObserver,
-            mUserTracker.userId
-        )
-        testScope.launch {
+    fun registerContentObserverForUserAsync_inputUri_success() =
+        testScope.runTest {
+            mSettings.registerContentObserverForUserAsync(
+                TEST_SETTING_URI,
+                mContentObserver,
+                mUserTracker.userId
+            )
+            testScope.advanceUntilIdle()
+
             verify(mSettings.getContentResolver())
                 .registerContentObserver(
                     eq(TEST_SETTING_URI),
@@ -220,24 +227,41 @@
                     eq(MAIN_USER_ID)
                 )
         }
-    }
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    @Test
+    fun registerContentObserverForUserAsync_callbackAfterRegister() =
+        testScope.runTest {
+            var callbackCalled = false
+            val runnable = { callbackCalled = true }
+
+            mSettings.registerContentObserverForUserAsync(
+                TEST_SETTING_URI,
+                mContentObserver,
+                mUserTracker.userId,
+                runnable
+            )
+            testScope.advanceUntilIdle()
+            assertThat(callbackCalled).isTrue()
+        }
 
     @Test
-    fun registerContentObserverForUser_inputUri_notifyForDescendants_true() {
-        mSettings.registerContentObserverForUserSync(
-            TEST_SETTING_URI,
-            notifyForDescendants = true,
-            mContentObserver,
-            mUserTracker.userId
-        )
-        verify(mSettings.getContentResolver())
-            .registerContentObserver(
-                eq(TEST_SETTING_URI),
-                eq(true),
-                eq(mContentObserver),
-                eq(MAIN_USER_ID)
+    fun registerContentObserverForUser_inputUri_notifyForDescendants_true() =
+        testScope.runTest {
+            mSettings.registerContentObserverForUserSync(
+                TEST_SETTING_URI,
+                notifyForDescendants = true,
+                mContentObserver,
+                mUserTracker.userId
             )
-    }
+            verify(mSettings.getContentResolver())
+                .registerContentObserver(
+                    eq(TEST_SETTING_URI),
+                    eq(true),
+                    eq(mContentObserver),
+                    eq(MAIN_USER_ID)
+                )
+        }
 
     @Test
     fun registerContentObserverForUserSuspend_inputUri_notifyForDescendants_true() =
@@ -260,14 +284,15 @@
         }
 
     @Test
-    fun registerContentObserverForUserAsync_inputUri_notifyForDescendants_true() {
-        mSettings.registerContentObserverForUserAsync(
-            TEST_SETTING_URI,
-            notifyForDescendants = true,
-            mContentObserver,
-            mUserTracker.userId
-        )
-        testScope.launch {
+    fun registerContentObserverForUserAsync_inputUri_notifyForDescendants_true() =
+        testScope.runTest {
+            mSettings.registerContentObserverForUserAsync(
+                TEST_SETTING_URI,
+                notifyForDescendants = true,
+                mContentObserver,
+                mUserTracker.userId
+            )
+            testScope.advanceUntilIdle()
             verify(mSettings.getContentResolver())
                 .registerContentObserver(
                     eq(TEST_SETTING_URI),
@@ -276,14 +301,19 @@
                     eq(MAIN_USER_ID)
                 )
         }
-    }
 
     @Test
-    fun registerContentObserver_inputUri_success() {
-        mSettings.registerContentObserverSync(TEST_SETTING_URI, mContentObserver)
-        verify(mSettings.getContentResolver())
-            .registerContentObserver(eq(TEST_SETTING_URI), eq(false), eq(mContentObserver), eq(0))
-    }
+    fun registerContentObserver_inputUri_success() =
+        testScope.runTest {
+            mSettings.registerContentObserverSync(TEST_SETTING_URI, mContentObserver)
+            verify(mSettings.getContentResolver())
+                .registerContentObserver(
+                    eq(TEST_SETTING_URI),
+                    eq(false),
+                    eq(mContentObserver),
+                    eq(0)
+                )
+        }
 
     @Test
     fun registerContentObserverSuspend_inputUri_success() =
@@ -313,15 +343,21 @@
     }
 
     @Test
-    fun registerContentObserver_inputUri_notifyForDescendants_true() {
-        mSettings.registerContentObserverSync(
-            TEST_SETTING_URI,
-            notifyForDescendants = true,
-            mContentObserver
-        )
-        verify(mSettings.getContentResolver())
-            .registerContentObserver(eq(TEST_SETTING_URI), eq(true), eq(mContentObserver), eq(0))
-    }
+    fun registerContentObserver_inputUri_notifyForDescendants_true() =
+        testScope.runTest {
+            mSettings.registerContentObserverSync(
+                TEST_SETTING_URI,
+                notifyForDescendants = true,
+                mContentObserver
+            )
+            verify(mSettings.getContentResolver())
+                .registerContentObserver(
+                    eq(TEST_SETTING_URI),
+                    eq(true),
+                    eq(mContentObserver),
+                    eq(0)
+                )
+        }
 
     @Test
     fun registerContentObserverSuspend_inputUri_notifyForDescendants_true() =
@@ -337,18 +373,19 @@
         }
 
     @Test
-    fun registerContentObserverAsync_inputUri_notifyForDescendants_true() {
-        mSettings.registerContentObserverAsync(TEST_SETTING_URI, mContentObserver)
-        testScope.launch {
-            verify(mSettings.getContentResolver())
-                .registerContentObserver(
-                    eq(TEST_SETTING_URI),
-                    eq(false),
-                    eq(mContentObserver),
-                    eq(0)
-                )
+    fun registerContentObserverAsync_inputUri_notifyForDescendants_true() =
+        testScope.runTest {
+            mSettings.registerContentObserverAsync(TEST_SETTING_URI, mContentObserver)
+            testScope.launch {
+                verify(mSettings.getContentResolver())
+                    .registerContentObserver(
+                        eq(TEST_SETTING_URI),
+                        eq(false),
+                        eq(mContentObserver),
+                        eq(0)
+                    )
+            }
         }
-    }
 
     @Test
     fun getString_keyPresent_returnValidValue() {