Android 9 WIFI 打开流程

本文详细解析了Android 9系统中打开WiFi的流程,从App端的WifiManager开始,通过Binder机制与WifiServiceImpl交互,接着深入到WIFIController管理WiFi状态,再到WifiStateMachinePrime中的状态转换,最后在ClientModeManager中执行具体操作。整个过程揭示了Android系统如何通过接口与硬件层通信来控制WiFi。

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

Wifi 打开 流程

App端 打开wifi操作

private WifiManager mWifiManager; 
mWifiManager = (WifiManager) mContext.getSystemService(WifiManager.class);\\获取WIFI的服务
mWifiManager.setWifiEnabled(true) 

让我们看一下WifiManager设置的时候是如何操作

	/**
      * 创建一个新的 WifiManager 实例。
      * 应用程序几乎总是想要使用
      * {@link android.content.Context#getSystemService Context.getSystemService()} 检索
      * 标准{@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}。
      * @param context 应用程序上下文
      * @param 服务Binder接口
      * @hide - 隐藏它,因为它接受一个 IWifiManager 类型的参数,这是一个系统私有类。
      */
public WifiManager(Context context, IWifiManager service, Looper looper) {
        mContext = context;
        mService = service; //拿到IWifiManager的接口
        mLooper = looper;
        mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
}

/**
 *启用或禁用Wi-Fi。
 * 应用程序必须具有 {@link android.Manifest.permission#CHANGE_WIFI_STATE}
 *切换wifi的权限。
 * @param enabled {@code true} 启用,{@code false} 禁用。
 * @return {@code false} 如果请求不能被满足; {@code true} 表示 wifi 已经处于请求状态,或者正在向请求状态前进。
 * @throws {@link java.lang.SecurityException} 如果调用者缺少所需的权限。
 */ 
public boolean setWifiEnabled(boolean enabled) {
  try {
       return mService.setWifiEnabled(mContext.getOpPackageName(), enabled);//通过IWifiManager与服务进行通讯
      } catch (RemoteException e) {
          throw e.rethrowFromSystemServer();
      }
  }

WifiManager通过Binder机制与WifiServiceImpl进行通讯

WifiServerImpl
(路径:frameworks\opt\net\wifi\service\java\com\android\server\wifi\WifiServiceImpl.java)

public class WifiServiceImpl extends IWifiManager.Stub {
 	 /**
      * 见 {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)}
      * @param enable {@code true} 启用,{@code false} 禁用。
      * @return {@code true} 如果启用/禁用操作已启动或已在队列中。
      */
    @Override
    public synchronized boolean setWifiEnabled(String packageName, boolean enable)
            throws RemoteException {
            //判断调用的app是否具有权限
        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 (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;
        }

       /*
         * 调用者可能没有 WRITE_SECURE_SETTINGS,
         * 只有 CHANGE_WIFI_STATE 被强制执行
         */
        long ident = Binder.clearCallingIdentity();
        try {
        	//保存wifi状态
            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;
    }
}

WIFIController.java

WififController 管理wifi开关,热点开关等状态

public class WifiController extends StateMachine {
...
	class StaDisabledState extends State {
		...
		@Override
        public boolean processMessage(Message msg) {
        	  switch (msg.what) {
                case CMD_WIFI_TOGGLED:
                	if (mSettingsStore.isWifiToggleEnabled()) {
                        ...
                        transitionTo(mDeviceActiveState);//转换到了DeviceActiveState状态;
                    } else if (checkScanOnlyModeAvailable()) {  //检测是否有被禁用位置服务
                       // 只有在我们不处于飞行模式时才进入扫描模式
                        if (mSettingsStore.isAirplaneModeOn()) {
                            transitionTo(mStaDisabledWithScanState);//转换到了DeviceActiveState状态
                        }
                    }
                    break;
                }
        }
        ...
	}
...
}
class DeviceActiveState extends State {
		@Override
        public void enter() {
            ...
            mWifiStateMachinePrime.enterClientMode();//调用WifiStateMachinePrime.java方法
            ...
        }
}

WifiStateMachinePrime.java

(路径:frameworks\opt\net\wifi\service\java\com\android\server\wifi\WifiStateMachinePrime.java)

public class WifiStateMachinePrime {
		....
		/**
		 * 将 wifi 切换到客户端模式的方法,将尝试连接到配置的网络。
		 */
	    public void enterClientMode() {
	        changeMode(ModeStateMachine.CMD_START_CLIENT_MODE);
	    }

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

