???????
目錄
一、APP層源碼分析
1.1、尋找頁面activity
1.2、尋找頁面開關按鈕布局
二,framework層代碼分析
2.1 開啟wifi入口
2.2?WiFiNative
三,HAL層代碼分析
?????????這段時間擼了WIFI開啟流程源碼,本著前人栽樹后人乘涼的原則,有志于android系統開發的新同學們提供一盞明燈,照亮你們前行。
? ? ? ? 本人擼代碼風格,喜歡從app擼到kernel,啟航出發。
一、APP層源碼分析
1.1、尋找頁面activity
adb shell dumpsys window | grep "mCurrentFocus"
執行上面代碼后,
得到頁面WifiSettings2Activity,
由《Android11 Settings詳解》文章分析可知,對應頁面為WifiSettings2.java,
1.2、尋找頁面開關按鈕布局
public void onCreate(Bundle icicle) {super.onCreate(icicle);// TODO(b/37429702): Add animations and preference comparator back after initial screen is// loaded (ODR).setAnimationAllowed(false);addPreferences();mIsRestricted = isUiRestricted();}
通過addPreferences()加載布局文件,
private void addPreferences() {addPreferencesFromResource(R.xml.wifi_settings2);mConnectedWifiEntryPreferenceCategory = findPreference(PREF_KEY_CONNECTED_ACCESS_POINTS);mWifiEntryPreferenceCategory = findPreference(PREF_KEY_ACCESS_POINTS);mConfigureWifiSettingsPreference = findPreference(PREF_KEY_CONFIGURE_WIFI_SETTINGS);mSavedNetworksPreference = findPreference(PREF_KEY_SAVED_NETWORKS);mAddWifiNetworkPreference = new AddWifiNetworkPreference(getPrefContext());mStatusMessagePreference = findPreference(PREF_KEY_STATUS_MESSAGE);mDataUsagePreference = findPreference(PREF_KEY_DATA_USAGE);mDataUsagePreference.setVisible(DataUsageUtils.hasWifiRadio(getContext()));mDataUsagePreference.setTemplate(NetworkTemplate.buildTemplateWifiWildcard(),0 /*subId*/,null /*service*/);}
對應的布局文件如下
<PreferenceScreenxmlns:android="http://schemas.android.com/apk/res/android"xmlns:settings="http://schemas.android.com/apk/res-auto"android:title="@string/wifi_settings"settings:keywords="@string/keywords_wifi"><com.android.settings.wifi.LinkablePreferenceandroid:key="wifi_status_message"/><PreferenceCategoryandroid:key="connected_access_point"android:layout="@layout/preference_category_no_label"/><PreferenceCategoryandroid:key="access_points"android:layout="@layout/preference_category_no_label"/><Preferenceandroid:key="configure_wifi_settings"android:title="@string/wifi_configure_settings_preference_title"settings:allowDividerAbove="true"android:fragment="com.android.settings.wifi.ConfigureWifiSettings"/><Preferenceandroid:key="saved_networks"android:title="@string/wifi_saved_access_points_label"android:fragment="com.android.settings.wifi.savedaccesspoints2.SavedAccessPointsWifiSettings2"/><com.android.settings.datausage.DataUsagePreferenceandroid:key="wifi_data_usage"android:title="@string/wifi_data_usage"/>
</PreferenceScreen>
發現并沒有WIFI打開按鈕對應的布局,納尼?代碼擼錯了?
在WifiSettings2.java文件里面尋找蛛絲馬跡,WifiSettings2本質是fragment,在onViewCreated接口中發現,
public void onViewCreated(View view, Bundle savedInstanceState) {super.onViewCreated(view, savedInstanceState);final Activity activity = getActivity();if (activity != null) {mProgressHeader = setPinnedHeaderView(R.layout.progress_header).findViewById(R.id.progress_bar_animation);setProgressBarVisible(false);}((SettingsActivity) activity).getSwitchBar().setSwitchBarText(R.string.wifi_settings_master_switch_title,R.string.wifi_settings_master_switch_title);}
跟著走,到SettingsActivity.java文件。哇哦,有點感覺了,哈哈。對應的布局文件settings_main_prefs.xml,是所有設置頁面的SwitchBar共有的,無需fragment增加布局,見下。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_height="match_parent"android:layout_width="match_parent"><com.android.settings.widget.SwitchBarandroid:id="@+id/switch_bar"android:layout_height="?android:attr/actionBarSize"android:layout_width="match_parent"android:theme="?attr/switchBarTheme"/><FrameLayoutandroid:id="@+id/main_content"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"/>
到這里,終于看到廬山真面目了,原來WIFI開關藏在這里,我們繼續擼。在文件WifiSettings.java文件中,構建了WifiEnabler對象,持有SwitchBarController對象,來控制SwitchBar找個UI組件,
private WifiEnabler createWifiEnabler() {final SettingsActivity activity = (SettingsActivity) getActivity();return new WifiEnabler(activity, new SwitchBarController(activity.getSwitchBar()),mMetricsFeatureProvider);}
在WifiEnabler.java文件中,控制開關代碼如下,
public boolean onSwitchToggled(boolean isChecked) {//Do nothing if called as a result of a state machine eventif (mStateMachineEvent) {return true;}// Show toast message if Wi-Fi is not allowed in airplane modeif (isChecked && !WirelessUtils.isRadioAllowed(mContext, Settings.Global.RADIO_WIFI)) {Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show();// Reset switch to off. No infinite check/listener loop.mSwitchWidget.setChecked(false);return false;}if (isChecked) {mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_WIFI_ON);} else {// Log if user was connected at the time of switching off.mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_WIFI_OFF,mConnected.get());}//這里控制WIFI開關,調用了wifimanagerif (!mWifiManager.setWifiEnabled(isChecked)) {// ErrormSwitchWidget.setEnabled(true);Toast.makeText(mContext, R.string.wifi_error, Toast.LENGTH_SHORT).show();}return true;}
mWifiManager.setWifiEnabled(isChecked),看到這行調用很興奮,有沒有?
APP層面代碼擼完了,接下來到framework層,follow me!
二,framework層代碼分析
接著第一章講解,
2.1 開啟wifi入口
在文件WifiManager.java中,
public boolean setWifiEnabled(boolean enabled) {try {return mService.setWifiEnabled(mContext.getOpPackageName(), enabled);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}
調用到WifiServiceImpl.java文件中,
@Overridepublic synchronized boolean setWifiEnabled(String packageName, boolean enable) {mWifiMetrics.incrementNumWifiToggles(isPrivileged, enable);//核心入口mActiveModeWarden.wifiToggled();return true;}
到文件ActiveModeWarden.java文件中,
/** Wifi has been toggled. */public void wifiToggled() {mWifiController.sendMessage(WifiController.CMD_WIFI_TOGGLED);}
接下來由ActiveModeWarden.java文件內部的WifiController處理CMD_WIFI_TOGGLED消息
在打開wifi的情況下,此時wifi是disabled,由DisabledState處理,
class DisabledState extends BaseState {@Overridepublic void enter() {log("DisabledState.enter()");super.enter();if (hasAnyModeManager()) {Log.e(TAG, "Entered DisabledState, but has active mode managers");}}@Overridepublic void exit() {log("DisabledState.exit()");super.exit();}@Overridepublic boolean processMessageFiltered(Message msg) {switch (msg.what) {case CMD_WIFI_TOGGLED:case CMD_SCAN_ALWAYS_MODE_CHANGED:if (shouldEnableSta()) {startClientModeManager();transitionTo(mEnabledState);}break;
..................................................................
走到startClientModeManager(),
private boolean startClientModeManager() {Log.d(TAG, "Starting ClientModeManager");ClientListener listener = new ClientListener();ClientModeManager manager = mWifiInjector.makeClientModeManager(listener);listener.setActiveModeManager(manager);manager.start();if (!switchClientModeManagerRole(manager)) {return false;}mActiveModeManagers.add(manager);return true;}
走到ClientModeManager.java,
public void start() {mTargetRole = ROLE_CLIENT_SCAN_ONLY;mStateMachine.sendMessage(ClientModeStateMachine.CMD_START);}
走到 mWifiNative.setupInterfaceForClientInScanMode( mWifiNativeInterfaceCallback),setupInterfaceForClientInScanMode
傳入了一個mWifiNativeInterfaceCallback
用來來自native層的iface狀態回調,
private class IdleState extends State {@Overridepublic void enter() {Log.d(TAG, "entering IdleState");mClientInterfaceName = null;mIfaceIsUp = false;}@Overridepublic boolean processMessage(Message message) {switch (message.what) {case CMD_START:// Always start in scan mode first.mClientInterfaceName =mWifiNative.setupInterfaceForClientInScanMode(mWifiNativeInterfaceCallback);if (TextUtils.isEmpty(mClientInterfaceName)) {Log.e(TAG, "Failed to create ClientInterface. Sit in Idle");mModeListener.onStartFailure();break;}transitionTo(mScanOnlyModeState);break;
2.2?WiFiNative
上面涉及到setupInterfaceForClientInScanMode(mWifiNativeInterfaceCallback);走到WifiNative.java文件,
// 1. 初始化驅動和vendor hal
startHal();
// 2. 初始化interface
Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_STA_FOR_SCAN);
iface.externalListener = interfaceCallback;
iface.name = createStaIface(iface, requestorWs);
// 3. 初始化wificond
mWifiCondManager.setupInterfaceForClientMode(iface.name, Runnable::run,new NormalScanEventCallback(iface.name),new PnoScanEventCallback(iface.name));//4. 監聽interface的down/up
iface.networkObserver = new NetworkObserverInternal(iface.id);
registerNetworkObserver(iface.networkObserver)// 5. 啟動supplicant監聽(但是此時supplicant進程還未啟動)
mWifiMonitor.startMonitoring(iface.name);
onInterfaceStateChanged(iface, isInterfaceUp(iface.name));
mWifiVendorHal.enableLinkLayerStats(iface.name);// 6. 獲取芯片支持的wifi feature
iface.featureSet = getSupportedFeatureSetInternal(iface.name);
接下來進入另外一個世界,hal層。
WifiNative -> WifiVendorHal -> HalDeviceManager
三,HAL層代碼分析
WifiNative.startHal() -> WifiVendorHal.startVendorHal() -> HalDeviceManager.start() -> HalDeviceManager.startWifi(),代碼流程如下,
a,?WifiNative#startHal()
private boolean startHal() {synchronized (mLock) {if (!mIfaceMgr.hasAnyIface()) {if (mWifiVendorHal.isVendorHalSupported()) {if (!mWifiVendorHal.startVendorHal()) {Log.e(TAG, "Failed to start vendor HAL");return false;}} else {Log.i(TAG, "Vendor Hal not supported, ignoring start.");}}return true;}}
b, WifiVendorHal#startVendorHal
public boolean startVendorHal() {synchronized (sLock) {if (!mHalDeviceManager.start()) {mLog.err("Failed to start vendor HAL").flush();return false;}mLog.info("Vendor Hal started successfully").flush();return true;}}
c,HalDeviceManager#start()
private boolean startWifi() {if (VDBG) Log.d(TAG, "startWifi");initIWifiIfNecessary();synchronized (mLock) {try {if (mWifi == null) {Log.w(TAG, "startWifi called but mWifi is null!?");return false;} else {int triedCount = 0;while (triedCount <= START_HAL_RETRY_TIMES) {//核心調用,調用hal層startWifiStatus status = mWifi.start();if (status.code == WifiStatusCode.SUCCESS) {initIWifiChipDebugListeners();managerStatusListenerDispatch();if (triedCount != 0) {Log.d(TAG, "start IWifi succeeded after trying "+ triedCount + " times");}return true;} else if (status.code == WifiStatusCode.ERROR_NOT_AVAILABLE) {// Should retry. Hal might still be stopping.Log.e(TAG, "Cannot start IWifi: " + statusString(status)+ ", Retrying...");try {Thread.sleep(START_HAL_RETRY_INTERVAL_MS);} catch (InterruptedException ignore) {// no-op}triedCount++;} else {// Should not retry on other failures.Log.e(TAG, "Cannot start IWifi: " + statusString(status));return false;}}Log.e(TAG, "Cannot start IWifi after trying " + triedCount + " times");return false;}} catch (RemoteException e) {Log.e(TAG, "startWifi exception: " + e);return false;}}}
mWifi.start()關鍵行,調用hal層wifi,hardware/interface/wifi1.6/default/wifi.cpp
Return<void> Wifi::start(start_cb hidl_status_cb) {return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::startInternal,hidl_status_cb);
}WifiStatus Wifi::startInternal() {// ... ...WifiStatus wifi_status = initializeModeControllerAndLegacyHal();// ... ...// Create the chip instance once the HAL is started.android::hardware::wifi::V1_0::ChipId chipId = kPrimaryChipId;for (auto& hal : legacy_hals_) {chips_.push_back(new WifiChip(chipId, chipId == kPrimaryChipId, hal, mode_controller_,std::make_shared<iface_util::WifiIfaceUtil>(iface_tool_, hal),feature_flags_, on_subsystem_restart_callback));chipId++;}
}WifiStatus Wifi::initializeModeControllerAndLegacyHal() {if (!mode_controller_->initialize()) {LOG(ERROR) << "Failed to initialize firmware mode controller";return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);}legacy_hal::wifi_error legacy_status = legacy_hal_->initialize();if (legacy_status != legacy_hal::WIFI_SUCCESS) {LOG(ERROR) << "Failed to initialize legacy HAL: "<< legacyErrorToString(legacy_status);return createWifiStatusFromLegacyError(legacy_status);}return createWifiStatus(WifiStatusCode::SUCCESS);
}
legacy_hal_->initialize()關鍵句調用,
wifi_error WifiLegacyHal::initialize() {LOG(DEBUG) << "Initialize legacy HAL";// TODO: Add back the HAL Tool if we need to. All we need from the HAL tool// for now is this function call which we can directly call.if (!initHalFuncTableWithStubs(&global_func_table_)) {LOG(ERROR)<< "Failed to initialize legacy hal function table with stubs";return WIFI_ERROR_UNKNOWN;}wifi_error status = init_wifi_vendor_hal_func_table(&global_func_table_);if (status != WIFI_SUCCESS) {LOG(ERROR) << "Failed to initialize legacy hal function table";}return status;
}
我們以libwifi-hal-qcom
為例,其init_wifi_vendor_hal_func_table()
方法如下,只是為函數指針賦值,
// hardware/qcom/wlan/qcwcn/wifi_hal/wifi_hal.cpp
/*initialize function pointer table with Qualcomm HAL API*/
wifi_error init_wifi_vendor_hal_func_table(wifi_hal_fn *fn) {if (fn == NULL) {return WIFI_ERROR_UNKNOWN;}fn->wifi_initialize = wifi_initialize;fn->wifi_wait_for_driver_ready = wifi_wait_for_driver_ready;fn->wifi_cleanup = wifi_cleanup;fn->wifi_event_loop = wifi_event_loop;fn->wifi_get_supported_feature_set = wifi_get_supported_feature_set;fn->wifi_get_concurrency_matrix = wifi_get_concurrency_matrix;fn->wifi_set_scanning_mac_oui = wifi_set_scanning_mac_oui;fn->wifi_get_ifaces = wifi_get_ifaces;fn->wifi_get_iface_name = wifi_get_iface_name;fn->wifi_set_iface_event_handler = wifi_set_iface_event_handler;fn->wifi_reset_iface_event_handler = wifi_reset_iface_event_handler;fn->wifi_start_gscan = wifi_start_gscan;fn->wifi_stop_gscan = wifi_stop_gscan;fn->wifi_get_cached_gscan_results = wifi_get_cached_gscan_results;fn->wifi_set_bssid_hotlist = wifi_set_bssid_hotlist;fn->wifi_reset_bssid_hotlist = wifi_reset_bssid_hotlist;fn->wifi_set_significant_change_handler = wifi_set_significant_change_handler;fn->wifi_reset_significant_change_handler = wifi_reset_significant_change_handler;fn->wifi_get_gscan_capabilities = wifi_get_gscan_capabilities;fn->wifi_set_link_stats = wifi_set_link_stats;fn->wifi_get_link_stats = wifi_get_link_stats;fn->wifi_clear_link_stats = wifi_clear_link_stats;fn->wifi_get_valid_channels = wifi_get_valid_channels;fn->wifi_rtt_range_request = wifi_rtt_range_request;fn->wifi_rtt_range_cancel = wifi_rtt_range_cancel;fn->wifi_get_rtt_capabilities = wifi_get_rtt_capabilities;fn->wifi_rtt_get_responder_info = wifi_rtt_get_responder_info;fn->wifi_enable_responder = wifi_enable_responder;fn->wifi_disable_responder = wifi_disable_responder;fn->wifi_set_nodfs_flag = wifi_set_nodfs_flag;fn->wifi_start_logging = wifi_start_logging;fn->wifi_set_epno_list = wifi_set_epno_list;fn->wifi_reset_epno_list = wifi_reset_epno_list;fn->wifi_set_country_code = wifi_set_country_code;fn->wifi_enable_tdls = wifi_enable_tdls;fn->wifi_disable_tdls = wifi_disable_tdls;fn->wifi_get_tdls_status = wifi_get_tdls_status;fn->wifi_get_tdls_capabilities = wifi_get_tdls_capabilities;fn->wifi_get_firmware_memory_dump = wifi_get_firmware_memory_dump;fn->wifi_set_log_handler = wifi_set_log_handler;fn->wifi_reset_log_handler = wifi_reset_log_handler;fn->wifi_set_alert_handler = wifi_set_alert_handler;fn->wifi_reset_alert_handler = wifi_reset_alert_handler;fn->wifi_get_firmware_version = wifi_get_firmware_version;fn->wifi_get_ring_buffers_status = wifi_get_ring_buffers_status;fn->wifi_get_logger_supported_feature_set = wifi_get_logger_supported_feature_set;fn->wifi_get_ring_data = wifi_get_ring_data;fn->wifi_get_driver_version = wifi_get_driver_version;fn->wifi_set_passpoint_list = wifi_set_passpoint_list;fn->wifi_reset_passpoint_list = wifi_reset_passpoint_list;fn->wifi_set_lci = wifi_set_lci;fn->wifi_set_lcr = wifi_set_lcr;fn->wifi_start_sending_offloaded_packet =wifi_start_sending_offloaded_packet;fn->wifi_stop_sending_offloaded_packet = wifi_stop_sending_offloaded_packet;fn->wifi_start_rssi_monitoring = wifi_start_rssi_monitoring;fn->wifi_stop_rssi_monitoring = wifi_stop_rssi_monitoring;fn->wifi_nan_enable_request = nan_enable_request;fn->wifi_nan_disable_request = nan_disable_request;fn->wifi_nan_publish_request = nan_publish_request;fn->wifi_nan_publish_cancel_request = nan_publish_cancel_request;fn->wifi_nan_subscribe_request = nan_subscribe_request;fn->wifi_nan_subscribe_cancel_request = nan_subscribe_cancel_request;fn->wifi_nan_transmit_followup_request = nan_transmit_followup_request;fn->wifi_nan_stats_request = nan_stats_request;fn->wifi_nan_config_request = nan_config_request;fn->wifi_nan_tca_request = nan_tca_request;fn->wifi_nan_beacon_sdf_payload_request = nan_beacon_sdf_payload_request;fn->wifi_nan_register_handler = nan_register_handler;fn->wifi_nan_get_version = nan_get_version;fn->wifi_set_packet_filter = wifi_set_packet_filter;fn->wifi_get_packet_filter_capabilities = wifi_get_packet_filter_capabilities;fn->wifi_read_packet_filter = wifi_read_packet_filter;fn->wifi_nan_get_capabilities = nan_get_capabilities;fn->wifi_nan_data_interface_create = nan_data_interface_create;fn->wifi_nan_data_interface_delete = nan_data_interface_delete;fn->wifi_nan_data_request_initiator = nan_data_request_initiator;fn->wifi_nan_data_indication_response = nan_data_indication_response;fn->wifi_nan_data_end = nan_data_end;fn->wifi_configure_nd_offload = wifi_configure_nd_offload;fn->wifi_get_driver_memory_dump = wifi_get_driver_memory_dump;fn->wifi_get_wake_reason_stats = wifi_get_wake_reason_stats;fn->wifi_start_pkt_fate_monitoring = wifi_start_pkt_fate_monitoring;fn->wifi_get_tx_pkt_fates = wifi_get_tx_pkt_fates;fn->wifi_get_rx_pkt_fates = wifi_get_rx_pkt_fates;fn->wifi_get_roaming_capabilities = wifi_get_roaming_capabilities;fn->wifi_configure_roaming = wifi_configure_roaming;fn->wifi_enable_firmware_roaming = wifi_enable_firmware_roaming;fn->wifi_select_tx_power_scenario = wifi_select_tx_power_scenario;fn->wifi_reset_tx_power_scenario = wifi_reset_tx_power_scenario;fn->wifi_set_radio_mode_change_handler = wifi_set_radio_mode_change_handler;fn->wifi_virtual_interface_create = wifi_virtual_interface_create;fn->wifi_virtual_interface_delete = wifi_virtual_interface_delete;fn->wifi_set_latency_mode = wifi_set_latency_mode;fn->wifi_set_thermal_mitigation_mode = wifi_set_thermal_mitigation_mode;fn->wifi_set_dtim_config = wifi_set_dtim_config;return WIFI_SUCCESS;
成功獲取到vendor hal接口后,對所有的legacy hal執行初始化