Merge "Send BLE callback after phone is unlocked if the app is not directBootAware." into main
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index edf9fd1..2d59309 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -23,7 +23,6 @@
import static android.Manifest.permission.REQUEST_COMPANION_SELF_MANAGED;
import static android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE;
import static android.Manifest.permission.USE_COMPANION_TRANSPORTS;
-import static android.companion.DevicePresenceEvent.EVENT_BT_CONNECTED;
import static android.content.pm.PackageManager.CERT_INPUT_SHA256;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Process.SYSTEM_UID;
@@ -53,7 +52,6 @@
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.IAssociationRequestCallback;
@@ -76,7 +74,6 @@
import android.os.Environment;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
-import android.os.ParcelUuid;
import android.os.PowerExemptionManager;
import android.os.PowerManagerInternal;
import android.os.RemoteException;
@@ -118,9 +115,7 @@
import java.io.File;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
import java.util.List;
import java.util.Set;
@@ -250,38 +245,9 @@
@Override
public void onUserUnlocked(@NonNull TargetUser user) {
+ Slog.i(TAG, "onUserUnlocked() user=" + user);
// Notify and bind the app after the phone is unlocked.
- final int userId = user.getUserIdentifier();
- final Set<BluetoothDevice> blueToothDevices =
- mDevicePresenceProcessor.getPendingConnectedDevices().get(userId);
-
- final List<ObservableUuid> observableUuids =
- mObservableUuidStore.getObservableUuidsForUser(userId);
-
- if (blueToothDevices != null) {
- for (BluetoothDevice bluetoothDevice : blueToothDevices) {
- final ParcelUuid[] bluetoothDeviceUuids = bluetoothDevice.getUuids();
-
- final List<ParcelUuid> deviceUuids = ArrayUtils.isEmpty(bluetoothDeviceUuids)
- ? Collections.emptyList() : Arrays.asList(bluetoothDeviceUuids);
-
- for (AssociationInfo ai :
- mAssociationStore.getActiveAssociationsByAddress(
- bluetoothDevice.getAddress())) {
- Slog.i(TAG, "onUserUnlocked, device id( " + ai.getId() + " ) is connected");
- mDevicePresenceProcessor.onBluetoothCompanionDeviceConnected(ai.getId());
- }
-
- for (ObservableUuid observableUuid : observableUuids) {
- if (deviceUuids.contains(observableUuid.getUuid())) {
- Slog.i(TAG, "onUserUnlocked, UUID( "
- + observableUuid.getUuid() + " ) is connected");
- mDevicePresenceProcessor.onDevicePresenceEventByUuid(
- observableUuid, EVENT_BT_CONNECTED);
- }
- }
- }
- }
+ mDevicePresenceProcessor.sendDevicePresenceEventOnUnlocked(user.getUserIdentifier());
}
private void onPackageRemoveOrDataClearedInternal(
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
index a789384..daa8fdb 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
@@ -80,25 +80,6 @@
final int associationId;
try {
- if ("simulate-device-event".equals(cmd) && Flags.devicePresence()) {
- associationId = getNextIntArgRequired();
- int event = getNextIntArgRequired();
- mDevicePresenceProcessor.simulateDeviceEvent(associationId, event);
- return 0;
- }
-
- if ("simulate-device-uuid-event".equals(cmd) && Flags.devicePresence()) {
- String uuid = getNextArgRequired();
- String packageName = getNextArgRequired();
- int userId = getNextIntArgRequired();
- int event = getNextIntArgRequired();
- ObservableUuid observableUuid = new ObservableUuid(
- userId, ParcelUuid.fromString(uuid), packageName,
- System.currentTimeMillis());
- mDevicePresenceProcessor.simulateDeviceEventByUuid(observableUuid, event);
- return 0;
- }
-
switch (cmd) {
case "list": {
final int userId = getNextIntArgRequired();
@@ -167,6 +148,51 @@
mDevicePresenceProcessor.simulateDeviceEvent(associationId, /* event */ 1);
break;
+ case "simulate-device-event": {
+ if (Flags.devicePresence()) {
+ associationId = getNextIntArgRequired();
+ int event = getNextIntArgRequired();
+ mDevicePresenceProcessor.simulateDeviceEvent(associationId, event);
+ }
+ break;
+ }
+
+ case "simulate-device-uuid-event": {
+ if (Flags.devicePresence()) {
+ String uuid = getNextArgRequired();
+ String packageName = getNextArgRequired();
+ int userId = getNextIntArgRequired();
+ int event = getNextIntArgRequired();
+ ObservableUuid observableUuid = new ObservableUuid(
+ userId, ParcelUuid.fromString(uuid), packageName,
+ System.currentTimeMillis());
+ mDevicePresenceProcessor.simulateDeviceEventByUuid(observableUuid, event);
+ }
+ break;
+ }
+
+ case "simulate-device-event-device-locked": {
+ if (Flags.devicePresence()) {
+ associationId = getNextIntArgRequired();
+ int userId = getNextIntArgRequired();
+ int event = getNextIntArgRequired();
+ String uuid = getNextArgRequired();
+ ParcelUuid parcelUuid =
+ uuid.equals("null") ? null : ParcelUuid.fromString(uuid);
+ mDevicePresenceProcessor.simulateDeviceEventOnDeviceLocked(
+ associationId, userId, event, parcelUuid);
+ }
+ break;
+ }
+
+ case "simulate-device-event-device-unlocked": {
+ if (Flags.devicePresence()) {
+ int userId = getNextIntArgRequired();
+ mDevicePresenceProcessor.simulateDeviceEventOnUserUnlocked(userId);
+ }
+ break;
+ }
+
case "get-backup-payload": {
final int userId = getNextIntArgRequired();
byte[] payload = mBackupRestoreProcessor.getBackupPayload(userId);
@@ -478,6 +504,17 @@
pw.println(" Make CDM act as if the given DEVICE is BT disconnected base"
+ "on the UUID");
pw.println(" USE FOR DEBUGGING AND/OR TESTING PURPOSES ONLY.");
+
+ pw.println(" simulate-device-event-device-locked"
+ + " ASSOCIATION_ID USER_ID DEVICE_EVENT PARCEL_UUID");
+ pw.println(" Simulate device event when the device is locked");
+ pw.println(" USE FOR DEBUGGING AND/OR TESTING PURPOSES ONLY.");
+
+ pw.println(" simulate-device-event-device-unlocked USER_ID");
+ pw.println(" Simulate device unlocked for given user. This will send corresponding");
+ pw.println(" callback after simulate-device-event-device-locked");
+ pw.println(" command has been called.");
+ pw.println(" USE FOR DEBUGGING AND/OR TESTING PURPOSES ONLY.");
}
pw.println(" remove-inactive-associations");
diff --git a/services/companion/java/com/android/server/companion/presence/BleCompanionDeviceScanner.java b/services/companion/java/com/android/server/companion/presence/BleCompanionDeviceScanner.java
index 9c37881..407b9da 100644
--- a/services/companion/java/com/android/server/companion/presence/BleCompanionDeviceScanner.java
+++ b/services/companion/java/com/android/server/companion/presence/BleCompanionDeviceScanner.java
@@ -73,9 +73,9 @@
private static final String TAG = "CDM_BleCompanionDeviceScanner";
interface Callback {
- void onBleCompanionDeviceFound(int associationId);
+ void onBleCompanionDeviceFound(int associationId, int userId);
- void onBleCompanionDeviceLost(int associationId);
+ void onBleCompanionDeviceLost(int associationId, int userId);
}
private final @NonNull AssociationStore mAssociationStore;
@@ -259,7 +259,7 @@
if (DEBUG) Log.d(TAG, " > associations=" + Arrays.toString(associations.toArray()));
for (AssociationInfo association : associations) {
- mCallback.onBleCompanionDeviceFound(association.getId());
+ mCallback.onBleCompanionDeviceFound(association.getId(), association.getUserId());
}
}
@@ -272,7 +272,7 @@
if (DEBUG) Log.d(TAG, " > associations=" + Arrays.toString(associations.toArray()));
for (AssociationInfo association : associations) {
- mCallback.onBleCompanionDeviceLost(association.getId());
+ mCallback.onBleCompanionDeviceLost(association.getId(), association.getUserId());
}
}
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 2d345c4..e1a8db4 100644
--- a/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java
+++ b/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java
@@ -34,20 +34,15 @@
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.internal.util.ArrayUtils;
import com.android.server.companion.association.AssociationStore;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Set;
@SuppressLint("LongLogTag")
public class BluetoothCompanionDeviceConnectionListener
@@ -56,14 +51,13 @@
private static final String TAG = "CDM_BluetoothCompanionDeviceConnectionListener";
interface Callback {
- void onBluetoothCompanionDeviceConnected(int associationId);
+ void onBluetoothCompanionDeviceConnected(int associationId, int userId);
- void onBluetoothCompanionDeviceDisconnected(int associationId);
+ void onBluetoothCompanionDeviceDisconnected(int associationId, int userId);
void onDevicePresenceEventByUuid(ObservableUuid uuid, int event);
}
- private final UserManager mUserManager;
private final @NonNull AssociationStore mAssociationStore;
private final @NonNull Callback mCallback;
/** A set of ALL connected BT device (not only companion.) */
@@ -71,21 +65,12 @@
private final @NonNull ObservableUuidStore mObservableUuidStore;
- /**
- * 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<Set<BluetoothDevice>> mPendingConnectedDevices = new SparseArray<>();
-
BluetoothCompanionDeviceConnectionListener(UserManager userManager,
@NonNull AssociationStore associationStore,
@NonNull ObservableUuidStore observableUuidStore, @NonNull Callback callback) {
mAssociationStore = associationStore;
mObservableUuidStore = observableUuidStore;
mCallback = callback;
- mUserManager = userManager;
}
public void init(@NonNull BluetoothAdapter btAdapter) {
@@ -111,19 +96,8 @@
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<BluetoothDevice> bluetoothDevices = mPendingConnectedDevices.get(
- userId, new HashSet<>());
- bluetoothDevices.add(device);
- mPendingConnectedDevices.put(userId, bluetoothDevices);
- }
- } else {
- onDeviceConnectivityChanged(device, true);
- }
+
+ onDeviceConnectivityChanged(device, true);
}
/**
@@ -149,19 +123,6 @@
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<BluetoothDevice> bluetoothDevices = mPendingConnectedDevices.get(userId);
- if (bluetoothDevices != null) {
- bluetoothDevices.remove(device);
- }
- }
-
- return;
- }
-
onDeviceConnectivityChanged(device, false);
}
@@ -190,16 +151,15 @@
if (!association.isNotifyOnDeviceNearby()) continue;
final int id = association.getId();
if (connected) {
- mCallback.onBluetoothCompanionDeviceConnected(id);
+ mCallback.onBluetoothCompanionDeviceConnected(id, association.getUserId());
} else {
- mCallback.onBluetoothCompanionDeviceDisconnected(id);
+ mCallback.onBluetoothCompanionDeviceDisconnected(id, association.getUserId());
}
}
for (ObservableUuid uuid : observableUuids) {
if (deviceUuids.contains(uuid.getUuid())) {
- mCallback.onDevicePresenceEventByUuid(
- uuid, connected ? EVENT_BT_CONNECTED
+ mCallback.onDevicePresenceEventByUuid(uuid, connected ? EVENT_BT_CONNECTED
: EVENT_BT_DISCONNECTED);
}
}
@@ -210,7 +170,8 @@
if (DEBUG) Log.d(TAG, "onAssociation_Added() " + association);
if (mAllConnectedDevices.containsKey(association.getDeviceMacAddress())) {
- mCallback.onBluetoothCompanionDeviceConnected(association.getId());
+ mCallback.onBluetoothCompanionDeviceConnected(
+ association.getId(), association.getUserId());
}
}
diff --git a/services/companion/java/com/android/server/companion/presence/DevicePresenceProcessor.java b/services/companion/java/com/android/server/companion/presence/DevicePresenceProcessor.java
index 642460e..092886c 100644
--- a/services/companion/java/com/android/server/companion/presence/DevicePresenceProcessor.java
+++ b/services/companion/java/com/android/server/companion/presence/DevicePresenceProcessor.java
@@ -35,7 +35,6 @@
import android.annotation.TestApi;
import android.annotation.UserIdInt;
import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
import android.companion.AssociationInfo;
import android.companion.DeviceNotAssociatedException;
import android.companion.DevicePresenceEvent;
@@ -59,8 +58,10 @@
import com.android.server.companion.association.AssociationStore;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
/**
@@ -97,6 +98,8 @@
private final BleCompanionDeviceScanner mBleScanner;
@NonNull
private final PowerManagerInternal mPowerManagerInternal;
+ @NonNull
+ private final UserManager mUserManager;
// NOTE: Same association may appear in more than one of the following sets at the same time.
// (E.g. self-managed devices that have MAC addresses, could be reported as present by their
@@ -129,6 +132,14 @@
private final BleDeviceDisappearedScheduler mBleDeviceDisappearedScheduler =
new BleDeviceDisappearedScheduler();
+ /**
+ * A structure hold the DevicePresenceEvents that are pending to be reported to the companion
+ * app when the user unlocks the local device per userId.
+ */
+ @GuardedBy("mPendingDevicePresenceEvents")
+ public final SparseArray<List<DevicePresenceEvent>> mPendingDevicePresenceEvents =
+ new SparseArray<>();
+
public DevicePresenceProcessor(@NonNull Context context,
@NonNull CompanionAppBinder companionAppBinder,
UserManager userManager,
@@ -139,6 +150,7 @@
mCompanionAppBinder = companionAppBinder;
mAssociationStore = associationStore;
mObservableUuidStore = observableUuidStore;
+ mUserManager = userManager;
mBtConnectionListener = new BluetoothCompanionDeviceConnectionListener(userManager,
associationStore, mObservableUuidStore,
/* BluetoothCompanionDeviceConnectionListener.Callback */ this);
@@ -461,7 +473,14 @@
}
@Override
- public void onBluetoothCompanionDeviceConnected(int associationId) {
+ public void onBluetoothCompanionDeviceConnected(int associationId, int userId) {
+ Slog.i(TAG, "onBluetoothCompanionDeviceConnected: "
+ + "associationId( " + associationId + " )");
+ if (!mUserManager.isUserUnlockingOrUnlocked(userId)) {
+ onDeviceLocked(associationId, userId, EVENT_BT_CONNECTED, /* ParcelUuid */ null);
+ return;
+ }
+
synchronized (mBtDisconnectedDevices) {
// A device is considered reconnected within 10 seconds if a pending BLE lost report is
// followed by a detected Bluetooth connection.
@@ -484,9 +503,15 @@
}
@Override
- public void onBluetoothCompanionDeviceDisconnected(int associationId) {
+ public void onBluetoothCompanionDeviceDisconnected(int associationId, int userId) {
Slog.i(TAG, "onBluetoothCompanionDeviceDisconnected "
+ "associationId( " + associationId + " )");
+
+ if (!mUserManager.isUserUnlockingOrUnlocked(userId)) {
+ onDeviceLocked(associationId, userId, EVENT_BT_DISCONNECTED, /* ParcelUuid */ null);
+ return;
+ }
+
// Start BLE scanning when the device is disconnected.
mBleScanner.startScan();
@@ -503,7 +528,13 @@
@Override
- public void onBleCompanionDeviceFound(int associationId) {
+ public void onBleCompanionDeviceFound(int associationId, int userId) {
+ Slog.i(TAG, "onBleCompanionDeviceFound " + "associationId( " + associationId + " )");
+ if (!mUserManager.isUserUnlockingOrUnlocked(userId)) {
+ onDeviceLocked(associationId, userId, EVENT_BLE_APPEARED, /* ParcelUuid */ null);
+ return;
+ }
+
onDevicePresenceEvent(mNearbyBleDevices, associationId, EVENT_BLE_APPEARED);
synchronized (mBtDisconnectedDevices) {
final boolean isCurrentPresent = mBtDisconnectedDevicesBlePresence.get(associationId);
@@ -514,7 +545,13 @@
}
@Override
- public void onBleCompanionDeviceLost(int associationId) {
+ public void onBleCompanionDeviceLost(int associationId, int userId) {
+ Slog.i(TAG, "onBleCompanionDeviceLost " + "associationId( " + associationId + " )");
+ if (!mUserManager.isUserUnlockingOrUnlocked(userId)) {
+ onDeviceLocked(associationId, userId, EVENT_BLE_APPEARED, /* ParcelUuid */ null);
+ return;
+ }
+
onDevicePresenceEvent(mNearbyBleDevices, associationId, EVENT_BLE_DISAPPEARED);
}
@@ -529,18 +566,20 @@
// Make sure the association exists.
enforceAssociationExists(associationId);
+ final AssociationInfo associationInfo = mAssociationStore.getAssociationById(associationId);
+
switch (event) {
case EVENT_BLE_APPEARED:
simulateDeviceAppeared(associationId, event);
break;
case EVENT_BT_CONNECTED:
- onBluetoothCompanionDeviceConnected(associationId);
+ onBluetoothCompanionDeviceConnected(associationId, associationInfo.getUserId());
break;
case EVENT_BLE_DISAPPEARED:
simulateDeviceDisappeared(associationId, event);
break;
case EVENT_BT_DISCONNECTED:
- onBluetoothCompanionDeviceDisconnected(associationId);
+ onBluetoothCompanionDeviceDisconnected(associationId, associationInfo.getUserId());
break;
default:
throw new IllegalArgumentException("Event: " + event + "is not supported");
@@ -558,6 +597,29 @@
onDevicePresenceEventByUuid(uuid, event);
}
+ /** FOR DEBUGGING AND/OR TESTING PURPOSES ONLY. */
+ @TestApi
+ public void simulateDeviceEventOnDeviceLocked(
+ int associationId, int userId, int event, ParcelUuid uuid) {
+ // IMPORTANT: this API should only be invoked via the
+ // 'companiondevice simulate-device-event-device-locked' Shell command,
+ // so the only uid-s allowed to make this call are SHELL and ROOT.
+ // No other caller (including SYSTEM!) should be allowed.
+ enforceCallerShellOrRoot();
+ onDeviceLocked(associationId, userId, event, uuid);
+ }
+
+ /** FOR DEBUGGING AND/OR TESTING PURPOSES ONLY. */
+ @TestApi
+ public void simulateDeviceEventOnUserUnlocked(int userId) {
+ // IMPORTANT: this API should only be invoked via the
+ // 'companiondevice simulate-device-event-device-unlocked' Shell command,
+ // so the only uid-s allowed to make this call are SHELL and ROOT.
+ // No other caller (including SYSTEM!) should be allowed.
+ enforceCallerShellOrRoot();
+ sendDevicePresenceEventOnUnlocked(userId);
+ }
+
private void simulateDeviceAppeared(int associationId, int state) {
onDevicePresenceEvent(mSimulated, associationId, state);
mSchedulerHelper.scheduleOnDeviceGoneCallForSimulatedDevicePresence(associationId);
@@ -660,8 +722,13 @@
+ "]...");
final ParcelUuid parcelUuid = uuid.getUuid();
- final String packageName = uuid.getPackageName();
final int userId = uuid.getUserId();
+ if (!mUserManager.isUserUnlockingOrUnlocked(userId)) {
+ onDeviceLocked(/* associationId */ -1, userId, eventType, parcelUuid);
+ return;
+ }
+
+ final String packageName = uuid.getPackageName();
final DevicePresenceEvent event = new DevicePresenceEvent(NO_ASSOCIATION, eventType,
parcelUuid);
@@ -882,14 +949,6 @@
// what's needed.
}
- /**
- * Return a set of devices that pending to report connectivity
- */
- public SparseArray<Set<BluetoothDevice>> getPendingConnectedDevices() {
- synchronized (mBtConnectionListener.mPendingConnectedDevices) {
- return mBtConnectionListener.mPendingConnectedDevices;
- }
- }
private static void enforceCallerShellOrRoot() {
final int callingUid = Binder.getCallingUid();
@@ -919,6 +978,114 @@
}
/**
+ * Store the positive DevicePresenceEvent in the cache if the current device is still
+ * locked.
+ * Remove the current DevicePresenceEvent if there's a negative event occurs.
+ */
+ private void onDeviceLocked(int associationId, int userId, int event, ParcelUuid uuid) {
+ switch (event) {
+ case EVENT_BLE_APPEARED, EVENT_BT_CONNECTED -> {
+ // Try to bind and notify the app after the phone is unlocked.
+ Slog.i(TAG, "Current user is not in unlocking or unlocked stage yet. "
+ + "Notify the application when the phone is unlocked");
+ synchronized (mPendingDevicePresenceEvents) {
+ final DevicePresenceEvent devicePresenceEvent = new DevicePresenceEvent(
+ associationId, event, uuid);
+ List<DevicePresenceEvent> deviceEvents = mPendingDevicePresenceEvents.get(
+ userId, new ArrayList<>());
+ deviceEvents.add(devicePresenceEvent);
+ mPendingDevicePresenceEvents.put(userId, deviceEvents);
+ }
+ }
+ case EVENT_BLE_DISAPPEARED -> {
+ synchronized (mPendingDevicePresenceEvents) {
+ List<DevicePresenceEvent> deviceEvents = mPendingDevicePresenceEvents
+ .get(userId);
+ if (deviceEvents != null) {
+ deviceEvents.removeIf(deviceEvent ->
+ deviceEvent.getEvent() == EVENT_BLE_APPEARED
+ && Objects.equals(deviceEvent.getUuid(), uuid)
+ && deviceEvent.getAssociationId() == associationId);
+ }
+ }
+ }
+ case EVENT_BT_DISCONNECTED -> {
+ // Do not need to report the event since the user is not unlock the
+ // phone so that cdm is not bind with the app yet.
+ synchronized (mPendingDevicePresenceEvents) {
+ List<DevicePresenceEvent> deviceEvents = mPendingDevicePresenceEvents
+ .get(userId);
+ if (deviceEvents != null) {
+ deviceEvents.removeIf(deviceEvent ->
+ deviceEvent.getEvent() == EVENT_BT_CONNECTED
+ && Objects.equals(deviceEvent.getUuid(), uuid)
+ && deviceEvent.getAssociationId() == associationId);
+ }
+ }
+ }
+ default -> Slog.e(TAG, "Event: " + event + "is not supported");
+ }
+ }
+
+ /**
+ * Send the device presence event by userID when the device is unlocked.
+ */
+ public void sendDevicePresenceEventOnUnlocked(int userId) {
+ final List<DevicePresenceEvent> deviceEvents = getPendingDevicePresenceEventsByUserId(
+ userId);
+ final List<ObservableUuid> observableUuids =
+ mObservableUuidStore.getObservableUuidsForUser(userId);
+ // Notify and bind the app after the phone is unlocked.
+ for (DevicePresenceEvent deviceEvent : deviceEvents) {
+ boolean isUuid = deviceEvent.getUuid() != null;
+ if (isUuid) {
+ for (ObservableUuid uuid : observableUuids) {
+ if (uuid.getUuid().equals(deviceEvent.getUuid())) {
+ onDevicePresenceEventByUuid(uuid, EVENT_BT_CONNECTED);
+ }
+ }
+ } else {
+ int event = deviceEvent.getEvent();
+ int associationId = deviceEvent.getAssociationId();
+ final AssociationInfo associationInfo = mAssociationStore.getAssociationById(
+ associationId);
+
+ if (associationInfo == null) {
+ return;
+ }
+
+ switch(event) {
+ case EVENT_BLE_APPEARED:
+ onBleCompanionDeviceFound(
+ associationInfo.getId(), associationInfo.getUserId());
+ break;
+ case EVENT_BT_CONNECTED:
+ onBluetoothCompanionDeviceConnected(
+ associationInfo.getId(), associationInfo.getUserId());
+ break;
+ default:
+ Slog.e(TAG, "Event: " + event + "is not supported");
+ break;
+ }
+ }
+ }
+
+ clearPendingDevicePresenceEventsByUserId(userId);
+ }
+
+ private List<DevicePresenceEvent> getPendingDevicePresenceEventsByUserId(int userId) {
+ synchronized (mPendingDevicePresenceEvents) {
+ return mPendingDevicePresenceEvents.get(userId, new ArrayList<>());
+ }
+ }
+
+ private void clearPendingDevicePresenceEventsByUserId(int userId) {
+ synchronized (mPendingDevicePresenceEvents) {
+ mPendingDevicePresenceEvents.get(userId).clear();
+ }
+ }
+
+ /**
* Dumps system information about devices that are marked as "present".
*/
public void dump(@NonNull PrintWriter out) {