Android11 wifi开启源码分析
目录
一、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执行初始化