From f745fd611b22c6b13cb4d942947bd97cdf53af6b Mon Sep 17 00:00:00 2001 From: Evan Chen Date: Thu, 27 Apr 2023 19:31:02 +0000 Subject: Notify/bind app after the phone is unlocked CDM is not able to bind the app before the phone is unlocked(if password was set) if the app is not boot aware. This cl contains: 1. Store the the device info when receive the BT.onDeviceConnected() if !UserManager.isUserUnlockingOrUnlocked which means CDM received the bt callback before user unlock the phone. 2. Trigger the callback in SystemService.onUserUnlocked() if we find any devices info were stored Bug: 235614233,276311331 Fix: 279789812 Test: manully test Change-Id: I13ffc67bb5b1cf74b537f9fc0c12d883d6904034 --- .../companion/CompanionDeviceManagerService.java | 20 +++++++- ...BluetoothCompanionDeviceConnectionListener.java | 54 ++++++++++++++++++++-- .../presence/CompanionDevicePresenceMonitor.java | 21 +++++++-- 3 files changed, 85 insertions(+), 10 deletions(-) diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java index 0172eaf03fa7..c8db662a7f49 100644 --- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java +++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java @@ -54,6 +54,7 @@ import android.app.ActivityManagerInternal; import android.app.AppOpsManager; import android.app.NotificationManager; import android.app.PendingIntent; +import android.bluetooth.BluetoothDevice; import android.companion.AssociationInfo; import android.companion.AssociationRequest; import android.companion.DeviceNotAssociatedException; @@ -234,7 +235,7 @@ public class CompanionDeviceManagerService extends SystemService { loadAssociationsFromDisk(); mAssociationStore.registerListener(mAssociationStoreChangeListener); - mDevicePresenceMonitor = new CompanionDevicePresenceMonitor( + mDevicePresenceMonitor = new CompanionDevicePresenceMonitor(mUserManager, mAssociationStore, mDevicePresenceCallback); mAssociationRequestsProcessor = new AssociationRequestsProcessor( @@ -322,6 +323,23 @@ public class CompanionDeviceManagerService extends SystemService { MINUTES.toMillis(10)); } + @Override + public void onUserUnlocked(@NonNull TargetUser user) { + // Notify and bind the app after the phone is unlocked. + final int userId = user.getUserIdentifier(); + final Set blueToothDevices = + mDevicePresenceMonitor.getPendingConnectedDevices().get(userId); + if (blueToothDevices != null) { + for (BluetoothDevice bluetoothDevice : blueToothDevices) { + for (AssociationInfo ai: + mAssociationStore.getAssociationsByAddress(bluetoothDevice.getAddress())) { + Slog.i(TAG, "onUserUnlocked, device id( " + ai.getId() + " ) is connected"); + mDevicePresenceMonitor.onBluetoothCompanionDeviceConnected(ai.getId()); + } + } + } + } + @NonNull AssociationInfo getAssociationWithCallerChecks( @UserIdInt int userId, @NonNull String packageName, @NonNull String macAddress) { diff --git a/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java b/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java index f6b99b551ecb..a5410e448c7b 100644 --- a/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java +++ b/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java @@ -27,17 +27,24 @@ import android.companion.AssociationInfo; import android.net.MacAddress; import android.os.Handler; import android.os.HandlerExecutor; +import android.os.UserHandle; +import android.os.UserManager; import android.util.Log; +import android.util.Slog; +import android.util.SparseArray; +import com.android.internal.annotations.GuardedBy; import com.android.server.companion.AssociationStore; import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; @SuppressLint("LongLogTag") -class BluetoothCompanionDeviceConnectionListener +public class BluetoothCompanionDeviceConnectionListener extends BluetoothAdapter.BluetoothConnectionCallback implements AssociationStore.OnChangeListener { private static final String TAG = "CDM_BluetoothCompanionDeviceConnectionListener"; @@ -48,15 +55,25 @@ class BluetoothCompanionDeviceConnectionListener void onBluetoothCompanionDeviceDisconnected(int associationId); } + private final UserManager mUserManager; private final @NonNull AssociationStore mAssociationStore; private final @NonNull Callback mCallback; /** A set of ALL connected BT device (not only companion.) */ private final @NonNull Map mAllConnectedDevices = new HashMap<>(); - BluetoothCompanionDeviceConnectionListener(@NonNull AssociationStore associationStore, - @NonNull Callback callback) { + /** + * A structure hold the connected BT devices that are pending to be reported to the companion + * app when the user unlocks the local device per userId. + */ + @GuardedBy("mPendingConnectedDevices") + @NonNull + final SparseArray> mPendingConnectedDevices = new SparseArray<>(); + + BluetoothCompanionDeviceConnectionListener(UserManager userManager, + @NonNull AssociationStore associationStore, @NonNull Callback callback) { mAssociationStore = associationStore; mCallback = callback; + mUserManager = userManager; } public void init(@NonNull BluetoothAdapter btAdapter) { @@ -76,12 +93,26 @@ class BluetoothCompanionDeviceConnectionListener if (DEBUG) Log.i(TAG, "onDevice_Connected() " + btDeviceToString(device)); final MacAddress macAddress = MacAddress.fromString(device.getAddress()); + final int userId = UserHandle.myUserId(); + if (mAllConnectedDevices.put(macAddress, device) != null) { if (DEBUG) Log.w(TAG, "Device " + btDeviceToString(device) + " is already connected."); return; } + // Try to bind and notify the app after the phone is unlocked. + if (!mUserManager.isUserUnlockingOrUnlocked(UserHandle.myUserId())) { + Slog.i(TAG, "Current user is not in unlocking or unlocked stage yet. Notify " + + "the application when the phone is unlocked"); + synchronized (mPendingConnectedDevices) { + Set bluetoothDevices = mPendingConnectedDevices.get( + userId, new HashSet<>()); + bluetoothDevices.add(device); + mPendingConnectedDevices.put(userId, bluetoothDevices); + } - onDeviceConnectivityChanged(device, true); + } else { + onDeviceConnectivityChanged(device, true); + } } /** @@ -98,6 +129,8 @@ class BluetoothCompanionDeviceConnectionListener } final MacAddress macAddress = MacAddress.fromString(device.getAddress()); + final int userId = UserHandle.myUserId(); + if (mAllConnectedDevices.remove(macAddress) == null) { if (DEBUG) { Log.w(TAG, "The device wasn't tracked as connected " + btDeviceToString(device)); @@ -105,6 +138,19 @@ class BluetoothCompanionDeviceConnectionListener return; } + // Do not need to report the connectivity since the user is not unlock the phone so + // that cdm is not bind with the app yet. + if (!mUserManager.isUserUnlockingOrUnlocked(userId)) { + synchronized (mPendingConnectedDevices) { + Set bluetoothDevices = mPendingConnectedDevices.get(userId); + if (bluetoothDevices != null) { + bluetoothDevices.remove(device); + } + } + + return; + } + onDeviceConnectivityChanged(device, false); } diff --git a/services/companion/java/com/android/server/companion/presence/CompanionDevicePresenceMonitor.java b/services/companion/java/com/android/server/companion/presence/CompanionDevicePresenceMonitor.java index 4010be922b2c..f6e9415a2a7e 100644 --- a/services/companion/java/com/android/server/companion/presence/CompanionDevicePresenceMonitor.java +++ b/services/companion/java/com/android/server/companion/presence/CompanionDevicePresenceMonitor.java @@ -23,13 +23,16 @@ import android.annotation.NonNull; import android.annotation.SuppressLint; import android.annotation.TestApi; import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; import android.companion.AssociationInfo; import android.content.Context; import android.os.Binder; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.os.UserManager; import android.util.Log; +import android.util.SparseArray; import com.android.server.companion.AssociationStore; @@ -86,13 +89,12 @@ public class CompanionDevicePresenceMonitor implements AssociationStore.OnChange private final SimulatedDevicePresenceSchedulerHelper mSchedulerHelper = new SimulatedDevicePresenceSchedulerHelper(); - public CompanionDevicePresenceMonitor(@NonNull AssociationStore associationStore, - @NonNull Callback callback) { + public CompanionDevicePresenceMonitor(UserManager userManager, + @NonNull AssociationStore associationStore, @NonNull Callback callback) { mAssociationStore = associationStore; mCallback = callback; - - mBtConnectionListener = new BluetoothCompanionDeviceConnectionListener(associationStore, - /* BluetoothCompanionDeviceConnectionListener.Callback */ this); + mBtConnectionListener = new BluetoothCompanionDeviceConnectionListener(userManager, + associationStore, /* BluetoothCompanionDeviceConnectionListener.Callback */ this); mBleScanner = new BleCompanionDeviceScanner(associationStore, /* BleCompanionDeviceScanner.Callback */ this); } @@ -298,6 +300,15 @@ public class CompanionDevicePresenceMonitor implements AssociationStore.OnChange // what's needed. } + /** + * Return a set of devices that pending to report connectivity + */ + public SparseArray> getPendingConnectedDevices() { + synchronized (mBtConnectionListener.mPendingConnectedDevices) { + return mBtConnectionListener.mPendingConnectedDevices; + } + } + private static void enforceCallerShellOrRoot() { final int callingUid = Binder.getCallingUid(); if (callingUid == SHELL_UID || callingUid == ROOT_UID) return; -- cgit v1.2.3-59-g8ed1b