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

Commit 6f747902 authored by Rahul Sabnis's avatar Rahul Sabnis Committed by Android (Google) Code Review
Browse files

Merge "Add AdapterService implementation for new CDM association-based...

Merge "Add AdapterService implementation for new CDM association-based permission model for BluetoothDevice#setAlias" into sc-dev
parents b7df24b1 20850979
Loading
Loading
Loading
Loading
+68 −0
Original line number Diff line number Diff line
@@ -16,11 +16,14 @@

package com.android.bluetooth;

import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AppOpsManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.companion.Association;
import android.companion.CompanionDeviceManager;
import android.content.ContentValues;
import android.content.Context;
import android.content.ContextWrapper;
@@ -285,6 +288,71 @@ public final class Utils {
        Utils.sForegroundUserId = uid;
    }

    /**
     * Enforces that a Companion Device Manager (CDM) association exists between the calling
     * application and the Bluetooth Device.
     *
     * @param cdm the CompanionDeviceManager object
     * @param context the Bluetooth AdapterService context
     * @param callingPackage the calling package
     * @param callingUid the calling app uid
     * @param device the remote BluetoothDevice
     * @return {@code true} if there is a CDM association
     * @throws SecurityException if the package name does not match the uid or the association
     *                           doesn't exist
     */
    public static boolean enforceCdmAssociation(CompanionDeviceManager cdm, Context context,
            String callingPackage, int callingUid, BluetoothDevice device) {
        if (!isPackageNameAccurate(context, callingPackage, callingUid)) {
            throw new SecurityException("hasCdmAssociation: Package name " + callingPackage
                    + " is inaccurate for calling uid " + callingUid);
        }

        for (Association association : cdm.getAllAssociations()) {
            if (association.getPackageName().equals(callingPackage)
                    && association.getDeviceMacAddress().equals(device.getAddress())) {
                return true;
            }
        }
        throw new SecurityException("The application with package name " + callingPackage
                + " does not have a CDM association with the Bluetooth Device");
    }

    /**
     * Verifies whether the calling package name matches the calling app uid
     * @param context the Bluetooth AdapterService context
     * @param callingPackage the calling application package name
     * @param callingUid the calling application uid
     * @return {@code true} if the package name matches the calling app uid, {@code false} otherwise
     */
    public static boolean isPackageNameAccurate(Context context, String callingPackage,
            int callingUid) {
        // Verifies the integrity of the calling package name
        try {
            int packageUid = context.getPackageManager().getPackageUid(callingPackage, 0);
            if (packageUid != callingUid) {
                return false;
            }
        } catch (PackageManager.NameNotFoundException e) {
            Log.e(TAG, "isPackageNameAccurate: App with package name " + callingPackage
                    + " does not exist");
            return false;
        }
        return true;
    }

    /**
     * Checks whether the caller has the BLUETOOTH_PRIVILEGED permission
     *
     * @param context the Bluetooth AdapterService context
     * @return {@code true} if the caller has the BLUETOOTH_PRIVILEGED permission, {@code false}
     *         otherwise
     */
    public static boolean hasBluetoothPrivilegedPermission(Context context) {
        return context.checkCallingOrSelfPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
                == PackageManager.PERMISSION_GRANTED;
    }

    public static void enforceBluetoothPermission(Context context) {
        context.enforceCallingOrSelfPermission(
                android.Manifest.permission.BLUETOOTH,
+17 −22
Original line number Diff line number Diff line
@@ -22,8 +22,11 @@ import static com.android.bluetooth.Utils.callerIsSystemOrActiveUser;
import static com.android.bluetooth.Utils.enforceBluetoothAdminPermission;
import static com.android.bluetooth.Utils.enforceBluetoothPermission;
import static com.android.bluetooth.Utils.enforceBluetoothPrivilegedPermission;
import static com.android.bluetooth.Utils.enforceCdmAssociation;
import static com.android.bluetooth.Utils.enforceDumpPermission;
import static com.android.bluetooth.Utils.enforceLocalMacAddressPermission;
import static com.android.bluetooth.Utils.hasBluetoothPrivilegedPermission;
import static com.android.bluetooth.Utils.isPackageNameAccurate;

import android.annotation.Nullable;
import android.app.ActivityManager;
@@ -49,7 +52,7 @@ import android.bluetooth.IBluetoothMetadataListener;
import android.bluetooth.IBluetoothSocketManager;
import android.bluetooth.OobData;
import android.bluetooth.UidTraffic;
import android.companion.ICompanionDeviceManager;
import android.companion.CompanionDeviceManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -249,7 +252,7 @@ public class AdapterService extends Service {
    private PowerManager.WakeLock mWakeLock;
    private String mWakeLockName;
    private UserManager mUserManager;
    private ICompanionDeviceManager mCompanionManager;
    private CompanionDeviceManager mCompanionDeviceManager;

    private PhonePolicy mPhonePolicy;
    private ActiveDeviceManager mActiveDeviceManager;
@@ -505,8 +508,7 @@ 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));
        mCompanionDeviceManager = getSystemService(CompanionDeviceManager.class);

        mBluetoothKeystoreService.initJni();

@@ -1722,13 +1724,18 @@ public class AdapterService extends Service {
        }

        @Override
        public boolean setRemoteAlias(BluetoothDevice device, String name) {
        public boolean setRemoteAlias(BluetoothDevice device, String name, String callingPackage) {
            AdapterService service = getService();
            if (service == null || !callerIsSystemOrActiveUser(TAG, "setRemoteAlias")) {
            if (service == null || !callerIsSystemOrActiveUser(TAG, "setRemoteAlias")
                    || name == null || name.isEmpty()) {
                return false;
            }

            if (!hasBluetoothPrivilegedPermission(service)) {
                enforceBluetoothPermission(service);
                enforceCdmAssociation(service.mCompanionDeviceManager, service, callingPackage,
                        Binder.getCallingUid(), device);
            }

            DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device);
            if (deviceProp == null) {
@@ -2441,14 +2448,7 @@ public class AdapterService extends Service {
            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");
        if (!isPackageNameAccurate(this, callingPackage, Binder.getCallingUid())) {
            return false;
        }

@@ -2546,13 +2546,8 @@ public class AdapterService extends Service {
    public boolean canBondWithoutDialog(BluetoothDevice device) {
        if (mBondAttemptCallerInfo.containsKey(device.getAddress())) {
            CallerInfo bondCallerInfo = mBondAttemptCallerInfo.get(device.getAddress());
            try {
                return mCompanionManager.canPairWithoutPrompt(bondCallerInfo.callerPackageName,
            return mCompanionDeviceManager.canPairWithoutPrompt(bondCallerInfo.callerPackageName,
                    device.getAddress(), bondCallerInfo.userId);
            } catch (RemoteException ex) {
                Log.e(TAG, "RemoteException while calling canPairWithoutPrompt in "
                        + "ICompanionDeviceManager");
            }
        }
        return false;
    }