Wifi模块—源码分析Wifi启动(Android P)

一、前言

Android P在wifi这块改动挺大的,Wifi到AndoidO之后不再使用jni,所以AndroidP也一样不再使用jni来实现Java代码与本地的C/C++代码交互,而是使用HIDL,Hardware Interface Define Language。摒弃了以前的hardware/libhardware_legacy/wifi/wifi.c作为底层接口,所以得重新梳理下整个wifi流程。

点击Wifi开关到Android的Java框架层,可以参考这个Wifi模块—源码分析Wifi启动1(Android P)

这里只记录下 HIDL—WPA适配层—wpa_supplicant—linux kernel

 

二、代码流程

1.Java框架层

frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java


/**
* Setup an interface for Client mode operations.
*
* * This method configures an interface in STA mode in all the native daemons
* (wificond, wpa_supplicant & vendor HAL).
*
* @param lowPrioritySta The requested STA has a low request priority (lower probability of
*                       getting created, higher probability of getting destroyed).
* @param interfaceCallback Associated callback for notifying status changes for the iface.
* @return Returns the name of the allocated interface, will be null on failure.
*/
public String setupInterfaceForClientMode(boolean lowPrioritySta,
@NonNull InterfaceCallback interfaceCallback) {
    synchronized (mLock) {
        if (!startHal()) {
            Log.e(TAG, "Failed to start Hal");
            mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal();
            return null;
        }
        if (!startSupplicant()) {
            Log.e(TAG, "Failed to start supplicant");
            mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant();
            return null;
        }
        Iface iface = mIfaceMgr.allocateIface(Iface.IFACE_TYPE_STA);
        if (iface == null) {
            Log.e(TAG, "Failed to allocate new STA iface");
            return null;
        }
        iface.externalListener = interfaceCallback;
        iface.name = createStaIface(iface, lowPrioritySta);
        if (TextUtils.isEmpty(iface.name)) {
            Log.e(TAG, "Failed to create STA iface in vendor HAL");
            mIfaceMgr.removeIface(iface.id);
            mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal();
            return null;
        }
        if (mWificondControl.setupInterfaceForClientMode(iface.name) == null) {
            Log.e(TAG, "Failed to setup iface in wificond on " + iface);
            teardownInterface(iface.name);
            mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToWificond();
            return null;
        }
        if (!mSupplicantStaIfaceHal.setupIface(iface.name)) {
            Log.e(TAG, "Failed to setup iface in supplicant on " + iface);
            teardownInterface(iface.name);
            mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant();
            return null;
        }
        iface.networkObserver = new NetworkObserverInternal(iface.id);
        if (!registerNetworkObserver(iface.networkObserver)) {
            Log.e(TAG, "Failed to register network observer on " + iface);
            teardownInterface(iface.name);
            return null;
        }
        mWifiMonitor.startMonitoring(iface.name);
        // Just to avoid any race conditions with interface state change callbacks,
        // update the interface state before we exit.
        onInterfaceStateChanged(iface, isInterfaceUp(iface.name));
        initializeNwParamsForClientInterface(iface.name);
        Log.i(TAG, "Successfully setup " + iface);
        return iface.name;
    }
}

看一些关键性的操作:

                         启动Hal:startHal()

                         启动supplicant:startSupplicant()

先分析startHAL

/** Helper method invoked to start supplicant if there were no ifaces */
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;
    }
}

看mWifiVendorHal.startVendorHal()

 

frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiVendorHal.java

/**
* Bring up the HIDL Vendor HAL.
* @return true on success, false otherwise.
*/
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;
    }
}

看mHalDeviceaManager.start()

 

frameworks/opt/net/wifi/service/java/com/android/server/wifi/HalDeviceManager.java

/**
* Attempts to start Wi-Fi (using HIDL). Returns the success (true) or failure (false) or
* the start operation. Will also dispatch any registered ManagerStatusCallback.onStart() on
* success.
*
* Note: direct call to HIDL.
*/
public boolean start() {
    return startWifi();
}

继续看startWifi()


private boolean startWifi() {
    if (VDBG) Log.d(TAG, "startWifi");
 
    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) {
                    WifiStatus 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;
        }
    }
}

主要看WifiStatus status = mWifi.start(),先看下mWifi是什么

import android.hardware.wifi.V1_0.IWifi;
private IWifi mWifi;
/**
* Wrapper function to access the HIDL services. Created to be mockable in unit-tests.
*/
protected IWifi getWifiServiceMockable() {
    try {
        return IWifi.getService();
    } catch (RemoteException e) {
        Log.e(TAG, "Exception getting IWifi service: " + e);
        return null;
    }
}

IWifi的定义就需要用到HIDL

 

