WifiDisplayAdapter.java revision 77aebfdbae489c3712ae3f9bca29d01fb1f09dc2
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; 30bc335457462a12434a9df6955de1dd693cdccac7Jeff 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 5377aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown private final PersistentDataStore mPersistentDataStore; 5477aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown private final boolean mSupportsProtectedBuffers; 5589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 56cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private WifiDisplayController mDisplayController; 57f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown private WifiDisplayDevice mDisplayDevice; 58cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 59e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private WifiDisplayStatus mCurrentStatus; 6089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private int mFeatureState; 61180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown private int mScanState; 62180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown private int mActiveDisplayState; 63180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown private WifiDisplay mActiveDisplay; 6489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private WifiDisplay[] mAvailableDisplays = WifiDisplay.EMPTY_ARRAY; 6589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private WifiDisplay[] mRememberedDisplays = WifiDisplay.EMPTY_ARRAY; 66e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 67e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private boolean mPendingStatusChangeBroadcast; 68e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 69cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public WifiDisplayAdapter(DisplayManagerService.SyncRoot syncRoot, 7089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown Context context, Handler handler, Listener listener, 7189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown PersistentDataStore persistentDataStore) { 72cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super(syncRoot, context, handler, listener, TAG); 7389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mPersistentDataStore = persistentDataStore; 7477aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown mSupportsProtectedBuffers = context.getResources().getBoolean( 7577aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown com.android.internal.R.bool.config_wifiDisplaySupportsProtectedBuffers); 76cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 77cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 78cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 79cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void dumpLocked(PrintWriter pw) { 80cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super.dumpLocked(pw); 81cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 82e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown pw.println("mCurrentStatus=" + getWifiDisplayStatusLocked()); 8389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown pw.println("mFeatureState=" + mFeatureState); 84180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown pw.println("mScanState=" + mScanState); 85180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown pw.println("mActiveDisplayState=" + mActiveDisplayState); 86180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown pw.println("mActiveDisplay=" + mActiveDisplay); 8789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown pw.println("mAvailableDisplays=" + Arrays.toString(mAvailableDisplays)); 8889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown pw.println("mRememberedDisplays=" + Arrays.toString(mRememberedDisplays)); 89e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown pw.println("mPendingStatusChangeBroadcast=" + mPendingStatusChangeBroadcast); 9077aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown pw.println("mSupportsProtectedBuffers=" + mSupportsProtectedBuffers); 91e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 92cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Try to dump the controller state. 93cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mDisplayController == null) { 94cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mDisplayController=null"); 95cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } else { 96cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mDisplayController:"); 97cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 98cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown ipw.increaseIndent(); 99cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown DumpUtils.dumpAsync(getHandler(), mDisplayController, ipw, 200); 100cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 101cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 102cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 103cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 104cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void registerLocked() { 105cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super.registerLocked(); 106cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 10789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateRememberedDisplaysLocked(); 10889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 109cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown getHandler().post(new Runnable() { 110cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 111cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void run() { 112cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mDisplayController = new WifiDisplayController( 113cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown getContext(), getHandler(), mWifiDisplayListener); 114cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 115cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }); 116cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 117cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 118e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void requestScanLocked() { 119e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getHandler().post(new Runnable() { 120e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 121e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void run() { 122e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mDisplayController != null) { 123e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mDisplayController.requestScan(); 124e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 125e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 126e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }); 127e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 128e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 129bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown public void requestConnectLocked(final String address, final boolean trusted) { 130bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown if (!trusted) { 131bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown synchronized (getSyncRoot()) { 132bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown if (!isRememberedDisplayLocked(address)) { 133bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown Slog.w(TAG, "Ignoring request by an untrusted client to connect to " 134bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown + "an unknown wifi display: " + address); 135bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown return; 136bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown } 137bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown } 138bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown } 139bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown 140e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getHandler().post(new Runnable() { 141e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 142e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void run() { 143e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mDisplayController != null) { 144e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mDisplayController.requestConnect(address); 145e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 146e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 147e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }); 148e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 149e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 150bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown private boolean isRememberedDisplayLocked(String address) { 151bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown for (WifiDisplay display : mRememberedDisplays) { 152bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown if (display.getDeviceAddress().equals(address)) { 153bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown return true; 154bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown } 155bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown } 156bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown return false; 157bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown } 158bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown 159e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void requestDisconnectLocked() { 160e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getHandler().post(new Runnable() { 161e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 162e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void run() { 163e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mDisplayController != null) { 164e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mDisplayController.requestDisconnect(); 165e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 166e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 167e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }); 168e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 169e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 17089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void requestRenameLocked(String address, String alias) { 17189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (alias != null) { 17289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown alias = alias.trim(); 17389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (alias.isEmpty()) { 17489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown alias = null; 17589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 17689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 17789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 17889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mPersistentDataStore.renameWifiDisplay(address, alias)) { 17989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mPersistentDataStore.saveIfNeeded(); 18089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateRememberedDisplaysLocked(); 18189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown scheduleStatusChangedBroadcastLocked(); 18289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 18389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 18489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 18589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void requestForgetLocked(String address) { 18689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mPersistentDataStore.forgetWifiDisplay(address)) { 18789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mPersistentDataStore.saveIfNeeded(); 18889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateRememberedDisplaysLocked(); 18989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown scheduleStatusChangedBroadcastLocked(); 19089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 19189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 19289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mActiveDisplay != null && mActiveDisplay.getDeviceAddress().equals(address)) { 19389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown requestDisconnectLocked(); 19489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 19589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 19689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 197e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public WifiDisplayStatus getWifiDisplayStatusLocked() { 198e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mCurrentStatus == null) { 19989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mCurrentStatus = new WifiDisplayStatus( 20089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mFeatureState, mScanState, mActiveDisplayState, 20189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mActiveDisplay, mAvailableDisplays, mRememberedDisplays); 202e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 203e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown return mCurrentStatus; 204e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 205cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 20689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private void updateRememberedDisplaysLocked() { 20789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mRememberedDisplays = mPersistentDataStore.getRememberedWifiDisplays(); 20889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mActiveDisplay = mPersistentDataStore.applyWifiDisplayAlias(mActiveDisplay); 20989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mAvailableDisplays = mPersistentDataStore.applyWifiDisplayAliases(mAvailableDisplays); 21089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 21189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 212f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown private void handleConnectLocked(WifiDisplay display, 213f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown Surface surface, int width, int height, int flags) { 214e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown handleDisconnectLocked(); 215e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 21689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mPersistentDataStore.rememberWifiDisplay(display)) { 21789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mPersistentDataStore.saveIfNeeded(); 21889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateRememberedDisplaysLocked(); 21989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown scheduleStatusChangedBroadcastLocked(); 22089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 22189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 222f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown int deviceFlags = 0; 223f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown if ((flags & RemoteDisplay.DISPLAY_FLAG_SECURE) != 0) { 22477aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown deviceFlags |= DisplayDeviceInfo.FLAG_SECURE; 22577aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown } 22677aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown if (mSupportsProtectedBuffers) { 22777aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown deviceFlags |= DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS; 228f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown } 229f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 230f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown float refreshRate = 60.0f; // TODO: get this for real 231f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 23289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown String name = display.getFriendlyDisplayName(); 233f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown IBinder displayToken = Surface.createDisplay(name); 234f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mDisplayDevice = new WifiDisplayDevice(displayToken, name, width, height, 235f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown refreshRate, deviceFlags, surface); 236f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_ADDED); 237cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 238cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 239e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private void handleDisconnectLocked() { 240f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown if (mDisplayDevice != null) { 241f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mDisplayDevice.clearSurfaceLocked(); 242f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_REMOVED); 243f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mDisplayDevice = null; 244cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 245cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 246cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 247e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private void scheduleStatusChangedBroadcastLocked() { 24889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mCurrentStatus = null; 249e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (!mPendingStatusChangeBroadcast) { 250e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mPendingStatusChangeBroadcast = true; 251e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getHandler().post(mStatusChangeBroadcast); 252e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 253e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 254e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 255e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private final Runnable mStatusChangeBroadcast = new Runnable() { 256e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 257e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void run() { 258e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown final Intent intent; 259e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 260e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (!mPendingStatusChangeBroadcast) { 261e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown return; 262e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 263e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 264e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mPendingStatusChangeBroadcast = false; 265e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown intent = new Intent(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED); 266e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 267e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown intent.putExtra(DisplayManager.EXTRA_WIFI_DISPLAY_STATUS, 268e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getWifiDisplayStatusLocked()); 269e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 270e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 271bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown // Send protected broadcast about wifi display status to registered receivers. 272bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown getContext().sendBroadcast(intent); 273e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 274e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }; 275e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 276cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final WifiDisplayController.Listener mWifiDisplayListener = 277cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown new WifiDisplayController.Listener() { 278cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 27989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void onFeatureStateChanged(int featureState) { 280e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 28189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mFeatureState != featureState) { 28289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mFeatureState = featureState; 283e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 284e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 285e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 286e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 287e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 288e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 289e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onScanStarted() { 290e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 291180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mScanState != WifiDisplayStatus.SCAN_STATE_SCANNING) { 292180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mScanState = WifiDisplayStatus.SCAN_STATE_SCANNING; 293e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 294e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 295e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 296e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 297e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 29889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void onScanFinished(WifiDisplay[] availableDisplays) { 299e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 30089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown availableDisplays = mPersistentDataStore.applyWifiDisplayAliases( 30189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown availableDisplays); 30289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 303180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mScanState != WifiDisplayStatus.SCAN_STATE_NOT_SCANNING 30489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown || !Arrays.equals(mAvailableDisplays, availableDisplays)) { 305180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mScanState = WifiDisplayStatus.SCAN_STATE_NOT_SCANNING; 30689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mAvailableDisplays = availableDisplays; 307e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 308e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 309e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 310e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 311e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 312e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 313e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onDisplayConnecting(WifiDisplay display) { 314e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 31589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown display = mPersistentDataStore.applyWifiDisplayAlias(display); 31689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 317180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTING 318180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay == null 319180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || !mActiveDisplay.equals(display)) { 320180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTING; 321180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = display; 322e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 323e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 324e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 325e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 326e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 327e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 328e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onDisplayConnectionFailed() { 329e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 330180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED 331180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay != null) { 332180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED; 333180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = null; 334e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 335e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 336e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 337e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 338e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 339e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 340f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown public void onDisplayConnected(WifiDisplay display, Surface surface, 341f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown int width, int height, int flags) { 342cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown synchronized (getSyncRoot()) { 34389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown display = mPersistentDataStore.applyWifiDisplayAlias(display); 344f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown handleConnectLocked(display, surface, width, height, flags); 345e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 346180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTED 347180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay == null 348180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || !mActiveDisplay.equals(display)) { 349180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTED; 350180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = display; 351e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 352e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 353cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 354cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 355cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 356cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 357cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onDisplayDisconnected() { 358cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Stop listening. 359cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown synchronized (getSyncRoot()) { 360e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown handleDisconnectLocked(); 361e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 362180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED 363180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay != null) { 364180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED; 365180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = null; 366e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 367e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 368cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 369cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 370cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }; 371cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 372cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final class WifiDisplayDevice extends DisplayDevice { 373cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final String mName; 374cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final int mWidth; 375cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final int mHeight; 376cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final float mRefreshRate; 377cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final int mFlags; 378cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 379cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private Surface mSurface; 380cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private DisplayDeviceInfo mInfo; 381cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 382cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public WifiDisplayDevice(IBinder displayToken, String name, 383cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown int width, int height, float refreshRate, int flags, 384cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Surface surface) { 385cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super(WifiDisplayAdapter.this, displayToken); 386cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mName = name; 387cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mWidth = width; 388cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mHeight = height; 389cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mRefreshRate = refreshRate; 390cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mFlags = flags; 391cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mSurface = surface; 392cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 393cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 394cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void clearSurfaceLocked() { 395cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mSurface = null; 396cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown sendTraversalRequestLocked(); 397cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 398cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 399cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 400cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void performTraversalInTransactionLocked() { 401cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown setSurfaceInTransactionLocked(mSurface); 402cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 403cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 404cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 405cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public DisplayDeviceInfo getDisplayDeviceInfoLocked() { 406cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mInfo == null) { 407cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo = new DisplayDeviceInfo(); 408cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.name = mName; 409cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.width = mWidth; 410cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.height = mHeight; 411cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.refreshRate = mRefreshRate; 412cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.flags = mFlags; 413d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL; 414cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.setAssumedDensityForExternalDisplay(mWidth, mHeight); 415cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 416cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return mInfo; 417cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 418cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 419cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown} 420