IMS Modify Call send request 发出升级视频请求
2016-08-23 19:25
393 查看
upgrade/downgrade 升降级,其实就是ModifyCall
界面入手
CallButtonFragment.java onClick()
packages/apps/InCallUI/src/com/android/incallui/CallButtonPresenter.java
changeToVideoClicked()
本来还有一个changeToVoiceClick()的,不过没有使用。
packages/apps/InCallUI/src/com/android/incallui/QtiCallUtils.java
QtiCallUtils.java
displayModifyCallOptions() 显示选项(早先是在overflow menu中有个modify call选项,点击后弹出4个选项供选择)
关于 R.bool.config_enable_enhance_video_call_ui 这个值,如果为true的话,modify的几个选项会会直接在CalButton上上显示,(通常是在overFlow menu里)。ehhance UI嘛,就是直接在UI上把那些发送,接收,双向的button或者选项列出来。
changeToVideoClicked()
这个方法同时也被 downgradeToVoiceCall()调用了。可见这部分不能光看方法名字理解它的作用了。
frameworks/base/telecomm/java/android/telecom/Connection.java
VideoProviderBinder
VideoProviderHandler
frameworks/base/telecomm/java/android/telecom/Connection.java
重写
frameworks/opt/net/ims/src/java/com/android/ims/internal/ImsVideoCallProvider.java
mProviderHandler
高通私有代码,不贴了,一般也不会改下层的。
关键词:android request 视频通话 upgrade public
流程图
界面入手
packages/apps/InCallUI
packages/apps/InCallUI/src/com/android/incallui/CallButtonFragment.JavaCallButtonFragment.java onClick()
case R.id.changeToVideoButton: if (call == null) { Log.i(this, "Call was null"); return; } if (getResources().getBoolean(R.bool.config_regional_number_patterns_video_call) && //默认为false !CallUtil.isVideoCallNumValid(call.getNumber())) { Toast.makeText(this.getActivity(), R.string.toast_change_video_call_failed, Toast.LENGTH_LONG).show(); return; } getPresenter().changeToVideoClicked();//切换为视频通话,实际是ModifyCall 后面可以看到调用 break;
packages/apps/InCallUI/src/com/android/incallui/CallButtonPresenter.java
changeToVideoClicked()
本来还有一个changeToVoiceClick()的,不过没有使用。
public void changeToVideoClicked() { final Context context = getUi().getContext(); if (QtiCallUtils.useExt(context)) {//为true,可以看下面的代码断 QtiCallUtils.displayModifyCallOptions(mCall, context);//这里 return; } VideoCall videoCall = mCall.getVideoCall(); if (videoCall == null) { return; } int currVideoState = mCall.getVideoState(); int currUnpausedVideoState = CallUtils.getUnPausedVideoState(currVideoState); currUnpausedVideoState |= VideoProfile.STATE_BIDIRECTIONAL; VideoProfile videoProfile = new VideoProfile(currUnpausedVideoState); videoCall.sendSessionModifyRequest(videoProfile); mCall.setSessionModificationState(Call.SessionModificationState.WAITING_FOR_RESPONSE); }
packages/apps/InCallUI/src/com/android/incallui/QtiCallUtils.java
QtiCallUtils.java
/** * 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 context != null && context.getResources().getBoolean(R.bool.video_call_use_ext); //默认为true }
displayModifyCallOptions() 显示选项(早先是在overflow menu中有个modify call选项,点击后弹出4个选项供选择)
/** * The function is called when Modify Call button gets pressed. The function creates and * displays modify call options. */ public static void displayModifyCallOptions(final Call call, final Context context) { if (call == null) { Log.d(LOG_TAG, "Can't display modify call options. Call is null"); return; } if (isTtyEnabled(context)) { Log.w(LOG_TAG, "Call session modification is allowed only when TTY is off."); displayToast(context, R.string.video_call_not_allowed_if_tty_enabled); return; } if (context.getResources().getBoolean( R.bool.config_enable_enhance_video_call_ui)) { //false,后面可能会改。 // selCallType is set to -1 default, if the value is not updated, it is unexpected. if (selectType != -1) { VideoProfile videoProfile = new VideoProfile(selectType); Log.v(LOG_TAG, "Videocall: Enhance videocall: upgrade/downgrade to " + callTypeToString(selectType)); changeToVideoClicked(call, videoProfile); } return; } final ArrayList<CharSequence> items = new ArrayList<CharSequence>(); final ArrayList<Integer> itemToCallType = new ArrayList<Integer>(); final Resources res = context.getResources(); // Prepare the string array and mapping.//开始准备modify call的dialog if (hasVoiceCapabilities(call)) { items.add(res.getText(R.string.modify_call_option_voice)); itemToCallType.add(VideoProfile.STATE_AUDIO_ONLY);//仅语音 } if (hasBidirectionalVideoCapabilities(call)) { items.add(res.getText(R.string.modify_call_option_vt_rx)); itemToCallType.add(VideoProfile.STATE_RX_ENABLED);//接收视频,也就是只显示对面的视频 items.add(res.getText(R.string.modify_call_option_vt_tx)); itemToCallType.add(VideoProfile.STATE_TX_ENABLED);//发送。只发送不接收 items.add(res.getText(R.string.modify_call_option_vt)); itemToCallType.add(VideoProfile.STATE_BIDIRECTIONAL);//双向,双方视频互相传送。这里客户可能会希望把单向的去掉 } AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(R.string.modify_call_option_title); final AlertDialog alert; Dialoginterface.OnClickListener listener = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int item) { Toast.makeText(context, items.get(item), Toast.LENGTH_SHORT).show(); final int selCallType = itemToCallType.get(item); Log.v(this, "Videocall: ModifyCall: upgrade/downgrade to " + callTypeToString(selCallType)); VideoProfile videoProfile = new VideoProfile(selCallType); changeToVideoClicked(call, videoProfile);//在弹出的窗口上点击以后 dialog.dismiss(); } }; final int currUnpausedVideoState = CallUtils.getUnPausedVideoState(call.getVideoState()); final int index = itemToCallType.indexOf(currUnpausedVideoState); builder.setSingleChoiceItems(items.toArray(new CharSequence[0]), index, listener); alert = builder.create(); alert.show(); }
关于 R.bool.config_enable_enhance_video_call_ui 这个值,如果为true的话,modify的几个选项会会直接在CalButton上上显示,(通常是在overFlow menu里)。ehhance UI嘛,就是直接在UI上把那些发送,接收,双向的button或者选项列出来。
changeToVideoClicked()
这个方法同时也被 downgradeToVoiceCall()调用了。可见这部分不能光看方法名字理解它的作用了。
/** * Sends a session modify request to the telephony framework */ private static void changeToVideoClicked(Call call, VideoProfile videoProfile) { VideoCall videoCall = call.getVideoCall();//这里有一个疑问,如果起先是语音电话呢,那这里还能拿到“VideoCall”么? if (videoCall == null) { return; } videoCall.sendSessionModifyRequest(videoProfile);//发送切换/更改请求 call.setSessionModificationState(Call.SessionModificationState.WAITING_FOR_RESPONSE); InCallAudioManager.getInstance().onModifyCallClicked(call, videoProfile.getVideoState());//同步更改Audio状态 }
frameworks/base/telecomm/java/android/telecom/VideoCallImpl.java
VideoCallImpl.java/** * Sends a session modification request to the video provider. * <p> * The {@link InCallService} will create the {@code requestProfile} based on the current * video state (i.e. {@link Call.Details#getVideoState()}). It is, however, possible that the * video state maintained by the {@link InCallService} could get out of sync with what is known * by the {@link android.telecom.Connection.VideoProvider}. To remove ambiguity, the * {@link VideoCallImpl} passes along the pre-modify video profile to the {@code VideoProvider} * to ensure it has full context of the requested change. * * @param requestProfile The requested video profile. */ public void sendSessionModifyRequest(VideoProfile requestProfile) { try { VideoProfile originalProfile = new VideoProfile(mCall.getDetails().getVideoState(), 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; }
frameworks/base/telecomm/java/android/telecom/Connection.java
/** * Issues a request to modify the properties of the current video session. * <p> * Example scenarios include: requesting an audio-only call to be upgraded to a * bi-directional video call, turning on or off the user's camera, sending a pause signal * when the {@link InCallService} is no longer the foreground application. * <p> * If the {@link VideoProvider} determines a request to be invalid, it should call * {@link #receiveSessionModifyResponse(int, VideoProfile, VideoProfile)} to report the * invalid request back to the {@link InCallService}. * <p> * Where a request requires confirmation from the user of the peer device, the * {@link VideoProvider} must communicate the request to the peer device and handle the * user's response. {@link #receiveSessionModifyResponse(int, VideoProfile, VideoProfile)} * is used to inform the {@link InCallService} of the result of the request. * <p> * Sent from the {@link InCallService} via * {@link InCallService.VideoCall#sendSessionModifyRequest(VideoProfile)}. * * @param fromProfile The video profile prior to the request. * @param toProfile The video profile with the requested changes made. */ public abstract void onSendSessionModifyRequest(VideoProfile fromProfile, VideoProfile toProfile);
frameworks/opt/net/ims/src/java/com/android/ims/internal/ImsVideoCallProviderWrapper.java
重写/** @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
/** * Default handler used to consolidate binder method calls onto a single thread. */ private final Handler mProviderHandler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { 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; } ... }
vendor/qcom/proprietary/telephony-apps/ims/src/com/qualcomm/ims/vt/ImsVideoCallProviderImpl.java
高通私有代码,不贴了,一般也不会改下层的。关键log
MO log03-01 00:12:52.872 4918 4918 D VideoCall_ImsVideoCallProviderImpl: (1) onSendSessionModifyRequest, videoState=0 quality= 4//请求转换为 AUDIO_ONLY 03-01 00:12:52.873 4918 4918 D VideoCall_ImsCallModification: validateOutgoingModifyConnectionType newCallType=0//CalllType 和videoState对应 03-01 00:12:52.873 4918 4918 D VideoCall_ImsCallModification: validateOutgoingModifyConnectionType modifyToCurrCallType = false isIndexValid = true isLowBattery = false 03-01 00:12:52.873 4918 4918 V ImsSenderRxr: modifyCallInitiate callModify= 1 0 2 callSubState 0 videoPauseState2 mediaId-1 Local Ability Peer Ability Cause code 0 0[SUB1] 03-01 00:12:52.873 4918 4918 V ImsSenderRxr: setCallModify callModify= 1 0 2 callSubState 0 videoPauseState2 mediaId-1 Local Ability Peer Ability Cause code 0 0[SUB1] 03-01 00:12:52.873 4918 4918 D ImsSenderRxr: [0043]> MODIFY_CALL_INITIATE[SUB1] 03-01 00:12:53.757 4918 5512 D ImsSenderRxr: [0043]< MODIFY_CALL_INITIATE [SUB1] 03-01 00:12:53.758 4918 4918 D VideoCall_ImsCallModification: EVENT_MODIFY_CALL_INITIATE_DONE received 03-01 00:12:53.758 4918 4918 D VideoCall_ImsCallModification: clearPendingModify imsconn=org.codeaurora.ims.ImsCallModification@1ea212 03-01 00:12:53.758 4918 4918 D VideoCall_ImsVideoCallProviderImpl: (1) handleSessionModifyDone msg.what=0 // 03-01 00:12:53.758 4918 4918 D VideoCall_ImsVideoCallProviderImpl: (1) Session modify success//成功切换 //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
小结
InCallUI会根据客户要求进行修改,建议体检熟悉代码,底层基本上不用动,大概跟一下流程就可以了。如果要改bug的话,底层的关键log还是要熟悉,尤其是关键log中携带的参数的意义。这个后面的博客中会提到。关键词:android request 视频通话 upgrade public
相关文章推荐
- IMS Modify Call (1) send request 发出升级视频请求
- IMS Modify Call (1) send request 发出升级视频请求
- 视频通话收到视频升级请求流程
- IMS Modify Call (2) receive request 收到视频升级请求
- IMS Modify Call (2) receive request 收到视频升级请求
- IMS Modify Call (3) accept reject timeout 接受/拒接/超时 视频升级请求
- IMS Modify Call (3) accept reject timeout 接受/拒接/超时 视频升级请求
- 无法向会话状态服务器发出会话状态请求。请确保已启动 ASP.NET State service,并且客户端和服务器端口保持相同。
- 升级到 Spring MVC Spring framework4.1.1 导致 ajax请求 406
- 无法向会话状态服务器发出会话状态请求。请确保 ASP.NET State Service (ASP.NET 状态服务)已启动,并且客户端端口与服务器端口相同。如果服务器位于远程计算机上,请检查。。。
- 无法向会话状态服务器发出会话状态请求。请确保 ASP.NET State Service (ASP.NET
- 过滤asp.net页面每次发出请求之前访问
- .Net发出图片Request请求
- 掌握 Ajax,第 2 部分: 使用 JavaScript 和 Ajax 发出异步请求
- 关于Volley的问题,GET方式下输入有空格的参数居然解析错误,导致不能正确发出请求
- System.Web.HttpException: 无法向会话状态服务器发出会话状态请求。
- 百度编辑器上传大视频报http请求错误怎么办
- Jquery Ajax学习实例1-向页面发出请求,返回XML格式数据
- 掌握 Ajax,第 2 部分: 使用 JavaScript 和 Ajax 发出异步请求
- Jquery Ajax学习实例6-向WebService发出请求,返回DataSet(XML) 异步调用