首页 热点专区 小学知识 中学知识 出国留学 考研考公
您的当前位置:首页正文

android 6.0 InCallService

2024-12-16 来源:要发发知识网

总结

InCallService是UI和telecom的桥梁。通过InCallService来完成各种call的更新与操作。

启动

CallsManager在生成新的Call实例后,会通过回调InCallController的onCallAdded函数,这个时候如果InCallService没有被启动,InCallController会去启动InCallService,如果已经绑定了,那么直接调用incallService的addCall函数。
即,所有CallsManager的回调,最后都调到InCallService的相关函数来处理。

@Override
public void onCallAdded(Call call) {
    if (!isBoundToServices()) {
        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) {
            }
        }
    }
}   

下面直接看一下,启动完成后,在onConnected函数中,做了什么

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 {
        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();
}
  1. 通过inCallService的setInCallAdapter设置了和InCallService双向通信的binder接口。
  2. 这个时候要是还有没出来的call,调用incallService.addCall

双向操作

可以看到InCallAdapter也是个IInCallAdapter的服务端实现(frameworks/base/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl)

   class InCallAdapter extends IInCallAdapter.Stub {
       private final CallsManager mCallsManager;
       private final CallIdMapper mCallIdMapper;
       private final TelecomSystem.SyncRoot mLock;
   ....

InCallServiceImpl(packages/apps/InCallUI/src/com/android/incallui/InCallServiceImpl.java)继承了InCallService,所以最后最后启动了InCallServiceImpl。

当用户操作的时候,通过InCallAdapter对象来通知telecom(最终是调用CallsManager相关函数),当底层状态变化(也是通过CallsManager调用InCallController的回调,最后调到InCallService),用InCallService来让上层更新相关状态。

所以,分层来看InCallService连接上下,操作的角度CallsManager承上启下。

显示全文