call对象
packages/services/Telecomm/src/com/android/server/telecom/Call.java
frameworks/base/telecomm/java/android/telecom/Call.java
packages/apps/InCallUI/src/com/android/incallui/Call.java
frameworks/opt/telephony/src/java/com/android/internal/telephony/Call.java
在不同包内的call的功能应该是不同的,但是它们标识的应该同一个call。那么这种一一对应的关系是怎么建立起来的?
packages/services/Telecomm/src/com/android/server/telecom/Call.java 首先被建立
代码在packages/services/Telecomm/src/com/android/server/telecom/CallsManager.java
MO startOutgoingCall, MT processIncomingCallIntent
Call startOutgoingCall(Uri handle, PhoneAccountHandle phoneAccountHandle, Bundle extras)
{...
addCall(call);
return call;
}
/**
* Adds the specified call to the main list of live calls.
*
* @param call The call to add.
*/
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).
for (CallsManagerListener listener : mListeners) {
if (Log.SYSTRACE_DEBUG) {
Trace.beginSection(listener.getClass().toString() + " addCall");
}
listener.onCallAdded(call);// 通知各个Listener
if (Log.SYSTRACE_DEBUG) {
Trace.endSection();
}
}
updateCallsManagerState();//更新状态
Trace.endSection();
}
packages/services/Telecomm/src/com/android/server/telecom/InCallController.java
listener.onCallAdded(call); 通知很多Listener,在构造函数里可以找到。和各个目录的call映射有关系应该是InCallController,看一下它的实现
@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
entry : mInCallServices.entrySet()) {
ComponentName componentName = entry.getKey();
IInCallService inCallService = entry.getValue();
ParcelableCall parcelableCall = toParcelableCall(call,
true /* includeVideoProvider */);
try {
inCallService.addCall(parcelableCall);
} catch (RemoteException ignored) {
}
}
}
}
bindToServices(call);看一下这个函数的注释,代码就不看了。
/**
* Binds to all the UI-providing InCallService as well as system-implemented non-UI
* InCallServices. Method-invoker must check {@link #isBoundToServices()} before invoking.
*
* @param call The newly added call that triggered the binding to the in-call services.
*/
这个函数主要是用来绑定提供打电话界面UI的InCallService,这个InCallService是Framework的类,所以应该可以被很多app重写实现,所以,
绑定服务这个InCallService的时候会绑定很多,包括系统的实现(InCallUI)。
看一下InCallService的注释
frameworks/base/telecomm/java/android/telecom/InCallService.java
/**
* This service is implemented by any app that wishes to provide the user-interface for managing
* phone calls. Telecom binds to this service while there exists a live (active or incoming) call,
* and uses it to notify the in-call app of any live and recently disconnected calls. An app must
* first be set as the default phone app (See {@link TelecomManager#getDefaultDialerPackage()})
* before the telecom service will bind to its {@code InCallService} implementation.
*
* Below is an example manifest registration for an {@code InCallService}. The meta-data
* ({@link TelecomManager#METADATA_IN_CALL_SERVICE_UI}) indicates that this particular
* {@code InCallService} implementation intends to replace the built-in in-call UI.
*
* {@code
* <service android:name="your.package.YourInCallServiceImplementation"
* android:permission="android.permission.BIND_IN_CALL_SERVICE">
* <meta-data android:name="android.telecom.IN_CALL_SERVICE_UI" android:value="true" />
* <intent-filter>
* <action android:name="android.telecom.InCallService"/>
* </intent-filter>
* </service>
* }
*
*/
如果服务已经绑定好了,addCall(call);//也把引用维护到本地
ParcelableCall parcelableCall = toParcelableCall(call, true /* includeVideoProvider */);//包装成ParcelableCall,通过aidl来传递的对象要实现parcelable?
inCallService.addCall(parcelableCall);//然后利用远程实例,通知各个service,添加call
->MSG_ADD_CALL
------------------------frameworks/base/telecomm/java/android/telecom/Call.java 来了~~~~~~----------------
->mPhone.internalAddCall((ParcelableCall) msg.obj);//这个mPhone是Telecom的Phone哦
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);
fireCallAdded(call);//这个fire该怎么理解
}
private void fireCallAdded(Call call) {
for (Listener listener : mListeners) {
listener.onCallAdded(this, call);//要找找都有哪些listener
}
}
正好InCallService在收到MSG_SET_IN_CALL_ADAPTER的时候会设置mPhone.addListener(mPhoneListener);
private Phone.Listener mPhoneListener = new Phone.Listener()
{...
public void onCallAdded(Phone phone, Call call) {
InCallService.this.onCallAdded(call);
}
...
}
InCallService.this.onCallAdded(call);// 这种写法总会让我感觉会调用父类方法,而不调用子类,是不是可以这样理解,因为new Phone.Listener()是
内部类的写法,InCallService.this只是标识是InCallService这个类方法,用来区别this。
现在掉到子类InCallService的onCallAdded,看一下系统实现的InCallService
packages/apps/InCallUI/src/com/android/incallui/InCallServiceImpl
public void onCallAdded(Call call) {
CallList.getInstance().onCallAdded(call);
InCallPresenter.getInstance().onCallAdded(call);
}
packages/apps/InCallUI/src/com/android/incallui/CallList
packages/apps/InCallUI/src/com/android/incallui/Call.java
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 {
onUpdate(call);
}
Trace.endSection();
}
->onUpdate(Call call)
->onUpdateCall(call)
->updateCallInMap(call)
{...
mCallById.put(call.getId(), call);
mCallByTelecommCall.put(call.getTelecommCall(), call);
...}
frameworks/opt/telephony/src/java/com/android/internal/telephony/Call.java
frameworks/opt/telephony/src/java/com/android/internal/telephony/gsm/GsmCallTracker.java
在GsmCallTracker中new的
public GsmCall mRingingCall = new GsmCall(this);
// A call that is ringing or (call) waiting
public GsmCall mForegroundCall = new GsmCall(this);
public GsmCall mBackgroundCall = new GsmCall(this);