Dialer: Request BLUETOOTH_CONNECT

* When we want to use the bluetooth device alias, we require the
  permission first.
* Ask the user to grant the permission but don't enforce it - we have
  a default string being shown

Change-Id: Ifa3733595741c1481ae0ab69f5026bb4f05f2a9a
diff --git a/java/com/android/incallui/incall/impl/InCallFragment.java b/java/com/android/incallui/incall/impl/InCallFragment.java
index e02369a..ed194f4 100644
--- a/java/com/android/incallui/incall/impl/InCallFragment.java
+++ b/java/com/android/incallui/incall/impl/InCallFragment.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2016 The Android Open Source Project
- * Copyright (C) 2023 The LineageOS Project
+ * Copyright (C) 2023-2024 The LineageOS Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
 
 package com.android.incallui.incall.impl;
 
+import android.Manifest;
 import android.Manifest.permission;
 import android.annotation.SuppressLint;
 import android.app.Activity;
@@ -101,6 +102,7 @@
   private int voiceNetworkType;
   private int phoneType;
   private boolean stateRestored;
+  private boolean userDeniedBluetooth;
 
   private final ActivityResultLauncher<String[]> permissionLauncher = registerForActivityResult(
           new ActivityResultContracts.RequestMultiplePermissions(),
@@ -111,6 +113,17 @@
             }
           });
 
+  private final ActivityResultLauncher<String[]> bluetoothPermissionLauncher =
+          registerForActivityResult(
+                  new ActivityResultContracts.RequestMultiplePermissions(),
+                  grantResults -> {
+                    boolean allGranted = grantResults.values().stream().allMatch(x -> x);
+                    inCallButtonUiDelegate.showAudioRouteSelector();
+                    if (!allGranted) {
+                      userDeniedBluetooth = true;
+                    }
+                  });
+
   // Add animation to educate users. If a call has enriched calling attachments then we'll
   // initially show the attachment page. After a delay seconds we'll animate to the button grid.
   private final Handler handler = new Handler(Looper.getMainLooper());
@@ -509,8 +522,22 @@
 
   @Override
   public void showAudioRouteSelector() {
-    AudioRouteSelectorDialogFragment.newInstance(inCallButtonUiDelegate.getCurrentAudioState())
-        .show(getChildFragmentManager(), null);
+    String[] permissions = new String[]{Manifest.permission.BLUETOOTH_CONNECT};
+    if (hasAllPermissions(permissions) || userDeniedBluetooth) {
+      AudioRouteSelectorDialogFragment.newInstance(inCallButtonUiDelegate.getCurrentAudioState())
+              .show(getChildFragmentManager(), null);
+    } else {
+      bluetoothPermissionLauncher.launch(permissions);
+    }
+  }
+
+  private boolean hasAllPermissions(String[] permissions) {
+    for (String p : permissions) {
+      if (requireContext().checkSelfPermission(p) != PackageManager.PERMISSION_GRANTED) {
+        return false;
+      }
+    }
+    return true;
   }
 
   @Override