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

Commit 0f6d7a1e authored by Sungsoo Lim's avatar Sungsoo Lim Committed by Gerrit Code Review
Browse files

Merge changes Ifc92b1b0,I7cfa3d0f

* changes:
  Add tests for BassClientStateMachine#ConnectedProcessing
  Add test for BassClientStateMachine#Connected
parents 0427cea2 176a9769
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -18,6 +18,9 @@ package com.android.bluetooth;

import android.annotation.RequiresPermission;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.le.PeriodicAdvertisingCallback;
import android.bluetooth.le.PeriodicAdvertisingManager;
import android.bluetooth.le.ScanResult;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
@@ -27,6 +30,7 @@ import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Handler;
import android.os.ParcelFileDescriptor;
import android.provider.Telephony;
import android.util.Log;
@@ -180,4 +184,14 @@ public class BluetoothMethodProxy {
    public long telephonyGetOrCreateThreadId(Context context, Set<String> recipients) {
        return Telephony.Threads.getOrCreateThreadId(context, recipients);
    }

    /**
     * Proxies {@link PeriodicAdvertisingManager#registerSync(ScanResult, int, int,
     * PeriodicAdvertisingCallback, Handler)}.
     */
    public void periodicAdvertisingManagerRegisterSync(PeriodicAdvertisingManager manager,
            ScanResult scanResult, int skip, int timeout,
            PeriodicAdvertisingCallback callback, Handler handler) {
        manager.registerSync(scanResult, skip, timeout, callback, handler);
    }
}
+15 −114
Original line number Diff line number Diff line
@@ -14,46 +14,6 @@
 * limitations under the License.
 */

/**
 * Bluetooth Bassclient StateMachine. There is one instance per remote device.
 *  - "Disconnected" and "Connected" are steady states.
 *  - "Connecting" and "Disconnecting" are transient states until the
 *     connection / disconnection is completed.
 *  - "ConnectedProcessing" is an intermediate state to ensure, there is only
 *    one Gatt transaction from the profile at any point of time
 *
 *
 *                        (Disconnected)
 *                           |       ^
 *                   CONNECT |       | DISCONNECTED
 *                           V       |
 *                 (Connecting)<--->(Disconnecting)
 *                           |       ^
 *                 CONNECTED |       | DISCONNECT
 *                           V       |
 *                          (Connected)
 *                           |       ^
 *                 GATT_TXN  |       | GATT_TXN_DONE/GATT_TXN_TIMEOUT
 *                           V       |
 *                          (ConnectedProcessing)
 * NOTES:
 *  - If state machine is in "Connecting" state and the remote device sends
 *    DISCONNECT request, the state machine transitions to "Disconnecting" state.
 *  - Similarly, if the state machine is in "Disconnecting" state and the remote device
 *    sends CONNECT request, the state machine transitions to "Connecting" state.
 *  - Whenever there is any Gatt Write/read, State machine will moved "ConnectedProcessing" and
 *    all other requests (add, update, remove source) operations will be deferred in
 *    "ConnectedProcessing" state
 *  - Once the gatt transaction is done (or after a specified timeout of no response),
 *    State machine will move back to "Connected" and try to process the deferred requests
 *    as needed
 *
 *                    DISCONNECT
 *    (Connecting) ---------------> (Disconnecting)
 *                 <---------------
 *                      CONNECT
 *
 */
package com.android.bluetooth.bass_client;

import static android.Manifest.permission.BLUETOOTH_CONNECT;
@@ -88,6 +48,7 @@ import android.os.ParcelUuid;
import android.provider.DeviceConfig;
import android.util.Log;

