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

Commit 9b43ee54 authored by Aritra Sen's avatar Aritra Sen
Browse files

Remove receiving ACTION_SDP_RECORD via broadcasts intents inside Bluetooth App.

Refactor PbapClient to make sure the service sends the message to the correct state machine instead of the state always receiving broadcast intents for the same.

Bug: 296932947
Test: atest BluetoothInstrumentationTests
Change-Id: I456d5f0af27a40d474fd4c46e1f9f47492afe778
parent 9b871e4f
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -92,6 +92,7 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelUuid;
import android.os.Parcelable;
import android.os.PowerManager;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
@@ -6983,6 +6984,20 @@ public class AdapterService extends Service {
        }
    }

    /** Notify MAP and Pbap when a new sdp search record is found. */
    public void sendSdpSearchRecord(
            BluetoothDevice device, int status, Parcelable record, ParcelUuid uuid) {
        if (mMapService != null && mMapService.isAvailable()) {
            mMapService.receiveSdpSearchRecord(status, record, uuid);
        }
        if (mMapClientService != null && mMapClientService.isAvailable()) {
            mMapClientService.receiveSdpSearchRecord(device, status, record, uuid);
        }
        if (mPbapClientService != null && mPbapClientService.isAvailable()) {
            mPbapClientService.receiveSdpSearchRecord(device, status, record, uuid);
        }
    }

    /** Handle Bluetooth profiles when bond state changes with a {@link BluetoothDevice} */
    public void handleBondStateChanged(BluetoothDevice device, int fromState, int toState) {
        if (mA2dpService != null && mA2dpService.isAvailable()) {
+8 −4
Original line number Diff line number Diff line
@@ -190,10 +190,14 @@ public class RemoteDevices {
            if (mDevices != null) {
                debugLog("reset(): Broadcasting ACL_DISCONNECTED");

                mDevices.forEach((address, deviceProperties) -> {
                mDevices.forEach(
                        (address, deviceProperties) -> {
                            BluetoothDevice bluetoothDevice = deviceProperties.getDevice();

                    debugLog("reset(): address=" + address + ", connected="
                            debugLog(
                                    "reset(): address="
                                            + address
                                            + ", connected="
                                            + bluetoothDevice.isConnected());

                    if (bluetoothDevice.isConnected()) {
+38 −32
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelUuid;
import android.os.Parcelable;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemProperties;
@@ -694,7 +695,6 @@ public class BluetoothMapService extends ProfileService {
        IntentFilter filter = new IntentFilter();
        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
        filter.addAction(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY);
        filter.addAction(BluetoothDevice.ACTION_SDP_RECORD);
        filter.addAction(USER_CONFIRM_TIMEOUT_ACTION);

        // We need two filters, since Type only applies to the ACTION_MESSAGE_SENT
@@ -1147,37 +1147,6 @@ public class BluetoothMapService extends ProfileService {
                    }
                    sendConnectCancelMessage();
                }
            } else if (action.equals(BluetoothDevice.ACTION_SDP_RECORD)) {
                if (DEBUG) {
                    Log.d(TAG, "Received ACTION_SDP_RECORD.");
                }
                ParcelUuid uuid = intent.getParcelableExtra(BluetoothDevice.EXTRA_UUID);
                if (VERBOSE) {
                    Log.v(TAG, "Received UUID: " + uuid.toString());
                    Log.v(TAG, "expected UUID: "
                            + BluetoothMnsObexClient.BLUETOOTH_UUID_OBEX_MNS.toString());
                }
                if (uuid.equals(BluetoothMnsObexClient.BLUETOOTH_UUID_OBEX_MNS)) {
                    mMnsRecord = intent.getParcelableExtra(BluetoothDevice.EXTRA_SDP_RECORD);
                    int status = intent.getIntExtra(BluetoothDevice.EXTRA_SDP_SEARCH_STATUS, -1);
                    if (VERBOSE) {
                        Log.v(TAG, " -> MNS Record:" + mMnsRecord);
                        Log.v(TAG, " -> status: " + status);
                    }
                    if (mBluetoothMnsObexClient != null && !mSdpSearchInitiated) {
                        mBluetoothMnsObexClient.setMnsRecord(mMnsRecord);
                    }
                    if (status != -1 && mMnsRecord != null) {
                        for (int i = 0, c = mMasInstances.size(); i < c; i++) {
                            mMasInstances.valueAt(i)
                                    .setRemoteFeatureMask(mMnsRecord.getSupportedFeatures());
                        }
                    }
                    if (mSdpSearchInitiated) {
                        mSdpSearchInitiated = false; // done searching
                        sendConnectMessage(-1); // -1 indicates all MAS instances
                    }
                }
            } else if (action.equals(BluetoothMapContentObserver.ACTION_MESSAGE_SENT)) {
                int result = getResultCode();
                boolean handled = false;
@@ -1222,6 +1191,43 @@ public class BluetoothMapService extends ProfileService {
        }
    }

    public void receiveSdpSearchRecord(int status, Parcelable record, ParcelUuid uuid) {
        mSessionStatusHandler.post(() -> handleSdpSearchRecordReceived(status, record, uuid));
    }

    private void handleSdpSearchRecordReceived(int status, Parcelable record, ParcelUuid uuid) {
        if (DEBUG) {
            Log.d(TAG, "Received ACTION_SDP_RECORD.");
        }
        if (VERBOSE) {
            Log.v(TAG, "Received UUID: " + uuid.toString());
            Log.v(
                    TAG,
                    "expected UUID: " + BluetoothMnsObexClient.BLUETOOTH_UUID_OBEX_MNS.toString());
        }
        if (uuid.equals(BluetoothMnsObexClient.BLUETOOTH_UUID_OBEX_MNS)) {
            mMnsRecord = (SdpMnsRecord) record;
            if (VERBOSE) {
                Log.v(TAG, " -> MNS Record:" + mMnsRecord);
                Log.v(TAG, " -> status: " + status);
            }
            if (mBluetoothMnsObexClient != null && !mSdpSearchInitiated) {
                mBluetoothMnsObexClient.setMnsRecord(mMnsRecord);
            }
            if (status != -1 && mMnsRecord != null) {
                for (int i = 0, c = mMasInstances.size(); i < c; i++) {
                    mMasInstances
                            .valueAt(i)
                            .setRemoteFeatureMask(mMnsRecord.getSupportedFeatures());
                }
            }
            if (mSdpSearchInitiated) {
                mSdpSearchInitiated = false; // done searching
                sendConnectMessage(-1); // -1 indicates all MAS instances
            }
        }
    }

    //Binder object: Must be static class or memory leak may occur

    /**
+26 −55
Original line number Diff line number Diff line
@@ -26,14 +26,11 @@ import android.bluetooth.BluetoothUuid;
import android.bluetooth.IBluetoothMapClient;
import android.bluetooth.SdpMasRecord;
import android.content.AttributionSource;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.ParcelUuid;
import android.os.Parcelable;
import android.sysprop.BluetoothProperties;
import android.util.Log;

@@ -67,7 +64,6 @@ public class MapClientService extends ProfileService {
    private DatabaseManager mDatabaseManager;
    private static MapClientService sMapClientService;
    @VisibleForTesting
    MapBroadcastReceiver mMapReceiver;
    private Handler mHandler;

    public static boolean isEnabled() {
@@ -326,11 +322,6 @@ public class MapClientService extends ProfileService {
            }
        }

        mMapReceiver = new MapBroadcastReceiver();
        IntentFilter filter = new IntentFilter();
        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
        filter.addAction(BluetoothDevice.ACTION_SDP_RECORD);
        registerReceiver(mMapReceiver, filter);
        removeUncleanAccounts();
        MapClientContent.clearAllContent(this);
        setMapClientService(this);
@@ -343,10 +334,6 @@ public class MapClientService extends ProfileService {
            Log.d(TAG, "stop()");
        }

        if (mMapReceiver != null) {
            unregisterReceiver(mMapReceiver);
            mMapReceiver = null;
        }
        if (mMnsServer != null) {
            mMnsServer.stop();
        }
@@ -730,67 +717,51 @@ public class MapClientService extends ProfileService {
        }
    }

    @VisibleForTesting
    class MapBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (DBG) {
                Log.d(TAG, "onReceive: " + action);
            }
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            if (device == null) {
                Log.e(TAG, "broadcast has NO device param!");
                return;
    public void aclDisconnected(BluetoothDevice device, int transport) {
        mHandler.post(() -> handleAclDisconnected(device, transport));
    }

    private void handleAclDisconnected(BluetoothDevice device, int transport) {
        MceStateMachine stateMachine = mMapInstanceMap.get(device);
        if (stateMachine == null) {
            Log.e(TAG, "No Statemachine found for the device=" + device.toString());
            return;
        }

            if (action.equals(BluetoothDevice.ACTION_SDP_RECORD)) {
                ParcelUuid uuid = intent.getParcelableExtra(BluetoothDevice.EXTRA_UUID);
                if (DBG) {
                    Log.d(TAG, "Received SDP Record event, device=" + device.toString() + ", uuid="
                            + uuid);
                }
        Log.i(TAG, "Received ACL disconnection event, device=" + device.toString()
                + ", transport=" + transport);

                if (uuid.equals(BluetoothUuid.MAS)) {
                    // Check if we have a successful status with a valid SDP record.
                    int status = intent.getIntExtra(BluetoothDevice.EXTRA_SDP_SEARCH_STATUS, -1);
                    SdpMasRecord masRecord =
                            intent.getParcelableExtra(BluetoothDevice.EXTRA_SDP_RECORD);
                    if (DBG) {
                        Log.d(TAG, "SDP complete, status: " + status + ", record:" + masRecord);
                    }
                    stateMachine.sendSdpResult(status, masRecord);
                }
        if (transport != BluetoothDevice.TRANSPORT_BREDR) {
            return;
        }

        if (stateMachine.getState() == BluetoothProfile.STATE_CONNECTED) {
            stateMachine.disconnect();
        }
    }

    public void aclDisconnected(BluetoothDevice device, int transport) {
        mHandler.post(() -> handleAclDisconnected(device, transport));
    public void receiveSdpSearchRecord(
            BluetoothDevice device, int status, Parcelable record, ParcelUuid uuid) {
        mHandler.post(() -> handleSdpSearchRecordReceived(device, status, record, uuid));
    }

    private void handleAclDisconnected(BluetoothDevice device, int transport) {
    private void handleSdpSearchRecordReceived(
            BluetoothDevice device, int status, Parcelable record, ParcelUuid uuid) {
        MceStateMachine stateMachine = mMapInstanceMap.get(device);
        if (DBG) {
            Log.d(TAG, "Received SDP Record, device=" + device.toString() + ", uuid=" + uuid);
        }
        if (stateMachine == null) {
            Log.e(TAG, "No Statemachine found for the device=" + device.toString());
            return;
        }

        Log.i(TAG, "Received ACL disconnection event, device=" + device.toString()
                + ", transport=" + transport);

        if (transport != BluetoothDevice.TRANSPORT_BREDR) {
            return;
        if (uuid.equals(BluetoothUuid.MAS)) {
            // Check if we have a valid SDP record.
            SdpMasRecord masRecord = (SdpMasRecord) record;
            if (DBG) {
                Log.d(TAG, "SDP complete, status: " + status + ", record:" + masRecord);
            }

        if (stateMachine.getState() == BluetoothProfile.STATE_CONNECTED) {
            stateMachine.disconnect();
            stateMachine.sendSdpResult(status, masRecord);
        }
    }
}
+26 −3
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.accounts.AccountManager;
import android.annotation.RequiresPermission;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
import android.bluetooth.IBluetoothPbapClient;
import android.content.AttributionSource;
import android.content.BroadcastReceiver;
@@ -30,6 +31,8 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.Looper;
import android.os.ParcelUuid;
import android.os.Parcelable;
import android.provider.CallLog;
import android.sysprop.BluetoothProperties;
import android.util.Log;
@@ -90,6 +93,7 @@ public class PbapClientService extends ProfileService {
     */
    // TODO(233361365): Remove this pattern when the framework solves their race condition
    private static final int ACCOUNT_VISIBILITY_CHECK_MS = 500;

    private static final int ACCOUNT_VISIBILITY_CHECK_TRIES_MAX = 6;
    private int mAccountVisibilityCheckTries = 0;
    private final Handler mAuthServiceHandler = new Handler();
@@ -131,7 +135,9 @@ public class PbapClientService extends ProfileService {
            Log.v(TAG, "onStart");
        }

        mDatabaseManager = Objects.requireNonNull(AdapterService.getAdapterService().getDatabase(),
        mDatabaseManager =
                Objects.requireNonNull(
                        AdapterService.getAdapterService().getDatabase(),
                        "DatabaseManager cannot be null when PbapClientService starts");

        setComponentAvailable(AUTHENTICATOR_SERVICE, true);
@@ -295,7 +301,6 @@ public class PbapClientService extends ProfileService {
        }
    }


    @VisibleForTesting
    class PbapBroadcastReceiver extends BroadcastReceiver {
        @Override
@@ -581,6 +586,24 @@ public class PbapClientService extends ProfileService {
        return deviceList;
    }

    public void receiveSdpSearchRecord(
            BluetoothDevice device, int status, Parcelable record, ParcelUuid uuid) {
        PbapClientStateMachine stateMachine = mPbapClientStateMachineMap.get(device);
        if (stateMachine == null) {
            Log.e(TAG, "No Statemachine found for the device=" + device.toString());
            return;
        }
        if (DBG) {
            Log.v(TAG, "Received UUID: " + uuid.toString());
            Log.v(TAG, "expected UUID: " + BluetoothUuid.PBAP_PSE.toString());
        }
        if (uuid.equals(BluetoothUuid.PBAP_PSE)) {
            stateMachine
                    .obtainMessage(PbapClientStateMachine.MSG_SDP_COMPLETE, record)
                    .sendToTarget();
        }
    }

    /**
     * Get the current connection state of the profile
     *
Loading