Merge "Make the btservices apex updatable." into tm-mainline-prod
diff --git a/apex/Android.bp b/apex/Android.bp
index edece23..82f74d9 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -97,8 +97,11 @@
 
 sdk {
     name: "btservices-module-sdk",
-    bootclasspath_fragments: ["com.android.btservices-bootclasspath-fragment"],
-    systemserverclasspath_fragments: ["com.android.btservices-systemserverclasspath-fragment"],
+    apexes: [
+        // Adds exportable dependencies of the APEX to the sdk,
+        // e.g. *classpath_fragments.
+        "com.android.btservices",
+    ],
 }
 
 // Encapsulate the contributions made by the com.android.bluetooth to the bootclasspath.
diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java
index 042a435..dda3f04 100644
--- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java
+++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java
@@ -56,6 +56,7 @@
 import android.content.IntentFilter;
 import android.content.ServiceConnection;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.database.ContentObserver;
@@ -2892,24 +2893,56 @@
      */
     private void updateOppLauncherComponentState(UserHandle userHandle,
             boolean bluetoothSharingDisallowed) {
-        final ComponentName oppLauncherComponent = new ComponentName(
-                mContext.getPackageManager().getPackagesForUid(Process.BLUETOOTH_UID)[0],
-                "com.android.bluetooth.opp.BluetoothOppLauncherActivity");
-        int newState;
-        if (bluetoothSharingDisallowed) {
-            newState = PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
-        } else if (BluetoothProperties.isProfileOppEnabled().orElse(false)) {
-            newState = PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
-        } else {
-            newState = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
-        }
         try {
-            mContext.createContextAsUser(userHandle, 0)
-                .getPackageManager()
-                .setComponentEnabledSetting(oppLauncherComponent, newState,
-                        PackageManager.DONT_KILL_APP);
+            int newState;
+            if (bluetoothSharingDisallowed) {
+                newState = PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+            } else if (BluetoothProperties.isProfileOppEnabled().orElse(false)) {
+                newState = PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+            } else {
+                newState = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
+            }
+
+            String launcherActivity = "com.android.bluetooth.opp.BluetoothOppLauncherActivity";
+
+            PackageManager packageManager = mContext.createContextAsUser(userHandle, 0)
+                                                        .getPackageManager();
+            var allPackages = packageManager.getPackagesForUid(Process.BLUETOOTH_UID);
+            for (String candidatePackage : allPackages) {
+                PackageInfo packageInfo;
+                try {
+                    // note: we need the package manager for the SYSTEM user, not our userHandle
+                    packageInfo = mContext.getPackageManager().getPackageInfo(
+                        candidatePackage,
+                        PackageManager.PackageInfoFlags.of(PackageManager.GET_ACTIVITIES));
+                } catch (PackageManager.NameNotFoundException e) {
+                    // ignore, try next package
+                    Log.e(TAG, "Could not find package " + candidatePackage);
+                    continue;
+                } catch (Exception e) {
+                    Log.e(TAG, "Error while loading package" + e);
+                    continue;
+                }
+                if (packageInfo.activities == null) {
+                    continue;
+                }
+                for (var activity : packageInfo.activities) {
+                    if (launcherActivity.equals(activity.name)) {
+                        final ComponentName oppLauncherComponent = new ComponentName(
+                                candidatePackage, launcherActivity
+                        );
+                        packageManager.setComponentEnabledSetting(
+                                oppLauncherComponent, newState, PackageManager.DONT_KILL_APP
+                        );
+                        return;
+                    }
+                }
+            }
+
+            Log.e(TAG,
+                    "Cannot toggle BluetoothOppLauncherActivity, could not find it in any package");
         } catch (Exception e) {
-            // The component was not found, do nothing.
+            Log.e(TAG, "updateOppLauncherComponentState failed: " + e);
         }
     }
 
diff --git a/system/stack/gatt/gatt_utils.cc b/system/stack/gatt/gatt_utils.cc
index 991944a..661fc6f 100644
--- a/system/stack/gatt/gatt_utils.cc
+++ b/system/stack/gatt/gatt_utils.cc
@@ -1397,7 +1397,12 @@
 /** Cancel LE Create Connection request */
 bool gatt_cancel_open(tGATT_IF gatt_if, const RawAddress& bda) {
   tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bda, BT_TRANSPORT_LE);
-  if (!p_tcb) return true;
+  if (!p_tcb) {
+    LOG_WARN(
+        "Unable to cancel open for unknown connection gatt_if:%hhu peer:%s",
+        gatt_if, PRIVATE_ADDRESS(bda));
+    return true;
+  }
 
   if (gatt_get_ch_state(p_tcb) == GATT_CH_OPEN) {
     LOG(ERROR) << __func__ << ": link connected Too late to cancel";
@@ -1406,9 +1411,21 @@
 
   gatt_update_app_use_link_flag(gatt_if, p_tcb, false, false);
 
-  if (p_tcb->app_hold_link.empty()) gatt_disconnect(p_tcb);
+  if (p_tcb->app_hold_link.empty()) {
+    LOG_DEBUG(
+        "Client reference count is zero disconnecting device gatt_if:%hhu "
+        "peer:%s",
+        gatt_if, PRIVATE_ADDRESS(bda));
+    gatt_disconnect(p_tcb);
+  }
 
-  connection_manager::direct_connect_remove(gatt_if, bda);
+  if (!connection_manager::direct_connect_remove(gatt_if, bda)) {
+    BTM_AcceptlistRemove(bda);
+    LOG_INFO(
+        "GATT connection manager has no record but removed filter acceptlist "
+        "gatt_if:%hhu peer:%s",
+        gatt_if, PRIVATE_ADDRESS(bda));
+  }
   return true;
 }