Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0b1ebd7c authored by Evan Chen's avatar Evan Chen
Browse files

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
Test: manully test
Change-Id: I3963b3974ba42cbd34ee043416e3ef58d0ec08e5
parent 9cc0dd6e
Loading
Loading
Loading
Loading
+17 −1
Original line number Diff line number Diff line
@@ -53,6 +53,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;
@@ -227,7 +228,7 @@ public class CompanionDeviceManagerService extends SystemService {
        loadAssociationsFromDisk();
        mAssociationStore.registerListener(mAssociationStoreChangeListener);

        mDevicePresenceMonitor = new CompanionDevicePresenceMonitor(
        mDevicePresenceMonitor = new CompanionDevicePresenceMonitor(mUserManager,
                mAssociationStore, mDevicePresenceCallback);

        mAssociationRequestsProcessor = new AssociationRequestsProcessor(
@@ -313,6 +314,21 @@ 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<BluetoothDevice> blueToothDevices =
                mDevicePresenceMonitor.getPendingReportConnectedDevices().get(userId);
        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) {
+53 −4
Original line number Diff line number Diff line
@@ -27,17 +27,23 @@ 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.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 +54,23 @@ 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<MacAddress, BluetoothDevice> mAllConnectedDevices = new HashMap<>();

    BluetoothCompanionDeviceConnectionListener(@NonNull AssociationStore associationStore,
            @NonNull Callback callback) {

    @GuardedBy("mPendingReportConnectedDevices")
    @NonNull
    final SparseArray<Set<BluetoothDevice>> mPendingReportConnectedDevices =
            new SparseArray<>();

    BluetoothCompanionDeviceConnectionListener(UserManager userManager,
            @NonNull AssociationStore associationStore, @NonNull Callback callback) {
        mAssociationStore = associationStore;
        mCallback = callback;
        mUserManager = userManager;
    }

    public void init(@NonNull BluetoothAdapter btAdapter) {
@@ -76,13 +90,33 @@ 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())) {
            if (DEBUG) {
                Log.i(TAG, "Current user is not in unlocking or unlocked stage yet. Notify "
                        + "the application when the phone is unlocked");
            }
            synchronized (mPendingReportConnectedDevices) {
                Set<BluetoothDevice> bluetoothDevices = mPendingReportConnectedDevices.get(userId);

                if (bluetoothDevices == null) {
                    bluetoothDevices = new HashSet<>();
                    mPendingReportConnectedDevices.put(userId, bluetoothDevices);
                }

                bluetoothDevices.add(device);
            }

        } else {
            onDeviceConnectivityChanged(device, true);
        }
    }

    /**
     * Overrides
@@ -98,6 +132,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 +141,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 (mPendingReportConnectedDevices) {
                Set<BluetoothDevice> bluetoothDevices = mPendingReportConnectedDevices.get(userId);
                if (bluetoothDevices != null) {
                    bluetoothDevices.remove(device);
                }
            }

            return;
        }

        onDeviceConnectivityChanged(device, false);
    }

+16 −5
Original line number Diff line number Diff line
@@ -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<Set<BluetoothDevice>> getPendingReportConnectedDevices() {
        synchronized (mBtConnectionListener.mPendingReportConnectedDevices) {
            return mBtConnectionListener.mPendingReportConnectedDevices;
        }
    }

    private static void enforceCallerShellOrRoot() {
        final int callingUid = Binder.getCallingUid();
        if (callingUid == SHELL_UID || callingUid == ROOT_UID) return;