Android Q-wifi启动流程(二)

9 篇文章 0 订阅
7 篇文章 2 订阅

3、WiFi 启动流程服务层分析
    WifiManager 的setWifiEnabled 最终调用到了WifiServiceImpl setWifiEnabled 方法,WifiServiceImpl setWifiEnabled 实现如下,参数
    STA_PRIMARY 表示打开的是主WiFi。如果第二个参数是STA_SECONDARY 则表示打开的是第二个WiFi。目前高通实现了WiFi 双STA 的功能,通过该
    参数来区别打开的哪一个WiFi。
    setWifiEnabled源码:
        @Override
        public synchronized boolean setWifiEnabled(String packageName, boolean enable) {
            return setWifiEnabled2(packageName, STA_PRIMARY, enable);
        }
    WifiServiceImpl setWifiEnabled 调用setWifiEnabled2 方法,setWifiEnabled2 方法实现如下;首先判断应用是有权限打开WiFi ,在Android Q
    中,需要有网络设置方面的权限才能打开WiFi ,setWifiEnabled 已经不是SDK 接口,不对第三方开放。只分析主WiFi的启动流程,辅助WiFi 暂时
    不分析,setWifiEnabled2 通过mWifiController 给自己发送CMD_WIFI_TOGGLED 消息。
    setWifiEnabled2源码:
        public synchronized boolean setWifiEnabled2(String packageName, int staId, boolean enable) {
            if (enforceChangePermission(packageName) != MODE_ALLOWED) {
                return false;
            }

            boolean isPrivileged = isPrivileged(Binder.getCallingPid(), Binder.getCallingUid());
            if (!isPrivileged && !isDeviceOrProfileOwner(Binder.getCallingUid())
                    && !mWifiPermissionsUtil.isTargetSdkLessThan(packageName, Build.VERSION_CODES.Q,
                      Binder.getCallingUid())
                    && !isSystem(packageName, Binder.getCallingUid())) {
                mLog.info("setWifiEnabled not allowed for uid=%")
                        .c(Binder.getCallingUid()).flush();
                return false;
            }
            // If Airplane mode is enabled, only privileged apps are allowed to toggle Wifi
            if (mSettingsStore.isAirplaneModeOn() && !isPrivileged) {
                mLog.err("setWifiEnabled in Airplane mode: only Settings can toggle wifi").flush();
                return false;
            }

            // If SoftAp is enabled, only privileged apps are allowed to toggle wifi
            boolean apEnabled = mWifiApState == WifiManager.WIFI_AP_STATE_ENABLED;
            if (apEnabled && !isPrivileged) {
                mLog.err("setWifiEnabled SoftAp enabled: only Settings can toggle wifi").flush();
                return false;
            }

            // If we're in crypt debounce, ignore any wifi state change APIs.
            if (mFrameworkFacade.inStorageManagerCryptKeeperBounce()) {
                return false;
            }

            mLog.info("setWifiEnabled package=% uid=% enable=%").c(packageName)
                    .c(Binder.getCallingUid()).c(enable).flush();
            long ident = Binder.clearCallingIdentity();
            try {
                if (staId == STA_PRIMARY && !mSettingsStore.handleWifiToggled(enable)) {
                    // Nothing to do if wifi cannot be toggled
                    return true;
                }
            } finally {
                Binder.restoreCallingIdentity(ident);
            }

            if (!mIsControllerStarted) {
                Slog.e(TAG,"WifiController is not yet started, abort setWifiEnabled");
                return false;
            }

            mWifiMetrics.incrementNumWifiToggles(isPrivileged, enable);

            if (staId == STA_PRIMARY) {
                mWifiController.sendMessage(CMD_WIFI_TOGGLED);
            } else if ((getNumConcurrentStaSupported() > 1)
                       && (getWifiEnabledState() == WifiManager.WIFI_STATE_ENABLED)
                       && staId > STA_PRIMARY) {
                mWifiController.sendMessage(CMD_ADD_WIFI_SET, staId, enable ? 1 : 0);
            } else {
               Slog.e(TAG,"setWifiEnabled not allowed for id:"+staId);
               return false;
            }

            return true;
        }
    3.1 WifiController 分析
        WifiController 是管理WiFi 开关状态的class,WifiController 是一个状态机,一共有六个状态,其中DefaultState状态是另外五个状态的
        父状态。
    3.2 WifiController 启动
        WifiController 是在WifiServiceImpl 中被启动的,在WifiServiceImpl checkAndStartWifi 方法的中调用了WifiController start 的方法
        Log.d(TAG, "qcdbg= mWifiStateMachine.syncInitialize()");
        if (!mClientModeImpl.syncInitialize(mClientModeImplChannel)) {
            Log.wtf(TAG, "Failed to initialize ClientModeImpl");
        }
        mWifiController.start();
        mIsControllerStarted = true;

        // If we are already disabled (could be due to airplane mode), avoid changing persist
        // state here
        if (wifiEnabled) {
            setWifiEnabled(mContext.getPackageName(), wifiEnabled);
        }
        WifiController start 方法实现如下,首先设置初始状态,如果是scanonly模式,设置初始状态为StaDisabledWithScanState,否则设置状态
        为StaDisabledState;注册一个广播接收器,监听WiFi SoftAP 和STA 状态改变的广播。
        start源码:
        public void start() {
            boolean isAirplaneModeOn = mSettingsStore.isAirplaneModeOn();
            boolean isWifiEnabled = mSettingsStore.isWifiToggleEnabled();
            boolean isScanningAlwaysAvailable = mSettingsStore.isScanAlwaysAvailable();
            boolean isLocationModeActive = mWifiPermissionsUtil.isLocationModeEnabled();

            log("isAirplaneModeOn = " + isAirplaneModeOn
                    + ", isWifiEnabled = " + isWifiEnabled
                    + ", isScanningAvailable = " + isScanningAlwaysAvailable
                    + ", isLocationModeActive = " + isLocationModeActive);

            if (checkScanOnlyModeAvailable()) {
                setInitialState(mStaDisabledWithScanState);
            } else {
                setInitialState(mStaDisabledState);
            }
            IntentFilter filter = new IntentFilter();
            filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
            filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
            filter.addAction(LocationManager.MODE_CHANGED_ACTION);
            mContext.registerReceiver(
                    new BroadcastReceiver() {
                        @Override
                        public void onReceive(Context context, Intent intent) {
                            String action = intent.getAction();
                            if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
                                int state = intent.getIntExtra(
                                        WifiManager.EXTRA_WIFI_AP_STATE,
                                        WifiManager.WIFI_AP_STATE_FAILED);
                                if (state == WifiManager.WIFI_AP_STATE_FAILED) {
                                    Log.e(TAG, "SoftAP start failed");
                                    sendMessage(CMD_AP_START_FAILURE);
                                } else if (state == WifiManager.WIFI_AP_STATE_DISABLED) {
                                    sendMessage(CMD_AP_STOPPED);
                                }
                            } else if (action.equals(LocationManager.MODE_CHANGED_ACTION) && mWifiControllerReady) {
                                // Location mode has been toggled...  trigger with the scan change
                                // update to make sure we are in the correct mode
                                sendMessage(CMD_SCAN_ALWAYS_MODE_CHANGED);
                            }
                        }
                    },
                    new IntentFilter(filter));
            super.start();
        }

        我们打开WiFi的时候,并非sanonly 模式,所以WifiController 初始化状态为StaDisabledState ;在StaDisabledState 状态机中处理了
        CMD_WIFI_TOGGLED 消息,CMD_WIFI_TOGGLED 主要是切换WifiController 的状态,让WifiController 进入StaEnabledState 状态
        processMessage源码:
        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(mStaEnabledState);
                    } else if (checkScanOnlyModeAvailable()) {
                        // only go to scan mode if we aren't in airplane mode
                        if (mSettingsStore.isAirplaneModeOn()) {
                            transitionTo(mStaDisabledWithScanState);
                        }
                    }
                    break;

        进入StaEnabledState 状态首先调用的是StaEnabledState 状态机的 enter 方法,enter 调用mActiveModeWarden 对象enterClientMode 方法
        enter源码:
        public void enter() {
            log("StaEnabledState.enter()");
            mActiveModeWarden.enterClientMode();
        }
        enterClientMode 实现如下:
       public void enterClientMode() {
            changeMode(ModeStateMachine.CMD_START_CLIENT_MODE);
        }
        changeMode 实现,
        private void changeMode(int newMode) {
            mModeStateMachine.sendMessage(newMode);
        }

        ModeStateMachine 也是一个状态机,有三个状态 ClientModeActiveState、ScanOnlyModeActiveState、WifiDisabledState;这三个状态相互
        独立,没有父子关系,初始状态被设置为 WifiDisabledState
        ModeStateMachine源码:
        ModeStateMachine() {
            super(TAG, mLooper);

            addState(mClientModeActiveState);
            addState(mScanOnlyModeActiveState);
            addState(mWifiDisabledState);

            Log.d(TAG, "Starting Wifi in WifiDisabledState");
            setInitialState(mWifiDisabledState);
            start();
        }
        WifiDisabledState 状态机对消息处理方法如下
        public boolean processMessage(Message message) {
            Log.d(TAG, "received a message in WifiDisabledState: " + message);
            if (checkForAndHandleModeChange(message)) {
                return HANDLED;
            }
            return NOT_HANDLED;
        }
        最终是调用checkForAndHandleModeChange 对消息进行处理,从上面可知,我们发给WifiDisabledState 状态的消息为CMD_START_CLIENT_MODE ,
        对CMD_START_CLIENT_MODE 的处理是 ModeStateMachine 状态机切换到 ClientModeActiveState 状态
        private boolean checkForAndHandleModeChange(Message message) {
            switch(message.what) {
                case ModeStateMachine.CMD_START_CLIENT_MODE:
                    Log.d(TAG, "Switching from " + getCurrentMode() + " to ClientMode");
                    if (getCurrentMode().equals(mClientModeActiveState.getName()))
                        return NOT_HANDLED;
                    mModeStateMachine.transitionTo(mClientModeActiveState);
                    break;
                case ModeStateMachine.CMD_START_SCAN_ONLY_MODE:
                    Log.d(TAG, "Switching from " + getCurrentMode() + " to ScanOnlyMode");
                    if (getCurrentMode().equals(mScanOnlyModeActiveState.getName()))
                        return NOT_HANDLED;
                    mModeStateMachine.transitionTo(mScanOnlyModeActiveState);
                    break;
                case ModeStateMachine.CMD_DISABLE_WIFI:
                    Log.d(TAG, "Switching from " + getCurrentMode() + " to WifiDisabled");
                    if (getCurrentMode().equals(mWifiDisabledState.getName()))
                        return NOT_HANDLED;
                    mModeStateMachine.transitionTo(mWifiDisabledState);
                    break;
                default:
                    return NOT_HANDLED;
            }
            return HANDLED;
        }
        ModeStateMachine 状态机切换到ClientModeActiveState 状态,首先执行ClientModeActiveState 状态的enter 方法,首先构造一个Manager 是
        ActiveModeManager 的对象,ActiveModeManager 是一个接口,对于STA模式它的实现类是ClientModeManager
         @Override
                public void enter() {
                    Log.d(TAG, "Entering ClientModeActiveState");

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

                    updateBatteryStatsWifiState(true);
                }

        makeClientModeManager 方法实现如下:

        public ClientModeManager makeClientModeManager(ClientModeManager.Listener listener) {
            return new ClientModeManager(mContext, mWifiCoreHandlerThread.getLooper(),
                    mWifiNative, listener, mWifiMetrics, mClientModeImpl);
        }

        mManager.start 方法调用的就是ClientModeManager 中的start 方法;ClientModeManager 构造方法如下
        ClientModeManager(Context context, @NonNull Looper looper, WifiNative wifiNative,
                Listener listener, WifiMetrics wifiMetrics, ClientModeImpl clientModeImpl) {
            mContext = context;
            mWifiNative = wifiNative;
            mListener = listener;
            mWifiMetrics = wifiMetrics;
            mClientModeImpl = clientModeImpl;
            mStateMachine = new ClientModeStateMachine(looper);
        }
        
        ClientModeManager 的start 方法如下
        public void start() {
            mStateMachine.sendMessage(ClientModeStateMachine.CMD_START);
        }

        从ClientModeManager 的构造方法中可知mStateMachine 对象为类ClientModeStateMachine ,ClientModeStateMachine 也是一个状态机,一个
        有两个独立的状态 mIdleState、mStartedState,初始状态为mIdleState 。

        ClientModeStateMachine(Looper looper) {
            super(TAG, looper);

            addState(mIdleState);
            addState(mStartedState);

            setInitialState(mIdleState);
            start();
        }
        当ClientModeManager 收到消息CMD_START 处理如下,调用WifiNative setupInterfaceForClientInConnectivityMode 方法来设置底层接口
        public boolean processMessage(Message message) {
            switch (message.what) {
                case CMD_START:
                    updateWifiState(WifiManager.WIFI_STATE_ENABLING,
                                    WifiManager.WIFI_STATE_DISABLED);

                    mClientInterfaceName =
                            mWifiNative.setupInterfaceForClientInConnectivityMode(
                            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;
                    }
                    transitionTo(mStartedState);
                    break;
                    
        setupInterfaceForClientInConnectivityMode 方法实现如下,setupInterfaceForClientInConnectivityMode 做的事情很多,主要是启动
        vendor HAL ,启动wpa_supplicant ,设置接口的client mode ,启动监听对应wlan 的事件。在这里只是笼统总结下,该函数后续单独分析
        public String setupInterfaceForClientInConnectivityMode(
                @NonNull InterfaceCallback interfaceCallback, boolean lowPriority) {
            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_FOR_CONNECTIVITY);
                if (iface == null) {
                    Log.e(TAG, "Failed to allocate new STA iface");
                    return null;
                }
                iface.externalListener = interfaceCallback;
                iface.name = createStaIface(iface, lowPriority);
                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 (!setupFstInterface(iface)) {
                    Log.e(TAG, "Failed to setup fst interface from: " + iface);
                    teardownInterface(iface.name);
                    mWifiMetrics.incrementNumSetupClientInterfaceFailureDueToWificond();
                    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);

                iface.featureSet = getSupportedFeatureSetInternal(iface.name);
                return iface.name;
            }
        }

        setupInterfaceForClientInConnectivityMode 方法执行完后,ClientModeManager 状态机切换到mStartedState 状态,首先执行mStartedState
        的enter方法,在enter 中调用了onUpChanged 的方法
        @Override
        public void enter() {
            Log.d(TAG, "entering StartedState");
            mIfaceIsUp = false;
            onUpChanged(mWifiNative.isInterfaceUp(mClientInterfaceName));
        }

        onUpChanged 实现如下,在setupInterfaceForClientInConnectivityMode 方法中,已经把对应的wlan 口设置好,并up起来 ,所有调用这里的
        时候isUP 是true,调用ClientModeImpl setOperationalMode 设置ClientModeImpl 的状态。ClientModeImpl 的STA 模式的主要的控制状态机,
        控制的WiFi 的连接,获取ip等流程。后面单独分析该状态机
        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");
                            mClientModeImpl.setOperationalMode(ClientModeImpl.CONNECT_MODE,
                                                               mClientInterfaceName);
                            updateWifiState(WifiManager.WIFI_STATE_ENABLED,
                                            WifiManager.WIFI_STATE_ENABLING);
                        } else {
                            if (mClientModeImpl.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);
                        }
                    }

        setOperationalMode 实现如下,由于第一个参数为CONNECT_MODE,所以设置ClientModeImpl 状态机进入mDisconnectedState模式,进入
        mDisconnectedState会触发一次连接扫描,该流程以后分析,到此,WiFi 的启动流程基本走完。

         public void setOperationalMode(int mode, String ifaceName) {
                if (mVerboseLoggingEnabled) {
                    log("setting operational mode to " + String.valueOf(mode) + " for iface: " + ifaceName);
                }

                new Exception().printStackTrace();

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

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值