softap的入口在ConnectivityManager.java中,作为连接的一部分。老版本Android的入口在WifiManager.java中。应用启动softap时,调用ConnectivityManager.startTethering()开始。

    @SystemApi@RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)public void startTethering(int type, boolean showProvisioningUi,final OnStartTetheringCallback callback, Handler handler) {Preconditions.checkNotNull(callback, "OnStartTetheringCallback cannot be null.");ResultReceiver wrappedCallback = new ResultReceiver(handler) {@Overrideprotected void onReceiveResult(int resultCode, Bundle resultData) {if (resultCode == TETHER_ERROR_NO_ERROR) {callback.onTetheringStarted();} else {callback.onTetheringFailed();}}};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);}}

参数type有三个类型:

ConnectivityManager.TETHERING_WIFI
ConnectivityManager.TETHERING_USB
ConnectivityManager.TETHERING_BLUETOOTH

我们现在关注的TETHERING_WIFI。进入到ConnectivityService.java中:

@ConnectivityService.java@Overridepublic 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);}

mTethering是Tethering类的实例。mTethering.startTethering的将调用enableTetheringInternal()方法。

    private void enableTetheringInternal(int type, boolean enable, ResultReceiver receiver) {int result;switch (type) {case TETHERING_WIFI:result = setWifiTethering(enable);sendTetherResult(receiver, result);break;case TETHERING_USB:result = setUsbTethering(enable);sendTetherResult(receiver, result);break;case TETHERING_BLUETOOTH:setBluetoothTethering(enable, receiver);break;default:Log.w(TAG, "Invalid tether type.");sendTetherResult(receiver, TETHER_ERROR_UNKNOWN_IFACE);}}private int setWifiTethering(final boolean enable) {final long ident = Binder.clearCallingIdentity();try {synchronized (mPublicSync) {final WifiManager mgr = getWifiManager();if (mgr == null) {mLog.e("setWifiTethering: failed to get WifiManager!");return TETHER_ERROR_SERVICE_UNAVAIL;}if ((enable && mgr.startSoftAp(null /* use existing wifi config */)) ||(!enable && mgr.stopSoftAp())) {mWifiTetherRequested = enable;return TETHER_ERROR_NO_ERROR;}}} finally {Binder.restoreCallingIdentity(ident);}return TETHER_ERROR_MASTER_ERROR;}

对于softap,在setWifiTethering()方法中,将调用WifiManager.startSoftAp(null),一切回到从前。

直接进入WifiServiceImpl.java中查看。

@WifiServiceImpl.java
public boolean startSoftAp(WifiConfiguration wifiConfig) {return startSoftApInternal(wifiConfig, WifiManager.IFACE_IP_MODE_TETHERED);
}

这里的wifiConfig参数为null。startSoftApInternal()方法实现为:

@WifiServiceImpl.java
private boolean startSoftApInternal(WifiConfiguration wifiConfig, int mode) {mLog.trace("startSoftApInternal uid=% mode=%").c(Binder.getCallingUid()).c(mode).flush();if (wifiConfig == null && TextUtils.isEmpty(mCountryCode.getCountryCode())) {Log.d(TAG, "Starting softap without country code. Fallback to 2G band");wifiConfig = new WifiConfiguration(mWifiApConfigStore.getApConfiguration());wifiConfig.apBand = WifiConfiguration.AP_BAND_2GHZ;}setDualSapMode(wifiConfig);if (wifiConfig == null || WifiApConfigStore.validateApWifiConfiguration(wifiConfig)) {SoftApModeConfiguration softApConfig = new SoftApModeConfiguration(mode, wifiConfig);Log.i(TAG, "Starting softap 2 apChannel=" + wifiConfig.apChannel);mWifiController.sendMessage(CMD_SET_AP, 1, 0, softApConfig);return true;}
}

上面的代码,首先会尝试从WifiApConfigStore中获取已经保存的ap配置信息。这个信息是通过WifiManager.setWifiApConfiguration()方法写入的。如果WifiApConfigStore获取不到,null也可以继续往下传递。接下来有WifiController出来CMD_SET_AP消息。

CMD_SET_AP消息会在WifiController的父类状态DefaultState中处理。处理方法如下:

