Android S源碼手動搜網(wǎng)流程

1 手動搜網(wǎng)應(yīng)用程序

1.1 MobileNetworkSettings入口

我們首先從apk的Manifest找入口坏瞄,如下:
/packages/apps/Settings/AndroidManifest.xml

        <activity android:name=".network.telephony.MobileNetworkActivity"
                  android:label="@string/network_settings_title"
                  android:exported="true"
                  android:launchMode="singleTask">
            <intent-filter android:priority="1">
                <!-- Displays the MobileNetworkActivity and opt-in dialog for capability discovery. -->
                <action android:name="android.telephony.ims.action.SHOW_CAPABILITY_DISCOVERY_OPT_IN" />
                <action android:name="android.settings.NETWORK_OPERATOR_SETTINGS" />
                <action android:name="android.settings.DATA_ROAMING_SETTINGS" />
                <action android:name="android.settings.MMS_MESSAGE_SETTING" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

緊接著的調(diào)用關(guān)系墨吓,會使用到布局xml文件:
/packages/apps/Settings/src/com/android/settings/network/telephony/MobileNetworkActivity.java
/packages/apps/Settings/src/com/android/settings/network/telephony/MobileNetworkSettings.java

    @Override
    protected int getPreferenceScreenResId() {
        return R.xml.mobile_network_settings;
    }

1.1.1 MobileNetworkSettings布局

從上述的R.xml.mobile_network_settings引入布局,這里摘抄部分:
/packages/apps/Settings/res/xml/mobile_network_settings.xml

<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:settings="http://schemas.android.com/apk/res-auto"
    android:key="mobile_network_pref_screen">

    <com.android.settings.widget.SettingsMainSwitchPreference
        android:key="use_sim_switch"
        settings:controller="com.android.settings.network.telephony.MobileNetworkSwitchController"/>

    <PreferenceCategory
        android:key="enabled_state_container"
        android:title="@string/summary_placeholder"
        settings:controller="com.android.settings.network.telephony.DisabledSubscriptionController"
        android:layout="@layout/preference_category_no_label">

        <SwitchPreference
            android:key="mobile_data_enable"
            android:title="@string/mobile_data_settings_title"
            android:summary="@string/mobile_data_settings_summary"
            settings:controller="com.android.settings.network.telephony.MobileDataPreferenceController"
            settings:allowDividerAbove="true"/>

        <com.android.settingslib.RestrictedSwitchPreference
            android:key="button_roaming_key"
            android:title="@string/roaming"
            android:persistent="false"
            android:summaryOn="@string/roaming_enable"
            android:summaryOff="@string/roaming_disable"
            settings:userRestriction="no_data_roaming"
            settings:controller="com.android.settings.network.telephony.RoamingPreferenceController"/>

        <SwitchPreference
            android:key="carrier_wifi_toggle"
            android:title="@string/carrier_wifi_offload_title"
            android:summary="@string/carrier_wifi_offload_summary"
            settings:controller="com.android.settings.network.CarrierWifiTogglePreferenceController"/>

        <Preference
            android:key="carrier_wifi_network"
            android:title="@string/carrier_wifi_network_title"
            android:selectable="false"
            settings:searchable="false"/>

        <SwitchPreference
            android:key="4g_calling"
            android:title="@string/enhanced_4g_lte_mode_title_4g_calling"
            android:persistent="false"
            android:summary="@string/enhanced_4g_lte_mode_summary_4g_calling"
            settings:keywords="@string/keywords_enhance_4g_lte"
            settings:controller="com.android.settings.network.telephony.Enhanced4gCallingPreferenceController"/>
        
        <ListPreference
            android:key="preferred_network_mode_key"
            android:title="@string/preferred_network_mode_title"
            android:summary="@string/preferred_network_mode_summary"
            android:entries="@array/preferred_network_mode_choices"
            android:entryValues="@array/preferred_network_mode_values"
            android:dialogTitle="@string/preferred_network_mode_dialogtitle"
            settings:controller="com.android.settings.network.telephony.PreferredNetworkModePreferenceController"/>

        <PreferenceCategory
            android:key="network_operators_category_key"
            android:title="@string/network_operator_category"
            settings:controller="com.android.settings.network.telephony.NetworkPreferenceCategoryController">

            <SwitchPreference
                android:key="auto_select_key"
                android:title="@string/select_automatically"
                settings:controller="com.android.settings.network.telephony.gsm.AutoSelectPreferenceController"/>

            <Preference
                android:key="choose_network_key"
                android:title="@string/choose_network_title"
                android:fragment="com.android.phone.NetworkSelectSetting"
                settings:controller="com.android.settings.network.telephony.gsm.OpenNetworkSelectPagePreferenceController"/>
        </PreferenceCategory>

        <!--We want separate APN setting from reset of settings because we want user to change it with caution-->
        <com.android.settingslib.RestrictedPreference
            android:key="telephony_apn_key"
            android:persistent="false"
            android:title="@string/mobile_network_apn_title"
            settings:allowDividerAbove="true"
            settings:controller="com.android.settings.network.telephony.ApnPreferenceController"/>
        
