我们首先从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>
紧接着的调用关系,会使用到布局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; }
从上述的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>
通过字符串也可以快速查找一些难以确认的界面程序入口:
/packages/apps/Settings/res/values/strings.xml
在onAttach进行一些初步的初始化:
/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);
从上述分析可以得知,手动搜网的代码入口java文件如下:
/packages/apps/Settings/src/com/android/settings/network/telephony/gsm/AutoSelectPreferenceController.java
如果用户选择了手动搜网,则走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; } }
如下界面被发起,startNetworkQuery()被调用。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()来启动手动搜网,走该代码的if分支,逐步完成对TelephonyManager API的调用。这里也需要注意,对于网络侧返回信息,则callback函数onSuccess()或onFailure()会被调用:
/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()); one rror(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) { one rror(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); } } }
四个主要的类:
TelephonyManager : 提供API给应用。
PhoneInterfaceManager : 实现ITelephony接口,实现对Phone的控制操作。其内部类MainThreadHandler继承于Handler。
GsmCdmaPhone : Phone,其父类继承于Handler。
RIL : RILJ,提供API给Phone
这些类的工作流程一般如下:
Step1: 通过TelephonyManager API调用Telephony Service(PhoneInterfaceManager)
Step2: 通过Telephony Service调用控制Phone
Step3: 通过Phone调用RILJ
Step4: RILJ通过HIDL实现对RILD的调用
Step5: RILD通过RadioResponse把返回值反馈给Phone
Step6: Phone把返回值传给Telephony Service
Step7: Telephony Service把返回值通知给应用程序
可参考3GPP TS 27.007之7.3 PLMN selection +COPS
如下是联通卡搜网的一个结果示例:
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)
版权声明:本文为 无痕1024 原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/wuhen1024/p/16052918.html