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

Commit bc4ba32d authored by William Escande's avatar William Escande Committed by Gerrit Code Review
Browse files

Merge "Csip: merge "start" into constructor" into main

parents 12634182 34257cb7
Loading
Loading
Loading
Loading
+10 −63
Original line number Diff line number Diff line
@@ -17,12 +17,13 @@

package com.android.bluetooth.csip;

import static java.util.Objects.requireNonNull;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.util.Log;

import com.android.bluetooth.Utils;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;

import java.util.UUID;
@@ -30,83 +31,29 @@ import java.util.UUID;
/** CSIP Set Coordinator role native interface */
public class CsipSetCoordinatorNativeInterface {
    private static final String TAG = "CsipSetCoordinatorNativeInterface";
    private BluetoothAdapter mAdapter;

    @GuardedBy("INSTANCE_LOCK")
    private static CsipSetCoordinatorNativeInterface sInstance;

    private static final Object INSTANCE_LOCK = new Object();

    private CsipSetCoordinatorNativeInterface() {
        mAdapter = BluetoothAdapter.getDefaultAdapter();
        if (mAdapter == null) {
            Log.wtf(TAG, "No Bluetooth Adapter Available");
        }
    }
    private final BluetoothAdapter mAdapter = BluetoothAdapter.getDefaultAdapter();