</PreferenceScreen>

1.1.2 MobileNetworkSettings字符串位置

通過字符串也可以快速查找一些難以確認(rèn)的界面程序入口:
/packages/apps/Settings/res/values/strings.xml

1.1.3 MobileNetworkSettings初始化

在onAttach進(jìn)行一些初步的初始化:
/packages/apps/Settings/src/com/android/settings/network/telephony/MobileNetworkSettings.java

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

        use(MobileNetworkSwitchController.class).init(getLifecycle(), mSubId);
        use(DisabledSubscriptionController.class).init(getLifecycle(), mSubId);
        use(MobileDataPreferenceController.class).init(getFragmentManager(), mSubId);
        use(MobileDataPreferenceController.class).setWifiPickerTrackerHelper(
                new WifiPickerTrackerHelper(getSettingsLifecycle(), context,
                        null /* WifiPickerTrackerCallback */));
        use(RoamingPreferenceController.class).init(getFragmentManager(), mSubId);
        use(ApnPreferenceController.class).init(mSubId);
        use(PreferredNetworkModePreferenceController.class).init(mSubId);
        use(CarrierWifiTogglePreferenceController.class).init(getLifecycle(), mSubId);

        final WifiCallingPreferenceController wifiCallingPreferenceController =
                use(WifiCallingPreferenceController.class).init(mSubId);

        final OpenNetworkSelectPagePreferenceController openNetworkSelectPagePreferenceController =
                use(OpenNetworkSelectPagePreferenceController.class).init(getLifecycle(), mSubId);
        final AutoSelectPreferenceController autoSelectPreferenceController =
                use(AutoSelectPreferenceController.class)
                        .init(getLifecycle(), mSubId)
                        .addListener(openNetworkSelectPagePreferenceController);
        use(NetworkPreferenceCategoryController.class).init(getLifecycle(), mSubId)
                .setChildren(Arrays.asList(autoSelectPreferenceController));

        use(NetworkPreferenceCategoryController.class).init(getLifecycle(), mSubId)
                .setChildren(Arrays.asList(autoSelectPreferenceController));
        use(Enhanced4gCallingPreferenceController.class).init(mSubId)
                .addListener(videoCallingPreferenceController);

1.2 手動搜網(wǎng)代碼入口

從上述分析可以得知填渠,手動搜網(wǎng)的代碼入口java文件如下:
/packages/apps/Settings/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java

1.3 手動搜網(wǎng)應(yīng)用流程

如果用戶選擇了手動搜網(wǎng),則走else流程:
/packages/apps/Settings/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java

    @Override
    public boolean setChecked(boolean isChecked) {
        if (isChecked) {
            setAutomaticSelectionMode();
            return false;
        } else {
            final Bundle bundle = new Bundle();
            bundle.putInt(Settings.EXTRA_SUB_ID, mSubId);
            new SubSettingLauncher(mContext)
                    .setDestination(NetworkSelectSettings.class.getName())
                    .setSourceMetricsCategory(SettingsEnums.MOBILE_NETWORK_SELECT)
                    .setTitleRes(R.string.choose_network_title)
                    .setArguments(bundle)
                    .launch();
            return false;
        }
    }

