相關代碼
frameworks/base/telephony --- telephony framework
frameworks/base/telecomm --- telecomm framework 沒有詳細看
package/services/telephony --- teleService.apk
package/services/Telecomm --- telepcomm.apk 沒有詳細看
frameworks/opt/telephony --- telephony-common
TELEPHONY_SERVICE
系統(tǒng)啟動后券敌,由systemserver.java的main方法開始:
systemserver.java
main() -> run() -> startBootstrapServices(其中啟動AMS)
->startotherServices -> AMS. systemReady 中調(diào)用startPersistentApps去啟動phone應用:
phoneapp->
phoneglobals->onCreat() ->
PhoneInterfaceManager.init(this) -> public() ->
TelephonyFrameworkInitializer
.getTelephonyServiceManager()
.getTelephonyServiceRegisterer()
.register(this);
//看下具體的實現(xiàn)
public ServiceRegisterer getTelephonyServiceRegisterer() {
return new ServiceRegisterer(Context.TELEPHONY_SERVICE);
}
如上巫员,在啟動phone過程中通過register操作座掘,將PhoneInterfaceManager注冊成為真正的Context.TELEPHONY_SERVICE的service端芦圾。
一個細節(jié)問題鸠珠,上述的getTelephonyServiceManager是在什么時候賦值的?通過搜索setTelephonyServiceManager方法边篮,發(fā)現(xiàn)是在ActivityThread中的main方法中:
調(diào)用initializeMainlineModules() ->
TelephonyFrameworkInitializer.setTelephonyServiceManager(new TelephonyServiceManager());
TelephonyServiceManager是用于管理和telephony相關的各種service鸽凶,主要是確保telephony相關的各種service能夠注冊成功。
SystemServiceRegistry
SystemServiceRegistry用于在APP端緩存各種系統(tǒng)服務齿椅,方便調(diào)用系統(tǒng)服務琉挖。其static方法如下:
static {
//......
JobSchedulerFrameworkInitializer.registerServiceWrappers();
BlobStoreManagerFrameworkInitializer.initialize();
TelephonyFrameworkInitializer.registerServiceWrappers();
WifiFrameworkInitializer.registerServiceWrappers();
StatsFrameworkInitializer.registerServiceWrappers();
//......
}
// TelephonyFrameworkInitializer 的 registerServiceWrappers方法具體實現(xiàn):
/**
* Called by {@link SystemServiceRegistry}'s static initializer and registers all telephony
* services to {@link Context}, so that {@link Context#getSystemService} can return them.
*
* @throws IllegalStateException if this is called from anywhere besides
* {@link SystemServiceRegistry}
*/
public static void registerServiceWrappers() {
SystemServiceRegistry.registerContextAwareService(
Context.TELEPHONY_SERVICE,
TelephonyManager.class,
context -> new TelephonyManager(context)
);
SystemServiceRegistry.registerContextAwareService(
Context.TELEPHONY_SUBSCRIPTION_SERVICE,
SubscriptionManager.class,
context -> new SubscriptionManager(context)
);
SystemServiceRegistry.registerContextAwareService(
Context.CARRIER_CONFIG_SERVICE,
CarrierConfigManager.class,
context -> new CarrierConfigManager(context)
);
SystemServiceRegistry.registerContextAwareService(
Context.EUICC_SERVICE,
EuiccManager.class,
context -> new EuiccManager(context)
);
SystemServiceRegistry.registerContextAwareService(
Context.EUICC_CARD_SERVICE,
EuiccCardManager.class,
context -> new EuiccCardManager(context)
);
SystemServiceRegistry.registerContextAwareService(
Context.TELEPHONY_IMS_SERVICE,
ImsManager.class,
context -> new ImsManager(context)
);
}
那么SystemServiceRegistry的調(diào)用是在什么時候呢?
//ConextImpl.java
final Object[] mServiceCache = SystemServiceRegistry.createServiceCache();
當ConextImpl對象創(chuàng)建時涣脚,其屬性就會創(chuàng)建示辈,由于上述所說,SystemServiceRegistry有static代碼塊遣蚀,因此該代碼塊會在第一次使用時就會加載矾麻。即在ConextImpl對象創(chuàng)建好之前纱耻,相關的服務就已經(jīng)在其中注冊了。
Telcommservice
systemserver.java
main() -> run() -> startBootstrapServices(其中啟動AMS)
->startotherServices -> 去StartTelecomLoaderService
t.traceBegin("StartTelecomLoaderService");
mSystemServiceManager.startService(TelecomLoaderService.class);
t.traceEnd();
后面當完成開機后险耀,在AMS的finishBooting中去執(zhí)行
// Let system services know.
mSystemServiceManager.startBootPhase(t, SystemService.PHASE_BOOT_COMPLETED);
這個方法中回去回調(diào)service.onBootPhase(mCurrentPhase)弄喘。
繼續(xù)查看TelecomLoaderService的onBootPhase實現(xiàn):
@Override
public void onBootPhase(int phase) {
if (phase == PHASE_ACTIVITY_MANAGER_READY) {
registerDefaultAppNotifier();
registerCarrierConfigChangedReceiver();
// core services will have already been loaded.
setupServiceRepository();
connectToTelecom();
}
}
private void connectToTelecom() {
synchronized (mLock) {
if (mServiceConnection != null) {
// TODO: Is unbinding worth doing or wait for system to rebind?
mContext.unbindService(mServiceConnection);
mServiceConnection = null;
}
TelecomServiceConnection serviceConnection = new TelecomServiceConnection();
Intent intent = new Intent(SERVICE_ACTION);
intent.setComponent(SERVICE_COMPONENT);
int flags = Context.BIND_IMPORTANT | Context.BIND_FOREGROUND_SERVICE
| Context.BIND_AUTO_CREATE;
// Bind to Telecom and register the service
if (mContext.bindServiceAsUser(intent, serviceConnection, flags, UserHandle.SYSTEM)) {
mServiceConnection = serviceConnection;
}
}
}
private static final ComponentName SERVICE_COMPONENT = new ComponentName(
"com.android.server.telecom",
"com.android.server.telecom.components.TelecomService");
private static final String SERVICE_ACTION = "com.android.ITelecomService";
可以看到TelecomLoaderService去bind了TelecomService,TelecomService做為TelecomLoaderService的服務端甩牺,實現(xiàn)了ITelecomLoader.Stub:
public class TelecomService extends Service implements TelecomSystem.Component {
@Override
public IBinder onBind(Intent intent) {
Log.d(this, "onBind");
//Task9999555-zhengpinhuang@tcl.com-Mobile data off-begin
TelecomGlobals.createInstance(getApplicationContext());
CarrierConfigManagerEx.init(getApplicationContext());
//Task9999555-zhengpinhuang@tcl.com-Mobile data off-end
return new ITelecomLoader.Stub() {
@Override
public ITelecomService createTelecomService(IInternalServiceRetriever retriever) {
InternalServiceRetrieverAdapter adapter =
new InternalServiceRetrieverAdapter(retriever);
initializeTelecomSystem(TelecomService.this, adapter);
synchronized (getTelecomSystem().getLock()) {
return getTelecomSystem().getTelecomServiceImpl().getBinder();
}
}
};
}
}
接下去看下蘑志,TelecomLoaderService在ServiceConnected成功后做了什么?
private class TelecomServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// Normally, we would listen for death here, but since telecom runs in the same process
// as this loader (process="system") that's redundant here.
try {
ITelecomLoader telecomLoader = ITelecomLoader.Stub.asInterface(service);
ITelecomService telecomService = telecomLoader.createTelecomService(mServiceRepo);
SmsApplication.getDefaultMmsApplication(mContext, false);
ServiceManager.addService(Context.TELECOM_SERVICE, telecomService.asBinder());
//......省略部分實現(xiàn)
} catch (RemoteException e) {
Slog.w(TAG, "Failed linking to death.");
}
}
可以看到在拿到service后贬派,第一時間就是調(diào)用createTelecomService急但,真正的實現(xiàn)是在TelecomLoaderService的service端,就是上面提到的實現(xiàn)了ITelecomLoader.Stub的地方搞乏。
return new ITelecomLoader.Stub() {
@Override
public ITelecomService createTelecomService(IInternalServiceRetriever retriever) {
InternalServiceRetrieverAdapter adapter =
new InternalServiceRetrieverAdapter(retriever);
initializeTelecomSystem(TelecomService.this, adapter);
synchronized (getTelecomSystem().getLock()) {
return getTelecomSystem().getTelecomServiceImpl().getBinder();
}
}
};
getTelecomServiceImpl的實現(xiàn)可以看到:
public TelecomServiceImpl getTelecomServiceImpl() {
return mTelecomServiceImpl;
}
mTelecomServiceImpl是在TelecomSystem的構造方法里面new的波桩。再看下getBinder的實現(xiàn):
public ITelecomService.Stub getBinder() {
return mBinderImpl;
}
private final ITelecomService.Stub mBinderImpl = new ITelecomService.Stub() {
@Override
public PhoneAccountHandle getDefaultOutgoingPhoneAccount(String uriScheme,
String callingPackage, String callingFeatureId) {
}
可以看到這里是真正telecomservice的實現(xiàn)端,是一個匿名內(nèi)部類查描。再一步步往回走突委,在拿到真正的telecomservice后,通過ServiceManager.addService將其加入到ServiceManager中冬三。
方法總結
上面總結了很多系統(tǒng)service的啟動和注冊流程匀油,那么對于這些系統(tǒng)的service,如何在看源碼的時候快速定位到具體service的實現(xiàn)呢勾笆?在已經(jīng)知道答案的情況下敌蚜,我個人大致反推了一下,方便后續(xù)查看其它系統(tǒng)service時能夠快速定位窝爪。
1弛车、假設現(xiàn)在要Context.TELECOM_SERVICE的具體實現(xiàn),從代碼可以知道這個service對應的標識是:
public static final String TELECOM_SERVICE = "telecom";
2蒲每、adb shell service list|grep -rin telecom 結果如下:
telecom: [com.android.internal.telecom.ITelecomService]
看到對應的aidl接口是ITelecomService.aidl
3纷跛、代碼全局搜索"extends ITelecomService.stub" ,如果沒有再搜索 "new ITelecomService.stub" 邀杏,因為有部分service端是匿名的類贫奠,telcom service就是這樣的。
完成上面3步望蜡,這些系統(tǒng)service的真正實現(xiàn)的地方基本就定位到了唤崭。
參考內(nèi)容
如何實現(xiàn)服務器端調(diào)用應用端的例子。
https://cloud.tencent.com/developer/article/1600478
解析telephonymanager和telecom的文章脖律,里面的很多時序圖很好驱犹。
https://blog.csdn.net/jason_wzn/article/details/58164251
https://blog.csdn.net/ZhongGuoRenMei/article/details/97037870