藍芽之十二-HFP app層

shichaog發表於2016-08-23

在android6中,HFP的app層程式碼位於:

/packages/apps/Bluetooth/src/com/android/bluetooth/hfpclient

配置使能程式碼位於

<values/config.xml>
    <bool name="profile_supported_hs_hfp">true</bool>
    <bool name="profile_supported_hfpclient">true</bool>

如上,配置了hs和hfpclinent使能,由於程式碼會呼叫層次結構比較深,這裡以廣度優先法分析HFP功能。
首先和HFP client息息相關的有三個檔案。

HeadsetClientHalConstants.java 
HeadsetClientService.java  
HeadsetClientStateMachine.java

HeadsetClientHalConstants.java

這個檔案的命名就顯示其和HAL層是有關係的,裡面的常量定義是和HAL層一致的。

final public class HeadsetClientHalConstants {
    // 如果這裡的定義有變化,需要和HAL bt_hf_client.h保持一致
    // 0~4和bt_hf_client.h檔案裡定義的列舉型別是一致的,用於表示連線的斷開,正在連線,連線成功,SLC(Service Level Connection)連線,和正在斷開連線
    final static int CONNECTION_STATE_DISCONNECTED = 0;
    final static int CONNECTION_STATE_CONNECTING = 1;
    final static int CONNECTION_STATE_CONNECTED = 2;
    final static int CONNECTION_STATE_SLC_CONNECTED = 3;
    final static int CONNECTION_STATE_DISCONNECTING = 4;

    // 和bt_hf_client.h檔案 bthf_client_audio_state_t 定義的列舉保持一致,用於指示audio狀態
    final static int AUDIO_STATE_DISCONNECTED = 0;
    final static int AUDIO_STATE_CONNECTING = 1;
    final static int AUDIO_STATE_CONNECTED = 2;
    final static int AUDIO_STATE_CONNECTED_MSBC = 3;

    // 和 bt_hf_client.h的bthf_client_vr_state_t定義的列舉型別一致,VR是voice Recognition的縮寫。
    final static int VR_STATE_STOPPED = 0;
    final static int VR_STATE_STARTED = 1;

    //bt_hf_client.h定義的bthf_client_volume_type_t列舉音量調節物件,speaker還是mic。
    final static int VOLUME_TYPE_SPK = 0;
    final static int VOLUME_TYPE_MIC = 1;

    // match up with bthf_client_network_state_t enum of bt_hf_client.h
    final static int NETWORK_STATE_NOT_AVAILABLE = 0;
    final static int NETWORK_STATE_AVAILABLE = 1;

    // match up with bthf_client_service_type_t enum of bt_hf_client.h
    final static int SERVICE_TYPE_HOME = 0;
    final static int SERVICE_TYPE_ROAMING = 1;

    // match up with bthf_client_call_state_t enum of bt_hf_client.h,RESP是response的縮寫
    final static int CALL_STATE_ACTIVE = 0;
    final static int CALL_STATE_HELD = 1;
    final static int CALL_STATE_DIALING = 2;
    final static int CALL_STATE_ALERTING = 3;
    final static int CALL_STATE_INCOMING = 4;
    final static int CALL_STATE_WAITING = 5;
    final static int CALL_STATE_HELD_BY_RESP_HOLD = 6;

    // match up with bthf_client_call_t enum of bt_hf_client.h
    final static int CALL_NO_CALLS_IN_PROGRESS = 0;
    final static int CALL_CALLS_IN_PROGRESS = 1;

    // match up with bthf_client_callsetup_t enum of bt_hf_client.h
    final static int CALLSETUP_NONE = 0;
    final static int CALLSETUP_INCOMING = 1;
    final static int CALLSETUP_OUTGOING = 2;
    final static int CALLSETUP_ALERTING = 3;

    // match up with bthf_client_callheld_t enum of bt_hf_client.h
    final static int CALLHELD_NONE = 0;
    final static int CALLHELD_HOLD_AND_ACTIVE = 1;
    final static int CALLHELD_HOLD = 2;

    // match up with btrh_client_resp_and_hold_t of bt_hf_client.h
    final static int RESP_AND_HOLD_HELD = 0;
    final static int RESP_AND_HOLD_ACCEPT = 1;
    final static int RESP_AND_HOLD_REJECT = 2;

