从AndroidO到AndroidP,Wifi架构上还是发生了挺多变化的。接口上也在发生变化,所以网上的很多的流程梳理已经跟当前的代码逻辑有一些差异了。不过还好,总体上,只要懂了一个版本的代码,看其他版本问题已经不是很大。

梳理还是简单易懂为要务。

调用WifiManager中的setWifiEabled()开启wifi:

public boolean setWifiEnabled(boolean enabled) {

try {

return mService.setWifiEnabled(getContext().getOpPackageName(), enabled);

} catch (RemoteException e) {

throw e.rethrowFromSystemServer();

}

}

通过aidl调用到系统进程中的服务类WifiServiceImpl.java中:

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;

}

此段代码逻辑中有涉及到权限检测,以及wifi开关状态保存等操作,最终调用到了如下方法:

mWifiController.sendMessage(CMD_WIFI_TOGGLED);

WifiController是一个状态机,接收到消息会根据处理逻辑进行不同状态的跳转,如下代码

if (checkScanOnlyModeAvailable()) {

setInitialState(mStaDisabledWithScanState);

} else {

setInitialState(mStaDisabledState);

}

WifiController的初始状态为mStaDisabledState,所以CMD_WIFI_TOGGLED消息应该在此状态下处理,查看其处理逻辑:

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;

代码逻辑大致为:

先判断当前设备状态是否支持打开wifi,如下方法:

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;

}

}

有涉及到飞行模式的相关考虑。

检测是否两次点击调用开启wifi是否时间差太短,如果太短,消息延时处理,否则的话直接跳转到mDeviceActiveState

如果wifi当前不支持打开,而此时“wifi scan always开关”打开,我们仍然要打开wifi,进入到mStaDisabledWithScanState状态。

接着上面的第二个步骤,当我们跳转到mDeviceActiveState之后,会继续相关逻辑处理。

WifiController状态机此时会用到,如下:

addState(mDefaultState);

addState(mStaDisabledState, mDefaultState);

addState(mStaEnabledState, mDefaultState);

addState(mDeviceActiveState, mStaEnabledState);

addState(mStaDisabledWithScanState, mDefaultState);

addState(mEcmState, mDefaultState);

进入到mDeviceActiveState之后会调用其enter方法,调用如下两个方法:

mWifiStateMachinePrime.enterClientMode();

mWifiStateMachine.setHighPerfModeEnabled(false);

通过查阅代码逻辑,可以看出:

/**

* Method to switch wifi into client mode where connections to configured networks will be

* attempted.

*/

public void enterClientMode() {

int mode = ModeStateMachine.CMD_START_CLIENT_MODE;

if (mIsSupportCucc) {

final FrameworkFacade facade = mWifiInjector.getFrameworkFacade();

int networktype = facade.getIntegerSetting(mContext,

Global.NETWORK_PREFERENCE, WIFI_DATA_TYPE);

int mobileDataStatus = facade.getIntegerSetting(mContext,

Global.MOBILE_DATA, MOBILE_DATA_ENABLE);

if (mobileDataStatus == MOBILE_DATA_ENABLE && networktype == MOBILE_DATA_TYPE) {

Log.d(TAG, "CUCC, client mode isn't allowed now, enter scan only mode");

mode = ModeStateMachine.CMD_START_SCAN_ONLY_MODE;

}

}

changeMode(mode);

}

看注释大意为:

使wifi跳转到client模式的一种方法,客户端模式中,

