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

Commit 25552a3e authored by Poompatai Puntitpong's avatar Poompatai Puntitpong Committed by Gerrit Code Review
Browse files

Merge "Add additional HFP AT commands that return device information to...

Merge "Add additional HFP AT commands that return device information to enhance IOP with remote devices" into main
parents be13cd04 0e4d90ae
Loading
Loading
Loading
Loading
+80 −1
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.bluetooth.BluetoothStatusCodes;
import android.bluetooth.hfp.BluetoothHfpProtoEnums;
import android.content.Intent;
import android.media.AudioManager;
import android.os.Build;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;
@@ -181,6 +182,18 @@ public class HeadsetStateMachine extends StateMachine {
        VENDOR_SPECIFIC_AT_COMMAND_COMPANY_ID.put(
                BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_IPHONEACCEV,
                BluetoothAssignedNumbers.APPLE);
        VENDOR_SPECIFIC_AT_COMMAND_COMPANY_ID.put(
                BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_CGMI,
                BluetoothAssignedNumbers.GOOGLE);
        VENDOR_SPECIFIC_AT_COMMAND_COMPANY_ID.put(
                BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_CGMR,
                BluetoothAssignedNumbers.GOOGLE);
        VENDOR_SPECIFIC_AT_COMMAND_COMPANY_ID.put(
                BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_CGMM,
                BluetoothAssignedNumbers.GOOGLE);
        VENDOR_SPECIFIC_AT_COMMAND_COMPANY_ID.put(
                BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_CGSN,
                BluetoothAssignedNumbers.GOOGLE);
    }

    private HeadsetStateMachine(BluetoothDevice device, Looper looper,
@@ -2030,7 +2043,32 @@ public class HeadsetStateMachine extends StateMachine {
    void processVendorSpecificAt(String atString, BluetoothDevice device) {
        log("processVendorSpecificAt - atString = " + atString);

        // Currently we accept only SET type commands.
        // Currently we accept only SET type commands, except the 4 AT commands
        // which requests the device's information: +CGMI, +CGMM, +CGMR and +CGSN, which we
        // responds to right away without any further processing.
        boolean isIopInfoRequestAt = true;
        switch (atString) {
            case BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_CGMI:
                processAtCgmi(device);
                break;
            case BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_CGMM:
                processAtCgmm(device);
                break;
            case BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_CGMR:
                processAtCgmr(device);
                break;
            case BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_CGSN:
                processAtCgsn(device);
                break;
            default:
                isIopInfoRequestAt = false;
        }
        if (isIopInfoRequestAt) {
            mNativeInterface.atResponseCode(device, HeadsetHalConstants.AT_RESPONSE_OK, 0);
            return;
        }

        // Check if the command is a SET type command.
        int indexOfEqual = atString.indexOf("=");
        if (indexOfEqual == -1) {
            Log.w(TAG, "processVendorSpecificAt: command type error in " + atString);
@@ -2221,6 +2259,47 @@ public class HeadsetStateMachine extends StateMachine {
        mNativeInterface.atResponseString(device, "+XAPL=iPhone," + String.valueOf(2));
    }

    /**
     * Process AT+CGMI AT command
     *
     * @param device Remote device that has sent this command
     */
    @VisibleForTesting
    void processAtCgmi(BluetoothDevice device) {
        mNativeInterface.atResponseString(device, Build.MANUFACTURER);
    }

    /**
     * Process AT+CGMM AT command
     *
     * @param device Remote device that has sent this command
     */
    @VisibleForTesting
    void processAtCgmm(BluetoothDevice device) {
        mNativeInterface.atResponseString(device, Build.MODEL);
    }

    /**
     * Process AT+CGMR AT command
     *
     * @param device Remote device that has sent this command
     */
    @VisibleForTesting
    void processAtCgmr(BluetoothDevice device) {
        mNativeInterface.atResponseString(
                device, String.format("%s (%s)", Build.VERSION.RELEASE, Build.VERSION.INCREMENTAL));
    }

    /**
     * Process AT+CGSN AT command
     *
     * @param device Remote device that has sent this command
     */
    @VisibleForTesting
    void processAtCgsn(BluetoothDevice device) {
        mNativeInterface.atResponseString(device, Build.getSerial());
    }

    @VisibleForTesting
    void processUnknownAt(String atString, BluetoothDevice device) {
        if (device == null) {
+45 −1
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.content.ServiceConnection;
import android.database.Cursor;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.HandlerThread;
@@ -1374,7 +1375,7 @@ public class HeadsetStateMachineTest {
    }

    @Test
    public void testProcessVendorSpecificAt_withNoEqualSignCommand() {
    public void testProcessVendorSpecificAt_withNonExceptedNoEqualSignCommand() {
        String atString = "invalid_command";

        mHeadsetStateMachine.processVendorSpecificAt(atString, mTestDevice);
@@ -1413,6 +1414,49 @@ public class HeadsetStateMachineTest {
        verify(mNativeInterface).atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_OK, 0);
    }

    @Test
    public void testProcessVendorSpecificAt_withExceptedNoEqualSignCommandCGMI() {
        String atString = BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_CGMI;

        mHeadsetStateMachine.processVendorSpecificAt(atString, mTestDevice);

        verify(mNativeInterface).atResponseString(mTestDevice, Build.MANUFACTURER);
        verify(mNativeInterface).atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_OK, 0);
    }

    @Test
    public void testProcessVendorSpecificAt_withExceptedNoEqualSignCommandCGMM() {
        String atString = BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_CGMM;

        mHeadsetStateMachine.processVendorSpecificAt(atString, mTestDevice);

        verify(mNativeInterface).atResponseString(mTestDevice, Build.MODEL);
        verify(mNativeInterface).atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_OK, 0);
    }

    @Test
    public void testProcessVendorSpecificAt_withExceptedNoEqualSignCommandCGMR() {
        String atString = BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_CGMR;

        mHeadsetStateMachine.processVendorSpecificAt(atString, mTestDevice);

        verify(mNativeInterface)
                .atResponseString(
                        mTestDevice,
                        String.format("%s (%s)", Build.VERSION.RELEASE, Build.VERSION.INCREMENTAL));
        verify(mNativeInterface).atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_OK, 0);
    }

    @Test
    public void testProcessVendorSpecificAt_withExceptedNoEqualSignCommandCGSN() {
        String atString = BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_CGSN;

        mHeadsetStateMachine.processVendorSpecificAt(atString, mTestDevice);

        verify(mNativeInterface).atResponseString(mTestDevice, Build.getSerial());
        verify(mNativeInterface).atResponseCode(mTestDevice, HeadsetHalConstants.AT_RESPONSE_OK, 0);
    }

    @Test
    public void testProcessVolumeEvent_withVolumeTypeMic() {
        when(mHeadsetService.getActiveDevice()).thenReturn(mTestDevice);
+29 −0
Original line number Diff line number Diff line
@@ -270,6 +270,35 @@ public final class BluetoothHeadset implements BluetoothProfile {
     */
    public static final String VENDOR_SPECIFIC_HEADSET_EVENT_XEVENT_BATTERY_LEVEL = "BATTERY";

    /**
     * A vendor-specific AT command that asks for the information about device manufacturer.
     *
     * @hide
     */
    public static final String VENDOR_SPECIFIC_HEADSET_EVENT_CGMI = "+CGMI";

    /**
     * A vendor-specific AT command that asks for the information about the model of the device.
     *
     * @hide
     */
    public static final String VENDOR_SPECIFIC_HEADSET_EVENT_CGMM = "+CGMM";

    /**
     * A vendor-specific AT command that asks for the revision information, for Android we will
     * return the OS version and build number.
     *
     * @hide
     */
    public static final String VENDOR_SPECIFIC_HEADSET_EVENT_CGMR = "+CGMR";

    /**
     * A vendor-specific AT command that asks for the device's serial number.
     *
     * @hide
     */
    public static final String VENDOR_SPECIFIC_HEADSET_EVENT_CGSN = "+CGSN";

    /**
     * Headset state when SCO audio is not connected.
     * This state can be one of