赞
踩
\packages\apps\Dialer
\packages\apps\InCallUI
\packages\services\Telecomm
\packages\services\Telephony
\frameworks\base\telecomm
\frameworks\base\telephony
\frameworks\opt\telephony
\frameworks\opt\net\ims
\vendor\mediatek\proprietary\packages\services\Ims
Android6.0去电流程,(右键点击在新标签页查看大图)
无Update的Log Step 68 69 70 71 72
(后期会加注释)
@Override public void onClick(View view) { /** M: Prevent the event if dialpad is not shown. @{ */ if (getActivity() != null && !((DialtactsActivity)getActivity()).isDialpadShown()) { Log.d(TAG, "onClick but dialpad is not shown, skip !!!"); return; } /** @} */ switch (view.getId()) { case R.id.dialpad_floating_action_button: mHaptic.vibrate(); android.util.Log.d("wds_mo","step1-->Dialer-->DialpadFragment.onClick()"); handleDialButtonPressed(); break; ....
private void handleDialButtonPressed(int type) { if (isDigitsEmpty()) { // No number entered. handleDialButtonClickWithEmptyDigits(); } else { final String number = mDigits.getText().toString(); // "persist.radio.otaspdial" is a temporary hack needed for one carrier's automated // test equipment. // TODO: clean it up. if (number != null && !TextUtils.isEmpty(mProhibitedPhoneNumberRegexp) && number.matches(mProhibitedPhoneNumberRegexp)) { Log.i(TAG, "The phone number is prohibited explicitly by a rule."); if (getActivity() != null) { DialogFragment dialogFragment = ErrorDialogFragment.newInstance( R.string.dialog_phone_call_prohibited_message); dialogFragment.show(getFragmentManager(), "phone_prohibited_dialog"); } // Clear the digits just in case. clearDialpad(); } else { final Intent intent; /** M: [IP Dial] check the type of call @{ */ if (type != Constants.DIAL_NUMBER_INTENT_NORMAL) { intent = IntentUtil.getCallIntent(IntentUtil.getCallUri(number), (getActivity() instanceof DialtactsActivity ? ((DialtactsActivity) getActivity()).getCallOrigin() : null), type); } else { intent = IntentUtil.getCallIntent(number, (getActivity() instanceof DialtactsActivity ? ((DialtactsActivity) getActivity()).getCallOrigin() : null)); } /** @} */ android.util.Log.d("wds_mo","step3-->Dialer-->DialpadFragment.handleDialButtonPressed()"); DialerUtils.startActivityWithErrorToast(getActivity(), intent); hideAndClearDialpad(false); } } }
public static void startActivityWithErrorToast(Context context, Intent intent, int msgId) { try { if ((IntentUtil.CALL_ACTION.equals(intent.getAction()) && context instanceof Activity)) { // All dialer-initiated calls should pass the touch point to the InCallUI Point touchPoint = TouchPointManager.getInstance().getPoint(); if (touchPoint.x != 0 || touchPoint.y != 0) { Bundle extras = new Bundle(); extras.putParcelable(TouchPointManager.TOUCH_POINT, touchPoint); intent.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, extras); } android.util.Log.d("wds_mo","step5-->Dialer-->DialerUtils.startActivityWithErrorToast()"); final TelecomManager tm = (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE); tm.placeCall(intent.getData(), intent.getExtras()); /// M: add log for debugging if (DEBUG) { Log.d(TAG, "startActivityWithErrorToast placeCall with intent " + intent); } } else { context.startActivity(intent); } } catch (ActivityNotFoundException e) { Toast.makeText(context, msgId, Toast.LENGTH_SHORT).show(); } }
public void placeCall(Uri address, Bundle extras) {
ITelecomService service = getTelecomService();
if (service != null) {
if (address == null) {
Log.w(TAG, "Cannot place call to empty address.");
}
try {
android.util.Log.d("wds_mo","step6-->framework/base/Telecom-->TelecomManager.placeCall()");
service.placeCall(address, extras == null ? new Bundle() : extras,
mContext.getOpPackageName());
} catch (RemoteException e) {
Log.e(TAG, "Error calling ITelecomService#placeCall", e);
}
}
}
@Override public void placeCall(Uri handle, Bundle extras, String callingPackage) { enforceCallingPackage(callingPackage); if (!canCallPhone(callingPackage, "placeCall")) { throw new SecurityException("Package " + callingPackage + " is not allowed to place phone calls"); } // Note: we can still get here for the default/system dialer, even if the Phone // permission is turned off. This is because the default/system dialer is always // allowed to attempt to place a call (regardless of permission state), in case // it turns out to be an emergency call. If the permission is denied and the // call is being made to a non-emergency number, the call will be denied later on // by {@link UserCallIntentProcessor}. final boolean hasCallAppOp = mAppOpsManager.noteOp(AppOpsManager.OP_CALL_PHONE, Binder.getCallingUid(), callingPackage) == AppOpsManager.MODE_ALLOWED; final boolean hasCallPermission = mContext.checkCallingPermission(CALL_PHONE) == PackageManager.PERMISSION_GRANTED; synchronized (mLock) { final UserHandle userHandle = Binder.getCallingUserHandle(); long token = Binder.clearCallingIdentity(); try { final Intent intent = new Intent(Intent.ACTION_CALL, handle); intent.putExtras(extras); android.util.Log.d("wds_mo","step7-->Telecom-->TelecomServiceImpl.placeCall()"); new UserCallIntentProcessor(mContext, userHandle).processIntent(intent, callingPackage, hasCallAppOp && hasCallPermission); } finally { Binder.restoreCallingIdentity(token); } } }
public void processIntent(Intent intent, String callingPackageName, boolean canCallNonEmergency) { // Ensure call intents are not processed on devices that are not capable of calling. if (!isVoiceCapable()) { return; } String action = intent.getAction(); if (Intent.ACTION_CALL.equals(action) || Intent.ACTION_CALL_PRIVILEGED.equals(action) || Intent.ACTION_CALL_EMERGENCY.equals(action)) { android.util.Log.d("wds_mo","step8-->Telecom-->UserCallIntentProcessor.processIntent()"); processOutgoingCallIntent(intent, callingPackageName, canCallNonEmergency); } }
private void processOutgoingCallIntent(Intent intent, String callingPackageName, boolean canCallNonEmergency) { Uri handle = intent.getData(); String scheme = handle.getScheme(); String uriString = handle.getSchemeSpecificPart(); /// M: Do noting for CDMA empty flash at present if (intent.getBooleanExtra(EXTRA_SEND_EMPTY_FLASH, false)) { Log.w(this, "Empty flash obtained from the call intent."); return; } if (!PhoneAccount.SCHEME_VOICEMAIL.equals(scheme)) { handle = Uri.fromParts(PhoneNumberUtils.isUriNumber(uriString) ? PhoneAccount.SCHEME_SIP : PhoneAccount.SCHEME_TEL, uriString, null); } final UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); if (userManager.hasUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, mUserHandle) && !TelephonyUtil.shouldProcessAsEmergency(mContext, handle)) { // Only emergency calls are allowed for users with the DISALLOW_OUTGOING_CALLS // restriction. showErrorDialogForRestrictedOutgoingCall(mContext, R.string.outgoing_call_not_allowed_user_restriction); Log.w(this, "Rejecting non-emergency phone call due to DISALLOW_OUTGOING_CALLS " + "restriction"); return; } 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; } int videoState = intent.getIntExtra( TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, VideoProfile.STATE_AUDIO_ONLY); Log.d(this, "processOutgoingCallIntent videoState = " + videoState); if (VideoProfile.isVideo(videoState) && TelephonyUtil.shouldProcessAsEmergency(mContext, handle)) { Log.d(this, "Emergency call...Converting video call to voice..."); videoState = VideoProfile.STATE_AUDIO_ONLY; intent.putExtra(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, videoState); } if (VideoProfile.isVideo(videoState) && isTtyModeEnabled()) { Toast.makeText(mContext, mContext.getResources().getString(R.string. video_call_not_allowed_if_tty_enabled), Toast.LENGTH_SHORT).show(); Log.d(this, "Rejecting video calls as tty is enabled"); return; } intent.putExtra(CallIntentProcessor.KEY_IS_PRIVILEGED_DIALER, isDefaultOrSystemDialer(callingPackageName)); android.util.Log.d("wds_mo","step9-->Telecom-->UserCallIntentProcessor.processOutgoingCallIntent()"); sendBroadcastToReceiver(intent); } private boolean isTtyModeEnabled() { return (android.provider.Settings.Secure.getInt( mContext.getContentResolver(), android.provider.Settings.Secure.PREFERRED_TTY_MODE, TelecomManager.TTY_MODE_OFF) != TelecomManager.TTY_MODE_OFF); } private boolean isDefaultOrSystemDialer(String callingPackageName) { if (TextUtils.isEmpty(callingPackageName)) { return false; } final String defaultDialer = DefaultDialerManager.getDefaultDialerApplication(mContext, mUserHandle.getIdentifier()); if (TextUtils.equals(defaultDialer, callingPackageName)) { return true; } final TelecomManager telecomManager = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE); return TextUtils.equals(telecomManager.getSystemDialerPackage(), callingPackageName); }
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");
android.util.Log.d("wds_mo","step10-->Telecom-->UserCallIntentProcessor.sendBroadcastToReceiver()");
mContext.sendBroadcastAsUser(intent, UserHandle.OWNER);
return true;
}
public class PrimaryCallReceiver extends BroadcastReceiver implements TelecomSystem.Component {
@Override
public void onReceive(Context context, Intent intent) {
synchronized (getTelecomSystem().getLock()) {
android.util.Log.d("wds_mo","step11-->Telecom-->PrimaryCallReceiver.onReceive()");
getTelecomSystem().getCallIntentProcessor().processIntent(intent);
}
}
public void processIntent(Intent intent) {
final boolean isUnknownCall = intent.getBooleanExtra(KEY_IS_UNKNOWN_CALL, false);
Log.i(this, "onReceive - isUnknownCall: %s", isUnknownCall);
Trace.beginSection("processNewCallCallIntent");
if (isUnknownCall) {
processUnknownCallIntent(mCallsManager, intent);
} else {
android.util.Log.d("wds_mo","step12-->Telecom-->CallIntentProcessor.processIntent()");
processOutgoingCallIntent(mContext, mCallsManager, intent);
}
Trace.endSection();
}
分两部分执行
static void processOutgoingCallIntent(
Context context,
CallsManager callsManager,
Intent intent) {
/// M: for log parser @{ LogUtils.logIntent(intent); /// @} if (shouldPreventDuplicateVideoCall(context, callsManager, intent)) { return; } Uri handle = intent.getData(); String scheme = handle.getScheme(); String uriString = handle.getSchemeSpecificPart(); if (!PhoneAccount.SCHEME_VOICEMAIL.equals(scheme)) { handle = Uri.fromParts(PhoneNumberUtils.isUriNumber(uriString) ? PhoneAccount.SCHEME_SIP : PhoneAccount.SCHEME_TEL, uriString, null); } PhoneAccountHandle phoneAccountHandle = intent.getParcelableExtra( TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE); Bundle clientExtras = null; if (intent.hasExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS)) { clientExtras = intent.getBundleExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS); } if (clientExtras == null) { clientExtras = new Bundle(); } final boolean isPrivilegedDialer = intent.getBooleanExtra(KEY_IS_PRIVILEGED_DIALER, false); /// M: For dial via specified slot. @{ if (intent.hasExtra(TelecomUtils.EXTRA_SLOT)) { int slotId = intent.getIntExtra(TelecomUtils.EXTRA_SLOT, -1); phoneAccountHandle = TelecomUtils .getPhoneAccountHandleWithSlotId(context, slotId, phoneAccountHandle); } /// @} /// M: for VoLTE @{ // Here we handle all error case for VoLTE. boolean isImsCallRequest = TelecomVolteUtils.isImsCallOnlyRequest(intent); boolean isConferenceDialRequest = TelecomVolteUtils.isConferenceDialRequest(intent); if (isImsCallRequest || isConferenceDialRequest) { Log.d(TAG, "MO - VoLTE case: Ims Call / Conference Dial = %s / %s", isImsCallRequest, isConferenceDialRequest); if (!TelecomVolteUtils.isImsEnabled(context)) { Log.d(TAG, "MO - VoLTE case: Ims is disabled => Abandon"); TelecomVolteUtils.showImsDisableDialog(context); return; } List<PhoneAccountHandle> accounts = TelecomUtils.getVoltePhoneAccountHandles(); if (accounts == null || accounts.isEmpty()) { Log.d(TAG, "MO - VoLTE case: No VoLTE account => Abandon"); TelecomVolteUtils.showNoImsAccountDialog(context); return; } if (isImsCallRequest) { clientExtras.putBoolean(TelecomVolteUtils.EXTRA_VOLTE_IMS_CALL, true); } if (isConferenceDialRequest) { handle = TelecomVolteUtils.checkHandleForConferenceDial(context, handle); } } /// @} /// M: For Ip dial & suggested account & VoLTE-Ims Call & // VoLTE-Conference Dial & ViLTE-Block certain ViLTE. @{ copyExtraToBundle(intent, clientExtras); /// @} // Send to CallsManager to ensure the InCallUI gets kicked off before the broadcast returns android.util.Log.d("wds_mo","step13-->Telecom-->CallIntentProcessor.processOutgoingCallIntent()-- to InCallUI"); Call call = callsManager.startOutgoingCall(handle, phoneAccountHandle, clientExtras); if (call != null) { /// M: ip dial. ip prefix already add, here need to change intent @{ if (call.isIpCall()) { intent.setData(call.getHandle()); } /// @} /// M: For VoLTE - Conference Dial @{ // For Con dial, skip NewOutgoingCallIntentBroadcaster. createConnection() directly. if (call.isConferenceDial()) { call.startCreateConnection(TelecomSystem.getInstance().getPhoneAccountRegistrar()); return; } /// @} // Asynchronous calls should not usually be made inside a BroadcastReceiver // because once // onReceive is complete, the BroadcastReceiver's process runs the risk of getting // killed if memory is scarce. However, this is OK here because the entire Telecom // process will be running throughout the duration of the phone call and should never // be killed. NewOutgoingCallIntentBroadcaster broadcaster = new NewOutgoingCallIntentBroadcaster( context, callsManager, call, intent, isPrivilegedDialer); final int result = broadcaster.processIntent(); final boolean success = result == DisconnectCause.NOT_DISCONNECTED; if (!success && call != null) { disconnectCallAndShowErrorDialog(context, call, result); } } }
Call startOutgoingCall(Uri handle, PhoneAccountHandle phoneAccountHandle, Bundle extras) { ... // Do not add the call if it is a potential MMI code. if ((isPotentialMMICode(handle) || isPotentialInCallMMICode) && !needsAccountSelection) { call.addListener(this); /// M: If no account for MMI Code, show a dialog with "No SIM or SIM error" message. @{ if (phoneAccountHandle == null) { Log.d(this, "MO - MMI with no sim: show error dialog and return"); TelecomUtils.showErrorDialog(mContext, R.string.callFailed_simError); disconnectCall(call); return null; } /// @} } else if (!mCalls.contains(call)) { // We check if mCalls already contains the call because we could potentially be reusing // a call which was previously added (See {@link #getNewOutgoingCall}). android.util.Log.d("wds_mo","step14-->Telecom-->CallsManager.startOutgoingCall()"); addCall(call); } return call; }
private void addCall(Call call) { Trace.beginSection("addCall"); Log.v(this, "addCall(%s)", call); call.addListener(this); mCalls.add(call); // TODO: Update mForegroundCall prior to invoking // onCallAdded for calls which immediately take the foreground (like the first call). android.util.Log.d("wds_mo","step15-->Telecom-->CallsManager.addCall()"); for (CallsManagerListener listener : mListeners) { if (Log.SYSTRACE_DEBUG) { Trace.beginSection(listener.getClass().toString() + " addCall"); } listener.onCallAdded(call); if (Log.SYSTRACE_DEBUG) { Trace.endSection(); } } updateCallsManagerState(); Trace.endSection(); }
@Override public void onCallAdded(Call call) { if (!isBoundToServices()) { android.util.Log.d("wds_mo","step16-->Telecom-->InCallController.onCallAdded()"); bindToServices(call); } else { adjustServiceBindingsForEmergency(); Log.i(this, "onCallAdded: %s", call); // Track the call if we don't already know about it. addCall(call); for (Map.Entry<ComponentName, IInCallService> entry : mInCallServices.entrySet()) { ComponentName componentName = entry.getKey(); IInCallService inCallService = entry.getValue(); ParcelableCall parcelableCall = toParcelableCall(call, true /* includeVideoProvider */); try { inCallService.addCall(parcelableCall); } catch (RemoteException ignored) { } } } }
private void bindToServices(Call call) { PackageManager packageManager = mContext.getPackageManager(); Intent serviceIntent = new Intent(InCallService.SERVICE_INTERFACE); List<ComponentName> inCallControlServices = new ArrayList<>(); ComponentName inCallUIService = null; .... .... if (inCallUIService != null) { // skip default dialer if we have an emergency call or if it failed binding. android.util.Log.d("wds_mo","step17-->Telecom-->InCallController.bindToServices()"); if (mCallsManager.hasEmergencyCall()) { Log.i(this, "Skipping default-dialer because of emergency call"); inCallUIService = null; } else if (!bindToInCallService(inCallUIService, call, "def-dialer")) { Log.event(call, Log.Events.ERROR_LOG, "InCallService UI failed binding: " + inCallUIService); inCallUIService = null; } } ...... }
private boolean bindToInCallService(ComponentName componentName, Call call, String tag) { if (mInCallServices.containsKey(componentName)) { Log.i(this, "An InCallService already exists: %s", componentName); return true; } if (mServiceConnections.containsKey(componentName)) { Log.w(this, "The service is already bound for this component %s", componentName); return true; } Intent intent = new Intent(InCallService.SERVICE_INTERFACE); intent.setComponent(componentName); if (call != null && !call.isIncoming()){ intent.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, call.getIntentExtras()); intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, call.getTargetPhoneAccount()); } Log.i(this, "Attempting to bind to [%s] InCall %s, with %s", tag, componentName, intent); InCallServiceConnection inCallServiceConnection = new InCallServiceConnection(); android.util.Log.d("wds_mo","step18-->Telecom-->InCallController.bindToInCallService()"); if (mContext.bindServiceAsUser(intent, inCallServiceConnection, Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, UserHandle.CURRENT)) { mServiceConnections.put(componentName, inCallServiceConnection); /// M: Register voice recording listener @{ PhoneRecorderHandler.getInstance().setListener(mRecorderListener); /// @} return true; } return false; }
@Override public IBinder onBind(Intent intent) { Log.d(this, "onBind"); final Context context = getApplicationContext(); /// M: [plugin]ensure a context is valid. ExtensionManager.registerApplicationContext(context); final ContactInfoCache contactInfoCache = ContactInfoCache.getInstance(context); android.util.Log.d("wds_mo","step19-->InCallUI-->InCallServiceImpl.onBind()"); InCallPresenter.getInstance().setUp( getApplicationContext(), CallList.getInstance(), AudioModeProvider.getInstance(), new StatusBarNotifier(context, contactInfoCache), contactInfoCache, new ProximitySensor(context, AudioModeProvider.getInstance()) ); InCallPresenter.getInstance().onServiceBind(); InCallPresenter.getInstance().maybeStartRevealAnimation(intent); TelecomAdapter.getInstance().setInCallService(this); return super.onBind(intent); }
public void setUp(Context context, CallList callList, AudioModeProvider audioModeProvider, StatusBarNotifier statusBarNotifier, ContactInfoCache contactInfoCache, ProximitySensor proximitySensor) { android.util.Log.d("wds_mo","step20-->InCallUI-->InCallPresenter.setUp()"); if (mServiceConnected) { Log.i(this, "New service connection replacing existing one."); // retain the current resources, no need to create new ones. Preconditions.checkState(context == mContext); Preconditions.checkState(callList == mCallList); Preconditions.checkState(audioModeProvider == mAudioModeProvider); return; } Preconditions.checkNotNull(context); mContext = context; mContactInfoCache = contactInfoCache; /// M: for ALPS01328763 @{ // remove the original one before add new listener if (mStatusBarNotifier != null) { removeListener(mStatusBarNotifier); removeIncomingCallListener(mStatusBarNotifier); mStatusBarNotifier.tearDown(); } /// @} mStatusBarNotifier = statusBarNotifier; addListener(mStatusBarNotifier); /// M: ALPS01843428 @{ // Passing incoming event to StatusBarNotifier for updating the notification. addIncomingCallListener(mStatusBarNotifier); /// @} mAudioModeProvider = audioModeProvider; /// M: for ALPS01328763 @{ // remove the original one before add new listener if (mProximitySensor != null) { removeListener(mProximitySensor); //M: fix ALPS02535607 removeDetailsListener(mProximitySensor); } /// @} mProximitySensor = proximitySensor; addListener(mProximitySensor); //M: fix ALPS02535607,add onDetail change listener for ProximitySensor addDetailsListener(mProximitySensor); addIncomingCallListener(mAnswerPresenter); addInCallUiListener(mAnswerPresenter); mCallList = callList; /// M: add for phone recording. mRecordingState = PhoneRecorderUtils.RecorderState.IDLE_STATE; // This only gets called by the service so this is okay. mServiceConnected = true; ///M: WFC @{ if (ImsManager.isWfcEnabledByPlatform(mContext)) { mRoveOutReceiver = new InCallUiWfcUtils.RoveOutReceiver(mContext); mRoveOutReceiver.register(mContext); } /// @} // The final thing we do in this set up is add ourselves as a listener to CallList. This // will kick off an update and the whole process can start. mCallList.addListener(this); VideoPauseController.getInstance().setUp(this); VideoSessionController.getInstance().setUp(this); /// M: [AutoAnswer]for Engineer Mode @{ mAutoAnswer = new AutoAnswerHelper(mContext); addIncomingCallListener(mAutoAnswer); /// @} Log.d(this, "Finished InCallPresenter.setUp"); }
public void maybeStartRevealAnimation(Intent intent) { if (intent == null || mInCallActivity != null) { return; } final Bundle extras = intent.getBundleExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS); if (extras == null) { // Incoming call, just show the in-call UI directly. return; } if (extras.containsKey(android.telecom.Call.AVAILABLE_PHONE_ACCOUNTS)) { // Account selection dialog will show up so don't show the animation. return; } final PhoneAccountHandle accountHandle = intent.getParcelableExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE); final Point touchPoint = extras.getParcelable(TouchPointManager.TOUCH_POINT); InCallPresenter.getInstance().setBoundAndWaitingForOutgoingCall(true, accountHandle); final Intent incallIntent = getInCallIntent(false, true); incallIntent.putExtra(TouchPointManager.TOUCH_POINT, touchPoint); android.util.Log.d("wds_mo","step21-->InCallUI-->InCallPresenter.maybeStartRevealAnimation()"); mContext.startActivity(incallIntent); }
@Override
protected void onCreate(Bundle icicle) {
Log.d(this, "onCreate()... this = " + this);
android.util.Log.d("wds_mo","step22-->InCallUI-->startActivity-->InCallActivity.onCreate() ");
super.onCreate(icicle);
......
}
public final class InCallController extends CallsManagerListenerBase { /** * Used to bind to the in-call app and triggers the start of communication between * this class and in-call app. */ private class InCallServiceConnection implements ServiceConnection { /** {@inheritDoc} */ @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.d(this, "onServiceConnected: %s", name); android.util.Log.d("wds_mo","step23-->Telecom-->InCallController.InCallServiceConnection.onServiceConnected()"); onConnected(name, service); } /** {@inheritDoc} */ @Override public void onServiceDisconnected(ComponentName name) { Log.d(this, "onDisconnected: %s", name); onDisconnected(name); } }
这里分两部分,先初始化InCallAdapter,后执行addCall
private void onConnected(ComponentName componentName, IBinder service) { Trace.beginSection("onConnected: " + componentName); Log.i(this, "onConnected to %s", componentName); IInCallService inCallService = IInCallService.Stub.asInterface(service); mInCallServices.put(componentName, inCallService); try { android.util.Log.d("wds_mo","step24-->Telecom-->InCallController.onConnected()"); inCallService.setInCallAdapter( new InCallAdapter( mCallsManager, mCallIdMapper, mLock)); } catch (RemoteException e) { Log.e(this, e, "Failed to set the in-call adapter."); Trace.endSection(); onInCallServiceFailure(componentName, "setInCallAdapter"); return; } // Upon successful connection, send the state of the world to the service. Collection<Call> calls = mCallsManager.getCalls(); if (!calls.isEmpty()) { Log.i(this, "Adding %s calls to InCallService after onConnected: %s", calls.size(), componentName); for (Call call : calls) { try { // Track the call if we don't already know about it. addCall(call); inCallService.addCall(toParcelableCall(call, true /* includeVideoProvider */)); } catch (RemoteException ignored) { } } onCallAudioStateChanged( null, mCallsManager.getAudioState()); onCanAddCallChanged(mCallsManager.canAddCall()); } else { unbindFromServices(); } Trace.endSection(); }
先后执行初始化,后使用
/** Manages the binder calls so that the implementor does not need to deal with it. */ private final class InCallServiceBinder extends IInCallService.Stub { @Override public void setInCallAdapter(IInCallAdapter inCallAdapter) { android.util.Log.d("wds_mo","step25-->framework/base/Telecom-->InCallService.InCallServiceBinder.setInCallAdapter()"); mHandler.obtainMessage(MSG_SET_IN_CALL_ADAPTER, inCallAdapter).sendToTarget(); } @Override public void addCall(ParcelableCall call) { android.util.Log.d("wds_mo","step27-->framework/base/Telecom-->InCallService.InCallServiceBinder.addCall()"); mHandler.obtainMessage(MSG_ADD_CALL, call).sendToTarget(); } @Override public void updateCall(ParcelableCall call) { android.util.Log.d("wds_mo","step70-->framework/base/Telecom-->InCallService.InCallServiceBinder.updateCall()"); mHandler.obtainMessage(MSG_UPDATE_CALL, call).sendToTarget(); } @Override public void setPostDial(String callId, String remaining) { // TODO: Unused } .............
@Override public void handleMessage(Message msg) { /// M: [log optimize]for performance debugging. mMessageAnalyzer.onStartHandleMessage(msg); if (mPhone == null && msg.what != MSG_SET_IN_CALL_ADAPTER) { /// M: [log optimize]for performance debugging. mMessageAnalyzer.onMessageHandled(msg); return; } SomeArgs args; switch (msg.what) { case MSG_SET_IN_CALL_ADAPTER: android.util.Log.d("wds_mo","step26-->framework/base/Telecom-->InCallService.handleMessage_MSG_SET_IN_CALL_ADAPTER"); mPhone = new Phone(new InCallAdapter((IInCallAdapter) msg.obj)); mPhone.addListener(mPhoneListener); onPhoneCreated(mPhone); break; case MSG_ADD_CALL: android.util.Log.d("wds_mo","step28-->framework/base/Telecom-->InCallService.handleMessage_MSG_ADD_CALL"); mPhone.internalAddCall((ParcelableCall) msg.obj); break;
final void internalAddCall(ParcelableCall parcelableCall) {
Call call = new Call(this, parcelableCall.getId(), mInCallAdapter,
parcelableCall.getState());
mCallByTelecomCallId.put(parcelableCall.getId(), call);
mCalls.add(call);
checkCallTree(parcelableCall);
call.internalUpdate(parcelableCall, mCallByTelecomCallId);
android.util.Log.d("wds_mo","step29-->framework/base/Telecom-->InCallService.internalAddCall()");
fireCallAdded(call);
}
private void fireCallAdded(Call call) {
android.util.Log.d("wds_mo","step30-->framework/base/Telecom-->Phone.fireCallAdded()");
for (Listener listener : mListeners) {
listener.onCallAdded(this, call);
}
}
public void onCallAdded(android.telecom.Call telecommCall) { Trace.beginSection("onCallAdded"); Call call = new Call(telecommCall); Log.d(this, "onCallAdded: callState=" + call.getState()); if (call.getState() == Call.State.INCOMING || call.getState() == Call.State.CALL_WAITING) { onIncoming(call, call.getCannedSmsResponses()); } else { android.util.Log.d("wds_mo","step32-->InCallUI-->CallList.onCallAdded() "); onUpdate(call); } /// M: [log optimize] @{ if (call.isConferenceCall()) { Log.notify(call, Log.CcNotifyAction.CONFERENCED, "ConfCreated"); } /// @} Trace.endSection(); }
public void onUpdate(Call call) {
Trace.beginSection("onUpdate");
onUpdateCall(call);
android.util.Log.d("wds_mo","step33-->InCallUI-->CallList.onUpdate()");
notifyGenericListeners();
Trace.endSection();
}
private void notifyGenericListeners() {
android.util.Log.d("wds_mo","step34-->InCallUI-->CallList.notifyGenericListeners()");
for (Listener listener : mListeners) {
listener.onCallListChange(this);
}
}
@Override public void onCallListChange(CallList callList) { android.util.Log.d("wds_mo","step35-->InCallUI-->InCallPresenter.onCallListChange()"); if (mInCallActivity != null && mInCallActivity.getCallCardFragment() != null && mInCallActivity.getCallCardFragment().isAnimating()) { /// M: add for monitor call card animation process Log.d(this, "[onCallListChange] Call Card view is animating!"); mAwaitingCallListUpdate = true; return; } if (callList == null) { return; } ..................
}
Step13继续执行
static void processOutgoingCallIntent(
......
NewOutgoingCallIntentBroadcaster broadcaster = new NewOutgoingCallIntentBroadcaster(
context, callsManager, call, intent, isPrivilegedDialer);
final int result = broadcaster.processIntent();
final boolean success = result == DisconnectCause.NOT_DISCONNECTED;
if (!success && call != null) {
disconnectCallAndShowErrorDialog(context, call, result);
}
}
}
private class NewOutgoingCallBroadcastIntentReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { ........... Uri originalUri = mIntent.getData(); if (originalUri.getSchemeSpecificPart().equals(resultNumber)) { Log.v(this, "Call number unmodified after new outgoing call intent broadcast."); } else { Log.v(this, "Retrieved modified handle after outgoing call intent broadcast: " + "Original: %s, Modified: %s", Log.pii(originalUri), Log.pii(resultHandleUri)); } GatewayInfo gatewayInfo = getGateWayInfoFromIntent(intent, resultHandleUri); android.util.Log.d("wds_mo","step36-->Telecom-->NewOutgoingCallIntentBroadcaster.onReceive()"); 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)); Trace.endSection(); } } }
void placeOutgoingCall(Call call, Uri handle, GatewayInfo gatewayInfo, boolean speakerphoneOn, int videoState) { ........... /// M: ALPS02035599 Since NewOutgoingCallIntentBroadcaster and the SELECT_PHONE_ACCOUNT @{ // sequence run in parallel, this call may be already disconnected in the select phone // account sequence. if (call.getState() == CallState.DISCONNECTED) { return; } /// @} if (call.getTargetPhoneAccount() != null || isEmergencyCall) { // If the account has been set, proceed to place the outgoing call. // Otherwise the connection will be initiated when the account is set by the user. android.util.Log.d("wds_mo","step37-->Telecom-->CallsManager.placeOutgoingCall()"); call.startCreateConnection(mPhoneAccountRegistrar); }
void startCreateConnection(PhoneAccountRegistrar phoneAccountRegistrar) { /// M: Workaround for ALPS01845919. @{ // Maybe broadcast will be delayed, the phoneAccount selected earlier than received broadcast, // and the call will be place twice, need cancel the duplicate one. if (mCreateConnectionProcessor != null) { Log.v(this, "Canceling this duplicate call."); return; } /// @} Preconditions.checkState(mCreateConnectionProcessor == null); mCreateConnectionProcessor = new CreateConnectionProcessor(this, mRepository, this, phoneAccountRegistrar, mContext); android.util.Log.d("wds_mo","step38-->Telecom-->Call.startCreateConnection()"); mCreateConnectionProcessor.process(); }
void process() {
Log.v(this, "process");
clearTimeout();
mAttemptRecords = new ArrayList<>();
if (mCall.getTargetPhoneAccount() != null) {
mAttemptRecords.add(new CallAttemptRecord(
mCall.getTargetPhoneAccount(), mCall.getTargetPhoneAccount()));
}
adjustAttemptsForConnectionManager();
adjustAttemptsForEmergency();
mAttemptRecordIterator = mAttemptRecords.iterator();
android.util.Log.d("wds_mo","step39-->Telecom-->CreateConnectionProcessor.process()");
attemptNextPhoneAccount();
}
private void attemptNextPhoneAccount() { .......... if (mResponse != null && attempt != null) { Log.i(this, "Trying attempt %s", attempt); 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); /// M: Valid phone account for ECC may have been set.@{ if (mCall.getTargetPhoneAccount() == null) { mCall.setTargetPhoneAccount(attempt.targetPhoneAccount); } /// @} mCall.setConnectionService(service); setTimeoutIfNeeded(service, attempt); android.util.Log.d("wds_mo","step40-->Telecom-->CreateConnectionProcessor.attemptNextPhoneAccount()"); service.createConnection(mCall, new Response(service)); } } else { Log.v(this, "attemptNextPhoneAccount, no more accounts, failing"); if (mResponse != null) { clearTimeout(); mResponse.handleCreateConnectionFailure(mLastErrorDisconnectCause != null ? mLastErrorDisconnectCause : new DisconnectCause(DisconnectCause.ERROR)); mResponse = null; mCall.clearConnectionService(); } } }
void createConnection(final Call call, final CreateConnectionResponse response) {
logOutgoing("createConnection(%s) via %s.", call, getComponentName());
BindCallback callback = new BindCallback() {
@Override
public void onSuccess() {
.....
android.util.Log.d("wds_mo","step41-->Telecom-->ConnectionServiceWrapper.createConnection()");
mBinder.bind(callback, call);
}
void bind(BindCallback callback, Call call) { Log.d(ServiceBinder.this, "bind()"); // Reset any abort request if we're asked to bind again. clearAbort(); if (!mCallbacks.isEmpty()) { // Binding already in progress, append to the list of callbacks and bail out. mCallbacks.add(callback); return; } 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) { android.util.Log.d("wds_mo","step42-->Telecom-->Binder2.bind(()"); 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(); } } }
private final class ServiceBinderConnection implements ServiceConnection { ........ @Override public void onServiceConnected(ComponentName componentName, IBinder binder) { synchronized (mLock) { Log.i(this, "Service bound %s", componentName); Log.event(mCall, Log.Events.CS_BOUND, componentName); mCall = null; // Unbind request was queued so unbind immediately. if (mIsBindingAborted) { clearAbort(); logServiceDisconnected("onServiceConnected"); mContext.unbindService(this); handleFailedConnection(); return; } mServiceConnection = this; android.util.Log.d("wds_mo","step43-->Telecom-->Binder2.onServiceConnected()"); setBinder(binder); handleSuccessfulConnection(); } } ..........
private void setBinder(IBinder binder) {
if (mBinder != binder) {
mBinder = binder;
android.util.Log.d("wds_mo","step44-->Telecom-->Binder2.setBinder()");
setServiceInterface(binder);
if (binder == null) {
for (Listener l : mListeners) {
l.onUnbind(this);
}
}
}
}
@Override protected void setServiceInterface(IBinder binder) { if (binder == null) { // We have lost our service connection. Notify the world that this service is done. // We must notify the adapter before CallsManager. The adapter will force any pending // outgoing calls to try the next service. This needs to happen before CallsManager // tries to clean up any calls still associated with this service. handleConnectionServiceDeath(); mCallsManager.handleConnectionServiceDeath(this); mServiceInterface = null; } else { android.util.Log.d("wds_mo","step45-->Telecom-->ConnectionServiceWrapper.setServiceInterface()"); mServiceInterface = IConnectionService.Stub.asInterface(binder); addConnectionServiceAdapter(mAdapter); } }
private void addConnectionServiceAdapter(IConnectionServiceAdapter adapter) {
if (isServiceValid("addConnectionServiceAdapter")) {
try {
logOutgoing("addConnectionServiceAdapter %s", adapter);
android.util.Log.d("wds_mo","step46-->Telecom-->ConnectionServiceWrapper.addConnectionServiceAdapter()");
mServiceInterface.addConnectionServiceAdapter(adapter);
} catch (RemoteException e) {
}
}
}
返回到43步继续执行,因为4647是并发执行,这里按照Log的顺序来,46执行到48 ,47执行到50,
private void handleSuccessfulConnection() {
android.util.Log.d("wds_mo","step47-->Telecom-->ServiceBinder.handleSuccessfulConnection()");
for (BindCallback callback : mCallbacks) {
callback.onSuccess();
}
mCallbacks.clear();
}
返回到41,如果47步callback.onSuccess() 继续执行
void createConnection(final Call call, final CreateConnectionResponse response) { logOutgoing("createConnection(%s) via %s.", call, getComponentName()); BindCallback callback = new BindCallback() { @Override public void onSuccess() { String callId = mCallIdMapper.getCallId(call); /// M: In some complex scenario, before binding success, the call has been // disconnected. So here pass a null callId to telephony will cause JE. if (callId == null) { Log.w(this, "createConnection stop, callId is null"); return; } mPendingResponses.put(callId, response); GatewayInfo gatewayInfo = call.getGatewayInfo(); Bundle extras = call.getIntentExtras(); if (gatewayInfo != null && gatewayInfo.getGatewayProviderPackageName() != null && gatewayInfo.getOriginalAddress() != null) { extras = (Bundle) extras.clone(); extras.putString( TelecomManager.GATEWAY_PROVIDER_PACKAGE, gatewayInfo.getGatewayProviderPackageName()); extras.putParcelable( TelecomManager.GATEWAY_ORIGINAL_ADDRESS, gatewayInfo.getOriginalAddress()); } Log.event(call, Log.Events.START_CONNECTION, Log.piiHandle(call.getHandle())); try { /// M: For VoLTE @{ boolean isConferenceDial = call.isConferenceDial(); if (isConferenceDial) { logOutgoing("createConference(%s) via %s.", call, getComponentName()); mServiceInterface.createConference( call.getConnectionManagerPhoneAccount(), callId, new ConnectionRequest( call.getTargetPhoneAccount(), call.getHandle(), extras, call.getVideoState()), call.getConferenceParticipants(), call.isIncoming()); } else { android.util.Log.d("wds_mo","step50-->Telecom-->ConnectionServiceWrapper.createConnection().onSuccess"); mServiceInterface.createConnection( call.getConnectionManagerPhoneAccount(), callId, new ConnectionRequest( call.getTargetPhoneAccount(), call.getHandle(), extras, call.getVideoState()), call.isIncoming(), call.isUnknown()); } /// @} .......
46和50 都是IConnectionService.aidl 客服端发送请求到服务端 mServiceInterface
private final IBinder mBinder = new IConnectionService.Stub() { @Override public void addConnectionServiceAdapter(IConnectionServiceAdapter adapter) { android.util.Log.d("wds_mo","step48-->framework/base/Telecom-->ConnectionService.IBinder.addConnectionServiceAdapter()"); mHandler.obtainMessage(MSG_ADD_CONNECTION_SERVICE_ADAPTER, adapter).sendToTarget(); } public void removeConnectionServiceAdapter(IConnectionServiceAdapter adapter) { mHandler.obtainMessage(MSG_REMOVE_CONNECTION_SERVICE_ADAPTER, adapter).sendToTarget(); } @Override public void createConnection( PhoneAccountHandle connectionManagerPhoneAccount, String id, ConnectionRequest request, boolean isIncoming, boolean isUnknown) { SomeArgs args = SomeArgs.obtain(); args.arg1 = connectionManagerPhoneAccount; args.arg2 = id; args.arg3 = request; args.argi1 = isIncoming ? 1 : 0; args.argi2 = isUnknown ? 1 : 0; android.util.Log.d("wds_mo","step52-->framework/base/Telecom-->ConnectionService.IBinder.createConnection()"); mHandler.obtainMessage(MSG_CREATE_CONNECTION, args).sendToTarget(); } .....................
private final Handler mHandler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_ADD_CONNECTION_SERVICE_ADAPTER: android.util.Log.d("wds_mo","step49-->framework/base/Telecom-->handleMessage.MSG_ADD_CONNECTION_SERVICE_ADAPTER"); mAdapter.addAdapter((IConnectionServiceAdapter) msg.obj); onAdapterAttached(); break; case MSG_REMOVE_CONNECTION_SERVICE_ADAPTER: mAdapter.removeAdapter((IConnectionServiceAdapter) msg.obj); break; case MSG_CREATE_CONNECTION: { SomeArgs args = (SomeArgs) msg.obj; try { final PhoneAccountHandle connectionManagerPhoneAccount = (PhoneAccountHandle) args.arg1; final String id = (String) args.arg2; final ConnectionRequest request = (ConnectionRequest) args.arg3; final boolean isIncoming = args.argi1 == 1; final boolean isUnknown = args.argi2 == 1; if (!mAreAccountsInitialized) { Log.d(this, "Enqueueing pre-init request %s", id); mPreInitializationConnectionRequests.add(new Runnable() { @Override public void run() { android.util.Log.d("wds_mo","step53-->framework/base/Telecom-->handleMessage.MSG_CREATE_CONNECTION"); createConnection( connectionManagerPhoneAccount, id, request, isIncoming, isUnknown); } }); } else { createConnection( connectionManagerPhoneAccount, id, request, isIncoming, isUnknown); } } finally { args.recycle(); } break; } .............
继续刚才49步的执行
void addAdapter(IConnectionServiceAdapter adapter) { android.util.Log.d("wds_mo","step51-->framework/base/Telecom-->ConnectionServiceAdapter.addAdapter()"); for (IConnectionServiceAdapter it : mAdapters) { if (it.asBinder() == adapter.asBinder()) { Log.w(this, "Ignoring duplicate adapter addition."); return; } } if (mAdapters.add(adapter)) { try { adapter.asBinder().linkToDeath(this, 0); } catch (RemoteException e) { mAdapters.remove(adapter); } } }
继续执行53步
private void createConnection(
final PhoneAccountHandle callManagerAccount,
final String callId,
final ConnectionRequest request,
boolean isIncoming,
boolean isUnknown) {
Log.d(this, “createConnection, callManagerAccount: %s, callId: %s, request: %s, ” +
“isIncoming: %b, isUnknown: %b”, callManagerAccount, callId, request, isIncoming,
isUnknown);
/// M: ALPS02136977. Prints debug messages for MO. @{ if (!isIncoming) { String callNumber = null; if (request != null && request.getAddress() != null) { callNumber = request.getAddress().getSchemeSpecificPart(); } FormattedLog formattedLog = new FormattedLog.Builder() .setCategory("CC") .setServiceName(getConnectionServiceName()) .setOpType(FormattedLog.OpType.OPERATION) .setActionName("Dial") .setCallNumber(callNumber) .setCallId("") .buildDebugMsg(); if (formattedLog != null) { Log.d(this, formattedLog.toString()); } } /// @} android.util.Log.d("wds_mo","step54-->framework/base/Telecom-->Connection.createConnection()"); Connection connection = isUnknown ? onCreateUnknownConnection(callManagerAccount, request) : isIncoming ? onCreateIncomingConnection(callManagerAccount, request) : onCreateOutgoingConnection(callManagerAccount, request); Log.d(this, "createConnection, connection: %s", connection); if (connection == null) { connection = Connection.createFailedConnection( new DisconnectCause(DisconnectCause.ERROR)); } if (connection.getState() != Connection.STATE_DISCONNECTED) { addConnection(callId, connection); } ........
@Override public Connection onCreateOutgoingConnection( PhoneAccountHandle connectionManagerPhoneAccount, final ConnectionRequest request) { ........... } else { android.util.Log.d("wds_mo","step55-->Telephony-->TelephonyConnectionService.onCreateOutgoingConnection()"); placeOutgoingConnection(connection, phone, request); } return connection; }
private void placeOutgoingConnection( TelephonyConnection connection, Phone phone, ConnectionRequest request) { String number = connection.getAddress().getSchemeSpecificPart(); boolean isEmergencyNumber = PhoneNumberUtils.isLocalEmergencyNumber(this, number); /// M: CC036: [ALPS01794357] Set PhoneAccountHandle for ECC @{ if (isEmergencyNumber) { final PhoneAccountHandle phoneAccountHandle; String phoneIccId = phone.getIccSerialNumber(); int slotId = SubscriptionController.getInstance().getSlotId(phone.getSubId()); if (slotId != SubscriptionManager.INVALID_SIM_SLOT_INDEX) { phoneIccId = !TextUtils.isEmpty(phoneIccId) ? phoneIccId : TelephonyManagerEx.getDefault().getSimSerialNumber(slotId); } if (TextUtils.isEmpty(phoneIccId)) { // If No SIM is inserted, the corresponding IccId will be null, // take phoneId as PhoneAccountHandle::mId which is IccId originally phoneAccountHandle = PhoneUtils.makePstnPhoneAccountHandle( Integer.toString(phone.getPhoneId())); } else { phoneAccountHandle = PhoneUtils.makePstnPhoneAccountHandle(phoneIccId); } Log.d(this, "placeOutgoingConnection, set back account mId: %s, iccId: %s", phoneAccountHandle.getId(), phoneIccId); connection.setAccountHandle(phoneAccountHandle); } /// @} com.android.internal.telephony.Connection originalConnection; try { android.util.Log.d("wds_mo","step56-->Telephony-->TelephonyConnectionService.placeOutgoingConnection()"); originalConnection = phone.dial(number, null, request.getVideoState(), request.getExtras()); } catch (CallStateException e) { ....... }
@Override public Connection dial (String dialString, UUSInfo uusInfo, int videoState, Bundle intentExtras) throws CallStateException { boolean isEmergency = PhoneNumberUtils.isEmergencyNumber(dialString); ImsPhone imsPhone = mImsPhone; ....... if (mSST != null && mSST.mSS.getState() == ServiceState.STATE_OUT_OF_SERVICE && mSST.mSS.getDataRegState() != ServiceState.STATE_IN_SERVICE && !isEmergency) { throw new CallStateException("cannot dial in current state"); } if (LOCAL_DEBUG) Rlog.d(LOG_TAG, "Trying (non-IMS) CS call"); /// M: For 3G VT only @{ //return dialInternal(dialString, null, VideoProfile.STATE_AUDIO_ONLY, intentExtras); Rlog.d("wds_mo","step57-->framework/opt/telephony-->GSMPhone.dial()B"); return dialInternal(dialString, null, videoState, intentExtras); /// @} }
@Override protected Connection dialInternal (String dialString, UUSInfo uusInfo, int videoState, Bundle intentExtras) throws CallStateException { /// M: Ignore stripping for VoLTE SIP uri. @{ String newDialString = dialString; if (!PhoneNumberUtils.isUriNumber(dialString)) { // Need to make sure dialString gets parsed properly newDialString = PhoneNumberUtils.stripSeparators(dialString); } /// @} // handle in-call MMI first if applicable if (handleInCallMmiCommands(newDialString)) { return null; } // Only look at the Network portion for mmi String networkPortion = PhoneNumberUtils.extractNetworkPortionAlt(newDialString); /* M: SS part */ Rlog.d(LOG_TAG, "network portion:" + networkPortion); /* M: SS part end */ GsmMmiCode mmi = GsmMmiCode.newFromDialString(networkPortion, this, mUiccApplication.get()); if (LOCAL_DEBUG) Rlog.d(LOG_TAG, "dialing w/ mmi '" + mmi + "'..."); if (mmi == null) { /// M: For 3G VT only @{ //return mCT.dial(newDialString, uusInfo, intentExtras); if (videoState == VideoProfile.STATE_AUDIO_ONLY) { Rlog.d("wds_mo","step58-->framework/opt/telephony-->GSMPhone.dialInternal()A"); return mCT.dial(newDialString, uusInfo, intentExtras); } else { if (!is3GVTEnabled()) { throw new CallStateException("cannot vtDial for non-3GVT-capable device"); } return mCT.vtDial(newDialString, uusInfo, intentExtras); } /// @} } else if (mmi.isTemporaryModeCLIR()) { /// M: For 3G VT only @{ //return mCT.dial(mmi.mDialingNumber, mmi.getCLIRMode(), uusInfo, intentExtras); if (videoState == VideoProfile.STATE_AUDIO_ONLY) { return mCT.dial(mmi.mDialingNumber, mmi.getCLIRMode(), uusInfo, intentExtras); } else { if (!is3GVTEnabled()) { throw new CallStateException("cannot vtDial for non-3GVT-capable device"); } return mCT.vtDial(mmi.mDialingNumber, mmi.getCLIRMode(), uusInfo, intentExtras); } /// @} } else { /* M: SS part */ Rlog.d(LOG_TAG, "[dial]mPendingMMIs.add(mmi) + " + mmi); /* M: SS part end */ mPendingMMIs.add(mmi); mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null)); mmi.processCode(); // FIXME should this return null or something else? return null; } }
synchronized Connection dial (String dialString, int clirMode, UUSInfo uusInfo, Bundle intentExtras) throws CallStateException { // note that this triggers call state changed notif clearDisconnected(); if (!canDial()) { throw new CallStateException("cannot dial in current state"); } String origNumber = dialString; dialString = convertNumberIfNecessary(mPhone, dialString); // The new call must be assigned to the foreground call. // That call must be idle, so place anything that's // there on hold if (mForegroundCall.getState() == GsmCall.State.ACTIVE) { // this will probably be done by the radio anyway // but the dial might fail before this happens // and we need to make sure the foreground call is clear // for the newly dialed connection /// M: CC015: CRSS special handling @{ mWaitingForHoldRequest.set(); /// @} switchWaitingOrHoldingAndActive(); // This is a hack to delay DIAL so that it is sent out to RIL only after // EVENT_SWITCH_RESULT is received. We've seen failures when adding a new call to // multi-way conference calls due to DIAL being sent out before SWITCH is processed try { Thread.sleep(500); } catch (InterruptedException e) { // do nothing } // Fake local state so that // a) foregroundCall is empty for the newly dialed connection // b) hasNonHangupStateChanged remains false in the // next poll, so that we don't clear a failed dialing call fakeHoldForegroundBeforeDial(); } if (mForegroundCall.getState() != GsmCall.State.IDLE) { //we should have failed in !canDial() above before we get here throw new CallStateException("cannot dial in current state"); } mPendingMO = new GsmConnection(mPhone.getContext(), checkForTestEmergencyNumber(dialString), this, mForegroundCall); mHangupPendingMO = false; if ( mPendingMO.getAddress() == null || mPendingMO.getAddress().length() == 0 || mPendingMO.getAddress().indexOf(PhoneNumberUtils.WILD) >= 0 ) { // Phone number is invalid mPendingMO.mCause = DisconnectCause.INVALID_NUMBER; /// M: CC015: CRSS special handling @{ mWaitingForHoldRequest.reset(); /// @} // handlePollCalls() will notice this call not present // and will mark it as dropped. pollCallsWhenSafe(); } else { // Always unmute when initiating a new call setMute(false); /// M: CC015: CRSS special handling @{ if (!mWaitingForHoldRequest.isWaiting()) { /// M: CC010: Add RIL interface @{ /// M: ECC Retry @{ if (PhoneNumberUtils.isEmergencyNumber(mPhone.getSubId(), dialString) /// @} && !PhoneNumberUtils.isSpecialEmergencyNumber(dialString)) { int serviceCategory = PhoneNumberUtils.getServiceCategoryFromEccBySubId( dialString, mPhone.getSubId()); mCi.setEccServiceCategory(serviceCategory); mCi.emergencyDial(mPendingMO.getAddress(), clirMode, uusInfo, obtainCompleteMessage(EVENT_DIAL_CALL_RESULT)); /// @} } else { Rlog.d("wds_mo","step59-->framework/opt/telephony-->GsmCallTracker.dial()"); mCi.dial(mPendingMO.getAddress(), clirMode, uusInfo, obtainCompleteMessage(EVENT_DIAL_CALL_RESULT)); } } else { mWaitingForHoldRequest.set(mPendingMO.getAddress(), clirMode, uusInfo); } /// @} } if (mNumberConverted) { mPendingMO.setConverted(origNumber); mNumberConverted = false; } updatePhoneState(); mPhone.notifyPreciseCallStateChanged(); return mPendingMO; }
@Override public void dial(String address, int clirMode, UUSInfo uusInfo, Message result) { Rlog.d("wds_mo","step60-->framework/opt/telephony-->RIL.dial() "); if (!PhoneNumberUtils.isUriNumber(address)) { RILRequest rr = RILRequest.obtain(RIL_REQUEST_DIAL, result); rr.mParcel.writeString(address); rr.mParcel.writeInt(clirMode); if (uusInfo == null) { rr.mParcel.writeInt(0); // UUS information is absent } else { rr.mParcel.writeInt(1); // UUS information is present rr.mParcel.writeInt(uusInfo.getType()); rr.mParcel.writeInt(uusInfo.getDcs()); rr.mParcel.writeByteArray(uusInfo.getUserData()); } if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); send(rr); } else { RILRequest rr = RILRequest.obtain(RIL_REQUEST_DIAL_WITH_SIP_URI, result); rr.mParcel.writeString(address); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); send(rr); } }
继续执行第54步,未执行完的
void handleCreateConnectionComplete(
String id,
ConnectionRequest request,
ParcelableConnection connection) {
android.util.Log.d("wds_mo","step60-->Telephony-->ConnectionServiceAdapter.handleCreateConnectionComplete()");
for (IConnectionServiceAdapter adapter : mAdapters) {
try {
adapter.handleCreateConnectionComplete(id, request, connection);
} catch (RemoteException e) {
}
}
}
private final class Adapter extends IConnectionServiceAdapter.Stub { @Override public void handleCreateConnectionComplete( String callId, ConnectionRequest request, ParcelableConnection connection) { long token = Binder.clearCallingIdentity(); try { synchronized (mLock) { /// M: for log parser @{ String number = ""; String action = ""; Uri uri = connection.getHandle(); if (uri != null) { number = uri.getSchemeSpecificPart(); } Call call = mCallIdMapper.getCall(callId); if (call != null) { if (call.isIncoming()) { action = LogUtils.NOTIFY_ACTION_CREATE_MT_SUCCESS; } else if (!call.isUnknown()) { action = LogUtils.NOTIFY_ACTION_CREATE_MO_SUCCESS; } } LogUtils.logCcNotify(number, action, callId, connection.toString()); /// @} logIncoming("handleCreateConnectionComplete %s", callId); if (mCallIdMapper.isValidCallId(callId)) { android.util.Log.d("wds_mo","step61-->Telecom-->ConnectionServiceWrapper.Adapter.handleCreateConnectionComplete()"); ConnectionServiceWrapper.this .handleCreateConnectionComplete(callId, request, connection); } } } finally { Binder.restoreCallingIdentity(token); } } ...........
private void handleCreateConnectionComplete( String callId, ConnectionRequest request, ParcelableConnection connection) { // TODO: Note we are not using parameter "request", which is a side effect of our tacit // assumption that we have at most one outgoing connection attempt per ConnectionService. // This may not continue to be the case. if (connection.getState() == Connection.STATE_DISCONNECTED) { // A connection that begins in the DISCONNECTED state is an indication of // failure to connect; we handle all failures uniformly removeCall(callId, connection.getDisconnectCause()); } else { // Successful connection if (mPendingResponses.containsKey(callId)) { String num = connection.getHandle().getSchemeSpecificPart(); /// M: add for CMCC L + C ecc retry if (PhoneNumberUtils.isEmergencyNumber(num)) { mPendingResponses.get(callId). handleCreateConnectionSuccess(mCallIdMapper, connection); } else { android.util.Log.d("wds_mo","step62-->Telecom-->ConnectionServiceWrapper.handleCreateConnectionComplete"); mPendingResponses.remove(callId) .handleCreateConnectionSuccess(mCallIdMapper, connection); } } } }
@Override public void handleCreateConnectionSuccess( CallIdMapper idMapper, ParcelableConnection connection) { Log.v(this, "handleCreateConnectionSuccessful %s", connection); setTargetPhoneAccount(connection.getPhoneAccount()); setHandle(connection.getHandle(), connection.getHandlePresentation()); setCallerDisplayName( connection.getCallerDisplayName(), connection.getCallerDisplayNamePresentation()); setConnectionCapabilities(connection.getConnectionCapabilities()); setVideoProvider(connection.getVideoProvider()); setVideoState(connection.getVideoState()); setRingbackRequested(connection.isRingbackRequested()); setIsVoipAudioMode(connection.getIsVoipAudioMode()); setStatusHints(connection.getStatusHints()); setExtras(connection.getExtras()); mConferenceableCalls.clear(); for (String id : connection.getConferenceableConnectionIds()) { mConferenceableCalls.add(idMapper.getCall(id)); } if (mIsUnknown) { for (Listener l : mListeners) { l.onSuccessfulUnknownCall(this, getStateFromConnectionState(connection.getState())); } } else if (mIsIncoming) { // We do not handle incoming calls immediately when they are verified by the connection // service. We allow the caller-info-query code to execute first so that we can read the // direct-to-voicemail property before deciding if we want to show the incoming call to // the user or if we want to reject the call. mDirectToVoicemailQueryPending = true; // Timeout the direct-to-voicemail lookup execution so that we dont wait too long before // showing the user the incoming call screen. mHandler.postDelayed(mDirectToVoicemailRunnable, Timeouts.getDirectToVoicemailMillis( mContext.getContentResolver())); } else { /// M: ALPS02568075 @{ // when perform ECC retry from dialing state // force to set as CONNECTING this time // in order to reset audio mode as normal in CallAudioManager.onCallStateChanged // then Ecc is changed to dialing again, can set audio mode once time. android.util.Log.d("wds_mo","step63-->Telecom-->Call.handleCreateConnectionSuccess()"); if (isEmergencyCall() && getState() == CallState.DIALING) { Log.v(this, "Change ecc state as connecting"); for (Listener l : mListeners) { l.onSuccessfulOutgoingCall(this, CallState.CONNECTING); } } /// @} for (Listener l : mListeners) { l.onSuccessfulOutgoingCall(this, getStateFromConnectionState(connection.getState())); } } }
@Override public void onSuccessfulOutgoingCall(Call call, int callState) { Log.v(this, "onSuccessfulOutgoingCall, %s", call); setCallState(call, callState, "successful outgoing call"); if (!mCalls.contains(call)) { // Call was not added previously in startOutgoingCall due to it being a potential MMI // code, so add it now. /// M: If already exist other calls, should handle properly. @{ // original google code: //addCall(call); handleShouldAddOutgoingCall(call); /// @} } else { // M: Temp solution for ALPS02548133. handleCallsWhenOutgoingSuccess(call); } // The call's ConnectionService has been updated. for (CallsManagerListener listener : mListeners) { listener.onConnectionServiceChanged(call, null, call.getConnectionService()); } //ALPS01781841, do not mark Ecc call as dialing state this time point //Ecc call is marked as dialing state only when FWK call state event(MSG_SET_DIALING) post to ConnectionServiceWrapper.Adapter android.util.Log.d("wds_mo","step64-->Telecom-->CallsManager.onSuccessfulOutgoingCall()"); if (!call.isEmergencyCall()) { markCallAsDialing(call); } }
private void setCallState(Call call, int newState, String tag) { if (call == null) { return; } int oldState = call.getState(); Log.i(this, "setCallState %s -> %s, call: %s", CallState.toString(oldState), CallState.toString(newState), call); if (newState != oldState) { // Unfortunately, in the telephony world the radio is king. So if the call notifies // us that the call is in a particular state, we allow it even if it doesn't make // sense (e.g., STATE_ACTIVE -> STATE_RINGING). // TODO: Consider putting a stop to the above and turning CallState // into a well-defined state machine. // TODO: Define expected state transitions here, and log when an // unexpected transition occurs. call.setState(newState, tag); /// M: Set the voice recording capability int capabilities = call.getConnectionCapabilities(); boolean hasRecordCap = (capabilities & Connection.CAPABILITY_VOICE_RECORD) == 0 ? false : true; boolean okToRecord = okToRecordVoice(call); if (okToRecord && !hasRecordCap) { call.setConnectionCapabilities(capabilities | Connection.CAPABILITY_VOICE_RECORD); } if (!okToRecord && hasRecordCap) { PhoneRecorderHandler.getInstance().stopVoiceRecordIfNecessary(call); call.setConnectionCapabilities(capabilities & ~Connection.CAPABILITY_VOICE_RECORD); } Trace.beginSection("onCallStateChanged"); // Only broadcast state change for calls that are being tracked. android.util.Log.d("wds_mo","step66-->Telecom-->CallsManager.setCallState()"); if (mCalls.contains(call)) { for (CallsManagerListener listener : mListeners) { if (Log.SYSTRACE_DEBUG) { Trace.beginSection(listener.getClass().toString() + " onCallStateChanged"); } listener.onCallStateChanged(call, oldState, newState); if (Log.SYSTRACE_DEBUG) { Trace.endSection(); } } updateCallsManagerState(); } /// M: MSMA call control, first call action finished. @{ handleActionProcessComplete(call); /// @} Trace.endSection(); } }
@Override
public void onCallStateChanged(Call call, int oldState, int newState) {
android.util.Log.d("wds_mo","step67-->Telecom-->InCallController.onCallStateChanged()");
updateCall(call);
}
private void updateCall(Call call, boolean videoProviderChanged) { if (!mInCallServices.isEmpty()) { ParcelableCall parcelableCall = toParcelableCall(call, videoProviderChanged /* includeVideoProvider */); Log.i(this, "Sending updateCall %s ==> %s", call, parcelableCall); List<ComponentName> componentsUpdated = new ArrayList<>(); android.util.Log.d("wds_mo","step69-->Telecom-->InCallController.updateCall()"); for (Map.Entry<ComponentName, IInCallService> entry : mInCallServices.entrySet()) { ComponentName componentName = entry.getKey(); IInCallService inCallService = entry.getValue(); componentsUpdated.add(componentName); try { inCallService.updateCall(parcelableCall); } catch (RemoteException ignored) { } } Log.i(this, "Components updated: %s", componentsUpdated); } }
private final class InCallServiceBinder extends IInCallService.Stub {
.......
@Override
public void updateCall(ParcelableCall call) {
android.util.Log.d("wds_mo","step70-->framework/base/Telecom-->InCallService.InCallServiceBinder.updateCall()");
mHandler.obtainMessage(MSG_UPDATE_CALL, call).sendToTarget();
}
.....
@Override public void handleMessage(Message msg) { /// M: [log optimize]for performance debugging. mMessageAnalyzer.onStartHandleMessage(msg); if (mPhone == null && msg.what != MSG_SET_IN_CALL_ADAPTER) { /// M: [log optimize]for performance debugging. mMessageAnalyzer.onMessageHandled(msg); return; } SomeArgs args; switch (msg.what) { .... case MSG_UPDATE_CALL: android.util.Log.d("wds_mo","step71-->framework/base/Telecom-->InCallService.handleMessage_MSG_UPDATE_CALL"); TelecomTrace.begin("InCallService_update"); mPhone.internalUpdateCall((ParcelableCall) msg.obj); TelecomTrace.end("InCallService_update"); break; ...
final void internalUpdateCall(ParcelableCall parcelableCall) {
Call call = mCallByTelecomCallId.get(parcelableCall.getId());
if (call != null) {
checkCallTree(parcelableCall);
android.util.Log.d("wds_mo","step72-->framework/base/Telecom-->Phone.internalUpdateCall");
call.internalUpdate(parcelableCall, mCallByTelecomCallId);
}
}
/** {@hide} */
final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) {
// First, we update the internal state as far as possible before firing any updates.
.........
if (stateChanged) {
android.util.Log.d("wds_mo","step73-->framework/base/Telecom-->Call.internalUpdate()");
fireStateChanged(mState);
}
.............
}
private void fireStateChanged(final int newState) {
android.util.Log.d("wds_mo","step74-->framework/base/Telecom-->Call.fireStateChanged()");
for (CallbackRecord<Callback> record : mCallbackRecords) {
final Call call = this;
final Callback callback = record.getCallback();
record.getHandler().post(new Runnable() {
@Override
public void run() {
callback.onStateChanged(call, newState);
}
});
}
}
private android.telecom.Call.Callback mTelecomCallCallback =
new android.telecom.Call.Callback() {
@Override
public void onStateChanged(android.telecom.Call call, int newState) {
Log.d(this, "TelecommCallCallback onStateChanged call=" + call + " newState="
+ newState);
android.util.Log.d("wds_mo","step75-->InCallUI-->Call.mTelecomCallCallback.onStateChanged()");
InCallTrace.begin("telecomStateChanged");
update();
InCallTrace.end("telecomStateChanged");
}
.....
private void update() { Trace.beginSection("Update"); int oldState = getState(); updateFromTelecommCall(); if (oldState != getState() && getState() == Call.State.DISCONNECTED) { /// M: [log optimize] Log.notify(this, Log.CcNotifyAction.DISCONNECTED, mDisconnectCause == null ? "DisconnectCause: null" : mDisconnectCause.toString()); CallList.getInstance().onDisconnect(this); } else { android.util.Log.d("wds_mo","step76-->InCallUI-->Call.update()"); CallList.getInstance().onUpdate(this); } Trace.endSection(); }
之后与33步重合
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。