1cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown/* 2cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Copyright (C) 2012 The Android Open Source Project 3cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * 4cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 5cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * you may not use this file except in compliance with the License. 6cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * You may obtain a copy of the License at 7cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * 8cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * http://www.apache.org/licenses/LICENSE-2.0 9cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * 10cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Unless required by applicable law or agreed to in writing, software 11cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 12cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * See the License for the specific language governing permissions and 14cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * limitations under the License. 15cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown */ 16cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 17cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownpackage com.android.server.display; 18cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 19cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport com.android.internal.util.DumpUtils; 20cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 21cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.content.BroadcastReceiver; 2289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownimport android.content.ContentResolver; 23cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.content.Context; 24cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.content.Intent; 25cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.content.IntentFilter; 2689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownimport android.database.ContentObserver; 27e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brownimport android.hardware.display.WifiDisplay; 281f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhangimport android.hardware.display.WifiDisplaySessionInfo; 2989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownimport android.hardware.display.WifiDisplayStatus; 30f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brownimport android.media.RemoteDisplay; 31cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.net.NetworkInfo; 3289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownimport android.net.Uri; 336681be27875a50bd0c74826cb5d8defec72b8d58Irfan Sheriffimport android.net.wifi.WpsInfo; 34cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.net.wifi.p2p.WifiP2pConfig; 35cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.net.wifi.p2p.WifiP2pDevice; 36cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.net.wifi.p2p.WifiP2pDeviceList; 37cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.net.wifi.p2p.WifiP2pGroup; 38cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.net.wifi.p2p.WifiP2pManager; 39cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.net.wifi.p2p.WifiP2pWfdInfo; 40cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.net.wifi.p2p.WifiP2pManager.ActionListener; 41cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.net.wifi.p2p.WifiP2pManager.Channel; 42cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.net.wifi.p2p.WifiP2pManager.GroupInfoListener; 43cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.net.wifi.p2p.WifiP2pManager.PeerListListener; 44cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.os.Handler; 4589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownimport android.provider.Settings; 46cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.util.Slog; 47f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brownimport android.view.Surface; 48cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 49cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport java.io.PrintWriter; 50cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport java.net.Inet4Address; 51cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport java.net.InetAddress; 52cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport java.net.NetworkInterface; 53cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport java.net.SocketException; 54cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport java.util.ArrayList; 55cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport java.util.Enumeration; 56607223f3b7a1c4dc3ac995f742f8d2da50d85ffcNarayan Kamathimport java.util.Objects; 57c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown 58cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown/** 59cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Manages all of the various asynchronous interactions with the {@link WifiP2pManager} 60cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * on behalf of {@link WifiDisplayAdapter}. 61cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * <p> 62cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * This code is isolated from {@link WifiDisplayAdapter} so that we can avoid 63cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * accidentally introducing any deadlocks due to the display manager calling 64cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * outside of itself while holding its lock. It's also way easier to write this 65cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * asynchronous code if we can assume that it is single-threaded. 66cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * </p><p> 67cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * The controller must be instantiated on the handler thread. 68cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * </p> 69cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown */ 70cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownfinal class WifiDisplayController implements DumpUtils.Dump { 71cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private static final String TAG = "WifiDisplayController"; 72c5df37c285221d0fb113f55b9e78b35632241d3fJeff Brown private static final boolean DEBUG = false; 73cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 74cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private static final int DEFAULT_CONTROL_PORT = 7236; 75cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private static final int MAX_THROUGHPUT = 50; 76ce468a35b388ca46578934706b38dbae94941643Jeff Brown private static final int CONNECTION_TIMEOUT_SECONDS = 30; 77e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown private static final int RTSP_TIMEOUT_SECONDS = 30; 781f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang private static final int RTSP_TIMEOUT_SECONDS_CERT_MODE = 120; 79cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 80ce468a35b388ca46578934706b38dbae94941643Jeff Brown // We repeatedly issue calls to discover peers every so often for a few reasons. 81ce468a35b388ca46578934706b38dbae94941643Jeff Brown // 1. The initial request may fail and need to retried. 82ce468a35b388ca46578934706b38dbae94941643Jeff Brown // 2. Discovery will self-abort after any group is initiated, which may not necessarily 83ce468a35b388ca46578934706b38dbae94941643Jeff Brown // be what we want to have happen. 84ce468a35b388ca46578934706b38dbae94941643Jeff Brown // 3. Discovery will self-timeout after 2 minutes, whereas we want discovery to 85ce468a35b388ca46578934706b38dbae94941643Jeff Brown // be occur for as long as a client is requesting it be. 86ce468a35b388ca46578934706b38dbae94941643Jeff Brown // 4. We don't seem to get updated results for displays we've already found until 87ce468a35b388ca46578934706b38dbae94941643Jeff Brown // we ask to discover again, particularly for the isSessionAvailable() property. 88ce468a35b388ca46578934706b38dbae94941643Jeff Brown private static final int DISCOVER_PEERS_INTERVAL_MILLIS = 10000; 890cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown 900cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown private static final int CONNECT_MAX_RETRIES = 3; 910cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown private static final int CONNECT_RETRY_DELAY_MILLIS = 500; 920cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown 93cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final Context mContext; 94cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final Handler mHandler; 95cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final Listener mListener; 9688469e56c8294a928e65398352e8444d66bdb75aJeff Brown 97cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final WifiP2pManager mWifiP2pManager; 98cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final Channel mWifiP2pChannel; 99cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 100cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private boolean mWifiP2pEnabled; 101cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private boolean mWfdEnabled; 102cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private boolean mWfdEnabling; 103cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private NetworkInfo mNetworkInfo; 104cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 10589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private final ArrayList<WifiP2pDevice> mAvailableWifiDisplayPeers = 106cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown new ArrayList<WifiP2pDevice>(); 107cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 10889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown // True if Wifi display is enabled by the user. 10989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private boolean mWifiDisplayOnSetting; 11089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 111ce468a35b388ca46578934706b38dbae94941643Jeff Brown // True if a scan was requested independent of whether one is actually in progress. 112ce468a35b388ca46578934706b38dbae94941643Jeff Brown private boolean mScanRequested; 113ce468a35b388ca46578934706b38dbae94941643Jeff Brown 1140cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown // True if there is a call to discoverPeers in progress. 1150cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown private boolean mDiscoverPeersInProgress; 1160cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown 117cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // The device to which we want to connect, or null if we want to be disconnected. 118cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private WifiP2pDevice mDesiredDevice; 119cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 120cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // The device to which we are currently connecting, or null if we have already connected 121cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // or are not trying to connect. 122cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private WifiP2pDevice mConnectingDevice; 123cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 12474da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown // The device from which we are currently disconnecting. 12574da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown private WifiP2pDevice mDisconnectingDevice; 12674da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown 12774da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown // The device to which we were previously trying to connect and are now canceling. 12874da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown private WifiP2pDevice mCancelingDevice; 12974da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown 130cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // The device to which we are currently connected, which means we have an active P2P group. 131cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private WifiP2pDevice mConnectedDevice; 132cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 133cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // The group info obtained after connecting. 134cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private WifiP2pGroup mConnectedDeviceGroupInfo; 135cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 1360cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown // Number of connection retries remaining. 1370cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown private int mConnectionRetriesLeft; 1380cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown 139f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown // The remote display that is listening on the connection. 140f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown // Created after the Wifi P2P network is connected. 141f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown private RemoteDisplay mRemoteDisplay; 142f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 143f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown // The remote display interface. 144f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown private String mRemoteDisplayInterface; 145f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 146f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown // True if RTSP has connected. 147f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown private boolean mRemoteDisplayConnected; 148f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 149c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown // The information we have most recently told WifiDisplayAdapter about. 150c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown private WifiDisplay mAdvertisedDisplay; 151c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown private Surface mAdvertisedDisplaySurface; 152c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown private int mAdvertisedDisplayWidth; 153c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown private int mAdvertisedDisplayHeight; 154c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown private int mAdvertisedDisplayFlags; 155c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown 1561f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang // Certification 1571f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang private boolean mWifiDisplayCertMode; 158e38af818b10e1a4927cc3fd69d19c9125d579321Chong Zhang private int mWifiDisplayWpsConfig = WpsInfo.INVALID; 159e38af818b10e1a4927cc3fd69d19c9125d579321Chong Zhang 1601f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang private WifiP2pDevice mThisDevice; 1611f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang 162cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public WifiDisplayController(Context context, Handler handler, Listener listener) { 163cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mContext = context; 164cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mHandler = handler; 165cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mListener = listener; 166cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 167cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mWifiP2pManager = (WifiP2pManager)context.getSystemService(Context.WIFI_P2P_SERVICE); 168cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mWifiP2pChannel = mWifiP2pManager.initialize(context, handler.getLooper(), null); 169cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 170cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown IntentFilter intentFilter = new IntentFilter(); 171cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION); 172cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION); 173cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); 1741f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang intentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION); 17589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown context.registerReceiver(mWifiP2pReceiver, intentFilter, null, mHandler); 17689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 17789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown ContentObserver settingsObserver = new ContentObserver(mHandler) { 17889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown @Override 17989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void onChange(boolean selfChange, Uri uri) { 18089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateSettings(); 18189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 18289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown }; 18389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 18489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown final ContentResolver resolver = mContext.getContentResolver(); 18589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown resolver.registerContentObserver(Settings.Global.getUriFor( 18689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown Settings.Global.WIFI_DISPLAY_ON), false, settingsObserver); 1871f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang resolver.registerContentObserver(Settings.Global.getUriFor( 1881f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang Settings.Global.WIFI_DISPLAY_CERTIFICATION_ON), false, settingsObserver); 189e38af818b10e1a4927cc3fd69d19c9125d579321Chong Zhang resolver.registerContentObserver(Settings.Global.getUriFor( 190e38af818b10e1a4927cc3fd69d19c9125d579321Chong Zhang Settings.Global.WIFI_DISPLAY_WPS_CONFIG), false, settingsObserver); 19189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateSettings(); 19289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 19389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 19489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private void updateSettings() { 19589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown final ContentResolver resolver = mContext.getContentResolver(); 19689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mWifiDisplayOnSetting = Settings.Global.getInt(resolver, 19789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown Settings.Global.WIFI_DISPLAY_ON, 0) != 0; 1981f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang mWifiDisplayCertMode = Settings.Global.getInt(resolver, 1991f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang Settings.Global.WIFI_DISPLAY_CERTIFICATION_ON, 0) != 0; 20089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 201e38af818b10e1a4927cc3fd69d19c9125d579321Chong Zhang mWifiDisplayWpsConfig = WpsInfo.INVALID; 202e38af818b10e1a4927cc3fd69d19c9125d579321Chong Zhang if (mWifiDisplayCertMode) { 203e38af818b10e1a4927cc3fd69d19c9125d579321Chong Zhang mWifiDisplayWpsConfig = Settings.Global.getInt(resolver, 204e38af818b10e1a4927cc3fd69d19c9125d579321Chong Zhang Settings.Global.WIFI_DISPLAY_WPS_CONFIG, WpsInfo.INVALID); 205e38af818b10e1a4927cc3fd69d19c9125d579321Chong Zhang } 206e38af818b10e1a4927cc3fd69d19c9125d579321Chong Zhang 20789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateWfdEnableState(); 208cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 209cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 21074da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown @Override 211ae6688b09649447e57468b3e7935691bc09ec9b9Dianne Hackborn public void dump(PrintWriter pw, String prefix) { 21289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown pw.println("mWifiDisplayOnSetting=" + mWifiDisplayOnSetting); 213cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mWifiP2pEnabled=" + mWifiP2pEnabled); 214cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mWfdEnabled=" + mWfdEnabled); 215cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mWfdEnabling=" + mWfdEnabling); 216cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mNetworkInfo=" + mNetworkInfo); 217ce468a35b388ca46578934706b38dbae94941643Jeff Brown pw.println("mScanRequested=" + mScanRequested); 2180cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown pw.println("mDiscoverPeersInProgress=" + mDiscoverPeersInProgress); 219cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mDesiredDevice=" + describeWifiP2pDevice(mDesiredDevice)); 220cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mConnectingDisplay=" + describeWifiP2pDevice(mConnectingDevice)); 22174da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown pw.println("mDisconnectingDisplay=" + describeWifiP2pDevice(mDisconnectingDevice)); 22274da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown pw.println("mCancelingDisplay=" + describeWifiP2pDevice(mCancelingDevice)); 223cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mConnectedDevice=" + describeWifiP2pDevice(mConnectedDevice)); 2240cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown pw.println("mConnectionRetriesLeft=" + mConnectionRetriesLeft); 225f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown pw.println("mRemoteDisplay=" + mRemoteDisplay); 226f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown pw.println("mRemoteDisplayInterface=" + mRemoteDisplayInterface); 227f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown pw.println("mRemoteDisplayConnected=" + mRemoteDisplayConnected); 228c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown pw.println("mAdvertisedDisplay=" + mAdvertisedDisplay); 229c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown pw.println("mAdvertisedDisplaySurface=" + mAdvertisedDisplaySurface); 230c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown pw.println("mAdvertisedDisplayWidth=" + mAdvertisedDisplayWidth); 231c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown pw.println("mAdvertisedDisplayHeight=" + mAdvertisedDisplayHeight); 232c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown pw.println("mAdvertisedDisplayFlags=" + mAdvertisedDisplayFlags); 233cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 23489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown pw.println("mAvailableWifiDisplayPeers: size=" + mAvailableWifiDisplayPeers.size()); 23589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown for (WifiP2pDevice device : mAvailableWifiDisplayPeers) { 236cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println(" " + describeWifiP2pDevice(device)); 237cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 238cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 239cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 240ce468a35b388ca46578934706b38dbae94941643Jeff Brown public void requestStartScan() { 241ce468a35b388ca46578934706b38dbae94941643Jeff Brown if (!mScanRequested) { 242ce468a35b388ca46578934706b38dbae94941643Jeff Brown mScanRequested = true; 243ce468a35b388ca46578934706b38dbae94941643Jeff Brown updateScanState(); 244ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 245ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 246ce468a35b388ca46578934706b38dbae94941643Jeff Brown 247ce468a35b388ca46578934706b38dbae94941643Jeff Brown public void requestStopScan() { 248ce468a35b388ca46578934706b38dbae94941643Jeff Brown if (mScanRequested) { 249ce468a35b388ca46578934706b38dbae94941643Jeff Brown mScanRequested = false; 250ce468a35b388ca46578934706b38dbae94941643Jeff Brown updateScanState(); 251ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 252e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 253e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 254e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void requestConnect(String address) { 25589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown for (WifiP2pDevice device : mAvailableWifiDisplayPeers) { 256e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (device.deviceAddress.equals(address)) { 257e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown connect(device); 258e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 259e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 260e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 261e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 2621f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang public void requestPause() { 2631f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang if (mRemoteDisplay != null) { 2641f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang mRemoteDisplay.pause(); 2651f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 2661f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 2671f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang 2681f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang public void requestResume() { 2691f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang if (mRemoteDisplay != null) { 2701f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang mRemoteDisplay.resume(); 2711f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 2721f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 2731f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang 274e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void requestDisconnect() { 275e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown disconnect(); 276e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 277e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 27889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private void updateWfdEnableState() { 27989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mWifiDisplayOnSetting && mWifiP2pEnabled) { 28089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown // WFD should be enabled. 28189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (!mWfdEnabled && !mWfdEnabling) { 28289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mWfdEnabling = true; 28389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 28489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown WifiP2pWfdInfo wfdInfo = new WifiP2pWfdInfo(); 28589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown wfdInfo.setWfdEnabled(true); 28689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown wfdInfo.setDeviceType(WifiP2pWfdInfo.WFD_SOURCE); 28789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown wfdInfo.setSessionAvailable(true); 28889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown wfdInfo.setControlPort(DEFAULT_CONTROL_PORT); 28989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown wfdInfo.setMaxThroughput(MAX_THROUGHPUT); 29089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mWifiP2pManager.setWFDInfo(mWifiP2pChannel, wfdInfo, new ActionListener() { 29189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown @Override 29289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void onSuccess() { 29389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (DEBUG) { 29489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown Slog.d(TAG, "Successfully set WFD info."); 29589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 29689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mWfdEnabling) { 29789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mWfdEnabling = false; 29889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mWfdEnabled = true; 29989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown reportFeatureState(); 300ce468a35b388ca46578934706b38dbae94941643Jeff Brown updateScanState(); 30189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 302cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 303cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 30489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown @Override 30589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void onFailure(int reason) { 30689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (DEBUG) { 30789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown Slog.d(TAG, "Failed to set WFD info with reason " + reason + "."); 30889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 30989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mWfdEnabling = false; 310cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 31189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown }); 31289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 31389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } else { 31489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown // WFD should be disabled. 31572193e1f329ec91bfd86f977035caecb00914444Chong Zhang if (mWfdEnabled || mWfdEnabling) { 31672193e1f329ec91bfd86f977035caecb00914444Chong Zhang WifiP2pWfdInfo wfdInfo = new WifiP2pWfdInfo(); 31772193e1f329ec91bfd86f977035caecb00914444Chong Zhang wfdInfo.setWfdEnabled(false); 31872193e1f329ec91bfd86f977035caecb00914444Chong Zhang mWifiP2pManager.setWFDInfo(mWifiP2pChannel, wfdInfo, new ActionListener() { 31972193e1f329ec91bfd86f977035caecb00914444Chong Zhang @Override 32072193e1f329ec91bfd86f977035caecb00914444Chong Zhang public void onSuccess() { 32172193e1f329ec91bfd86f977035caecb00914444Chong Zhang if (DEBUG) { 32272193e1f329ec91bfd86f977035caecb00914444Chong Zhang Slog.d(TAG, "Successfully set WFD info."); 32372193e1f329ec91bfd86f977035caecb00914444Chong Zhang } 32472193e1f329ec91bfd86f977035caecb00914444Chong Zhang } 32572193e1f329ec91bfd86f977035caecb00914444Chong Zhang 32672193e1f329ec91bfd86f977035caecb00914444Chong Zhang @Override 32772193e1f329ec91bfd86f977035caecb00914444Chong Zhang public void onFailure(int reason) { 32872193e1f329ec91bfd86f977035caecb00914444Chong Zhang if (DEBUG) { 32972193e1f329ec91bfd86f977035caecb00914444Chong Zhang Slog.d(TAG, "Failed to set WFD info with reason " + reason + "."); 33072193e1f329ec91bfd86f977035caecb00914444Chong Zhang } 33172193e1f329ec91bfd86f977035caecb00914444Chong Zhang } 33272193e1f329ec91bfd86f977035caecb00914444Chong Zhang }); 33372193e1f329ec91bfd86f977035caecb00914444Chong Zhang } 33489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mWfdEnabling = false; 33589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mWfdEnabled = false; 33689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown reportFeatureState(); 337ce468a35b388ca46578934706b38dbae94941643Jeff Brown updateScanState(); 33889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown disconnect(); 339cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 340cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 341cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 34289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private void reportFeatureState() { 34389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown final int featureState = computeFeatureState(); 34489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mHandler.post(new Runnable() { 34589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown @Override 34689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void run() { 34789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mListener.onFeatureStateChanged(featureState); 34889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 34989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown }); 35089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 35189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 35289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private int computeFeatureState() { 35389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (!mWifiP2pEnabled) { 35489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown return WifiDisplayStatus.FEATURE_STATE_DISABLED; 355e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 35689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown return mWifiDisplayOnSetting ? WifiDisplayStatus.FEATURE_STATE_ON : 35789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown WifiDisplayStatus.FEATURE_STATE_OFF; 358e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 359e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 360ce468a35b388ca46578934706b38dbae94941643Jeff Brown private void updateScanState() { 361ce468a35b388ca46578934706b38dbae94941643Jeff Brown if (mScanRequested && mWfdEnabled && mDesiredDevice == null) { 362ce468a35b388ca46578934706b38dbae94941643Jeff Brown if (!mDiscoverPeersInProgress) { 363ce468a35b388ca46578934706b38dbae94941643Jeff Brown Slog.i(TAG, "Starting Wifi display scan."); 364ce468a35b388ca46578934706b38dbae94941643Jeff Brown mDiscoverPeersInProgress = true; 365ce468a35b388ca46578934706b38dbae94941643Jeff Brown handleScanStarted(); 366ce468a35b388ca46578934706b38dbae94941643Jeff Brown tryDiscoverPeers(); 367ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 368ce468a35b388ca46578934706b38dbae94941643Jeff Brown } else { 369ce468a35b388ca46578934706b38dbae94941643Jeff Brown if (mDiscoverPeersInProgress) { 370ce468a35b388ca46578934706b38dbae94941643Jeff Brown // Cancel automatic retry right away. 371ce468a35b388ca46578934706b38dbae94941643Jeff Brown mHandler.removeCallbacks(mDiscoverPeers); 372ce468a35b388ca46578934706b38dbae94941643Jeff Brown 373ce468a35b388ca46578934706b38dbae94941643Jeff Brown // Defer actually stopping discovery if we have a connection attempt in progress. 374ce468a35b388ca46578934706b38dbae94941643Jeff Brown // The wifi display connection attempt often fails if we are not in discovery 375ce468a35b388ca46578934706b38dbae94941643Jeff Brown // mode. So we allow discovery to continue until we give up trying to connect. 376ce468a35b388ca46578934706b38dbae94941643Jeff Brown if (mDesiredDevice == null || mDesiredDevice == mConnectedDevice) { 377ce468a35b388ca46578934706b38dbae94941643Jeff Brown Slog.i(TAG, "Stopping Wifi display scan."); 378ce468a35b388ca46578934706b38dbae94941643Jeff Brown mDiscoverPeersInProgress = false; 379ce468a35b388ca46578934706b38dbae94941643Jeff Brown stopPeerDiscovery(); 380ce468a35b388ca46578934706b38dbae94941643Jeff Brown handleScanFinished(); 381ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 382ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 3830cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown } 3840cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown } 3850cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown 3860cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown private void tryDiscoverPeers() { 387cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mWifiP2pManager.discoverPeers(mWifiP2pChannel, new ActionListener() { 388cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 389cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onSuccess() { 390cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (DEBUG) { 391cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.d(TAG, "Discover peers succeeded. Requesting peers now."); 392cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 393cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 394ce468a35b388ca46578934706b38dbae94941643Jeff Brown if (mDiscoverPeersInProgress) { 395ce468a35b388ca46578934706b38dbae94941643Jeff Brown requestPeers(); 396ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 397cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 398cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 399cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 400cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onFailure(int reason) { 401cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (DEBUG) { 402cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.d(TAG, "Discover peers failed with reason " + reason + "."); 403cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 4040cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown 405ce468a35b388ca46578934706b38dbae94941643Jeff Brown // Ignore the error. 406ce468a35b388ca46578934706b38dbae94941643Jeff Brown // We will retry automatically in a little bit. 407ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 408ce468a35b388ca46578934706b38dbae94941643Jeff Brown }); 409ce468a35b388ca46578934706b38dbae94941643Jeff Brown 410ce468a35b388ca46578934706b38dbae94941643Jeff Brown // Retry discover peers periodically until stopped. 411ce468a35b388ca46578934706b38dbae94941643Jeff Brown mHandler.postDelayed(mDiscoverPeers, DISCOVER_PEERS_INTERVAL_MILLIS); 412ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 413ce468a35b388ca46578934706b38dbae94941643Jeff Brown 414ce468a35b388ca46578934706b38dbae94941643Jeff Brown private void stopPeerDiscovery() { 415ce468a35b388ca46578934706b38dbae94941643Jeff Brown mWifiP2pManager.stopPeerDiscovery(mWifiP2pChannel, new ActionListener() { 416ce468a35b388ca46578934706b38dbae94941643Jeff Brown @Override 417ce468a35b388ca46578934706b38dbae94941643Jeff Brown public void onSuccess() { 418ce468a35b388ca46578934706b38dbae94941643Jeff Brown if (DEBUG) { 419ce468a35b388ca46578934706b38dbae94941643Jeff Brown Slog.d(TAG, "Stop peer discovery succeeded."); 420ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 421ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 422ce468a35b388ca46578934706b38dbae94941643Jeff Brown 423ce468a35b388ca46578934706b38dbae94941643Jeff Brown @Override 424ce468a35b388ca46578934706b38dbae94941643Jeff Brown public void onFailure(int reason) { 425ce468a35b388ca46578934706b38dbae94941643Jeff Brown if (DEBUG) { 426ce468a35b388ca46578934706b38dbae94941643Jeff Brown Slog.d(TAG, "Stop peer discovery failed with reason " + reason + "."); 4270cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown } 428cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 429cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }); 430cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 431cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 432cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void requestPeers() { 433cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mWifiP2pManager.requestPeers(mWifiP2pChannel, new PeerListListener() { 434cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 435cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onPeersAvailable(WifiP2pDeviceList peers) { 436cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (DEBUG) { 437cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.d(TAG, "Received list of peers."); 438cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 439cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 44089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mAvailableWifiDisplayPeers.clear(); 441cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown for (WifiP2pDevice device : peers.getDeviceList()) { 442cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (DEBUG) { 443cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.d(TAG, " " + describeWifiP2pDevice(device)); 444cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 445cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 446cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (isWifiDisplay(device)) { 44789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mAvailableWifiDisplayPeers.add(device); 448cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 449cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 450cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 451ce468a35b388ca46578934706b38dbae94941643Jeff Brown if (mDiscoverPeersInProgress) { 452ce468a35b388ca46578934706b38dbae94941643Jeff Brown handleScanResults(); 453ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 454e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 455e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }); 456e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 457cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 458e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private void handleScanStarted() { 459e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mHandler.post(new Runnable() { 460e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 461e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void run() { 462e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mListener.onScanStarted(); 463e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 464e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }); 465e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 466cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 467ce468a35b388ca46578934706b38dbae94941643Jeff Brown private void handleScanResults() { 46889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown final int count = mAvailableWifiDisplayPeers.size(); 469e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown final WifiDisplay[] displays = WifiDisplay.CREATOR.newArray(count); 470e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown for (int i = 0; i < count; i++) { 47174da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown WifiP2pDevice device = mAvailableWifiDisplayPeers.get(i); 47274da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown displays[i] = createWifiDisplay(device); 47374da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown updateDesiredDevice(device); 474e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 475e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 476e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mHandler.post(new Runnable() { 477e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 478e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void run() { 479ce468a35b388ca46578934706b38dbae94941643Jeff Brown mListener.onScanResults(displays); 480ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 481ce468a35b388ca46578934706b38dbae94941643Jeff Brown }); 482ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 483ce468a35b388ca46578934706b38dbae94941643Jeff Brown 484ce468a35b388ca46578934706b38dbae94941643Jeff Brown private void handleScanFinished() { 485ce468a35b388ca46578934706b38dbae94941643Jeff Brown mHandler.post(new Runnable() { 486ce468a35b388ca46578934706b38dbae94941643Jeff Brown @Override 487ce468a35b388ca46578934706b38dbae94941643Jeff Brown public void run() { 488ce468a35b388ca46578934706b38dbae94941643Jeff Brown mListener.onScanFinished(); 489cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 490cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }); 491cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 492cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 49374da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown private void updateDesiredDevice(WifiP2pDevice device) { 49474da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown // Handle the case where the device to which we are connecting or connected 49574da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown // may have been renamed or reported different properties in the latest scan. 49674da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown final String address = device.deviceAddress; 49774da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown if (mDesiredDevice != null && mDesiredDevice.deviceAddress.equals(address)) { 49874da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown if (DEBUG) { 49974da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown Slog.d(TAG, "updateDesiredDevice: new information " 50074da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown + describeWifiP2pDevice(device)); 50174da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 50274da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown mDesiredDevice.update(device); 50374da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown if (mAdvertisedDisplay != null 50474da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown && mAdvertisedDisplay.getDeviceAddress().equals(address)) { 50574da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown readvertiseDisplay(createWifiDisplay(mDesiredDevice)); 50674da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 50774da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 50874da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 50974da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown 510cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void connect(final WifiP2pDevice device) { 511cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mDesiredDevice != null 512cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown && !mDesiredDevice.deviceAddress.equals(device.deviceAddress)) { 513cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (DEBUG) { 514cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.d(TAG, "connect: nothing to do, already connecting to " 515cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + describeWifiP2pDevice(device)); 516cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 517cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return; 518cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 519cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 520cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mConnectedDevice != null 521cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown && !mConnectedDevice.deviceAddress.equals(device.deviceAddress) 522cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown && mDesiredDevice == null) { 523cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (DEBUG) { 524cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.d(TAG, "connect: nothing to do, already connected to " 525cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + describeWifiP2pDevice(device) + " and not part way through " 526cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + "connecting to a different device."); 527cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 5280cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown return; 529cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 530cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 531ce468a35b388ca46578934706b38dbae94941643Jeff Brown if (!mWfdEnabled) { 532ce468a35b388ca46578934706b38dbae94941643Jeff Brown Slog.i(TAG, "Ignoring request to connect to Wifi display because the " 533ce468a35b388ca46578934706b38dbae94941643Jeff Brown +" feature is currently disabled: " + device.deviceName); 534ce468a35b388ca46578934706b38dbae94941643Jeff Brown return; 535ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 536ce468a35b388ca46578934706b38dbae94941643Jeff Brown 537cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mDesiredDevice = device; 5380cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown mConnectionRetriesLeft = CONNECT_MAX_RETRIES; 539cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown updateConnection(); 540cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 541cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 542cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void disconnect() { 543cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mDesiredDevice = null; 544cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown updateConnection(); 545cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 546cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 5470cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown private void retryConnection() { 54889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown // Cheap hack. Make a new instance of the device object so that we 54989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown // can distinguish it from the previous connection attempt. 55089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown // This will cause us to tear everything down before we try again. 55189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mDesiredDevice = new WifiP2pDevice(mDesiredDevice); 55289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateConnection(); 5530cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown } 5540cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown 555cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown /** 556cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * This function is called repeatedly after each asynchronous operation 557cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * until all preconditions for the connection have been satisfied and the 558cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * connection is established (or not). 559cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown */ 560cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void updateConnection() { 561ce468a35b388ca46578934706b38dbae94941643Jeff Brown // Step 0. Stop scans if necessary to prevent interference while connected. 562ce468a35b388ca46578934706b38dbae94941643Jeff Brown // Resume scans later when no longer attempting to connect. 563ce468a35b388ca46578934706b38dbae94941643Jeff Brown updateScanState(); 564ce468a35b388ca46578934706b38dbae94941643Jeff Brown 565cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Step 1. Before we try to connect to a new device, tell the system we 566cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // have disconnected from the old one. 567f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown if (mRemoteDisplay != null && mConnectedDevice != mDesiredDevice) { 568f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown Slog.i(TAG, "Stopped listening for RTSP connection on " + mRemoteDisplayInterface 569f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown + " from Wifi display: " + mConnectedDevice.deviceName); 570f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 571f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mRemoteDisplay.dispose(); 572f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mRemoteDisplay = null; 573f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mRemoteDisplayInterface = null; 574f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mRemoteDisplayConnected = false; 575f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mHandler.removeCallbacks(mRtspTimeout); 576f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 577f110a3701b8d7ac435c5bb65df4dd9d758be1762Jeff Brown mWifiP2pManager.setMiracastMode(WifiP2pManager.MIRACAST_DISABLED); 578c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown unadvertiseDisplay(); 579cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 580cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // continue to next step 581cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 582cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 583cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Step 2. Before we try to connect to a new device, disconnect from the old one. 58474da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown if (mDisconnectingDevice != null) { 58574da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown return; // wait for asynchronous callback 58674da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 587cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mConnectedDevice != null && mConnectedDevice != mDesiredDevice) { 588cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Disconnecting from Wifi display: " + mConnectedDevice.deviceName); 58974da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown mDisconnectingDevice = mConnectedDevice; 59074da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown mConnectedDevice = null; 5911f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang mConnectedDeviceGroupInfo = null; 592cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 593c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown unadvertiseDisplay(); 594c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown 59574da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown final WifiP2pDevice oldDevice = mDisconnectingDevice; 596cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mWifiP2pManager.removeGroup(mWifiP2pChannel, new ActionListener() { 597cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 598cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onSuccess() { 599cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Disconnected from Wifi display: " + oldDevice.deviceName); 600cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown next(); 601cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 602cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 603cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 604cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onFailure(int reason) { 605cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Failed to disconnect from Wifi display: " 606cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + oldDevice.deviceName + ", reason=" + reason); 607cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown next(); 608cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 609cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 610cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void next() { 61174da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown if (mDisconnectingDevice == oldDevice) { 61274da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown mDisconnectingDevice = null; 613cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown updateConnection(); 614cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 615cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 616cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }); 617cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return; // wait for asynchronous callback 618cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 619cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 620cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Step 3. Before we try to connect to a new device, stop trying to connect 621cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // to the old one. 62274da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown if (mCancelingDevice != null) { 62374da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown return; // wait for asynchronous callback 62474da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 625cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mConnectingDevice != null && mConnectingDevice != mDesiredDevice) { 626cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Canceling connection to Wifi display: " + mConnectingDevice.deviceName); 62774da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown mCancelingDevice = mConnectingDevice; 62874da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown mConnectingDevice = null; 629cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 630c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown unadvertiseDisplay(); 631cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mHandler.removeCallbacks(mConnectionTimeout); 632cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 63374da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown final WifiP2pDevice oldDevice = mCancelingDevice; 634cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mWifiP2pManager.cancelConnect(mWifiP2pChannel, new ActionListener() { 635cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 636cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onSuccess() { 637cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Canceled connection to Wifi display: " + oldDevice.deviceName); 638cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown next(); 639cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 640cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 641cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 642cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onFailure(int reason) { 643cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Failed to cancel connection to Wifi display: " 644cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + oldDevice.deviceName + ", reason=" + reason); 645cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown next(); 646cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 647cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 648cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void next() { 64974da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown if (mCancelingDevice == oldDevice) { 65074da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown mCancelingDevice = null; 651cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown updateConnection(); 652cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 653cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 654cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }); 655cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return; // wait for asynchronous callback 656cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 657cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 6581f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang // Step 4. If we wanted to disconnect, or we're updating after starting an 6591f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang // autonomous GO, then mission accomplished. 660cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mDesiredDevice == null) { 6611f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang if (mWifiDisplayCertMode) { 6621f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang mListener.onDisplaySessionInfo(getSessionInfo(mConnectedDeviceGroupInfo, 0)); 6631f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 664c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown unadvertiseDisplay(); 665cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return; // done 666cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 667cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 668cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Step 5. Try to connect. 669cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mConnectedDevice == null && mConnectingDevice == null) { 670cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Connecting to Wifi display: " + mDesiredDevice.deviceName); 671cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 672cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mConnectingDevice = mDesiredDevice; 673cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown WifiP2pConfig config = new WifiP2pConfig(); 6746681be27875a50bd0c74826cb5d8defec72b8d58Irfan Sheriff WpsInfo wps = new WpsInfo(); 675e38af818b10e1a4927cc3fd69d19c9125d579321Chong Zhang if (mWifiDisplayWpsConfig != WpsInfo.INVALID) { 676e38af818b10e1a4927cc3fd69d19c9125d579321Chong Zhang wps.setup = mWifiDisplayWpsConfig; 677e38af818b10e1a4927cc3fd69d19c9125d579321Chong Zhang } else if (mConnectingDevice.wpsPbcSupported()) { 6786681be27875a50bd0c74826cb5d8defec72b8d58Irfan Sheriff wps.setup = WpsInfo.PBC; 6796681be27875a50bd0c74826cb5d8defec72b8d58Irfan Sheriff } else if (mConnectingDevice.wpsDisplaySupported()) { 6806681be27875a50bd0c74826cb5d8defec72b8d58Irfan Sheriff // We do keypad if peer does display 6816681be27875a50bd0c74826cb5d8defec72b8d58Irfan Sheriff wps.setup = WpsInfo.KEYPAD; 6826681be27875a50bd0c74826cb5d8defec72b8d58Irfan Sheriff } else { 6836681be27875a50bd0c74826cb5d8defec72b8d58Irfan Sheriff wps.setup = WpsInfo.DISPLAY; 6846681be27875a50bd0c74826cb5d8defec72b8d58Irfan Sheriff } 6856681be27875a50bd0c74826cb5d8defec72b8d58Irfan Sheriff config.wps = wps; 686cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown config.deviceAddress = mConnectingDevice.deviceAddress; 687e0c28d5f1358fc2d4c464f910bd04fed4b283fefIrfan Sheriff // Helps with STA & P2P concurrency 68899766cf40ed706aad36032f2107fb0c1e54fc398Irfan Sheriff config.groupOwnerIntent = WifiP2pConfig.MIN_GROUP_OWNER_INTENT; 689cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 690c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown WifiDisplay display = createWifiDisplay(mConnectingDevice); 691c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown advertiseDisplay(display, null, 0, 0, 0); 692e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 693cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown final WifiP2pDevice newDevice = mDesiredDevice; 694cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mWifiP2pManager.connect(mWifiP2pChannel, config, new ActionListener() { 695cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 696cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onSuccess() { 697cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // The connection may not yet be established. We still need to wait 698cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // for WIFI_P2P_CONNECTION_CHANGED_ACTION. However, we might never 699cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // get that broadcast, so we register a timeout. 700cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Initiated connection to Wifi display: " + newDevice.deviceName); 701cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 702cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mHandler.postDelayed(mConnectionTimeout, CONNECTION_TIMEOUT_SECONDS * 1000); 703cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 704cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 705cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 706cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onFailure(int reason) { 707cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mConnectingDevice == newDevice) { 708f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown Slog.i(TAG, "Failed to initiate connection to Wifi display: " 709f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown + newDevice.deviceName + ", reason=" + reason); 710cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mConnectingDevice = null; 7110cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown handleConnectionFailure(false); 712cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 713cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 714cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }); 715cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return; // wait for asynchronous callback 716cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 717cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 718ce468a35b388ca46578934706b38dbae94941643Jeff Brown // Step 6. Listen for incoming RTSP connection. 719f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown if (mConnectedDevice != null && mRemoteDisplay == null) { 720cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Inet4Address addr = getInterfaceAddress(mConnectedDeviceGroupInfo); 721cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (addr == null) { 722cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Failed to get local interface address for communicating " 723cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + "with Wifi display: " + mConnectedDevice.deviceName); 7240cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown handleConnectionFailure(false); 725cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return; // done 726cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 727cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 728f110a3701b8d7ac435c5bb65df4dd9d758be1762Jeff Brown mWifiP2pManager.setMiracastMode(WifiP2pManager.MIRACAST_SOURCE); 729c9bd4ca005768cb30aaaa44c1171e113c13cd107Jeff Brown 730f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown final WifiP2pDevice oldDevice = mConnectedDevice; 7310f68d166e6ca45fe27410ea520967275e0733757Jeff Brown final int port = getPortNumber(mConnectedDevice); 732cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown final String iface = addr.getHostAddress() + ":" + port; 733f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mRemoteDisplayInterface = iface; 734cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 735f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown Slog.i(TAG, "Listening for RTSP connection on " + iface 736f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown + " from Wifi display: " + mConnectedDevice.deviceName); 737f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 738f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mRemoteDisplay = RemoteDisplay.listen(iface, new RemoteDisplay.Listener() { 739cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 740c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown public void onDisplayConnected(Surface surface, 7411f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang int width, int height, int flags, int session) { 742f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown if (mConnectedDevice == oldDevice && !mRemoteDisplayConnected) { 743f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown Slog.i(TAG, "Opened RTSP connection with Wifi display: " 744f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown + mConnectedDevice.deviceName); 745f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mRemoteDisplayConnected = true; 746f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mHandler.removeCallbacks(mRtspTimeout); 747f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 7481f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang if (mWifiDisplayCertMode) { 7491f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang mListener.onDisplaySessionInfo( 7501f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang getSessionInfo(mConnectedDeviceGroupInfo, session)); 7511f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 7521f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang 753f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown final WifiDisplay display = createWifiDisplay(mConnectedDevice); 754c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown advertiseDisplay(display, surface, width, height, flags); 755f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown } 756cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 757f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 758f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown @Override 759f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown public void onDisplayDisconnected() { 760f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown if (mConnectedDevice == oldDevice) { 761f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown Slog.i(TAG, "Closed RTSP connection with Wifi display: " 762f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown + mConnectedDevice.deviceName); 763f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mHandler.removeCallbacks(mRtspTimeout); 764f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown disconnect(); 765f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown } 766f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown } 767f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 768f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown @Override 769f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown public void onDisplayError(int error) { 770f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown if (mConnectedDevice == oldDevice) { 771f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown Slog.i(TAG, "Lost RTSP connection with Wifi display due to error " 772f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown + error + ": " + mConnectedDevice.deviceName); 773f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mHandler.removeCallbacks(mRtspTimeout); 774f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown handleConnectionFailure(false); 775f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown } 776f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown } 777fa5ecdc4ac6d7a8db2bb9e4a6a60a3189025df30Svet Ganov }, mHandler, mContext.getOpPackageName()); 778f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 7791f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang // Use extended timeout value for certification, as some tests require user inputs 7801f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang int rtspTimeout = mWifiDisplayCertMode ? 7811f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang RTSP_TIMEOUT_SECONDS_CERT_MODE : RTSP_TIMEOUT_SECONDS; 7821f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang 7831f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang mHandler.postDelayed(mRtspTimeout, rtspTimeout * 1000); 7841f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 7851f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 7861f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang 7871f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang private WifiDisplaySessionInfo getSessionInfo(WifiP2pGroup info, int session) { 7881f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang if (info == null) { 7891f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang return null; 7901f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 7911f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang Inet4Address addr = getInterfaceAddress(info); 7921f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang WifiDisplaySessionInfo sessionInfo = new WifiDisplaySessionInfo( 7931f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang !info.getOwner().deviceAddress.equals(mThisDevice.deviceAddress), 7941f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang session, 7951f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang info.getOwner().deviceAddress + " " + info.getNetworkName(), 7961f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang info.getPassphrase(), 7971f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang (addr != null) ? addr.getHostAddress() : ""); 7981f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang if (DEBUG) { 7991f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang Slog.d(TAG, sessionInfo.toString()); 800cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 8011f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang return sessionInfo; 802cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 803cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 804cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void handleStateChanged(boolean enabled) { 80589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mWifiP2pEnabled = enabled; 80689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateWfdEnableState(); 807cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 808cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 809cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void handlePeersChanged() { 81056925d65fde7f1ac8676ada6f91d0e604645c0a5Irfan Sheriff // Even if wfd is disabled, it is best to get the latest set of peers to 81156925d65fde7f1ac8676ada6f91d0e604645c0a5Irfan Sheriff // keep in sync with the p2p framework 81256925d65fde7f1ac8676ada6f91d0e604645c0a5Irfan Sheriff requestPeers(); 813cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 814cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 815cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void handleConnectionChanged(NetworkInfo networkInfo) { 816cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mNetworkInfo = networkInfo; 817180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mWfdEnabled && networkInfo.isConnected()) { 8181f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang if (mDesiredDevice != null || mWifiDisplayCertMode) { 819cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mWifiP2pManager.requestGroupInfo(mWifiP2pChannel, new GroupInfoListener() { 820cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 821cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onGroupInfoAvailable(WifiP2pGroup info) { 822cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (DEBUG) { 823cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.d(TAG, "Received group info: " + describeWifiP2pGroup(info)); 824cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 825cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 826cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mConnectingDevice != null && !info.contains(mConnectingDevice)) { 827cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Aborting connection to Wifi display because " 828cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + "the current P2P group does not contain the device " 82989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown + "we expected to find: " + mConnectingDevice.deviceName 83089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown + ", group info was: " + describeWifiP2pGroup(info)); 8310cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown handleConnectionFailure(false); 832cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return; 833cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 834cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 835cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mDesiredDevice != null && !info.contains(mDesiredDevice)) { 836cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown disconnect(); 837cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return; 838cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 839cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 8401f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang if (mWifiDisplayCertMode) { 8411f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang boolean owner = info.getOwner().deviceAddress 8421f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang .equals(mThisDevice.deviceAddress); 8431f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang if (owner && info.getClientList().isEmpty()) { 8441f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang // this is the case when we started Autonomous GO, 8451f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang // and no client has connected, save group info 8461f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang // and updateConnection() 8471f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang mConnectingDevice = mDesiredDevice = null; 8481f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang mConnectedDeviceGroupInfo = info; 8491f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang updateConnection(); 8501f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } else if (mConnectingDevice == null && mDesiredDevice == null) { 8511f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang // this is the case when we received an incoming connection 8521f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang // from the sink, update both mConnectingDevice and mDesiredDevice 8531f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang // then proceed to updateConnection() below 8541f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang mConnectingDevice = mDesiredDevice = owner ? 8551f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang info.getClientList().iterator().next() : info.getOwner(); 8561f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 8571f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 8581f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang 859cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mConnectingDevice != null && mConnectingDevice == mDesiredDevice) { 8600cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown Slog.i(TAG, "Connected to Wifi display: " 8610cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown + mConnectingDevice.deviceName); 862cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 863cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mHandler.removeCallbacks(mConnectionTimeout); 864cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mConnectedDeviceGroupInfo = info; 865cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mConnectedDevice = mConnectingDevice; 866cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mConnectingDevice = null; 867cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown updateConnection(); 868cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 869cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 870cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }); 871cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 872cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } else { 8731f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang mConnectedDeviceGroupInfo = null; 874ce468a35b388ca46578934706b38dbae94941643Jeff Brown 875ce468a35b388ca46578934706b38dbae94941643Jeff Brown // Disconnect if we lost the network while connecting or connected to a display. 876ce468a35b388ca46578934706b38dbae94941643Jeff Brown if (mConnectingDevice != null || mConnectedDevice != null) { 877ce468a35b388ca46578934706b38dbae94941643Jeff Brown disconnect(); 878ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 879180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown 880180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown // After disconnection for a group, for some reason we have a tendency 881180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown // to get a peer change notification with an empty list of peers. 882180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown // Perform a fresh scan. 883180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mWfdEnabled) { 884180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown requestPeers(); 885180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown } 886cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 887cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 888cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 889ce468a35b388ca46578934706b38dbae94941643Jeff Brown private final Runnable mDiscoverPeers = new Runnable() { 890ce468a35b388ca46578934706b38dbae94941643Jeff Brown @Override 891ce468a35b388ca46578934706b38dbae94941643Jeff Brown public void run() { 892ce468a35b388ca46578934706b38dbae94941643Jeff Brown tryDiscoverPeers(); 893ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 894ce468a35b388ca46578934706b38dbae94941643Jeff Brown }; 895ce468a35b388ca46578934706b38dbae94941643Jeff Brown 896cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final Runnable mConnectionTimeout = new Runnable() { 897cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 898cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void run() { 899cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mConnectingDevice != null && mConnectingDevice == mDesiredDevice) { 900cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Timed out waiting for Wifi display connection after " 901cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + CONNECTION_TIMEOUT_SECONDS + " seconds: " 902cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + mConnectingDevice.deviceName); 9030cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown handleConnectionFailure(true); 904cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 905cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 906cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }; 907cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 908f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown private final Runnable mRtspTimeout = new Runnable() { 909f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown @Override 910f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown public void run() { 911f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown if (mConnectedDevice != null 912f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown && mRemoteDisplay != null && !mRemoteDisplayConnected) { 913f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown Slog.i(TAG, "Timed out waiting for Wifi display RTSP connection after " 914f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown + RTSP_TIMEOUT_SECONDS + " seconds: " 915f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown + mConnectedDevice.deviceName); 916f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown handleConnectionFailure(true); 917f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown } 918f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown } 919f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown }; 920f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 9210cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown private void handleConnectionFailure(boolean timeoutOccurred) { 922f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown Slog.i(TAG, "Wifi display connection failed!"); 9230cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown 924f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown if (mDesiredDevice != null) { 9250cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown if (mConnectionRetriesLeft > 0) { 92689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown final WifiP2pDevice oldDevice = mDesiredDevice; 9270cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown mHandler.postDelayed(new Runnable() { 9280cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown @Override 9290cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown public void run() { 93089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mDesiredDevice == oldDevice && mConnectionRetriesLeft > 0) { 93189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mConnectionRetriesLeft -= 1; 93289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown Slog.i(TAG, "Retrying Wifi display connection. Retries left: " 93389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown + mConnectionRetriesLeft); 93489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown retryConnection(); 93589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 9360cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown } 9370cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown }, timeoutOccurred ? 0 : CONNECT_RETRY_DELAY_MILLIS); 9380cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown } else { 9390cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown disconnect(); 9400cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown } 941cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 942cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 943cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 944c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown private void advertiseDisplay(final WifiDisplay display, 945c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown final Surface surface, final int width, final int height, final int flags) { 946607223f3b7a1c4dc3ac995f742f8d2da50d85ffcNarayan Kamath if (!Objects.equals(mAdvertisedDisplay, display) 947c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown || mAdvertisedDisplaySurface != surface 948c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown || mAdvertisedDisplayWidth != width 949c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown || mAdvertisedDisplayHeight != height 950c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown || mAdvertisedDisplayFlags != flags) { 951c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown final WifiDisplay oldDisplay = mAdvertisedDisplay; 952c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown final Surface oldSurface = mAdvertisedDisplaySurface; 953c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown 954c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown mAdvertisedDisplay = display; 955c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown mAdvertisedDisplaySurface = surface; 956c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown mAdvertisedDisplayWidth = width; 957c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown mAdvertisedDisplayHeight = height; 958c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown mAdvertisedDisplayFlags = flags; 959c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown 960c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown mHandler.post(new Runnable() { 961c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown @Override 962c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown public void run() { 963c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown if (oldSurface != null && surface != oldSurface) { 964c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown mListener.onDisplayDisconnected(); 96574da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } else if (oldDisplay != null && !oldDisplay.hasSameAddress(display)) { 966c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown mListener.onDisplayConnectionFailed(); 967c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown } 968c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown 969c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown if (display != null) { 97074da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown if (!display.hasSameAddress(oldDisplay)) { 971c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown mListener.onDisplayConnecting(display); 97274da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } else if (!display.equals(oldDisplay)) { 97374da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown // The address is the same but some other property such as the 97474da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown // name must have changed. 97574da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown mListener.onDisplayChanged(display); 976c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown } 977c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown if (surface != null && surface != oldSurface) { 978c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown mListener.onDisplayConnected(display, surface, width, height, flags); 979c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown } 980c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown } 981c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown } 982c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown }); 983c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown } 984c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown } 985c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown 986c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown private void unadvertiseDisplay() { 987c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown advertiseDisplay(null, null, 0, 0, 0); 988c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown } 989c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown 99074da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown private void readvertiseDisplay(WifiDisplay display) { 99174da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown advertiseDisplay(display, mAdvertisedDisplaySurface, 99274da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown mAdvertisedDisplayWidth, mAdvertisedDisplayHeight, 99374da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown mAdvertisedDisplayFlags); 99474da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 99574da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown 996cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private static Inet4Address getInterfaceAddress(WifiP2pGroup info) { 997cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown NetworkInterface iface; 998cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown try { 999cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown iface = NetworkInterface.getByName(info.getInterface()); 1000cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } catch (SocketException ex) { 1001cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.w(TAG, "Could not obtain address of network interface " 1002cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + info.getInterface(), ex); 1003cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return null; 1004cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 1005cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 1006cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Enumeration<InetAddress> addrs = iface.getInetAddresses(); 1007cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown while (addrs.hasMoreElements()) { 1008cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown InetAddress addr = addrs.nextElement(); 1009cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (addr instanceof Inet4Address) { 1010cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return (Inet4Address)addr; 1011cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 1012cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 1013cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 1014cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.w(TAG, "Could not obtain address of network interface " 1015cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + info.getInterface() + " because it had no IPv4 addresses."); 1016cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return null; 1017cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 1018cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 10190f68d166e6ca45fe27410ea520967275e0733757Jeff Brown private static int getPortNumber(WifiP2pDevice device) { 10200f68d166e6ca45fe27410ea520967275e0733757Jeff Brown if (device.deviceName.startsWith("DIRECT-") 10210f68d166e6ca45fe27410ea520967275e0733757Jeff Brown && device.deviceName.endsWith("Broadcom")) { 10220f68d166e6ca45fe27410ea520967275e0733757Jeff Brown // These dongles ignore the port we broadcast in our WFD IE. 10230f68d166e6ca45fe27410ea520967275e0733757Jeff Brown return 8554; 10240f68d166e6ca45fe27410ea520967275e0733757Jeff Brown } 10250f68d166e6ca45fe27410ea520967275e0733757Jeff Brown return DEFAULT_CONTROL_PORT; 10260f68d166e6ca45fe27410ea520967275e0733757Jeff Brown } 10270f68d166e6ca45fe27410ea520967275e0733757Jeff Brown 1028cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private static boolean isWifiDisplay(WifiP2pDevice device) { 10290f68d166e6ca45fe27410ea520967275e0733757Jeff Brown return device.wfdInfo != null 10300f68d166e6ca45fe27410ea520967275e0733757Jeff Brown && device.wfdInfo.isWfdEnabled() 10310f68d166e6ca45fe27410ea520967275e0733757Jeff Brown && isPrimarySinkDeviceType(device.wfdInfo.getDeviceType()); 10320f68d166e6ca45fe27410ea520967275e0733757Jeff Brown } 10330f68d166e6ca45fe27410ea520967275e0733757Jeff Brown 10340f68d166e6ca45fe27410ea520967275e0733757Jeff Brown private static boolean isPrimarySinkDeviceType(int deviceType) { 10350f68d166e6ca45fe27410ea520967275e0733757Jeff Brown return deviceType == WifiP2pWfdInfo.PRIMARY_SINK 10360f68d166e6ca45fe27410ea520967275e0733757Jeff Brown || deviceType == WifiP2pWfdInfo.SOURCE_OR_PRIMARY_SINK; 1037cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 1038cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 1039cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private static String describeWifiP2pDevice(WifiP2pDevice device) { 1040cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return device != null ? device.toString().replace('\n', ',') : "null"; 1041cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 1042cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 1043cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private static String describeWifiP2pGroup(WifiP2pGroup group) { 1044cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return group != null ? group.toString().replace('\n', ',') : "null"; 1045cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 1046cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 1047e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private static WifiDisplay createWifiDisplay(WifiP2pDevice device) { 104821f603996ed83c7a9a6c430582e8a5af5ac13c6cChong Zhang return new WifiDisplay(device.deviceAddress, device.deviceName, null, 1049ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang true, device.wfdInfo.isSessionAvailable(), false); 1050e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 1051e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 1052cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final BroadcastReceiver mWifiP2pReceiver = new BroadcastReceiver() { 1053cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 1054cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onReceive(Context context, Intent intent) { 1055cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown final String action = intent.getAction(); 1056cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (action.equals(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION)) { 105789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown // This broadcast is sticky so we'll always get the initial Wifi P2P state 105889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown // on startup. 1059cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown boolean enabled = (intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, 1060cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown WifiP2pManager.WIFI_P2P_STATE_DISABLED)) == 1061cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown WifiP2pManager.WIFI_P2P_STATE_ENABLED; 1062cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (DEBUG) { 1063cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.d(TAG, "Received WIFI_P2P_STATE_CHANGED_ACTION: enabled=" 1064cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + enabled); 1065cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 1066cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 1067cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown handleStateChanged(enabled); 1068cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } else if (action.equals(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION)) { 1069cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (DEBUG) { 1070cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.d(TAG, "Received WIFI_P2P_PEERS_CHANGED_ACTION."); 1071cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 1072cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 1073cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown handlePeersChanged(); 1074cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } else if (action.equals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)) { 1075cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown NetworkInfo networkInfo = (NetworkInfo)intent.getParcelableExtra( 1076cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown WifiP2pManager.EXTRA_NETWORK_INFO); 1077cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (DEBUG) { 1078cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.d(TAG, "Received WIFI_P2P_CONNECTION_CHANGED_ACTION: networkInfo=" 1079cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + networkInfo); 1080cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 1081cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 1082cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown handleConnectionChanged(networkInfo); 10831f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } else if (action.equals(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION)) { 10841f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang mThisDevice = (WifiP2pDevice) intent.getParcelableExtra( 10851f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang WifiP2pManager.EXTRA_WIFI_P2P_DEVICE); 10861f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang if (DEBUG) { 10871f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang Slog.d(TAG, "Received WIFI_P2P_THIS_DEVICE_CHANGED_ACTION: mThisDevice= " 10881f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang + mThisDevice); 10891f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 1090cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 1091cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 1092cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }; 1093cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 1094cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown /** 1095cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Called on the handler thread when displays are connected or disconnected. 1096cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown */ 1097cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public interface Listener { 109889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown void onFeatureStateChanged(int featureState); 1099e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 1100e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown void onScanStarted(); 1101ce468a35b388ca46578934706b38dbae94941643Jeff Brown void onScanResults(WifiDisplay[] availableDisplays); 1102ce468a35b388ca46578934706b38dbae94941643Jeff Brown void onScanFinished(); 1103e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 1104e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown void onDisplayConnecting(WifiDisplay display); 1105e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown void onDisplayConnectionFailed(); 110674da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown void onDisplayChanged(WifiDisplay display); 1107f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown void onDisplayConnected(WifiDisplay display, 1108f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown Surface surface, int width, int height, int flags); 11091f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang void onDisplaySessionInfo(WifiDisplaySessionInfo sessionInfo); 1110cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown void onDisplayDisconnected(); 1111cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 1112cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown} 1113