[VolumePanel] Add Hearable control slice in VolumePanel

Bug: 229048602
Test: make -j64 RunSettingsRoboTests
Change-Id: Ia799a805594803a9a014eef76bb3db5a50a13524
diff --git a/src/com/android/settings/panel/VolumePanel.java b/src/com/android/settings/panel/VolumePanel.java
index e0d8a7f..98939cf 100644
--- a/src/com/android/settings/panel/VolumePanel.java
+++ b/src/com/android/settings/panel/VolumePanel.java
@@ -27,30 +27,43 @@
 import static com.android.settings.slices.CustomSliceRegistry.VOLUME_RINGER_URI;
 
 import android.app.settings.SettingsEnums;
+import android.bluetooth.BluetoothDevice;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.net.Uri;
 import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.Log;
 
 import androidx.lifecycle.LifecycleObserver;
 import androidx.lifecycle.OnLifecycleEvent;
 
 import com.android.settings.R;
+import com.android.settings.bluetooth.Utils;
+import com.android.settingslib.bluetooth.A2dpProfile;
+import com.android.settingslib.bluetooth.BluetoothUtils;
+import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
 import com.android.settingslib.media.MediaOutputConstants;
 
 import java.util.ArrayList;
+import java.util.IllegalFormatException;
 import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.FutureTask;
 
 /**
  * Panel data class for Volume settings.
  */
 public class VolumePanel implements PanelContent, LifecycleObserver {
+    private static final String TAG = "VolumePanel";
 
     private final Context mContext;
 
     private PanelContentCallback mCallback;
+    private LocalBluetoothProfileManager mProfileManager;
 
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
@@ -67,6 +80,21 @@
 
     private VolumePanel(Context context) {
         mContext = context.getApplicationContext();
+
+        final FutureTask<LocalBluetoothManager> localBtManagerFutureTask = new FutureTask<>(
+                // Avoid StrictMode ThreadPolicy violation
+                () -> Utils.getLocalBtManager(mContext));
+        LocalBluetoothManager localBluetoothManager;
+        try {
+            localBtManagerFutureTask.run();
+            localBluetoothManager = localBtManagerFutureTask.get();
+        } catch (InterruptedException | ExecutionException e) {
+            Log.w(TAG, "Error getting LocalBluetoothManager.");
+            return;
+        }
+        if (localBluetoothManager != null) {
+            mProfileManager = localBluetoothManager.getProfileManager();
+        }
     }
 
     /** Invoked when the panel is resumed. */
@@ -95,6 +123,11 @@
 
         uris.add(REMOTE_MEDIA_SLICE_URI);
         uris.add(VOLUME_MEDIA_URI);
+        Uri controlUri = getExtraControlUri();
+        if (controlUri != null) {
+            Log.d(TAG, "add extra control slice");
+            uris.add(controlUri);
+        }
         uris.add(MEDIA_OUTPUT_INDICATOR_SLICE_URI);
         uris.add(VOLUME_CALL_URI);
         uris.add(VOLUME_RINGER_URI);
@@ -121,4 +154,33 @@
     public void registerCallback(PanelContentCallback callback) {
         mCallback = callback;
     }
+
+    private Uri getExtraControlUri() {
+        Uri controlUri = null;
+        final BluetoothDevice bluetoothDevice = findActiveDevice();
+        if (bluetoothDevice != null) {
+            final int width = mContext.getResources().getDimensionPixelSize(
+                    R.dimen.settings_panel_width);
+            final String uri = BluetoothUtils.getControlUriMetaData(bluetoothDevice);
+            if (!TextUtils.isEmpty(uri)) {
+                try {
+                    controlUri = Uri.parse(String.format(uri, width));
+                } catch (IllegalFormatException | NullPointerException exception) {
+                    Log.d(TAG, "unable to parse uri");
+                    controlUri = null;
+                }
+            }
+        }
+        return controlUri;
+    }
+
+    private BluetoothDevice findActiveDevice() {
+        if (mProfileManager != null) {
+            final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
+            if (a2dpProfile != null) {
+                return a2dpProfile.getActiveDevice();
+            }
+        }
+        return null;
+    }
 }
\ No newline at end of file