去电流程分析---之一

2019-04-13 14:01发布

1,去电流程分析

1.1 app dialer

拨号盘界面有关拨号的部分由DialpadFragment.java实现,无论是单卡还是双卡,当点击拨号按键时,最后都会调用 handleDialButtonPressed方法进行处理,调用流程图如下,
在handleDialButtonPressed方法中,首先进行号码的有效性检查,然后调用DialerUtils的startActivityWithErrorToast的方法进行处理, final Intent intent = CallUtil.getCallIntent(number); if (!isDigitsShown && !PhoneNumberUtils.isEmergencyNumber(number)) { // must be dial conference add extra intent.putExtra(EXTRA_DIAL_CONFERENCE_URI, true); } intent.putExtra(ADD_PARTICIPANT_KEY, mAddParticipant && isPhoneInUse()); if (subcription != INVALID_SUBSCRIPTION) { intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subcription); } DialerUtils.startActivityWithErrorToast(getActivity(), intent); hideAndClearDialpad(false);//隐藏拨号盘 CallUtil的getCallIntent获取的intent, final Intent intent = new Intent(Intent.ACTION_CALL, uri);  DialerUtils的startActivityWithErrorToast方法在此就是启动一个Activity, context.startActivity(intent); 这样,在dialer进程中就处理完成了。

1.2 services telecom

telecom 中的AndroidManifest有关定义如下, package="com.android.server.telecom" coreApp="true" android:sharedUserId="android.uid.system" 并且,在UserCallActivity下面,定义了intent-filter等信息, 因此, Intent.ACTION_CALL 会启动UserCallActivity,调用流程图如下,
UserCallActivity的onCreate方法如下, new UserCallIntentProcessor(this, userHandle).processIntent(getIntent(), getCallingPackage(), true /* hasCallAppOp*/); 创建并调用UserCallIntentProcessor对象的processIntent方法,主要是一些检查, if (!canCallNonEmergency && !TelephonyUtil.shouldProcessAsEmergency(mContext, handle)) { showErrorDialogForRestrictedOutgoingCall(mContext, R.string.outgoing_call_not_allowed_no_permission); Log.w(this, "Rejecting non-emergency phone call because " + android.Manifest.permission.CALL_PHONE + " permission is not granted."); return; } 检查完成之后,调用sendBroadcastToReceiver方法发送广播。 private boolean sendBroadcastToReceiver(Intent intent) { intent.putExtra(CallIntentProcessor.KEY_IS_INCOMING_CALL, false); intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND); intent.setClass(mContext, PrimaryCallReceiver.class); Log.d(this, "Sending broadcast as user to CallReceiver"); mContext.sendBroadcastAsUser(intent, UserHandle.OWNER); return true; } 直接发送给PrimaryCallReceiver, 调用流程图如下,

