IMS Modify Call (2) receive request 收到视频升级请求
主要内容为MT收到视频升级的请求的过程,也是MT消息上传的过程。流程图,关键代码,关键log。
·
主要内容为MT收到视频升级的请求的过程,也是MT消息上传的过程。
流程图
可以看到信息上报跨了4个模块,没有经过service/Telecom
看关键log方便跟踪
06-19 19:05:41.437 3329-4362/com.android.phone V/ImsSenderRxr: Read packet: 24 bytes06-19 19:05:41.437 3329-4362/com.android.phone V/ImsSenderRxr: processResponse[SUB1]06-19 19:05:41.437 3329-4362/com.android.phone D/ImsSenderRxr: Response data: [12, 13, -1, -1, -1, -1, 16, 3, 24, -49, 1, 32, 0, 21, 1, 0, 0, 0, 26, 4, 8, 3, 16, 2][SUB1]06-19 19:05:41.437 3329-4362/com.android.phone D/ImsSenderRxr: Tag -1 3 207 0[SUB1]06-19 19:05:41.437 3329-4362/com.android.phone D/ImsSenderRxr: responseModifyCall 1 3 2 callSubState 0 videoPauseState2 mediaId-1 Local Ability Peer Ability Cause code 0 0[SUB1]06-19 19:05:41.438 3329-4362/com.android.phone D/ImsSenderRxr: [UNSL]< UNSOL_MODIFY_CALL 1 3 2 callSubState 0 videoPauseState2 mediaId-1 Local Ability Peer Ability Cause code 0 0[SUB1]06-19 19:05:41.438 3329-3329/com.android.phone D/ImsServiceSub: Message received: what = 1306-19 19:05:41.438 3329-3329/com.android.phone D/ImsServiceSub: handleCallModifyRequest( 1 3 2 callSubState 0 videoPauseState2 mediaId-1 Local Ability Peer Ability Cause code 0 0)06-19 19:05:41.438 3329-3329/com.android.phone D/VideoCall_ImsCallModification: onReceivedCallModify( 1 3 2 callSubState 0 videoPauseState2 mediaId-1 Local Ability Peer Ability Cause code 0 0)06-19 19:05:41.438 3329-3329/com.android.phone D/VideoCall_ImsCallModification: validateIncomingModifyConnectionType newCallType = 306-19 19:05:41.438 3329-3329/com.android.phone D/VideoCall_ImsCallModification: validateIncomingModifyConnectionType modifyToCurrCallType = false isIndexValid = true isLowBattery = false06-19 19:05:41.439 3329-3329/com.android.phone D/VideoCall_ImsVideoCallProviderImpl: (1) onCallTypeChanged session= callid= 1 mediaId=5
代码段
vendor/qcom/proprietary/telephony-apps/ims
高通私有代码,略。
frameworks/opt/net/ims
android/frameworks/opt/net/ims/src/java/com/android/ims/internal/ImsVideoCallProvider.java
看到方法名带receive request字样,直译就是收到请求,在响应之后方法名中就会换上类似response。
/** @see Connection.VideoProvider#receiveSessionModifyRequest */public void receiveSessionModifyRequest(VideoProfile VideoProfile) {if (mCallback != null) {try {mCallback.receiveSessionModifyRequest(VideoProfile);} catch (RemoteException ignored) {}}}
android/frameworks/opt/net/ims/src/java/com/android/ims/internal/ImsVideoCallProviderWrapper.java
/*** IImsVideoCallCallback stub implementation.*/private final class ImsVideoCallCallback extends IImsVideoCallCallback.Stub {@Overridepublic void receiveSessionModifyRequest(VideoProfile VideoProfile) {mHandler.obtainMessage(MSG_RECEIVE_SESSION_MODIFY_REQUEST,VideoProfile).sendToTarget();}
/** Default handler used to consolidate binder method calls onto a single thread. */private final Handler mHandler = new Handler(Looper.getMainLooper()) {@Overridepublic void handleMessage(Message msg) {SomeArgs args;switch (msg.what) {case MSG_RECEIVE_SESSION_MODIFY_REQUEST:receiveSessionModifyRequest((VideoProfile) msg.obj);break;
frameworks/base/telecomm
android/frameworks/base/telecomm/java/android/telecom/Connection.java
/*** Used to inform listening {@link InCallService} implementations when the* {@link VideoProvider} receives a session modification request.* <p>* Received by the {@link InCallService} via* {@link InCallService.VideoCall.Callback#onSessionModifyRequestReceived(VideoProfile)},** @param videoProfile The requested video profile.* @see #onSendSessionModifyRequest(VideoProfile, VideoProfile)*/public void receiveSessionModifyRequest(VideoProfile videoProfile) {if (mVideoCallbacks != null) {for (IVideoCallback callback : mVideoCallbacks.values()) {try {callback.receiveSessionModifyRequest(videoProfile);//多处调用} catch (RemoteException ignored) {Log.w(this, "receiveSessionModifyRequest callback failed", ignored);}}}}
android/frameworks/base/telecomm/java/android/telecom/VideoCallImpl.java
/*** IVideoCallback stub implementation.*/private final class VideoCallListenerBinder extends IVideoCallback.Stub {@Overridepublic void receiveSessionModifyRequest(VideoProfile videoProfile) {if (mHandler == null) {return;}mHandler.obtainMessage(MessageHandler.MSG_RECEIVE_SESSION_MODIFY_REQUEST,videoProfile).sendToTarget();}
handleMessage
@Overridepublic void handleMessage(Message msg) {if (mCallback == null) {return;}SomeArgs args;switch (msg.what) {case MSG_RECEIVE_SESSION_MODIFY_REQUEST:mCallback.onSessionModifyRequestReceived((VideoProfile) msg.obj);break;
前面几乎都没什么说的,走一条线就是了,然后经InCallService接口回调到InCallUI
packages/apps/InCallUI
一般客户有需求,要修改界面的话也都是该InCallUI,下层的流程是不动的,因此下面一部分比较重要
android/packages/apps/InCallUI/src/com/android/incallui/InCallVideoCallCallback.java
目前为止传想来的消息都只是MODIFY CALL,并没有携带说是升级还是降级,从下面的方法中可以看到有分开两种情况了。
/*** Handles an incoming session modification request.** @param videoProfile The requested video call profile.*/@Overridepublic void onSessionModifyRequestReceived(VideoProfile videoProfile) {Log.d(this, " onSessionModifyRequestReceived videoProfile=" + videoProfile);int previousVideoState = CallUtils.getUnPausedVideoState(mCall.getVideoState());int newVideoState = CallUtils.getUnPausedVideoState(videoProfile.getVideoState());InCallPresenter.getInstance().wakeUpScreen();boolean wasVideoCall = CallUtils.isVideoCall(previousVideoState);boolean isVideoCall = CallUtils.isVideoCall(newVideoState);// Check for upgrades to video and downgrades to audio.if (wasVideoCall && !isVideoCall) {InCallVideoCallCallbackNotifier.getInstance().downgradeToAudio(mCall);} else if (previousVideoState != newVideoState) {InCallVideoCallCallbackNotifier.getInstance().upgradeToVideoRequest(mCall,newVideoState);}}
downgradeToAudio()方法在后面会调用到VideoCallPresenter.java的onDowngradeToAudio()方法,进而调用exitVideoMode()退出视频模式。
upgradeToVideoRequest()升级视频的请求
/*** Inform listeners of an upgrade to video request for a call.* @param call The call.* @param videoState The video state we want to upgrade to.*/public void upgradeToVideoRequest(Call call, int videoState) {Log.d(this, "upgradeToVideoRequest call = " + call + " new video state = " + videoState);for (SessionModificationListener listener : mSessionModificationListeners) {listener.onUpgradeToVideoRequest(call, videoState);}}
InCallPresenter
@Overridepublic void onUpgradeToVideoRequest(Call call, int videoState) {Log.d(this, "onUpgradeToVideoRequest call = " + call + " video state = " + videoState);if (call == null) {return;}call.setSessionModificationTo(videoState);}
android/packages/apps/InCallUI/src/com/android/incallui/Call.java
/*** This method is called when we request for a video upgrade or downgrade. This handles the* session modification state RECEIVED_UPGRADE_TO_VIDEO_REQUEST and sets the video state we* want to upgrade/downgrade to.*/public void setSessionModificationTo(int videoState) {Log.d(this, "setSessionModificationTo - video state= " + videoState);if (videoState == getVideoState()) {mSessionModificationState = Call.SessionModificationState.NO_REQUEST;Log.w(this,"setSessionModificationTo - Clearing session modification state");} else {mSessionModificationState =Call.SessionModificationState.RECEIVED_UPGRADE_TO_VIDEO_REQUEST;setModifyToVideoState(videoState);CallList.getInstance().onUpgradeToVideo(this);}Log.d(this, "setSessionModificationTo - mSessionModificationState="+ mSessionModificationState + " video state= " + videoState);update();}
android/packages/apps/InCallUI/src/com/android/incallui/CallList.java
public void onUpgradeToVideo(Call call){Log.d(this, "onUpgradeToVideo call=" + call);for (Listener listener : mListeners) {listener.onUpgradeToVideo(call);}}
看前面的注释
这是modify call的唯一调用的方法,等下我们看下降级的
* Called when a new modify call request comes in* This is the only method that gets called for modify requests.*/public void onUpgradeToVideo(Call call);
android/packages/apps/InCallUI/src/com/android/incallui/AnswerPresenter.java
界面显示,(在5.1上我们自己做过升级声音提示,在6.0上高通加了一个类实现这个功能,不知道AOSP上有没有那个提示音的功能)
@Overridepublic void onUpgradeToVideo(Call call) {Log.d(this, "onUpgradeToVideo: " + this + " call=" + call);showAnswerUi(true);//一次boolean isUpgradePending = isVideoUpgradePending(call);InCallPresenter inCallPresenter = InCallPresenter.getInstance();if (isUpgradePending&& inCallPresenter.getInCallState() == InCallPresenter.InCallState.INCOMING) {Log.d(this, "declining upgrade request");//If there is incoming call reject upgrade requestinCallPresenter.declineUpgradeRequest(getUi().getContext());} else if (isUpgradePending) {Log.d(this, "process upgrade request as no MT call");processVideoUpgradeRequestCall(call);}}
private void processVideoUpgradeRequestCall(Call call) {Log.d(this, " processVideoUpgradeRequestCall call=" + call);int subId = call.getSubId();int phoneId = mCalls.getPhoneId(subId);mCallId[phoneId] = call.getId();mCall[phoneId] = call;// Listen for call updates for the current call.CallList.getInstance().addCallUpdateListener(mCallId[phoneId], this);final int currentVideoState = call.getVideoState();final int modifyToVideoState = call.getModifyToVideoState();if (currentVideoState == modifyToVideoState) {Log.w(this, "processVideoUpgradeRequestCall: Video states are same. Return.");return;}AnswerUi ui = getUi();if (ui == null) {Log.e(this, "Ui is null. Can't process upgrade request");return;}showAnswerUi(true);//2次ui.showTargets(QtiCallUtils.getSessionModificationOptions(getUi().getContext(),currentVideoState, modifyToVideoState));}
QtiCallUtils.java
根据实际情况,在界面AnswerFragment上显示不同选择。
/*** Returns the session modification user options based on session modify request video states* (current video state and modify request video state)*/public static int getSessionModificationOptions(Context context, int currentVideoState,int modifyToVideoState) {if (!useExt(context)) {return AnswerFragment.TARGET_SET_FOR_VIDEO_ACCEPT_REJECT_REQUEST;}if (showVideoUpgradeOptions(currentVideoState, modifyToVideoState)) {return AnswerFragment.TARGET_SET_FOR_QTI_VIDEO_ACCEPT_REJECT_REQUEST;} else if (isEnabled(VideoProfile.STATE_BIDIRECTIONAL, modifyToVideoState)) {return AnswerFragment.TARGET_SET_FOR_QTI_BIDIRECTIONAL_VIDEO_ACCEPT_REJECT_REQUEST;} else if (isEnabled(VideoProfile.STATE_TX_ENABLED, modifyToVideoState)) {return AnswerFragment.TARGET_SET_FOR_QTI_VIDEO_TRANSMIT_ACCEPT_REJECT_REQUEST;} else if (isEnabled(VideoProfile.STATE_RX_ENABLED, modifyToVideoState)) {return AnswerFragment.TARGET_SET_FOR_QTI_VIDEO_RECEIVE_ACCEPT_REJECT_REQUEST;}return AnswerFragment.TARGET_SET_FOR_QTI_VIDEO_ACCEPT_REJECT_REQUEST;}
在我们的代码中,这个返回值后面被修改了,会根据运营商返回不同的值,
/*** Checks the boolean flag in config file to figure out if we are going to use Qti extension or* not*/public static boolean useExt(Context context) {if (context == null) {Log.w(context, "Context is null...");}return isConfigEnabled(context, R.bool.video_call_use_ext);//这个布尔值默认为true,但是针对mnc为405的都重写成了false}
AnswerFragment.java
显示到界面上
/*** Sets targets on the glowpad according to target set identified by the parameter.* @param targetSet Integer identifying the set of targets to use.*/public void showTargets(int targetSet) {showTargets(targetSet, VideoProfile.STATE_BIDIRECTIONAL);}/*** Sets targets on the glowpad according to target set identified by the parameter.* @param targetSet Integer identifying the set of targets to use.*/@Overridepublic void showTargets(int targetSet, int videoState) {final int targetResourceId;final int targetDescriptionsResourceId;final int directionDescriptionsResourceId;final int handleDrawableResourceId;mGlowpad.setVideoState(videoState);final boolean isEnhanceUIEnabled = getContext().getResources().getBoolean(R.bool.config_enable_enhance_video_call_ui);switch (targetSet) {...case TARGET_SET_FOR_VIDEO_ACCEPT_REJECT_REQUEST:targetResourceId =R.array.incoming_call_widget_video_request_targets;targetDescriptionsResourceId =R.array.incoming_call_widget_video_request_target_descriptions;directionDescriptionsResourceId = R.array.incoming_call_widget_video_request_target_direction_descriptions;handleDrawableResourceId = R.drawable.ic_incall_video_handle;break;
log
06-19 19:05:41.622 14182-14182/com.android.dialer I/InCall: StatusBarNotifier - Will show "dismiss upgrade" action in the incoming call Notification06-19 19:05:41.624 14182-14182/com.android.dialer I/InCall: StatusBarNotifier - Will show "accept upgrade" action in the incoming call Notification
关键log
MT receive
收到视频升级请求
//receive06-19 19:05:41.437 3329-4362/com.android.phone V/ImsSenderRxr: Read packet: 24 bytes06-19 19:05:41.437 3329-4362/com.android.phone V/ImsSenderRxr: processResponse[SUB1]06-19 19:05:41.437 3329-4362/com.android.phone D/ImsSenderRxr: Response data: [12, 13, -1, -1, -1, -1, 16, 3, 24, -49, 1, 32, 0, 21, 1, 0, 0, 0, 26, 4, 8, 3, 16, 2][SUB1]06-19 19:05:41.437 3329-4362/com.android.phone D/ImsSenderRxr: Tag -1 3 207 0[SUB1]06-19 19:05:41.437 3329-4362/com.android.phone D/ImsSenderRxr: responseModifyCall 1 3 2 callSubState 0 videoPauseState2 mediaId-1 Local Ability Peer Ability Cause code 0 0[SUB1]06-19 19:05:41.438 3329-4362/com.android.phone D/ImsSenderRxr: [UNSL]< UNSOL_MODIFY_CALL 1 3 2 callSubState 0 videoPauseState2 mediaId-1 Local Ability Peer Ability Cause code 0 0[SUB1]
MO send request, accepted, rejected, time out
MT接受升级请求后MO的log
//accepted response06-25 21:37:21.793 3289-4294/com.android.phone V/ImsSenderRxr: Read packet: 12 bytes06-25 21:37:21.793 3289-4294/com.android.phone V/ImsSenderRxr: processResponse[SUB1]06-25 21:37:21.793 3289-4294/com.android.phone D/ImsSenderRxr: Response data: [11, 13, 110, 0, 0, 0, 16, 2, 24, 17, 32, 0][SUB1]06-25 21:37:21.793 3289-4294/com.android.phone D/ImsSenderRxr: Tag 110 2 17 0[SUB1]06-25 21:37:21.793 3289-4294/com.android.phone D/ImsSenderRxr: [0110]< MODIFY_CALL_INITIATE [SUB1]06-25 21:37:21.793 3289-3289/com.android.phone D/VideoCall_ImsCallModification: EVENT_MODIFY_CALL_INITIATE_DONE received
升级请求被拒绝和超时,可以看到两者的log是一样的
//send request06-21 16:00:12.167 13623-13623/com.android.phone D/ImsSenderRxr: [0021]> MODIFY_CALL_INITIATE[SUB0]//reject06-21 16:00:19.129 13623-14690/com.android.phone D/ImsSenderRxr: [0021]< MODIFY_CALL_INITIATE error: 2806-21 16:00:19.129 13623-13623/com.android.phone D/VideoCall_ImsCallModification: EVENT_MODIFY_CALL_INITIATE_DONE received//send request07-17 10:00:11.655 2915-2915/com.android.phone D/ImsSenderRxr: [0028]> MODIFY_CALL_INITIATE[SUB1]//time out07-17 10:00:27.733 2915-4049/com.android.phone D/ImsSenderRxr: [0028]< MODIFY_CALL_INITIATE error: 28 07-17 10:00:27.733 2915-2915/com.android.phone D/VideoCall_ImsCallModification: EVENT_MODIFY_CALL_INITIATE_DONE received07-17 10:00:27.748 13872-13872/com.android.dialer D/InCall: InCallVideoCallCallback - onSessionModifyResponseReceived status=5 requestedProfile=[VideoProfile videoState = Audio Tx Rx
MT不做任何处理的话15秒后(运营商决定)MO收到运营商发来的响应消息,其中包括InCallVideoCallCallback - onSessionModifyResponseReceived status=5,这个5的定义为VideoProvider.SESSION_MODIFY_REQUEST_REJECTED_BY_REMOTE(5)意为被远端拒绝了可见对于MO来说超时和reject是一样的,而在MT收到的则是VideoProvider.SESSION_MODIFY_REQUEST_TIMED_OUT(4),所以在MT方 reject和time out是区分的。
然后这个error: 28的定义在imsIF.proto中查到,也证明了timeout和reject的。
E_REJECTED_BY_REMOTE = 28; /* Remote end rejected a change started byREQUEST_MODIFY_CALL_INITIATE */
小结
整个流程中的log不多,主要是底层ImsSenderRxr.java中的log多些,UNSOL_MODIFY_CALL (未处理的新消息),MODIFY_CALL_CONFIRM(MT界面应答),MODIFY_CALL_INITIATE(MO发起),然后InCall中在一些场景中有些log,AnswerPresenter和CallCardPresenter的log。
如果出问题的话也基本上在从底层和上层判断,中间应该不会有什么问题,底层看消息首发,上层看信息显示。Modify Call已经包括upgrade和downgrade,流程整体也是一样,在需要区分的时候会通过callType(CallMofidy)来区分。
更多推荐


所有评论(0)