目录
- 概述
- 时序图
- 关键代码
- 关键log
- 总结
一、概述
这里的通话类型指的是语音通话和视频通话,转换包括upgrade/ downgrade升降级,就是语音通话升级为视频通话、视频通话降级为语音通话。升级为视频通话一般就是包括如下图示的4步,MO发起请求,MT接收请求,MT响应请求,MO接收响应。本文主要学习第一步,MO发起请求的流程(upgradeToVideo为例)。
二、时序图
如上为MO发起请求upgradeToVideo的时序图,主要包含从App(Dialer)到最终通过imsRadio发起请求的过程。
下面跟着关键代码进一步理解这一过程。
三、关键代码
代码主要包含如下几个路径,时序图最上面也有标识出。
packages\apps\Dialer
frameworks\base\telecomm
frameworks\opt\net\ims
vendor\qcom\proprietary\commonsys\telephony-apps\ims
- App界面点击
packages/apps/Dialer/java/com/android/incallui/incall/impl/ButtonController.java
class UpgradeToVideoButtonController extends SimpleNonCheckableButtonController {
public UpgradeToVideoButtonController(@NonNull InCallButtonUiDelegate delegate) {
super(
delegate,
InCallButtonIds.BUTTON_UPGRADE_TO_VIDEO,
0,
R.string.incall_label_videocall,
R.drawable.quantum_ic_videocam_white_36);
Assert.isNotNull(delegate);
}
@Override
public void onClick(View view) {
delegate.changeToVideoClicked();
}
}
packages/apps/Dialer/java/com/android/incallui/CallButtonPresenter.java
@Override
public void changeToVideoClicked() {
LogUtil.enterBlock("CallButtonPresenter.changeToVideoClicked");
Logger.get(context)
.logCallImpression(
DialerImpression.Type.VIDEO_CALL_UPGRADE_REQUESTED,
call.getUniqueCallId(),
call.getTimeAddedMs());
call.getVideoTech().upgradeToVideo(context);
}
packages/apps/Dialer/java/com/android/incallui/videotech/ims/ImsVideoTech.java
@Override
public void upgradeToVideo(@NonNull Context context) {
LogUtil.enterBlock("ImsVideoTech.upgradeToVideo");
int unpausedVideoState = getUnpausedVideoState(call.getDetails().getVideoState());
call.getVideoCall()
.sendSessionModifyRequest(
new VideoProfile(unpausedVideoState | VideoProfile.STATE_BIDIRECTIONAL));
setSessionModificationState(SessionModificationState.WAITING_FOR_UPGRADE_TO_VIDEO_RESPONSE);
logger.logImpression(DialerImpression.Type.IMS_VIDEO_UPGRADE_REQUESTED);
}
至sendSessionModifyRequest,Dialer中的点击事件完成,下一步是frameworks中的流程。
- frameworks中的流程
向video provider发送callType修改请求。
frameworks/base/telecom/java/android/telecom/VideoCallImpl.java
public void sendSessionModifyRequest(VideoProfile requestProfile) {
try {
VideoProfile originalProfile = new VideoProfile(mVideoState, mVideoQuality);
mVideoProvider.sendSessionModifyRequest(originalProfile, requestProfile);
} catch (RemoteException e) {
}
}
frameworks/base/telecomm/java/android/telecom/Connection.java
VideoProviderBinder
/**
* IVideoProvider stub implementation.
*/
private final class VideoProviderBinder extends IVideoProvider.Stub {
public void sendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = fromProfile;
args.arg2 = toProfile;
mMessageHandler.obtainMessage(MSG_SEND_SESSION_MODIFY_REQUEST, args).sendToTarget();
}
}
VideoProviderHandler
case MSG_SEND_SESSION_MODIFY_REQUEST: {
SomeArgs args = (SomeArgs) msg.obj;
try {
onSendSessionModifyRequest((VideoProfile) args.arg1, (VideoProfile) args.arg2);
} finally {
args.recycle();
}
break;
}
public abstract void onSendSessionModifyRequest(VideoProfile fromProfile,
VideoProfile toProfile);
frameworks/opt/net/ims/src/java/com/android/ims/internal/ImsVideoCallProviderWrapper.java
重写 Connection.java中的onSendSessionModifyRequest方法。
/** @inheritDoc */
public void onSendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile) {
try {
……
mVideoCallProvider.sendSessionModifyRequest(fromProfile, toProfile);
} catch (RemoteException e) {
}
}
frameworks/opt/net/ims/src/java/com/android/ims/internal/ImsVideoCallProvider.java
public void sendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = fromProfile;
args.arg2 = toProfile;
mProviderHandler.obtainMessage(MSG_SEND_SESSION_MODIFY_REQUEST, args).sendToTarget();
}
mProviderHandler
case MSG_SEND_SESSION_MODIFY_REQUEST: {
SomeArgs args = (SomeArgs) msg.obj;
try {
VideoProfile fromProfile = (VideoProfile) args.arg1;
VideoProfile toProfile = (VideoProfile) args.arg2;
onSendSessionModifyRequest(fromProfile, toProfile);
} finally {
args.recycle();
}
break;
}
/** @see Connection.VideoProvider#onSendSessionModifyRequest */
public abstract void onSendSessionModifyRequest(VideoProfile fromProfile,
VideoProfile toProfile);
frameworks中的处理完成,下一步到高通私有类中接着处理
3、高通私有类中的流程
vendor/qcom/proprietary/commonsys/telephony-apps/ims/src/com/qualcomm/ims/
vt/ImsVideoCallProviderImpl.java
重写 onSendSessionModifyRequest方法
@Override
public void onSendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile) {
......
// Neither pause or resume, so this is upgrade/downgrade request
Message newMsg = mHandler.obtainMessage(EVENT_SEND_SESSION_MODIFY_REQUEST_DONE);
int callType = ImsCallUtils.convertVideoStateToCallType(toProfile.getVideoState());
mImsCallModification.changeConnectionType(newMsg, callType, null);
}
到这可以看到,从传过来的VideoProfile中获取了需要转换的callType。
Vendor/qcom/proprietary/commonsys/telephony-apps/ims/src/org/codeaurora/ims/ ImsCallModification.java
// MODIFY_CALL_INITIATE
public void changeConnectionType(Message msg, int newCallType, Map<String, String> newExtras){
......
modifyCallInitiate(newMsg, newCallType, newExtras);
......
}
private void modifyCallInitiate(Message newMsg, int newCallType, Map<String, String> newExtras){
......
CallDetails callDetails = new CallDetails(newCallType, mImsCallSessionImpl.getCallDomain(),
CallDetails.getExtrasFromMap(newExtras));
ImsCallProfile callProfile = mImsCallSessionImpl.getCallProfile();
if (callProfile != null) {
callDetails.setRttMode(callProfile.mMediaProfile.mRttMode);
}
CallModify callModify = new CallModify(callDetails, mIndex);
mCi.modifyCallInitiate(newMsg, callModify);
}
将newCallType转换为callModify传入。
Vendor/qcom/proprietary/commonsys/telephony-apps/ims/src/org/codeaurora/
ims/ImsSenderRxr.java
public void modifyCallInitiate(Message result, CallModify callModify) {
......
try {
logSolicitedRequest(rr);
imsRadioV10().modifyCallInitiate(rr.mSerial,
ImsRadioUtils.buildCallModifyInfo(callModify));
} catch (Exception ex) {
removeFromQueueAndSendResponse(rr.mSerial);
Log.e(this, msgIdString + "request to IImsRadio: Exception: " + ex);
}
}
最后通过imsRadio将callModify发送出去
四、关键log
//upgrade
03-01 00:12:58.120 4918 4918 D VideoCall_ImsVideoCallProviderImpl: (1) onSendSessionModifyRequest, videoState=3 quality= 4
03-01 00:12:58.120 4918 4918 D VideoCall_ImsCallModification: validateOutgoingModifyConnectionType newCallType=3//CalllType 和videoState对应
03-01 00:12:58.120 4918 4918 D VideoCall_ImsCallModification: validateOutgoingModifyConnectionType modifyToCurrCallType = false isIndexValid = true isLowBattery = false
03-01 00:12:58.120 4918 4918 V ImsSenderRxr: modifyCallInitiate callModify= 1 3 2 callSubState 0 videoPauseState2 mediaId-1 Local Ability Peer Ability Cause code 0 0[SUB1]
03-01 00:12:58.120 4918 4918 V ImsSenderRxr: setCallModify callModify= 1 3 2 callSubState 0 videoPauseState2 mediaId-1 Local Ability Peer Ability Cause code 0 0[SUB1]
03-01 00:12:58.120 4918 4918 D ImsSenderRxr: [0044]> MODIFY_CALL_INITIATE[SUB1]
03-01 00:13:02.989 4918 5512 D ImsSenderRxr: [0044]< MODIFY_CALL_INITIATE [SUB1]
03-01 00:13:02.989 4918 4918 D VideoCall_ImsCallModification: EVENT_MODIFY_CALL_INITIATE_DONE received
03-01 00:13:02.989 4918 4918 D VideoCall_ImsCallModification: clearPendingModify imsconn=org.codeaurora.ims.ImsCallModification@1ea212
03-01 00:13:02.990 4918 4918 D VideoCall_ImsVideoCallProviderImpl: (1) handleSessionModifyDone msg.what=0
03-01 00:13:02.990 4918 4918 D VideoCall_ImsVideoCallProviderImpl: (1) Session modify success
五、总结
在实际开发中,无论是需求还是解bug,重点需要关注的是Dialer App中和framework中的流程,Vendor中的高通私有类的流程了解即可,一般不会修改到,对关键log信息要熟悉,便于对此类问题的分析。