如下界面被發(fā)起鸟辅,startNetworkQuery()被調(diào)用氛什。mUseNewApi來自config_enableNewAutoSelectNetworkUI,該值為false匪凉,所以選擇了NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS:
/packages/apps/Settings/src/com/android/settings/network/telephony/NetworkSelectSettings.java

    @Override
    public void onStart() {
        super.onStart();

        updateForbiddenPlmns();
        if (isProgressBarVisible()) {
            return;
        }
        if (mWaitingForNumberOfScanResults <= 0) {
            startNetworkQuery();
        }
    }

    private void startNetworkQuery() {
        setProgressBarVisible(true);
        if (mNetworkScanHelper != null) {
            mRequestIdManualNetworkScan = getNewRequestId();
            mWaitingForNumberOfScanResults = MIN_NUMBER_OF_SCAN_REQUIRED;
            mNetworkScanHelper.startNetworkScan(
                    mUseNewApi
                            ? NetworkScanHelper.NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS
                            : NetworkScanHelper.NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS);
        }
    }

接下來通過startNetworkScan()來啟動手動搜網(wǎng)枪眉,走該代碼的if分支,逐步完成對TelephonyManager API的調(diào)用再层。這里也需要注意贸铜,對于網(wǎng)絡(luò)側(cè)返回信息,則callback函數(shù)onSuccess()或onFailure()會被調(diào)用:
/packages/apps/Settings/src/com/android/settings/network/telephony/NetworkScanHelper.java

    /**
     * Performs a network scan for the given type {@code type}.
     * {@link #NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS} is recommended if modem supports
     * {@link TelephonyManager#requestNetworkScan(
     * NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)}.
     *
     * @param type used to tell which network scan API should be used.
     */
    public void startNetworkScan(@NetworkQueryType int type) {
        if (type == NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS) {
            mNetworkScanFuture = SettableFuture.create();
            Futures.addCallback(mNetworkScanFuture, new FutureCallback<List<CellInfo>>() {
                @Override
                public void onSuccess(List<CellInfo> result) {
                    onResults(result);
                    onComplete();
                }

                @Override
                public void onFailure(Throwable t) {
                    if (t instanceof CancellationException) {
                        return;
                    }
                    int errCode = Integer.parseInt(t.getMessage());
                    onError(errCode);
                }
            }, MoreExecutors.directExecutor());
            mExecutor.execute(new NetworkScanSyncTask(
                    mTelephonyManager, (SettableFuture) mNetworkScanFuture));
        } else if (type == NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS) {
            if (mNetworkScanRequester != null) {
                return;
            }
            mNetworkScanRequester = mTelephonyManager.requestNetworkScan(
                    createNetworkScanForPreferredAccessNetworks(),
                    mExecutor,
                    mInternalNetworkScanCallback);
            if (mNetworkScanRequester == null) {
                onError(NetworkScan.ERROR_RADIO_INTERFACE_ERROR);
            }
        }
    }

    private static final class NetworkScanSyncTask implements Runnable {
        private final SettableFuture<List<CellInfo>> mCallback;
        private final TelephonyManager mTelephonyManager;

        NetworkScanSyncTask(
                TelephonyManager telephonyManager, SettableFuture<List<CellInfo>> callback) {
            mTelephonyManager = telephonyManager;
            mCallback = callback;
        }

        @Override
        public void run() {
            final CellNetworkScanResult result = mTelephonyManager.getAvailableNetworks();
            if (result.getStatus() == CellNetworkScanResult.STATUS_SUCCESS) {
                final List<CellInfo> cellInfos = result.getOperators()
                        .stream()
                        .map(operatorInfo
                                -> CellInfoUtil.convertOperatorInfoToCellInfo(operatorInfo))
                        .collect(Collectors.toList());
                Log.d(TAG, "Sync network scan completed, cellInfos = "
                        + CellInfoUtil.cellInfoListToString(cellInfos));
                mCallback.set(cellInfos);
            } else {
                final Throwable error = new Throwable(
                        Integer.toString(convertToScanErrorCode(result.getStatus())));
                mCallback.setException(error);
                Log.d(TAG, "Sync network scan error, ex = " + error);
            }
        }
    }

