如果你也是年轻的程序员,关注我一起学习探讨


Android9.0中对热点做了较大改动,将热点很大程度从Wifi中剥离出来了。
下面我们看一下热点是怎么开启的。

首先是在WifiTetherSettings中,调用startTether()函数,可以看到startTether函数中主要是调用了WifiTetherSwitchBarController.java中的startTether()函数。
源码路径:
http://androidxref.com/9.0.0_r3/xref/packages/apps/Settings/src/com/android/settings/wifi/tether/WifiTetherSettings.java#174

    private void startTether() {mRestartWifiApAfterConfigChange = false;mSwitchBarController.startTether();}

然后我们看WifiTetherSwitchBarController里的startTether函数,WifiTetherSwitchBarController是用来控制开关栏切换的,可以看到他调用了ConnectivityManager的startTethering函数。
源码路径:
http://androidxref.com/9.0.0_r3/xref/packages/apps/Settings/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java#107

    void startTether() {mSwitchBar.setEnabled(false);mConnectivityManager.startTethering(TETHERING_WIFI, true /* showProvisioningUi */,mOnStartTetheringCallback, new Handler(Looper.getMainLooper()));}

然后在这里调用了ConnectivityService的startTethering函数。
源码路径:
http://androidxref.com/9.0.0_r3/xref/frameworks/base/core/java/android/net/ConnectivityManager.java#2261

    public void startTethering(int type, boolean showProvisioningUi,final OnStartTetheringCallback callback, Handler handler) {try {String pkgName = mContext.getOpPackageName();Log.i(TAG, "startTethering caller:" + pkgName);mService.startTethering(type, wrappedCallback, showProvisioningUi, pkgName);} catch (RemoteException e) {Log.e(TAG, "Exception trying to start tethering.", e);wrappedCallback.send(TETHER_ERROR_SERVICE_UNAVAIL, null);}}

在ConnectivityService中,会跳到Tethering.java的startTethering函数。
源码路径:
http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/ConnectivityService.java#3232

    public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi,String callerPkg) {ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);if (!isTetheringSupported()) {receiver.send(ConnectivityManager.TETHER_ERROR_UNSUPPORTED, null);return;}mTethering.startTethering(type, receiver, showProvisioningUi);}

在Tethering.java中,函数的调用顺序如下:startTethering—>enableTetheringInternal—>setWifiTethering。在setWifiTethering中,调用了WifiManager的startSoftAp函数。
源码路径:
http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/connectivity/Tethering.java#368