import com.android.bluetooth.BluetoothMethodProxy;
import com.android.bluetooth.Utils;
import com.android.bluetooth.btservice.ProfileService;
import com.android.bluetooth.btservice.ServiceFactory;
@@ -113,8 +74,10 @@ import java.util.stream.IntStream;
@VisibleForTesting
public class BassClientStateMachine extends StateMachine {
    private static final String TAG = "BassClientStateMachine";
    private static final byte[] REMOTE_SCAN_STOP = {00};
    private static final byte[] REMOTE_SCAN_START = {01};
    @VisibleForTesting
    static final byte[] REMOTE_SCAN_STOP = {00};
    @VisibleForTesting
    static final byte[] REMOTE_SCAN_START = {01};
    private static final byte OPCODE_ADD_SOURCE = 0x02;
    private static final byte OPCODE_UPDATE_SOURCE = 0x03;
    private static final byte OPCODE_SET_BCAST_PIN = 0x04;
@@ -150,7 +113,6 @@ public class BassClientStateMachine extends StateMachine {
    private final Disconnected mDisconnected = new Disconnected();
    private final Connected mConnected = new Connected();
    private final Connecting mConnecting = new Connecting();
    private final Disconnecting mDisconnecting = new Disconnecting();
    private final ConnectedProcessing mConnectedProcessing = new ConnectedProcessing();
    @VisibleForTesting
    final List<BluetoothGattCharacteristic> mBroadcastCharacteristics =
@@ -173,15 +135,18 @@ public class BassClientStateMachine extends StateMachine {
    private BluetoothAdapter mBluetoothAdapter =
            BluetoothAdapter.getDefaultAdapter();
    private ServiceFactory mFactory = new ServiceFactory();
    private int mPendingOperation = -1;
    private byte mPendingSourceId = -1;
    @VisibleForTesting
    int mPendingOperation = -1;
    @VisibleForTesting
    byte mPendingSourceId = -1;
    private BluetoothLeBroadcastMetadata mPendingMetadata = null;
    private BluetoothLeBroadcastReceiveState mSetBroadcastPINRcvState = null;
    private boolean mSetBroadcastCodePending = false;
    private final Map<Integer, Boolean> mPendingRemove = new HashMap();
    // Psync and PAST interfaces
    private PeriodicAdvertisingManager mPeriodicAdvManager;
    private boolean mAutoTriggered = false;
    @VisibleForTesting
    boolean mAutoTriggered = false;
    @VisibleForTesting
    boolean mNoStopScanOffload = false;
    private boolean mDefNoPAS = false;
@@ -200,7 +165,6 @@ public class BassClientStateMachine extends StateMachine {
        mService = svc;
        mConnectTimeoutMs = connectTimeoutMs;
        addState(mDisconnected);
        addState(mDisconnecting);
        addState(mConnected);
        addState(mConnecting);
        addState(mConnectedProcessing);
@@ -386,8 +350,9 @@ public class BassClientStateMachine extends StateMachine {
        mNoStopScanOffload = true;
        cancelActiveSync(null);
        try {
            mPeriodicAdvManager.registerSync(scanRes, 0,
                    BassConstants.PSYNC_TIMEOUT, mPeriodicAdvCallback);
            BluetoothMethodProxy.getInstance().periodicAdvertisingManagerRegisterSync(
                    mPeriodicAdvManager, scanRes, 0, BassConstants.PSYNC_TIMEOUT,
                    mPeriodicAdvCallback, null);
        } catch (IllegalArgumentException ex) {
            Log.w(TAG, "registerSync:IllegalArgumentException");
            Message message = obtainMessage(STOP_SCAN_OFFLOAD);
@@ -1795,7 +1760,7 @@ public class BassClientStateMachine extends StateMachine {
                    transitionTo(mConnected);
                    break;
                case GATT_TXN_TIMEOUT:
                    log("GATT transaction timedout for" + mDevice);
                    log("GATT transaction timeout for" + mDevice);
                    sendPendingCallbacks(
                            mPendingOperation,
                            BluetoothStatusCodes.ERROR_UNKNOWN);
@@ -1821,67 +1786,6 @@ public class BassClientStateMachine extends StateMachine {
        }
    }

    @VisibleForTesting
    class Disconnecting extends State {
        @Override
        public void enter() {
            log("Enter Disconnecting(" + mDevice + "): "
                    + messageWhatToString(getCurrentMessage().what));
            sendMessageDelayed(CONNECT_TIMEOUT, mDevice, mConnectTimeoutMs);
            broadcastConnectionState(
                    mDevice, mLastConnectionState, BluetoothProfile.STATE_DISCONNECTING);
        }

        @Override
        public void exit() {
            log("Exit Disconnecting(" + mDevice + "): "
                    + messageWhatToString(getCurrentMessage().what));
            removeMessages(CONNECT_TIMEOUT);
            mLastConnectionState = BluetoothProfile.STATE_DISCONNECTING;
        }

        @Override
        public boolean processMessage(Message message) {
            log("Disconnecting process message(" + mDevice + "): "
                    + messageWhatToString(message.what));
            switch (message.what) {
                case CONNECT:
                    log("Disconnecting to " + mDevice);
                    log("deferring this connection request " + mDevice);
                    deferMessage(message);
                    break;
                case DISCONNECT:
                    Log.w(TAG, "Already disconnecting: DISCONNECT ignored: " + mDevice);
                    break;
                case CONNECTION_STATE_CHANGED:
                    int state = (int) message.obj;
                    Log.w(TAG, "Disconnecting: connection state changed:" + state);
                    if (state == BluetoothProfile.STATE_CONNECTED) {
                        Log.e(TAG, "should never happen from this state");
                        transitionTo(mConnected);
                    } else {
                        Log.w(TAG, "disconnection successful to " + mDevice);
                        cancelActiveSync(null);
                        transitionTo(mDisconnected);
                    }
                    break;
                case CONNECT_TIMEOUT:
                    Log.w(TAG, "CONNECT_TIMEOUT");
                    BluetoothDevice device = (BluetoothDevice) message.obj;
                    if (!mDevice.equals(device)) {
                        Log.e(TAG, "Unknown device timeout " + device);
                        break;
                    }
                    transitionTo(mDisconnected);
                    break;
                default:
                    log("Disconnecting: not handled message:" + message.what);
                    return NOT_HANDLED;
            }
            return HANDLED;
        }
    }

    void broadcastConnectionState(BluetoothDevice device, int fromState, int toState) {
        log("broadcastConnectionState " + device + ": " + fromState + "->" + toState);
        if (fromState == BluetoothProfile.STATE_CONNECTED
@@ -1908,9 +1812,6 @@ public class BassClientStateMachine extends StateMachine {
            case "Disconnected":
                log("Disconnected");
                return BluetoothProfile.STATE_DISCONNECTED;
            case "Disconnecting":
                log("Disconnecting");
                return BluetoothProfile.STATE_DISCONNECTING;
            case "Connecting":
                log("Connecting");
                return BluetoothProfile.STATE_CONNECTING;
+434 −11

File changed.

Preview size limit exceeded, changes collapsed.