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

Commit 4e1e3f7f authored by Oli Lan's avatar Oli Lan Committed by Jeff Sharkey
Browse files

Replace BLUETOOTH and BLUETOOTH_ADMIN permission checks in BluetoothManagerService.

This replaces the checks for the legacy bluetooth permissions
with checks for the new BLUETOOTH_CONNECT permission.

All of the new checks are done as ForPreflight in this CL, i.e. app
ops will be checked but not noted. Changes to make some of the
checks ForDataDelivery (i.e. noting the app op) will be made in
follow-ups - this requires additional work as the calling package
and attribution tag must be plumbed through from the app side.

Bug: 183203469
Test: builds
Change-Id: I7b99a203ac25a8dcc0d33f442b08203244bff534
parent 98788331
Loading
Loading
Loading
Loading
+40 −11
Original line number Diff line number Diff line
@@ -16,7 +16,10 @@

package com.android.server;

import static android.Manifest.permission.BLUETOOTH_CONNECT;
import static android.content.PermissionChecker.PERMISSION_HARD_DENIED;
import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.UserHandle.USER_SYSTEM;

import android.Manifest;
@@ -43,6 +46,7 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.PermissionChecker;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
@@ -95,8 +99,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
    private static final String TAG = "BluetoothManagerService";
    private static final boolean DBG = true;

    private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
    private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
    private static final String BLUETOOTH_PRIVILEGED =
            android.Manifest.permission.BLUETOOTH_PRIVILEGED;

@@ -696,14 +698,18 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
            Slog.w(TAG, "Callback is null in unregisterAdapter");
            return;
        }
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!checkConnectPermissionForPreflight(mContext)) {
            return;
        }
        synchronized (mCallbacks) {
            mCallbacks.unregister(callback);
        }
    }

    public void registerStateChangeCallback(IBluetoothStateChangeCallback callback) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!checkConnectPermissionForPreflight(mContext)) {
            return;
        }
        if (callback == null) {
            Slog.w(TAG, "registerStateChangeCallback: Callback is null!");
            return;
@@ -714,7 +720,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
    }

    public void unregisterStateChangeCallback(IBluetoothStateChangeCallback callback) {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!checkConnectPermissionForPreflight(mContext)) {
            return;
        }
        if (callback == null) {
            Slog.w(TAG, "unregisterStateChangeCallback: Callback is null!");
            return;
@@ -945,8 +953,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
                return false;
            }

            mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                    "Need BLUETOOTH ADMIN permission");
            if (!checkConnectPermissionForPreflight(mContext)) {
                return false;
            }
        }
        return true;
    }
@@ -1672,7 +1681,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
    }

    public String getAddress() {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!checkConnectPermissionForPreflight(mContext)) {
            return null;
        }

        if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) {
            Slog.w(TAG, "getAddress(): not allowed for non-active and non system user");
@@ -1704,7 +1715,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
    }

    public String getName() {
        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
        if (!checkConnectPermissionForPreflight(mContext)) {
            return null;
        }

        if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) {
            Slog.w(TAG, "getName(): not allowed for non-active and non system user");
@@ -2459,7 +2472,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
        intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
        intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
        mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM);
        mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_CONNECT);
    }

    private void bluetoothStateChangeHandler(int prevState, int newState) {
@@ -2538,7 +2551,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
            intent.putExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, prevState);
            intent.putExtra(BluetoothAdapter.EXTRA_STATE, newState);
            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
            mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_PERM);
            mContext.sendBroadcastAsUser(intent, UserHandle.ALL, BLUETOOTH_CONNECT);
        }
    }

@@ -2827,4 +2840,20 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
            default: return "UNKNOWN[" + reason + "]";
        }
    }

    /**
     * Returns true if the BLUETOOTH_CONNECT permission is granted for the calling app. Returns
     * false if the result is a soft denial. Throws SecurityException if the result is a hard
     * denial.
     *
     * <p>Should be used in situations where the app op should not be noted.
     */
    private static boolean checkConnectPermissionForPreflight(Context context) {
        int permissionCheckResult = PermissionChecker.checkCallingOrSelfPermissionForPreflight(
                context, BLUETOOTH_CONNECT);
        if (permissionCheckResult == PERMISSION_HARD_DENIED) {
            throw new SecurityException("Need BLUETOOTH_CONNECT permission");
        }
        return permissionCheckResult == PERMISSION_GRANTED;
    }
}