美文网首页蓝牙和WIFI
Wifi笔记 | Android P 启动流程之startHal

Wifi笔记 | Android P 启动流程之startHal

作者: 力卉编程 | 来源:发表于2020-01-12 11:05 被阅读0次

    android O wifi启动流程主要包括驱动的加载,supplicant的启动,以及supplicant的连接(hidl),之前也看过Android 4.4的WiFi启动流程,前面提及的几个主要部分功能实现还是差不多的,Android O主要引入了Wificond和hidl。

    一、WIFI启动总体总体流程

    WIFI启动总体总体流程

    二、WIFI启动消息图

    WIFI启动消息图

    三、代码流程

    3.1 WifiManager

    public boolean setWifiEnabled(boolean enabled) {
            try {
                return mService.setWifiEnabled(mContext.getOpPackageName(), enabled);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    

    3.2 WifiSerivceImpl

    public synchronized boolean setWifiEnabled(String packageName, boolean enable)
                throws RemoteException {
            if (enforceChangePermission(packageName) != MODE_ALLOWED) {
                return false;
            }
     
            Slog.d(TAG, "setWifiEnabled: " + enable + " pid=" + Binder.getCallingPid()
                        + ", uid=" + Binder.getCallingUid() + ", package=" + packageName);
            mLog.info("setWifiEnabled package=% uid=% enable=%").c(packageName)
                    .c(Binder.getCallingUid()).c(enable).flush();
     
            boolean isFromSettings = checkNetworkSettingsPermission(
                    Binder.getCallingPid(), Binder.getCallingUid());
     
            // If Airplane mode is enabled, only Settings is allowed to toggle Wifi
            if (mSettingsStore.isAirplaneModeOn() && !isFromSettings) {
                mLog.info("setWifiEnabled in Airplane mode: only Settings can enable wifi").flush();
                return false;
            }
     
            // If SoftAp is enabled, only Settings is allowed to toggle wifi
            boolean apEnabled = mWifiApState == WifiManager.WIFI_AP_STATE_ENABLED;
     
            if (apEnabled && !isFromSettings) {
                mLog.info("setWifiEnabled SoftAp not disabled: only Settings can enable wifi").flush();
                return false;
            }
     
            /*
            * Caller might not have WRITE_SECURE_SETTINGS,
            * only CHANGE_WIFI_STATE is enforced
            */
            long ident = Binder.clearCallingIdentity();
            try {
                if (! mSettingsStore.handleWifiToggled(enable)) {
                    // Nothing to do if wifi cannot be toggled
                    return true;
                }
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
     
     
            if (mPermissionReviewRequired) {
                final int wiFiEnabledState = getWifiEnabledState();
                if (enable) {
                    if (wiFiEnabledState == WifiManager.WIFI_STATE_DISABLING
                            || wiFiEnabledState == WifiManager.WIFI_STATE_DISABLED) {
                        if (startConsentUi(packageName, Binder.getCallingUid(),
                                WifiManager.ACTION_REQUEST_ENABLE)) {
                            return true;
                        }
                    }
                } else if (wiFiEnabledState == WifiManager.WIFI_STATE_ENABLING
                        || wiFiEnabledState == WifiManager.WIFI_STATE_ENABLED) {
                    if (startConsentUi(packageName, Binder.getCallingUid(),
                            WifiManager.ACTION_REQUEST_DISABLE)) {
                        return true;
                    }
                }
            }
     
            mWifiController.sendMessage(CMD_WIFI_TOGGLED);
            return true;
        }
    

    3.3 WifiController

    对比Android O的WifiController简略了很多

    • ap相关(softap)剥离了,
    • StaEnabledState和DeviceActiveState其实是一个了,合成一个。
    // CHECKSTYLE:OFF IndentationCheck
            addState(mDefaultState);
                addState(mStaDisabledState, mDefaultState);
                addState(mStaEnabledState, mDefaultState);
                    addState(mDeviceActiveState, mStaEnabledState);
                addState(mStaDisabledWithScanState, mDefaultState);
                addState(mEcmState, mDefaultState);
            // CHECKSTYLE:ON IndentationCheck
    

    看下ModeStateMachine的模式

            // Commands for the state machine  - these will be removed,
            // along with the StateMachine itself
            public static final int CMD_START_CLIENT_MODE    = 0;
            public static final int CMD_START_SCAN_ONLY_MODE = 1;
            public static final int CMD_DISABLE_WIFI         = 3;
    

    有3个模式

    • ClientMode模式,应该就是WiFi普通打开模式,
    • Scan_ONLY应该就是不打开WiFi只打开WiFi扫描的模式,
    • Disable_WIFI应该是上面两个都没打开的情况。

    3.4 ClientModeManager 合并了SoftAp功能,这是Android P的新的改变

    这里从api注释来看解耦出来了一个接口,用于Client, ScanOnly and SoftAp的实现。

    /** Manager WiFi in Client Mode where we connect to configured networks. */
    public class ClientModeManager implements ActiveModeManager {
     /**
     * Base class for available WiFi operating modes.
     *
     * Currently supported modes include Client, ScanOnly and SoftAp.
     */
    public interface ActiveModeManager {
        String TAG = "ActiveModeManager";
     
        /**
         * Method used to start the Manager for a given Wifi operational mode.
         */
        void start();
     
        /**
         * Method used to stop the Manager for a give Wifi operational mode.
         */
        void stop();
     
        /**
         * Method to dump for logging state.
         */
        void dump(FileDescriptor fd, PrintWriter pw, String[] args);
     
        /**
         * Method that allows Mode Managers to update WifiScanner about the current state.
         *
         * @param context Context to use for the notification
         * @param available boolean indicating if scanning is available
         */
        default void sendScanAvailableBroadcast(Context context, boolean available) {
            Log.d(TAG, "sending scan available broadcast: " + available);
            final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE);
            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
            if (available) {
                intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WifiManager.WIFI_STATE_ENABLED);
            } else {
                intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WifiManager.WIFI_STATE_DISABLED);
            }
            context.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
        }
    }
    

    3.5 WifiNative

    WifiNative 主要工作:

    • startHal
    • startSupplicant
    • createStaIface
    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;
            }
        }
    
    3.5.1 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;
            }
        }
    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;
            }
        }
    //HalDeviceManager
    public boolean start() {
            return 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();

    3.5.2 WIFI连接驱动硬件

    最后一句:driver_tool_->LoadDriver()

    //hardware/interfaces/wifi/1.0/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() {
        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);
    }
    ///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;
    }
    
    3.5.3 驱动硬件
    /hardware/interfaces/wifi/1.2/default/wifi_legacy_hal.cpp
    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;
    }
    

    到这边startHal就走完了。

    相关文章

      网友评论

        本文标题:Wifi笔记 | Android P 启动流程之startHal

        本文链接:https://www.haomeiwen.com/subject/ucuiactx.html