WifiDisplayAdapter.java revision ab87a63997a7dc771acfd0dcd7efda990dc3d5fe
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; 33e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brownimport android.hardware.display.WifiDisplayStatus; 34cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.media.RemoteDisplay; 35cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.os.Handler; 36cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.os.IBinder; 37a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brownimport android.os.Looper; 38a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brownimport android.os.Message; 39a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brownimport android.os.UserHandle; 40a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brownimport android.provider.Settings; 41bc335457462a12434a9df6955de1dd693cdccac7Jeff Brownimport android.util.Slog; 4292130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brownimport android.view.Display; 43cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.view.Surface; 443866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopianimport android.view.SurfaceControl; 45cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 46cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport java.io.PrintWriter; 47e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brownimport java.util.Arrays; 48ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhangimport java.util.List; 49ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhangimport java.util.ArrayList; 50cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 5174da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brownimport libcore.util.Objects; 5274da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown 53cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown/** 54cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Connects to Wifi displays that implement the Miracast protocol. 55cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * <p> 56cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * The Wifi display protocol relies on Wifi direct for discovering and pairing 57cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * with the display. Once connected, the Media Server opens an RTSP socket and accepts 58cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * a connection from the display. After session negotiation, the Media Server 59cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * streams encoded buffers to the display. 60cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * </p><p> 61cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * This class is responsible for connecting to Wifi displays and mediating 62cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * the interactions between Media Server, Surface Flinger and the Display Manager Service. 63cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * </p><p> 64cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock. 65cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * </p> 66cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown */ 67cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownfinal class WifiDisplayAdapter extends DisplayAdapter { 68cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private static final String TAG = "WifiDisplayAdapter"; 69cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 702444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown private static final boolean DEBUG = false; 712444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown 72a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private static final int MSG_SEND_STATUS_CHANGE_BROADCAST = 1; 73a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private static final int MSG_UPDATE_NOTIFICATION = 2; 74a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 75a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private static final String ACTION_DISCONNECT = "android.server.display.wfd.DISCONNECT"; 76a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 77a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private final WifiDisplayHandler mHandler; 7877aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown private final PersistentDataStore mPersistentDataStore; 7977aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown private final boolean mSupportsProtectedBuffers; 80a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private final NotificationManager mNotificationManager; 81a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 8266692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown private PendingIntent mSettingsPendingIntent; 8366692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown private PendingIntent mDisconnectPendingIntent; 8489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 85cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private WifiDisplayController mDisplayController; 86f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown private WifiDisplayDevice mDisplayDevice; 87cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 88e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private WifiDisplayStatus mCurrentStatus; 8989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private int mFeatureState; 90180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown private int mScanState; 91180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown private int mActiveDisplayState; 92180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown private WifiDisplay mActiveDisplay; 93ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang private WifiDisplay[] mDisplays = WifiDisplay.EMPTY_ARRAY; 9489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private WifiDisplay[] mAvailableDisplays = WifiDisplay.EMPTY_ARRAY; 9589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private WifiDisplay[] mRememberedDisplays = WifiDisplay.EMPTY_ARRAY; 96e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 97e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private boolean mPendingStatusChangeBroadcast; 98a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private boolean mPendingNotificationUpdate; 99e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 10066692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown // Called with SyncRoot lock held. 101cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public WifiDisplayAdapter(DisplayManagerService.SyncRoot syncRoot, 10289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown Context context, Handler handler, Listener listener, 10389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown PersistentDataStore persistentDataStore) { 104cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super(syncRoot, context, handler, listener, TAG); 105a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mHandler = new WifiDisplayHandler(handler.getLooper()); 10689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mPersistentDataStore = persistentDataStore; 10777aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown mSupportsProtectedBuffers = context.getResources().getBoolean( 10877aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown com.android.internal.R.bool.config_wifiDisplaySupportsProtectedBuffers); 109a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mNotificationManager = (NotificationManager)context.getSystemService( 110a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown Context.NOTIFICATION_SERVICE); 111cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 112cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 113cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 114cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void dumpLocked(PrintWriter pw) { 115cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super.dumpLocked(pw); 116cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 117e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown pw.println("mCurrentStatus=" + getWifiDisplayStatusLocked()); 11889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown pw.println("mFeatureState=" + mFeatureState); 119180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown pw.println("mScanState=" + mScanState); 120180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown pw.println("mActiveDisplayState=" + mActiveDisplayState); 121180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown pw.println("mActiveDisplay=" + mActiveDisplay); 122ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang pw.println("mDisplays=" + Arrays.toString(mDisplays)); 12389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown pw.println("mAvailableDisplays=" + Arrays.toString(mAvailableDisplays)); 12489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown pw.println("mRememberedDisplays=" + Arrays.toString(mRememberedDisplays)); 125e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown pw.println("mPendingStatusChangeBroadcast=" + mPendingStatusChangeBroadcast); 126a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown pw.println("mPendingNotificationUpdate=" + mPendingNotificationUpdate); 12777aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown pw.println("mSupportsProtectedBuffers=" + mSupportsProtectedBuffers); 128e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 129cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Try to dump the controller state. 130cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mDisplayController == null) { 131cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mDisplayController=null"); 132cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } else { 133cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mDisplayController:"); 134cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 135cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown ipw.increaseIndent(); 136cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown DumpUtils.dumpAsync(getHandler(), mDisplayController, ipw, 200); 137cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 138cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 139cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 140cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 141cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void registerLocked() { 142cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super.registerLocked(); 143cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 14489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateRememberedDisplaysLocked(); 14589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 146cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown getHandler().post(new Runnable() { 147cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 148cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void run() { 149cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mDisplayController = new WifiDisplayController( 150cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown getContext(), getHandler(), mWifiDisplayListener); 15166692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown 15266692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, 15366692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown new IntentFilter(ACTION_DISCONNECT), null, mHandler); 154cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 155cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }); 156cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 157cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 158e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void requestScanLocked() { 1592444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown if (DEBUG) { 1602444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown Slog.d(TAG, "requestScanLocked"); 1612444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown } 1622444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown 163e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getHandler().post(new Runnable() { 164e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 165e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void run() { 166e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mDisplayController != null) { 167e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mDisplayController.requestScan(); 168e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 169e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 170e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }); 171e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 172e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 173bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown public void requestConnectLocked(final String address, final boolean trusted) { 1742444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown if (DEBUG) { 1752444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown Slog.d(TAG, "requestConnectLocked: address=" + address + ", trusted=" + trusted); 1762444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown } 1772444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown 178bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown if (!trusted) { 179bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown synchronized (getSyncRoot()) { 180bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown if (!isRememberedDisplayLocked(address)) { 181bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown Slog.w(TAG, "Ignoring request by an untrusted client to connect to " 182bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown + "an unknown wifi display: " + address); 183bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown return; 184bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown } 185bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown } 186bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown } 187bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown 188e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getHandler().post(new Runnable() { 189e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 190e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void run() { 191e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mDisplayController != null) { 192e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mDisplayController.requestConnect(address); 193e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 194e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 195e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }); 196e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 197e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 198bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown private boolean isRememberedDisplayLocked(String address) { 199bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown for (WifiDisplay display : mRememberedDisplays) { 200bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown if (display.getDeviceAddress().equals(address)) { 201bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown return true; 202bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown } 203bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown } 204bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown return false; 205bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown } 206bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown 207e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void requestDisconnectLocked() { 2082444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown if (DEBUG) { 2092444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown Slog.d(TAG, "requestDisconnectedLocked"); 2102444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown } 2112444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown 212e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getHandler().post(new Runnable() { 213e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 214e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void run() { 215e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mDisplayController != null) { 216e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mDisplayController.requestDisconnect(); 217e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 218e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 219e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }); 220e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 221e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 22289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void requestRenameLocked(String address, String alias) { 2232444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown if (DEBUG) { 2242444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown Slog.d(TAG, "requestRenameLocked: address=" + address + ", alias=" + alias); 2252444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown } 2262444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown 22789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (alias != null) { 22889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown alias = alias.trim(); 2292444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown if (alias.isEmpty() || alias.equals(address)) { 23089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown alias = null; 23189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 23289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 23389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 23474da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown WifiDisplay display = mPersistentDataStore.getRememberedWifiDisplay(address); 23574da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown if (display != null && !Objects.equal(display.getDeviceAlias(), alias)) { 236ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang display = new WifiDisplay(address, display.getDeviceName(), alias, 237ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang false, false, false); 23874da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown if (mPersistentDataStore.rememberWifiDisplay(display)) { 23974da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown mPersistentDataStore.saveIfNeeded(); 24074da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown updateRememberedDisplaysLocked(); 24174da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown scheduleStatusChangedBroadcastLocked(); 24274da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 24389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 244ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown 24574da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown if (mActiveDisplay != null && mActiveDisplay.getDeviceAddress().equals(address)) { 24674da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown renameDisplayDeviceLocked(mActiveDisplay.getFriendlyDisplayName()); 247ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown } 24889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 24989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 25089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void requestForgetLocked(String address) { 2512444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown if (DEBUG) { 2522444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown Slog.d(TAG, "requestForgetLocked: address=" + address); 2532444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown } 2542444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown 25589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mPersistentDataStore.forgetWifiDisplay(address)) { 25689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mPersistentDataStore.saveIfNeeded(); 25789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateRememberedDisplaysLocked(); 25889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown scheduleStatusChangedBroadcastLocked(); 25989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 26089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 26189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mActiveDisplay != null && mActiveDisplay.getDeviceAddress().equals(address)) { 26289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown requestDisconnectLocked(); 26389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 26489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 26589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 266e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public WifiDisplayStatus getWifiDisplayStatusLocked() { 267e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mCurrentStatus == null) { 26889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mCurrentStatus = new WifiDisplayStatus( 26989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mFeatureState, mScanState, mActiveDisplayState, 270ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang mActiveDisplay, mDisplays); 271e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 2722444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown 2732444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown if (DEBUG) { 2742444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown Slog.d(TAG, "getWifiDisplayStatusLocked: result=" + mCurrentStatus); 2752444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown } 276e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown return mCurrentStatus; 277e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 278cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 279ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang private void updateDisplaysLocked() { 280ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang List<WifiDisplay> displays = new ArrayList<WifiDisplay>( 281ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang mAvailableDisplays.length + mRememberedDisplays.length); 282ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang boolean[] remembered = new boolean[mAvailableDisplays.length]; 283ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang for (WifiDisplay d : mRememberedDisplays) { 284ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang boolean available = false; 285ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang for (int i = 0; i < mAvailableDisplays.length; i++) { 286ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang if (d.equals(mAvailableDisplays[i])) { 287ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang remembered[i] = available = true; 288ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang break; 289ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang } 290ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang } 291ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang if (!available) { 292ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang displays.add(new WifiDisplay(d.getDeviceAddress(), d.getDeviceName(), 293ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang d.getDeviceAlias(), false, false, true)); 294ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang } 295ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang } 296ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang for (int i = 0; i < mAvailableDisplays.length; i++) { 297ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang WifiDisplay d = mAvailableDisplays[i]; 298ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang displays.add(new WifiDisplay(d.getDeviceAddress(), d.getDeviceName(), 299ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang d.getDeviceAlias(), true, d.canConnect(), remembered[i])); 300ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang } 301ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang mDisplays = displays.toArray(WifiDisplay.EMPTY_ARRAY); 302ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang } 303ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang 30489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private void updateRememberedDisplaysLocked() { 30589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mRememberedDisplays = mPersistentDataStore.getRememberedWifiDisplays(); 30689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mActiveDisplay = mPersistentDataStore.applyWifiDisplayAlias(mActiveDisplay); 30789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mAvailableDisplays = mPersistentDataStore.applyWifiDisplayAliases(mAvailableDisplays); 308ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang updateDisplaysLocked(); 30989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 31089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 31174da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown private void fixRememberedDisplayNamesFromAvailableDisplaysLocked() { 31274da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown // It may happen that a display name has changed since it was remembered. 31374da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown // Consult the list of available displays and update the name if needed. 31474da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown // We don't do anything special for the active display here. The display 31574da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown // controller will send a separate event when it needs to be updates. 31674da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown boolean changed = false; 31774da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown for (int i = 0; i < mRememberedDisplays.length; i++) { 31874da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown WifiDisplay rememberedDisplay = mRememberedDisplays[i]; 31974da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown WifiDisplay availableDisplay = findAvailableDisplayLocked( 32074da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown rememberedDisplay.getDeviceAddress()); 32174da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown if (availableDisplay != null && !rememberedDisplay.equals(availableDisplay)) { 32274da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown if (DEBUG) { 32374da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown Slog.d(TAG, "fixRememberedDisplayNamesFromAvailableDisplaysLocked: " 32474da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown + "updating remembered display to " + availableDisplay); 32574da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 32674da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown mRememberedDisplays[i] = availableDisplay; 32774da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown changed |= mPersistentDataStore.rememberWifiDisplay(availableDisplay); 32874da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 32974da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 33074da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown if (changed) { 33174da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown mPersistentDataStore.saveIfNeeded(); 33274da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 33374da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 33474da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown 33574da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown private WifiDisplay findAvailableDisplayLocked(String address) { 33674da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown for (WifiDisplay display : mAvailableDisplays) { 33774da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown if (display.getDeviceAddress().equals(address)) { 33874da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown return display; 33974da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 34074da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 34174da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown return null; 34274da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 34374da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown 34474da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown private void addDisplayDeviceLocked(WifiDisplay display, 345f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown Surface surface, int width, int height, int flags) { 34674da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown removeDisplayDeviceLocked(); 347e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 34889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mPersistentDataStore.rememberWifiDisplay(display)) { 34989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mPersistentDataStore.saveIfNeeded(); 35089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateRememberedDisplaysLocked(); 35189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown scheduleStatusChangedBroadcastLocked(); 35289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 35389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 354f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown boolean secure = (flags & RemoteDisplay.DISPLAY_FLAG_SECURE) != 0; 355f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown int deviceFlags = 0; 356f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown if (secure) { 35777aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown deviceFlags |= DisplayDeviceInfo.FLAG_SECURE; 358f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown if (mSupportsProtectedBuffers) { 359f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown deviceFlags |= DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS; 360f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown } 361f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown } 362f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 363f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown float refreshRate = 60.0f; // TODO: get this for real 364f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 36589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown String name = display.getFriendlyDisplayName(); 36692130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown String address = display.getDeviceAddress(); 3673866f0d581ceaa165710feeee9f37fe1b0d7067dMathias Agopian IBinder displayToken = SurfaceControl.createDisplay(name, secure); 368f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mDisplayDevice = new WifiDisplayDevice(displayToken, name, width, height, 36992130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown refreshRate, deviceFlags, address, surface); 370f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_ADDED); 371a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 372a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown scheduleUpdateNotificationLocked(); 373cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 374cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 37574da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown private void removeDisplayDeviceLocked() { 376f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown if (mDisplayDevice != null) { 377f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mDisplayDevice.clearSurfaceLocked(); 378f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_REMOVED); 379f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mDisplayDevice = null; 380a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 381a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown scheduleUpdateNotificationLocked(); 382cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 383cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 384cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 38574da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown private void renameDisplayDeviceLocked(String name) { 38674da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown if (mDisplayDevice != null && !mDisplayDevice.getNameLocked().equals(name)) { 38774da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown mDisplayDevice.setNameLocked(name); 38874da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_CHANGED); 38974da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 39074da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 39174da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown 392e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private void scheduleStatusChangedBroadcastLocked() { 39389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mCurrentStatus = null; 394e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (!mPendingStatusChangeBroadcast) { 395e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mPendingStatusChangeBroadcast = true; 396a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mHandler.sendEmptyMessage(MSG_SEND_STATUS_CHANGE_BROADCAST); 397e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 398e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 399e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 400a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private void scheduleUpdateNotificationLocked() { 401a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown if (!mPendingNotificationUpdate) { 402a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mPendingNotificationUpdate = true; 403a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mHandler.sendEmptyMessage(MSG_UPDATE_NOTIFICATION); 404a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 405a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 406a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 407a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown // Runs on the handler. 408a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private void handleSendStatusChangeBroadcast() { 409a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown final Intent intent; 410a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown synchronized (getSyncRoot()) { 411a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown if (!mPendingStatusChangeBroadcast) { 412a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown return; 413a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 414a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 415a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mPendingStatusChangeBroadcast = false; 416a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown intent = new Intent(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED); 417a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 418a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown intent.putExtra(DisplayManager.EXTRA_WIFI_DISPLAY_STATUS, 419a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown getWifiDisplayStatusLocked()); 420a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 421e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 422a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown // Send protected broadcast about wifi display status to registered receivers. 423a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown getContext().sendBroadcastAsUser(intent, UserHandle.ALL); 424a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 425a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 426a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown // Runs on the handler. 427a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private void handleUpdateNotification() { 428a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown final boolean isConnected; 429a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown synchronized (getSyncRoot()) { 430a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown if (!mPendingNotificationUpdate) { 431a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown return; 432e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 433e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 434a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mPendingNotificationUpdate = false; 435a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown isConnected = (mDisplayDevice != null); 436a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 437a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 43866692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown // Cancel the old notification if there is one. 439a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mNotificationManager.cancelAsUser(null, 440a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown R.string.wifi_display_notification_title, UserHandle.ALL); 441a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 442a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown if (isConnected) { 443a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown Context context = getContext(); 444a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 44566692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown // Initialize pending intents for the notification outside of the lock because 44666692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown // creating a pending intent requires a call into the activity manager. 44766692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown if (mSettingsPendingIntent == null) { 44866692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown Intent settingsIntent = new Intent(Settings.ACTION_WIFI_DISPLAY_SETTINGS); 44966692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 45066692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 45166692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown | Intent.FLAG_ACTIVITY_CLEAR_TOP); 45266692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown mSettingsPendingIntent = PendingIntent.getActivityAsUser( 45366692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown context, 0, settingsIntent, 0, null, UserHandle.CURRENT); 45466692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown } 45566692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown 45666692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown if (mDisconnectPendingIntent == null) { 45766692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown Intent disconnectIntent = new Intent(ACTION_DISCONNECT); 45866692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown mDisconnectPendingIntent = PendingIntent.getBroadcastAsUser( 45966692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown context, 0, disconnectIntent, 0, UserHandle.CURRENT); 46066692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown } 46166692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown 46266692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown // Post the notification. 463a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown Resources r = context.getResources(); 464a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown Notification notification = new Notification.Builder(context) 465a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown .setContentTitle(r.getString( 466a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown R.string.wifi_display_notification_title)) 467a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown .setContentText(r.getString( 468a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown R.string.wifi_display_notification_message)) 469a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown .setContentIntent(mSettingsPendingIntent) 470a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown .setSmallIcon(R.drawable.ic_notify_wifidisplay) 471a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown .setOngoing(true) 472a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown .addAction(android.R.drawable.ic_menu_close_clear_cancel, 473a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown r.getString(R.string.wifi_display_notification_disconnect), 474a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mDisconnectPendingIntent) 475a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown .build(); 476a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mNotificationManager.notifyAsUser(null, 477a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown R.string.wifi_display_notification_title, 478a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown notification, UserHandle.ALL); 479a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 480a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 481a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 482a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 483a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown @Override 484a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown public void onReceive(Context context, Intent intent) { 485a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown if (intent.getAction().equals(ACTION_DISCONNECT)) { 486a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown synchronized (getSyncRoot()) { 487a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown requestDisconnectLocked(); 488a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 489a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 490e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 491e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }; 492e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 493cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final WifiDisplayController.Listener mWifiDisplayListener = 494cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown new WifiDisplayController.Listener() { 495cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 49689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void onFeatureStateChanged(int featureState) { 497e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 49889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mFeatureState != featureState) { 49989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mFeatureState = featureState; 500e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 501e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 502e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 503e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 504e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 505e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 506e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onScanStarted() { 507e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 508180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mScanState != WifiDisplayStatus.SCAN_STATE_SCANNING) { 509180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mScanState = WifiDisplayStatus.SCAN_STATE_SCANNING; 510e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 511e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 512e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 513e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 514e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 5152444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown @Override 51689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void onScanFinished(WifiDisplay[] availableDisplays) { 517e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 51889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown availableDisplays = mPersistentDataStore.applyWifiDisplayAliases( 51989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown availableDisplays); 52089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 521ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang // check if any of the available displays changed canConnect status 522ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang boolean changed = !Arrays.equals(mAvailableDisplays, availableDisplays); 523ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang for (int i = 0; !changed && i<availableDisplays.length; i++) { 524ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang changed = availableDisplays[i].canConnect() 525ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang != mAvailableDisplays[i].canConnect(); 526ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang } 527ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang 528ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang if (mScanState != WifiDisplayStatus.SCAN_STATE_NOT_SCANNING || changed) { 529180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mScanState = WifiDisplayStatus.SCAN_STATE_NOT_SCANNING; 53089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mAvailableDisplays = availableDisplays; 53174da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown fixRememberedDisplayNamesFromAvailableDisplaysLocked(); 532ab87a63997a7dc771acfd0dcd7efda990dc3d5feChong Zhang updateDisplaysLocked(); 533e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 534e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 535e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 536e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 537e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 538e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 539e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onDisplayConnecting(WifiDisplay display) { 540e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 54189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown display = mPersistentDataStore.applyWifiDisplayAlias(display); 54289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 543180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTING 544180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay == null 545180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || !mActiveDisplay.equals(display)) { 546180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTING; 547180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = display; 548e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 549e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 550e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 551e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 552e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 553e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 554e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onDisplayConnectionFailed() { 555e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 556180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED 557180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay != null) { 558180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED; 559180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = null; 560e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 561e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 562e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 563e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 564e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 565e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 566f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown public void onDisplayConnected(WifiDisplay display, Surface surface, 567f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown int width, int height, int flags) { 568cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown synchronized (getSyncRoot()) { 56989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown display = mPersistentDataStore.applyWifiDisplayAlias(display); 57074da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown addDisplayDeviceLocked(display, surface, width, height, flags); 571e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 572180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTED 573180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay == null 574180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || !mActiveDisplay.equals(display)) { 575180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTED; 576180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = display; 577e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 578e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 579cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 580cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 581cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 582cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 58374da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown public void onDisplayChanged(WifiDisplay display) { 58474da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown synchronized (getSyncRoot()) { 58574da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown display = mPersistentDataStore.applyWifiDisplayAlias(display); 58674da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown if (mActiveDisplay != null 58774da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown && mActiveDisplay.hasSameAddress(display) 58874da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown && !mActiveDisplay.equals(display)) { 58974da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown mActiveDisplay = display; 59074da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown renameDisplayDeviceLocked(display.getFriendlyDisplayName()); 59174da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown scheduleStatusChangedBroadcastLocked(); 59274da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 59374da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 59474da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown } 59574da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown 59674da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown @Override 597cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onDisplayDisconnected() { 598cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Stop listening. 599cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown synchronized (getSyncRoot()) { 60074da109102864f19b3dcdb30cd1d92c46fb12f2fJeff Brown removeDisplayDeviceLocked(); 601e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 602180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED 603180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay != null) { 604180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED; 605180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = null; 606e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 607e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 608cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 609cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 610cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }; 611cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 612cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final class WifiDisplayDevice extends DisplayDevice { 613ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown private String mName; 614cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final int mWidth; 615cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final int mHeight; 616cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final float mRefreshRate; 617cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final int mFlags; 61892130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown private final String mAddress; 619cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 620cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private Surface mSurface; 621cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private DisplayDeviceInfo mInfo; 622cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 623cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public WifiDisplayDevice(IBinder displayToken, String name, 62492130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown int width, int height, float refreshRate, int flags, String address, 625cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Surface surface) { 626cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super(WifiDisplayAdapter.this, displayToken); 627cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mName = name; 628cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mWidth = width; 629cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mHeight = height; 630cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mRefreshRate = refreshRate; 631cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mFlags = flags; 63292130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown mAddress = address; 633cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mSurface = surface; 634cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 635cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 636cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void clearSurfaceLocked() { 637cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mSurface = null; 638cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown sendTraversalRequestLocked(); 639cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 640cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 641ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown public void setNameLocked(String name) { 642ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown mName = name; 643ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown mInfo = null; 644ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown } 645ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown 646cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 647cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void performTraversalInTransactionLocked() { 648cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown setSurfaceInTransactionLocked(mSurface); 649cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 650cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 651cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 652cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public DisplayDeviceInfo getDisplayDeviceInfoLocked() { 653cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mInfo == null) { 654cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo = new DisplayDeviceInfo(); 655cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.name = mName; 656cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.width = mWidth; 657cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.height = mHeight; 658cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.refreshRate = mRefreshRate; 659cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.flags = mFlags; 66092130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown mInfo.type = Display.TYPE_WIFI; 66192130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown mInfo.address = mAddress; 662d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL; 663cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.setAssumedDensityForExternalDisplay(mWidth, mHeight); 664cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 665cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return mInfo; 666cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 667cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 668a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 669a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private final class WifiDisplayHandler extends Handler { 670a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown public WifiDisplayHandler(Looper looper) { 671a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown super(looper, null, true /*async*/); 672a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 673a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 674a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown @Override 675a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown public void handleMessage(Message msg) { 676a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown switch (msg.what) { 677a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown case MSG_SEND_STATUS_CHANGE_BROADCAST: 678a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown handleSendStatusChangeBroadcast(); 679a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown break; 680a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 681a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown case MSG_UPDATE_NOTIFICATION: 682a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown handleUpdateNotification(); 683a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown break; 684a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 685a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 686a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 687cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown} 688