2.HIDL

HIDL 读作 hide-l,Wifi到Andoid O之后所以Android P也一样不再使用jni,而是使用HIDL,Hardware Interface Define Language。

2.1 hardware/interfaces/wifi/1.0/IWifi.hal

/**
* Perform any setup that is required to make use of the module. If the module
* is already started then this must be a noop.
* Must trigger |IWifiEventCallback.onStart| on success.
*
* @return status WifiStatus of the operation.
*         Possible status codes:
*         |WifiStatusCode.SUCCESS|,
*         |WifiStatusCode.NOT_AVAILABLE|,
*         |WifiStatusCode.UNKNOWN|
*/
@entry
@callflow(next={"registerEventCallback", "start", "stop", "getChip"})
start() generates (WifiStatus status);

系统编译的时候会自动产生IWifi.java文件。

out/soong/.intermediates/hardware/interfaces/wifi/1.0/android.hardware.wifi_V1.0-java_gen_java/gen/android/hardware/wifi/V1_0/IWifi.java

IWifi.java的getService方法
 

public static IWifi getService(String serviceName) throws android.os.RemoteException {
          return IWifi.asInterface(android.os.HwBinder.getService("android.hardware.wifi@1.0::IWifi",serviceName));
      }

再看一下 IWifi.java的asInterface方法

IWifi.asInterface(android.os.HwBinder.getService("android.hardware.wifi@1.0::IWifi",serviceName));

从而我们就可以知道IWifi对应的服务端了

 

2.2 在hardware/interfaces/wifi/有三个版本,分别是1.0 /1.1 /1.2,使用哪个版本是可以设置的,wpa_supplicant和hostapd同理

device/fsl/imx8m/evk_8mq/manifest.xml

    <hal format="hidl">
       <name>android.hardware.wifi</name>
       <transport>hwbinder</transport>
       <version>1.2</version>
       <interface>
           <name>IWifi</name>
           <instance>default</instance>
       </interface>
    </hal>
    <hal format="hidl">
       <name>android.hardware.wifi.supplicant</name>
       <transport>hwbinder</transport>
       <version>1.1</version>
       <interface>
           <name>ISupplicant</name>
           <instance>default</instance>
       </interface>
    </hal>
    <hal format="hidl">
        <name>android.hardware.wifi.hostapd</name>
        <transport>hwbinder</transport>
        <version>1.0</version>
        <interface>
            <name>IHostapd</name>
            <instance>default</instance>
        </interface>
    </hal>

hardware/interfaces/wifi/1.2/default/wifi.cpp

Return<void> Wifi::start(start_cb hidl_status_cb) {
    return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,
            &Wifi::startInternal, hidl_status_cb);
}

  看startInternal()

WifiStatus Wifi::startInternal() {
    if (run_state_ == RunState::STARTED) {
        return createWifiStatus(WifiStatusCode::SUCCESS);
    } else if (run_state_ == RunState::STOPPING) {
        return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE,
                                "HAL is stopping");
    }
    WifiStatus wifi_status = initializeModeControllerAndLegacyHal();
    if (wifi_status.code == WifiStatusCode::SUCCESS) {
        // Create the chip instance once the HAL is started.
        chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_,
                            feature_flags_);
        run_state_ = RunState::STARTED;
        for (const auto& callback : event_cb_handler_.getCallbacks()) {
            if (!callback->onStart().isOk()) {
                LOG(ERROR) << "Failed to invoke onStart callback";
            };
        }
        LOG(INFO) << "Wifi HAL started";
    } else {
        for (const auto& callback : event_cb_handler_.getCallbacks()) {
            if (!callback->onFailure(wifi_status).isOk()) {
                LOG(ERROR) << "Failed to invoke onFailure callback";
            }
        }
        LOG(ERROR) << "Wifi HAL start failed";
    }
    return wifi_status;
}
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);
}

接着看wifi_mode_controller.cpp得initialize()方法

2.3 hardware/interfaces/wifi/1.2/default/wifi_mode_controller.cpp

bool WifiModeController::initialize() {
    if (!driver_tool_->LoadDriver()) {
        LOG(ERROR) << "Failed to load WiFi driver";
        return false;
    }
    return true;
}

再继续看driver_tool.cpp这里开始走到WPA适配层了

3 WPA适配层(硬件抽象层 HAL)

 HAL 可定义一个标准接口以供硬件供应商实现,这可让 Android 忽略较低级别的驱动程序实现。借助 HAL,可以顺利实现相关功能,而不会影响或更改更高级别的系统。HAL 实现会被封装成模块,并由 Android 系统适时地加载。

      wpa_supplicant适配层是通用的wpa_supplicant的封装,在Android中作为WiFi部分的硬件抽象层来使用。wpa_supplicant适配层主要用于与wpa_supplicant守护进程的通信,以提供给Android框架使用,它实现了加载、控制和消息监控等功能。

