1.先打开p2p后打开softap

softap的interface会将p2p的interface替换掉,适合于下面列出来的rule 4

HalDeviceManager

    /*** Returns true if we're allowed to delete the existing interface type for the requested* interface type.** Rules - applies in order:** General rules:* 1. No interface will be destroyed for a requested interface of the same type* 2. No interface will be destroyed if one of the requested interfaces already exists* 3. If there are >1 interface of an existing type, then it is ok to destroy that type*    interface** Type-specific rules (but note that the general rules are appied first):* 4. Request for AP or STA will destroy any other interface* 5. Request for P2P will destroy NAN-only (but will destroy a second STA per #3)* 6. Request for NAN will not destroy any interface (but will destroy a second STA per #3)** Note: the 'numNecessaryInterfaces' is used to specify how many interfaces would be needed to* be deleted. This is used to determine whether there are that many low priority interfaces* of the requested type to delete.*/private boolean allowedToDeleteIfaceTypeForRequestedType(int existingIfaceType,int requestedIfaceType, WifiIfaceInfo[][] currentIfaces, int numNecessaryInterfaces) {// rule 0: check for any low priority interfacesint numAvailableLowPriorityInterfaces = 0;for (InterfaceCacheEntry entry : mInterfaceInfoCache.values()) {if (entry.type == existingIfaceType && entry.isLowPriority) {numAvailableLowPriorityInterfaces++;}}if (numAvailableLowPriorityInterfaces >= numNecessaryInterfaces) {return true;}// rule 1if (existingIfaceType == requestedIfaceType) {return false;}// rule 2if (currentIfaces[requestedIfaceType].length != 0) {return false;}// rule 3if (currentIfaces[existingIfaceType].length > 1) {return true;}// rule 6if (requestedIfaceType == IfaceType.NAN) {return false;}// rule 5if (requestedIfaceType == IfaceType.P2P) {return existingIfaceType == IfaceType.NAN;}// rule 4, the requestIfaceType is either AP or STAreturn true;}

2.先打开softap后打开p2p

p2p打不开,因为softap优先级比较高,适用于上面的rule 5

3.softap关闭后p2p自动打开

原理在于interface destroy后会通知监听的listener

    /*** Removes (releases/destroys) the given interface. Will trigger any registered* InterfaceDestroyedListeners and possibly some InterfaceAvailableForRequestListeners if we* can potentially create some other interfaces as a result of removing this interface.*/public boolean removeIface(IWifiIface iface) {boolean success = removeIfaceInternal(iface);dispatchAvailableForRequestListeners();return success;}// dispatch all available for request listeners of the specified type AND clean-out the list:// listeners are called once at most!private boolean dispatchAvailableForRequestListeners() {if (VDBG) Log.d(TAG, "dispatchAvailableForRequestListeners");synchronized (mLock) {WifiChipInfo[] chipInfos = getAllChipInfo();if (chipInfos == null) {Log.e(TAG, "dispatchAvailableForRequestListeners: no chip info found");stopWifi(); // major error: shutting downreturn false;}if (VDBG) {Log.d(TAG, "dispatchAvailableForRequestListeners: chipInfos="+ Arrays.deepToString(chipInfos));}for (int ifaceType : IFACE_TYPES_BY_PRIORITY) {dispatchAvailableForRequestListenersForType(ifaceType, chipInfos);}}return true;}

依次按优先级通知各个interface type对应的listener(只有在有可能创建的时候才会真正去通知)

    private void dispatchAvailableForRequestListenersForType(int ifaceType,WifiChipInfo[] chipInfos) {if (VDBG) Log.d(TAG, "dispatchAvailableForRequestListenersForType: ifaceType=" + ifaceType);synchronized (mLock) {Map<InterfaceAvailableForRequestListenerProxy, Boolean> listeners =mInterfaceAvailableForRequestListeners.get(ifaceType);if (listeners.size() == 0) {return;}boolean isAvailable = isItPossibleToCreateIface(chipInfos, ifaceType);if (VDBG) {Log.d(TAG, "Interface available for: ifaceType=" + ifaceType + " = " + isAvailable);}for (Map.Entry<InterfaceAvailableForRequestListenerProxy, Boolean> listenerEntry :listeners.entrySet()) {if (listenerEntry.getValue() == null || listenerEntry.getValue() != isAvailable) {if (VDBG) {Log.d(TAG, "Interface available listener dispatched: ifaceType=" + ifaceType+ ", listener=" + listenerEntry.getKey());}listenerEntry.getKey().triggerWithArg(isAvailable);}listenerEntry.setValue(isAvailable);}}}

看下哪些interface会注册监听器

    /*** Register a listener to be called when an interface of the specified type could be requested.* No guarantees are provided (some other entity could request it first). The listener is* active from registration until unregistration - using* unregisterInterfaceAvailableForRequestListener().** Only a single instance of a listener will be registered (even if the specified looper is* different).** Note that if it is possible to create the specified interface type at registration time* then the callback will be triggered immediately.** @param ifaceType The interface type (IfaceType) to be monitored.* @param listener Listener to call when an interface of the requested*                 type could be created* @param handler Handler on which to dispatch listener. Null implies the listener will be*                invoked synchronously from the context of the client which triggered the*                mode change.*/public void registerInterfaceAvailableForRequestListener(int ifaceType,@NonNull InterfaceAvailableForRequestListener listener, @Nullable Handler handler) {if (VDBG) {Log.d(TAG, "registerInterfaceAvailableForRequestListener: ifaceType=" + ifaceType+ ", listener=" + listener + ", handler=" + handler);}synchronized (mLock) {InterfaceAvailableForRequestListenerProxy proxy =new InterfaceAvailableForRequestListenerProxy(listener, handler);if (mInterfaceAvailableForRequestListeners.get(ifaceType).containsKey(proxy)) {if (VDBG) {Log.d(TAG,"registerInterfaceAvailableForRequestListener: dup listener skipped: "+ listener);}return;}mInterfaceAvailableForRequestListeners.get(ifaceType).put(proxy, null);}WifiChipInfo[] chipInfos = getAllChipInfo();if (chipInfos == null) {Log.e(TAG,"registerInterfaceAvailableForRequestListener: no chip info found - but "+ "possibly registered pre-started - ignoring");return;}dispatchAvailableForRequestListenersForType(ifaceType, chipInfos);}

这边判断key是不是一样是判断listener是不是一个

    private abstract class ListenerProxy<LISTENER>  {protected LISTENER mListener;private Handler mHandler;// override equals & hash to make sure that the container HashSet is unique with respect to// the contained listener@Overridepublic boolean equals(Object obj) {return mListener == ((ListenerProxy<LISTENER>) obj).mListener;}

主要有两个地方会调用这个监听器

http://androidxref.com/9.0.0_r3/xref/frameworks/opt/net/wifi/service/java/com/android/server/wifi/aware/WifiAwareNativeManager.java#90

NAN

http://androidxref.com/9.0.0_r3/xref/frameworks/opt/net/wifi/service/java/com/android/server/wifi/p2p/WifiP2pNative.java#162

P2P

主要看下P2P

    // Internal callback registered to HalDeviceManager.private class InterfaceAvailableListenerInternal implementsHalDeviceManager.InterfaceAvailableForRequestListener {private final HalDeviceManager.InterfaceAvailableForRequestListener mExternalListener;InterfaceAvailableListenerInternal(HalDeviceManager.InterfaceAvailableForRequestListener externalListener) {mExternalListener = externalListener;}@Overridepublic void onAvailabilityChanged(boolean isAvailable) {Log.d(TAG, "P2P InterfaceAvailableListener " + isAvailable);// We need another level of abstraction here. When a P2P interface is created,// we should mask the availability change callback from WifiP2pService.// This is because when the P2P interface is created, we'll get a callback// indicating that we can no longer create a new P2P interface. We don't need to// propagate this internal state to WifiP2pServiceImpl.if (mIWifiP2pIface != null && !isAvailable) {Log.i(TAG, "Masking interface non-availability callback because "+ "we created a P2P iface");return;}mExternalListener.onAvailabilityChanged(isAvailable);}}/*** Register for an interface available callbacks from HalDeviceManager.** @param listener callback to be invoked when the interface is available/not available.*/public void registerInterfaceAvailableListener(@NonNull HalDeviceManager.InterfaceAvailableForRequestListener listener,Handler handler) {mInterfaceAvailableListener = new InterfaceAvailableListenerInternal(listener);// The interface available callbacks are cleared on every HAL stop, so need to// re-register these callbacks on every start.mHalDeviceManager.registerStatusListener(() -> {if (mHalDeviceManager.isStarted()) {Log.i(TAG, "Registering for interface available listener");mHalDeviceManager.registerInterfaceAvailableForRequestListener(IfaceType.P2P, mInterfaceAvailableListener, handler);}}, handler);if (mHalDeviceManager.isStarted()) {mHalDeviceManager.registerInterfaceAvailableForRequestListener(IfaceType.P2P, mInterfaceAvailableListener, handler);}}

http://androidxref.com/9.0.0_r3/xref/frameworks/opt/net/wifi/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java#744

                // Register for interface availability from HalDeviceManagermWifiNative.registerInterfaceAvailableListener((boolean isAvailable) -> {mIsInterfaceAvailable = isAvailable;if (isAvailable) {checkAndReEnableP2p();}checkAndSendP2pStateChangedBroadcast();}, getHandler());// Check & re-enable P2P if needed.// P2P interface will be created if all of the below are true:// a) Wifi is enabled.// b) P2P interface is available.// c) There is atleast 1 client app which invoked initialize().private void checkAndReEnableP2p() {Log.d(TAG, "Wifi enabled=" + mIsWifiEnabled + ", P2P Interface availability="+ mIsInterfaceAvailable + ", Number of clients=" + mDeathDataByBinder.size());if (mIsWifiEnabled && mIsInterfaceAvailable && !mDeathDataByBinder.isEmpty()) {sendMessage(ENABLE_P2P);}}

原生逻辑会在WiFi打开p2p可得并且当前有p2p client的情况下将p2p打开

4.总结

总结下softap的优先级比p2p高,只有在关闭热点的情况下才能使用p2p相关功能。

原生p2p一直打开,不知道是处于什么考虑,热点打开的时候ap会替换掉p2p,p2p无法取代ap,但ap关闭后p2p会有条件开启。

(一百七十一) 探索softap和p2p interface优先级相关推荐

  1. 计算机网络 - 练习(一百七十一)

    计算机网络 练习(一百七十一) 以下关于 S-HTTP 的描述中,正确的是(). A. S-HTTP 是一种面向报文的安全通讯协议,使用 TCP 443 端口 B. S-HTTP所使用的语法和报文格式 ...

  2. Android开发笔记(一百七十一)使用Glide加载网络图片

    如何方便而又快速地显示网络图片,一直是安卓网络编程的热门课题,前些年图片缓存框架Picasso.Fresco等等大行其道,以至于谷歌按捺不住也开发了自己的Glide开源库.由于Android本身就是谷 ...

  3. 七十一、Python | Leetcode字符串系列(上篇)

    @Author:Runsen @Date:2020/7/3 人生最重要的不是所站的位置,而是内心所朝的方向.只要我在每篇博文中写得自己体会,修炼身心:在每天的不断重复学习中,耐住寂寞,练就真功,不畏艰 ...

  4. JavaScript学习(七十一)—call、apply、bind学习总结

    JavaScript学习(七十一)-call.apply.bind学习总结 一.call方法 call方法调用一个对象,简单的理解为调用函数的方式,但是它可以改变函数的this指向 二.apply() ...

  5. 【正点原子Linux连载】第七十一章 Linux 4G通信实验 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0

    1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址: ...

  6. 达芬奇密码 第七十一章

    达芬奇密码 第七十一章[@more@] 第七十一章 "猎鹰者"号腾空而起,向英格兰方向飞去.兰登小心翼翼地将紫檀木盒子从膝盖上举起来.刚才飞机起飞时,他就一直把它放在膝盖上,保护着 ...

  7. 第七十一章 SQL命令 SELECT(三)

    文章目录 第七十一章 SQL命令 SELECT(三) 列别名 字段列别名 Non-Field列别名 FROM子句 表的别名 Sharding Transparent to SELECT Queries ...

  8. 【Microsoft Azure 的1024种玩法】七十一.基于Azure Virtual Machines快速上手搭建Typecho博客系统

    [简介] Typecho 是基于 PHP5 构建的开源跨平台博客系统,Typecho开源跨平台博客系统相较于wordpress .hexo有一定的性能优势,是我们记录文章内容的最佳首选博客,那么本篇文 ...

  9. eigen 编译_OpenCV+Eigen上位机程序移植(七十一)

    1.给硬盘分区 现在小伙伴们对于给电脑硬盘分区想必比较头疼,给电脑硬盘分区分为两种情况,一是在安装系统之前给系统硬盘分区,二是在安装系统之后给硬盘分区,我们现在购买的品牌机和笔记本的用户比较多,而且笔 ...

最新文章

  1. Python基本语法_函数_返回值
  2. BZOJ1795 : [Ioi2008]Pyramid Base 金字塔地基
  3. PostMessage和sendMessage传递问题
  4. python set
  5. 福建计算机及应用专业的大学,33所福建大学公布国家级/省级一流本科专业!
  6. 【AI视野·今日NLP 自然语言处理论文速览 第二十六期】Wed, 3 Nov 2021
  7. 虚拟资源拳王公社:虚拟副业怎么赚钱,最简单的副业是什么,小白没经验怎么做副业
  8. Java内存溢出异常(下)
  9. Hive静态分区和动态分区
  10. java9之后,String为何从char类型数组转成byte类型数组
  11. Apache commons-text和Configuration 命令执行CVE-2022-42889/CVE-2022-33980分析
  12. 深入浅出设计模式---5、享元模式
  13. python3根据图片链接下载图片
  14. 怎样查找MP3音乐链接地址 用于QQ空间背景
  15. Redis的那些事儿:关系型和非关系型数据库,非关系型数据库的类型,redis数据类型、编码格式、高性能、可以做什么、分布式锁失效的原因,string为采用sds数据类型,为什么是二进制安全的,
  16. 英特尔芯片漏洞比想象中更严重:控制计算机无需密码
  17. JTAG与SWD接口定义映射
  18. 2021爱分析・数据智能平台实践报告—重构数据智能时代的数据基础设施
  19. 小车高速怎么收费标准_2018小轿车高速路收费标准 私家车走高速怎么收费
  20. Struts2自定义类型转换器

热门文章

  1. 通过抓包看quic定义的包结构
  2. Android tv树莓派遥控器,用红外遥控器遥控树莓派(XBMC)
  3. jstree 使用简介
  4. HBCK2修复RIT实践笔记
  5. resnet 卷积核大小_resnet50卷积神经网络cnn在covid 19射线照相上的图像分类
  6. 消化性溃疡(胃、十二指肠溃疡)
  7. 我在北京,我不在北京
  8. 无线蓝牙耳机哪个品牌音质最好?2023音质蓝牙耳机排行
  9. 照明基础知识(三)——荧光灯(气体放电光源)发展史工作原理
  10. 【Unity Shader实例】 水体WaterEffect(一) 设计