Android WLAN connection switch process analysis and (b) framework layer

PS: On a layer of talk about frameworks WifiManager class is the core class WLAN

So we start with this section WifiManager start.

A, WLAN switch Analysis

WifiSettings application layer in the WifiEnabler new object called setWifiEnabled WifiManager () method in the WifiEnabler.

路径:frameworks/base/wifi/java/android/net/wifi/WfiManager.java

WfiManager->setWifiEnabled()

   /**
     * Enable or disable Wi-Fi.
     * <p>
     * Applications must have the {@link android.Manifest.permission#CHANGE_WIFI_STATE}
     * permission to toggle wifi.
     *
     * @param enabled {@code true} to enable, {@code false} to disable.
     * @return {@code false} if the request cannot be satisfied; {@code true} indicates that wifi is
     *         either already in the requested state, or in progress toward the requested state.
     * @throws  {@link java.lang.SecurityException} if the caller is missing required permissions.
     */
    public boolean setWifiEnabled(boolean enabled) {
        try {
            return mService.setWifiEnabled(mContext.getOpPackageName(), enabled);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

Here returns the result of calling a service

IWifiManager mService

Path: frameworks / Base / WiFi / Java / Android / NET / WiFi / IWifiManager.aidl    PS: note the aidl

IWifiManager->setWifiEnabled()

So we need to find IWifiManager.aidl corresponding Service to find the class that implements IWifiManager.Stub

 

WifiServiceImpl extends IWifiManager.Stub 

路径:frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiServiceImpl.java

WifiServiceImpl->setWifiEnabled()

   /**
     * 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 {
...
...
//判断是否飞行模式以及各种权限和打印日志,略过
...
        mWifiController.sendMessage(CMD_WIFI_TOGGLED);
        return true;
    }

Send a WLAN handover information

WifiController  mWifiController

路径:frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiController.java

 

/**状态机
 * WifiController is the class used to manage on/off state of WifiStateMachine for various operating
 * modes (normal, airplane, wifi hotspot, etc.).
 */
public class WifiController extends StateMachine {

 

Unlike WifiStateMachine, WifiStateMachine is a complex state machine, which maintains the startup Wifi, scanning, connection, disconnection and other state. WifiController wifi state machine is high level, the switch management wifi, wifi hot state switch or the like.

  WifiController(Context context, WifiStateMachine wsm, Looper wifiStateMachineLooper,
                   WifiSettingsStore wss, Looper wifiServiceLooper, FrameworkFacade f,
                   WifiStateMachinePrime wsmp) {
        super(TAG, wifiServiceLooper);
        mFacade = f;
        mContext = context;
        mWifiStateMachine = wsm;
        mWifiStateMachineLooper = wifiStateMachineLooper;
        mWifiStateMachinePrime = wsmp;
        mSettingsStore = wss;

        // CHECKSTYLE:OFF IndentationCheck
//添加各个状态及父状态
addState(mDefaultState); addState(mStaDisabledState, mDefaultState); addState(mStaEnabledState, mDefaultState); addState(mDeviceActiveState, mStaEnabledState); addState(mStaDisabledWithScanState, mDefaultState); addState(mEcmState, mDefaultState); // CHECKSTYLE:ON IndentationCheck boolean isAirplaneModeOn = mSettingsStore.isAirplaneModeOn(); boolean isWifiEnabled = mSettingsStore.isWifiToggleEnabled(); boolean isScanningAlwaysAvailable = mSettingsStore.isScanAlwaysAvailable(); boolean isLocationModeActive = mSettingsStore.getLocationModeSetting(mContext) == Settings.Secure.LOCATION_MODE_OFF; log("isAirplaneModeOn = " + isAirplaneModeOn + ", isWifiEnabled = " + isWifiEnabled + ", isScanningAvailable = " + isScanningAlwaysAvailable + ", isLocationModeActive = " + isLocationModeActive); if (checkScanOnlyModeAvailable()) { setInitialState(mStaDisabledWithScanState); } else { setInitialState(mStaDisabledState); }

路径:frameworks/base/core/java/com/android/internal/util/StateMachine.java

addState () method is the parent class StateMachine method, the first parameter is newly added state, the second state is the parent.

       /**
         * Add a new state to the state machine. Bottom up addition
         * of states is allowed but the same state may only exist
         * in one hierarchy.
         *
         * @param state the state to add
         * @param parent the parent of state
         * @return stateInfo for this state
         */
        private final StateInfo addState(State state, State parent) {
            if (mDbg) {
                mSm.log("addStateInternal: E state=" + state.getName() + ",parent="
                        + ((parent == null) ? "" : parent.getName()));
            }
            StateInfo parentStateInfo = null;
            if (parent != null) {
                parentStateInfo = mStateInfo.get(parent);
                if (parentStateInfo == null) {
                    // Recursively add our parent as it's not been added yet.
                    parentStateInfo = addState(parent, null);
                }
            }
            StateInfo stateInfo = mStateInfo.get(state);
            if (stateInfo == null) {
                stateInfo = new StateInfo();
                mStateInfo.put(state, stateInfo);
            }

            // Validate that we aren't adding the same state in two different hierarchies.
            if ((stateInfo.parentStateInfo != null)
                    && (stateInfo.parentStateInfo != parentStateInfo)) {
                throw new RuntimeException("state already added");
            }
            stateInfo.state = state;
            stateInfo.parentStateInfo = parentStateInfo;
            stateInfo.active = false;
            if (mDbg) mSm.log("addStateInternal: X stateInfo: " + stateInfo);
            return stateInfo;
        }
StaDisabledState, StaEnabledState, StaDisabledWithScanState, parent of EcmState is DefaultState; is the parent of DeviceActiveState StaEnabledState. 
The initial state is StaDisableState
 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();
        }
...
...
In this state, the received message CMD_WIFI_TOGGLED executes the corresponding code block.
 @Override
        public boolean processMessage(Message msg) {
            switch (msg.what) {
                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);
                    } else if (checkScanOnlyModeAvailable()) {
                        // only go to scan mode if we aren't in airplane mode
//进入扫描模式
if (mSettingsStore.isAirplaneModeOn()) { transitionTo(mStaDisabledWithScanState); } } break;
In this process do not substantially state and then switch to DeviceActiveState. Parent state DeviceActiveState is StaEnabledState, 
the mechanism of the state machine, when converted to the target state, will in turn call the parent state and enter itself () method.
StaEnableState
 class StaEnabledState extends State {
        @Override
        public void enter() {
            log("StaEnabledState.enter()");
        }
...
...//没做处理
DeviceActiveState
  class DeviceActiveState extends State {
        @Override
        public void enter() {
            mWifiStateMachinePrime.enterClientMode();
            mWifiStateMachine.setHighPerfModeEnabled(false);
        }
...
...
WifiStateMachinePrime mWifiStateMachinePrime
路径:frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachinePrime.java
  /**
     * 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);
    }
ModeStateMachine mModeStateMachine 
clear, ModeStateMachine is a state machine, is an internal class WifiStateMachinePrime
 private class ModeStateMachine extends StateMachine {
        // 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;

        private final State mWifiDisabledState = new WifiDisabledState();
        private final State mClientModeActiveState = new ClientModeActiveState();
        private final State mScanOnlyModeActiveState = new ScanOnlyModeActiveState();

        ModeStateMachine() {
            super(TAG, mLooper);

            addState(mClientModeActiveState);
            addState(mScanOnlyModeActiveState);
            addState(mWifiDisabledState);
...
...
 
ModeStateMachine有四种状态WifiDisabledState、ClientModeActiveState、ScanOnlyModeActiveState及父状态ModeActiveState。
初始也是关闭状态
WiFiDisableState
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;
    }
 
    @Override
    public void exit() {
        // do not have an active mode manager...  nothing to clean up
    }
}
private boolean checkForAndHandleModeChange(Message message) {
    switch(message.what) {
        case ModeStateMachine.CMD_START_CLIENT_MODE:
            Log.d(TAG, "Switching from " + getCurrentMode() + " to ClientMode");
            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;
}

接着转换为ClientModeActiveState

       class ClientModeActiveState extends ModeActiveState {
            ClientListener mListener;
            private class ClientListener implements ClientModeManager.Listener {
...
            @Override
            public void enter() {
                Log.d(TAG, "Entering ClientModeActiveState");

                mListener = new ClientListener();
                mManager = mWifiInjector.makeClientModeManager(mListener);
                mManager.start();
                mActiveModeManagers.add(mManager);
                updateBatteryStatsWifiState(true);
            }
...

ActiveModeManager mManager 

ClientModeManager是ActiveModeManager的实现类

 

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

 

ClientModeStateMachine mStateMachine
ClientModeStateMachine也是一个状态机,有两种状态IdleState和StartedState
       ClientModeStateMachine(Looper looper) {
            super(TAG, looper);

            addState(mIdleState);
            addState(mStartedState);

            setInitialState(mIdleState);
            start();
        }

初始为IdleState状态

      private class IdleState extends State {

            @Override
            public void enter() {
                Log.d(TAG, "entering IdleState");
                mClientInterfaceName = null;
                mIfaceIsUp = false;
            }

            @Override
            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;
                    default:
                        Log.d(TAG, "received an invalid message: " + message);
                        return NOT_HANDLED;
                }
                return HANDLED;
            }
        }

WifiNative mWifiNative 

路径: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;
        }
    }

startHal()

startSupplicant()

加载驱动setupInterfaceForClientMode()

另外启动了Wifi监视器startMonitoring()

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;
        }
    }
isVendorHalSupported()和startVendorHal()分别调用了HalDeviceManagerisSupported()和start()方法。
 

startSupplicant()实际上调用了WificondControlenableSupplicant()方法

   /**
    * 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;
    }
retrieveWificondAndRegisterForDeath()
  private boolean retrieveWificondAndRegisterForDeath() {
        if (mWificond != null) {
            if (mVerboseLoggingEnabled) {
                Log.d(TAG, "Wificond handle already retrieved");
            }
            // We already have a wificond handle.
            return true;
        }
        mWificond = mWifiInjector.makeWificond();
IWificond mWificond 
路径:system/connectivity/wificond/aidl/android/net/wifi/IWificond.aidl
其实现类为WiFiInjector
在上面的方法中被初始化
  public IWificond makeWificond() {
        // We depend on being able to refresh our binder in WifiStateMachine, so don't cache it.
        IBinder binder = ServiceManager.getService(WIFICOND_SERVICE_NAME);
        return IWificond.Stub.asInterface(binder);
    }
 
路径:frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiInjector.java
WIFICOND_SERVICE_NAME = wificond
ServiceManager.getService("wificond")直接调用了底层cpp
Status Server::enableSupplicant(bool* success) {
  *success = supplicant_manager_->StartSupplicant();
  return Status::ok();
}
路径:system/connectivity/wificond/server.cpp

 





 

 

 

 

 
 

 

 
 

 

 

 

Guess you like

Origin www.cnblogs.com/nextbug/p/12299592.html