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

Commit 4e4c9c47 authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Refinement of AttributionSource handling.

Previous CLs had started passing AttributionSource values across
Binder calls inside BluetoothDevice instances, but this can cause
confuse the permission check logic in the future; we should instead
always aim to use the AttributionSource closest to the app making
the call, instead of parceling it.

This change also improves logging to highlight when we're quietly
treating a permission as denied, and when a UID is mismatched.

Bug: 186106084
Test: atest BluetoothInstrumentationTests
Change-Id: I5d3fdb3c573cb9e77474952d8680caa4c4c464eb
parent d4e014e2
Loading
Loading
Loading
Loading
+49 −55
Original line number Diff line number Diff line
@@ -53,7 +53,6 @@ import android.os.Binder;
import android.os.Build;
import android.os.IBinder;
import android.os.ParcelUuid;
import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
@@ -75,6 +74,7 @@ import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Executor;
@@ -713,7 +713,6 @@ public final class BluetoothAdapter {
    private final IBluetoothManager mManagerService;
    @UnsupportedAppUsage
    private IBluetooth mService;
    private Context mContext;
    private final ReentrantReadWriteLock mServiceLock = new ReentrantReadWriteLock();

    private final Object mLock = new Object();
@@ -723,6 +722,8 @@ public final class BluetoothAdapter {
    private final Map<BluetoothConnectionCallback, Executor>
            mBluetoothConnectionCallbackExecutorMap = new HashMap<>();

    private AttributionSource mAttributionSource;

    /**
     * Bluetooth metadata listener. Overrides the default BluetoothMetadataListener
     * implementation.
@@ -762,16 +763,21 @@ public final class BluetoothAdapter {
    @RequiresNoPermission
    public static synchronized BluetoothAdapter getDefaultAdapter() {
        if (sAdapter == null) {
            IBinder b = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
            if (b != null) {
                IBluetoothManager managerService = IBluetoothManager.Stub.asInterface(b);
                sAdapter = new BluetoothAdapter(managerService);
            sAdapter = createAdapter();
        }
        return sAdapter;
    }

    /** {@hide} */
    public static BluetoothAdapter createAdapter() {
        IBinder binder = ServiceManager.getService(BLUETOOTH_MANAGER_SERVICE);
        if (binder != null) {
            return new BluetoothAdapter(IBluetoothManager.Stub.asInterface(binder));
        } else {
            Log.e(TAG, "Bluetooth binder is null");
            return null;
        }
    }
        return sAdapter;
    }

    /**
     * Use {@link #getDefaultAdapter} to get the BluetoothAdapter instance.
@@ -793,6 +799,15 @@ public final class BluetoothAdapter {
        mToken = new Binder();
    }

    void setAttributionSource(AttributionSource attributionSource) {
        mAttributionSource = attributionSource;
    }

    private AttributionSource resolveAttributionSource() {
        return (mAttributionSource != null) ? mAttributionSource
                : ActivityThread.currentAttributionSource();
    }

    /**
     * Get a {@link BluetoothDevice} object for the given Bluetooth hardware
     * address.
@@ -807,7 +822,9 @@ public final class BluetoothAdapter {
     */
    @RequiresNoPermission
    public BluetoothDevice getRemoteDevice(String address) {
        return new BluetoothDevice(address, getAttributionSource());
        final BluetoothDevice res = new BluetoothDevice(address);
        res.setAttributionSource(mAttributionSource);
        return res;
    }

    /**
@@ -826,9 +843,11 @@ public final class BluetoothAdapter {
        if (address == null || address.length != 6) {
            throw new IllegalArgumentException("Bluetooth address must have 6 bytes");
        }
        return new BluetoothDevice(
        final BluetoothDevice res = new BluetoothDevice(
                String.format(Locale.US, "%02X:%02X:%02X:%02X:%02X:%02X", address[0], address[1],
                        address[2], address[3], address[4], address[5]), getAttributionSource());
                        address[2], address[3], address[4], address[5]));
        res.setAttributionSource(mAttributionSource);
        return res;
    }

    /**
@@ -891,7 +910,7 @@ public final class BluetoothAdapter {
        synchronized (mLock) {
            if (sBluetoothLeScanner == null) {
                sBluetoothLeScanner =
                        new BluetoothLeScanner(mManagerService, getAttributionSource());
                        new BluetoothLeScanner(mManagerService, resolveAttributionSource());
            }
        }
        return sBluetoothLeScanner;
@@ -1330,7 +1349,7 @@ public final class BluetoothAdapter {
        try {
            mServiceLock.readLock().lock();
            if (mService != null) {
                return mService.getUuids(getAttributionSource());
                return mService.getUuids(resolveAttributionSource());
            }
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
@@ -1364,7 +1383,7 @@ public final class BluetoothAdapter {
        try {
            mServiceLock.readLock().lock();
            if (mService != null) {
                return mService.setName(name, getAttributionSource());
                return mService.setName(name, resolveAttributionSource());
            }
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
@@ -1392,7 +1411,7 @@ public final class BluetoothAdapter {
        try {
            mServiceLock.readLock().lock();
            if (mService != null) {
                return mService.getBluetoothClass(getAttributionSource());
                return mService.getBluetoothClass(resolveAttributionSource());
            }
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
@@ -1448,7 +1467,7 @@ public final class BluetoothAdapter {
        if (getState() != STATE_ON) return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
        try {
            mServiceLock.readLock().lock();
            if (mService != null) return mService.getIoCapability(getAttributionSource());
            if (mService != null) return mService.getIoCapability(resolveAttributionSource());
        } catch (RemoteException e) {
            Log.e(TAG, e.getMessage(), e);
        } finally {
@@ -1501,7 +1520,7 @@ public final class BluetoothAdapter {
        if (getState() != STATE_ON) return BluetoothAdapter.IO_CAPABILITY_UNKNOWN;
        try {
            mServiceLock.readLock().lock();
            if (mService != null) return mService.getLeIoCapability(getAttributionSource());
            if (mService != null) return mService.getLeIoCapability(resolveAttributionSource());
        } catch (RemoteException e) {
            Log.e(TAG, e.getMessage(), e);
        } finally {
@@ -1563,7 +1582,7 @@ public final class BluetoothAdapter {
        try {
            mServiceLock.readLock().lock();
            if (mService != null) {
                return mService.getScanMode(getAttributionSource());
                return mService.getScanMode(resolveAttributionSource());
            }
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
@@ -1612,7 +1631,7 @@ public final class BluetoothAdapter {
            mServiceLock.readLock().lock();
            if (mService != null) {
                int durationSeconds = Math.toIntExact(durationMillis / 1000);
                return mService.setScanMode(mode, durationSeconds, getAttributionSource());
                return mService.setScanMode(mode, durationSeconds, resolveAttributionSource());
            }
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
@@ -1662,7 +1681,7 @@ public final class BluetoothAdapter {
        try {
            mServiceLock.readLock().lock();
            if (mService != null) {
                return mService.setScanMode(mode, getDiscoverableTimeout(), getAttributionSource());
                return mService.setScanMode(mode, getDiscoverableTimeout(), resolveAttributionSource());
            }
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
@@ -1683,7 +1702,7 @@ public final class BluetoothAdapter {
        try {
            mServiceLock.readLock().lock();
            if (mService != null) {
                return mService.getDiscoverableTimeout(getAttributionSource());
                return mService.getDiscoverableTimeout(resolveAttributionSource());
            }
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
@@ -1704,7 +1723,7 @@ public final class BluetoothAdapter {
        try {
            mServiceLock.readLock().lock();
            if (mService != null) {
                mService.setDiscoverableTimeout(timeout, getAttributionSource());
                mService.setDiscoverableTimeout(timeout, resolveAttributionSource());
            }
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
@@ -1737,31 +1756,6 @@ public final class BluetoothAdapter {
        return -1;
    }

    /**
     * Set the context for this BluetoothAdapter (only called from BluetoothManager)
     * @hide
     */
    @RequiresNoPermission
    public void setContext(Context context) {
        mContext = context;
    }

    String getOpPackageName() {
        // Workaround for legacy API for getting a BluetoothAdapter not
        // passing a context
        if (mContext != null) {
            return mContext.getOpPackageName();
        }
        return ActivityThread.currentOpPackageName();
    }

    AttributionSource getAttributionSource() {
        if (mContext != null) {
            return mContext.getAttributionSource();
        }
        return new AttributionSource(Process.myUid(), ActivityThread.currentOpPackageName(), null);
    }

    /**
     * Start the remote device discovery process.
     * <p>The discovery process usually involves an inquiry scan of about 12
@@ -1802,7 +1796,7 @@ public final class BluetoothAdapter {
        try {
            mServiceLock.readLock().lock();
            if (mService != null) {
                return mService.startDiscovery(getAttributionSource());
                return mService.startDiscovery(resolveAttributionSource());
            }
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
@@ -1838,7 +1832,7 @@ public final class BluetoothAdapter {
        try {
            mServiceLock.readLock().lock();
            if (mService != null) {
                return mService.cancelDiscovery(getAttributionSource());
                return mService.cancelDiscovery(resolveAttributionSource());
            }
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
@@ -1876,7 +1870,7 @@ public final class BluetoothAdapter {
        try {
            mServiceLock.readLock().lock();
            if (mService != null) {
                return mService.isDiscovering(getAttributionSource());
                return mService.isDiscovering(resolveAttributionSource());
            }
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
@@ -2313,7 +2307,7 @@ public final class BluetoothAdapter {
        try {
            mServiceLock.readLock().lock();
            if (mService != null) {
                return mService.getMaxConnectedAudioDevices(getAttributionSource());
                return mService.getMaxConnectedAudioDevices(resolveAttributionSource());
            }
        } catch (RemoteException e) {
            Log.e(TAG, "failed to get getMaxConnectedAudioDevices, error: ", e);
@@ -2425,7 +2419,7 @@ public final class BluetoothAdapter {
        try {
            mServiceLock.readLock().lock();
            if (mService != null) {
                return mService.getMostRecentlyConnectedDevices(getAttributionSource());
                return mService.getMostRecentlyConnectedDevices(resolveAttributionSource());
            }
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
@@ -2455,7 +2449,7 @@ public final class BluetoothAdapter {
        try {
            mServiceLock.readLock().lock();
            if (mService != null) {
                return toDeviceSet(mService.getBondedDevices(getAttributionSource()));
                return toDeviceSet(mService.getBondedDevices(resolveAttributionSource()));
            }
            return toDeviceSet(new BluetoothDevice[0]);
        } catch (RemoteException e) {
@@ -3270,7 +3264,7 @@ public final class BluetoothAdapter {

    /**
     * Provides callback methods for receiving {@link OobData} from the host stack, as well as an
     * error interface in order to allow the caller to determine next steps based on the {@link
     * error interface in order to allow the caller to determine next steps based on the {@code
     * ErrorCode}.
     *
     * @hide
+35 −32
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.app.ActivityThread;
import android.app.PropertyInvalidatedCache;
import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
import android.bluetooth.annotations.RequiresBluetoothLocationPermission;
@@ -1102,11 +1103,11 @@ public final class BluetoothDevice implements Parcelable {
     */
    private static volatile IBluetooth sService;

    private final AttributionSource mAttributionSource;

    private final String mAddress;
    @AddressType private final int mAddressType;

    private AttributionSource mAttributionSource;

    /*package*/
    @UnsupportedAppUsage
    static IBluetooth getService() {
@@ -1157,7 +1158,8 @@ public final class BluetoothDevice implements Parcelable {
     * @throws IllegalArgumentException address is invalid
     * @hide
     */
    public BluetoothDevice(String address, AttributionSource attributionSource) {
    @UnsupportedAppUsage
    /*package*/ BluetoothDevice(String address) {
        getService();  // ensures sService is initialized
        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
            throw new IllegalArgumentException(address + " is not a valid Bluetooth address");
@@ -1165,12 +1167,15 @@ public final class BluetoothDevice implements Parcelable {

        mAddress = address;
        mAddressType = ADDRESS_TYPE_PUBLIC;
    }

    void setAttributionSource(AttributionSource attributionSource) {
        mAttributionSource = attributionSource;
    }

    @UnsupportedAppUsage
    /*package*/ BluetoothDevice(String address) {
        this(address, BluetoothAdapter.getDefaultAdapter().getAttributionSource());
    private AttributionSource resolveAttributionSource() {
        return (mAttributionSource != null) ? mAttributionSource
                : ActivityThread.currentAttributionSource();
    }

    @Override
@@ -1208,8 +1213,7 @@ public final class BluetoothDevice implements Parcelable {
    public static final @android.annotation.NonNull Parcelable.Creator<BluetoothDevice> CREATOR =
            new Parcelable.Creator<BluetoothDevice>() {
                public BluetoothDevice createFromParcel(Parcel in) {
                    return new BluetoothDevice(
                            in.readString(), in.readParcelable(getClass().getClassLoader()));
                    return new BluetoothDevice(in.readString());
                }

                public BluetoothDevice[] newArray(int size) {
@@ -1220,7 +1224,6 @@ public final class BluetoothDevice implements Parcelable {
    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeString(mAddress);
        out.writeParcelable(mAttributionSource, 0);
    }

    /**
@@ -1265,7 +1268,7 @@ public final class BluetoothDevice implements Parcelable {
            return null;
        }
        try {
            String name = service.getRemoteName(this, mAttributionSource);
            String name = service.getRemoteName(this, resolveAttributionSource());
            if (name != null) {
                // remove whitespace characters from the name
                return name
@@ -1296,7 +1299,7 @@ public final class BluetoothDevice implements Parcelable {
            return DEVICE_TYPE_UNKNOWN;
        }
        try {
            return service.getRemoteType(this, mAttributionSource);
            return service.getRemoteType(this, resolveAttributionSource());
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        }
@@ -1320,7 +1323,7 @@ public final class BluetoothDevice implements Parcelable {
            return null;
        }
        try {
            String alias = service.getRemoteAliasWithAttribution(this, mAttributionSource);
            String alias = service.getRemoteAliasWithAttribution(this, resolveAttributionSource());
            if (alias == null) {
                return getName();
            }
@@ -1361,9 +1364,9 @@ public final class BluetoothDevice implements Parcelable {
            return false;
        }
        try {
            BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
            return service.setRemoteAlias(
                    this, alias, adapter.getOpPackageName(), mAttributionSource);
            return service.setRemoteAlias(this, alias,
                    resolveAttributionSource().getPackageName(),
                    resolveAttributionSource());
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        }
@@ -1389,7 +1392,7 @@ public final class BluetoothDevice implements Parcelable {
            return BATTERY_LEVEL_BLUETOOTH_OFF;
        }
        try {
            return service.getBatteryLevel(this, mAttributionSource);
            return service.getBatteryLevel(this, resolveAttributionSource());
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        }
@@ -1480,7 +1483,7 @@ public final class BluetoothDevice implements Parcelable {
        }
        try {
            return service.createBond(
                    this, transport, remoteP192Data, remoteP256Data, mAttributionSource);
                    this, transport, remoteP192Data, remoteP256Data, resolveAttributionSource());
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        }
@@ -1505,7 +1508,7 @@ public final class BluetoothDevice implements Parcelable {
            return false;
        }
        try {
            return service.isBondingInitiatedLocally(this, mAttributionSource);
            return service.isBondingInitiatedLocally(this, resolveAttributionSource());
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        }
@@ -1530,7 +1533,7 @@ public final class BluetoothDevice implements Parcelable {
            Log.i(TAG, "cancelBondProcess() for device " + getAddress()
                    + " called by pid: " + Process.myPid()
                    + " tid: " + Process.myTid());
            return service.cancelBondProcess(this, mAttributionSource);
            return service.cancelBondProcess(this, resolveAttributionSource());
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        }
@@ -1558,7 +1561,7 @@ public final class BluetoothDevice implements Parcelable {
            Log.i(TAG, "removeBond() for device " + getAddress()
                    + " called by pid: " + Process.myPid()
                    + " tid: " + Process.myTid());
            return service.removeBond(this, mAttributionSource);
            return service.removeBond(this, resolveAttributionSource());
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        }
@@ -1574,7 +1577,7 @@ public final class BluetoothDevice implements Parcelable {
                @SuppressLint("AndroidFrameworkRequiresPermission")
                protected Integer recompute(BluetoothDevice query) {
                    try {
                        return sService.getBondState(query, mAttributionSource);
                        return sService.getBondState(query, resolveAttributionSource());
                    } catch (RemoteException e) {
                        throw e.rethrowAsRuntimeException();
                    }
@@ -1664,7 +1667,7 @@ public final class BluetoothDevice implements Parcelable {
            return false;
        }
        try {
            return service.getConnectionStateWithAttribution(this, mAttributionSource)
            return service.getConnectionStateWithAttribution(this, resolveAttributionSource())
                    != CONNECTION_STATE_DISCONNECTED;
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
@@ -1690,7 +1693,7 @@ public final class BluetoothDevice implements Parcelable {
            return false;
        }
        try {
            return service.getConnectionStateWithAttribution(this, mAttributionSource)
            return service.getConnectionStateWithAttribution(this, resolveAttributionSource())
                    > CONNECTION_STATE_CONNECTED;
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
@@ -1713,7 +1716,7 @@ public final class BluetoothDevice implements Parcelable {
            return null;
        }
        try {
            int classInt = service.getRemoteClass(this, mAttributionSource);
            int classInt = service.getRemoteClass(this, resolveAttributionSource());
            if (classInt == BluetoothClass.ERROR) return null;
            return new BluetoothClass(classInt);
        } catch (RemoteException e) {
@@ -1742,7 +1745,7 @@ public final class BluetoothDevice implements Parcelable {
            return null;
        }
        try {
            return service.getRemoteUuids(this, mAttributionSource);
            return service.getRemoteUuids(this, resolveAttributionSource());
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        }
@@ -1772,7 +1775,7 @@ public final class BluetoothDevice implements Parcelable {
            return false;
        }
        try {
            return service.fetchRemoteUuidsWithAttribution(this, mAttributionSource);
            return service.fetchRemoteUuidsWithAttribution(this, resolveAttributionSource());
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        }
@@ -1809,7 +1812,7 @@ public final class BluetoothDevice implements Parcelable {
            return false;
        }
        try {
            return service.sdpSearch(this, uuid, mAttributionSource);
            return service.sdpSearch(this, uuid, resolveAttributionSource());
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        }
@@ -1831,7 +1834,7 @@ public final class BluetoothDevice implements Parcelable {
            return false;
        }
        try {
            return service.setPin(this, true, pin.length, pin, mAttributionSource);
            return service.setPin(this, true, pin.length, pin, resolveAttributionSource());
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        }
@@ -1894,7 +1897,7 @@ public final class BluetoothDevice implements Parcelable {
            return false;
        }
        try {
            return service.cancelBondProcess(this, mAttributionSource);
            return service.cancelBondProcess(this, resolveAttributionSource());
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        }
@@ -1927,7 +1930,7 @@ public final class BluetoothDevice implements Parcelable {
            return ACCESS_UNKNOWN;
        }
        try {
            return service.getPhonebookAccessPermission(this, mAttributionSource);
            return service.getPhonebookAccessPermission(this, resolveAttributionSource());
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        }
@@ -2033,7 +2036,7 @@ public final class BluetoothDevice implements Parcelable {
            return ACCESS_UNKNOWN;
        }
        try {
            return service.getMessageAccessPermission(this, mAttributionSource);
            return service.getMessageAccessPermission(this, resolveAttributionSource());
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        }
@@ -2084,7 +2087,7 @@ public final class BluetoothDevice implements Parcelable {
            return ACCESS_UNKNOWN;
        }
        try {
            return service.getSimAccessPermission(this, mAttributionSource);
            return service.getSimAccessPermission(this, resolveAttributionSource());
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        }
+3 −25
Original line number Diff line number Diff line
@@ -16,19 +16,15 @@

package android.bluetooth;

import android.Manifest;
import android.annotation.RequiresFeature;
import android.annotation.RequiresNoPermission;
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.SystemService;
import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;

import java.util.ArrayList;
@@ -66,27 +62,9 @@ public final class BluetoothManager {
     * @hide
     */
    public BluetoothManager(Context context) {
        if (context.getAttributionTag() == null) {
            context = context.getApplicationContext();
            if (context == null) {
                throw new IllegalArgumentException(
                        "context not associated with any application (using a mock context?)");
            }

            mAdapter = BluetoothAdapter.getDefaultAdapter();
        } else {
            IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE);
            if (b != null) {
                mAdapter = new BluetoothAdapter(IBluetoothManager.Stub.asInterface(b));
            } else {
                Log.e(TAG, "Bluetooth binder is null");
                mAdapter = null;
            }
        }

        // Context is not initialized in constructor
        if (mAdapter != null) {
            mAdapter.setContext(context);
        mAdapter = BluetoothAdapter.createAdapter();
        if (context != null) {
            mAdapter.setAttributionSource(context.getAttributionSource());
        }
    }