我们先看下7.0启动InCallActivity时序图:
android incall UI启动流程.png还记得上篇讲的*号标记的地方么,对CallIntentProcessor里调用CallsManager的startOutgoingCall方法,我们从这里开始分析:
// Send to CallsManager to ensure the InCallUI gets kicked off before the broadcast returns
Call call = callsManager.startOutgoingCall(handle, phoneAccountHandle, clientExtras, initiatingUser);
- packages/services/Telecomm – CallsManager
if (!mCalls.contains(call) && mPendingMOEmerCall == null) {
// We check if mCalls already contains the call because we could potentially be reusing
// a call which was previously added (See {@link #reuseOutgoingCall}).
addCall(call);
}
去寻找监听CallsManagerListener的onCallAdded方法:
private void addCall(Call call) {
for (CallsManagerListener listener : mListeners) {
listener.onCallAdded(call);
}
}
- packages/services/Telecomm – InCallController
@Override
public void onCallAdded(Call call) {
if (!isBoundToServices()) {
bindToServices(call);
}
}
来看关键代码,绑定InCallService:
Intent intent = new Intent(InCallService.SERVICE_INTERFACE);
intent.setComponent(mInCallServiceInfo.getComponentName());
if (call != null && !call.isIncoming() && !call.isExternalCall()){
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 InCall %s, with %s", mInCallServiceInfo, intent);
mIsConnected = true;
if (!mContext.bindServiceAsUser(intent, mServiceConnection,
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE |
Context.BIND_ABOVE_CLIENT,
UserHandle.CURRENT)) {
Log.w(this, "Failed to connect.");
mIsConnected = false;
}
查看mServiceConnection的onServiceConnected方法:
private class InCallServiceBindingConnection extends InCallServiceConnection {
private final ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
synchronized (mLock) {
try {
mIsBound = true;
if (mIsConnected) {
// Only proceed if we are supposed to be connected.
onConnected(service);
}
}
}
}
onConnected方法:
protected void onConnected(IBinder service) {
boolean shouldRemainConnected =
InCallController.this.onConnected(mInCallServiceInfo, service);
}
先找到aidl IInCallService对应的接收端,并找到方法addCall:
private boolean onConnected(InCallServiceInfo info, IBinder service) {
IInCallService inCallService = IInCallService.Stub.asInterface(service);
mInCallServices.put(info, inCallService);
try {
inCallService.setInCallAdapter(
new InCallAdapter(
mCallsManager,
mCallIdMapper,
mLock,
info.getComponentName().getPackageName()));
}
for (Call call : calls) {
try {
// Track the call if we don't already know about it.
addCall(call);
numCallsSent += 1;
inCallService.addCall(ParcelableCallUtils.toParcelableCall(
call,
true /* includeVideoProvider */,
mCallsManager.getPhoneAccountRegistrar(),
info.isExternalCallsSupported()));
} catch (RemoteException ignored) {
}
}
- packages/services/Telecomm – InCallService
private final class InCallServiceBinder extends IInCallService.Stub {
@Override
public void addCall(ParcelableCall call) {
mHandler.obtainMessage(MSG_ADD_CALL, call).sendToTarget();
}
- frameworks/base/telecomm -- Phone
去找监听的代码,找到onCallAdded方法:
private void fireCallAdded(Call call) {
for (Listener listener : mListeners) {
listener.onCallAdded(this, call);
}
}
- packages/services/Telecomm – InCallService
绕了一下,又回到了InCallService,并去寻找InCallService的子类:
private Phone.Listener mPhoneListener = new Phone.Listener() {
/** ${inheritDoc} */
@Override
public void onCallAdded(Phone phone, Call call) {
InCallService.this.onCallAdded(call);
}
- packages/app/Dialer – InCallServiceImpl
InCallServiceImpl extends InCallService
@Override
public void onCallAdded(Call call) {
InCallPresenter.getInstance().onCallAdded(call);
}
- packages/app/Dialer – InCallPresenter
public void onCallAdded(final android.telecom.Call call) {
if (shouldAttemptBlocking(call)) {
maybeBlockCall(call);
} else {
mCallList.onCallAdded(call);
}
}
- packages/app/Dialer – CallList
需要找到实现监听implements CallList.Listener,实现方法onCallListChange的地方:
private void notifyGenericListeners() {
for (Listener listener : mListeners) {
listener.onCallListChange(this);
}
}
- packages/app/Dialer – InCallPresenter
startOrFinishUi
public void onCallListChange(CallList callList) {
InCallState newState = getPotentialStateFromCallList(callList);
InCallState oldState = mInCallState;
newState = startOrFinishUi(newState);
启动InCallActivity:
public void showInCall(final boolean showDialpad, final boolean newOutgoingCall) {
Log.i(this, "Showing InCallActivity");
mContext.startActivity(getInCallIntent(showDialpad, newOutgoingCall));
}
到这为止,呼出InCallActivity启动的流程基本结束了。
网友评论