Android13 BluetoothHeadsetClient dial流程分析

BluetoothHeadsetClient dial用于拨打电话,代码如下:

//packages/modules/Bluetooth/framework/java/android/bluetooth/BluetoothHeadsetClient.java
public final class BluetoothHeadsetClient implements BluetoothProfile, AutoCloseable {
    public BluetoothHeadsetClientCall dial(BluetoothDevice device, String number) {
        if (DBG) log("dial()");
        final IBluetoothHeadsetClient service = getService();
        final BluetoothHeadsetClientCall defaultValue = null;
        if (service == null) {
            Log.w(TAG, "Proxy not attached to service");
            if (DBG) log(Log.getStackTraceString(new Throwable()));
        } else if (isEnabled() && isValidDevice(device)) {
            try {
                final SynchronousResultReceiver<BluetoothHeadsetClientCall> recv =
                        SynchronousResultReceiver.get();
                service.dial(device, number, mAttributionSource, recv);
                return Attributable.setAttributionSource(
                        recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue),
                        mAttributionSource);
            } catch (RemoteException | TimeoutException e) {
                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
            }
        }
        return defaultValue;
    }
}

调用IBluetoothHeadsetClient的dial方法,IBluetoothHeadsetClient是一个接口由HeadsetClientService的内部类BluetoothHeadsetClientBinder实现:

//packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientService.java
public class HeadsetClientService extends ProfileService {
    private static class BluetoothHeadsetClientBinder extends IBluetoothHeadsetClient.Stub
            implements IProfileServiceBinder {
        private HeadsetClientService mService;
        @Override
        public void dial(BluetoothDevice device, String number,
                AttributionSource source, SynchronousResultReceiver receiver) {
            try {
                HeadsetClientService service = getService(source);
                BluetoothHeadsetClientCall defaultValue = null;
                if (service != null) {
                    HfpClientCall call = service.dial(device, number);
                    defaultValue = toLegacyCall(call);
                }
                receiver.send(defaultValue);
            } catch (RuntimeException e) {
                receiver.propagateException(e);
            }
        }
    }
}

调用HeadsetClientService的dial方法:

//packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientService.java
public class HeadsetClientService extends ProfileService {
    public HfpClientCall dial(BluetoothDevice device, String number) {
        HeadsetClientStateMachine sm = getStateMachine(device);
        if (sm == null) {
            Log.e(TAG, "SM does not exist for device " + device);
            return null;
        }


        int connectionState = sm.getConnectionState(device);
        if (connectionState != BluetoothProfile.STATE_CONNECTED
                && connectionState != BluetoothProfile.STATE_CONNECTING) { //连接状态如果不是STATE_CONNECTED或STATE_CONNECTING直接返回null
            return null;
        }


        HfpClientCall call = new HfpClientCall(device,
                HeadsetClientStateMachine.HF_ORIGINATED_CALL_ID,
                HfpClientCall.CALL_STATE_DIALING, number, false  /* multiparty */,
                true  /* outgoing */, sm.getInBandRing()); //创建HfpClientCall对象
        Message msg = sm.obtainMessage(HeadsetClientStateMachine.DIAL_NUMBER);
        msg.obj = call;
        sm.sendMessage(msg);
        return call;
    }
}

上面方法主要处理如下:

1、创建HfpClientCall对象,HfpClientCall是一个电话实体类信息。该类包含了电话的各种信息,例如电话号码、呼叫状态、通话时间等等。

2、发送DIAL_NUMBER消息到HeadsetClientStateMachine状态机

下面分别进行分析:

HfpClientCall

如下为HfpClientCall的构造方法:

//packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/connserv/HfpClientCall.java
public final class HfpClientCall implements Parcelable {
    public HfpClientCall(BluetoothDevice device, int id, int state, String number,
            boolean multiParty, boolean outgoing, boolean inBandRing) {
        this(device, id, UUID.randomUUID(), state, number, multiParty, outgoing, inBandRing);
    }


    private HfpClientCall(BluetoothDevice device, int id, UUID uuid, int state,
            String number, boolean multiParty, boolean outgoing, boolean inBandRing) {
        mDevice = device;
        mId = id;
        mUUID = uuid;
        mState = state;
        mNumber = number != null ? number : "";
        mMultiParty = multiParty;
        mOutgoing = outgoing;
        mInBandRing = inBandRing;
        mCreationElapsedMilli = SystemClock.elapsedRealtime();
    }
}

HeadsetClientStateMachine Connected DIAL_NUMBER

发送DIAL_NUMBER消息到HeadsetClientStateMachine状态机,发送的消息会在HeadsetClientStateMachine内部类Connected的processMessage中处理:

//packages/modules/Bluetooth/android/app/srv/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java
public class HeadsetClientStateMachine extends StateMachine {
    private final NativeInterface mNativeInterface;
    class Connected extends State {
        public synchronized boolean processMessage(Message message) {
            switch (message.what) {
                case DIAL_NUMBER:
                    // Add the call as an outgoing call.
                    HfpClientCall c = (HfpClientCall) message.obj;
                    mCalls.put(HF_ORIGINATED_CALL_ID, c);


                    if (mNativeInterface.dial(mCurrentDevice, c.getNumber())) {
                        addQueuedAction(DIAL_NUMBER, c.getNumber());
                        // Start looping on calling current calls.
                        sendMessage(QUERY_CURRENT_CALLS);
                    } else {
                        Log.e(TAG,
                                "ERROR: Cannot dial with a given number:" + c.toString());
                        // Set the call to terminated remove.
                        c.setState(HfpClientCall.CALL_STATE_TERMINATED);
                        sendCallChangedIntent(c);
                        mCalls.remove(HF_ORIGINATED_CALL_ID);
                    }
                    break;
            }
        }
    }
}

上面方法主要处理如下:

1、调用NativeInterface的dial方法

2、调用addQueuedAction方法,向发送操作队列增加DIAL_NUMBER Action

3、发送QUERY_CURRENT_CALLS消息

下面分别进行分析

NativeInterface dial

调用NativeInterface的dial方法:

//packages/modules/Bluetooth/android/app/srv/com/android/bluetooth/hfpclient/NativeInterface.java
public class NativeInterface {
    public boolean dial(BluetoothDevice device, String number) {
        return dialNative(getByteAddress(device), number);
    }
}

调用dialNative方法,并返回结果,dialNative为Native方法,通过查表得出调用的是方法dialNative:

static bthf_client_interface_t* sBluetoothHfpClientInterface = NULL;
//packages/modules/Bluetooth/android/app/jni/com_android_bluetooth_hfpclient.cpp
static jboolean dialNative(JNIEnv* env, jobject object, jbyteArray address,
                           jstring number_str) {
  std::shared_lock<std::shared_mutex> lock(interface_mutex);
  if (!sBluetoothHfpClientInterface) return JNI_FALSE;


  jbyte* addr = env->GetByteArrayElements(address, NULL);
  if (!addr) {
    jniThrowIOException(env, EINVAL);
    return JNI_FALSE;
  }


  const char* number = nullptr;
  if (number_str != nullptr) {
    number = env->GetStringUTFChars(number_str, nullptr);
  }
  bt_status_t status =
    sBluetoothHfpClientInterface->dial((const RawAddress*)addr,
                                       number == nullptr ? "" : number);


  if (status != BT_STATUS_SUCCESS) {
    ALOGE("Failed to dial, status: %d", status);
  }
  if (number != nullptr) {
    env->ReleaseStringUTFChars(number_str, number);
  }
  env->ReleaseByteArrayElements(address, addr, 0);
  return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
}

调用bthf_client_interface_t的dial函数,bthf_client_interface_t是个结构体,在bt_hf_client.h中定义,在bt_hf_client.cc中实现:

//packages/modules/Bluetooth/system/btif/src/bt_hf_client.cc
static bt_status_t dial(UNUSED_ATTR const RawAddress* bd_addr,
                        const char* number) {
  btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
  if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;


  CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);


  if (number) {
    BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_ATD, 0, 0, number);
  } else {
    BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_BLDN, 0, 0, NULL);
  }
  return BT_STATUS_SUCCESS;
}

调用BTA_HfClientSendAT方法:

//packages/modules/Bluetooth/system/bta/hf_client/bta_hf_client_api.cc
void BTA_HfClientSendAT(uint16_t handle, tBTA_HF_CLIENT_AT_CMD_TYPE at,
                        uint32_t val1, uint32_t val2, const char* str) {
  tBTA_HF_CLIENT_DATA_VAL* p_buf =
      (tBTA_HF_CLIENT_DATA_VAL*)osi_malloc(sizeof(tBTA_HF_CLIENT_DATA_VAL));


  p_buf->hdr.event = BTA_HF_CLIENT_SEND_AT_CMD_EVT;
  p_buf->uint8_val = at;
  p_buf->uint32_val1 = val1;
  p_buf->uint32_val2 = val2;


  if (str) {
    strlcpy(p_buf->str, str, BTA_HF_CLIENT_NUMBER_LEN + 1);
    p_buf->str[BTA_HF_CLIENT_NUMBER_LEN] = '\0';
  } else {
    p_buf->str[0] = '\0';
  }


  p_buf->hdr.layer_specific = handle;


  bta_sys_sendmsg(p_buf);
}

在之后就是蓝牙协议栈相关内容,在这里就不再分析了。

addQueuedAction

调用addQueuedAction方法,向发送操作队列增加DIAL_NUMBER Action:

/packages/modules/Bluetooth/android/app/srv/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java
public class HeadsetClientStateMachine extends StateMachine {
    // queue of send actions (pair action, action_data)
    private Queue<Pair<Integer, O

HeadsetClientStateMachine Connected QUERY_CURRENT_CALLS

发送QUERY_CURRENT_CALLS消息,发送的消息会在HeadsetClientStateMachine内部类Connected的processMessage中处理:

//packages/modules/Bluetooth/android/app/srv/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java
public class HeadsetClientStateMachine extends StateMachine {
    private final NativeInterface mNativeInterface;
    class Connected extends State {
        public synchronized boolean processMessage(Message message) {
            switch (message.what) {
                case QUERY_CURRENT_CALLS: //查询当前通话
                    removeMessages(QUERY_CURRENT_CALLS);
                    // If there are ongoing calls periodically check their status.
                    if (mCalls.size() > 1
                            && mService.getResources().getBoolean(
                            R.bool.hfp_clcc_poll_during_call)) {
                        sendMessageDelayed(QUERY_CURRENT_CALLS,
                                mService.getResources().getInteger(
                                R.integer.hfp_clcc_poll_interval_during_call)); //延迟发送QUERY_CURRENT_CALLS消息,查询当前通话,由此形成loop
                    } else if (mCalls.size() > 0) {
                        sendMessageDelayed(QUERY_CURRENT_CALLS,
                                QUERY_CURRENT_CALLS_WAIT_MILLIS);
                    }
                    queryCallsStart();
                    break;
            }
        }
    }
}

调用queryCallsStart方法:

//packages/modules/Bluetooth/android/app/srv/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java
public class HeadsetClientStateMachine extends StateMachine {
    private final NativeInterface mNativeInterface;
    private boolean queryCallsStart() {
        logD("queryCallsStart");
        clearPendingAction(); //清除Pending的Action
        mNativeInterface.queryCurrentCalls(mCurrentDevice); 
        addQueuedAction(QUERY_CURRENT_CALLS, 0); //添加QUERY_CURRENT_CALLS到Action队列
        return true;
    }
}

NativeInterface queryCurrentCalls

调用NativeInterface的queryCurrentCalls方法,

//packages/modules/Bluetooth/android/app/srv/com/android/bluetooth/hfpclient/NativeInterface.java
public class NativeInterface {
    public boolean queryCurrentCalls(BluetoothDevice device) {
        return queryCurrentCallsNative(getByteAddress(device));
    }
}

调用queryCurrentCallsNative方法,queryCurrentCallsNative是一个Native方法,通过查表得出调用的是方法queryCurrentCallsNative:

static bthf_client_interface_t* sBluetoothHfpClientInterface = NULL;
//packages/modules/Bluetooth/android/app/jni/com_android_bluetooth_hfpclient.cpp
static jboolean queryCurrentCallsNative(JNIEnv* env, jobject object,
                                        jbyteArray address) {
  std::shared_lock<std::shared_mutex> lock(interface_mutex);
  if (!sBluetoothHfpClientInterface) return JNI_FALSE;


  jbyte* addr = env->GetByteArrayElements(address, NULL);
  if (!addr) {
    jniThrowIOException(env, EINVAL);
    return JNI_FALSE;
  }


  bt_status_t status = sBluetoothHfpClientInterface->query_current_calls(
      (const RawAddress*)addr);


  if (status != BT_STATUS_SUCCESS) {
    ALOGE("Failed to query current calls, status: %d", status);
  }
  env->ReleaseByteArrayElements(address, addr, 0);
  return (status == BT_STATUS_SUCCESS) ? JNI_TRUE : JNI_FALSE;
}

调用bthf_client_interface_t的query_current_calls函数,bthf_client_interface_t是个结构体,在bt_hf_client.h中定义,在bt_hf_client.cc中实现:

//packages/modules/Bluetooth/system/btif/src/bt_hf_client.cc
static bt_status_t query_current_calls(UNUSED_ATTR const RawAddress* bd_addr) {
  btif_hf_client_cb_t* cb = btif_hf_client_get_cb_by_bda(*bd_addr);
  if (cb == NULL || !is_connected(cb)) return BT_STATUS_FAIL;


  CHECK_BTHF_CLIENT_SLC_CONNECTED(cb);


  if (cb->peer_feat & BTA_HF_CLIENT_PEER_ECS) {
    BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CLCC, 0, 0, NULL);
    return BT_STATUS_SUCCESS;
  }


  return BT_STATUS_UNSUPPORTED;
}

调用BTA_HfClientSendAT方法:

//packages/modules/Bluetooth/system/bta/hf_client/bta_hf_client_api.cc
void BTA_HfClientSendAT(uint16_t handle, tBTA_HF_CLIENT_AT_CMD_TYPE at,
                        uint32_t val1, uint32_t val2, const char* str) {
  tBTA_HF_CLIENT_DATA_VAL* p_buf =
      (tBTA_HF_CLIENT_DATA_VAL*)osi_malloc(sizeof(tBTA_HF_CLIENT_DATA_VAL));


  p_buf->hdr.event = BTA_HF_CLIENT_SEND_AT_CMD_EVT;
  p_buf->uint8_val = at;
  p_buf->uint32_val1 = val1;
  p_buf->uint32_val2 = val2;


  if (str) {
    strlcpy(p_buf->str, str, BTA_HF_CLIENT_NUMBER_LEN + 1);
    p_buf->str[BTA_HF_CLIENT_NUMBER_LEN] = '\0';
  } else {
    p_buf->str[0] = '\0';
  }


  p_buf->hdr.layer_specific = handle;


  bta_sys_sendmsg(p_buf);
}

在之后就是蓝牙协议栈相关内容,在这里就不再分析了。

  • 18
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值