2 手動搜網(wǎng)Framework

2.1 Framework涉及到的類

frame_class.png

四個主要的類:
TelephonyManager : 提供API給應(yīng)用聂受。
PhoneInterfaceManager : 實現(xiàn)ITelephony接口蒿秦,實現(xiàn)對Phone的控制操作。其內(nèi)部類MainThreadHandler繼承于Handler蛋济。
GsmCdmaPhone : Phone棍鳖,其父類繼承于Handler。
RIL : RILJ碗旅,提供API給Phone

2.2 流程圖

這些類的工作流程一般如下:


getAvailableNetworks_framework.png

Step1: 通過TelephonyManager API調(diào)用Telephony Service(PhoneInterfaceManager)
Step2: 通過Telephony Service調(diào)用控制Phone
Step3: 通過Phone調(diào)用RILJ
Step4: RILJ通過HIDL實現(xiàn)對RILD的調(diào)用
Step5: RILD通過RadioResponse把返回值反饋給Phone
Step6: Phone把返回值傳給Telephony Service
Step7: Telephony Service把返回值通知給應(yīng)用程序

3 手動搜網(wǎng)RILD

3.1 流程圖

rild.png

3.2 AT Command

可參考3GPP TS 27.007之7.3 PLMN selection +COPS
如下是聯(lián)通卡搜網(wǎng)的一個結(jié)果示例:

AT> AT+COPS=?
AT< +COPS: (1,"China Unicom","CU-GSM","46001","25C7",7),(1,"China Unicom","CU-GSM","46001","A5AB",2),(2,"China Unicom","CU-GSM","46001","77B600",11),(3,"46011","46011","46011","7C06",7),(3,"China Mobile","CMCC","46000","2441",7),(3,"46011","46011","46011","77B600",11),,(0-3),(0-2)
AT< OK

界面效果如下:
China Unicom 4G (Available)
China Unicom 3G (Available)
China Unicom 5G (Current)
China Telecom 4G (Forbidden)
China Mobile 4G (Forbidden)
China Telecom 5G (Forbidden)

版權(quán)聲明:本文為 無痕1024 原創(chuàng)文章鹊杖,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接和本聲明扛芽。
本文鏈接:http://www.reibang.com/p/e56e83ca520d

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末骂蓖,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子川尖,更是在濱河造成了極大的恐慌登下,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件叮喳,死亡現(xiàn)場離奇詭異被芳,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)馍悟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進(jìn)店門畔濒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人锣咒,你說我怎么就攤上這事侵状≡廾郑” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵趣兄,是天一觀的道長绽左。 經(jīng)常有香客問我,道長艇潭,這世上最難降的妖魔是什么拼窥? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮蹋凝,結(jié)果婚禮上鲁纠,老公的妹妹穿的比我還像新娘。我一直安慰自己鳍寂,他們只是感情好房交,可當(dāng)我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著伐割,像睡著了一般候味。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上隔心,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天白群,我揣著相機(jī)與錄音,去河邊找鬼硬霍。 笑死帜慢,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的唯卖。 我是一名探鬼主播粱玲,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼拜轨!你這毒婦竟也來了抽减?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤橄碾,失蹤者是張志新(化名)和其女友劉穎卵沉,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體法牲,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡史汗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了拒垃。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片停撞。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖悼瓮,靈堂內(nèi)的尸體忽然破棺而出戈毒,到底是詐尸還是另有隱情艰猬,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布副硅,位于F島的核電站姥宝,受9級特大地震影響翅萤,放射性物質(zhì)發(fā)生泄漏恐疲。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一套么、第九天 我趴在偏房一處隱蔽的房頂上張望培己。 院中可真熱鬧,春花似錦胚泌、人聲如沸省咨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽零蓉。三九已至,卻和暖如春穷缤,著一層夾襖步出監(jiān)牢的瞬間敌蜂,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工津肛, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留章喉,地道東北人。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓身坐,卻偏偏與公主長得像秸脱,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子部蛇,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,933評論 2 355