WifiDisplayAdapter.java revision e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9
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; 58e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private WifiDisplay mConnectedDisplay; 59e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private WifiDisplay[] mKnownDisplays = WifiDisplay.EMPTY_ARRAY; 60e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private boolean mScanInProgress; 61e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private boolean mConnectionInProgress; 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); 83e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown pw.println("mConnectedDisplay=" + mConnectedDisplay); 84e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown pw.println("mKnownDisplays=" + Arrays.toString(mKnownDisplays)); 85e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown pw.println("mScanInProgress=" + mScanInProgress); 86e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown pw.println("mConnectionInProgress=" + mConnectionInProgress); 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) { 148e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mCurrentStatus = new WifiDisplayStatus(mEnabled, 149e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mConnectedDisplay, mKnownDisplays, 150e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mScanInProgress, mConnectionInProgress); 151e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 152e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown return mCurrentStatus; 153e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 154cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 155e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private void handleConnectLocked(WifiDisplay display, String iface) { 156e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown handleDisconnectLocked(); 157e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 158e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mDisplayHandle = new WifiDisplayHandle(display.getDeviceName(), iface); 159cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 160cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 161e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private void handleDisconnectLocked() { 162cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mDisplayHandle != null) { 163cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mDisplayHandle.disposeLocked(); 164cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mDisplayHandle = null; 165cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 166cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 167cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 168e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private void scheduleStatusChangedBroadcastLocked() { 169e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (!mPendingStatusChangeBroadcast) { 170e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mPendingStatusChangeBroadcast = true; 171e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getHandler().post(mStatusChangeBroadcast); 172e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 173e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 174e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 175e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private final Runnable mStatusChangeBroadcast = new Runnable() { 176e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 177e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void run() { 178e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown final Intent intent; 179e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 180e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (!mPendingStatusChangeBroadcast) { 181e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown return; 182e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 183e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 184e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mPendingStatusChangeBroadcast = false; 185e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown intent = new Intent(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED); 186e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 187e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown intent.putExtra(DisplayManager.EXTRA_WIFI_DISPLAY_STATUS, 188e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getWifiDisplayStatusLocked()); 189e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 190e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 191e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown // Send protected broadcast about wifi display status to receivers that 192e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown // have the required permission. 193e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getContext().sendBroadcast(intent, 194e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown android.Manifest.permission.CONFIGURE_WIFI_DISPLAY); 195e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 196e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }; 197e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 198cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final WifiDisplayController.Listener mWifiDisplayListener = 199cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown new WifiDisplayController.Listener() { 200cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 201e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onEnablementChanged(boolean enabled) { 202e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 203e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mEnabled != enabled) { 204e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mCurrentStatus = null; 205e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mEnabled = enabled; 206e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 207e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 208e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 209e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 210e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 211e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 212e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onScanStarted() { 213e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 214e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (!mScanInProgress) { 215e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mCurrentStatus = null; 216e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mScanInProgress = true; 217e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 218e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 219e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 220e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 221e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 222e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onScanFinished(WifiDisplay[] knownDisplays) { 223e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 224e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (!Arrays.equals(mKnownDisplays, knownDisplays) || mScanInProgress) { 225e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mCurrentStatus = null; 226e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mKnownDisplays = knownDisplays; 227e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mScanInProgress = false; 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()) { 236e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (!mConnectionInProgress) { 237e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mCurrentStatus = null; 238e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mConnectionInProgress = true; 239e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 240e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 241e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 242e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 243e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 244e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 245e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onDisplayConnectionFailed() { 246e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 247e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mConnectionInProgress) { 248e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mCurrentStatus = null; 249e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mConnectionInProgress = false; 250e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 251e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 252e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 253e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 254e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 255e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 256e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onDisplayConnected(WifiDisplay display, String iface) { 257cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown synchronized (getSyncRoot()) { 258e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown handleConnectLocked(display, iface); 259e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 260e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mConnectedDisplay == null || !mConnectedDisplay.equals(display) 261e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown || mConnectionInProgress) { 262e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mCurrentStatus = null; 263e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mConnectedDisplay = display; 264e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mConnectionInProgress = false; 265e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 266e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 267cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 268cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 269cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 270cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 271cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onDisplayDisconnected() { 272cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Stop listening. 273cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown synchronized (getSyncRoot()) { 274e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown handleDisconnectLocked(); 275e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 276e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mConnectedDisplay != null || mConnectionInProgress) { 277e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mCurrentStatus = null; 278e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mConnectedDisplay = null; 279e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mConnectionInProgress = false; 280e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 281e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 282cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 283cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 284cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }; 285cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 286cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final class WifiDisplayDevice extends DisplayDevice { 287cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final String mName; 288cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final int mWidth; 289cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final int mHeight; 290cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final float mRefreshRate; 291cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final int mFlags; 292cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 293cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private Surface mSurface; 294cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private DisplayDeviceInfo mInfo; 295cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 296cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public WifiDisplayDevice(IBinder displayToken, String name, 297cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown int width, int height, float refreshRate, int flags, 298cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Surface surface) { 299cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super(WifiDisplayAdapter.this, displayToken); 300cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mName = name; 301cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mWidth = width; 302cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mHeight = height; 303cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mRefreshRate = refreshRate; 304cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mFlags = flags; 305cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mSurface = surface; 306cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 307cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 308cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void clearSurfaceLocked() { 309cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mSurface = null; 310cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown sendTraversalRequestLocked(); 311cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 312cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 313cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 314cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void performTraversalInTransactionLocked() { 315cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown setSurfaceInTransactionLocked(mSurface); 316cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 317cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 318cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 319cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public DisplayDeviceInfo getDisplayDeviceInfoLocked() { 320cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mInfo == null) { 321cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo = new DisplayDeviceInfo(); 322cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.name = mName; 323cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.width = mWidth; 324cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.height = mHeight; 325cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.refreshRate = mRefreshRate; 326cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.flags = mFlags; 327cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.setAssumedDensityForExternalDisplay(mWidth, mHeight); 328cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 329cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return mInfo; 330cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 331cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 332cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 333cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final class WifiDisplayHandle implements RemoteDisplay.Listener { 334cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final String mName; 335cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final String mIface; 336cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final RemoteDisplay mRemoteDisplay; 337cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 338cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private WifiDisplayDevice mDevice; 339cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private int mLastError; 340cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 341cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public WifiDisplayHandle(String name, String iface) { 342cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mName = name; 343cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mIface = iface; 344cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mRemoteDisplay = RemoteDisplay.listen(iface, this, getHandler()); 345cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 346cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Listening for Wifi display connections on " + iface 347cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + " from " + mName); 348cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 349cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 350cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void disposeLocked() { 351cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Stopped listening for Wifi display connections on " + mIface 352cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown + " from " + mName); 353cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 354cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown removeDisplayLocked(); 355cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mRemoteDisplay.dispose(); 356cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 357cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 358cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void dumpLocked(PrintWriter pw) { 359cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println(" " + mName + ": " + (mDevice != null ? "connected" : "disconnected")); 360cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println(" mIface=" + mIface); 361cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println(" mLastError=" + mLastError); 362cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 363cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 364cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Called on the handler thread. 365cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 366cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onDisplayConnected(Surface surface, int width, int height, int flags) { 367cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown synchronized (getSyncRoot()) { 368cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mLastError = 0; 369cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown removeDisplayLocked(); 370cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown addDisplayLocked(surface, width, height, flags); 371cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 372cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Wifi display connected: " + mName); 373cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 374cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 375cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 376cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Called on the handler thread. 377cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 378cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onDisplayDisconnected() { 379cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown synchronized (getSyncRoot()) { 380cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mLastError = 0; 381cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown removeDisplayLocked(); 382cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 383cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Wifi display disconnected: " + mName); 384cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 385cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 386cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 387cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Called on the handler thread. 388cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 389cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onDisplayError(int error) { 390cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown synchronized (getSyncRoot()) { 391cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mLastError = error; 392cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown removeDisplayLocked(); 393cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 394cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Slog.i(TAG, "Wifi display disconnected due to error " + error + ": " + mName); 395cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 396cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 397cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 398cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void addDisplayLocked(Surface surface, int width, int height, int flags) { 399cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown int deviceFlags = 0; 400cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if ((flags & RemoteDisplay.DISPLAY_FLAG_SECURE) != 0) { 401cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown deviceFlags |= DisplayDeviceInfo.FLAG_SECURE; 402cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 403cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 404cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown float refreshRate = 60.0f; // TODO: get this for real 405cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 406cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown IBinder displayToken = Surface.createDisplay(mName); 407cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mDevice = new WifiDisplayDevice(displayToken, mName, width, height, 408cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown refreshRate, deviceFlags, surface); 409cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_ADDED); 410cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 411cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 412cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private void removeDisplayLocked() { 413cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mDevice != null) { 414cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mDevice.clearSurfaceLocked(); 415cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_REMOVED); 416cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mDevice = null; 417cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 418cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 419cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 420cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown} 421