3.1frameworks/opt/net/wifi/libwifi_hal/driver_tool.cpp

bool DriverTool::LoadDriver() {
  return ::wifi_load_driver() == 0;
}

2.2 frameworks/opt/net/wifi/libwifi_hal/wifi_hal_common.cpp

int wifi_load_driver() {
#ifdef WIFI_DRIVER_MODULE_PATH
  if (is_wifi_driver_loaded()) {
    return 0;
  }
 
  if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0) return -1;
#endif
 
#ifdef WIFI_DRIVER_STATE_CTRL_PARAM
  if (is_wifi_driver_loaded()) {
    return 0;
  }
 
  if (wifi_change_driver_state(WIFI_DRIVER_STATE_ON) < 0) return -1;
#endif
  property_set(DRIVER_PROP_NAME, "ok");
  return 0;
}

到这里Wifi驱动就加载完成了

 

4 wpa_supplicant

现在回到文章的最开始分析完了startHal(),接下来就该分析startSupplicant()

 4.1 frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java

    /** Helper method invoked to start supplicant if there were no STA ifaces */
    private boolean startSupplicant() {
        synchronized (mLock) {
            if (!mIfaceMgr.hasAnyStaIface()) {
                if (!mWificondControl.enableSupplicant()) {
                    Log.e(TAG, "Failed to enable supplicant");
                    return false;
                }    
                if (!waitForSupplicantConnection()) {
                    Log.e(TAG, "Failed to connect to supplicant");
                    return false;
                }    
                if (!mSupplicantStaIfaceHal.registerDeathHandler(
                        new SupplicantDeathHandlerInternal())) {
                    Log.e(TAG, "Failed to register supplicant death handler");
                    return false;
                }    
            }    
            return true;
        }    
    }

看mWificondControl.enableSupplicant()

frameworks/opt/net/wifi/service/java/com/android/server/wifi/WificondControl.java

    /** 
    * Enable wpa_supplicant via wificond.
    * @return Returns true on success.
    */
    public boolean enableSupplicant() {
        if (!retrieveWificondAndRegisterForDeath()) {
            return false;
        }   
        try {
            return mWificond.enableSupplicant();
        } catch (RemoteException e) {
            Log.e(TAG, "Failed to enable supplicant due to remote exception");
        }   
        return false;
    } 

看 mWificond.enableSupplicant()

private IWificond mWificond;
import android.net.wifi.IWificond;

4.2 IWificond的方法

system/connectivity/wificond/server.cpp

Status Server::enableSupplicant(bool* success) {
  *success = supplicant_manager_->StartSupplicant();
  return Status::ok();
}

4.3 frameworks/opt/net/wifi/libwifi_system/supplicant_manager.cpp

bool SupplicantManager::StartSupplicant() {
  char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
  int count = 200; /* wait at most 20 seconds for completion */
  const prop_info* pi;
  unsigned serial = 0;

  /* Check whether already running */
  if (property_get(kSupplicantInitProperty, supp_status, NULL) &&
      strcmp(supp_status, "running") == 0) {
    return true;
  }

  /*
   * Get a reference to the status property, so we can distinguish
   * the case where it goes stopped => running => stopped (i.e.,
   * it start up, but fails right away) from the case in which
   * it starts in the stopped state and never manages to start
   * running at all.
   */
  pi = __system_property_find(kSupplicantInitProperty);
  if (pi != NULL) {
    serial = __system_property_serial(pi);
  }

  property_set("ctl.start", kSupplicantServiceName);
  sched_yield();

  while (count-- > 0) {
    if (pi == NULL) {
      pi = __system_property_find(kSupplicantInitProperty);
    }
    if (pi != NULL) {
      /*
       * property serial updated means that init process is scheduled
       * after we sched_yield, further property status checking is based on this
       */
      if (__system_property_serial(pi) != serial) {
        __system_property_read(pi, NULL, supp_status);
        if (strcmp(supp_status, "running") == 0) {
          return true;
        } else if (strcmp(supp_status, "stopped") == 0) {
          return false;
        }
      }
    }
    usleep(100000);
  }
  return false;
}
namespace {

const char kSupplicantInitProperty[] = "init.svc.wpa_supplicant";
const char kSupplicantServiceName[] = "wpa_supplicant";

}  // namespace

以前wifi.c的start_supplicant就搬到这儿来了

 

到此wifi驱动已经加载,wpa_supplicant服务也已经启动了,wifi的启动流程也就分析完了

 

 

  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值