368    public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi) {if (!isTetherProvisioningRequired()) {enableTetheringInternal(type, true, receiver);return;}if (showProvisioningUi) {runUiTetherProvisioningAndEnable(type, receiver);} else {runSilentTetherProvisioningAndEnable(type, receiver);}}
    private void enableTetheringInternal(int type, boolean enable, ResultReceiver receiver) {boolean isProvisioningRequired = enable && isTetherProvisioningRequired();int result;switch (type) {case TETHERING_WIFI:result = setWifiTethering(enable);if (isProvisioningRequired && result == TETHER_ERROR_NO_ERROR) {scheduleProvisioningRechecks(type);}sendTetherResult(receiver, result);break;
    private int setWifiTethering(final boolean enable) {int rval = TETHER_ERROR_MASTER_ERROR;final long ident = Binder.clearCallingIdentity();try {synchronized (mPublicSync) {mWifiTetherRequested = enable;final WifiManager mgr = getWifiManager();if ((enable && mgr.startSoftAp(null /* use existing wifi config */)) ||(!enable && mgr.stopSoftAp())) {rval = TETHER_ERROR_NO_ERROR;}}} finally {Binder.restoreCallingIdentity(ident);}return rval;}

在这里调用了WifiServiceImpl.java的startSoftAp函数。
源码路径:
http://androidxref.com/9.0.0_r3/xref/frameworks/base/wifi/java/android/net/wifi/WifiManager.java#1909

    public boolean startSoftAp(@Nullable WifiConfiguration wifiConfig) {try {return mService.startSoftAp(wifiConfig);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}

在这里调用了startSoftApInternal函数,然后向WifiController的状态机发送了CMD_SET_AP消息。
源码路径:
http://androidxref.com/9.0.0_r3/xref/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiServiceImpl.java#1004

    public boolean startSoftAp(WifiConfiguration wifiConfig) {// NETWORK_STACK is a signature only permission.enforceNetworkStackPermission();mLog.info("startSoftAp uid=%").c(Binder.getCallingUid()).flush();synchronized (mLocalOnlyHotspotRequests) {// If a tethering request comes in while we have LOHS running (or requested), call stop// for softap mode and restart softap with the tethering config.if (!mLocalOnlyHotspotRequests.isEmpty()) {stopSoftApInternal();}return startSoftApInternal(wifiConfig, WifiManager.IFACE_IP_MODE_TETHERED);}}
    private boolean startSoftApInternal(WifiConfiguration wifiConfig, int mode) {mLog.trace("startSoftApInternal uid=% mode=%").c(Binder.getCallingUid()).c(mode).flush();// null wifiConfig is a meaningful input for CMD_SET_APif (wifiConfig == null || WifiApConfigStore.validateApWifiConfiguration(wifiConfig)) {SoftApModeConfiguration softApConfig = new SoftApModeConfiguration(mode, wifiConfig);mWifiController.sendMessage(CMD_SET_AP, 1, 0, softApConfig);return true;}Slog.e(TAG, "Invalid WifiConfiguration");return false;}

在这里,处理结果是调用WifiStateMachinePrime的enterSoftAPMode方法。
源码路径:
http://androidxref.com/9.0.0_r3/xref/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiController.java#593

    class DefaultState extends State {case CMD_SET_AP:// note: CMD_SET_AP is handled/dropped in ECM mode - will not start here// first make sure we aren't in airplane modeif (mSettingsStore.isAirplaneModeOn()) {log("drop softap requests when in airplane mode");break;}if (msg.arg1 == 1) {SoftApModeConfiguration config = (SoftApModeConfiguration) msg.obj;mWifiStateMachinePrime.enterSoftAPMode((SoftApModeConfiguration) msg.obj);} else {mWifiStateMachinePrime.stopSoftAPMode();}break;

在WifiStateMachinePrime中,创建了SoftApManager对象,并且调用了start方法。
源码路径:
http://androidxref.com/9.0.0_r3/xref/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachinePrime.java#549

    public void enterSoftAPMode(@NonNull SoftApModeConfiguration wifiConfig) {mHandler.post(() -> {startSoftAp(wifiConfig);});}
    private void startSoftAp(SoftApModeConfiguration softapConfig) {Log.d(TAG, "Starting SoftApModeManager");WifiConfiguration config = softapConfig.getWifiConfiguration();if (config != null && config.SSID != null) {Log.d(TAG, "Passing config to SoftApManager! " + config);} else {config = null;}SoftApCallbackImpl callback = new SoftApCallbackImpl();ActiveModeManager manager = mWifiInjector.makeSoftApManager(callback, softapConfig);callback.setActiveModeManager(manager);manager.start();mActiveModeManagers.add(manager);updateBatteryStatsWifiState(true);}

在这里,StateMachine发送了消息CMD_START,然后由IdleState 处理,这里主要的处理结果就是调用startSoftAp方法。在startSoftAp里,调用了WifiNative.java的startSoftAp方法。
源码路径:
http://androidxref.com/9.0.0_r3/xref/frameworks/opt/net/wifi/service/java/com/android/server/wifi/SoftApManager.java#142

    public void start() {mStateMachine.sendMessage(SoftApStateMachine.CMD_START, mApConfig);}
        private class IdleState extends State {public boolean processMessage(Message message) {switch (message.what) {case CMD_START:mApInterfaceName = mWifiNative.setupInterfaceForSoftApMode(mWifiNativeInterfaceCallback);if (TextUtils.isEmpty(mApInterfaceName)) {Log.e(TAG, "setup failure when creating ap interface.");updateApState(WifiManager.WIFI_AP_STATE_FAILED,WifiManager.WIFI_AP_STATE_DISABLED,WifiManager.SAP_START_FAILURE_GENERAL);mWifiMetrics.incrementSoftApStartResult(false, WifiManager.SAP_START_FAILURE_GENERAL);break;}updateApState(WifiManager.WIFI_AP_STATE_ENABLING,WifiManager.WIFI_AP_STATE_DISABLED, 0);int result = startSoftAp((WifiConfiguration) message.obj);if (result != SUCCESS) {int failureReason = WifiManager.SAP_START_FAILURE_GENERAL;if (result == ERROR_NO_CHANNEL) {failureReason = WifiManager.SAP_START_FAILURE_NO_CHANNEL;}updateApState(WifiManager.WIFI_AP_STATE_FAILED,WifiManager.WIFI_AP_STATE_ENABLING,failureReason);stopSoftAp();mWifiMetrics.incrementSoftApStartResult(false, failureReason);break;}transitionTo(mStartedState);break;
    private int startSoftAp(WifiConfiguration config) {if (config == null || config.SSID == null) {Log.e(TAG, "Unable to start soft AP without valid configuration");return ERROR_GENERIC;}// Make a copy of configuration for updating AP band and channel.WifiConfiguration localConfig = new WifiConfiguration(config);int result = ApConfigUtil.updateApChannelConfig(mWifiNative, mCountryCode,mWifiApConfigStore.getAllowed2GChannel(), localConfig);if (result != SUCCESS) {Log.e(TAG, "Failed to update AP band and channel");return result;}// Setup country code if it is provided.if (mCountryCode != null) {// Country code is mandatory for 5GHz band, return an error if failed to set// country code when AP is configured for 5GHz band.if (!mWifiNative.setCountryCodeHal(mApInterfaceName, mCountryCode.toUpperCase(Locale.ROOT))&& config.apBand == WifiConfiguration.AP_BAND_5GHZ) {Log.e(TAG, "Failed to set country code, required for setting up "+ "soft ap in 5GHz");return ERROR_GENERIC;}}if (localConfig.hiddenSSID) {Log.d(TAG, "SoftAP is a hidden network");}if (!mWifiNative.startSoftAp(mApInterfaceName, localConfig, mSoftApListener)) {Log.e(TAG, "Soft AP start failed");return ERROR_GENERIC;}Log.d(TAG, "Soft AP is started");return SUCCESS;}

在这里,主要是调用WificondControl.java的startHostapd方法。
源码路径:
http://androidxref.com/9.0.0_r3/xref/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java#1250

    public boolean startSoftAp(@NonNull String ifaceName, WifiConfiguration config, SoftApListener listener) {if (!mWificondControl.startHostapd(ifaceName, listener)) {Log.e(TAG, "Failed to start hostapd");mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();return false;}if (!waitForHostapdConnection()) {Log.e(TAG, "Failed to establish connection to hostapd");mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();return false;}if (!mHostapdHal.registerDeathHandler(new HostapdDeathHandlerInternal())) {Log.e(TAG, "Failed to register hostapd death handler");mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();return false;}if (!mHostapdHal.addAccessPoint(ifaceName, config)) {Log.e(TAG, "Failed to add acccess point");mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();return false;}return true;}

在这里可以看到创建了IApInterface 对象,然后调用了他的startHostapd方法。而IApInterface 是由ap_interface_impl.cpp实现的。
源码路径:
http://androidxref.com/9.0.0_r3/xref/frameworks/opt/net/wifi/service/java/com/android/server/wifi/WificondControl.java#787

    public boolean startHostapd(@NonNull String ifaceName,SoftApListener listener) {IApInterface iface = getApInterface(ifaceName);if (iface == null) {Log.e(TAG, "No valid ap interface handler");return false;}try {IApInterfaceEventCallback  callback = new ApInterfaceEventCallback(listener);mApInterfaceListeners.put(ifaceName, callback);boolean success = iface.startHostapd(callback);if (!success) {Log.e(TAG, "Failed to start hostapd.");return false;}} catch (RemoteException e) {Log.e(TAG, "Exception in starting soft AP: " + e);return false;}return true;}

在这里又调用了hostapd_manager的StartHostapd函数。
源码路径:
http://androidxref.com/9.0.0_r3/xref/system/connectivity/wificond/ap_interface_impl.cpp#86

bool ApInterfaceImpl::StartHostapd() {return hostapd_manager_->StartHostapd();
}

然后在hostapd_manager.cpp里调用了StartHostapd方法。
源码路径:
http://androidxref.com/9.0.0_r3/xref/frameworks/opt/net/wifi/libwifi_system/hostapd_manager.cpp#26

bool HostapdManager::StartHostapd() {if (property_set("ctl.start", kHostapdServiceName) != 0) {LOG(ERROR) << "Failed to start SoftAP";return false;LOG(DEBUG) << "SoftAP started successfully";return true;
}

再往后就是底层C的代码了,不是特别看得懂。然后返回success的话,热点就成功打开了,状态也变为started。

Android9.0Wifi热点开启流程梳理相关推荐

  1. (七十一)Android O WiFi热点 开启流程梳理

    前言:之前主要梳理了WiFi开启扫描连接的流程,现在梳理下WiFi 热点 的开启流程. 时序图mdj样式:https://download.csdn.net/download/sinat_200594 ...

  2. (九十七)Android O WiFi热点 开启流程梳理续(二)

    前言:从之前WiFi的连接流程可以知道WiFi最后一步会和服务端进行dhcp以获取ip地址,那么WiFi热点开启的时候应该也要配置相关dhcp属性,以供后续WiFi连接的时候ip分配,根据这块流程继续 ...

  3. Android11 热点开启流程

    Android11 热点开启流程 文章目录 Android11 热点开启流程 一.应用中热点开启和关闭的代码: 二.系统源码追踪 1.ConnectivityManager.startTetherin ...

  4. android9.0蓝牙功能,Android9.0 蓝牙开启流程

    微信扫码,给个关注吧 第一次接触蓝牙,先从蓝牙的开启流程入手吧,借此顺便熟悉一下蓝牙的代码架构. 1.UI /packages/apps/Settings/src/com/android/settin ...

  5. Android 10.0热点为Enhanced Open模式时不允许WiFI和热点同时开启代码流程梳理

    前言: WLAN Enhanced Open 官方介绍 WLAN Enhanced Open :WiFi增强开放,这个功能就是当手机开启热点时,Securty的一个选项,与WPA2/WPA3同级,En ...

  6. Android 11 WiFi开启流程

    从刚接触WiFi时跟过wifi的开启流程,当时还是android9.到了Android11代码架构有了不小的改动,在这里重新梳理一遍,便于在工作中更快速的跟踪代码. 一.Settings里改动不大,还 ...

  7. 【Binder 机制】AIDL 分析 ( AIDL 通信完整流程梳理 )

    文章目录 AIDL 跨进程通信完整流程梳理 1.AIDL 文件编译 2.注册服务 3.IMyAidlInterface.Stub.asInterface 方法获取远程服务 4.IMyAidlInter ...

  8. android 13 热点启动流程

    近期在看一个热点启动的问题.发现网上基本上都算android 9 的wifi热点启动流程.自己去看android 13 的源码的时候发现与之前相比已经有一些小改动了. 在此总结一下wifie热点的启动 ...

  9. 仰邦LED(BX-Y08)二次开发的java版流程梳理记录

    仰邦LED-bx_y08二次开发的java版流程梳理记录 首次开发的项目是一个停车场主要显示剩余多少车辆 遇到很多难题;主要还要搞清楚二次开发LED的发送流程,在这记录下 //初始化API环境 仅一次 ...

最新文章

  1. 起搏器可以用计算机吗,关于起搏器患者能否做核磁共振的最全说法
  2. Hibernate 之单向多对一映射及其衍生问题
  3. 一分钟带你玩转 Spring IoC
  4. android java函数_java – 在android中创建全局函数
  5. excel 地级市名单_“excel随机抽取名单“谁有全国行政区划列表(EXCEL版且含省市县乡)?...
  6. 暴力猴简单脚本 - 去除右键菜单、文本选择限制
  7. 社交网络分析的 R 基础:(五)图的导入与简单分析
  8. mysql 允许局域网连接_设置Mysql允许局域网或外部连接
  9. 笔记本电脑连接无线网总是突然断网
  10. Markdown任务列表(实现列表勾选/非勾选操作)
  11. Hexo接入码云评论系统
  12. 配置树莓派中文环境 及解决 no write since last change
  13. 怎么用java程序控制步进电机_用单片机按键控制步进电机转动的程序怎么写
  14. Codeforces Round #193 (Div. 2) B. Maximum Absurdity(线段树+思维)
  15. 图像处理--医疗图片的处理
  16. ios rsa加密 java解密_iOS RSA加密与解密 签名与验签(附Java端处理)
  17. URAL_2032_Conspiracy Theory and Rebranding(暴力枚举)
  18. 商越程序:企业在采购数字化变革设计思路上的“四个改变”
  19. Vue2系列教程——SSR服务端渲染
  20. FORTRAN动态链接库DLL from《FORTRAN95 程序设计》

热门文章

  1. 【redis】无法链接远程redis服务器,解决办法集合
  2. 解决python编码格式错误问题
  3. 个税专项附加扣除怎么搞?新华社逐条解析
  4. 休学的影响来了,家长多养孩子一年
  5. java juc exchanger_JUC之Exchanger
  6. 【李宏毅2021机器学习深度学习】作业讲解 笔记收藏 课程主页
  7. idea 字体行间距_idea
  8. 如何将微信公众号文章同步导入采集到WordPress网站中
  9. 全双工,双工,单工的区别
  10. ucos查找最高优先级任务