WIFI Direct Study

1、注册P2P广播
通过监听广播的方式来了解系统中Wi-Fi P2P相关的信息及变化情况。下面这几个广播属于P2P特有的,其作用如下:

     * WIFI_P2P_STATE_CHANGED_ACTION:用于通知系统中P2P功能的启用情况,如该功能是enable还是disable。
     * WIFI_P2P_PEERS_CHANGED_ACTION:系统内部将保存搜索到的其他P2P设备信息,如果这些信息有变化,则系统将发送该广播。接收者需要通过WifiP2PManager的requestPeers函数重新获取这些P2P设备的信息。
     * WIFI_P2P_CONNECTION_CHANGED_ACTION:用于通知P2P连接情况,该广播可携带WifiP2pInfo和NetworkInfo两个对象。相关信息可从这两个对象中获取。
     * WIFI_P2P_THIS_DEVICE_CHANGED_ACTION:用于通知本机P2P设备信息发生了变化。
     * WIFI_P2P_DISCOVERY_CHANGED_ACTION:用于通知P2P Device Discovery的工作状态,如启动或停止。
     * WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION:用于通知persistent group信息发生了变化。

2、启动peers
mWifiP2pManager.discoverPeers(mWifiP2pChannel, mP2pActionListenerAdapter);
这里会启用发现附近可用设备,如果发现可用连接,会收到广播WIFI_P2P_PEERS_CHANGED_ACTION,而我们代码里并没有在收到广播后去请求requestPeers,因为我们是sink端,这里discoverPeers的目的只是为了让手机能发现头盔。
3、请求连接
发现之后的选择连接对象,建立连接都在手机端
用户选择连接对象之后,头盔上收到底层发来的消息CONFIRMBTN_DIALOG_P2P_CREATE
显示链接对话框
4、允许连接
在头盔端点击允许之后,调用脚本方法:

public void onConfirmAllowClick(
    {
        //send sign
        if(_ajoActivity != null)
        {
            int ret = _ajoActivity.Call("onUnityToAndroid", 
dialogManager.CONFIRMBTN_DIALOG_UTY_RESULT, 1, null);
        }
        mainMenuCtrl.onConfirmAllowClick();
    }

调用android端code,
CONFIRMBTN_DIALOG_UTY_RESULT
android再发消息
mWifiP2pAsyncChannel.sendMessage(CONFIRMBTN_DIALOG_APP_RESULT,param1);
WifiP2pServiceImpl.java中
/frameworks/opt/net/wifi/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java

case CONFIRMBTN_DIALOG_APP_RESULT:
                   if (message.arg1 == 1) {
                       sendMessage(PEER_CONNECTION_USER_ACCEPT);
                   } else {
                       sendMessage(PEER_CONNECTION_USER_REJECT);
                   }

收到消息后发送PEER_CONNECTION_USER_ACCEPT

case PEER_CONNECTION_USER_ACCEPT:
                    mWifiNative.p2pStopFind();//停止find
                    if (!reinvokePersistentGroup(mSavedPeerConfig)) {
                        // Do negotiation when persistence fails
                        p2pConnectWithPinDisplay(mSavedPeerConfig);
                    }
                    mPeers.updateStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED);//更新状态
                    sendPeersChangedBroadcast();发送广播
                    transitionTo(mGroupNegotiationState);
                   break;
 case PEER_CONNECTION_USER_REJECT:
                    if (DBG) logd("User rejected invitation " + mSavedPeerConfig);
                    transitionTo(mInactiveState);
                    break;
 default:
                    return NOT_HANDLED;

收到WIFI_P2P_CONNECTION_CHANGED_ACTION广播:

mMiracast.invokeSink()-->
Miracast.java-->
mWifiP2pManager.requestGroupInfo-->
public void onGroupInfoAvailable(-->
invokeSink2nd-->
mWifiP2pManager.requestConnectionInfo(-->
public void onConnectionInfoAvailable-->
delayedInvokeSinkThread-->
invokeSinkThread-->
new AvoidANRThread(-->
nativeMiracastSink3DUIBC(ip, port, layerstack, uibcSend3d)

连接成功。

layerstack
layerstack来自:
MainActivity.onCreate-->mDisplayStackId = mSurfaceControl.initDisplay();

initDisplay中:

public int initDisplay()
    {
        // TODO : virtual display related section
        mDisplayManager = (DisplayManager) mActivity.getSystemService(DISPLAY_SERVICE);
        mDisplayManager.registerDisplayListener((MainActivity)mActivity, null);
        mWindowManager = (WindowManager) mActivity.getSystemService(WINDOW_SERVICE);
      mWindowManager.getDefaultDisplay().getRealSize(mRealDisplaySize);
  mWindowManager.getDefaultDisplay().getMetrics(mDefaultDisplayMetrics);
        mDensityDpi = mDefaultDisplayMetrics.densityDpi;
        mWidth = Constants.INT_720P_WIDTH;
        mHeight = Constants.INT_720P_HEIGHT;
        Log.i(TAG, "mDensityDpi= "+mDensityDpi);
        //创建VirtualDisplay
        mVirtualDisplay = mDisplayManager.createVirtualDisplay(
                DISPLAY_NAME,
                mWidth,
                mHeight,
                mDensityDpi,
                null,                DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY | 1 << 5,
                null,
                null);
        // TODO : hard code set source to 720p.
        // TODO : consider to use THREAD_PRIORITY_URGENT_DISPLAY to pull high the priority.
        mImageThread = new HandlerThread(IMAGETHREAD_NAME);
        mImageThread.start();
        mImageHandler = new Handler(mImageThread.getLooper());
        mImageListener.setBitmapListener(mBitmapListener);
        mImageListener.rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
        //创建ImageReader
        mImageReader = ImageReader.newInstance(
                Constants.INT_720P_WIDTH,
                Constants.INT_720P_HEIGHT,
                PixelFormat.RGBA_8888, 2);
         //设置图像改变监听
        mImageReader.setOnImageAvailableListener(mImageListener, mImageHandler);
        //获得ImageSurface
        mImageSurface = mImageReader.getSurface();
        // TODO : assign mImageSurface to MiraCast renderer.
        //把ImageSurface设置给VirtualDisplay
        if (mVirtualDisplay != null) {
            mVirtualDisplay.setSurface(mImageSurface);
        }
        return mVirtualDisplay.getDisplay().getDisplayId();
    }

ImageReader,使应用能够以图片数据的形式读取绘制到Surface中的内容。
然后图像发生改变时,会回调mImageListener,把图形变化传递给unity端进行显示。也就是显示手机界面。

至于为什么头盔上创建的虚拟显示能拿到手机端的图形显示,猜测应该是连接成功的最后一步nativeMiracastSink3DUIBC(ip, port, layerstack, uibcSend3d)
native方法中进行的关联吧。

你可能感兴趣的:(unity,WIFI,Direct)