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

Wifi 笔记 | 启动流程

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

    csd:csdn_of_coder/article/details/51541094
    aosp: Android O

    Android网络各个模式中,Wifi应该是目前最常用的一种网络方式了;下面就简单介绍下Android中Wifi的启动流程。
    当我在Setting菜单里点击打开Wifi时,调用的入口函数是WifiManager::setWifiEnabled(boolean enabled):

    用户可以通过systemUi和设置里的WiFi开关打开WiFi,这时候会调用到wifi framework的相关接口,继而再继续往下启用具体的硬件完成WiFi启动流程,这里只对应用到framework层有些简单的了解,本篇也主要注重framework这一块

    一、WIFI启动总体流程

    WiFi打开流程还是从设置的WiFi开关开始梳理吧,不考虑打开飞行模式后打开WiFi的情况


    总体流程

    二、WIFI启动分步详解:

    2.1 设置启动WiFi

    设置这边说到底其实就是监控WiFi开关的变化,然后根据开关走对应的逻辑处理。
    两个比较重要的类:

    • WifiSettings:设置中wifi主界面所对应的代码
    • WifiEnabler:设置中负责wifi开关打开和关闭事件处理的类
    2.1.1 WifiSettings
    //packages/apps/Settings/src/com/android/settings/wifi/WifiSettings.java
    private WifiEnabler createWifiEnabler() {
        final SettingsActivity activity = (SettingsActivity) getActivity();
        return new WifiEnabler(activity, new SwitchBarController(activity.getSwitchBar()),
            mMetricsFeatureProvider);
    }
    //packages/apps/Settings/src/com/android/settings/widget/SwitchBarController.java
    public class SwitchBarController extends SwitchWidgetController implements
        
    }
    
    2.1.2 WifiEnabler
    //packages/apps/Settings/src/com/android/settings/wifi/WifiEnabler.java
    WifiEnabler(Context context, SwitchWidgetController switchWidget,
        }
        //省略N多代码
        {
              mWifiManager.setWifiEnabled(isChecked)) {
        }
    }
    
    
    2.1.3 总结:

    看到这里其实发现应用层打开和关闭WiFi就是调用了下WifiManager的setWifiEabled(boolean)接口即可。

    2.2 WiFi framework
    2.2.1 WifiManager的setWifiEabled接口
    //framework/base/wifi/java/android/net/wifi/WifiManager.java
    public boolean setWifiEnabled(boolean enabled) {
            try {
                return mService.setWifiEnabled(mContext.getOpPackageName(), enabled);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    
    2.2.2 WifiService的setWifiEnabled
    IWifiManager mService;
    public WifiManager(Context context, IWifiManager service, Looper looper) {
            mContext = context;
            mService = service;
            mLooper = looper;
            mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
        }
    mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    
    2.2.3 注册服务
    ///framework/base/core/java/android/app/SystemServiceRegistry.java
    registerService(Context.WIFI_SERVICE, WifiManager.class,
                    new CachedServiceFetcher<WifiManager>() {
                @Override
                public WifiManager createService(ContextImpl ctx) throws ServiceNotFoundException {
                    IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_SERVICE);
                    IWifiManager service = IWifiManager.Stub.asInterface(b);
                    return new WifiManager(ctx.getOuterContext(), service,
                            ConnectivityThread.getInstanceLooper());
                }});
    IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_SERVICE);
    
    2.2.4 WifiService

    SystemServer启动WifiService
    private static final String WIFI_SERVICE_CLASS ="com.android.server.wifi.WifiService";
    mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
    WifiService 是接口类,WifiServiceImpl 是实现类

    public final class WifiService extends SystemService {
     
        private static final String TAG = "WifiService";
        final WifiServiceImpl mImpl;
     
        public WifiService(Context context) {
            super(context);
            mImpl = new WifiServiceImpl(context, new WifiInjector(context), new WifiAsyncChannel(TAG));
        }
     
        @Override
        public void onStart() {
            Log.i(TAG, "Registering " + Context.WIFI_SERVICE);
            publishBinderService(Context.WIFI_SERVICE, mImpl);
        }
    
    2.3 Service的WiFi启动流程
    public class WifiServiceImpl extends IWifiManager.Stub {
     
        /**
         * see {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)}
         * @param enable {@code true} to enable, {@code false} to disable.
         * @return {@code true} if the enable/disable operation was
         *         started or is already in the queue.
         */
        @Override
        public synchronized boolean setWifiEnabled(String packageName, boolean enable)
                throws RemoteException {
            enforceChangePermission();
            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 =
                    mWifiStateMachine.syncGetWifiApState() != WifiManager.WIFI_AP_STATE_DISABLED;
     
            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;
        }
    
    2.3.1 WifiController 中的WIFI

    service会调用WifiController来处理WIFI的启动,WifiController是一个状态机,异步处理WIF启动 过程
    mWifiController.sendMessage(CMD_WIFI_TOGGLED);
    mSettingsStore.handleWifiToggled(enable)设置一下SettingsProvider中存储的WIFI_ON的值

    public synchronized boolean handleWifiToggled(boolean wifiEnabled) {
            // Can Wi-Fi be toggled in airplane mode ?
            if (mAirplaneModeOn && !isAirplaneToggleable()) {
                return false;
            }
     
            if (wifiEnabled) {
                if (mAirplaneModeOn) {
                    persistWifiState(WIFI_ENABLED_AIRPLANE_OVERRIDE);
                } else {
                    persistWifiState(WIFI_ENABLED);
                }
            } else {
                // When wifi state is disabled, we do not care
                // if airplane mode is on or not. The scenario of
                // wifi being disabled due to airplane mode being turned on
                // is handled handleAirplaneModeToggled()
                persistWifiState(WIFI_DISABLED);
            }
            return true;
        }
    

    WifiServiceImpl在走到WifiController之前有提及修改了一下SettingsProvider,其实也顺带改了一下WifiSettingsStore的mPersistWifiState值,用来标记wifi状态。

    persistWifiState(WIFI_ENABLED);
    public synchronized boolean isWifiToggleEnabled() {
            if (!mCheckSavedStateAtBoot) {
                mCheckSavedStateAtBoot = true;
                if (testAndClearWifiSavedState()) return true;
            }
     
            if (mAirplaneModeOn) {
                return mPersistWifiState == WIFI_ENABLED_AIRPLANE_OVERRIDE;
            } else {
                return mPersistWifiState != WIFI_DISABLED;
            }
        }
    private boolean doDeferEnable(Message msg) {
                long delaySoFar = SystemClock.elapsedRealtime() - mDisabledTimestamp;
                if (delaySoFar >= mReEnableDelayMillis) {
                    return false;
                }
     
                log("WifiController msg " + msg + " deferred for " +
                        (mReEnableDelayMillis - delaySoFar) + "ms");
     
                // need to defer this action.
                Message deferredMsg = obtainMessage(CMD_DEFERRED_TOGGLE);
                deferredMsg.obj = Message.obtain(msg);
                deferredMsg.arg1 = ++mDeferredEnableSerialNumber;
                sendMessageDelayed(deferredMsg, mReEnableDelayMillis - delaySoFar + DEFER_MARGIN_MS);
                return true;
            }
            mReEnableDelayMillis = mFacade.getLongSetting(mContext,
                    Settings.Global.WIFI_REENABLE_DELAY_MS, DEFAULT_REENABLE_DELAY_MS);
    
    2.3.2 WifiStateMachine 状态机

    mWifiStateMachine.setOperationalMode(WifiStateMachine.CONNECT_MODE);
    mWifiStateMachine.setSupplicantRunning(true);
    mWifiStateMachine.setOperationalMode(WifiStateMachine.CONNECT_MODE);
    mWifiStateMachine.setHighPerfModeEnabled(false);

    在状态处理中会发送:CMD_START_SUPPLICANT 启动协议栈的认证机制wpa_supplicant
    接收到该消息进行的关键操作:
    mWifiNative.enableSupplicant()
    mWifiMonitor.startMonitoring(mInterfaceName, true);
    切换到SupplicantStartingState状态

    2.3.4 协议栈
        public boolean enableSupplicant() {
            return mWificondControl.enableSupplicant();
        }
    public synchronized void startMonitoring(String iface, boolean isStaIface) {
            if (ensureConnectedLocked()) {
                setMonitoring(iface, true);
                broadcastSupplicantConnectionEvent(iface);
            } else {
                boolean originalMonitoring = isMonitoring(iface);
                setMonitoring(iface, true);
                broadcastSupplicantDisconnectionEvent(iface);
                setMonitoring(iface, originalMonitoring);
                Log.e(TAG, "startMonitoring(" + iface + ") failed!");
            }
        }
    
    2.3.5 WifiNative中的Supplicant
    private void setSuspendOptimizationsNative(int reason, boolean enabled) {
            if (mVerboseLoggingEnabled) {
                log("setSuspendOptimizationsNative: " + reason + " " + enabled
                        + " -want " + mUserWantsSuspendOpt.get()
                        + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName()
                        + " - " + Thread.currentThread().getStackTrace()[3].getMethodName()
                        + " - " + Thread.currentThread().getStackTrace()[4].getMethodName()
                        + " - " + Thread.currentThread().getStackTrace()[5].getMethodName());
            }
            //mWifiNative.setSuspendOptimizations(enabled);
     
            if (enabled) {
                mSuspendOptNeedsDisabled &= ~reason;
                /* None of dhcp, screen or highperf need it disabled and user wants it enabled */
                if (mSuspendOptNeedsDisabled == 0 && mUserWantsSuspendOpt.get()) {
                    if (mVerboseLoggingEnabled) {
                        log("setSuspendOptimizationsNative do it " + reason + " " + enabled
                                + " stack:" + Thread.currentThread().getStackTrace()[2].getMethodName()
                                + " - " + Thread.currentThread().getStackTrace()[3].getMethodName()
                                + " - " + Thread.currentThread().getStackTrace()[4].getMethodName()
                                + " - " + Thread.currentThread().getStackTrace()[5].getMethodName());
                    }
                    mWifiNative.setSuspendOptimizations(true);
                }
            } else {
                mSuspendOptNeedsDisabled |= reason;
                mWifiNative.setSuspendOptimizations(false);
            }
        }
    

    完~~~
    整理 | 力卉编程

    相关文章

      网友评论

        本文标题:Wifi 笔记 | 启动流程

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