		private class ModeStateMachine extends StateMachine {
		...
		//最后会走到checkForAndHandleModeChange
			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;
                    ...
            }
            return HANDLED;
        	}
		}
}

转到ClientModeActiviteState状态
WifiStateMachinePrime.java

class ClientModeActiveState extends ModeActiveState {
		...
			@Override
            public void enter() {
				mManager = mWifiInjector.makeClientModeManager(mListener);
                mManager.start();//跳转到ClientModeManager的start方法
			}
	   ...
}

ClientModeManager.java

(路径:frameworks\opt\net\wifi\service\java\com\android\server\wifi\ClientModeManager.java)

public class ClientModeManager implements ActiveModeManager {
	....
	/**
     * Start client mode.
     */
    public void start() {
        mStateMachine.sendMessage(ClientModeStateMachine.CMD_START);//会跳转到IdleState(初始化时候默认是IdleState)
    }
	...
	private class IdleState extends State {
		@Override
        public boolean processMessage(Message message) {
			switch (message.what) {
                    case CMD_START:
                    	/**
					     * Update Wifi state and send the broadcast.
					     * @param newState new Wifi state
					     * @param currentState current wifi state
					     */
                    	updateWifiState(WifiManager.WIFI_STATE_ENABLING,
                                        WifiManager.WIFI_STATE_DISABLED);

                        if (WifiInjector.getInstance().getAtcAospEnhancement()) {
                            mEnableTime = Calendar.getInstance().getTimeInMillis();
                            Log.d(TAG, "We will check Wi-Fi Enable time");
                        }
						//setupInterfaceForClientMode方法startHal
                        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;
                   ...     
            }
		}
	}
}

总结:App端都是通过wifimanager暴露的接口通过binder机制与WifiServer进行通信。
//setupInterfaceForClientMode方法startHal,下面就是开始到hal层(后面会继续更新),可能会根据硬件芯片厂商做一些定制化的操作

AndroidWiFi连接流程图主要包括以下步骤: 1. 打开WiFi:用户进入设置界面,打开设备的WiFi开关,使设备开始搜索可用的WiFi网络。 2. 搜索和扫描:Android设备开始搜索周围的WiFi网络,扫描到的网络信息将会显示在WiFi设置列表中,包括网络名称(SSID)、信号强度等。 3. 用户选择网络:用户根据列表中显示的网络信息,选择要连接的WiFi网络。 4. 请求连接:Android设备通过向选择的WiFi网络发送请求连接的请求,包括认证信息和其他必要的参数。 5. 连接认证:WiFi网络收到连接请求后,会进行身份验证,包括密码验证、MAC地址过滤等。如果认证通过,网络将发送认可的连接响应。 6. IP地址获取:一旦连接成功,Android设备将向WiFi网络请求分配一个IP地址,以便在网络上进行通信。 7. 地址分配:WiFi网络会为设备分配一个合法的IP地址,并将该信息通过DHCP(动态主机配置协议)返回给设备。 8. 连接成功:设备接收到IP地址和其他网络配置信息后,与WiFi网络建立连接成功。 9. 数据传输:现在,设备可以通过WiFi网络进行数据传输,包括浏览互联网、收发电子邮件等。 10. 断开连接:当用户关闭设备的WiFi开关或者设备离开WiFi网络的范围时,设备会与WiFi网络断开连接。 总的来说,AndroidWiFi连接流程图涵盖了搜索、选择、连接认证、IP地址获取、数据传输等多个环节,确保设备可以顺利地连接和使用WiFi网络。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值