android wifi flow

本文深入剖析了Android WiFi启动流程,从Wifiservice的注册到开机自动检测WiFi的开关状态,再到用户层面的WiFi开启流程。重点介绍了WiFiManager的获取方式、WiFi启用流程中的权限检查、状态机转换及与wpa_supplicant的交互过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

复习并记录下android wifi相关知识,因为下载的是androidp 的source code,因此codebase就用androidP的版本,复习整个android wifi的flow,我大概会分为以下几个部分来讲解

1 android wifi enable flow

2 androi wifi scanning flow

3 android wifi user connect flow

4 android wifi auto connect flow

5 android network type swtich flow

.....

暂时想写的有上面这些,后续想到了再补充

今天这篇来写一下android wifi enable flow

android 发展到现在,wifi flow 从android N开始实际上已经开始了有了很多的变化,可以说整个架构都已经和原来的不一样了。上层与wpa_supplicant 之间 IPC也在将unix socket (android domain socket) 替换成hidl 方式。更有scan get_scan_result这些都是直接建立netlink socket 与kernel 通信而不通过wpa_supplicant。

首先先看下Wifiservice的注册,以及开机自动检测wifi的开启或关闭流程如下:

一般获取WifiManager有两种方式,

1 mWifiManager = mWifiManager = new WifiManager(mContext, mWifiService, mLooper.getLooper());

2 WifiManager wifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE )

第一种比较好理解,就是new一个WifiManager的实例,而第二种实际上也是new 一个WifiManager的实例,只不过是

这个new 实例的过程是在framework层做的,而不是在app层做的.以下讲解下这个流程,先上图,再解析source code

SystemServiceRegistry

        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());
            }});

而registerService,实际上就是把该类与名称对应存入map中 

    /**
     * Statically registers a system service with the context.
     * This method must be called during static initialization only.
     */
    private static <T> void registerService(String serviceName, Class<T> serviceClass,
            ServiceFetcher<T> serviceFetcher) {
        SYSTEM_SERVICE_NAMES.put(serviceClass, serviceName);
        SYSTEM_SERVICE_FETCHERS.put(serviceName, serviceFetcher);
    }

 使用如下接口获取WifiManger实例mContext.getSystemService(Context.WIFI_SERVICE )则是从map表中查找

Context.java 

public abstract @Nullable Object getSystemService(@ServiceName @NonNull String name);

==>

ContextWrapper.java

    @Override
    public Object getSystemService(String name) {
        return mBase.getSystemService(name);
    }

==>

ConttextImpl.java

1738     @Override
1739     public Object getSystemService(String name) {
1740         return SystemServiceRegistry.getSystemService(this, name);
1741     }

==>SystemServiceRegistry

    public static Object getSystemService(ContextImpl ctx, String name) {
        ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
        return fetcher != null ? fetcher.getService(ctx) : null;
    }

则是用service name在之前注册的map里查找类WifiManger


UI上面打开wifi的flow 如下 

app层会调用到WifiManager的接口

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

通过binder 继而call到 WifiServiceImpl.java

    public synchronized boolean setWifiEnabled(String packageName, boolean enable)
            throws RemoteException {
        if (enforceChangePermission(packageName) != MODE_ALLOWED) {
            return false;
        }
        //打印出uid和apk名称,便于debug
        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;
        }

