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

Commit 6cf8f612 authored by Rahul Sabnis's avatar Rahul Sabnis
Browse files

Adds support in AdapterService to query for whether a consent dialog can

be skipped for recently CDM associated app and device combos

Tag: #feature
Bug: 172006481
Test: Manual
Change-Id: I3aa9153839119fbd6508219875d7878c074cf961
parent a967dceb
Loading
Loading
Loading
Loading
+66 −3
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ import android.bluetooth.IBluetoothMetadataListener;
import android.bluetooth.IBluetoothSocketManager;
import android.bluetooth.OobData;
import android.bluetooth.UidTraffic;
import android.companion.ICompanionDeviceManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -217,6 +218,7 @@ public class AdapterService extends Service {
    private RemoteCallbackList<IBluetoothCallback> mCallbacks;
    private int mCurrentRequestId;
    private boolean mQuietmode = false;
    private HashMap<String, CallerInfo> mBondAttemptCallerInfo = new HashMap<>();

    private AlarmManager mAlarmManager;
    private PendingIntent mPendingAlarm;
@@ -225,6 +227,7 @@ public class AdapterService extends Service {
    private PowerManager.WakeLock mWakeLock;
    private String mWakeLockName;
    private UserManager mUserManager;
    private ICompanionDeviceManager mCompanionManager;

    private PhonePolicy mPhonePolicy;
    private ActiveDeviceManager mActiveDeviceManager;
@@ -469,6 +472,8 @@ public class AdapterService extends Service {
        mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);
        mBatteryStats = IBatteryStats.Stub.asInterface(
                ServiceManager.getService(BatteryStats.SERVICE_NAME));
        mCompanionManager = ICompanionDeviceManager.Stub.asInterface(
                ServiceManager.getService(Context.COMPANION_DEVICE_SERVICE));

        mBluetoothKeystoreService.initJni();

@@ -1442,7 +1447,8 @@ public class AdapterService extends Service {
        }

        @Override
        public boolean createBond(BluetoothDevice device, int transport, OobData oobData) {
        public boolean createBond(BluetoothDevice device, int transport, OobData oobData,
                String callingPackage) {
            AdapterService service = getService();
            if (service == null || !callerIsSystemOrActiveOrManagedUser(service, TAG, "createBond")) {
                return false;
@@ -1450,7 +1456,7 @@ public class AdapterService extends Service {

            enforceBluetoothAdminPermission(service);

            return service.createBond(device, transport, oobData);
            return service.createBond(device, transport, oobData, callingPackage);
        }

        @Override
@@ -1483,6 +1489,7 @@ public class AdapterService extends Service {
            if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) {
                return false;
            }
            service.mBondAttemptCallerInfo.remove(device.getAddress());
            deviceProp.setBondingInitiatedLocally(false);

            Message msg = service.mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND);
@@ -1539,6 +1546,18 @@ public class AdapterService extends Service {
            return service.getConnectionState(device);
        }

        @Override
        public boolean canBondWithoutDialog(BluetoothDevice device) {
            AdapterService service = getService();
            if (service == null) {
                return false;
            }

            enforceBluetoothPrivilegedPermission(service);

            return service.canBondWithoutDialog(device);
        }

        @Override
        public boolean removeActiveDevice(@ActiveDeviceUse int profiles) {
            if (!Utils.checkCaller()) {
@@ -2337,12 +2356,34 @@ public class AdapterService extends Service {
        return mDatabaseManager;
    }

    boolean createBond(BluetoothDevice device, int transport, OobData oobData) {
    private class CallerInfo {
        public String callerPackageName;
        public int userId;
    }

    boolean createBond(BluetoothDevice device, int transport, OobData oobData,
            String callingPackage) {
        DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device);
        if (deviceProp != null && deviceProp.getBondState() != BluetoothDevice.BOND_NONE) {
            return false;
        }

        // Verifies the integrity of the calling package name
        try {
            int packageUid = getPackageManager().getPackageUid(callingPackage, 0);
            if (packageUid != Binder.getCallingUid()) {
                return false;
            }
        } catch (PackageManager.NameNotFoundException e) {
            Log.e(TAG, "createBond: App with package name " + callingPackage + " does not exist");
            return false;
        }

        CallerInfo createBondCaller = new CallerInfo();
        createBondCaller.callerPackageName = callingPackage;
        createBondCaller.userId = UserHandle.getCallingUserId();
        mBondAttemptCallerInfo.put(device.getAddress(), createBondCaller);

        mRemoteDevices.setBondingInitiatedLocally(Utils.getByteAddress(device));

        // Pairing is unreliable while scanning, so cancel discovery
@@ -2413,6 +2454,28 @@ public class AdapterService extends Service {
        return getConnectionStateNative(addressToBytes(device.getAddress()));
    }

    /**
     * Checks whether the device was recently associated with the comapnion app that called
     * {@link BluetoothDevice#createBond}. This allows these devices to skip the pairing dialog if
     * their pairing variant is {@link BluetoothDevice#PAIRING_VARIANT_CONSENT}.
     *
     * @param device the bluetooth device that is being bonded
     * @return true if it was recently associated and we can bypass the dialog, false otherwise
     */
    public boolean canBondWithoutDialog(BluetoothDevice device) {
        if (mBondAttemptCallerInfo.containsKey(device.getAddress())) {
            CallerInfo bondCallerInfo = mBondAttemptCallerInfo.get(device.getAddress());
            try {
                return mCompanionManager.canPairWithoutPrompt(bondCallerInfo.callerPackageName,
                        device.getAddress(), bondCallerInfo.userId);
            } catch (RemoteException ex) {
                Log.e(TAG, "RemoteException while calling canPairWithoutPrompt in "
                        + "ICompanionDeviceManager");
            }
        }
        return false;
    }

    /**
     * Sets device as the active devices for the profiles passed into the function
     *