Android Wifi 启动过程,AndroidP wifi启动流程相关推荐

  1. 【Android 启动过程】Activity 启动源码分析 ( ActivityThread 流程分析 二 )

    文章目录 前言 一.ActivityManagerService.attachApplicationLocked 二.ActivityStackSupervisor.attachApplication ...

  2. 【Android 启动过程】Activity 启动源码分析 ( ActivityThread -> Activity、主线程阶段 二 )

    文章目录 前言 一.ActivityThread 类 handleLaunchActivity -> performLaunchActivity 方法 二.Instrumentation.new ...

  3. 【Android 启动过程】Activity 启动源码分析 ( AMS -> ActivityThread、AMS 线程阶段 二 )

    文章目录 前言 一.热启动与冷启动选择 二.AMS 进程中执行的相关操作 三.通过 Binder 机制转到 ActivityThread 中执行的操作 总结 前言 上一篇博客 [Android 启动过 ...

  4. 【Android 启动过程】Activity 启动源码分析 ( ActivityThread -> Activity、主线程阶段 一 )

    文章目录 前言 一.ClientTransactionHandler.scheduleTransaction 二.ActivityThread.H 处理 EXECUTE_TRANSACTION 消息 ...

  5. 你所不知道的SQL Server数据库启动过程,以及启动不起来的各种问题的分析及解决技巧

    你所不知道的SQL Server数据库启动过程,以及启动不起来的各种问题的分析及解决技巧 参考文章: (1)你所不知道的SQL Server数据库启动过程,以及启动不起来的各种问题的分析及解决技巧 ( ...

  6. linux内核启动过程5:启动用户空间

    上一篇<<linux内核启动过程4:内核运行时>>分析到了内核进入运行时状态(不退出),本篇分析用户空间(用户层)的加载过程. 启动应用空间 进入kernel_init函数,在 ...

  7. arm linux内核启动过程,ARM64的启动过程之(一):内核第一个脚印

    ARM64的启动过程之(一):内核第一个脚印 作者:linuxer 发布于:2015-10-10 15:06 分类:ARMv8A Arch 一.前言 kernel的整个启动过程涉及的内容很多,不可能每 ...

  8. 用英语简述计算机的启动过程,计算机的启动过程(详细)

    对于使用电脑用户来说,打开电源启动电脑几乎是每天必做的事情,但计算机在显示这些启动画面的时候都在做什么呢?大多数用户都未必清楚. 下面就向大家介绍一下从打开电源到出现Windows桌面的蓝天白云,计算 ...

  9. 你所不知道的SQL Server数据库启动过程,以及启动不起来的各种问题的分析及解决技巧(转)...

    目前SQL Server数据库作为微软一款优秀的RDBMS,其本身启动的时候是很少出问题的,我们在平时用的时候,很少关注起启动过程,或者很少了解其底层运行过程,大部分的过程只关注其内部的表.存储过程. ...

最新文章

  1. Nehalem LGA1156/1155插座实物首次曝光
  2. linux导出文件夹到u盘,Linux系统放到U盘上直接在U盘上运行Linux
  3. 免费在线调查系统:调查派 http://www.diaochapai.com/
  4. 民非企业盈利怎么处理_对企业法人无力偿还债务时要怎么处理,如何解决?
  5. 智能集群理论优化控制_探索群体智能的奥妙——ROB-MAS多智能体协作
  6. Lock,LockFree,MemoryBarrier,ConcurrentCollection
  7. 動態設定GridView的列寬
  8. 减少SQL Server ASYNC_NETWORK_IO等待类型
  9. 网站快速收录-网站快速收录工具下载免费
  10. 新手如何Reverces(3自动化逆向篇)
  11. juniper防火墙HA详解
  12. 在AWS Lambda上部署标准FFmpeg工具——Docker方案
  13. 微软Visual Studio Code基本特征
  14. 在表示计算机存储容量中1T,1T等于多少G,
  15. 苹果手机开热点,连上了却无网
  16. [学习笔记]数据与科学训练营之五:机器学习
  17. 罗永浩 AR 创业公司估值 10 亿;​苹果宣布加大 AppStore 广告推送量;​Node.js 19 发布|极客头条...
  18. 计算机网络技术期末考试2010模拟试题及答案
  19. [Computer Architecture读书笔记] H.2 Detecting and Enhancing Loop-Level Parallelism
  20. 调查显示,41%的下一代家族企业接班人希望未来五年成为执行董事

热门文章

  1. python实现文件上传预览_Python文件上传功能简单实现
  2. 深度学习100例 | 第51天-目标检测算法(YOLOv5)(入门篇)
  3. 爬虫 wordcloud操作
  4. day13 Python数据基本类型
  5. 剖析Elasticsearch集群系列第三篇 近实时搜索、深层分页问题和搜索相关性权衡之道...
  6. servlet 和filter 抛出404等异常
  7. Understanding Spring Web Application Architecture: The Classic Way--转载
  8. 评分卡开发方法论scorecard
  9. 区块链开发之搭建以太坊私有链
  10. 常用机器学习算法原理及推导