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

Commit 98f3044c authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

More Binder call AttributionSource assignment.

Since developers can use a BluetoothDevice object can make remote
calls, it needs to have an accurate AttributionSource.  Previous CLs
had updated many places where these BluetoothDevice instances were
passed across Binder interfaces, but this change updates several
remaining locations which had been missed.

Introduces new "Attributable" marker interface to offer consistent
tooling when applying AttributionSource updates.

Bug: 187097694
Test: atest BluetoothInstrumentationTests
Change-Id: Icad3b9726591f0fbad58a493cefa5a0af7648280
parent 0cc9fe2c
Loading
Loading
Loading
Loading
+10 −5
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Attributable;
import android.content.AttributionSource;
import android.content.Context;
import android.os.Binder;
@@ -389,8 +390,9 @@ public final class BluetoothA2dp implements BluetoothProfile {
        try {
            final IBluetoothA2dp service = getService();
            if (service != null && isEnabled()) {
                return BluetoothDevice.setAttributionSource(
                        service.getConnectedDevices(), mAttributionSource);
                return Attributable.setAttributionSource(
                        service.getConnectedDevicesWithAttribution(mAttributionSource),
                        mAttributionSource);
            }
            if (service == null) Log.w(TAG, "Proxy not attached to service");
            return new ArrayList<BluetoothDevice>();
@@ -411,8 +413,10 @@ public final class BluetoothA2dp implements BluetoothProfile {
        try {
            final IBluetoothA2dp service = getService();
            if (service != null && isEnabled()) {
                return BluetoothDevice.setAttributionSource(
                        service.getDevicesMatchingConnectionStates(states), mAttributionSource);
                return Attributable.setAttributionSource(
                        service.getDevicesMatchingConnectionStatesWithAttribution(states,
                                mAttributionSource),
                        mAttributionSource);
            }
            if (service == null) Log.w(TAG, "Proxy not attached to service");
            return new ArrayList<BluetoothDevice>();
@@ -500,7 +504,8 @@ public final class BluetoothA2dp implements BluetoothProfile {
        try {
            final IBluetoothA2dp service = getService();
            if (service != null && isEnabled()) {
                return service.getActiveDevice(mAttributionSource);
                return Attributable.setAttributionSource(
                        service.getActiveDevice(mAttributionSource), mAttributionSource);
            }
            if (service == null) Log.w(TAG, "Proxy not attached to service");
            return null;
+3 −2
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Attributable;
import android.content.AttributionSource;
import android.content.Context;
import android.os.Binder;
@@ -206,7 +207,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
        final IBluetoothA2dpSink service = getService();
        if (service != null && isEnabled()) {
            try {
                return BluetoothDevice.setAttributionSource(
                return Attributable.setAttributionSource(
                        service.getConnectedDevices(mAttributionSource), mAttributionSource);
            } catch (RemoteException e) {
                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
@@ -230,7 +231,7 @@ public final class BluetoothA2dpSink implements BluetoothProfile {
        final IBluetoothA2dpSink service = getService();
        if (service != null && isEnabled()) {
            try {
                return BluetoothDevice.setAttributionSource(
                return Attributable.setAttributionSource(
                        service.getDevicesMatchingConnectionStates(states, mAttributionSource),
                        mAttributionSource);
            } catch (RemoteException e) {
+33 −25
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ import android.bluetooth.le.ScanRecord;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Attributable;
import android.content.AttributionSource;
import android.content.Context;
import android.os.BatteryStats;
@@ -719,8 +720,8 @@ public final class BluetoothAdapter {

    private final Object mLock = new Object();
    private final Map<LeScanCallback, ScanCallback> mLeScanClients;
    private static final Map<BluetoothDevice, List<Pair<OnMetadataChangedListener, Executor>>>
                sMetadataListeners = new HashMap<>();
    private final Map<BluetoothDevice, List<Pair<OnMetadataChangedListener, Executor>>>
                mMetadataListeners = new HashMap<>();
    private final Map<BluetoothConnectionCallback, Executor>
            mBluetoothConnectionCallbackExecutorMap = new HashMap<>();

@@ -729,14 +730,15 @@ public final class BluetoothAdapter {
     * implementation.
     */
    @SuppressLint("AndroidFrameworkBluetoothPermission")
    private static final IBluetoothMetadataListener sBluetoothMetadataListener =
    private final IBluetoothMetadataListener mBluetoothMetadataListener =
            new IBluetoothMetadataListener.Stub() {
        @Override
        public void onMetadataChanged(BluetoothDevice device, int key, byte[] value) {
            synchronized (sMetadataListeners) {
                if (sMetadataListeners.containsKey(device)) {
            Attributable.setAttributionSource(device, mAttributionSource);
            synchronized (mMetadataListeners) {
                if (mMetadataListeners.containsKey(device)) {
                    List<Pair<OnMetadataChangedListener, Executor>> list =
                            sMetadataListeners.get(device);
                            mMetadataListeners.get(device);
                    for (Pair<OnMetadataChangedListener, Executor> pair : list) {
                        OnMetadataChangedListener listener = pair.first;
                        Executor executor = pair.second;
@@ -2445,7 +2447,9 @@ public final class BluetoothAdapter {
        try {
            mServiceLock.readLock().lock();
            if (mService != null) {
                return mService.getMostRecentlyConnectedDevices(mAttributionSource);
                return Attributable.setAttributionSource(
                        mService.getMostRecentlyConnectedDevices(mAttributionSource),
                        mAttributionSource);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
@@ -2470,14 +2474,16 @@ public final class BluetoothAdapter {
    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
    public Set<BluetoothDevice> getBondedDevices() {
        if (getState() != STATE_ON) {
            return toDeviceSet(new BluetoothDevice[0]);
            return toDeviceSet(Arrays.asList());
        }
        try {
            mServiceLock.readLock().lock();
            if (mService != null) {
                return toDeviceSet(mService.getBondedDevices(mAttributionSource));
                return toDeviceSet(Attributable.setAttributionSource(
                        Arrays.asList(mService.getBondedDevices(mAttributionSource)),
                        mAttributionSource));
            }
            return toDeviceSet(new BluetoothDevice[0]);
            return toDeviceSet(Arrays.asList());
        } catch (RemoteException e) {
            Log.e(TAG, "", e);
        } finally {
@@ -3165,10 +3171,10 @@ public final class BluetoothAdapter {
                            }
                        }
                    }
                    synchronized (sMetadataListeners) {
                        sMetadataListeners.forEach((device, pair) -> {
                    synchronized (mMetadataListeners) {
                        mMetadataListeners.forEach((device, pair) -> {
                            try {
                                mService.registerMetadataListener(sBluetoothMetadataListener,
                                mService.registerMetadataListener(mBluetoothMetadataListener,
                                        device, mAttributionSource);
                            } catch (RemoteException e) {
                                Log.e(TAG, "Failed to register metadata listener", e);
@@ -3455,8 +3461,8 @@ public final class BluetoothAdapter {
        }
    }

    private Set<BluetoothDevice> toDeviceSet(BluetoothDevice[] devices) {
        Set<BluetoothDevice> deviceSet = new HashSet<BluetoothDevice>(Arrays.asList(devices));
    private Set<BluetoothDevice> toDeviceSet(List<BluetoothDevice> devices) {
        Set<BluetoothDevice> deviceSet = new HashSet<BluetoothDevice>(devices);
        return Collections.unmodifiableSet(deviceSet);
    }

@@ -3926,13 +3932,13 @@ public final class BluetoothAdapter {
            throw new NullPointerException("executor is null");
        }

        synchronized (sMetadataListeners) {
        synchronized (mMetadataListeners) {
            List<Pair<OnMetadataChangedListener, Executor>> listenerList =
                    sMetadataListeners.get(device);
                    mMetadataListeners.get(device);
            if (listenerList == null) {
                // Create new listener/executor list for registeration
                listenerList = new ArrayList<>();
                sMetadataListeners.put(device, listenerList);
                mMetadataListeners.put(device, listenerList);
            } else {
                // Check whether this device was already registed by the lisenter
                if (listenerList.stream().anyMatch((pair) -> (pair.first.equals(listener)))) {
@@ -3946,7 +3952,7 @@ public final class BluetoothAdapter {

            boolean ret = false;
            try {
                ret = service.registerMetadataListener(sBluetoothMetadataListener, device,
                ret = service.registerMetadataListener(mBluetoothMetadataListener, device,
                        mAttributionSource);
            } catch (RemoteException e) {
                Log.e(TAG, "registerMetadataListener fail", e);
@@ -3956,7 +3962,7 @@ public final class BluetoothAdapter {
                    listenerList.remove(listenerPair);
                    if (listenerList.isEmpty()) {
                        // Remove the device if its listener list is empty
                        sMetadataListeners.remove(device);
                        mMetadataListeners.remove(device);
                    }
                }
            }
@@ -3995,17 +4001,17 @@ public final class BluetoothAdapter {
            throw new NullPointerException("listener is null");
        }

        synchronized (sMetadataListeners) {
            if (!sMetadataListeners.containsKey(device)) {
        synchronized (mMetadataListeners) {
            if (!mMetadataListeners.containsKey(device)) {
                throw new IllegalArgumentException("device was not registered");
            }
            // Remove issued listener from the registered device
            sMetadataListeners.get(device).removeIf((pair) -> (pair.first.equals(listener)));
            mMetadataListeners.get(device).removeIf((pair) -> (pair.first.equals(listener)));

            if (sMetadataListeners.get(device).isEmpty()) {
            if (mMetadataListeners.get(device).isEmpty()) {
                // Unregister to Bluetooth service if all listeners are removed from
                // the registered device
                sMetadataListeners.remove(device);
                mMetadataListeners.remove(device);
                final IBluetooth service = mService;
                if (service == null) {
                    // Bluetooth is OFF, do nothing to Bluetooth service.
@@ -4045,6 +4051,7 @@ public final class BluetoothAdapter {
            new IBluetoothConnectionCallback.Stub() {
        @Override
        public void onDeviceConnected(BluetoothDevice device) {
            Attributable.setAttributionSource(device, mAttributionSource);
            for (Map.Entry<BluetoothConnectionCallback, Executor> callbackExecutorEntry:
                    mBluetoothConnectionCallbackExecutorMap.entrySet()) {
                BluetoothConnectionCallback callback = callbackExecutorEntry.getKey();
@@ -4055,6 +4062,7 @@ public final class BluetoothAdapter {

        @Override
        public void onDeviceDisconnected(BluetoothDevice device, int hciReason) {
            Attributable.setAttributionSource(device, mAttributionSource);
            for (Map.Entry<BluetoothConnectionCallback, Executor> callbackExecutorEntry:
                    mBluetoothConnectionCallbackExecutorMap.entrySet()) {
                BluetoothConnectionCallback callback = callbackExecutorEntry.getKey();
+3 −2
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.annotation.SuppressLint;
import android.annotation.SdkConstant.SdkConstantType;
import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
import android.content.Attributable;
import android.content.AttributionSource;
import android.content.Context;
import android.os.Binder;
@@ -135,7 +136,7 @@ public final class BluetoothAvrcpController implements BluetoothProfile {
                getService();
        if (service != null && isEnabled()) {
            try {
                return BluetoothDevice.setAttributionSource(
                return Attributable.setAttributionSource(
                        service.getConnectedDevices(mAttributionSource), mAttributionSource);
            } catch (RemoteException e) {
                Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
@@ -158,7 +159,7 @@ public final class BluetoothAvrcpController implements BluetoothProfile {
                getService();
        if (service != null && isEnabled()) {
            try {
                return BluetoothDevice.setAttributionSource(
                return Attributable.setAttributionSource(
                        service.getDevicesMatchingConnectionStates(states, mAttributionSource),
                        mAttributionSource);
            } catch (RemoteException e) {
+5 −20
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
import android.bluetooth.annotations.RequiresLegacyBluetoothPermission;
import android.companion.AssociationRequest;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Attributable;
import android.content.AttributionSource;
import android.content.Context;
import android.os.Build;
@@ -47,7 +48,6 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
import java.util.UUID;

/**
@@ -84,7 +84,7 @@ import java.util.UUID;
 * {@see BluetoothAdapter}
 * {@see BluetoothSocket}
 */
public final class BluetoothDevice implements Parcelable {
public final class BluetoothDevice implements Parcelable, Attributable {
    private static final String TAG = "BluetoothDevice";
    private static final boolean DBG = false;

@@ -1170,28 +1170,13 @@ public final class BluetoothDevice implements Parcelable {
        mAttributionSource = BluetoothManager.resolveAttributionSource(null);
    }

    void setAttributionSource(AttributionSource attributionSource) {
    /** {@hide} */
    public void setAttributionSource(@NonNull AttributionSource attributionSource) {
        mAttributionSource = attributionSource;
    }

    static BluetoothDevice setAttributionSource(BluetoothDevice device,
            AttributionSource attributionSource) {
        device.setAttributionSource(attributionSource);
        return device;
    }

    static List<BluetoothDevice> setAttributionSource(List<BluetoothDevice> devices,
            AttributionSource attributionSource) {
        if (devices != null) {
            for (BluetoothDevice device : devices) {
                device.setAttributionSource(attributionSource);
            }
        }
        return devices;
    }

    /** {@hide} */
    public void prepareToEnterProcess(AttributionSource attributionSource) {
    public void prepareToEnterProcess(@NonNull AttributionSource attributionSource) {
        setAttributionSource(attributionSource);
    }

Loading