Android Dialer源码分析之去电流程

Android的拨号流程,从拨号盘的点击拨号按钮开始,
DialpadFragment.java

  @Override
  public void onClick(View view) {
    int resId = view.getId();
    if (resId == R.id.dialpad_floating_action_button) {
      view.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
      handleDialButtonPressed();
    } 
    ....
  }
private void handleDialButtonPressed() {
	...
	final String number = digits.getText().toString();
	...
    PreCall.start(getContext(), new CallIntentBuilder(number, CallInitiationType.Type.DIALPAD));
    ...
  }
  static void start(Context context, CallIntentBuilder builder) {
    DialerUtils.startActivityWithErrorToast(context, getIntent(context, builder));
  }
  public static void startActivityWithErrorToast(Context context, Intent intent) {
	...	
    startActivityWithErrorToast(context, intent, R.string.activity_not_available);
  }
public static void startActivityWithErrorToast(
      final Context context, final Intent intent, int msgId) {
    try {
      if ((Intent.ACTION_CALL.equals(intent.getAction()))) {
        Point touchPoint = TouchPointManager.getInstance().getPoint();
        if (touchPoint.x != 0 || touchPoint.y != 0) {
          Bundle extras;
          if (intent.hasExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS)) {
            extras = intent.getParcelableExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS);
          } else {
            extras = new Bundle();
          }
          extras.putParcelable(TouchPointManager.TOUCH_POINT, touchPoint);
          intent.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, extras);
        }
		...
        placeCallOrMakeToast(context, intent);
        ...
      } else {
        context.startActivity(intent);
      }
    } catch (ActivityNotFoundException e) {
      Toast.makeText(context, msgId, Toast.LENGTH_SHORT).show();
    }
  }
  private static void placeCallOrMakeToast(Context context, Intent intent) {
    ExtensionManager.getDialerOthersExtension().setPrecallInfo(context, intent);
    final boolean hasCallPermission = TelecomUtil.placeCall(context, intent);
    if (!hasCallPermission) {
      Toast.makeText(context, "Cannot place call without Phone permission", Toast.LENGTH_SHORT)
          .show();
    }
  }

TelecomUtil.java

  public static boolean placeCall(Context context, Intent intent) {
    if (hasCallPhonePermission(context)) {
      getTelecomManager(context).placeCall(intent.getData(), intent.getExtras());
      return true;
    }
    return false;
  }

TelecomManager.java

public void placeCall(Uri address, Bundle extras) {
    ITelecomService service = getTelecomService();
    if (service != null) {
	    ...
        try {
            service.placeCall(address, extras == null ? new Bundle() : extras,
                    mContext.getOpPackageName(), mContext.getAttributionTag());
        } catch (RemoteException e) {
            Log.e(TAG, "Error calling ITelecomService#placeCall", e);
        }
    }
}

TelecomServiceImpl.java

@Override
public void placeCall(Uri handle, Bundle extras, String callingPackage,
        String callingFeatureId) {
		...

        mUserCallIntentProcessorFactory.create(mContext, userHandle)
                .processIntent(
                        intent, callingPackage, isSelfManaged ||
                                (hasCallAppOp && hasCallPermission),
                        true /* isLocalInvocation */);
       ...               
}

UserCallIntentProcessor.java

public void processIntent(Intent intent, String callingPackageName,
            boolean canCallNonEmergency, boolean isLocalInvocation) {
        ...
        String action = intent.getAction();
        if (Intent.ACTION_CALL.equals(action) ||
                Intent.ACTION_CALL_PRIVILEGED.equals(action) ||
                Intent.ACTION_CALL_EMERGENCY.equals(action)) {
            processOutgoingCallIntent(intent, callingPackageName, canCallNonEmergency,
                    isLocalInvocation);
        }
        ...
    }
private void processOutgoingCallIntent(Intent intent, String callingPackageName,
            boolean canCallNonEmergency, boolean isLocalInvocation) {
        ...
        sendIntentToDestination(intent, isLocalInvocation, callingPackageName);
    }

private boolean sendIntentToDestination(Intent intent, boolean isLocalInvocation,
            String callingPackage) {
    ...
    TelecomManager tm = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
    tm.handleCallIntent(intent, callingPackage);
    ...
}

public void handleCallIntent(Intent intent, String callingPackageProxy) {
	...
    getTelecomService().handleCallIntent(intent, callingPackageProxy);
    ...
}

TelecomServiceImpl.java