@WifiController.java
case CMD_SET_AP:// note: CMD_SET_AP is handled/dropped in ECM mode - will not start here// If request is to start dual sap, turn off sta.if (msg.arg1 == 1 && mWifiApConfigStore.getDualSapStatus()) {mActiveModeWarden.disableWifi();transitionTo(mStaDisabledState);}if (msg.arg1 == 1) {SoftApModeConfiguration config = (SoftApModeConfiguration) msg.obj;mActiveModeWarden.enterSoftAPMode((SoftApModeConfiguration) msg.obj);} else {mActiveModeWarden.stopSoftAPMode(msg.arg2);}break;

转入WIFI模式管理类进一步操作:

@ActiveModeWarden.java
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(softapConfig.getTargetMode());ActiveModeManager manager = mWifiInjector.makeSoftApManager(callback, softapConfig);callback.setActiveModeManager(manager);manager.start();mActiveModeManagers.add(manager);updateBatteryStatsWifiState(true);
}

SoftApCallbackImpl类中将调用WifiManager.SoftApCallbackImpl()注册的回调方法,通知到应用程序。makeSoftApManager构造一个SoftApManager对象。Client, softap都有一个父类为ActiveModeManager的状态管理类。makeSoftApManager()方法中传入了apconfig, 回调防暑等必要信息。

调用SoftApManager的start方法。

    public void start() {mStateMachine.sendMessage(SoftApStateMachine.CMD_START, mApConfig);}

向mStateMachine状态机发送CMD_START信息。

在SoftApManager.java中有SoftApStateMachine状态机。只有两种状态:

@SoftApManager.java
SoftApStateMachine(Looper looper) {super(TAG, looper);addState(mIdleState);addState(mStartedState);setInitialState(mIdleState);start();
}

CMD_START在IdleState中处理,首先会启动hostapd进程。

mApInterfaceName = mWifiNative.setupInterfaceForSoftApMode(mWifiNativeInterfaceCallback);

最后将调用startSoftAp()。

@SoftApManager.java
private int startSoftAp(WifiConfiguration config) {//设置国家码mWifiNative.setCountryCodeHal(mApInterfaceName, mCountryCode.toUpperCase(Locale.ROOT));// 是否支持5Gif (config.apBand == WifiConfiguration.AP_BAND_5GHZ&& !mWifiNative.is5GhzBandSupported()) {mSoftApStartFailureDesc = WifiManager.WIFI_AP_FAILURE_DESC_NO_5GHZ_SUPPORT;Log.e(TAG, "Failed to start soft AP as 5Ghz band not supported");return ERROR_NO_CHANNEL;} else {mSoftApStartFailureDesc = "";}// Make a copy of configuration for updating AP band and channel.WifiConfiguration localConfig = new WifiConfiguration(config);// 如果apchannel,根据配置文件config_wifi_framework_sap_2G_channel_list,随机查找一个信道int result = ApConfigUtil.updateApChannelConfig(mWifiNative, mCountryCode,mWifiApConfigStore.getAllowed2GChannel(), localConfig);// 开启SoftApmWifiNative.startSoftAp(mApInterfaceName, localConfig, mSoftApListener);mStartTimestamp = SystemClock.elapsedRealtime();
}

上面函数,在通过检查国家码,是否支持5G信道后,来判断配置是否正确。如果apchannel=0,还会从xml设置的信道中,随机选择一个信道作为参数。最后调用WifiNative.startSoftAp().

public boolean startSoftAp(@NonNull String ifaceName, WifiConfiguration config, SoftApListener listener) {if (!mWificondControl.registerApListener(ifaceName, listener)) {Log.e(TAG, "Failed to register ap listener");return false;}if (mHostapdHal.isVendorHostapdHal()) {if (!mHostapdHal.addVendorAccessPoint(ifaceName, config, listener)) {Log.e(TAG, "Failed to add Vendor acccess point");mWifiMetrics.incrementNumSetupSoftApInterfaceFailureDueToHostapd();return false;}}
}

