Move hasHeadTracker to background thread in device details page

BUG: 316490612
Test: atest BluetoothDetailsSpatialAudioControllerTest
Change-Id: Ic9ca426190bd6389c05272416c87fbf9da392abd
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioController.java b/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioController.java
index c0869b2..e5fb365 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioController.java
@@ -37,6 +37,9 @@
 import com.android.settings.overlay.FeatureFactory;
 import com.android.settingslib.bluetooth.CachedBluetoothDevice;
 import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.utils.ThreadUtils;
+
+import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * The controller of the Spatial audio setting in the bluetooth detail settings.
@@ -56,6 +59,8 @@
     @VisibleForTesting
     AudioDeviceAttributes mAudioDevice = null;
 
+    AtomicBoolean mHasHeadTracker = new AtomicBoolean(false);
+
     public BluetoothDetailsSpatialAudioController(
             Context context,
             PreferenceFragmentCompat fragment,
@@ -77,7 +82,13 @@
         String key = switchPreference.getKey();
         if (TextUtils.equals(key, KEY_SPATIAL_AUDIO)) {
             updateSpatializerEnabled(switchPreference.isChecked());
-            refreshSpatialAudioEnabled(switchPreference);
+            ThreadUtils.postOnBackgroundThread(
+                    () -> {
+                        mHasHeadTracker.set(
+                                mAudioDevice != null && mSpatializer.hasHeadTracker(mAudioDevice));
+                        mContext.getMainExecutor()
+                                .execute(() -> refreshSpatialAudioEnabled(switchPreference));
+                    });
             return true;
         } else if (TextUtils.equals(key, KEY_HEAD_TRACKING)) {
             updateSpatializerHeadTracking(switchPreference.isChecked());
@@ -124,7 +135,15 @@
         if (mAudioDevice == null) {
             getAvailableDevice();
         }
+        ThreadUtils.postOnBackgroundThread(
+                () -> {
+                    mHasHeadTracker.set(
+                            mAudioDevice != null && mSpatializer.hasHeadTracker(mAudioDevice));
+                    mContext.getMainExecutor().execute(this::refreshUi);
+                });
+    }
 
+    private void refreshUi() {
         TwoStatePreference spatialAudioPref = mProfilesContainer.findPreference(KEY_SPATIAL_AUDIO);
         if (spatialAudioPref == null && mAudioDevice != null) {
             spatialAudioPref = createSpatialAudioPreference(mProfilesContainer.getContext());
@@ -145,7 +164,8 @@
         refreshSpatialAudioEnabled(spatialAudioPref);
     }
 
-    private void refreshSpatialAudioEnabled(TwoStatePreference spatialAudioPref) {
+    private void refreshSpatialAudioEnabled(
+            TwoStatePreference spatialAudioPref) {
         boolean isSpatialAudioOn = mSpatializer.getCompatibleAudioDevices().contains(mAudioDevice);
         Log.d(TAG, "refresh() isSpatialAudioOn : " + isSpatialAudioOn);
         spatialAudioPref.setChecked(isSpatialAudioOn);
@@ -160,9 +180,8 @@
 
     private void refreshHeadTracking(TwoStatePreference spatialAudioPref,
             TwoStatePreference headTrackingPref) {
-        boolean isHeadTrackingAvailable =
-                spatialAudioPref.isChecked() && mSpatializer.hasHeadTracker(mAudioDevice);
-        Log.d(TAG, "refresh() has head tracker : " + mSpatializer.hasHeadTracker(mAudioDevice));
+        boolean isHeadTrackingAvailable = spatialAudioPref.isChecked() && mHasHeadTracker.get();
+        Log.d(TAG, "refresh() has head tracker : " + mHasHeadTracker.get());
         headTrackingPref.setVisible(isHeadTrackingAvailable);
         if (isHeadTrackingAvailable) {
             headTrackingPref.setChecked(mSpatializer.isHeadTrackerEnabled(mAudioDevice));
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioControllerTest.java
index de70330..2cc55a7 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioControllerTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsSpatialAudioControllerTest.java
@@ -43,6 +43,7 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowLooper;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -120,6 +121,7 @@
         when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices);
 
         mController.refresh();
+        ShadowLooper.idleMainLooper();
 
         assertThat(mSpatialAudioPref.isChecked()).isTrue();
     }
@@ -130,6 +132,7 @@
         when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices);
 
         mController.refresh();
+        ShadowLooper.idleMainLooper();
 
         assertThat(mSpatialAudioPref.isChecked()).isFalse();
     }
@@ -142,6 +145,7 @@
         when(mSpatializer.hasHeadTracker(mController.mAudioDevice)).thenReturn(true);
 
         mController.refresh();
+        ShadowLooper.idleMainLooper();
 
         assertThat(mHeadTrackingPref.isVisible()).isTrue();
     }
@@ -156,6 +160,7 @@
         when(mSpatializer.hasHeadTracker(mController.mAudioDevice)).thenReturn(false);
 
         mController.refresh();
+        ShadowLooper.idleMainLooper();
 
         verify(mProfilesContainer).removePreference(mHeadTrackingPref);
     }
@@ -166,6 +171,7 @@
         when(mSpatializer.getCompatibleAudioDevices()).thenReturn(compatibleAudioDevices);
 
         mController.refresh();
+        ShadowLooper.idleMainLooper();
 
         verify(mProfilesContainer).removePreference(mHeadTrackingPref);
     }
@@ -181,6 +187,7 @@
         when(mSpatializer.isHeadTrackerEnabled(mController.mAudioDevice)).thenReturn(true);
 
         mController.refresh();
+        ShadowLooper.idleMainLooper();
 
         assertThat(mHeadTrackingPref.isChecked()).isTrue();
     }
@@ -196,6 +203,7 @@
         when(mSpatializer.isHeadTrackerEnabled(mController.mAudioDevice)).thenReturn(false);
 
         mController.refresh();
+        ShadowLooper.idleMainLooper();
 
         assertThat(mHeadTrackingPref.isChecked()).isFalse();
     }