//权限检测,详细可参照另一篇文章
//https://blog.youkuaiyun.com/lpboss/article/details/86610726

        /*
        * 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;
                }
            }
        }
//给WifiController这个StateMachine发送CMD_WIFI_TOGGLED
        mWifiController.sendMessage(CMD_WIFI_TOGGLED);
        return true;
    }

 

当前WifiController状态机开机后初始状态会在staDisabledState如下

    class StaDisabledState extends State {
        private int mDeferredEnableSerialNumber = 0;
        private boolean mHaveDeferredEnable = false;
        private long mDisabledTimestamp;

        @Override
        public void enter() {
            mWifiStateMachinePrime.disableWifi();
            // Supplicant can't restart right away, so note the time we switched off
            mDisabledTimestamp = SystemClock.elapsedRealtime();
            mDeferredEnableSerialNumber++;
            mHaveDeferredEnable = false;
            mWifiStateMachine.clearANQPCache();
        }
        @Override
        public boolean processMessage(Message msg) {
            switch (msg.what) {
//收到WifiServiceImpl发送过来的CMD_WIFI_TOGGLED,在这个子状态里面处理后,最后会跳转到 mDeviceActiveState子状态 
                case CMD_WIFI_TOGGLED:
                    if (mSettingsStore.isWifiToggleEnabled()) {
                        if (doDeferEnable(msg)) {
                            if (mHaveDeferredEnable) {
                                //  have 2 toggles now, inc serial number and ignore both
                                mDeferredEnableSerialNumber++;
                            }
                            mHaveDeferredEnable = !mHaveDeferredEnable;
                            break;
                        }
                        transitionTo(mDeviceActiveState);
                    } 
                    
...
}

WifiController状态机的层级结构如下:

可以看到mStaEnabledState是mDeviceActiveState的父状态,因此跳转到mDeviceActiveState时,会先要进mStaEnabledState的enter,然后再进mDeviceActiveState的enter

   DeviceActiveState 
        public void enter() {
            mWifiStateMachinePrime.enterClientMode();
            mWifiStateMachine.setHighPerfModeEnabled(false);
        }

在enter function里,调到WifiStateMachinePrime.enterClientMode api

enterClientMode

    /**
     * Method to switch wifi into client mode where connections to configured networks will be
     * attempted.
     */
    public void enterClientMode() {
        changeMode(ModeStateMachine.CMD_START_CLIENT_MODE);
    }

    private void changeMode(int newMode) {
        mModeStateMachine.sendMessage(newMode);
    }

即 发送CMD_START_CLIENT_MODE到ModeStateMachine中