    // match up with bthf_client_call_direction_t enum of bt_hf_client.h
    final static int CALL_DIRECTION_OUTGOING = 0;
    final static int CALL_DIRECTION_INCOMING = 1;

    // match up with bthf_client_call_mpty_type_t enum of bt_hf_client.h,SINGLE單電話, MULTI多方電話
    final static int CALL_MPTY_TYPE_SINGLE = 0;
    final static int CALL_MPTY_TYPE_MULTI = 1;

    // match up with bthf_client_cmd_complete_t enum of bt_hf_client.h,命令完成應答
    final static int CMD_COMPLETE_OK = 0;
    final static int CMD_COMPLETE_ERROR = 1;
    final static int CMD_COMPLETE_ERROR_NO_CARRIER = 2;
    final static int CMD_COMPLETE_ERROR_BUSY = 3;
    final static int CMD_COMPLETE_ERROR_NO_ANSWER = 4;
    final static int CMD_COMPLETE_ERROR_DELAYED = 5;
    final static int CMD_COMPLETE_ERROR_BLACKLISTED = 6;
    final static int CMD_COMPLETE_ERROR_CME = 7;

    // match up with bthf_client_call_action_t enum of bt_hf_client.h,呼叫動作
    final static int CALL_ACTION_CHLD_0 = 0;
    final static int CALL_ACTION_CHLD_1 = 1;
    final static int CALL_ACTION_CHLD_2 = 2;
    final static int CALL_ACTION_CHLD_3 = 3;
    final static int CALL_ACTION_CHLD_4 = 4;
    final static int CALL_ACTION_CHLD_1x = 5;
    final static int CALL_ACTION_CHLD_2x = 6;
    final static int CALL_ACTION_ATA = 7;
    final static int CALL_ACTION_CHUP = 8;
    final static int CALL_ACTION_BTRH_0 = 9;
    final static int CALL_ACTION_BTRH_1 = 10;
    final static int CALL_ACTION_BTRH_2 = 11;

    // match up with bthf_client_subscriber_service_type_t enum of
    // bt_hf_client.h
    final static int SUBSCRIBER_SERVICE_TYPE_UNKNOWN = 0;
    final static int SUBSCRIBER_SERVICE_TYPE_VOICE = 1;
    final static int SUBSCRIBER_SERVICE_TYPE_FAX = 2;

    // match up with bthf_client_in_band_ring_state_t enum in bt_hf_client.h,電話鈴聲同傳
    final static int IN_BAND_RING_NOT_PROVIDED = 0;
    final static int IN_BAND_RING_PROVIDED = 1;

    // AG(Audio Gate) features masks,
    // match up with masks in bt_hf_client.h
    // Three-way calling
    final static int PEER_FEAT_3WAY     = 0x00000001;
    // Echo cancellation and/or noise reduction
    final static int PEER_FEAT_ECNR     = 0x00000002;
    // Voice recognition
    final static int PEER_FEAT_VREC     = 0x00000004;
    // In-band ring tone
    final static int PEER_FEAT_INBAND   = 0x00000008;
    // Attach a phone number to a voice tag
    final static int PEER_FEAT_VTAG     = 0x00000010;
    // Ability to reject incoming call
    final static int PEER_FEAT_REJECT   = 0x00000020;
    // Enhanced Call Status
    final static int PEER_FEAT_ECS      = 0x00000040;
    // Enhanced Call Control
    final static int PEER_FEAT_ECC      = 0x00000080;
    // Extended error codes
    final static int PEER_FEAT_EXTERR   = 0x00000100;
    // Codec Negotiation
    final static int PEER_FEAT_CODEC    = 0x00000200;

