WifiDisplayAdapter.java revision bc335457462a12434a9df6955de1dd693cdccac7
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 5389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private PersistentDataStore mPersistentDataStore; 5489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 55cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private WifiDisplayController mDisplayController; 56f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown private WifiDisplayDevice mDisplayDevice; 57cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 58e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private WifiDisplayStatus mCurrentStatus; 5989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private int mFeatureState; 60180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown private int mScanState; 61180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown private int mActiveDisplayState; 62180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown private WifiDisplay mActiveDisplay; 6389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private WifiDisplay[] mAvailableDisplays = WifiDisplay.EMPTY_ARRAY; 6489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private WifiDisplay[] mRememberedDisplays = WifiDisplay.EMPTY_ARRAY; 65e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 66e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private boolean mPendingStatusChangeBroadcast; 67e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 68cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public WifiDisplayAdapter(DisplayManagerService.SyncRoot syncRoot, 6989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown Context context, Handler handler, Listener listener, 7089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown PersistentDataStore persistentDataStore) { 71cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super(syncRoot, context, handler, listener, TAG); 7289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mPersistentDataStore = persistentDataStore; 73cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 74cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 75cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 76cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void dumpLocked(PrintWriter pw) { 77cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super.dumpLocked(pw); 78cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 79e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown pw.println("mCurrentStatus=" + getWifiDisplayStatusLocked()); 8089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown pw.println("mFeatureState=" + mFeatureState); 81180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown pw.println("mScanState=" + mScanState); 82180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown pw.println("mActiveDisplayState=" + mActiveDisplayState); 83180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown pw.println("mActiveDisplay=" + mActiveDisplay); 8489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown pw.println("mAvailableDisplays=" + Arrays.toString(mAvailableDisplays)); 8589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown pw.println("mRememberedDisplays=" + Arrays.toString(mRememberedDisplays)); 86e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown pw.println("mPendingStatusChangeBroadcast=" + mPendingStatusChangeBroadcast); 87e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 88cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Try to dump the controller state. 89cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mDisplayController == null) { 90cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mDisplayController=null"); 91cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } else { 92cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mDisplayController:"); 93cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 94cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown ipw.increaseIndent(); 95cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown DumpUtils.dumpAsync(getHandler(), mDisplayController, ipw, 200); 96cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 97cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 98cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 99cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 100cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void registerLocked() { 101cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super.registerLocked(); 102cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 10389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateRememberedDisplaysLocked(); 10489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 105cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown getHandler().post(new Runnable() { 106cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 107cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void run() { 108cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mDisplayController = new WifiDisplayController( 109cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown getContext(), getHandler(), mWifiDisplayListener); 110cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 111cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }); 112cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 113cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 114e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void requestScanLocked() { 115e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getHandler().post(new Runnable() { 116e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 117e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void run() { 118e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mDisplayController != null) { 119e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mDisplayController.requestScan(); 120e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 121e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 122e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }); 123e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 124e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 125bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown public void requestConnectLocked(final String address, final boolean trusted) { 126bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown if (!trusted) { 127bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown synchronized (getSyncRoot()) { 128bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown if (!isRememberedDisplayLocked(address)) { 129bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown Slog.w(TAG, "Ignoring request by an untrusted client to connect to " 130bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown + "an unknown wifi display: " + address); 131bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown return; 132bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown } 133bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown } 134bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown } 135bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown 136e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getHandler().post(new Runnable() { 137e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 138e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void run() { 139e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mDisplayController != null) { 140e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mDisplayController.requestConnect(address); 141e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 142e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 143e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }); 144e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 145e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 146bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown private boolean isRememberedDisplayLocked(String address) { 147bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown for (WifiDisplay display : mRememberedDisplays) { 148bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown if (display.getDeviceAddress().equals(address)) { 149bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown return true; 150bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown } 151bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown } 152bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown return false; 153bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown } 154bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown 155e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void requestDisconnectLocked() { 156e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getHandler().post(new Runnable() { 157e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 158e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void run() { 159e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mDisplayController != null) { 160e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mDisplayController.requestDisconnect(); 161e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 162e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 163e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }); 164e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 165e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 16689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void requestRenameLocked(String address, String alias) { 16789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (alias != null) { 16889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown alias = alias.trim(); 16989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (alias.isEmpty()) { 17089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown alias = null; 17189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 17289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 17389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 17489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mPersistentDataStore.renameWifiDisplay(address, alias)) { 17589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mPersistentDataStore.saveIfNeeded(); 17689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateRememberedDisplaysLocked(); 17789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown scheduleStatusChangedBroadcastLocked(); 17889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 17989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 18089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 18189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void requestForgetLocked(String address) { 18289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mPersistentDataStore.forgetWifiDisplay(address)) { 18389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mPersistentDataStore.saveIfNeeded(); 18489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateRememberedDisplaysLocked(); 18589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown scheduleStatusChangedBroadcastLocked(); 18689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 18789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 18889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mActiveDisplay != null && mActiveDisplay.getDeviceAddress().equals(address)) { 18989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown requestDisconnectLocked(); 19089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 19189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 19289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 193e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public WifiDisplayStatus getWifiDisplayStatusLocked() { 194e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mCurrentStatus == null) { 19589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mCurrentStatus = new WifiDisplayStatus( 19689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mFeatureState, mScanState, mActiveDisplayState, 19789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mActiveDisplay, mAvailableDisplays, mRememberedDisplays); 198e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 199e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown return mCurrentStatus; 200e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 201cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 20289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private void updateRememberedDisplaysLocked() { 20389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mRememberedDisplays = mPersistentDataStore.getRememberedWifiDisplays(); 20489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mActiveDisplay = mPersistentDataStore.applyWifiDisplayAlias(mActiveDisplay); 20589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mAvailableDisplays = mPersistentDataStore.applyWifiDisplayAliases(mAvailableDisplays); 20689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 20789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 208f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown private void handleConnectLocked(WifiDisplay display, 209f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown Surface surface, int width, int height, int flags) { 210e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown handleDisconnectLocked(); 211e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 21289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mPersistentDataStore.rememberWifiDisplay(display)) { 21389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mPersistentDataStore.saveIfNeeded(); 21489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateRememberedDisplaysLocked(); 21589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown scheduleStatusChangedBroadcastLocked(); 21689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 21789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 218f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown int deviceFlags = 0; 219f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown if ((flags & RemoteDisplay.DISPLAY_FLAG_SECURE) != 0) { 220c5df37c285221d0fb113f55b9e78b35632241d3fJeff Brown deviceFlags |= DisplayDeviceInfo.FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT; 221f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown } 222f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 223f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown float refreshRate = 60.0f; // TODO: get this for real 224f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 22589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown String name = display.getFriendlyDisplayName(); 226f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown IBinder displayToken = Surface.createDisplay(name); 227f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mDisplayDevice = new WifiDisplayDevice(displayToken, name, width, height, 228f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown refreshRate, deviceFlags, surface); 229f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_ADDED); 230cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 231cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 232e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private void handleDisconnectLocked() { 233f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown if (mDisplayDevice != null) { 234f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mDisplayDevice.clearSurfaceLocked(); 235f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_REMOVED); 236f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mDisplayDevice = null; 237cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 238cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 239cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 240e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private void scheduleStatusChangedBroadcastLocked() { 24189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mCurrentStatus = null; 242e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (!mPendingStatusChangeBroadcast) { 243e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mPendingStatusChangeBroadcast = true; 244e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getHandler().post(mStatusChangeBroadcast); 245e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 246e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 247e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 248e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private final Runnable mStatusChangeBroadcast = new Runnable() { 249e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 250e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void run() { 251e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown final Intent intent; 252e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 253e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (!mPendingStatusChangeBroadcast) { 254e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown return; 255e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 256e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 257e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mPendingStatusChangeBroadcast = false; 258e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown intent = new Intent(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED); 259e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 260e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown intent.putExtra(DisplayManager.EXTRA_WIFI_DISPLAY_STATUS, 261e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getWifiDisplayStatusLocked()); 262e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 263e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 264bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown // Send protected broadcast about wifi display status to registered receivers. 265bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown getContext().sendBroadcast(intent); 266e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 267e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }; 268e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 269cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final WifiDisplayController.Listener mWifiDisplayListener = 270cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown new WifiDisplayController.Listener() { 271cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 27289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void onFeatureStateChanged(int featureState) { 273e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 27489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mFeatureState != featureState) { 27589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mFeatureState = featureState; 276e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 277e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 278e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 279e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 280e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 281e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 282e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onScanStarted() { 283e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 284180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mScanState != WifiDisplayStatus.SCAN_STATE_SCANNING) { 285180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mScanState = WifiDisplayStatus.SCAN_STATE_SCANNING; 286e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 287e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 288e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 289e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 290e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 29189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void onScanFinished(WifiDisplay[] availableDisplays) { 292e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 29389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown availableDisplays = mPersistentDataStore.applyWifiDisplayAliases( 29489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown availableDisplays); 29589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 296180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mScanState != WifiDisplayStatus.SCAN_STATE_NOT_SCANNING 29789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown || !Arrays.equals(mAvailableDisplays, availableDisplays)) { 298180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mScanState = WifiDisplayStatus.SCAN_STATE_NOT_SCANNING; 29989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mAvailableDisplays = availableDisplays; 300e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 301e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 302e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 303e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 304e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 305e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 306e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onDisplayConnecting(WifiDisplay display) { 307e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 30889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown display = mPersistentDataStore.applyWifiDisplayAlias(display); 30989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 310180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTING 311180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay == null 312180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || !mActiveDisplay.equals(display)) { 313180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTING; 314180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = display; 315e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 316e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 317e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 318e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 319e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 320e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 321e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onDisplayConnectionFailed() { 322e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 323180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED 324180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay != null) { 325180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED; 326180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = null; 327e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 328e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 329e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 330e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 331e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 332e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 333f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown public void onDisplayConnected(WifiDisplay display, Surface surface, 334f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown int width, int height, int flags) { 335cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown synchronized (getSyncRoot()) { 33689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown display = mPersistentDataStore.applyWifiDisplayAlias(display); 337f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown handleConnectLocked(display, surface, width, height, flags); 338e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 339180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTED 340180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay == null 341180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || !mActiveDisplay.equals(display)) { 342180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTED; 343180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = display; 344e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 345e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 346cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 347cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 348cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 349cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 350cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onDisplayDisconnected() { 351cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Stop listening. 352cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown synchronized (getSyncRoot()) { 353e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown handleDisconnectLocked(); 354e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 355180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED 356180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay != null) { 357180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED; 358180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = null; 359e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 360e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 361cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 362cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 363cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }; 364cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 365cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final class WifiDisplayDevice extends DisplayDevice { 366cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final String mName; 367cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final int mWidth; 368cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final int mHeight; 369cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final float mRefreshRate; 370cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final int mFlags; 371cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 372cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private Surface mSurface; 373cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private DisplayDeviceInfo mInfo; 374cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 375cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public WifiDisplayDevice(IBinder displayToken, String name, 376cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown int width, int height, float refreshRate, int flags, 377cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Surface surface) { 378cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super(WifiDisplayAdapter.this, displayToken); 379cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mName = name; 380cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mWidth = width; 381cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mHeight = height; 382cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mRefreshRate = refreshRate; 383cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mFlags = flags; 384cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mSurface = surface; 385cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 386cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 387cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void clearSurfaceLocked() { 388cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mSurface = null; 389cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown sendTraversalRequestLocked(); 390cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 391cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 392cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 393cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void performTraversalInTransactionLocked() { 394cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown setSurfaceInTransactionLocked(mSurface); 395cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 396cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 397cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 398cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public DisplayDeviceInfo getDisplayDeviceInfoLocked() { 399cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mInfo == null) { 400cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo = new DisplayDeviceInfo(); 401cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.name = mName; 402cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.width = mWidth; 403cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.height = mHeight; 404cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.refreshRate = mRefreshRate; 405cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.flags = mFlags; 406d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL; 407cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.setAssumedDensityForExternalDisplay(mWidth, mHeight); 408cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 409cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return mInfo; 410cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 411cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 412cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown} 413