ModeStateMachine当前的状态处在WifiDisabledState ,因此看他的processMessage会对这个cmd做什么处理
 

        class WifiDisabledState extends ModeActiveState {
            @Override
            public void enter() {
                Log.d(TAG, "Entering WifiDisabledState");
                mDefaultModeManager.sendScanAvailableBroadcast(mContext, false);
                mScanRequestProxy.enableScanningForHiddenNetworks(false);
                mScanRequestProxy.clearScanResults();
            }

            @Override
            public boolean processMessage(Message message) {
                Log.d(TAG, "received a message in WifiDisabledState: " + message);
                if (checkForAndHandleModeChange(message)) {
                    return HANDLED;
                }
                return NOT_HANDLED;
            }

        private boolean checkForAndHandleModeChange(Message message) {
            switch(message.what) {
                case ModeStateMachine.CMD_START_CLIENT_MODE:
                    Log.d(TAG, "Switching from " + getCurrentMode() + " to ClientMode");
///////////跳转到 clientModeActiveState子状态 
                    mModeStateMachine.transitionTo(mClientModeActiveState);
                    break;
                case ModeStateMachine.CMD_START_SCAN_ONLY_MODE:
                    Log.d(TAG, "Switching from " + getCurrentMode() + " to ScanOnlyMode");
                    mModeStateMachine.transitionTo(mScanOnlyModeActiveState);
                    break;
                case ModeStateMachine.CMD_DISABLE_WIFI:
                    Log.d(TAG, "Switching from " + getCurrentMode() + " to WifiDisabled");
                    mModeStateMachine.transitionTo(mWifiDisabledState);
                    break;
                default:
                    return NOT_HANDLED;
            }
            return HANDLED;
        }

跳转到mClientModeActiveState 子状态 

            public void enter() {
                Log.d(TAG, "Entering ClientModeActiveState");

                mListener = new ClientListener();
//////调用到WifiInjector里去了。
                mManager = mWifiInjector.makeClientModeManager(mListener);
                mManager.start();
                mActiveModeManagers.add(mManager);

                updateBatteryStatsWifiState(true);
            }

WifiInjector这个类的用途如google说明:

/**
 *  WiFi dependency injector. To be used for accessing various WiFi class instances and as a
 *  handle for mock injection.
 *
 *  Some WiFi class instances currently depend on having a Looper from a HandlerThread that has
 *  been started. To accommodate this, we have a two-phased approach to initialize and retrieve
 *  an instance of the WifiInjector.
 */

用来管理很多wifi相关的类,继续往下走

    /**
     * Create a ClientModeManager
     *
     * @param listener listener for ClientModeManager state changes
     * @return a new instance of ClientModeManager
     */
    public ClientModeManager makeClientModeManager(ClientModeManager.Listener listener) {
        return new ClientModeManager(mContext, mWifiStateMachineHandlerThread.getLooper(),
                mWifiNative, listener, mWifiMetrics, mScanRequestProxy, mWifiStateMachine);
    }

new一个ClientModeManager的实例,在上面也有说到,ModeStatemachine子状态 mClientModeActiveState enter函数中,还调用该实例的start api ,clientModeManager的用途如下:

/**
 * Manager WiFi in Client Mode where we connect to configured networks.
 */

    /**
     * Start client mode.
     */
    public void start() {
        mStateMachine.sendMessage(ClientModeStateMachine.CMD_START);
    }

ClientModeStateMachine,这个StateMachine的子状态只有两个idleState, startedState.明显,初始化的时候肯定在idelState

看看idleState的processMessage会针对CMD_START这个cmd做什么处理

            public boolean processMessage(Message message) {
                switch (message.what) {
                    case CMD_START:
                        updateWifiState(WifiManager.WIFI_STATE_ENABLING,
                                        WifiManager.WIFI_STATE_DISABLED);

                        mClientInterfaceName = mWifiNative.setupInterfaceForClientMode(
                                false /* not low priority */, mWifiNativeInterfaceCallback);
                        if (TextUtils.isEmpty(mClientInterfaceName)) {
                            Log.e(TAG, "Failed to create ClientInterface. Sit in Idle");
                            updateWifiState(WifiManager.WIFI_STATE_UNKNOWN,
                                            WifiManager.WIFI_STATE_ENABLING);
                            updateWifiState(WifiManager.WIFI_STATE_DISABLED,
                                            WifiManager.WIFI_STATE_UNKNOWN);
                            break;
                        }
                        sendScanAvailableBroadcast(false);
                        mScanRequestProxy.enableScanningForHiddenNetworks(false);
                        mScanRequestProxy.clearScanResults();
                        transitionTo(mStartedState);
                        break;

 调用到WifiNative 的接口setupInterfaceForClientMode,马上就要到开启wpa_supplicant的流程了。一到启动wpa_supplicant的流程以及与wpa_supplicant建立起连接之后,wifi的enable flow就要告一段落了。接着往下吧:注意一下

 mClientInterfaceName = mWifiNative.setupInterfaceForClientMode(
                                false /* not low priority */, mWifiNativeInterfaceCallback);

调用的时候有个参数,是注册进wifinative的call back,当interface有up and down时,会有callback 回来告知clientModeStateMachine.

/**
     * 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) {
/*看看wifi是否有实现wifi hal层,如果有,走wifi hal层会有不一样的flow,如果没有也没关系可以继续
往下走,这里有一个有关系的bug,就是androidP,走到p2p flow的时候 ,要求必须有hal层才能开p2p,这
里有跟google沟通过,是一个bug,并不需要强制产商一定要实现wifi hal层,才能用p2p,所以应该是下一个版本会修。*/
            if (!startHal()) {
                Log.e(TAG, "Failed to start Hal");
                mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToHal();
                return null;
            }
//开启wpa_supplicant
            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;
            }
/*androidP启动wpa_supplicant的方式跟之前有差别,以前wpa_supplicant的service一启动就会up 
wlan0和p2p0的interface,并要求在此之前要准备好wpa_supplicant.conf和p2p_supplicant.conf配
置文件,但在androidP,则不一样,androidP只是先把wpa_supplicant启动起来,也不带conf.然后后面
再将interface add 进来,因此也可以看到以前在启动wpa_supplicant之前会有个config拷贝的动作在
wpa_supplicant以外做完,但现在则是直接做在了wpa_supplicant调用addInterface里面,这也是
porting androidP要注意的点之一,如果还用之前的wpa_supplicant service,那就会报很多问题*/
            if (!mSupplicantStaIfaceHal.setupIface(iface.name)) {
                Log.e(TAG, "Failed to setup iface in supplicant on " + iface);
                teardownInterface(iface.name);
                mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToSupplicant();
                return null;
            }
/*注删interface observer,只要interface有up and down,则会调用observer类里面的callback 
function .这个跟之前ModeStateMachine注册进wifiNative的callback会相关,后面会讲到*/
            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;
            }
/*开始监听wpa_supplicant回报的event.WifiMonitor实现跟之前有差别,但是作用是一样的*/
            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;
        }
    }

wpa_supplicant service 在androidP的写法如下:

service wpa_supplicant /vendor/bin/hw/wpa_supplicant -d \
    -puse_p2p_group_interface=1 \
    -m/data/vendor/wifi/wpa/p2p_supplicant.conf \
    -O/data/vendor/wifi/wpa/sockets \
    -g@android:wpa_wlan0
 #  we will start as root and wpa_supplicant will switch to user wifi
 #  after setting up the capabilities required for WEXT
 #  user wifi
 #  group wifi inet keystore
    interface android.hardware.wifi.supplicant@1.0::ISupplicant default
    interface android.hardware.wifi.supplicant@1.1::ISupplicant default
    class late_start
    socket wpa_wlan0 dgram 660 wifi wifi
    disabled
    oneshot

