欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

WIFI Direct Study

程序员文章站 2022-07-01 20:32:16
...

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<int>("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