Android13 BluetoothHeadsetClient acceptCall流程分析

BluetoothHeadsetClient的acceptCall用于接听电话,流程图如下:

代码如下:

//packages/modules/Bluetooth/framework/java/android/bluetooth/BluetoothHeadsetClient.java
public final class BluetoothHeadsetClient implements BluetoothProfile, AutoCloseable {
    public boolean acceptCall(BluetoothDevice device, int flag) {
        if (DBG) log("acceptCall()");
        final IBluetoothHeadsetClient service = getService();
        final boolean defaultValue = false;
        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<Boolean> recv = SynchronousResultReceiver.get();
                service.acceptCall(device, flag, mAttributionSource, recv);
                return recv.awaitResultNoInterrupt(getSyncTimeout()).getValue(defaultValue);
            } catch (RemoteException | TimeoutException e) {
                Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable()));
            }
        }
        return defaultValue;
    }
}

调用IBluetoothHeadsetClient的acceptCall方法,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;
        public void acceptCall(BluetoothDevice device, int flag, AttributionSource source,
                SynchronousResultReceiver receiver) {
            try {
                HeadsetClientService service = getService(source);
                boolean defaultValue = false;
                if (service != null) {
                    defaultValue = service.acceptCall(device, flag);
                }
                receiver.send(defaultValue);
            } catch (RuntimeException e) {
                receiver.propagateException(e);
            }
        }
    }
}

调用HeadsetClientService的acceptCall方法:

//packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientService.java
public class HeadsetClientService extends ProfileService {
    public boolean acceptCall(BluetoothDevice device, int flag) {
        /* Phonecalls from a single device are supported, hang up any calls on the other phone */
        synchronized (mStateMachineMap) {
            for (Map.Entry<BluetoothDevice, HeadsetClientStateMachine> entry : mStateMachineMap
                    .entrySet()) {
                if (entry.getValue() == null || entry.getKey().equals(device)) {
                    continue;
                }
                int connectionState = entry.getValue().getConnectionState(entry.getKey());
                if (DBG) {
                    Log.d(TAG,
                            "Accepting a call on device " + device + ". Possibly disconnecting on "
                                    + entry.getValue());
                }
                if (connectionState == BluetoothProfile.STATE_CONNECTED) {
                    entry.getValue()
                            .obtainMessage(HeadsetClientStateMachine.TERMINATE_CALL)
                            .sendToTarget();
                }
            }
        }
        HeadsetClientStateMachine sm = getStateMachine(device); //取得HeadsetClientStateMachine 对象
        if (sm == null) {
            Log.e(TAG, "SM does not exist for device " + device);
            return false;
        }


        int connectionState = sm.getConnectionState(device); //取得设备状态,如果不适连接状态返回失败
        if (connectionState != BluetoothProfile.STATE_CONNECTED) {
            return false;
        }
        Message msg = sm.obtainMessage(HeadsetClientStateMachine.ACCEPT_CALL);
        msg.arg1 = flag;
        sm.sendMessage(msg); //发送ACCEPT_CALL消息
        return true;
    }
}

发送ACCEPT_CALL消息,发送的消息会在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 ACCEPT_CALL:
                    acceptCall(message.arg1);
                    break;
            }
        }
    }
}

调用acceptCall方法:

//packages/modules/Bluetooth/android/app/srv/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java
public class HeadsetClientStateMachine extends StateMachine {
    private final NativeInterface mNativeInterface;
    private void acceptCall(int flag) {
        int action = -1;


        logD("acceptCall: (" + flag + ")");


        HfpClientCall c = getCall(HfpClientCall.CALL_STATE_INCOMING,
                HfpClientCall.CALL_STATE_WAITING); //获取HfpClientCall 对象
        if (c == null) {
            c = getCall(HfpClientCall.CALL_STATE_HELD_BY_RESPONSE_AND_HOLD,
                    HfpClientCall.CALL_STATE_HELD);


            if (c == null) {
                return;
            }
        }


        logD("Call to accept: " + c);
        switch (c.getState()) { //判断当前状态
            case HfpClientCall.CALL_STATE_INCOMING: //来电
                if (flag != BluetoothHeadsetClient.CALL_ACCEPT_NONE) {
                    return;
                }
                action = HeadsetClientHalConstants.CALL_ACTION_ATA;
                break;
            case HfpClientCall.CALL_STATE_WAITING: //当已有活动呼叫时,等待呼叫状态。
                if (callsInState(HfpClientCall.CALL_STATE_ACTIVE) == 0) {
                    // if no active calls present only plain accept is allowed
                    if (flag != BluetoothHeadsetClient.CALL_ACCEPT_NONE) {
                        return;
                    }
                    action = HeadsetClientHalConstants.CALL_ACTION_CHLD_2;
                    break;
                }


                // if active calls are present then we have the option to either terminate the
                // existing call or hold the existing call. We hold the other call by default.
                if (flag == BluetoothHeadsetClient.CALL_ACCEPT_HOLD
                        || flag == BluetoothHeadsetClient.CALL_ACCEPT_NONE) {
                    logD("Accepting call with accept and hold");
                    action = HeadsetClientHalConstants.CALL_ACTION_CHLD_2;
                } else if (flag == BluetoothHeadsetClient.CALL_ACCEPT_TERMINATE) {
                    logD("Accepting call with accept and reject");
                    action = HeadsetClientHalConstants.CALL_ACTION_CHLD_1;
                } else {
                    Log.e(TAG, "Aceept call with invalid flag: " + flag);
                    return;
                }
                break;
            case HfpClientCall.CALL_STATE_HELD: //呼叫处于保持状态
                if (flag == BluetoothHeadsetClient.CALL_ACCEPT_HOLD) {
                    action = HeadsetClientHalConstants.CALL_ACTION_CHLD_2;
                } else if (flag == BluetoothHeadsetClient.CALL_ACCEPT_TERMINATE) {
                    action = HeadsetClientHalConstants.CALL_ACTION_CHLD_1;
                } else if (getCall(HfpClientCall.CALL_STATE_ACTIVE) != null) {
                    action = HeadsetClientHalConstants.CALL_ACTION_CHLD_3;
                } else if (flag == BluetoothHeadsetClient.CALL_ACCEPT_NONE) {
                    action = HeadsetClientHalConstants.CALL_ACTION_CHLD_2;
                } else {
                    action = HeadsetClientHalConstants.CALL_ACTION_CHLD_2;
                }
                break;
            case HfpClientCall.CALL_STATE_HELD_BY_RESPONSE_AND_HOLD: //已通过响应和保持保持的呼叫
                action = HeadsetClientHalConstants.CALL_ACTION_BTRH_1;
                break;
            case HfpClientCall.CALL_STATE_ALERTING:
            case HfpClientCall.CALL_STATE_ACTIVE:
            case HfpClientCall.CALL_STATE_DIALING:
            default:
                return;
        }


        if (flag == BluetoothHeadsetClient.CALL_ACCEPT_HOLD) {
            // When unholding a call over Bluetooth make sure to route audio.
     //通过蓝牙取消通话时,请确保路由音频。
            routeHfpAudio(true);
        }


        if (mNativeInterface.handleCallAction(mCurrentDevice, action, 0)) { //调用NativeInterface的handleCallAction,处理Call活动
            addQueuedAction(ACCEPT_CALL, action); //将ACCEPT_CALL加入队列
        } else {
            Log.e(TAG, "ERROR: Couldn't accept a call, action:" + action);
        }
    }
}

调用NativeInterface的handleCallAction,处理Call活动:

//packages/modules/Bluetooth/android/app/srv/com/android/bluetooth/hfpclient/NativeInterface.java
public class NativeInterface {
    public boolean handleCallAction(BluetoothDevice device, int action, int index) {
        return handleCallActionNative(getByteAddress(device), action, index);
    }
}