    // AG's 3WC features masks
    // match up with masks in bt_hf_client.h
    // 0  Release waiting call or held calls
    final static int CHLD_FEAT_REL           = 0x00000001;
    // 1  Release active calls and accept other (waiting or held) cal
    final static int CHLD_FEAT_REL_ACC       = 0x00000002;
    // 1x Release specified active call only
    final static int CHLD_FEAT_REL_X         = 0x00000004;
    // 2  Active calls on hold and accept other (waiting or held) call
    final static int CHLD_FEAT_HOLD_ACC      = 0x00000008;
    // 2x Request private mode with specified call (put the rest on hold)
    final static int CHLD_FEAT_PRIV_X        = 0x00000010;
    // 3  Add held call to multiparty */
    final static int CHLD_FEAT_MERGE         = 0x00000020;
    // 4  Connect two calls and leave (disconnect from) multiparty */
    final static int CHLD_FEAT_MERGE_DETACH  = 0x00000040;

    // AT Commands
    // These Commands values must match with Constants defined in
    // tBTA_HF_CLIENT_AT_CMD_TYPE in bta_hf_client_api.h
    // used for sending vendor specific AT cmds to AG.

    final static int HANDSFREECLIENT_AT_CMD_NREC = 15;

    // Flag to check for local NREC support
    final static boolean HANDSFREECLIENT_NREC_SUPPORTED = true;
}

HeadsetClientService.java

public class HeadsetClientService extends ProfileService {
    //狀態機,多例
    private HeadsetClientStateMachine mStateMachine;
    //Headset client服務端,單例,可以有多個HeadsetClient代理
    private static HeadsetClientService sHeadsetClientService;
    @Override//代理的binder
    public IProfileServiceBinder initBinder() {
        return new BluetoothHeadsetClientBinder(this);
    }

        @Override
    protected boolean start() {
        mStateMachine = HeadsetClientStateMachine.make(this);//建立狀態機
        IntentFilter filter = new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION);
        filter.addAction(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY);
        try {
        //註冊廣播時間的過濾器和行為
            registerReceiver(mBroadcastReceiver, filter);
        } catch (Exception e) {
            Log.w(TAG, "Unable to register broadcat receiver", e);
        }
        //啟動服務時,service存在檢查
        setHeadsetClientService(this);
        return true;
    }
    //broadcastReceiver類建立,該類向HeadsetClientStateMachine傳送音量設定訊息
        private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();

            if (action.equals(AudioManager.VOLUME_CHANGED_ACTION)) {
                int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
                if (streamType == AudioManager.STREAM_BLUETOOTH_SCO) {
                    int streamValue = intent
                            .getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1);
                    int streamPrevValue = intent.getIntExtra(
                            AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, -1);

                    if (streamValue != -1 && streamValue != streamPrevValue) {
                        mStateMachine.sendMessage(mStateMachine.obtainMessage(
                                HeadsetClientStateMachine.SET_SPEAKER_VOLUME, streamValue, 0));
                    }
                }
            }
        }
    };
    //frameworks/base/core/java/android/bluetooth/IBluetoothHeadsetClient.aidl定義的client可以使用的介面實現。這些介面就是呼叫該service實現該方法的。

    private static class BluetoothHeadsetClientBinder extends IBluetoothHeadsetClient.Stub
            implements IProfileServiceBinder {
        private HeadsetClientService mService;
        ...
       }
//傳送訊息給state machine。實現連線功能
    public boolean connect(BluetoothDevice device) {
        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                "Need BLUETOOTH ADMIN permission");

        if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) {
            return false;
        }

        int connectionState = mStateMachine.getConnectionState(device);
        if (connectionState == BluetoothProfile.STATE_CONNECTED ||
                connectionState == BluetoothProfile.STATE_CONNECTING) {
            return false;
        }

        mStateMachine.sendMessage(HeadsetClientStateMachine.CONNECT, device);
        return true;
    }

總結一下,該檔案實現了aidl檔案的方法,這些方法包括連線,連線音訊,撥打/接聽/拒接等,這些方法的呼叫是通過JNI的。這些方法的實現通過傳送訊息給狀態機來完成。

HeadsetClientStateMachine.java

final class HeadsetClientStateMachine extends StateMachine {
//定義了四個狀態機,分別是未連線,正在連線/連線成功和音訊開啟四個狀態。
    private final Disconnected mDisconnected;
    private final Connecting mConnecting;
    private final Connected mConnected;
    private final AudioOn mAudioOn;

//塊靜態方法
    static {
        classInitNative();
    }

相關文章