telephony

相關代碼

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流程.png

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

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末黄刚,一起剝皮案震驚了整個濱河市殊校,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌冕杠,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件眯分,死亡現(xiàn)場離奇詭異拌汇,居然都是意外死亡,警方通過查閱死者的電腦和手機弊决,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進店門噪舀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人飘诗,你說我怎么就攤上這事与倡。” “怎么了昆稿?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵纺座,是天一觀的道長。 經(jīng)常有香客問我溉潭,道長净响,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任喳瓣,我火速辦了婚禮馋贤,結果婚禮上,老公的妹妹穿的比我還像新娘畏陕。我一直安慰自己配乓,他們只是感情好,可當我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布惠毁。 她就那樣靜靜地躺著犹芹,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鞠绰。 梳的紋絲不亂的頭發(fā)上腰埂,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天,我揣著相機與錄音蜈膨,去河邊找鬼盐固。 笑死,一個胖子當著我的面吹牛丈挟,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播志电,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼曙咽,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了挑辆?” 一聲冷哼從身側(cè)響起例朱,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤孝情,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后洒嗤,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體箫荡,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年渔隶,在試婚紗的時候發(fā)現(xiàn)自己被綠了羔挡。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡间唉,死狀恐怖绞灼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情呈野,我是刑警寧澤低矮,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站被冒,受9級特大地震影響军掂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜昨悼,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一蝗锥、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧幔戏,春花似錦玛追、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至垒玲,卻和暖如春陆馁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背合愈。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工叮贩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人佛析。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓益老,卻偏偏與公主長得像,于是被迫代替她去往敵國和親寸莫。 傳聞我的和親對象是個殘疾皇子捺萌,可洞房花燭夜當晚...
    茶點故事閱讀 44,678評論 2 354

推薦閱讀更多精彩內(nèi)容