    /** Get singleton instance. */
    public static CsipSetCoordinatorNativeInterface getInstance() {
        synchronized (INSTANCE_LOCK) {
            if (sInstance == null) {
                sInstance = new CsipSetCoordinatorNativeInterface();
            }
            return sInstance;
        }
    CsipSetCoordinatorNativeInterface() {
        requireNonNull(mAdapter);
    }

    /** Set singleton instance. */
    @VisibleForTesting
    public static void setInstance(CsipSetCoordinatorNativeInterface instance) {
        synchronized (INSTANCE_LOCK) {
            sInstance = instance;
        }
    }

    /**
     * Initializes the native interface.
     *
     * <p>priorities to configure.
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public void init() {
    void init() {
        initNative();
    }

    /** Cleanup the native interface. */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public void cleanup() {
    void cleanup() {
        cleanupNative();
    }

    /**
     * Initiates CsipSetCoordinator connection to a remote device.
     *
     * @param device the remote device
     * @return true on success, otherwise false.
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public boolean connect(BluetoothDevice device) {
    boolean connect(BluetoothDevice device) {
        return connectNative(getByteAddress(device));
    }

    /**
     * Disconnects CsipSetCoordinator from a remote device.
     *
     * @param device the remote device
     * @return true on success, otherwise false.
     */
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public boolean disconnect(BluetoothDevice device) {
    boolean disconnect(BluetoothDevice device) {
        return disconnectNative(getByteAddress(device));
    }

    /**
     * Get the device by the address
     *
     * @return the device
     */
    @VisibleForTesting
    public BluetoothDevice getDevice(byte[] address) {
    BluetoothDevice getDevice(byte[] address) {
        return mAdapter.getRemoteDevice(address);
    }

+67 −113
Original line number Diff line number Diff line
@@ -20,6 +20,9 @@ package com.android.bluetooth.csip;
import static android.Manifest.permission.BLUETOOTH_CONNECT;
import static android.Manifest.permission.BLUETOOTH_PRIVILEGED;

import static java.util.Objects.requireNonNull;
import static java.util.Objects.requireNonNullElseGet;

import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -33,9 +36,7 @@ import android.bluetooth.IBluetoothCsipSetCoordinator;
import android.bluetooth.IBluetoothCsipSetCoordinatorCallback;
import android.bluetooth.IBluetoothCsipSetCoordinatorLockCallback;
import android.content.AttributionSource;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
@@ -60,7 +61,6 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
@@ -76,15 +76,13 @@ public class CsipSetCoordinatorService extends ProfileService {

    private static CsipSetCoordinatorService sCsipSetCoordinatorService;

    private Handler mHandler = null;

    private AdapterService mAdapterService;
    private LeAudioService mLeAudioService;
    private DatabaseManager mDatabaseManager;
    private HandlerThread mStateMachinesThread;
    @VisibleForTesting ServiceFactory mServiceFactory = new ServiceFactory();

    @VisibleForTesting CsipSetCoordinatorNativeInterface mCsipSetCoordinatorNativeInterface;
    private final AdapterService mAdapterService;
    private final DatabaseManager mDatabaseManager;
    private final Handler mHandler;
    private final HandlerThread mStateMachinesThread;
    private final Looper mStateMachinesLooper;
    private final CsipSetCoordinatorNativeInterface mNativeInterface;
    private final ServiceFactory mServiceFactory;

    @GuardedBy("mStateMachines")
    private final Map<BluetoothDevice, CsipSetCoordinatorStateMachine> mStateMachines =
@@ -103,66 +101,53 @@ public class CsipSetCoordinatorService extends ProfileService {
    private final Map<Integer, Pair<UUID, IBluetoothCsipSetCoordinatorLockCallback>> mLocks =
            new ConcurrentHashMap<>();

    public CsipSetCoordinatorService(Context ctx) {
        super(ctx);
    }
    private LeAudioService mLeAudioService;

    public static boolean isEnabled() {
        return BluetoothProperties.isProfileCsipSetCoordinatorEnabled().orElse(false);
    public CsipSetCoordinatorService(AdapterService adapterService) {
        this(adapterService, null, null, new ServiceFactory());
    }

    @Override
    protected IProfileServiceBinder initBinder() {
        return new BluetoothCsisBinder(this);
    @VisibleForTesting
    CsipSetCoordinatorService(
            AdapterService adapterService,
            Looper looper,
            CsipSetCoordinatorNativeInterface nativeInterface,
            ServiceFactory serviceFactory) {
        super(requireNonNull(adapterService));
        mAdapterService = adapterService;
        mDatabaseManager = requireNonNull(mAdapterService.getDatabase());
        mNativeInterface =
                requireNonNullElseGet(
                        nativeInterface, () -> new CsipSetCoordinatorNativeInterface());
        mServiceFactory = requireNonNull(serviceFactory);
        if (looper == null) {
            mHandler = new Handler(requireNonNull(Looper.getMainLooper()));
            mStateMachinesThread = new HandlerThread("CsipSetCoordinatorService.StateMachines");
            mStateMachinesThread.start();
            mStateMachinesLooper = mStateMachinesThread.getLooper();
        } else {
            mHandler = new Handler(looper);
            mStateMachinesThread = null;
            mStateMachinesLooper = looper;
        }

    @Override
    public void start() {
        Log.d(TAG, "start()");
        if (sCsipSetCoordinatorService != null) {
            throw new IllegalStateException("start() called twice");
        }

        // Get AdapterService, DatabaseManager, CsipSetCoordinatorNativeInterface.
        // None of them can be null.
        mAdapterService =
                Objects.requireNonNull(
                        AdapterService.getAdapterService(),
                        "AdapterService cannot be null when CsipSetCoordinatorService starts");
        mDatabaseManager =
                Objects.requireNonNull(
                        mAdapterService.getDatabase(),
                        "DatabaseManager cannot be null when CsipSetCoordinatorService starts");
        mCsipSetCoordinatorNativeInterface =
                Objects.requireNonNull(
                        CsipSetCoordinatorNativeInterface.getInstance(),
                        "CsipSetCoordinatorNativeInterface cannot be null when"
                                .concat("CsipSetCoordinatorService starts"));

        // Setup Handler.
        mHandler = new Handler(Looper.getMainLooper());

        // Get LE Audio service (can be null)
        mLeAudioService = mServiceFactory.getLeAudioService();

        synchronized (mStateMachines) {
            mStateMachines.clear();
        }

        // Start handler thread for state machines
        mStateMachinesThread = new HandlerThread("CsipSetCoordinatorService.StateMachines");
        mStateMachinesThread.start();

        // Setup broadcast receivers
        IntentFilter filter = new IntentFilter();
        filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
        filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);

        // Mark service as started
        setCsipSetCoordinatorService(this);

        // Initialize native interface
        mCsipSetCoordinatorNativeInterface.init();
        mNativeInterface.init();
    }

    public static boolean isEnabled() {
        return BluetoothProperties.isProfileCsipSetCoordinatorEnabled().orElse(false);
    }

    @Override
    protected IProfileServiceBinder initBinder() {
        return new BluetoothCsisBinder(this);
    }

    @Override
@@ -174,8 +159,7 @@ public class CsipSetCoordinatorService extends ProfileService {
        }

        // Cleanup native interface
        mCsipSetCoordinatorNativeInterface.cleanup();
        mCsipSetCoordinatorNativeInterface = null;
        mNativeInterface.cleanup();

        // Mark service as stopped
        setCsipSetCoordinatorService(null);
@@ -193,17 +177,13 @@ public class CsipSetCoordinatorService extends ProfileService {
            try {
                mStateMachinesThread.quitSafely();
                mStateMachinesThread.join(SM_THREAD_JOIN_TIMEOUT_MS);
                mStateMachinesThread = null;
            } catch (InterruptedException e) {
                // Do not rethrow as we are shutting down anyway
            }
        }

        // Unregister Handler and stop all queued messages.
        if (mHandler != null) {
        mHandler.removeCallbacksAndMessages(null);
            mHandler = null;
        }

        mDeviceGroupIdRankMap.clear();
        mCallbacks.clear();
@@ -213,10 +193,6 @@ public class CsipSetCoordinatorService extends ProfileService {
        mGroupIdToUuidMap.clear();

        mLocks.clear();

        // Clear AdapterService, CsipSetCoordinatorNativeInterface
        mCsipSetCoordinatorNativeInterface = null;
        mAdapterService = null;
    }

    @Override
@@ -515,7 +491,7 @@ public class CsipSetCoordinatorService extends ProfileService {
        }

        Log.d(TAG, "lockGroup(): locking group: " + groupId);
        mCsipSetCoordinatorNativeInterface.groupLockSet(groupId, true);
        mNativeInterface.groupLockSet(groupId, true);
        return uuid;
    }

@@ -536,7 +512,7 @@ public class CsipSetCoordinatorService extends ProfileService {
                Pair<UUID, IBluetoothCsipSetCoordinatorLockCallback> uuidCbPair = entry.getValue();
                if (uuidCbPair.first.equals(lockUuid)) {
                    Log.d(TAG, "unlockGroup(): unlocking ... " + lockUuid);
                    mCsipSetCoordinatorNativeInterface.groupLockSet(entry.getKey(), false);
                    mNativeInterface.groupLockSet(entry.getKey(), false);
                    return;
                }
            }
@@ -823,7 +799,7 @@ public class CsipSetCoordinatorService extends ProfileService {
        Intent intent = null;
        int groupId = stackEvent.valueInt1;
        if (stackEvent.type == CsipSetCoordinatorStackEvent.EVENT_TYPE_DEVICE_AVAILABLE) {
            Objects.requireNonNull(device);
            requireNonNull(device);

            intent = new Intent(BluetoothCsipSetCoordinator.ACTION_CSIS_DEVICE_AVAILABLE);
            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, stackEvent.device);
@@ -841,7 +817,7 @@ public class CsipSetCoordinatorService extends ProfileService {
                    stackEvent.valueInt2);
        } else if (stackEvent.type
                == CsipSetCoordinatorStackEvent.EVENT_TYPE_SET_MEMBER_AVAILABLE) {
            Objects.requireNonNull(device);
            requireNonNull(device);
            if (!mFoundSetMemberToGroupId.containsKey(device)) {
                mFoundSetMemberToGroupId.put(device, groupId);
            }
@@ -900,10 +876,7 @@ public class CsipSetCoordinatorService extends ProfileService {
            Log.d(TAG, "Creating a new state machine for " + device);
            sm =
                    CsipSetCoordinatorStateMachine.make(
                            device,
                            this,
                            mCsipSetCoordinatorNativeInterface,
                            mStateMachinesThread.getLooper());
                            device, this, mNativeInterface, mStateMachinesLooper);
            mStateMachines.put(device, sm);
            return sm;
        }
@@ -911,16 +884,6 @@ public class CsipSetCoordinatorService extends ProfileService {

    /** Process a change in the bonding state for a device */
    public void handleBondStateChanged(BluetoothDevice device, int fromState, int toState) {
        if (mHandler == null) {
            Log.e(
                    TAG,
                    "mHandler is null, service is stopped. Ignore Bond State for "
                            + device
                            + " to state: "
                            + toState);
            return;
        }

        mHandler.post(() -> bondStateChanged(device, toState));
    }

@@ -982,15 +945,6 @@ public class CsipSetCoordinatorService extends ProfileService {
    }

    void handleConnectionStateChanged(BluetoothDevice device, int fromState, int toState) {
        if (mHandler == null) {
            Log.e(
                    TAG,
                    "mHandler is null, service is stopped. Ignore Connection State for "
                            + device
                            + " to state: "
                            + toState);
            return;
        }
        mHandler.post(() -> connectionStateChanged(device, fromState, toState));
    }

@@ -1074,7 +1028,7 @@ public class CsipSetCoordinatorService extends ProfileService {

        @Override
        public List<BluetoothDevice> getConnectedDevices(AttributionSource source) {
            Objects.requireNonNull(source, "source cannot be null");
            requireNonNull(source);

            CsipSetCoordinatorService service = getService(source);
            if (service == null) {
@@ -1087,7 +1041,7 @@ public class CsipSetCoordinatorService extends ProfileService {
        @Override
        public List<BluetoothDevice> getDevicesMatchingConnectionStates(
                int[] states, AttributionSource source) {
            Objects.requireNonNull(source, "source cannot be null");
            requireNonNull(source);

            CsipSetCoordinatorService service = getService(source);
            if (service == null) {
@@ -1099,8 +1053,8 @@ public class CsipSetCoordinatorService extends ProfileService {

        @Override
        public int getConnectionState(BluetoothDevice device, AttributionSource source) {
            Objects.requireNonNull(device, "device cannot be null");
            Objects.requireNonNull(source, "source cannot be null");
            requireNonNull(device);
            requireNonNull(source);

            CsipSetCoordinatorService service = getService(source);
            if (service == null) {
@@ -1113,8 +1067,8 @@ public class CsipSetCoordinatorService extends ProfileService {
        @Override
        public boolean setConnectionPolicy(
                BluetoothDevice device, int connectionPolicy, AttributionSource source) {
            Objects.requireNonNull(device, "device cannot be null");
            Objects.requireNonNull(source, "source cannot be null");
            requireNonNull(device);
            requireNonNull(source);

            CsipSetCoordinatorService service = getService(source);
            if (service == null) {
@@ -1126,8 +1080,8 @@ public class CsipSetCoordinatorService extends ProfileService {

        @Override
        public int getConnectionPolicy(BluetoothDevice device, AttributionSource source) {
            Objects.requireNonNull(device, "device cannot be null");
            Objects.requireNonNull(source, "source cannot be null");
            requireNonNull(device);
            requireNonNull(source);

            CsipSetCoordinatorService service = getService(source);
            if (service == null) {
@@ -1142,8 +1096,8 @@ public class CsipSetCoordinatorService extends ProfileService {
                int groupId,
                @NonNull IBluetoothCsipSetCoordinatorLockCallback callback,
                AttributionSource source) {
            Objects.requireNonNull(callback, "callback cannot be null");
            Objects.requireNonNull(source, "source cannot be null");
            requireNonNull(callback);
            requireNonNull(source);

            CsipSetCoordinatorService service = getService(source);
            if (service == null) {
@@ -1156,8 +1110,8 @@ public class CsipSetCoordinatorService extends ProfileService {

        @Override
        public void unlockGroup(@NonNull ParcelUuid lockUuid, AttributionSource source) {
            Objects.requireNonNull(lockUuid, "lockUuid cannot be null");
            Objects.requireNonNull(source, "source cannot be null");
            requireNonNull(lockUuid);
            requireNonNull(source);

            CsipSetCoordinatorService service = getService(source);
            if (service == null) {
@@ -1169,8 +1123,8 @@ public class CsipSetCoordinatorService extends ProfileService {

        @Override
        public List<Integer> getAllGroupIds(ParcelUuid uuid, AttributionSource source) {
            Objects.requireNonNull(uuid, "uuid cannot be null");
            Objects.requireNonNull(source, "source cannot be null");
            requireNonNull(uuid);
            requireNonNull(source);

            CsipSetCoordinatorService service = getService(source);
            if (service == null) {
+1 −4
Original line number Diff line number Diff line
@@ -37,7 +37,6 @@ import com.android.bluetooth.a2dpsink.A2dpSinkNativeInterface;
import com.android.bluetooth.avrcp.AvrcpNativeInterface;
import com.android.bluetooth.avrcpcontroller.AvrcpControllerNativeInterface;
import com.android.bluetooth.btservice.storage.DatabaseManager;
import com.android.bluetooth.csip.CsipSetCoordinatorNativeInterface;
import com.android.bluetooth.hearingaid.HearingAidNativeInterface;
import com.android.bluetooth.hfp.HeadsetNativeInterface;
import com.android.bluetooth.hfpclient.NativeInterface;
@@ -91,7 +90,6 @@ public class ProfileServiceTest {
    @Mock private HidDeviceNativeInterface mHidDeviceNativeInterface;
    @Mock private HidHostNativeInterface mHidHostNativeInterface;
    @Mock private PanNativeInterface mPanNativeInterface;
    @Mock private CsipSetCoordinatorNativeInterface mCsipSetCoordinatorInterface;
    @Mock private LeAudioNativeInterface mLeAudioInterface;

    private void setProfileState(int profile, int state) {
@@ -156,6 +154,7 @@ public class ProfileServiceTest {
                                profile ->
                                        profile != BluetoothProfile.HAP_CLIENT
                                                && profile != BluetoothProfile.VOLUME_CONTROL
                                                && profile != BluetoothProfile.CSIP_SET_COORDINATOR
                                                && profile != BluetoothProfile.GATT)
                        .toArray();
        TestUtils.setAdapterService(mAdapterService);
@@ -172,7 +171,6 @@ public class ProfileServiceTest {
        HidDeviceNativeInterface.setInstance(mHidDeviceNativeInterface);
        HidHostNativeInterface.setInstance(mHidHostNativeInterface);
        PanNativeInterface.setInstance(mPanNativeInterface);
        CsipSetCoordinatorNativeInterface.setInstance(mCsipSetCoordinatorInterface);
        LeAudioNativeInterface.setInstance(mLeAudioInterface);
    }

@@ -192,7 +190,6 @@ public class ProfileServiceTest {
        HidDeviceNativeInterface.setInstance(null);
        HidHostNativeInterface.setInstance(null);
        PanNativeInterface.setInstance(null);
        CsipSetCoordinatorNativeInterface.setInstance(null);
        LeAudioNativeInterface.setInstance(null);
    }

+237 −509

File changed.

Preview size limit exceeded, changes collapsed.