/** * Updates the UI with device data [AR] Called when a peer device is clicked in the [AR] list * view, makes a menu appear with a connect/disconnect [AR] button for that peer * * @param device the device to be displayed */ public void showDetails(WifiP2pDevice device) { this.device = device; this.getView().setVisibility(View.VISIBLE); TextView view = (TextView) mContentView.findViewById(R.id.device_address); view.setText(device.deviceAddress); view = (TextView) mContentView.findViewById(R.id.device_info); view.setText(device.toString()); }
private void updateDesiredDevice(WifiP2pDevice device) { // Handle the case where the device to which we are connecting or connected // may have been renamed or reported different properties in the latest scan. final String address = device.deviceAddress; if (mDesiredDevice != null && mDesiredDevice.deviceAddress.equals(address)) { if (DEBUG) { Slog.d(TAG, "updateDesiredDevice: new information " + describeWifiP2pDevice(device)); } mDesiredDevice.update(device); if (mAdvertisedDisplay != null && mAdvertisedDisplay.getDeviceAddress().equals(address)) { readvertiseDisplay(createWifiDisplay(mDesiredDevice)); } } }
/** * This function is called repeatedly after each asynchronous operation until all preconditions * for the connection have been satisfied and the connection is established (or not). */ private void updateConnection() { // Step 0. Stop scans if necessary to prevent interference while connected. // Resume scans later when no longer attempting to connect. updateScanState(); // Step 1. Before we try to connect to a new device, tell the system we // have disconnected from the old one. if ((mRemoteDisplay != null || mExtRemoteDisplay != null) && mConnectedDevice != mDesiredDevice) { Slog.i( TAG, "Stopped listening for RTSP connection on " + mRemoteDisplayInterface + " from Wifi display: " + mConnectedDevice.deviceName); if (mRemoteDisplay != null) { mRemoteDisplay.dispose(); } else if (mExtRemoteDisplay != null) { ExtendedRemoteDisplayHelper.dispose(mExtRemoteDisplay); } mExtRemoteDisplay = null; mRemoteDisplay = null; mRemoteDisplayInterface = null; mRemoteDisplayConnected = false; mHandler.removeCallbacks(mRtspTimeout); mWifiP2pManager.setMiracastMode(WifiP2pManager.MIRACAST_DISABLED); unadvertiseDisplay(); // continue to next step } // Step 2. Before we try to connect to a new device, disconnect from the old one. if (mDisconnectingDevice != null) { return; // wait for asynchronous callback } if (mConnectedDevice != null && mConnectedDevice != mDesiredDevice) { Slog.i(TAG, "Disconnecting from Wifi display: " + mConnectedDevice.deviceName); mDisconnectingDevice = mConnectedDevice; mConnectedDevice = null; mConnectedDeviceGroupInfo = null; unadvertiseDisplay(); final WifiP2pDevice oldDevice = mDisconnectingDevice; mWifiP2pManager.removeGroup( mWifiP2pChannel, new ActionListener() { @Override public void onSuccess() { Slog.i(TAG, "Disconnected from Wifi display: " + oldDevice.deviceName); next(); } @Override public void onFailure(int reason) { Slog.i( TAG, "Failed to disconnect from Wifi display: " + oldDevice.deviceName + ", reason=" + reason); next(); } private void next() { if (mDisconnectingDevice == oldDevice) { mDisconnectingDevice = null; updateConnection(); } } }); return; // wait for asynchronous callback } // Step 3. Before we try to connect to a new device, stop trying to connect // to the old one. if (mCancelingDevice != null) { return; // wait for asynchronous callback } if (mConnectingDevice != null && mConnectingDevice != mDesiredDevice) { Slog.i(TAG, "Canceling connection to Wifi display: " + mConnectingDevice.deviceName); mCancelingDevice = mConnectingDevice; mConnectingDevice = null; unadvertiseDisplay(); mHandler.removeCallbacks(mConnectionTimeout); final WifiP2pDevice oldDevice = mCancelingDevice; mWifiP2pManager.cancelConnect( mWifiP2pChannel, new ActionListener() { @Override public void onSuccess() { Slog.i(TAG, "Canceled connection to Wifi display: " + oldDevice.deviceName); next(); } @Override public void onFailure(int reason) { Slog.i( TAG, "Failed to cancel connection to Wifi display: " + oldDevice.deviceName + ", reason=" + reason); next(); } private void next() { if (mCancelingDevice == oldDevice) { mCancelingDevice = null; updateConnection(); } } }); return; // wait for asynchronous callback } // Step 4. If we wanted to disconnect, or we're updating after starting an // autonomous GO, then mission accomplished. if (mDesiredDevice == null) { if (mWifiDisplayCertMode) { mListener.onDisplaySessionInfo(getSessionInfo(mConnectedDeviceGroupInfo, 0)); } unadvertiseDisplay(); return; // done } // Step 5. Try to connect. if (mConnectedDevice == null && mConnectingDevice == null) { Slog.i(TAG, "Connecting to Wifi display: " + mDesiredDevice.deviceName); mConnectingDevice = mDesiredDevice; WifiP2pConfig config = new WifiP2pConfig(); WpsInfo wps = new WpsInfo(); if (mWifiDisplayWpsConfig != WpsInfo.INVALID) { wps.setup = mWifiDisplayWpsConfig; } else if (mConnectingDevice.wpsPbcSupported()) { wps.setup = WpsInfo.PBC; } else if (mConnectingDevice.wpsDisplaySupported()) { // We do keypad if peer does display wps.setup = WpsInfo.KEYPAD; } else { wps.setup = WpsInfo.DISPLAY; } config.wps = wps; config.deviceAddress = mConnectingDevice.deviceAddress; // Helps with STA & P2P concurrency config.groupOwnerIntent = WifiP2pConfig.MIN_GROUP_OWNER_INTENT; WifiDisplay display = createWifiDisplay(mConnectingDevice); advertiseDisplay(display, null, 0, 0, 0); final WifiP2pDevice newDevice = mDesiredDevice; mWifiP2pManager.connect( mWifiP2pChannel, config, new ActionListener() { @Override public void onSuccess() { // The connection may not yet be established. We still need to wait // for WIFI_P2P_CONNECTION_CHANGED_ACTION. However, we might never // get that broadcast, so we register a timeout. Slog.i(TAG, "Initiated connection to Wifi display: " + newDevice.deviceName); mHandler.postDelayed(mConnectionTimeout, CONNECTION_TIMEOUT_SECONDS * 1000); } @Override public void onFailure(int reason) { if (mConnectingDevice == newDevice) { Slog.i( TAG, "Failed to initiate connection to Wifi display: " + newDevice.deviceName + ", reason=" + reason); mConnectingDevice = null; handleConnectionFailure(false); } } }); return; // wait for asynchronous callback } // Step 6. Listen for incoming RTSP connection. if (mConnectedDevice != null && mRemoteDisplay == null && mExtRemoteDisplay == null) { Inet4Address addr = getInterfaceAddress(mConnectedDeviceGroupInfo); if (addr == null) { Slog.i( TAG, "Failed to get local interface address for communicating " + "with Wifi display: " + mConnectedDevice.deviceName); handleConnectionFailure(false); return; // done } mWifiP2pManager.setMiracastMode(WifiP2pManager.MIRACAST_SOURCE); final WifiP2pDevice oldDevice = mConnectedDevice; final int port = getPortNumber(mConnectedDevice); final String iface = addr.getHostAddress() + ":" + port; mRemoteDisplayInterface = iface; Slog.i( TAG, "Listening for RTSP connection on " + iface + " from Wifi display: " + mConnectedDevice.deviceName); RemoteDisplay.Listener listener = new RemoteDisplay.Listener() { @Override public void onDisplayConnected( Surface surface, int width, int height, int flags, int session) { if (mConnectedDevice == oldDevice && !mRemoteDisplayConnected) { Slog.i( TAG, "Opened RTSP connection with Wifi display: " + mConnectedDevice.deviceName); mRemoteDisplayConnected = true; mHandler.removeCallbacks(mRtspTimeout); if (mWifiDisplayCertMode) { mListener.onDisplaySessionInfo( getSessionInfo(mConnectedDeviceGroupInfo, session)); } final WifiDisplay display = createWifiDisplay(mConnectedDevice); advertiseDisplay(display, surface, width, height, flags); } } @Override public void onDisplayDisconnected() { if (mConnectedDevice == oldDevice) { Slog.i( TAG, "Closed RTSP connection with Wifi display: " + mConnectedDevice.deviceName); mHandler.removeCallbacks(mRtspTimeout); disconnect(); } } @Override public void onDisplayError(int error) { if (mConnectedDevice == oldDevice) { Slog.i( TAG, "Lost RTSP connection with Wifi display due to error " + error + ": " + mConnectedDevice.deviceName); mHandler.removeCallbacks(mRtspTimeout); handleConnectionFailure(false); } } }; if (ExtendedRemoteDisplayHelper.isAvailable()) { mExtRemoteDisplay = ExtendedRemoteDisplayHelper.listen(iface, listener, mHandler, mContext); } else { mRemoteDisplay = RemoteDisplay.listen(iface, listener, mHandler, mContext.getOpPackageName()); } // Use extended timeout value for certification, as some tests require user inputs int rtspTimeout = mWifiDisplayCertMode ? RTSP_TIMEOUT_SECONDS_CERT_MODE : RTSP_TIMEOUT_SECONDS; mHandler.postDelayed(mRtspTimeout, rtspTimeout * 1000); } }
private static String describeWifiP2pDevice(WifiP2pDevice device) { return device != null ? device.toString().replace('\n', ',') : "null"; }