onReceive方法如下,
public void onReceive(Context context, Intent intent) { synchronized (getTelecomSystem().getLock()) { getTelecomSystem().getCallIntentProcessor().processIntent(intent); } } getTelecomSystem方法如下, public TelecomSystem getTelecomSystem() { return TelecomSystem.getInstance(); } 返回的是TelecomSystem对象, TelecomSystem也是一个单例,整个android系统中只有一个, TelecomSystem的 getCallIntentProcessor方法如下, public CallIntentProcessor getCallIntentProcessor() { return mCallIntentProcessor; } 返回的是CallIntentProcessor对象, CallIntentProcessor是在TelecomSystem的构造方法中构造的。 因此,最后调用的是CallIntentProcessor的processIntent方法,该方法如下, if (isUnknownCall) { processUnknownCallIntent(mCallsManager, intent); } else { processOutgoingCallIntent(mContext, mCallsManager, intent); } 如果是未知号码如空号由processUnknownCallIntent方法处理 否则调用processOutgoingCallIntent方法,该方法主要逻辑如下, 1,从intent中获取各种参数, Uri handle = intent.getData(); String scheme = handle.getScheme(); String uriString = handle.getSchemeSpecificPart(); ••• 2,调用CallsManager的startOutgoingCall启动拨号界面, Call call = callsManager.startOutgoingCall(handle, phoneAccountHandle, clientExtras); 3,调用NewOutgoingCallIntentBroadcaster的processIntent方法继续拨号, NewOutgoingCallIntentBroadcaster broadcaster = new NewOutgoingCallIntentBroadcaster( context, callsManager, call, intent, isPrivilegedDialer); final int result = broadcaster.processIntent(); 拨号界面的启动后面再详细的论述。processIntent方法的调用流程图如下,
processIntent方法主要对三种类型call的一些检查, 普通call Intent.ACTION_CALL 系统call Intent.ACTION_CALL_PRIVILEGED 紧急呼叫call Intent.ACTION_CALL_EMERGENCY 普通call任何应用都可以发起,第三方应用拨号都是使用该intent 系统call只有系统应用才能使用 紧急呼叫call 同样只有系统应用才能使用,并且可以在无卡状态下拨号. if (Intent.ACTION_CALL.equals(action)) { if (isPotentialEmergencyNumber) { if (!mIsDefaultOrSystemPhoneApp) { Log.w(this, "Cannot call potential emergency number %s with CALL Intent %s " + "unless caller is system or default dialer.", number, intent); launchSystemDialer(intent.getData()); return DisconnectCause.OUTGOING_CANCELED; } else { callImmediately = true; } } ••• 最后调用broadcastIntent方法发送广播, broadcastIntent(intent, number, !callImmediately); broadcastIntent方法如下, private void broadcastIntent(Intent originalCallIntent, String number, boolean receiverRequired) { Intent broadcastIntent = new Intent(Intent.ACTION_NEW_OUTGOING_CALL); if (number != null) { broadcastIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, number); } // Force receivers of this broadcast intent to run at foreground priority because we // want to finish processing the broadcast intent as soon as possible. broadcastIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); Log.v(this, "Broadcasting intent: %s.", broadcastIntent); checkAndCopyProviderExtras(originalCallIntent, broadcastIntent); mContext.sendOrderedBroadcastAsUser(broadcastIntent, UserHandle.CURRENT, android.Manifest.permission.PROCESS_OUTGOING_CALLS, AppOpsManager.OP_PROCESS_OUTGOING_CALLS, receiverRequired ? new NewOutgoingCallBroadcastIntentReceiver() : null, null, // scheduler Activity.RESULT_OK, // initialCode number, // initialData: initial value for the result data (number to be modified) null); // initialExtras } 直接发送给内部类NewOutgoingCallBroadcastIntentReceiver进行处理, onReceive方法又进行一系列检查, 最后调用CallsManager的placeOutgoingCall方法进行拨号, mCallsManager.placeOutgoingCall(mCall, resultHandleUri, gatewayInfo, mIntent.getBooleanExtra(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE,false), mIntent.getIntExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,VideoProfile.STATE_AUDIO_ONLY)); 真觉得这个内部类是多余的。 CallsManager的placeOutgoingCall方法会调用Call的startCreateConnection建立拨号连接, startCreateConnection方法首先创建CreateConnectionProcessor对象,然后调用其process方法, CreateConnectionProcessor的process方法调用流程图如下,
process方法会调用attemptNextPhoneAccount方法,在该方法中,首先获取ConnectionServiceWrapper对象, 然后调用createConnection方法建立连接, PhoneAccountHandle phoneAccount = attempt.connectionManagerPhoneAccount; ConnectionServiceWrapper service = mRepository.getService( phoneAccount.getComponentName(),phoneAccount.getUserHandle()); if (service == null) { Log.i(this, "Found no connection service for attempt %s", attempt); attemptNextPhoneAccount(); } else { mCall.setConnectionManagerPhoneAccount(attempt.connectionManagerPhoneAccount); mCall.setTargetPhoneAccount(attempt.targetPhoneAccount); mCall.setConnectionService(service); setTimeoutIfNeeded(service, attempt); service.createConnection(mCall, new Response(service)); } mRepository是ConnectionServiceRepository对象,其getService方法如下, ConnectionServiceWrapper getService(ComponentName componentName, UserHandle userHandle) { Pair cacheKey = Pair.create(componentName, userHandle); ConnectionServiceWrapper service = mServiceCache.get(cacheKey); if (service == null) { service = new ConnectionServiceWrapper(componentName, this, mPhoneAccountRegistrar, mCallsManager, mContext, mLock, userHandle); service.addListener(mUnbindListener); mServiceCache.put(cacheKey, service); } return service; } 在mServiceCache变量中找不到就创建ConnectionServiceWrapper对象,相当于一个本地的service管理。 ConnectionServiceWrapper继承于ServiceBinder, ConnectionServiceWrapper的createConnection方法中,定义了BindCallback匿名类并且实现了onSuccess 和onFailure回调方法,并且调用了Binder2的bind方法,该方法如下, mCallbacks.add(callback);//添加回调 if (mServiceConnection == null) {//连接未建立 Intent serviceIntent = new Intent(mServiceAction).setComponent(mComponentName); ServiceConnection connection = new ServiceBinderConnection(call); Log.event(call, Log.Events.BIND_CS, mComponentName); final int bindingFlags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE; final boolean isBound; if (mUserHandle != null) { isBound = mContext.bindServiceAsUser(serviceIntent, connection, bindingFlags, mUserHandle); } else { isBound = mContext.bindService(serviceIntent, connection, bindingFlags); } if (!isBound) { handleFailedConnection(); return; } } else {//连接已建立 Log.d(ServiceBinder.this, "Service is already bound."); Preconditions.checkNotNull(mBinder); handleSuccessfulConnection(); } 如果未建立连接,会调用bindService绑定远程服务, mServiceAction和mComponentName变量都是在ServiceBinder的构造方法中赋值的, ConnectionServiceWrapper的构造方法中会调用ServiceBinder的构造方法, super(ConnectionService.SERVICE_INTERFACE, componentName, context, lock, userHandle); ConnectionService的SERVICE_INTERFACE变量如下, public static final String SERVICE_INTERFACE = "android.telecom.ConnectionService"; ConnectionService只是一个抽象类,具体的实现在services Telephony的TelephonyConnectionService中,并且 services Telephony的AndroidManifest关于TelephonyConnectionService有关定义如下, 因此,绑定的就是TelephonyConnectionService服务。 当然,绑定失败的代码在此就不分析了,仅分析绑定成功的代码。 绑定成功之后, 就会回调ServiceBinder的内部类ServiceBinderConnection的onServiceConnected方法, setBinder(binder); //获取远程服务的binder handleSuccessfulConnection();//回调方法 setBinder方法会调用ConnectionServiceWrapper的setServiceInterface方法,如下, mServiceInterface = IConnectionService.Stub.asInterface(binder); addConnectionServiceAdapter(mAdapter); 为mServiceInterface变量赋值,这样mServiceInterface就指向远程的TelephonyConnectionService对象。 ServiceBinder的handleSuccessfulConnection方法如下, private void handleSuccessfulConnection() { for (BindCallback callback : mCallbacks) { callback.onSuccess(); } mCallbacks.clear(); } 回调createConnection方法中的callback的onSuccess方法, mServiceInterface.createConnection(call.getConnectionManagerPhoneAccount(), callId, new ConnectionRequest(call.getTargetPhoneAccount(),call.getHandle(),extras, call.getVideoState()),call.isIncoming(),call.isUnknown()); 这样,就会调用TelephonyConnectionService的createConnection方法。 创建连接实际上就是创建services telecom 到 services Telephony的一个连接。 这样, services telecom中的流程也处理完成了。