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; 2889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownimport android.hardware.display.WifiDisplayStatus; 2988469e56c8294a928e65398352e8444d66bdb75aJeff Brownimport android.media.AudioManager; 30f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brownimport android.media.RemoteDisplay; 31cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.net.NetworkInfo; 3289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownimport android.net.Uri; 33cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.net.wifi.p2p.WifiP2pConfig; 34cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.net.wifi.p2p.WifiP2pDevice; 35cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.net.wifi.p2p.WifiP2pDeviceList; 36cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.net.wifi.p2p.WifiP2pGroup; 37cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.net.wifi.p2p.WifiP2pManager; 38cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.net.wifi.p2p.WifiP2pWfdInfo; 39cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.net.wifi.p2p.WifiP2pManager.ActionListener; 40cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.net.wifi.p2p.WifiP2pManager.Channel; 41cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.net.wifi.p2p.WifiP2pManager.GroupInfoListener; 42cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.net.wifi.p2p.WifiP2pManager.PeerListListener; 43cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.os.Handler; 4489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brownimport android.provider.Settings; 45cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.util.Slog; 46f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brownimport android.view.Surface; 47cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 48cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport java.io.PrintWriter; 49cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport java.net.Inet4Address; 50cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport java.net.InetAddress; 51cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport java.net.NetworkInterface; 52cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport java.net.SocketException; 53cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport java.util.ArrayList; 54cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport java.util.Enumeration; 55cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 56c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brownimport libcore.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; 762c2ca5cb7c083cd53dee00e71af99d1abf931976Irfan Sheriff private static final int CONNECTION_TIMEOUT_SECONDS = 60; 77f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown private static final int RTSP_TIMEOUT_SECONDS = 15; 78cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 790cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown private static final int DISCOVER_PEERS_MAX_RETRIES = 10; 800cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown private static final int DISCOVER_PEERS_RETRY_DELAY_MILLIS = 500; 810cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown 820cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown private static final int CONNECT_MAX_RETRIES = 3; 830cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown private static final int CONNECT_RETRY_DELAY_MILLIS = 500; 840cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown 8588469e56c8294a928e65398352e8444d66bdb75aJeff Brown // A unique token to identify the remote submix that is managed by Wifi display. 8688469e56c8294a928e65398352e8444d66bdb75aJeff Brown // It must match what the media server uses when it starts recording the submix 8788469e56c8294a928e65398352e8444d66bdb75aJeff Brown // for transmission. We use 0 although the actual value is currently ignored. 8888469e56c8294a928e65398352e8444d66bdb75aJeff Brown private static final int REMOTE_SUBMIX_ADDRESS = 0; 8988469e56c8294a928e65398352e8444d66bdb75aJeff Brown 90cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final Context mContext; 91cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final Handler mHandler; 92cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final Listener mListener; 9388469e56c8294a928e65398352e8444d66bdb75aJeff Brown 94cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final WifiP2pManager mWifiP2pManager; 95cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final Channel mWifiP2pChannel; 96cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 9788469e56c8294a928e65398352e8444d66bdb75aJeff Brown private final AudioManager mAudioManager; 9888469e56c8294a928e65398352e8444d66bdb75aJeff Brown 99cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private boolean mWifiP2pEnabled; 100cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private boolean mWfdEnabled; 101cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private boolean mWfdEnabling; 102cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private NetworkInfo mNetworkInfo; 103cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 10489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private final ArrayList<WifiP2pDevice> mAvailableWifiDisplayPeers = 105cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown new ArrayList<WifiP2pDevice>(); 106cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 10789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown // True if Wifi display is enabled by the user. 10889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private boolean mWifiDisplayOnSetting; 10989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 1100cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown // True if there is a call to discoverPeers in progress. 1110cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown private boolean mDiscoverPeersInProgress; 1120cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown 1130cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown // Number of discover peers retries remaining. 1140cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown private int mDiscoverPeersRetriesLeft; 1150cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown 116cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // The device to which we want to connect, or null if we want to be disconnected. 117cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private WifiP2pDevice mDesiredDevice; 118cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 119cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // The device to which we are currently connecting, or null if we have already connected 120cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // or are not trying to connect. 121cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private WifiP2pDevice mConnectingDevice; 122cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 123cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // The device to which we are currently connected, which means we have an active P2P group. 124cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private WifiP2pDevice mConnectedDevice; 125cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 126cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // The group info obtained after connecting. 127cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private WifiP2pGroup mConnectedDeviceGroupInfo; 128cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 1290cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown // Number of connection retries remaining. 1300cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown private int mConnectionRetriesLeft; 1310cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown 132f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown // The remote display that is listening on the connection. 133f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown // Created after the Wifi P2P network is connected. 134f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown private RemoteDisplay mRemoteDisplay; 135f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 136f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown // The remote display interface. 137f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown private String mRemoteDisplayInterface; 138f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 139f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown // True if RTSP has connected. 140f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown private boolean mRemoteDisplayConnected; 141f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 142c9bd4ca005768cb30aaaa44c1171e113c13cd107Jeff Brown // True if the remote submix is enabled. 143c9bd4ca005768cb30aaaa44c1171e113c13cd107Jeff Brown private boolean mRemoteSubmixOn; 144c9bd4ca005768cb30aaaa44c1171e113c13cd107Jeff Brown 145c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown // The information we have most recently told WifiDisplayAdapter about. 146c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown private WifiDisplay mAdvertisedDisplay; 147c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown private Surface mAdvertisedDisplaySurface; 148c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown private int mAdvertisedDisplayWidth; 149c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown private int mAdvertisedDisplayHeight; 150c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown private int mAdvertisedDisplayFlags; 151c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown 152cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public WifiDisplayController(Context context, Handler handler, Listener listener) { 153cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mContext = context; 154cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mHandler = handler; 155cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mListener = listener; 156cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 157cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mWifiP2pManager = (WifiP2pManager)context.getSystemService(Context.WIFI_P2P_SERVICE); 158cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mWifiP2pChannel = mWifiP2pManager.initialize(context, handler.getLooper(), null); 159cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 16088469e56c8294a928e65398352e8444d66bdb75aJeff Brown mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE); 16188469e56c8294a928e65398352e8444d66bdb75aJeff Brown 162cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown IntentFilter intentFilter = new IntentFilter(); 163cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown intentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION); 164cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown intentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION); 165cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown intentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); 16689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown context.registerReceiver(mWifiP2pReceiver, intentFilter, null, mHandler); 16789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 16889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown ContentObserver settingsObserver = new ContentObserver(mHandler) { 16989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown @Override 17089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void onChange(boolean selfChange, Uri uri) { 17189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateSettings(); 17289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 17389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown }; 17489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 17589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown final ContentResolver resolver = mContext.getContentResolver(); 17689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown resolver.registerContentObserver(Settings.Global.getUriFor( 17789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown Settings.Global.WIFI_DISPLAY_ON), false, settingsObserver); 17889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateSettings(); 17989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 18089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 18189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private void updateSettings() { 18289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown final ContentResolver resolver = mContext.getContentResolver(); 18389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mWifiDisplayOnSetting = Settings.Global.getInt(resolver, 18489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown Settings.Global.WIFI_DISPLAY_ON, 0) != 0; 18589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 18689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateWfdEnableState(); 187cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 188cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 189cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void dump(PrintWriter pw) { 19089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown pw.println("mWifiDisplayOnSetting=" + mWifiDisplayOnSetting); 191cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mWifiP2pEnabled=" + mWifiP2pEnabled); 192cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mWfdEnabled=" + mWfdEnabled); 193cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mWfdEnabling=" + mWfdEnabling); 194cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mNetworkInfo=" + mNetworkInfo); 1950cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown pw.println("mDiscoverPeersInProgress=" + mDiscoverPeersInProgress); 1960cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown pw.println("mDiscoverPeersRetriesLeft=" + mDiscoverPeersRetriesLeft); 197cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mDesiredDevice=" + describeWifiP2pDevice(mDesiredDevice)); 198cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mConnectingDisplay=" + describeWifiP2pDevice(mConnectingDevice)); 199cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mConnectedDevice=" + describeWifiP2pDevice(mConnectedDevice)); 2000cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown pw.println("mConnectionRetriesLeft=" + mConnectionRetriesLeft); 201f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown pw.println("mRemoteDisplay=" + mRemoteDisplay); 202f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown pw.println("mRemoteDisplayInterface=" + mRemoteDisplayInterface); 203f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown pw.println("mRemoteDisplayConnected=" + mRemoteDisplayConnected); 204c9bd4ca005768cb30aaaa44c1171e113c13cd107Jeff Brown pw.println("mRemoteSubmixOn=" + mRemoteSubmixOn); 205c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown pw.println("mAdvertisedDisplay=" + mAdvertisedDisplay); 206c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown pw.println("mAdvertisedDisplaySurface=" + mAdvertisedDisplaySurface); 207c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown pw.println("mAdvertisedDisplayWidth=" + mAdvertisedDisplayWidth); 208c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown pw.println("mAdvertisedDisplayHeight=" + mAdvertisedDisplayHeight); 209c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown pw.println("mAdvertisedDisplayFlags=" + mAdvertisedDisplayFlags); 210cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 21189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown pw.println("mAvailableWifiDisplayPeers: size=" + mAvailableWifiDisplayPeers.size()); 21289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown for (WifiP2pDevice device : mAvailableWifiDisplayPeers) { 213cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println(" " + describeWifiP2pDevice(device)); 214cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 215cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 216cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 217e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void requestScan() { 218e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown discoverPeers(); 219e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 220e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 221e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void requestConnect(String address) { 22289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown for (WifiP2pDevice device : mAvailableWifiDisplayPeers) { 223e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (device.deviceAddress.equals(address)) { 224e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown connect(device); 225e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 226e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 227e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 228e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 229e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void requestDisconnect() { 230e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown disconnect(); 231e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 232e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 23389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private void updateWfdEnableState() { 23489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mWifiDisplayOnSetting && mWifiP2pEnabled) { 23589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown // WFD should be enabled. 23689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (!mWfdEnabled && !mWfdEnabling) { 23789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mWfdEnabling = true; 23889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 23989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown WifiP2pWfdInfo wfdInfo = new WifiP2pWfdInfo(); 24089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown wfdInfo.setWfdEnabled(true); 24189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown wfdInfo.setDeviceType(WifiP2pWfdInfo.WFD_SOURCE); 24289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown wfdInfo.setSessionAvailable(true); 24389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown wfdInfo.setControlPort(DEFAULT_CONTROL_PORT); 24489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown wfdInfo.setMaxThroughput(MAX_THROUGHPUT); 24589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mWifiP2pManager.setWFDInfo(mWifiP2pChannel, wfdInfo, new ActionListener() { 24689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown @Override 24789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void onSuccess() { 24889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (DEBUG) { 24989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown Slog.d(TAG, "Successfully set WFD info."); 25089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 25189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mWfdEnabling) { 25289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mWfdEnabling = false; 25389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mWfdEnabled = true; 25489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown reportFeatureState(); 25589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 256cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 257cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 25889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown @Override 25989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void onFailure(int reason) { 26089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (DEBUG) { 26189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown Slog.d(TAG, "Failed to set WFD info with reason " + reason + "."); 26289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 26389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mWfdEnabling = false; 264cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 26589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown }); 26689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 26789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } else { 26889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown // WFD should be disabled. 26989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mWfdEnabling = false; 27089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mWfdEnabled = false; 27189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown reportFeatureState(); 27289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown disconnect(); 273cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 274cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 275cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 27689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private void reportFeatureState() { 27789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown final int featureState = computeFeatureState(); 27889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mHandler.post(new Runnable() { 27989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown @Override 28089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void run() { 28189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mListener.onFeatureStateChanged(featureState); 28289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 28389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown }); 28489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 28589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 28689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private int computeFeatureState() { 28789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (!mWifiP2pEnabled) { 28889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown return WifiDisplayStatus.FEATURE_STATE_DISABLED; 289e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 29089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown return mWifiDisplayOnSetting ? WifiDisplayStatus.FEATURE_STATE_ON : 29189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown WifiDisplayStatus.FEATURE_STATE_OFF; 292e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 293e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 294cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void discoverPeers() { 2950cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown if (!mDiscoverPeersInProgress) { 2960cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown mDiscoverPeersInProgress = true; 2970cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown mDiscoverPeersRetriesLeft = DISCOVER_PEERS_MAX_RETRIES; 298e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown handleScanStarted(); 2990cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown tryDiscoverPeers(); 3000cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown } 3010cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown } 3020cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown 3030cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown private void tryDiscoverPeers() { 304cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mWifiP2pManager.discoverPeers(mWifiP2pChannel, new ActionListener() { 305cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 306cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onSuccess() { 307cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (DEBUG) { 308cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.d(TAG, "Discover peers succeeded. Requesting peers now."); 309cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 310cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 3110cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown mDiscoverPeersInProgress = false; 312cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown requestPeers(); 313cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 314cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 315cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 316cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onFailure(int reason) { 317cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (DEBUG) { 318cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.d(TAG, "Discover peers failed with reason " + reason + "."); 319cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 3200cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown 3210cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown if (mDiscoverPeersInProgress) { 3220cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown if (reason == 0 && mDiscoverPeersRetriesLeft > 0 && mWfdEnabled) { 3230cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown mHandler.postDelayed(new Runnable() { 3240cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown @Override 3250cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown public void run() { 3260cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown if (mDiscoverPeersInProgress) { 3270cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown if (mDiscoverPeersRetriesLeft > 0 && mWfdEnabled) { 3280cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown mDiscoverPeersRetriesLeft -= 1; 3290cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown if (DEBUG) { 3300cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown Slog.d(TAG, "Retrying discovery. Retries left: " 3310cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown + mDiscoverPeersRetriesLeft); 3320cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown } 3330cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown tryDiscoverPeers(); 3340cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown } else { 335e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown handleScanFinished(); 3360cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown mDiscoverPeersInProgress = false; 3370cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown } 3380cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown } 3390cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown } 3400cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown }, DISCOVER_PEERS_RETRY_DELAY_MILLIS); 3410cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown } else { 342e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown handleScanFinished(); 3430cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown mDiscoverPeersInProgress = false; 3440cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown } 3450cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown } 346cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 347cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }); 348cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 349cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 350cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void requestPeers() { 351cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mWifiP2pManager.requestPeers(mWifiP2pChannel, new PeerListListener() { 352cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 353cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onPeersAvailable(WifiP2pDeviceList peers) { 354cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (DEBUG) { 355cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.d(TAG, "Received list of peers."); 356cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 357cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 35889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mAvailableWifiDisplayPeers.clear(); 359cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown for (WifiP2pDevice device : peers.getDeviceList()) { 360cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (DEBUG) { 361cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.d(TAG, " " + describeWifiP2pDevice(device)); 362cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 363cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 364cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (isWifiDisplay(device)) { 36589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mAvailableWifiDisplayPeers.add(device); 366cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 367cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 368cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 369e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown handleScanFinished(); 370e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 371e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }); 372e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 373cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 374e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private void handleScanStarted() { 375e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mHandler.post(new Runnable() { 376e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 377e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void run() { 378e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mListener.onScanStarted(); 379e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 380e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }); 381e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 382cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 383e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private void handleScanFinished() { 38489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown final int count = mAvailableWifiDisplayPeers.size(); 385e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown final WifiDisplay[] displays = WifiDisplay.CREATOR.newArray(count); 386e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown for (int i = 0; i < count; i++) { 38789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown displays[i] = createWifiDisplay(mAvailableWifiDisplayPeers.get(i)); 388e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 389e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 390e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mHandler.post(new Runnable() { 391e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 392e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void run() { 393e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mListener.onScanFinished(displays); 394cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 395cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }); 396cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 397cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 398cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void connect(final WifiP2pDevice device) { 399cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mDesiredDevice != null 400cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown && !mDesiredDevice.deviceAddress.equals(device.deviceAddress)) { 401cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (DEBUG) { 402cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.d(TAG, "connect: nothing to do, already connecting to " 403cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + describeWifiP2pDevice(device)); 404cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 405cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return; 406cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 407cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 408cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mConnectedDevice != null 409cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown && !mConnectedDevice.deviceAddress.equals(device.deviceAddress) 410cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown && mDesiredDevice == null) { 411cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (DEBUG) { 412cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.d(TAG, "connect: nothing to do, already connected to " 413cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + describeWifiP2pDevice(device) + " and not part way through " 414cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + "connecting to a different device."); 415cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 4160cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown return; 417cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 418cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 419cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mDesiredDevice = device; 4200cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown mConnectionRetriesLeft = CONNECT_MAX_RETRIES; 421cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown updateConnection(); 422cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 423cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 424cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void disconnect() { 425cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mDesiredDevice = null; 426cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown updateConnection(); 427cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 428cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 4290cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown private void retryConnection() { 43089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown // Cheap hack. Make a new instance of the device object so that we 43189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown // can distinguish it from the previous connection attempt. 43289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown // This will cause us to tear everything down before we try again. 43389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mDesiredDevice = new WifiP2pDevice(mDesiredDevice); 43489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateConnection(); 4350cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown } 4360cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown 437cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown /** 438cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * This function is called repeatedly after each asynchronous operation 439cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * until all preconditions for the connection have been satisfied and the 440cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * connection is established (or not). 441cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown */ 442cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void updateConnection() { 443cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Step 1. Before we try to connect to a new device, tell the system we 444cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // have disconnected from the old one. 445f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown if (mRemoteDisplay != null && mConnectedDevice != mDesiredDevice) { 446f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown Slog.i(TAG, "Stopped listening for RTSP connection on " + mRemoteDisplayInterface 447f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown + " from Wifi display: " + mConnectedDevice.deviceName); 448f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 449f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mRemoteDisplay.dispose(); 450f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mRemoteDisplay = null; 451f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mRemoteDisplayInterface = null; 452f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mRemoteDisplayConnected = false; 453f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mHandler.removeCallbacks(mRtspTimeout); 454f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 455c9bd4ca005768cb30aaaa44c1171e113c13cd107Jeff Brown setRemoteSubmixOn(false); 456c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown unadvertiseDisplay(); 457cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 458cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // continue to next step 459cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 460cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 461cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Step 2. Before we try to connect to a new device, disconnect from the old one. 462cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mConnectedDevice != null && mConnectedDevice != mDesiredDevice) { 463cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Disconnecting from Wifi display: " + mConnectedDevice.deviceName); 464cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 465c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown unadvertiseDisplay(); 466c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown 467cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown final WifiP2pDevice oldDevice = mConnectedDevice; 468cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mWifiP2pManager.removeGroup(mWifiP2pChannel, new ActionListener() { 469cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 470cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onSuccess() { 471cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Disconnected from Wifi display: " + oldDevice.deviceName); 472cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown next(); 473cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 474cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 475cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 476cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onFailure(int reason) { 477cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Failed to disconnect from Wifi display: " 478cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + oldDevice.deviceName + ", reason=" + reason); 479cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown next(); 480cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 481cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 482cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void next() { 483cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mConnectedDevice == oldDevice) { 484cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mConnectedDevice = null; 485cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown updateConnection(); 486cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 487cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 488cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }); 489cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return; // wait for asynchronous callback 490cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 491cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 492cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Step 3. Before we try to connect to a new device, stop trying to connect 493cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // to the old one. 494cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mConnectingDevice != null && mConnectingDevice != mDesiredDevice) { 495cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Canceling connection to Wifi display: " + mConnectingDevice.deviceName); 496cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 497c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown unadvertiseDisplay(); 498cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mHandler.removeCallbacks(mConnectionTimeout); 499cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 500cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown final WifiP2pDevice oldDevice = mConnectingDevice; 501cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mWifiP2pManager.cancelConnect(mWifiP2pChannel, new ActionListener() { 502cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 503cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onSuccess() { 504cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Canceled connection to Wifi display: " + oldDevice.deviceName); 505cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown next(); 506cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 507cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 508cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 509cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onFailure(int reason) { 510cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Failed to cancel connection to Wifi display: " 511cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + oldDevice.deviceName + ", reason=" + reason); 512cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown next(); 513cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 514cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 515cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void next() { 516cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mConnectingDevice == oldDevice) { 517cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mConnectingDevice = null; 518cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown updateConnection(); 519cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 520cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 521cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }); 522cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return; // wait for asynchronous callback 523cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 524cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 525cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Step 4. If we wanted to disconnect, then mission accomplished. 526cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mDesiredDevice == null) { 527c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown unadvertiseDisplay(); 528cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return; // done 529cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 530cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 531cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Step 5. Try to connect. 532cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mConnectedDevice == null && mConnectingDevice == null) { 533cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Connecting to Wifi display: " + mDesiredDevice.deviceName); 534cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 535cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mConnectingDevice = mDesiredDevice; 536cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown WifiP2pConfig config = new WifiP2pConfig(); 537cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown config.deviceAddress = mConnectingDevice.deviceAddress; 538e0c28d5f1358fc2d4c464f910bd04fed4b283fefIrfan Sheriff // Helps with STA & P2P concurrency 53999766cf40ed706aad36032f2107fb0c1e54fc398Irfan Sheriff config.groupOwnerIntent = WifiP2pConfig.MIN_GROUP_OWNER_INTENT; 540cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 541c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown WifiDisplay display = createWifiDisplay(mConnectingDevice); 542c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown advertiseDisplay(display, null, 0, 0, 0); 543e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 544cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown final WifiP2pDevice newDevice = mDesiredDevice; 545cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mWifiP2pManager.connect(mWifiP2pChannel, config, new ActionListener() { 546cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 547cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onSuccess() { 548cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // The connection may not yet be established. We still need to wait 549cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // for WIFI_P2P_CONNECTION_CHANGED_ACTION. However, we might never 550cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // get that broadcast, so we register a timeout. 551cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Initiated connection to Wifi display: " + newDevice.deviceName); 552cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 553cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mHandler.postDelayed(mConnectionTimeout, CONNECTION_TIMEOUT_SECONDS * 1000); 554cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 555cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 556cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 557cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onFailure(int reason) { 558cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mConnectingDevice == newDevice) { 559f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown Slog.i(TAG, "Failed to initiate connection to Wifi display: " 560f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown + newDevice.deviceName + ", reason=" + reason); 561cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mConnectingDevice = null; 5620cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown handleConnectionFailure(false); 563cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 564cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 565cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }); 566cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return; // wait for asynchronous callback 567cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 568cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 569f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown // Step 6. Listen for incoming connections. 570f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown if (mConnectedDevice != null && mRemoteDisplay == null) { 571cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Inet4Address addr = getInterfaceAddress(mConnectedDeviceGroupInfo); 572cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (addr == null) { 573cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Failed to get local interface address for communicating " 574cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + "with Wifi display: " + mConnectedDevice.deviceName); 5750cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown handleConnectionFailure(false); 576cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return; // done 577cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 578cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 579c9bd4ca005768cb30aaaa44c1171e113c13cd107Jeff Brown setRemoteSubmixOn(true); 580c9bd4ca005768cb30aaaa44c1171e113c13cd107Jeff Brown 581f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown final WifiP2pDevice oldDevice = mConnectedDevice; 5820f68d166e6ca45fe27410ea520967275e0733757Jeff Brown final int port = getPortNumber(mConnectedDevice); 583cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown final String iface = addr.getHostAddress() + ":" + port; 584f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mRemoteDisplayInterface = iface; 585cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 586f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown Slog.i(TAG, "Listening for RTSP connection on " + iface 587f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown + " from Wifi display: " + mConnectedDevice.deviceName); 588f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 589f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mRemoteDisplay = RemoteDisplay.listen(iface, new RemoteDisplay.Listener() { 590cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 591c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown public void onDisplayConnected(Surface surface, 592c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown int width, int height, int flags) { 593f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown if (mConnectedDevice == oldDevice && !mRemoteDisplayConnected) { 594f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown Slog.i(TAG, "Opened RTSP connection with Wifi display: " 595f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown + mConnectedDevice.deviceName); 596f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mRemoteDisplayConnected = true; 597f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mHandler.removeCallbacks(mRtspTimeout); 598f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 599f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown final WifiDisplay display = createWifiDisplay(mConnectedDevice); 600c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown advertiseDisplay(display, surface, width, height, flags); 601f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown } 602cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 603f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 604f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown @Override 605f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown public void onDisplayDisconnected() { 606f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown if (mConnectedDevice == oldDevice) { 607f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown Slog.i(TAG, "Closed RTSP connection with Wifi display: " 608f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown + mConnectedDevice.deviceName); 609f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mHandler.removeCallbacks(mRtspTimeout); 610f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown disconnect(); 611f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown } 612f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown } 613f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 614f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown @Override 615f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown public void onDisplayError(int error) { 616f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown if (mConnectedDevice == oldDevice) { 617f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown Slog.i(TAG, "Lost RTSP connection with Wifi display due to error " 618f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown + error + ": " + mConnectedDevice.deviceName); 619f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mHandler.removeCallbacks(mRtspTimeout); 620f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown handleConnectionFailure(false); 621f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown } 622f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown } 623f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown }, mHandler); 624f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 625f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mHandler.postDelayed(mRtspTimeout, RTSP_TIMEOUT_SECONDS * 1000); 626cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 627cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 628cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 629c9bd4ca005768cb30aaaa44c1171e113c13cd107Jeff Brown private void setRemoteSubmixOn(boolean on) { 630c9bd4ca005768cb30aaaa44c1171e113c13cd107Jeff Brown if (mRemoteSubmixOn != on) { 631c9bd4ca005768cb30aaaa44c1171e113c13cd107Jeff Brown mRemoteSubmixOn = on; 632c9bd4ca005768cb30aaaa44c1171e113c13cd107Jeff Brown mAudioManager.setRemoteSubmixOn(on, REMOTE_SUBMIX_ADDRESS); 633c9bd4ca005768cb30aaaa44c1171e113c13cd107Jeff Brown } 634c9bd4ca005768cb30aaaa44c1171e113c13cd107Jeff Brown } 635c9bd4ca005768cb30aaaa44c1171e113c13cd107Jeff Brown 636cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void handleStateChanged(boolean enabled) { 63789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mWifiP2pEnabled = enabled; 63889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateWfdEnableState(); 639cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 640cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 641cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void handlePeersChanged() { 64256925d65fde7f1ac8676ada6f91d0e604645c0a5Irfan Sheriff // Even if wfd is disabled, it is best to get the latest set of peers to 64356925d65fde7f1ac8676ada6f91d0e604645c0a5Irfan Sheriff // keep in sync with the p2p framework 64456925d65fde7f1ac8676ada6f91d0e604645c0a5Irfan Sheriff requestPeers(); 645cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 646cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 647cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void handleConnectionChanged(NetworkInfo networkInfo) { 648cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mNetworkInfo = networkInfo; 649180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mWfdEnabled && networkInfo.isConnected()) { 650cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mDesiredDevice != null) { 651cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mWifiP2pManager.requestGroupInfo(mWifiP2pChannel, new GroupInfoListener() { 652cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 653cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onGroupInfoAvailable(WifiP2pGroup info) { 654cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (DEBUG) { 655cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.d(TAG, "Received group info: " + describeWifiP2pGroup(info)); 656cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 657cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 658cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mConnectingDevice != null && !info.contains(mConnectingDevice)) { 659cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Aborting connection to Wifi display because " 660cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + "the current P2P group does not contain the device " 66189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown + "we expected to find: " + mConnectingDevice.deviceName 66289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown + ", group info was: " + describeWifiP2pGroup(info)); 6630cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown handleConnectionFailure(false); 664cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return; 665cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 666cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 667cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mDesiredDevice != null && !info.contains(mDesiredDevice)) { 668cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown disconnect(); 669cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return; 670cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 671cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 672cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mConnectingDevice != null && mConnectingDevice == mDesiredDevice) { 6730cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown Slog.i(TAG, "Connected to Wifi display: " 6740cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown + mConnectingDevice.deviceName); 675cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 676cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mHandler.removeCallbacks(mConnectionTimeout); 677cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mConnectedDeviceGroupInfo = info; 678cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mConnectedDevice = mConnectingDevice; 679cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mConnectingDevice = null; 680cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown updateConnection(); 681cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 682cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 683cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }); 684cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 685cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } else { 686cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown disconnect(); 687180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown 688180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown // After disconnection for a group, for some reason we have a tendency 689180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown // to get a peer change notification with an empty list of peers. 690180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown // Perform a fresh scan. 691180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mWfdEnabled) { 692180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown requestPeers(); 693180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown } 694cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 695cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 696cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 697cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final Runnable mConnectionTimeout = new Runnable() { 698cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 699cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void run() { 700cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mConnectingDevice != null && mConnectingDevice == mDesiredDevice) { 701cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Timed out waiting for Wifi display connection after " 702cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + CONNECTION_TIMEOUT_SECONDS + " seconds: " 703cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + mConnectingDevice.deviceName); 7040cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown handleConnectionFailure(true); 705cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 706cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 707cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }; 708cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 709f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown private final Runnable mRtspTimeout = new Runnable() { 710f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown @Override 711f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown public void run() { 712f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown if (mConnectedDevice != null 713f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown && mRemoteDisplay != null && !mRemoteDisplayConnected) { 714f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown Slog.i(TAG, "Timed out waiting for Wifi display RTSP connection after " 715f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown + RTSP_TIMEOUT_SECONDS + " seconds: " 716f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown + mConnectedDevice.deviceName); 717f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown handleConnectionFailure(true); 718f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown } 719f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown } 720f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown }; 721f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 7220cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown private void handleConnectionFailure(boolean timeoutOccurred) { 723f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown Slog.i(TAG, "Wifi display connection failed!"); 7240cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown 725f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown if (mDesiredDevice != null) { 7260cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown if (mConnectionRetriesLeft > 0) { 72789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown final WifiP2pDevice oldDevice = mDesiredDevice; 7280cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown mHandler.postDelayed(new Runnable() { 7290cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown @Override 7300cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown public void run() { 73189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mDesiredDevice == oldDevice && mConnectionRetriesLeft > 0) { 73289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mConnectionRetriesLeft -= 1; 73389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown Slog.i(TAG, "Retrying Wifi display connection. Retries left: " 73489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown + mConnectionRetriesLeft); 73589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown retryConnection(); 73689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 7370cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown } 7380cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown }, timeoutOccurred ? 0 : CONNECT_RETRY_DELAY_MILLIS); 7390cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown } else { 7400cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown disconnect(); 7410cfebf28b15e85a42981a8f9e6a09556bef36ea3Jeff Brown } 742cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 743cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 744cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 745c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown private void advertiseDisplay(final WifiDisplay display, 746c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown final Surface surface, final int width, final int height, final int flags) { 747c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown if (!Objects.equal(mAdvertisedDisplay, display) 748c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown || mAdvertisedDisplaySurface != surface 749c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown || mAdvertisedDisplayWidth != width 750c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown || mAdvertisedDisplayHeight != height 751c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown || mAdvertisedDisplayFlags != flags) { 752c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown final WifiDisplay oldDisplay = mAdvertisedDisplay; 753c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown final Surface oldSurface = mAdvertisedDisplaySurface; 754c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown 755c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown mAdvertisedDisplay = display; 756c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown mAdvertisedDisplaySurface = surface; 757c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown mAdvertisedDisplayWidth = width; 758c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown mAdvertisedDisplayHeight = height; 759c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown mAdvertisedDisplayFlags = flags; 760c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown 761c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown mHandler.post(new Runnable() { 762c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown @Override 763c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown public void run() { 764c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown if (oldSurface != null && surface != oldSurface) { 765c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown mListener.onDisplayDisconnected(); 766c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown } else if (oldDisplay != null && !Objects.equal(display, oldDisplay)) { 767c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown mListener.onDisplayConnectionFailed(); 768c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown } 769c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown 770c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown if (display != null) { 771c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown if (!Objects.equal(display, oldDisplay)) { 772c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown mListener.onDisplayConnecting(display); 773c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown } 774c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown if (surface != null && surface != oldSurface) { 775c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown mListener.onDisplayConnected(display, surface, width, height, flags); 776c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown } 777c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown } 778c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown } 779c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown }); 780c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown } 781c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown } 782c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown 783c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown private void unadvertiseDisplay() { 784c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown advertiseDisplay(null, null, 0, 0, 0); 785c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown } 786c2b9ea624148df80945afad4198fe686a0ab8dcaJeff Brown 787cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private static Inet4Address getInterfaceAddress(WifiP2pGroup info) { 788cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown NetworkInterface iface; 789cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown try { 790cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown iface = NetworkInterface.getByName(info.getInterface()); 791cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } catch (SocketException ex) { 792cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.w(TAG, "Could not obtain address of network interface " 793cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + info.getInterface(), ex); 794cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return null; 795cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 796cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 797cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Enumeration<InetAddress> addrs = iface.getInetAddresses(); 798cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown while (addrs.hasMoreElements()) { 799cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown InetAddress addr = addrs.nextElement(); 800cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (addr instanceof Inet4Address) { 801cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return (Inet4Address)addr; 802cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 803cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 804cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 805cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.w(TAG, "Could not obtain address of network interface " 806cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + info.getInterface() + " because it had no IPv4 addresses."); 807cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return null; 808cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 809cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 8100f68d166e6ca45fe27410ea520967275e0733757Jeff Brown private static int getPortNumber(WifiP2pDevice device) { 8110f68d166e6ca45fe27410ea520967275e0733757Jeff Brown if (device.deviceName.startsWith("DIRECT-") 8120f68d166e6ca45fe27410ea520967275e0733757Jeff Brown && device.deviceName.endsWith("Broadcom")) { 8130f68d166e6ca45fe27410ea520967275e0733757Jeff Brown // These dongles ignore the port we broadcast in our WFD IE. 8140f68d166e6ca45fe27410ea520967275e0733757Jeff Brown return 8554; 8150f68d166e6ca45fe27410ea520967275e0733757Jeff Brown } 8160f68d166e6ca45fe27410ea520967275e0733757Jeff Brown return DEFAULT_CONTROL_PORT; 8170f68d166e6ca45fe27410ea520967275e0733757Jeff Brown } 8180f68d166e6ca45fe27410ea520967275e0733757Jeff Brown 819cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private static boolean isWifiDisplay(WifiP2pDevice device) { 8200f68d166e6ca45fe27410ea520967275e0733757Jeff Brown return device.wfdInfo != null 8210f68d166e6ca45fe27410ea520967275e0733757Jeff Brown && device.wfdInfo.isWfdEnabled() 8220f68d166e6ca45fe27410ea520967275e0733757Jeff Brown && isPrimarySinkDeviceType(device.wfdInfo.getDeviceType()); 8230f68d166e6ca45fe27410ea520967275e0733757Jeff Brown } 8240f68d166e6ca45fe27410ea520967275e0733757Jeff Brown 8250f68d166e6ca45fe27410ea520967275e0733757Jeff Brown private static boolean isPrimarySinkDeviceType(int deviceType) { 8260f68d166e6ca45fe27410ea520967275e0733757Jeff Brown return deviceType == WifiP2pWfdInfo.PRIMARY_SINK 8270f68d166e6ca45fe27410ea520967275e0733757Jeff Brown || deviceType == WifiP2pWfdInfo.SOURCE_OR_PRIMARY_SINK; 828cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 829cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 830cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private static String describeWifiP2pDevice(WifiP2pDevice device) { 831cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return device != null ? device.toString().replace('\n', ',') : "null"; 832cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 833cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 834cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private static String describeWifiP2pGroup(WifiP2pGroup group) { 835cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return group != null ? group.toString().replace('\n', ',') : "null"; 836cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 837cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 838e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private static WifiDisplay createWifiDisplay(WifiP2pDevice device) { 83989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown return new WifiDisplay(device.deviceAddress, device.deviceName, null); 840e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 841e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 842cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final BroadcastReceiver mWifiP2pReceiver = new BroadcastReceiver() { 843cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 844cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onReceive(Context context, Intent intent) { 845cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown final String action = intent.getAction(); 846cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (action.equals(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION)) { 84789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown // This broadcast is sticky so we'll always get the initial Wifi P2P state 84889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown // on startup. 849cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown boolean enabled = (intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE, 850cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown WifiP2pManager.WIFI_P2P_STATE_DISABLED)) == 851cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown WifiP2pManager.WIFI_P2P_STATE_ENABLED; 852cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (DEBUG) { 853cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.d(TAG, "Received WIFI_P2P_STATE_CHANGED_ACTION: enabled=" 854cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + enabled); 855cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 856cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 857cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown handleStateChanged(enabled); 858cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } else if (action.equals(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION)) { 859cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (DEBUG) { 860cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.d(TAG, "Received WIFI_P2P_PEERS_CHANGED_ACTION."); 861cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 862cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 863cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown handlePeersChanged(); 864cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } else if (action.equals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)) { 865cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown NetworkInfo networkInfo = (NetworkInfo)intent.getParcelableExtra( 866cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown WifiP2pManager.EXTRA_NETWORK_INFO); 867cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (DEBUG) { 868cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.d(TAG, "Received WIFI_P2P_CONNECTION_CHANGED_ACTION: networkInfo=" 869cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + networkInfo); 870cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 871cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 872cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown handleConnectionChanged(networkInfo); 873cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 874cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 875cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }; 876cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 877cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown /** 878cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Called on the handler thread when displays are connected or disconnected. 879cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown */ 880cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public interface Listener { 88189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown void onFeatureStateChanged(int featureState); 882e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 883e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown void onScanStarted(); 88489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown void onScanFinished(WifiDisplay[] availableDisplays); 885e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 886e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown void onDisplayConnecting(WifiDisplay display); 887e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown void onDisplayConnectionFailed(); 888f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown void onDisplayConnected(WifiDisplay display, 889f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown Surface surface, int width, int height, int flags); 890cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown void onDisplayDisconnected(); 891cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 892cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown} 893