WifiDisplayAdapter.java revision 180bbc71810496e280e9993177bfeddb3ad1f558
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 Brownimport com.android.internal.util.IndentingPrintWriter; 21cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 22cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.content.Context; 23e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brownimport android.content.Intent; 24e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brownimport android.hardware.display.DisplayManager; 25e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brownimport android.hardware.display.WifiDisplay; 26e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brownimport android.hardware.display.WifiDisplayStatus; 27cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.media.RemoteDisplay; 28cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.os.Handler; 29cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.os.IBinder; 30cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.util.Slog; 31cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.view.Surface; 32cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 33cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport java.io.PrintWriter; 34e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brownimport java.util.Arrays; 35cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 36cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown/** 37cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Connects to Wifi displays that implement the Miracast protocol. 38cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * <p> 39cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * The Wifi display protocol relies on Wifi direct for discovering and pairing 40cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * with the display. Once connected, the Media Server opens an RTSP socket and accepts 41cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * a connection from the display. After session negotiation, the Media Server 42cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * streams encoded buffers to the display. 43cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * </p><p> 44cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * This class is responsible for connecting to Wifi displays and mediating 45cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * the interactions between Media Server, Surface Flinger and the Display Manager Service. 46cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * </p><p> 47cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock. 48cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * </p> 49cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown */ 50cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownfinal class WifiDisplayAdapter extends DisplayAdapter { 51cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private static final String TAG = "WifiDisplayAdapter"; 52cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 53cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private WifiDisplayHandle mDisplayHandle; 54cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private WifiDisplayController mDisplayController; 55cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 56e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private WifiDisplayStatus mCurrentStatus; 57e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private boolean mEnabled; 58180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown private int mScanState; 59180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown private int mActiveDisplayState; 60180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown private WifiDisplay mActiveDisplay; 61e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private WifiDisplay[] mKnownDisplays = WifiDisplay.EMPTY_ARRAY; 62e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 63e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private boolean mPendingStatusChangeBroadcast; 64e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 65cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public WifiDisplayAdapter(DisplayManagerService.SyncRoot syncRoot, 66cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Context context, Handler handler, Listener listener) { 67cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super(syncRoot, context, handler, listener, TAG); 68cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 69cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 70cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 71cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void dumpLocked(PrintWriter pw) { 72cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super.dumpLocked(pw); 73cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 74cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mDisplayHandle == null) { 75cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mDisplayHandle=null"); 76cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } else { 77cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mDisplayHandle:"); 78cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mDisplayHandle.dumpLocked(pw); 79cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 80cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 81e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown pw.println("mCurrentStatus=" + getWifiDisplayStatusLocked()); 82e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown pw.println("mEnabled=" + mEnabled); 83180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown pw.println("mScanState=" + mScanState); 84180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown pw.println("mActiveDisplayState=" + mActiveDisplayState); 85180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown pw.println("mActiveDisplay=" + mActiveDisplay); 86e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown pw.println("mKnownDisplays=" + Arrays.toString(mKnownDisplays)); 87e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown pw.println("mPendingStatusChangeBroadcast=" + mPendingStatusChangeBroadcast); 88e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 89cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Try to dump the controller state. 90cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mDisplayController == null) { 91cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mDisplayController=null"); 92cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } else { 93cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mDisplayController:"); 94cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 95cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown ipw.increaseIndent(); 96cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown DumpUtils.dumpAsync(getHandler(), mDisplayController, ipw, 200); 97cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 98cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 99cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 100cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 101cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void registerLocked() { 102cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super.registerLocked(); 103cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 104cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown getHandler().post(new Runnable() { 105cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 106cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void run() { 107cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mDisplayController = new WifiDisplayController( 108cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown getContext(), getHandler(), mWifiDisplayListener); 109cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 110cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }); 111cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 112cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 113e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void requestScanLocked() { 114e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getHandler().post(new Runnable() { 115e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 116e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void run() { 117e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mDisplayController != null) { 118e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mDisplayController.requestScan(); 119e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 120e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 121e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }); 122e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 123e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 124e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void requestConnectLocked(final String address) { 125e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getHandler().post(new Runnable() { 126e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 127e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void run() { 128e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mDisplayController != null) { 129e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mDisplayController.requestConnect(address); 130e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 131e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 132e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }); 133e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 134e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 135e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void requestDisconnectLocked() { 136e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getHandler().post(new Runnable() { 137e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 138e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void run() { 139e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mDisplayController != null) { 140e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mDisplayController.requestDisconnect(); 141e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 142e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 143e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }); 144e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 145e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 146e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public WifiDisplayStatus getWifiDisplayStatusLocked() { 147e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mCurrentStatus == null) { 148180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mCurrentStatus = new WifiDisplayStatus(mEnabled, mScanState, mActiveDisplayState, 149180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay, mKnownDisplays); 150e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 151e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown return mCurrentStatus; 152e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 153cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 154e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private void handleConnectLocked(WifiDisplay display, String iface) { 155e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown handleDisconnectLocked(); 156e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 157e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mDisplayHandle = new WifiDisplayHandle(display.getDeviceName(), iface); 158cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 159cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 160e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private void handleDisconnectLocked() { 161cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mDisplayHandle != null) { 162cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mDisplayHandle.disposeLocked(); 163cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mDisplayHandle = null; 164cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 165cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 166cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 167e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private void scheduleStatusChangedBroadcastLocked() { 168e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (!mPendingStatusChangeBroadcast) { 169e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mPendingStatusChangeBroadcast = true; 170e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getHandler().post(mStatusChangeBroadcast); 171e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 172e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 173e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 174e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private final Runnable mStatusChangeBroadcast = new Runnable() { 175e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 176e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void run() { 177e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown final Intent intent; 178e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 179e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (!mPendingStatusChangeBroadcast) { 180e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown return; 181e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 182e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 183e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mPendingStatusChangeBroadcast = false; 184e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown intent = new Intent(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED); 185e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 186e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown intent.putExtra(DisplayManager.EXTRA_WIFI_DISPLAY_STATUS, 187e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getWifiDisplayStatusLocked()); 188e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 189e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 190e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown // Send protected broadcast about wifi display status to receivers that 191e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown // have the required permission. 192e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getContext().sendBroadcast(intent, 193e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown android.Manifest.permission.CONFIGURE_WIFI_DISPLAY); 194e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 195e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }; 196e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 197cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final WifiDisplayController.Listener mWifiDisplayListener = 198cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown new WifiDisplayController.Listener() { 199cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 200e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onEnablementChanged(boolean enabled) { 201e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 202e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mEnabled != enabled) { 203e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mCurrentStatus = null; 204e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mEnabled = enabled; 205e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 206e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 207e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 208e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 209e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 210e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 211e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onScanStarted() { 212e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 213180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mScanState != WifiDisplayStatus.SCAN_STATE_SCANNING) { 214e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mCurrentStatus = null; 215180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mScanState = WifiDisplayStatus.SCAN_STATE_SCANNING; 216e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 217e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 218e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 219e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 220e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 221e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onScanFinished(WifiDisplay[] knownDisplays) { 222e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 223180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mScanState != WifiDisplayStatus.SCAN_STATE_NOT_SCANNING 224180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || !Arrays.equals(mKnownDisplays, knownDisplays)) { 225e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mCurrentStatus = null; 226180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mScanState = WifiDisplayStatus.SCAN_STATE_NOT_SCANNING; 227e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mKnownDisplays = knownDisplays; 228e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 229e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 230e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 231e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 232e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 233e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 234e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onDisplayConnecting(WifiDisplay display) { 235e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 236180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTING 237180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay == null 238180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || !mActiveDisplay.equals(display)) { 239e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mCurrentStatus = null; 240180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTING; 241180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = display; 242e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 243e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 244e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 245e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 246e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 247e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 248e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onDisplayConnectionFailed() { 249e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 250180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED 251180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay != null) { 252e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mCurrentStatus = null; 253180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED; 254180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = null; 255e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 256e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 257e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 258e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 259e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 260e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 261e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onDisplayConnected(WifiDisplay display, String iface) { 262cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown synchronized (getSyncRoot()) { 263e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown handleConnectLocked(display, iface); 264e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 265180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTED 266180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay == null 267180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || !mActiveDisplay.equals(display)) { 268e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mCurrentStatus = null; 269180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTED; 270180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = display; 271e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 272e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 273cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 274cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 275cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 276cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 277cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onDisplayDisconnected() { 278cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Stop listening. 279cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown synchronized (getSyncRoot()) { 280e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown handleDisconnectLocked(); 281e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 282180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED 283180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay != null) { 284e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mCurrentStatus = null; 285180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED; 286180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = null; 287e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 288e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 289cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 290cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 291cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }; 292cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 293cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final class WifiDisplayDevice extends DisplayDevice { 294cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final String mName; 295cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final int mWidth; 296cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final int mHeight; 297cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final float mRefreshRate; 298cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final int mFlags; 299cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 300cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private Surface mSurface; 301cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private DisplayDeviceInfo mInfo; 302cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 303cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public WifiDisplayDevice(IBinder displayToken, String name, 304cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown int width, int height, float refreshRate, int flags, 305cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Surface surface) { 306cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super(WifiDisplayAdapter.this, displayToken); 307cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mName = name; 308cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mWidth = width; 309cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mHeight = height; 310cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mRefreshRate = refreshRate; 311cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mFlags = flags; 312cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mSurface = surface; 313cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 314cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 315cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void clearSurfaceLocked() { 316cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mSurface = null; 317cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown sendTraversalRequestLocked(); 318cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 319cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 320cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 321cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void performTraversalInTransactionLocked() { 322cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown setSurfaceInTransactionLocked(mSurface); 323cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 324cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 325cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 326cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public DisplayDeviceInfo getDisplayDeviceInfoLocked() { 327cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mInfo == null) { 328cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo = new DisplayDeviceInfo(); 329cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.name = mName; 330cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.width = mWidth; 331cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.height = mHeight; 332cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.refreshRate = mRefreshRate; 333cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.flags = mFlags; 334d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL; 335cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.setAssumedDensityForExternalDisplay(mWidth, mHeight); 336cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 337cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return mInfo; 338cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 339cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 340cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 341cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final class WifiDisplayHandle implements RemoteDisplay.Listener { 342cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final String mName; 343cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final String mIface; 344cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final RemoteDisplay mRemoteDisplay; 345cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 346cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private WifiDisplayDevice mDevice; 347cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private int mLastError; 348cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 349cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public WifiDisplayHandle(String name, String iface) { 350cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mName = name; 351cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mIface = iface; 352cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mRemoteDisplay = RemoteDisplay.listen(iface, this, getHandler()); 353cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 354cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Listening for Wifi display connections on " + iface 355cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + " from " + mName); 356cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 357cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 358cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void disposeLocked() { 359cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Stopped listening for Wifi display connections on " + mIface 360cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + " from " + mName); 361cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 362cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown removeDisplayLocked(); 363cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mRemoteDisplay.dispose(); 364cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 365cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 366cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void dumpLocked(PrintWriter pw) { 367cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println(" " + mName + ": " + (mDevice != null ? "connected" : "disconnected")); 368cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println(" mIface=" + mIface); 369cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println(" mLastError=" + mLastError); 370cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 371cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 372cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Called on the handler thread. 373cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 374cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onDisplayConnected(Surface surface, int width, int height, int flags) { 375cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown synchronized (getSyncRoot()) { 376cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mLastError = 0; 377cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown removeDisplayLocked(); 378cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown addDisplayLocked(surface, width, height, flags); 379cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 380cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Wifi display connected: " + mName); 381cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 382cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 383cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 384cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Called on the handler thread. 385cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 386cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onDisplayDisconnected() { 387cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown synchronized (getSyncRoot()) { 388cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mLastError = 0; 389cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown removeDisplayLocked(); 390cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 391cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Wifi display disconnected: " + mName); 392cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 393cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 394cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 395cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Called on the handler thread. 396cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 397cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onDisplayError(int error) { 398cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown synchronized (getSyncRoot()) { 399cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mLastError = error; 400cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown removeDisplayLocked(); 401cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 402cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Wifi display disconnected due to error " + error + ": " + mName); 403cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 404cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 405cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 406cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void addDisplayLocked(Surface surface, int width, int height, int flags) { 407cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown int deviceFlags = 0; 408cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if ((flags & RemoteDisplay.DISPLAY_FLAG_SECURE) != 0) { 409cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown deviceFlags |= DisplayDeviceInfo.FLAG_SECURE; 410cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 411cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 412cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown float refreshRate = 60.0f; // TODO: get this for real 413cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 414cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown IBinder displayToken = Surface.createDisplay(mName); 415cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mDevice = new WifiDisplayDevice(displayToken, mName, width, height, 416cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown refreshRate, deviceFlags, surface); 417cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_ADDED); 418cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 419cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 420cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void removeDisplayLocked() { 421cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mDevice != null) { 422cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mDevice.clearSurfaceLocked(); 423cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_REMOVED); 424cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mDevice = null; 425cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 426cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 427cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 428cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown} 429