去電介面啟動分析---之一
1,去電介面啟動分析
在去電流程中論述過,會呼叫CallsManager的startOutgoingCall啟動撥號介面,在該方法中會呼叫addCall方法,
此時還處於services telecom程式中。
addCall(call);
addCall方法如下,
for (CallsManagerListener listener : mListeners) {
if (Log.SYSTRACE_DEBUG) {
Trace.beginSection(listener.getClass().toString() + " addCall");
}
listener.onCallAdded(call);
if (Log.SYSTRACE_DEBUG) {
Trace.endSection();
}
}
mListeners定義如下,
private final Set<CallsManagerListener> mListeners = Collections.newSetFromMap(
new ConcurrentHashMap<CallsManagerListener, Boolean>(16, 0.9f, 1));
該雜湊表是執行緒安全的。
並且在CallsManager的構造方法中就會新增監聽器,
mListeners.add(mInCallController);
mListeners.add(mRinger);
當然,還可以呼叫addListener方法新增監聽器,
void addListener(CallsManagerListener listener) {
mListeners.add(listener);
}
InCallController的onCallAdded方法主要邏輯如下,
1, 繫結InCallService服務
if (!isBoundToServices()) {//如果還沒有繫結
bindToServices(call);
}
2,新增具體的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) {
}
}
3,電話狀態的變化,
onCallAudioStateChanged(null, mCallsManager.getAudioState());
1.1繫結InCallService服務
InCallController的bindToServices方法中會呼叫bindToInCallService方法,該方法如下,
Intent intent = new Intent(InCallService.SERVICE_INTERFACE);
intent.setComponent(componentName);
if (call != null && !call.isIncoming()){
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 [%s] InCall %s, with %s", tag, componentName, intent);
InCallServiceConnection inCallServiceConnection = new InCallServiceConnection();
if (mContext.bindServiceAsUser(intent, inCallServiceConnection,
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
UserHandle.CURRENT)) {
mServiceConnections.put(componentName, inCallServiceConnection);
return true;
}
InCallService的SERVICE_INTERFACE變數如下,
public static final String SERVICE_INTERFACE = "android.telecom.InCallService";
InCallService只是一個抽象類,具體的實現在IncallUI 的InCallServiceImpl中, IncallUI 整個執行於dialer程式中。
InCallServiceImpl繼承於InCallService,
public class InCallServiceImpl extends InCallService {
Dialer的AndroidManifest.xml 中有關InCallServiceImpl如下,
<service android:name="com.android.incallui.InCallServiceImpl"
android:permission="android.permission.BIND_INCALL_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>
由此可見,確認是啟動InCallServiceImpl無疑。
InCallServiceImpl的onBind方法會呼叫父類InCallService的onBind方法,
public IBinder onBind(Intent intent) {
return new InCallServiceBinder();
}
返回的是InCallServiceBinder物件, InCallServiceBinder是InCallService的內部類,定義如下,
private final class InCallServiceBinder extends IInCallService.Stub {
因此,繫結的是dialer程式中的是InCallService的內部類InCallServiceBinder。
InCallServiceConnection是 InCallController的內部類,繫結成功之後,就會回撥InCallServiceConnection的
onServiceConnected方法,
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(this, "onServiceConnected: %s", name);
onConnected(name, service);
}
onConnected方法如下,
1,首先儲存繫結的遠端物件,
IInCallService inCallService = IInCallService.Stub.asInterface(service);
mInCallServices.put(componentName, inCallService);
2,呼叫繫結物件的setInCallAdapter方法,
inCallService.setInCallAdapter(new InCallAdapter(mCallsManager, mCallIdMapper, mLock));
dialer程式中的是InCallService的內部類InCallServiceBinder的setInCallAdapter方法下個小節詳細論述。
1.2設定InCallAdapter
InCallService的內部類InCallServiceBinder的setInCallAdapter方法如下,
public void setInCallAdapter(IInCallAdapter inCallAdapter) {
mHandler.obtainMessage(MSG_SET_IN_CALL_ADAPTER, inCallAdapter).sendToTarget();
}
mHandler的handleMessage對MSG_SET_IN_CALL_ADAPTER訊息處理如下,
case MSG_SET_IN_CALL_ADAPTER:
mPhone = new Phone(new InCallAdapter((IInCallAdapter) msg.obj));
mPhone.addListener(mPhoneListener);
onPhoneCreated(mPhone);
break;
在構造Phone物件之前會構造InCallAdapter物件, InCallAdapter構造方法如下,
public InCallAdapter(IInCallAdapter adapter) {
mAdapter = adapter;
}
mAdapter就是指向services Telephony的InCallAdapter物件。
這樣services telecom就可以通過binder進行跨程式呼叫。例如,結束通話電話/接聽電話等操作。
相關文章
- 啟動電路
- RetHatLinux啟動到文字介面(不啟動xwindow)Linux
- 打造一個啟動介面
- 電腦長時間停留在啟動等待介面是為什麼
- 如何啟動MongoDB的WEB介面MongoDBWeb
- Activity啟動流程分析
- activity 啟動流程分析
- Unbound啟動流程分析
- Android MTK平臺 客製化系統來電介面(遮蔽 InCallUI 提供介面給客戶自行展示來電去電頁面)AndroidUI
- Tomcat 7 啟動分析(一)啟動指令碼Tomcat指令碼
- 啟動Activity但不顯示其介面
- 【IDL〕編寫程式啟動介面
- docker-compose下的java應用啟動順序兩部曲之一:問題分析DockerJava
- FlutterApp啟動流程分析FlutterAPP
- nodejs啟動流程分析NodeJS
- Service啟動過程分析
- Activity啟動過程分析
- PackageManagerService啟動原始碼分析Package原始碼
- 移動介面設計趨勢分析
- gonsq/nsqlookupd 分析之一GoSQL
- phpStudy啟動介面的功能簡介PHP
- 如何製作 Uber 啟動開屏介面
- 中央銀行將啟動去中心化貨幣中心化
- 小米真出電動牙刷?小米電動牙刷實用性分析
- Flutter啟動流程原始碼分析Flutter原始碼
- Liferay 啟動過程分析
- Linux:uboot啟動流程分析Linuxboot
- apiserver原始碼分析——啟動流程APIServer原始碼
- Eureka Server啟動過程分析Server
- Linux 啟動過程分析Linux
- Activity啟動流程原始碼分析原始碼
- Linux啟動過程分析Linux
- ThinkPHP6.0 原始碼分析之啟動分析PHP原始碼
- OpenRTMFP/Cumulus Primer(22)執行緒邏輯分析之一:RTMFPServer執行緒的啟動和等待執行緒Server
- 電腦自啟動軟體管理
- itpub awr案例分析之一
- 電腦充不進去電是怎麼回事 電腦充不進去電的解決方法
- 電腦無法啟動怎麼辦 電腦啟動不了的原因與解決辦法