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 19a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brownimport com.android.internal.R; 20cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport com.android.internal.util.DumpUtils; 21cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport com.android.internal.util.IndentingPrintWriter; 22cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 23a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brownimport android.app.Notification; 24a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brownimport android.app.NotificationManager; 25a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brownimport android.app.PendingIntent; 26a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brownimport android.content.BroadcastReceiver; 27cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.content.Context; 28e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brownimport android.content.Intent; 29a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brownimport android.content.IntentFilter; 30a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brownimport android.content.res.Resources; 31e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brownimport android.hardware.display.DisplayManager; 32e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brownimport android.hardware.display.WifiDisplay; 331f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhangimport android.hardware.display.WifiDisplaySessionInfo; 34e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brownimport android.hardware.display.WifiDisplayStatus; 35cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.media.RemoteDisplay; 36cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.os.Handler; 37cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.os.IBinder; 38a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brownimport android.os.Looper; 39a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brownimport android.os.Message; 40a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brownimport android.os.UserHandle; 41a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brownimport android.provider.Settings; 42bc335457462a12434a9df6955de1dd693cdccac7Jeff Brownimport android.util.Slog; 4392130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brownimport android.view.Display; 44cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.view.Surface; 453866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopianimport android.view.SurfaceControl; 46cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 47cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport java.io.PrintWriter; 48e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brownimport java.util.Arrays; 49ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhangimport java.util.List; 50ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhangimport java.util.ArrayList; 51cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 5274da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brownimport libcore.util.Objects; 5374da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown 54cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown/** 55cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Connects to Wifi displays that implement the Miracast protocol. 56cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * <p> 57cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * The Wifi display protocol relies on Wifi direct for discovering and pairing 58cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * with the display. Once connected, the Media Server opens an RTSP socket and accepts 59cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * a connection from the display. After session negotiation, the Media Server 60cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * streams encoded buffers to the display. 61cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * </p><p> 62cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * This class is responsible for connecting to Wifi displays and mediating 63cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * the interactions between Media Server, Surface Flinger and the Display Manager Service. 64cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * </p><p> 65cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock. 66cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * </p> 67cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown */ 68cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownfinal class WifiDisplayAdapter extends DisplayAdapter { 69cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private static final String TAG = "WifiDisplayAdapter"; 70cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 712444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown private static final boolean DEBUG = false; 722444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown 73a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private static final int MSG_SEND_STATUS_CHANGE_BROADCAST = 1; 74a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private static final int MSG_UPDATE_NOTIFICATION = 2; 75a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 76a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private static final String ACTION_DISCONNECT = "android.server.display.wfd.DISCONNECT"; 77a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 78a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private final WifiDisplayHandler mHandler; 7977aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown private final PersistentDataStore mPersistentDataStore; 8077aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown private final boolean mSupportsProtectedBuffers; 81a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private final NotificationManager mNotificationManager; 82a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 8366692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown private PendingIntent mSettingsPendingIntent; 8466692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown private PendingIntent mDisconnectPendingIntent; 8589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 86cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private WifiDisplayController mDisplayController; 87f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown private WifiDisplayDevice mDisplayDevice; 88cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 89e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private WifiDisplayStatus mCurrentStatus; 9089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private int mFeatureState; 91180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown private int mScanState; 92180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown private int mActiveDisplayState; 93180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown private WifiDisplay mActiveDisplay; 94ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang private WifiDisplay[] mDisplays = WifiDisplay.EMPTY_ARRAY; 9589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private WifiDisplay[] mAvailableDisplays = WifiDisplay.EMPTY_ARRAY; 9689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private WifiDisplay[] mRememberedDisplays = WifiDisplay.EMPTY_ARRAY; 971f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang private WifiDisplaySessionInfo mSessionInfo; 98e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 99e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private boolean mPendingStatusChangeBroadcast; 100a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private boolean mPendingNotificationUpdate; 101e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 10266692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown // Called with SyncRoot lock held. 103cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public WifiDisplayAdapter(DisplayManagerService.SyncRoot syncRoot, 10489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown Context context, Handler handler, Listener listener, 10589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown PersistentDataStore persistentDataStore) { 106cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super(syncRoot, context, handler, listener, TAG); 107a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mHandler = new WifiDisplayHandler(handler.getLooper()); 10889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mPersistentDataStore = persistentDataStore; 10977aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown mSupportsProtectedBuffers = context.getResources().getBoolean( 11077aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown com.android.internal.R.bool.config_wifiDisplaySupportsProtectedBuffers); 111a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mNotificationManager = (NotificationManager)context.getSystemService( 112a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown Context.NOTIFICATION_SERVICE); 113cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 114cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 115cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 116cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void dumpLocked(PrintWriter pw) { 117cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super.dumpLocked(pw); 118cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 119e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown pw.println("mCurrentStatus=" + getWifiDisplayStatusLocked()); 12089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown pw.println("mFeatureState=" + mFeatureState); 121180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown pw.println("mScanState=" + mScanState); 122180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown pw.println("mActiveDisplayState=" + mActiveDisplayState); 123180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown pw.println("mActiveDisplay=" + mActiveDisplay); 124ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang pw.println("mDisplays=" + Arrays.toString(mDisplays)); 12589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown pw.println("mAvailableDisplays=" + Arrays.toString(mAvailableDisplays)); 12689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown pw.println("mRememberedDisplays=" + Arrays.toString(mRememberedDisplays)); 127e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown pw.println("mPendingStatusChangeBroadcast=" + mPendingStatusChangeBroadcast); 128a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown pw.println("mPendingNotificationUpdate=" + mPendingNotificationUpdate); 12977aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown pw.println("mSupportsProtectedBuffers=" + mSupportsProtectedBuffers); 130ce468a35b388ca46578934706b38dbae94941643Jeff Brown 131cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Try to dump the controller state. 132cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mDisplayController == null) { 133cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mDisplayController=null"); 134cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } else { 135cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mDisplayController:"); 136cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 137cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown ipw.increaseIndent(); 138cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown DumpUtils.dumpAsync(getHandler(), mDisplayController, ipw, 200); 139cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 140cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 141cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 142cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 143cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void registerLocked() { 144cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super.registerLocked(); 145cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 14689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateRememberedDisplaysLocked(); 14789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 148cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown getHandler().post(new Runnable() { 149cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 150cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void run() { 151cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mDisplayController = new WifiDisplayController( 152cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown getContext(), getHandler(), mWifiDisplayListener); 15366692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown 15466692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, 15566692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown new IntentFilter(ACTION_DISCONNECT), null, mHandler); 156cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 157cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }); 158cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 159cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 160ce468a35b388ca46578934706b38dbae94941643Jeff Brown public void requestStartScanLocked() { 1612444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown if (DEBUG) { 162ce468a35b388ca46578934706b38dbae94941643Jeff Brown Slog.d(TAG, "requestStartScanLocked"); 1632444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown } 1642444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown 165e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getHandler().post(new Runnable() { 166e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 167e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void run() { 168e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mDisplayController != null) { 169ce468a35b388ca46578934706b38dbae94941643Jeff Brown mDisplayController.requestStartScan(); 170e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 171e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 172e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }); 173e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 174e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 175ce468a35b388ca46578934706b38dbae94941643Jeff Brown public void requestStopScanLocked() { 1762444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown if (DEBUG) { 177ce468a35b388ca46578934706b38dbae94941643Jeff Brown Slog.d(TAG, "requestStopScanLocked"); 178bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown } 179bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown 180e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getHandler().post(new Runnable() { 181e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 182e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void run() { 183e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mDisplayController != null) { 184ce468a35b388ca46578934706b38dbae94941643Jeff Brown mDisplayController.requestStopScan(); 185e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 186e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 187e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }); 188e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 189e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 190ce468a35b388ca46578934706b38dbae94941643Jeff Brown public void requestConnectLocked(final String address) { 191ce468a35b388ca46578934706b38dbae94941643Jeff Brown if (DEBUG) { 192ce468a35b388ca46578934706b38dbae94941643Jeff Brown Slog.d(TAG, "requestConnectLocked: address=" + address); 193bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown } 194ce468a35b388ca46578934706b38dbae94941643Jeff Brown 195ce468a35b388ca46578934706b38dbae94941643Jeff Brown getHandler().post(new Runnable() { 196ce468a35b388ca46578934706b38dbae94941643Jeff Brown @Override 197ce468a35b388ca46578934706b38dbae94941643Jeff Brown public void run() { 198ce468a35b388ca46578934706b38dbae94941643Jeff Brown if (mDisplayController != null) { 199ce468a35b388ca46578934706b38dbae94941643Jeff Brown mDisplayController.requestConnect(address); 200ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 201ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 202ce468a35b388ca46578934706b38dbae94941643Jeff Brown }); 203bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown } 204bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown 2051f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang public void requestPauseLocked() { 2061f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang if (DEBUG) { 2071f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang Slog.d(TAG, "requestPauseLocked"); 2081f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 2091f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang 2101f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang getHandler().post(new Runnable() { 2111f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang @Override 2121f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang public void run() { 2131f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang if (mDisplayController != null) { 2141f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang mDisplayController.requestPause(); 2151f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 2161f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 2171f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang }); 2181f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 2191f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang 2201f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang public void requestResumeLocked() { 2211f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang if (DEBUG) { 2221f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang Slog.d(TAG, "requestResumeLocked"); 2231f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 2241f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang 2251f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang getHandler().post(new Runnable() { 2261f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang @Override 2271f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang public void run() { 2281f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang if (mDisplayController != null) { 2291f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang mDisplayController.requestResume(); 2301f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 2311f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 2321f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang }); 2331f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 2341f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang 235e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void requestDisconnectLocked() { 2362444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown if (DEBUG) { 2372444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown Slog.d(TAG, "requestDisconnectedLocked"); 2382444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown } 2392444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown 240e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getHandler().post(new Runnable() { 241e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 242e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void run() { 243e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mDisplayController != null) { 244e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mDisplayController.requestDisconnect(); 245e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 246e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 247e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }); 248e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 249e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 25089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void requestRenameLocked(String address, String alias) { 2512444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown if (DEBUG) { 2522444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown Slog.d(TAG, "requestRenameLocked: address=" + address + ", alias=" + alias); 2532444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown } 2542444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown 25589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (alias != null) { 25689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown alias = alias.trim(); 2572444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown if (alias.isEmpty() || alias.equals(address)) { 25889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown alias = null; 25989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 26089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 26189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 26274da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown WifiDisplay display = mPersistentDataStore.getRememberedWifiDisplay(address); 26374da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown if (display != null && !Objects.equal(display.getDeviceAlias(), alias)) { 264ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang display = new WifiDisplay(address, display.getDeviceName(), alias, 265ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang false, false, false); 26674da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown if (mPersistentDataStore.rememberWifiDisplay(display)) { 26774da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown mPersistentDataStore.saveIfNeeded(); 26874da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown updateRememberedDisplaysLocked(); 26974da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown scheduleStatusChangedBroadcastLocked(); 27074da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 27189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 272ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown 27374da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown if (mActiveDisplay != null && mActiveDisplay.getDeviceAddress().equals(address)) { 27474da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown renameDisplayDeviceLocked(mActiveDisplay.getFriendlyDisplayName()); 275ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown } 27689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 27789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 27889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void requestForgetLocked(String address) { 2792444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown if (DEBUG) { 2802444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown Slog.d(TAG, "requestForgetLocked: address=" + address); 2812444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown } 2822444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown 28389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mPersistentDataStore.forgetWifiDisplay(address)) { 28489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mPersistentDataStore.saveIfNeeded(); 28589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateRememberedDisplaysLocked(); 28689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown scheduleStatusChangedBroadcastLocked(); 28789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 28889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 28989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mActiveDisplay != null && mActiveDisplay.getDeviceAddress().equals(address)) { 29089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown requestDisconnectLocked(); 29189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 29289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 29389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 294e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public WifiDisplayStatus getWifiDisplayStatusLocked() { 295e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mCurrentStatus == null) { 29689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mCurrentStatus = new WifiDisplayStatus( 29789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mFeatureState, mScanState, mActiveDisplayState, 2981f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang mActiveDisplay, mDisplays, mSessionInfo); 299e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 3002444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown 3012444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown if (DEBUG) { 3022444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown Slog.d(TAG, "getWifiDisplayStatusLocked: result=" + mCurrentStatus); 3032444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown } 304e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown return mCurrentStatus; 305e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 306cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 307ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang private void updateDisplaysLocked() { 308ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang List<WifiDisplay> displays = new ArrayList<WifiDisplay>( 309ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang mAvailableDisplays.length + mRememberedDisplays.length); 310ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang boolean[] remembered = new boolean[mAvailableDisplays.length]; 311ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang for (WifiDisplay d : mRememberedDisplays) { 312ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang boolean available = false; 313ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang for (int i = 0; i < mAvailableDisplays.length; i++) { 314ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang if (d.equals(mAvailableDisplays[i])) { 315ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang remembered[i] = available = true; 316ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang break; 317ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang } 318ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang } 319ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang if (!available) { 320ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang displays.add(new WifiDisplay(d.getDeviceAddress(), d.getDeviceName(), 321ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang d.getDeviceAlias(), false, false, true)); 322ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang } 323ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang } 324ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang for (int i = 0; i < mAvailableDisplays.length; i++) { 325ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang WifiDisplay d = mAvailableDisplays[i]; 326ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang displays.add(new WifiDisplay(d.getDeviceAddress(), d.getDeviceName(), 327ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang d.getDeviceAlias(), true, d.canConnect(), remembered[i])); 328ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang } 329ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang mDisplays = displays.toArray(WifiDisplay.EMPTY_ARRAY); 330ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang } 331ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang 33289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private void updateRememberedDisplaysLocked() { 33389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mRememberedDisplays = mPersistentDataStore.getRememberedWifiDisplays(); 33489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mActiveDisplay = mPersistentDataStore.applyWifiDisplayAlias(mActiveDisplay); 33589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mAvailableDisplays = mPersistentDataStore.applyWifiDisplayAliases(mAvailableDisplays); 336ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang updateDisplaysLocked(); 33789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 33889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 33974da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown private void fixRememberedDisplayNamesFromAvailableDisplaysLocked() { 34074da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown // It may happen that a display name has changed since it was remembered. 34174da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown // Consult the list of available displays and update the name if needed. 34274da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown // We don't do anything special for the active display here. The display 34374da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown // controller will send a separate event when it needs to be updates. 34474da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown boolean changed = false; 34574da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown for (int i = 0; i < mRememberedDisplays.length; i++) { 34674da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown WifiDisplay rememberedDisplay = mRememberedDisplays[i]; 34774da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown WifiDisplay availableDisplay = findAvailableDisplayLocked( 34874da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown rememberedDisplay.getDeviceAddress()); 34974da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown if (availableDisplay != null && !rememberedDisplay.equals(availableDisplay)) { 35074da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown if (DEBUG) { 35174da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown Slog.d(TAG, "fixRememberedDisplayNamesFromAvailableDisplaysLocked: " 35274da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown + "updating remembered display to " + availableDisplay); 35374da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 35474da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown mRememberedDisplays[i] = availableDisplay; 35574da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown changed |= mPersistentDataStore.rememberWifiDisplay(availableDisplay); 35674da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 35774da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 35874da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown if (changed) { 35974da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown mPersistentDataStore.saveIfNeeded(); 36074da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 36174da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 36274da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown 36374da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown private WifiDisplay findAvailableDisplayLocked(String address) { 36474da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown for (WifiDisplay display : mAvailableDisplays) { 36574da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown if (display.getDeviceAddress().equals(address)) { 36674da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown return display; 36774da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 36874da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 36974da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown return null; 37074da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 37174da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown 37274da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown private void addDisplayDeviceLocked(WifiDisplay display, 373f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown Surface surface, int width, int height, int flags) { 37474da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown removeDisplayDeviceLocked(); 375e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 37689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mPersistentDataStore.rememberWifiDisplay(display)) { 37789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mPersistentDataStore.saveIfNeeded(); 37889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateRememberedDisplaysLocked(); 37989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown scheduleStatusChangedBroadcastLocked(); 38089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 38189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 382f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown boolean secure = (flags & RemoteDisplay.DISPLAY_FLAG_SECURE) != 0; 3837d00affce6e25b22fd8fc135933b3bf6b547a0dcJeff Brown int deviceFlags = DisplayDeviceInfo.FLAG_PRESENTATION; 384f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown if (secure) { 38577aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown deviceFlags |= DisplayDeviceInfo.FLAG_SECURE; 386f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown if (mSupportsProtectedBuffers) { 387f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown deviceFlags |= DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS; 388f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown } 389f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown } 390f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 391f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown float refreshRate = 60.0f; // TODO: get this for real 392f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 39389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown String name = display.getFriendlyDisplayName(); 39492130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown String address = display.getDeviceAddress(); 3953866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian IBinder displayToken = SurfaceControl.createDisplay(name, secure); 396f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mDisplayDevice = new WifiDisplayDevice(displayToken, name, width, height, 39792130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown refreshRate, deviceFlags, address, surface); 398f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_ADDED); 399cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 400cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 40174da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown private void removeDisplayDeviceLocked() { 402f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown if (mDisplayDevice != null) { 4036a6bc216d15293886ad088bb0ca99aadb7df85dcJesse Hall mDisplayDevice.destroyLocked(); 404f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_REMOVED); 405f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mDisplayDevice = null; 406cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 407cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 408cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 40974da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown private void renameDisplayDeviceLocked(String name) { 41074da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown if (mDisplayDevice != null && !mDisplayDevice.getNameLocked().equals(name)) { 41174da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown mDisplayDevice.setNameLocked(name); 41274da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_CHANGED); 41374da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 41474da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 41574da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown 416e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private void scheduleStatusChangedBroadcastLocked() { 41789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mCurrentStatus = null; 418e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (!mPendingStatusChangeBroadcast) { 419e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mPendingStatusChangeBroadcast = true; 420a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mHandler.sendEmptyMessage(MSG_SEND_STATUS_CHANGE_BROADCAST); 421e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 422e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 423e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 424a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private void scheduleUpdateNotificationLocked() { 425a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown if (!mPendingNotificationUpdate) { 426a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mPendingNotificationUpdate = true; 427a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mHandler.sendEmptyMessage(MSG_UPDATE_NOTIFICATION); 428a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 429a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 430a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 431a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown // Runs on the handler. 432a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private void handleSendStatusChangeBroadcast() { 433a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown final Intent intent; 434a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown synchronized (getSyncRoot()) { 435a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown if (!mPendingStatusChangeBroadcast) { 436a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown return; 437a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 438a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 439a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mPendingStatusChangeBroadcast = false; 440a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown intent = new Intent(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED); 441a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 442a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown intent.putExtra(DisplayManager.EXTRA_WIFI_DISPLAY_STATUS, 443a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown getWifiDisplayStatusLocked()); 444a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 445e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 446a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown // Send protected broadcast about wifi display status to registered receivers. 447a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown getContext().sendBroadcastAsUser(intent, UserHandle.ALL); 448a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 449a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 450a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown // Runs on the handler. 451a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private void handleUpdateNotification() { 452e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown final int state; 453e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown final WifiDisplay display; 454a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown synchronized (getSyncRoot()) { 455a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown if (!mPendingNotificationUpdate) { 456a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown return; 457e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 458e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 459a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mPendingNotificationUpdate = false; 460e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown state = mActiveDisplayState; 461e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown display = mActiveDisplay; 462a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 463a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 46466692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown // Cancel the old notification if there is one. 465a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mNotificationManager.cancelAsUser(null, 466e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown R.string.wifi_display_notification_disconnect, UserHandle.ALL); 467a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 468e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown if (state == WifiDisplayStatus.DISPLAY_STATE_CONNECTING 469e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown || state == WifiDisplayStatus.DISPLAY_STATE_CONNECTED) { 470a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown Context context = getContext(); 471a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 47266692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown // Initialize pending intents for the notification outside of the lock because 47366692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown // creating a pending intent requires a call into the activity manager. 47466692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown if (mSettingsPendingIntent == null) { 47566692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown Intent settingsIntent = new Intent(Settings.ACTION_WIFI_DISPLAY_SETTINGS); 47666692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 47766692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 47866692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown | Intent.FLAG_ACTIVITY_CLEAR_TOP); 47966692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown mSettingsPendingIntent = PendingIntent.getActivityAsUser( 48066692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown context, 0, settingsIntent, 0, null, UserHandle.CURRENT); 48166692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown } 48266692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown 48366692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown if (mDisconnectPendingIntent == null) { 48466692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown Intent disconnectIntent = new Intent(ACTION_DISCONNECT); 48566692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown mDisconnectPendingIntent = PendingIntent.getBroadcastAsUser( 48666692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown context, 0, disconnectIntent, 0, UserHandle.CURRENT); 48766692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown } 48866692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown 48966692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown // Post the notification. 490a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown Resources r = context.getResources(); 491e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown Notification notification; 492e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown if (state == WifiDisplayStatus.DISPLAY_STATE_CONNECTING) { 493e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown notification = new Notification.Builder(context) 494e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown .setContentTitle(r.getString( 495e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown R.string.wifi_display_notification_connecting_title)) 496e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown .setContentText(r.getString( 497e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown R.string.wifi_display_notification_connecting_message, 498e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown display.getFriendlyDisplayName())) 499e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown .setContentIntent(mSettingsPendingIntent) 500e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown .setSmallIcon(R.drawable.ic_notification_cast_connecting) 501e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown .setOngoing(true) 502e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown .addAction(android.R.drawable.ic_menu_close_clear_cancel, 503e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown r.getString(R.string.wifi_display_notification_disconnect), 504e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown mDisconnectPendingIntent) 505e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown .build(); 506e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown } else { 507e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown notification = new Notification.Builder(context) 508e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown .setContentTitle(r.getString( 509e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown R.string.wifi_display_notification_connected_title)) 510e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown .setContentText(r.getString( 511e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown R.string.wifi_display_notification_connected_message, 512e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown display.getFriendlyDisplayName())) 513e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown .setContentIntent(mSettingsPendingIntent) 514e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown .setSmallIcon(R.drawable.ic_notification_cast_on) 515e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown .setOngoing(true) 516e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown .addAction(android.R.drawable.ic_menu_close_clear_cancel, 517e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown r.getString(R.string.wifi_display_notification_disconnect), 518e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown mDisconnectPendingIntent) 519e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown .build(); 520e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown } 521a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mNotificationManager.notifyAsUser(null, 522e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown R.string.wifi_display_notification_disconnect, 523a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown notification, UserHandle.ALL); 524a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 525a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 526a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 527a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 528a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown @Override 529a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown public void onReceive(Context context, Intent intent) { 530a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown if (intent.getAction().equals(ACTION_DISCONNECT)) { 531a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown synchronized (getSyncRoot()) { 532a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown requestDisconnectLocked(); 533a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 534a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 535e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 536e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }; 537e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 538cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final WifiDisplayController.Listener mWifiDisplayListener = 539cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown new WifiDisplayController.Listener() { 540cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 54189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void onFeatureStateChanged(int featureState) { 542e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 54389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mFeatureState != featureState) { 54489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mFeatureState = featureState; 545e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 546e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 547e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 548e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 549e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 550e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 551e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onScanStarted() { 552e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 553180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mScanState != WifiDisplayStatus.SCAN_STATE_SCANNING) { 554180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mScanState = WifiDisplayStatus.SCAN_STATE_SCANNING; 555e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 556e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 557e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 558e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 559e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 5602444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown @Override 561ce468a35b388ca46578934706b38dbae94941643Jeff Brown public void onScanResults(WifiDisplay[] availableDisplays) { 562e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 56389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown availableDisplays = mPersistentDataStore.applyWifiDisplayAliases( 56489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown availableDisplays); 56589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 566ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang boolean changed = !Arrays.equals(mAvailableDisplays, availableDisplays); 567ce468a35b388ca46578934706b38dbae94941643Jeff Brown 568ce468a35b388ca46578934706b38dbae94941643Jeff Brown // Check whether any of the available displays changed canConnect status. 569ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang for (int i = 0; !changed && i<availableDisplays.length; i++) { 570ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang changed = availableDisplays[i].canConnect() 571ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang != mAvailableDisplays[i].canConnect(); 572ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang } 573ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang 574ce468a35b388ca46578934706b38dbae94941643Jeff Brown if (changed) { 57589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mAvailableDisplays = availableDisplays; 57674da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown fixRememberedDisplayNamesFromAvailableDisplaysLocked(); 577ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang updateDisplaysLocked(); 578e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 579e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 580e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 581e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 582e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 583e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 584ce468a35b388ca46578934706b38dbae94941643Jeff Brown public void onScanFinished() { 585ce468a35b388ca46578934706b38dbae94941643Jeff Brown synchronized (getSyncRoot()) { 586ce468a35b388ca46578934706b38dbae94941643Jeff Brown if (mScanState != WifiDisplayStatus.SCAN_STATE_NOT_SCANNING) { 587ce468a35b388ca46578934706b38dbae94941643Jeff Brown mScanState = WifiDisplayStatus.SCAN_STATE_NOT_SCANNING; 588ce468a35b388ca46578934706b38dbae94941643Jeff Brown scheduleStatusChangedBroadcastLocked(); 589ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 590ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 591ce468a35b388ca46578934706b38dbae94941643Jeff Brown } 592ce468a35b388ca46578934706b38dbae94941643Jeff Brown 593ce468a35b388ca46578934706b38dbae94941643Jeff Brown @Override 594e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onDisplayConnecting(WifiDisplay display) { 595e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 59689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown display = mPersistentDataStore.applyWifiDisplayAlias(display); 59789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 598180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTING 599180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay == null 600180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || !mActiveDisplay.equals(display)) { 601180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTING; 602180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = display; 603e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 604e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown scheduleUpdateNotificationLocked(); 605e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 606e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 607e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 608e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 609e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 610e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onDisplayConnectionFailed() { 611e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 612180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED 613180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay != null) { 614180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED; 615180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = null; 616e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 617e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown scheduleUpdateNotificationLocked(); 618e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 619e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 620e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 621e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 622e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 623f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown public void onDisplayConnected(WifiDisplay display, Surface surface, 624f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown int width, int height, int flags) { 625cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown synchronized (getSyncRoot()) { 62689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown display = mPersistentDataStore.applyWifiDisplayAlias(display); 62774da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown addDisplayDeviceLocked(display, surface, width, height, flags); 628e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 629180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTED 630180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay == null 631180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || !mActiveDisplay.equals(display)) { 632180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTED; 633180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = display; 634e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 635e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown scheduleUpdateNotificationLocked(); 636e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 637cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 638cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 639cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 640cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 6411f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang public void onDisplaySessionInfo(WifiDisplaySessionInfo sessionInfo) { 6421f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang synchronized (getSyncRoot()) { 6431f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang mSessionInfo = sessionInfo; 6441f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang scheduleStatusChangedBroadcastLocked(); 6451f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 6461f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang } 6471f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang 6481f3ecaae6303d5ee6c5ca8499262c9962f036365Chong Zhang @Override 64974da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown public void onDisplayChanged(WifiDisplay display) { 65074da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown synchronized (getSyncRoot()) { 65174da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown display = mPersistentDataStore.applyWifiDisplayAlias(display); 65274da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown if (mActiveDisplay != null 65374da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown && mActiveDisplay.hasSameAddress(display) 65474da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown && !mActiveDisplay.equals(display)) { 65574da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown mActiveDisplay = display; 65674da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown renameDisplayDeviceLocked(display.getFriendlyDisplayName()); 65774da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown scheduleStatusChangedBroadcastLocked(); 658e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown scheduleUpdateNotificationLocked(); 65974da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 66074da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 66174da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 66274da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown 66374da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown @Override 664cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onDisplayDisconnected() { 665cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Stop listening. 666cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown synchronized (getSyncRoot()) { 66774da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown removeDisplayDeviceLocked(); 668e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 669180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED 670180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay != null) { 671180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED; 672180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = null; 673e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 674e7ae644522f692c204d0233f91e77c7841bdfe53Jeff Brown scheduleUpdateNotificationLocked(); 675e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 676cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 677cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 678cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }; 679cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 680cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final class WifiDisplayDevice extends DisplayDevice { 681ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown private String mName; 682cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final int mWidth; 683cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final int mHeight; 684cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final float mRefreshRate; 685cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final int mFlags; 68692130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown private final String mAddress; 687cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 688cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private Surface mSurface; 689cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private DisplayDeviceInfo mInfo; 690cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 691cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public WifiDisplayDevice(IBinder displayToken, String name, 69292130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown int width, int height, float refreshRate, int flags, String address, 693cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Surface surface) { 694cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super(WifiDisplayAdapter.this, displayToken); 695cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mName = name; 696cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mWidth = width; 697cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mHeight = height; 698cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mRefreshRate = refreshRate; 699cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mFlags = flags; 70092130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown mAddress = address; 701cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mSurface = surface; 702cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 703cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 7046a6bc216d15293886ad088bb0ca99aadb7df85dcJesse Hall public void destroyLocked() { 7056a6bc216d15293886ad088bb0ca99aadb7df85dcJesse Hall if (mSurface != null) { 7066a6bc216d15293886ad088bb0ca99aadb7df85dcJesse Hall mSurface.release(); 7076a6bc216d15293886ad088bb0ca99aadb7df85dcJesse Hall mSurface = null; 7086a6bc216d15293886ad088bb0ca99aadb7df85dcJesse Hall } 7096a6bc216d15293886ad088bb0ca99aadb7df85dcJesse Hall SurfaceControl.destroyDisplay(getDisplayTokenLocked()); 710cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 711cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 712ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown public void setNameLocked(String name) { 713ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown mName = name; 714ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown mInfo = null; 715ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown } 716ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown 717cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 718cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void performTraversalInTransactionLocked() { 7196a6bc216d15293886ad088bb0ca99aadb7df85dcJesse Hall if (mSurface != null) { 7206a6bc216d15293886ad088bb0ca99aadb7df85dcJesse Hall setSurfaceInTransactionLocked(mSurface); 7216a6bc216d15293886ad088bb0ca99aadb7df85dcJesse Hall } 722cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 723cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 724cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 725cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public DisplayDeviceInfo getDisplayDeviceInfoLocked() { 726cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mInfo == null) { 727cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo = new DisplayDeviceInfo(); 728cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.name = mName; 729cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.width = mWidth; 730cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.height = mHeight; 731cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.refreshRate = mRefreshRate; 732cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.flags = mFlags; 73392130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown mInfo.type = Display.TYPE_WIFI; 73492130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown mInfo.address = mAddress; 735d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL; 736cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.setAssumedDensityForExternalDisplay(mWidth, mHeight); 737cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 738cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return mInfo; 739cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 740cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 741a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 742a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private final class WifiDisplayHandler extends Handler { 743a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown public WifiDisplayHandler(Looper looper) { 744a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown super(looper, null, true /*async*/); 745a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 746a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 747a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown @Override 748a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown public void handleMessage(Message msg) { 749a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown switch (msg.what) { 750a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown case MSG_SEND_STATUS_CHANGE_BROADCAST: 751a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown handleSendStatusChangeBroadcast(); 752a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown break; 753a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 754a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown case MSG_UPDATE_NOTIFICATION: 755a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown handleUpdateNotification(); 756a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown break; 757a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 758a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 759a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 760cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown} 761