Android10 高通平台 softap热点基本流程1相关推荐

  1. Android10 高通平台 softap热点基本流程2

    上一篇讲到SoftApManager.IdleState状态中处理CMD_START消息,这个消息用来打开热点功能.我们从这里继续看热点功能基本流程. public boolean processMe ...

  2. 高通平台RF配置流程

    高通平台RF配置流程 **注:**本文参考项目路径和代码为SIM7600 LE20分支 1 准备工作 需要的资料: 各个器件的datasheet 原理图 逻辑表(内容包含支持哪些制式.band,各个b ...

  3. 高通平台Bootloader启动流程【转】

    本文转载自:http://blog.csdn.net/fang_first/article/details/49615631 ====================基本知识============= ...

  4. 高通平台msm8917蓝牙mac地址流程

    高通平台msm8917蓝牙mac地址流程 Where is the BD address? BD address can be saved in following places: modem NV ...

  5. 高通android开源代码下载,高通平台Android源码bootloader分析之sbl1(三)

    前两篇博文分析了启动流程.代码流程.cdt,接下来就分析另外几个需要格外关注的部分. ##log系统 sbl1中的log系统也是sbl1部分调试会经常接触得部分高通平台在sbl中做的log系统并不是很 ...

  6. android加载efi分区,高通Android UEFI XBL 代码流程分析

    高通Android UEFI XBL 代码流程分析 背景 之前学习的lk阶段点亮LCD的流程算是比较经典,但是高通已经推出了很多种基于UEFI方案的启动架构. 所以需要对这块比较新的技术进行学习.在学 ...

  7. 高通平台sensor学习

    刚入行驱动时最先接触调试的外设模块便是sensor,一直都是零零散散的记录,这次终于下定决心对自己所学做一个系统的总结. sensor作为一款常用的外设,虽不起眼但是很多功能确实离不开它.比如我们手机 ...

  8. 高通平台android开发总结 MSM平台上的AMSS

    http://blog.csdn.net/mirkerson/article/details/7691029 MSM平台上的AMSS REX启动分析--基于Qualcomm平台 1.高通平台andro ...

  9. 高通平台 lcd driver 调试小结

    一.概述 1.1 简介 本文档主要包括LCD模块的驱动流程分析.Framebuffer相关知识.Gralloc等相关内容,以及LCD调试的一些经验和相关bug的分析和讲解. 1.2  开发环境 And ...

最新文章

  1. java8的jvm优化_基于JDK8 版本的SpringBoot 启动参数优化(建议收藏)
  2. python 搜索二维矩阵
  3. python cpython关系_第3篇:CPython内部探究:PyASCIIObject的初始化
  4. debug LUW1 - do binding workflow
  5. vue3 v-model变化
  6. 第9步 spring 配置 springmvc配置
  7. 国际站html代码,国际站必须看得懂的HTML代码
  8. java 技能鉴定_JAVA试题-技能鉴定
  9. python分类算法的应用_Python使用sklearn库实现的各种分类算法简单应用小结
  10. IP计算机取证,计算机取证1资料.doc
  11. Python数据结构与算法(3.5)——双端队列
  12. Mac上emacs gpg: 无法检查签名:没有公钥
  13. MCU程序布局----优化升级方式
  14. QThread: Destroyed while thread is still running的处理方法
  15. 七里香计算机音乐谱子,七里香(改编自《新经典》)
  16. qq邮箱收信服务器imap,普通IMAP、POP邮箱的设置 教你使用iPhone邮件客户端管理QQ邮箱...
  17. 个人手机网站接入支付宝在线收款功能
  18. 服务器怎么建ip网站,云服务器搭建网站ip
  19. 连接问题:ORA-3136:inbound connection timed out
  20. Eclipse+ GNU ARM Eclipse Plug-in+ Sourcery G++ Lite Edition for ARM+OPENCD+Jlink

热门文章

  1. mktime() php,php中mktime()函数是什么
  2. 零基础搭建属于自己的网站--网页设计【学习笔记6】
  3. 典型回溯题目 - 全排列(一、二)
  4. Unity音乐播放完整案例
  5. Linux下GitLab服务器搭建
  6. vue+vux vux安装出现错误
  7. 人脸识别与膜虹识别_3D人脸识别越来越普及 为何三星的虹膜识别却不受待见
  8. Kettle执行python脚本
  9. 把RecyclerView撸成 马 蜂 窝
  10. 基于springboot实现电子招投标系统项目源码