挂断界面流程分析

3,挂断界面分析

无论数本地主动挂断还是远程挂断,最后都会finish通话界面。

在远程挂点电话流程分析已论述, CallsManager的setCallState方法会更新界面,在此就是finish通话界面。

同样的,消息流也会从services telecom走到InCallUI。

3.1 services telecom

CallsManager的setCallState方法调用流程图如下,

挂断界面流程分析_第1张图片

CallsManager的setCallState方法中有关电话挂断的代码如下,

listener.onCallStateChanged(call, oldState, newState);

在InCallController方法中,比较多的方法会调用updateCall方法,该方法如下,

for (Map.Entry entry : mInCallServices.entrySet()) {
    ComponentName componentName = entry.getKey();
    IInCallService inCallService = entry.getValue();
    componentsUpdated.add(componentName);
    try {
       inCallService.updateCall(parcelableCall);
    } catch (RemoteException ignored) {
    }
}

IinCallService指向的是dialer进程中的是InCallService的内部类InCallServiceBinder。

3.2 InCallUI

InCallService的内部类InCallServiceBinder的updateCall方法如下,

public void updateCall(ParcelableCall call) {
     mHandler.obtainMessage(MSG_UPDATE_CALL, call).sendToTarget();
}

mHandler变量的handleMessage方法对MSG_UPDATE_CALL消息处理如下,

case MSG_UPDATE_CALL:
    mPhone.internalUpdateCall((ParcelableCall) msg.obj);
    break;

Phone的internalUpdateCall方法调用流程图如下,

挂断界面流程分析_第2张图片

Phone的internalUpdateCall方法如下,

final void internalUpdateCall(ParcelableCall parcelableCall) {
    Call call = mCallByTelecomCallId.get(parcelableCall.getId());
    if (call != null) {
         checkCallTree(parcelableCall);
         call.internalUpdate(parcelableCall, mCallByTelecomCallId);
    }
}

Call的fireStateChanged方法如下,

private void fireStateChanged(final int newState) {
    for (CallbackRecord record : mCallbackRecords) {
          final Call call = this;
          final Callback callback = record.getCallback();
          record.getHandler().post(new Runnable() {
              @Override
              public void run() {
                  callback.onStateChanged(call, newState);
              }
         });
    }
}

mCallbackRecordslist中保存了回调的CallbackRecord对象,

是在registerCallback方法中注册的,

public void registerCallback(Callback callback, Handler handler) {
      unregisterCallback(callback);
      // Don't allow new callback registration if the call is already being destroyed.
      if (callback != null && handler != null && mState != STATE_DISCONNECTED) {
          mCallbackRecords.add(new CallbackRecord(callback, handler));
      }
}

在InCallUI的Call.java中的构造方法中,会调用Telecom Call的registerCallback进行注册,

public Call(android.telecom.Call telecommCall) {
     mTelecommCall = telecommCall;
     mId = ID_PREFIX + Integer.toString(sIdCounter++);

     updateFromTelecommCall();
     mTelecommCall.registerCallback(mTelecomCallCallback);
}

注意, Telecom Call是services telecom对外提供的接口,phone系统中有好几个名为Call的类,当然,还有一些其他的同名类,

看代码时千万不要混淆。

mTelecomCallCallback变量的onStateChanged方法如下,

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);
            update();
        }
•••

mTelecomCallCallback变量的大部分方法都会调用update方法,

update方法如下,

private void update() {
     Trace.beginSection("Update");
     int oldState = getState();
     updateFromTelecommCall();
     if (oldState != getState() && getState() == Call.State.DISCONNECTED) {
         CallList.getInstance().onDisconnect(this);
         /* Disconnect the QTI IMS service */
         mQtiImsInterfaceImpl.stopQtiImsInterface();
     } else {
         CallList.getInstance().onUpdate(this);
     }
     Trace.endSection();
}

在很多情况下会更新call,

如果当前的状态是断开(DISCONNECTED),那就调用CallList的onDisconnect方法;

其他情况下,例如远程接听,会调用CallList的onUpdate方法。

在此,接听的更新就不论述了,和onDisconnect方法调用流程几乎相同。

CallList的onDisconnect方法如下,

public void onDisconnect(Call call) {
     if (updateCallInMap(call)) {
         Log.i(this, "onDisconnect: " + call);
         // notify those listening for changes on this specific change
         notifyCallUpdateListeners(call);
         // notify those listening for all disconnects
         notifyListenersOfDisconnect(call);
    }
}

notifyListenersOfDisconnect方法如下,

private void notifyListenersOfDisconnect(Call call) {
     for (Listener listener : mListeners) {
         listener.onDisconnect(call);
     }
}

InCallPresenter的onDisconnect方法如下,

public void onDisconnect(Call call) {
     maybeShowErrorDialogOnDisconnect(call);

     // We need to do the run the same code as onCallListChange.
     onCallListChange(mCallList);// finish activity

     if (isActivityStarted()) {
         mInCallActivity.dismissKeyguard(false);
     }
     wakeUpScreen();//屏幕唤醒
}

InCallPresenter的attemptFinishActivity方法如下,

if (doFinish) {
   mInCallActivity.setExcludeFromRecents(true);
   mInCallActivity.finish();

直接调用InCallActivity的finish方法。

这样,通话界面就finish了。整个通话过程也结束了。

另外,在InCallPresenter 的onCallListChange方法中,调用startOrFinishUi方法之后,

for (InCallStateListener listener : mListeners) {
     Log.d(this, "Notify " + listener + " of state " + mInCallState.toString());
     listener.onStateChange(oldState, mInCallState, callList);
}

会调用监听器的onStateChange方法,和来电时的onIncomingCall 监听方法类似,

VideoCallPresenter/CallCardPresenter/CallButtonPresenter等会实现onStateChange方法,更新界面。

你可能感兴趣的:(---【phone分析】)