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);
}
在之后就是蓝牙协议栈相关内容,在这里就不再分析了。