关于WifiDIsplay的JAVA层的代码在“packages/apps/Settings/src/com/android/settings/wfd/WifiDisplaySettings.java”文件中。(因为在实际应用中选择WifiDisplay的选项在设置中嘛)
扫描的开始在“packages/apps/Settings/src/com/android/settings/wfd/WifiDisplaySettings.java”的“onResume()”函数中。
1.1、首先调用mDisplayManager.scanWifiDisplays(); 函数开始WifiDisplay的扫描。
--------------------------------------------------------------------------------------------mDisplayManager------------------------------------
----------------------------------------------------------------
这里的mDisplayManager对象是JAVA层的DisplayManager对象,在onCreate函数中创建。(关于这些onCreate和onResume的知识可以看一下activity的生命周期)
---------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------
这里具体看scanWifiDisplays();的实现,该函数的实现在文件“frameworks/base/core/java/android/hardware/display/DisplayManager.java”。这里直接调用了DisplayManagerGlobal类型的mGlobal对象的scanWifiDisplays函数,下面看在DisplayManagerGlobal中scanWifiDisplays函数的实现。
1.2、frameworks/base/core/java/android/hardware/display/DisplayManagerGlobal.java文件中的scanWifiDisplays直接调用了IDisplayManager类型的mDm对象的scanWifiDisplays函数。
一看mDm的类型为IDisplayManager,那么自然而然就会想到这里肯定是用到了android的binder机制。这里的mDm只是远程服务对象的代理机构,其具体的实现肯定在另一端。通过查看代码,果然DisplayManagerService类继承了IDisplayManager.Stub对象。那么之后的追踪肯定就在DisplayManagerService类中进行了。
在继续分析之前,先理一下之前涉及到的对象的关系。
1.3、下面从“DisplayManagerService”开始往下分析,该对象在“frameworks/base/services/java/com/android/server/display/DisplayManagerService.java”文件中。
可以看到这里直接调用了WifiDisplayAdapter类型的对象mWifiDisplayAdapter的requestScanLocked函数。
说明一下mWifiDisplayAdapter的作用。首先必须明确的是在系统中的显示设备肯定不只WifiDisplay一种,那么这里的DisplayManagerService肯定要进行对多个显示设备的管理,这样就有引入Adapter的必要了,让每一种Adapter对应一种显示设备而在具体的某种类型的Adapter中实现针对该显示设备的具体功能,这样就可以减轻DisplayManagerService的负担了。
1.4、进入WifiDisplayAdapter对象中进行具体的分析。该函数在“frameworks/base/services/java/com/android/server/display/WifiDisplayAdapter.java”
这里用到了android中很重要的消息机制。这里首先调用getHandler()函数得到WifiDisplayHandler对象,然后通过该对象往消息队列中加入一个运行对象,那么接下来要执行的肯定就是mDisplayController.requestScan()。
1.5、进入WifiDisplayController进行分析。WifiDisplayController的主要作用在于代表WifiDisplayAdapter对象完成与WifiP2pManager的异步交互。
继续看discoverPeers(),这里首先看是否已经在进行发现对等点了(即mDiscoverPeersInProgress是否置位),如果mDiscoverPeersInProgress已经置位则什么也不做,如果mDiscoverPeersInProgress没有置位则说明现在没有进行设备的发现,调用tryDiscoverPeers()进行设备的发现过程。
1.6、接着看tryDiscoverPeers()的执行。该函数中直接调用mWifiP2pManager的discoverPeers函数进行设备的发现,可以看到在该函数的调用中传入了一个
Channel类型的mWifiP2pChannel对象(该函数是在WifiDisplayController的构造函数中通过调用mWifiP2pManager.initialize(context, handler.getLooper(), null)函数得到的)和一个回调监听对象(该函数用于处理在 mWifiP2pManager调用discoverPeers()函数成功或失败后的后续处理)。
1.6.1、进入mWifiP2pManager中分析discoverPeers函数的执行。这里首先对之前创建的channel进行检查,然后通过该channnel对象c发送进行设备发现的消息,因为发送的是异步消息,所以发送完消息之后该函数会立即返回。
1.6.2、下面看发送消息,并且发现peers成功之后的处理。即看在onSuccess函数中requestPeers()函数所完成的功能。
这里所完成的功能是在之前discoverPeers请求peers的基础上进行发现peers的操作。其还是调用了mWifiP2pManager的requestPeers函数,其所完成的功能还是发送异步消息,不在细看,这里主要看请求Peers成功之后的调用。
即看onPeersAvailable(WifiP2pDeviceLIst peers)函数的实现,这里主要的任务就是在for 循环中将找到的所有支持p2p的设备加入到ArrayList<WifiP2pDevice>类型的mAvailableWifiDisplayPeers对象中。
搜索到的p2p显示设备都添加到mAvailableWifiDisplayPeers对象中之后就会调用handleScanFinished()函数,看一下在该函数中主要完成了什么工作。
可以看到在该函数中首先为搜索到的所有p2p设备创建了WifiDisplay类型的对象实例,并放入displays数组中,然后以该数组为参数,向函数调用的上层回调,也即向上层通知扫描到的显示设备。这样上层就有了可用p2p设备的全部信息,之后就可以通过这些信息来进行连接等进一步的操作了。
至此从设置中wifiDisplay项的创建开始WiifDisplay设备的扫描调用开始,到完成设备的扫描将扫描到的设备信息返回给上层的所有流程都介绍完。分析的难点在于对android的binder机制、消息机制等基础机制的理解。
值得指出的是这里的分析都只停留在java层的分析,没有涉及到C++层的分析。