WifiDisplayAdapter.java revision 89d5546d7fd3a3bb19820c42e8b4527013dd6545
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.view.Surface; 31cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 32cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport java.io.PrintWriter; 33e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brownimport java.util.Arrays; 34cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 35cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown/** 36cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Connects to Wifi displays that implement the Miracast protocol. 37cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * <p> 38cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * The Wifi display protocol relies on Wifi direct for discovering and pairing 39cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * with the display. Once connected, the Media Server opens an RTSP socket and accepts 40cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * a connection from the display. After session negotiation, the Media Server 41cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * streams encoded buffers to the display. 42cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * </p><p> 43cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * This class is responsible for connecting to Wifi displays and mediating 44cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * the interactions between Media Server, Surface Flinger and the Display Manager Service. 45cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * </p><p> 46cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock. 47cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * </p> 48cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown */ 49cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownfinal class WifiDisplayAdapter extends DisplayAdapter { 50cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private static final String TAG = "WifiDisplayAdapter"; 51cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 5289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private PersistentDataStore mPersistentDataStore; 5389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 54cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private WifiDisplayController mDisplayController; 55f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown private WifiDisplayDevice mDisplayDevice; 56cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 57e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private WifiDisplayStatus mCurrentStatus; 5889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private int mFeatureState; 59180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown private int mScanState; 60180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown private int mActiveDisplayState; 61180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown private WifiDisplay mActiveDisplay; 6289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private WifiDisplay[] mAvailableDisplays = WifiDisplay.EMPTY_ARRAY; 6389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private WifiDisplay[] mRememberedDisplays = WifiDisplay.EMPTY_ARRAY; 64e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 65e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private boolean mPendingStatusChangeBroadcast; 66e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 67cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public WifiDisplayAdapter(DisplayManagerService.SyncRoot syncRoot, 6889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown Context context, Handler handler, Listener listener, 6989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown PersistentDataStore persistentDataStore) { 70cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super(syncRoot, context, handler, listener, TAG); 7189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mPersistentDataStore = persistentDataStore; 72cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 73cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 74cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 75cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void dumpLocked(PrintWriter pw) { 76cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super.dumpLocked(pw); 77cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 78e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown pw.println("mCurrentStatus=" + getWifiDisplayStatusLocked()); 7989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown pw.println("mFeatureState=" + mFeatureState); 80180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown pw.println("mScanState=" + mScanState); 81180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown pw.println("mActiveDisplayState=" + mActiveDisplayState); 82180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown pw.println("mActiveDisplay=" + mActiveDisplay); 8389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown pw.println("mAvailableDisplays=" + Arrays.toString(mAvailableDisplays)); 8489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown pw.println("mRememberedDisplays=" + Arrays.toString(mRememberedDisplays)); 85e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown pw.println("mPendingStatusChangeBroadcast=" + mPendingStatusChangeBroadcast); 86e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 87cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Try to dump the controller state. 88cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mDisplayController == null) { 89cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mDisplayController=null"); 90cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } else { 91cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mDisplayController:"); 92cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 93cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown ipw.increaseIndent(); 94cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown DumpUtils.dumpAsync(getHandler(), mDisplayController, ipw, 200); 95cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 96cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 97cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 98cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 99cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void registerLocked() { 100cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super.registerLocked(); 101cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 10289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateRememberedDisplaysLocked(); 10389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff 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 14689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void requestRenameLocked(String address, String alias) { 14789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (alias != null) { 14889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown alias = alias.trim(); 14989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (alias.isEmpty()) { 15089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown alias = null; 15189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 15289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 15389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 15489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mPersistentDataStore.renameWifiDisplay(address, alias)) { 15589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mPersistentDataStore.saveIfNeeded(); 15689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateRememberedDisplaysLocked(); 15789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown scheduleStatusChangedBroadcastLocked(); 15889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 15989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 16089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 16189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void requestForgetLocked(String address) { 16289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mPersistentDataStore.forgetWifiDisplay(address)) { 16389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mPersistentDataStore.saveIfNeeded(); 16489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateRememberedDisplaysLocked(); 16589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown scheduleStatusChangedBroadcastLocked(); 16689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 16789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 16889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mActiveDisplay != null && mActiveDisplay.getDeviceAddress().equals(address)) { 16989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown requestDisconnectLocked(); 17089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 17189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 17289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 173e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public WifiDisplayStatus getWifiDisplayStatusLocked() { 174e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mCurrentStatus == null) { 17589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mCurrentStatus = new WifiDisplayStatus( 17689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mFeatureState, mScanState, mActiveDisplayState, 17789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mActiveDisplay, mAvailableDisplays, mRememberedDisplays); 178e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 179e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown return mCurrentStatus; 180e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 181cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 18289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private void updateRememberedDisplaysLocked() { 18389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mRememberedDisplays = mPersistentDataStore.getRememberedWifiDisplays(); 18489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mActiveDisplay = mPersistentDataStore.applyWifiDisplayAlias(mActiveDisplay); 18589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mAvailableDisplays = mPersistentDataStore.applyWifiDisplayAliases(mAvailableDisplays); 18689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 18789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 188f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown private void handleConnectLocked(WifiDisplay display, 189f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown Surface surface, int width, int height, int flags) { 190e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown handleDisconnectLocked(); 191e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 19289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mPersistentDataStore.rememberWifiDisplay(display)) { 19389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mPersistentDataStore.saveIfNeeded(); 19489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateRememberedDisplaysLocked(); 19589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown scheduleStatusChangedBroadcastLocked(); 19689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 19789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 198f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown int deviceFlags = 0; 199f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown if ((flags & RemoteDisplay.DISPLAY_FLAG_SECURE) != 0) { 200c5df37c285221d0fb113f55b9e78b35632241d3fJeff Brown deviceFlags |= DisplayDeviceInfo.FLAG_SUPPORTS_SECURE_VIDEO_OUTPUT; 201f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown } 202f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 203f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown float refreshRate = 60.0f; // TODO: get this for real 204f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 20589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown String name = display.getFriendlyDisplayName(); 206f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown IBinder displayToken = Surface.createDisplay(name); 207f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mDisplayDevice = new WifiDisplayDevice(displayToken, name, width, height, 208f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown refreshRate, deviceFlags, surface); 209f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_ADDED); 210cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 211cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 212e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private void handleDisconnectLocked() { 213f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown if (mDisplayDevice != null) { 214f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mDisplayDevice.clearSurfaceLocked(); 215f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_REMOVED); 216f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mDisplayDevice = null; 217cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 218cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 219cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 220e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private void scheduleStatusChangedBroadcastLocked() { 22189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mCurrentStatus = null; 222e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (!mPendingStatusChangeBroadcast) { 223e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mPendingStatusChangeBroadcast = true; 224e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getHandler().post(mStatusChangeBroadcast); 225e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 226e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 227e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 228e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private final Runnable mStatusChangeBroadcast = new Runnable() { 229e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 230e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void run() { 231e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown final Intent intent; 232e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 233e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (!mPendingStatusChangeBroadcast) { 234e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown return; 235e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 236e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 237e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mPendingStatusChangeBroadcast = false; 238e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown intent = new Intent(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED); 239e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 240e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown intent.putExtra(DisplayManager.EXTRA_WIFI_DISPLAY_STATUS, 241e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getWifiDisplayStatusLocked()); 242e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 243e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 244e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown // Send protected broadcast about wifi display status to receivers that 245e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown // have the required permission. 246e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getContext().sendBroadcast(intent, 247e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown android.Manifest.permission.CONFIGURE_WIFI_DISPLAY); 248e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 249e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }; 250e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 251cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final WifiDisplayController.Listener mWifiDisplayListener = 252cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown new WifiDisplayController.Listener() { 253cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 25489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void onFeatureStateChanged(int featureState) { 255e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 25689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mFeatureState != featureState) { 25789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mFeatureState = featureState; 258e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 259e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 260e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 261e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 262e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 263e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 264e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onScanStarted() { 265e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 266180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mScanState != WifiDisplayStatus.SCAN_STATE_SCANNING) { 267180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mScanState = WifiDisplayStatus.SCAN_STATE_SCANNING; 268e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 269e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 270e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 271e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 272e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 27389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void onScanFinished(WifiDisplay[] availableDisplays) { 274e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 27589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown availableDisplays = mPersistentDataStore.applyWifiDisplayAliases( 27689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown availableDisplays); 27789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 278180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mScanState != WifiDisplayStatus.SCAN_STATE_NOT_SCANNING 27989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown || !Arrays.equals(mAvailableDisplays, availableDisplays)) { 280180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mScanState = WifiDisplayStatus.SCAN_STATE_NOT_SCANNING; 28189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mAvailableDisplays = availableDisplays; 282e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 283e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 284e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 285e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 286e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 287e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 288e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onDisplayConnecting(WifiDisplay display) { 289e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 29089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown display = mPersistentDataStore.applyWifiDisplayAlias(display); 29189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 292180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTING 293180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay == null 294180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || !mActiveDisplay.equals(display)) { 295180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTING; 296180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = display; 297e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 298e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 299e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 300e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 301e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 302e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 303e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onDisplayConnectionFailed() { 304e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 305180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED 306180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay != null) { 307180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED; 308180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = null; 309e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 310e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 311e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 312e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 313e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 314e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 315f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown public void onDisplayConnected(WifiDisplay display, Surface surface, 316f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown int width, int height, int flags) { 317cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown synchronized (getSyncRoot()) { 31889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown display = mPersistentDataStore.applyWifiDisplayAlias(display); 319f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown handleConnectLocked(display, surface, width, height, flags); 320e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 321180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTED 322180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay == null 323180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || !mActiveDisplay.equals(display)) { 324180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTED; 325180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = display; 326e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 327e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 328cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 329cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 330cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 331cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 332cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onDisplayDisconnected() { 333cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Stop listening. 334cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown synchronized (getSyncRoot()) { 335e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown handleDisconnectLocked(); 336e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 337180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED 338180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay != null) { 339180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED; 340180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = null; 341e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 342e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 343cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 344cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 345cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }; 346cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 347cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final class WifiDisplayDevice extends DisplayDevice { 348cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final String mName; 349cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final int mWidth; 350cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final int mHeight; 351cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final float mRefreshRate; 352cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final int mFlags; 353cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 354cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private Surface mSurface; 355cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private DisplayDeviceInfo mInfo; 356cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 357cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public WifiDisplayDevice(IBinder displayToken, String name, 358cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown int width, int height, float refreshRate, int flags, 359cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Surface surface) { 360cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super(WifiDisplayAdapter.this, displayToken); 361cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mName = name; 362cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mWidth = width; 363cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mHeight = height; 364cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mRefreshRate = refreshRate; 365cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mFlags = flags; 366cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mSurface = surface; 367cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 368cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 369cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void clearSurfaceLocked() { 370cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mSurface = null; 371cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown sendTraversalRequestLocked(); 372cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 373cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 374cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 375cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void performTraversalInTransactionLocked() { 376cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown setSurfaceInTransactionLocked(mSurface); 377cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 378cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 379cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 380cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public DisplayDeviceInfo getDisplayDeviceInfoLocked() { 381cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mInfo == null) { 382cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo = new DisplayDeviceInfo(); 383cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.name = mName; 384cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.width = mWidth; 385cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.height = mHeight; 386cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.refreshRate = mRefreshRate; 387cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.flags = mFlags; 388d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL; 389cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.setAssumedDensityForExternalDisplay(mWidth, mHeight); 390cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 391cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return mInfo; 392cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 393cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 394cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown} 395