调用handleCallActionNative方法,并返回处理结果,handleCallActionNative是Native方法,通过查表调用的是handleCallActionNative方法:

static bthf_client_interface_t* sBluetoothHfpClientInterface = NULL;
//packages/modules/Bluetooth/android/app/jni/com_android_bluetooth_hfpclient.cpp
static jboolean handleCallActionNative(JNIEnv* env, jobject object,
                                       jbyteArray address, jint action,
                                       jint index) {
  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->handle_call_action(
      (const RawAddress*)addr, (bthf_client_call_action_t)action, (int)index);


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

调用bthf_client_interface_t的handle_call_action函数,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 handle_call_action(const RawAddress* bd_addr,
                                      bthf_client_call_action_t action,
                                      int idx) {
  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);


  switch (action) {
    case BTHF_CLIENT_CALL_ACTION_CHLD_0:
      if (cb->chld_feat & BTA_HF_CLIENT_CHLD_REL) {
        BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CHLD, 0, 0, NULL);
        break;
      }
      return BT_STATUS_UNSUPPORTED;
    case BTHF_CLIENT_CALL_ACTION_CHLD_1:
      // CHLD 1 is mandatory for 3 way calling
      if (cb->peer_feat & BTA_HF_CLIENT_PEER_FEAT_3WAY) {
        BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CHLD, 1, 0, NULL);
        break;
      }
      return BT_STATUS_UNSUPPORTED;
    case BTHF_CLIENT_CALL_ACTION_CHLD_2:
      // CHLD 2 is mandatory for 3 way calling
      if (cb->peer_feat & BTA_HF_CLIENT_PEER_FEAT_3WAY) {
        BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CHLD, 2, 0, NULL);
        break;
      }
      return BT_STATUS_UNSUPPORTED;
    case BTHF_CLIENT_CALL_ACTION_CHLD_3:
      if (cb->chld_feat & BTA_HF_CLIENT_CHLD_MERGE) {
        BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CHLD, 3, 0, NULL);
        break;
      }
      return BT_STATUS_UNSUPPORTED;
    case BTHF_CLIENT_CALL_ACTION_CHLD_4:
      if (cb->chld_feat & BTA_HF_CLIENT_CHLD_MERGE_DETACH) {
        BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CHLD, 4, 0, NULL);
        break;
      }
      return BT_STATUS_UNSUPPORTED;
    case BTHF_CLIENT_CALL_ACTION_CHLD_1x:
      if (cb->peer_feat & BTA_HF_CLIENT_PEER_ECC) {
        if (idx < 1) {
          return BT_STATUS_FAIL;
        }
        BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CHLD, 1, idx, NULL);
        break;
      }
      return BT_STATUS_UNSUPPORTED;
    case BTHF_CLIENT_CALL_ACTION_CHLD_2x:
      if (cb->peer_feat & BTA_HF_CLIENT_PEER_ECC) {
        if (idx < 1) {
          return BT_STATUS_FAIL;
        }
        BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CHLD, 2, idx, NULL);
        break;
      }
      return BT_STATUS_UNSUPPORTED;
    case BTHF_CLIENT_CALL_ACTION_ATA:
      BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_ATA, 0, 0, NULL);
      break;
    case BTHF_CLIENT_CALL_ACTION_CHUP:
      BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_CHUP, 0, 0, NULL);
      break;
    case BTHF_CLIENT_CALL_ACTION_BTRH_0:
      BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_BTRH, 0, 0, NULL);
      break;
    case BTHF_CLIENT_CALL_ACTION_BTRH_1:
      BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_BTRH, 1, 0, NULL);
      break;
    case BTHF_CLIENT_CALL_ACTION_BTRH_2:
      BTA_HfClientSendAT(cb->handle, BTA_HF_CLIENT_AT_CMD_BTRH, 2, 0, NULL);
      break;
    default:
      return BT_STATUS_FAIL;
  }


  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);
}

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值