startSupplicant再往下走

    /** 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;
        }
    }

会进到 wifiCondController

    /**
    * 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,实际上是wificond 这个service的一个client端,通过aidl方式实现的binder IPC,call到 wificond

server.cpp | ~/workspace/android_source/system/connectivity/wificond

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

接下来wificond会调用libwifisystem这个库里面的supplicant_manager的api StartSupplicant

bool SupplicantManager::StartSupplicant() ==》这个function主要作用则是用ctl.start 的方式,将上述的wpa_supplicant rc注册的service enable起来。至此wpa_supplicant终于启动了。

接着看WifiMonitor的startMonring

    /**
     * Start Monitoring for wpa_supplicant events.
     *
     * @param iface Name of iface.
     */
    public synchronized void startMonitoring(String iface) {
        if (mVerboseLoggingEnabled) Log.d(TAG, "startMonitoring(" + iface + ")");
        setMonitoring(iface, true);
        broadcastSupplicantConnectionEvent(iface);
    }
    /**
     * Broadcast the connection to wpa_supplicant event to all the handlers registered for
     * this event.
     *
     * @param iface Name of iface on which this occurred.
     */
    public void broadcastSupplicantConnectionEvent(String iface) {
        sendMessage(iface, SUP_CONNECTION_EVENT);
    }

以前的版本会用这个event在做为判断framework 与wpa_supplicant已经建立连线。让framework走一步动作用,现在androidP看起来好像sta没有在用这个event的感觉。还是我看得有问题,先pass,往下走看看。

上面其实有讲到在setupInterfaceForClientMode,有注册了一个interface 的监听器l,在wpa_supplicant开启后,以及addInterface后,实际上wpa_supplicant就会把interface up起来。那么这时候NetworkObserverInternal的callback

interfaceLinkStateChanged会被调用到。

        public void interfaceLinkStateChanged(String ifaceName, boolean unusedIsLinkUp) {
            synchronized (mLock) {
                final Iface ifaceWithId = mIfaceMgr.getIface(mInterfaceId);
                if (ifaceWithId == null) {
                    if (mVerboseLoggingEnabled) {
                        Log.v(TAG, "Received iface link up/down notification on an invalid iface="
                                + mInterfaceId);
                    }
                    return;
                }
                final Iface ifaceWithName = mIfaceMgr.getIface(ifaceName);
                if (ifaceWithName == null || ifaceWithName != ifaceWithId) {
                    if (mVerboseLoggingEnabled) {
                        Log.v(TAG, "Received iface link up/down notification on an invalid iface="
                                + ifaceName);
                    }
                    return;
                }
                onInterfaceStateChanged(ifaceWithName, isInterfaceUp(ifaceName));
            }
        }
    /** Helper method invoked to handle interface change. */
    private void onInterfaceStateChanged(Iface iface, boolean isUp) {
        synchronized (mLock) {
            // Mask multiple notifications with the same state.
            if (isUp == iface.isUp) {
                if (mVerboseLoggingEnabled) {
                    Log.v(TAG, "Interface status unchanged on " + iface + " from " + isUp
                            + ", Ignoring...");
                }
                return;
            }
            Log.i(TAG, "Interface state changed on " + iface + ", isUp=" + isUp);
            if (isUp) {
/*这个看着眼熟吧,这个externalListener就是之前clientModeManager注册进来的callback,
这里interface up 起来之后,会call到之前callback 类的onUp api*/
                iface.externalListener.onUp(iface.name);
            } else {
                iface.externalListener.onDown(iface.name);
                if (iface.type == Iface.IFACE_TYPE_STA) {
                    mWifiMetrics.incrementNumClientInterfaceDown();
                } else if (iface.type == Iface.IFACE_TYPE_AP) {
                    mWifiMetrics.incrementNumSoftApInterfaceDown();
                }
            }
            iface.isUp = isUp;
        }
    }

紧接着看看之前ClientModeManager onUp之前没做完的事情

              @Override
              public void onUp(String ifaceName) {
                  if (mClientInterfaceName != null && mClientInterfaceName.equals(ifaceName)) {
                      sendMessage(CMD_INTERFACE_STATUS_CHANGED, 1);
                  }
              }