@Override
public void handleCallIntent(Intent intent, String callingPackage) {
	...
    mCallIntentProcessorAdapter.processOutgoingCallIntent(mContext,
            mCallsManager, intent, callingPackage);
	...
}
@Override
public void processOutgoingCallIntent(Context context, CallsManager callsManager,
        Intent intent, String callingPackage) {
    CallIntentProcessor.processOutgoingCallIntent(context, callsManager, intent,
            callingPackage, mDefaultDialerCache);
}
static void processOutgoingCallIntent(
            Context context,
            CallsManager callsManager,
            Intent intent,
            String callingPackage,
            DefaultDialerCache defaultDialerCache) {
        ...
        CompletableFuture<Call> callFuture = callsManager
                .startOutgoingCall(handle, phoneAccountHandle, clientExtras, initiatingUser,
                        intent, callingPackage);

		...
    }

CallsManager.java

  public CompletableFuture<Call> startOutgoingCall(Uri handle,
          PhoneAccountHandle requestedAccountHandle,
          Bundle extras, UserHandle initiatingUser, Intent originalIntent,
          String callingPackage) {
		...
      return startOutgoingCall(callee, requestedAccountHandle, extras, initiatingUser,
              originalIntent, callingPackage, false);
  }

private CompletableFuture<Call> startOutgoingCall(List<Uri> participants,
        PhoneAccountHandle requestedAccountHandle,
        Bundle extras, UserHandle initiatingUser, Intent originalIntent,
        String callingPackage, boolean isConference) {
        ...
        call = new Call(.....)
        ...
        addCall(callToPlace);
        ...
****
```java
@VisibleForTesting
public void addCall(Call call) {
  	...
   call.addListener(this);
   mCalls.add(call);

   // Specifies the time telecom finished routing the call. This is used by the dialer for
   // analytics.
   Bundle extras = call.getIntentExtras();
   extras.putLong(TelecomManager.EXTRA_CALL_TELECOM_ROUTING_END_TIME_MILLIS,
           SystemClock.elapsedRealtime());

   updateCanAddCall();
   updateHasActiveRttCall();
   updateExternalCallCanPullSupport();
   // onCallAdded for calls which immediately take the foreground (like the first call).
   for (CallsManagerListener listener : mListeners) {
   		...
       listener.onCallAdded(call);
		...
   }
	...
}

InCallController.java

@Override
    public void onCallAdded(Call call) {
    	...
       addCall(call);
		...
		IInCallService inCallService = entry.getValue();
       inCallService.addCall(sanitizeParcelableCallForService(info, parcelableCall));
		...
    }

InCallServiceBinder

@Override
public void addCall(ParcelableCall call) {
    mHandler.obtainMessage(MSG_ADD_CALL, call).sendToTarget();
}

InCallService.java

case MSG_ADD_CALL:
    mPhone.internalAddCall((ParcelableCall) msg.obj);
    break;

final void internalAddCall(ParcelableCall parcelableCall) {
	...
    call.internalUpdate(parcelableCall, mCallByTelecomCallId);
    ...
}

final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) {
	...
	if (stateChanged) {
       fireStateChanged(mState);
    }
    if (detailsChanged) {
       fireDetailsChanged(mDetails);
    }
	...
}

private void fireStateChanged(final int newState) {
    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);
            }
        });
    }
}

DialerCall.java

@Override
public void onStateChanged(Call call, int newState) {
	...
  stateUpdate();
  	...
}
private void stateUpdate() {
    ...
   for (DialerCallListener listener : listeners) {
     listener.onDialerCallUpdate();
   }
	...
  }

DialerCallListenerImpl

@Override
public void onDialerCallUpdate() {
  Trace.beginSection("CallList.onDialerCallUpdate");
  onUpdateCall(call);
  notifyGenericListeners();
  Trace.endSection();
}

private void notifyGenericListeners() {
  for (Listener listener : listeners) {
    listener.onCallListChange(this);
  }
}

InCallPresenter.java

  @Override
  public void onCallListChange(CallList callList) {
  	...
	newState = startOrFinishUi(newState);
	...
  }

private InCallState startOrFinishUi(InCallState newState) {
	...
	showInCall(...)
	...
}

  public void showInCall(boolean showDialpad, boolean newOutgoingCall) {
    LogUtil.i("InCallPresenter.showInCall", "Showing InCallActivity");
    context.startActivity(
        InCallActivity.getIntent(context, showDialpad, newOutgoingCall, false));
  }

至此,InCallActivity将会启动到并显示UI


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值