clientModeStateMachine里 在调用完setupInterfaceForClientMode这个之后,已经将State跳转到了StartedState了,因此,看下StartedState会对CMD_INTERFACE_STATUS_CHANGED做什么事情:

                      case CMD_INTERFACE_STATUS_CHANGED:
                          boolean isUp = message.arg1 == 1;
                          onUpChanged(isUp);
                          break;
          private class StartedState extends State {

              private void onUpChanged(boolean isUp) {
                  if (isUp == mIfaceIsUp) {
                      return;  // no change
                  }
                  mIfaceIsUp = isUp;
                  if (isUp) {
                      Log.d(TAG, "Wifi is ready to use for client mode");
/*发送可以scan的广播,让scan service可以开始做scan动作*/
                      sendScanAvailableBroadcast(true);
/*与WifiStateMachine交互下面具体看看WifiStateMachine的跳转*/
                      mWifiStateMachine.setOperationalMode(WifiStateMachine.CONNECT_MODE,
                                                           mClientInterfaceName);
                      updateWifiState(WifiManager.WIFI_STATE_ENABLED,
                                      WifiManager.WIFI_STATE_ENABLING);
                  } else {
                      if (mWifiStateMachine.isConnectedMacRandomizationEnabled()) {
                          // Handle the error case where our underlying interface went down if we
                          // do not have mac randomization enabled (b/72459123).
                          return;
                      }
                      // if the interface goes down we should exit and go back to idle state.
                      Log.d(TAG, "interface down!");
                      updateWifiState(WifiManager.WIFI_STATE_UNKNOWN,
                                      WifiManager.WIFI_STATE_ENABLED);
                      mStateMachine.sendMessage(CMD_INTERFACE_DOWN);
                  }
              }

还以为androidP 直接抛弃了WifiStateMachine呢,原来这里才开始有交互。紧接着往下走吧

WifiStateMachine的初始状态为mDefaultState ,调用了setOperationalMode后

    public void setOperationalMode(int mode, String ifaceName) {
        if (mVerboseLoggingEnabled) {
            log("setting operational mode to " + String.valueOf(mode) + " for iface: " + ifaceName);
        }
        mModeChange = true;
        if (mode != CONNECT_MODE) {
            // we are disabling client mode...   need to exit connect mode now
            transitionTo(mDefaultState);
        } else {
            // do a quick sanity check on the iface name, make sure it isn't null
            if (ifaceName != null) {
                mInterfaceName = ifaceName;
                transitionTo(mDisconnectedState);
            } else {
                Log.e(TAG, "supposed to enter connect mode, but iface is null -> DefaultState");
                transitionTo(mDefaultState);
            }
        }
        // use the CMD_SET_OPERATIONAL_MODE to force the transitions before other messages are
        // handled.
        sendMessageAtFrontOfQueue(CMD_SET_OPERATIONAL_MODE);
    }

会先跳转到DisconnectedState,然后再发送cmd CMD_SET_OPERATIONAL_MODE

    class DisconnectedState extends State {
        @Override
        public void enter() {
            Log.i(TAG, "disconnectedstate enter");
            // We dont scan frequently if this is a temporary disconnect
            // due to p2p
            if (mTemporarilyDisconnectWifi) {
                p2pSendMessage(WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE);
                return;
            }

            if (mVerboseLoggingEnabled) {
                logd(" Enter DisconnectedState screenOn=" + mScreenOn);
            }

            /** clear the roaming state, if we were roaming, we failed */
            mIsAutoRoaming = false;

            mWifiConnectivityManager.handleConnectionStateChanged(
                    WifiConnectivityManager.WIFI_STATE_DISCONNECTED);

            mDisconnectedTimeStamp = mClock.getWallClockMillis();
        }
    /**
     * Handler for WiFi state (connected/disconnected) changes
     */
    public void handleConnectionStateChanged(int state) {
        localLog("handleConnectionStateChanged: state=" + stateToString(state));

        mWifiState = state;

        if (mWifiState == WIFI_STATE_CONNECTED) {
            mOpenNetworkNotifier.handleWifiConnected();
            mCarrierNetworkNotifier.handleWifiConnected();
        }

        // Reset BSSID of last connection attempt and kick off
        // the watchdog timer if entering disconnected state.
        if (mWifiState == WIFI_STATE_DISCONNECTED) {
            mLastConnectionAttemptBssid = null;
            scheduleWatchdogTimer();
            startConnectivityScan(SCAN_IMMEDIATELY);
        } else {
            startConnectivityScan(SCAN_ON_SCHEDULE);
        }
    }

至此,framework开始作扫描动作。

扫描放到下一篇来说。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值