WifiDisplayAdapter.java revision 92130f6407dc51c58b3b941d28a6daf4e04b8d62
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; 44cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 45cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport java.io.PrintWriter; 46e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brownimport java.util.Arrays; 47cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 48cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown/** 49cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Connects to Wifi displays that implement the Miracast protocol. 50cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * <p> 51cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * The Wifi display protocol relies on Wifi direct for discovering and pairing 52cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * with the display. Once connected, the Media Server opens an RTSP socket and accepts 53cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * a connection from the display. After session negotiation, the Media Server 54cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * streams encoded buffers to the display. 55cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * </p><p> 56cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * This class is responsible for connecting to Wifi displays and mediating 57cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * the interactions between Media Server, Surface Flinger and the Display Manager Service. 58cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * </p><p> 59cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock. 60cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * </p> 61cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown */ 62cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownfinal class WifiDisplayAdapter extends DisplayAdapter { 63cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private static final String TAG = "WifiDisplayAdapter"; 64cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 652444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown private static final boolean DEBUG = false; 662444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown 67a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private static final int MSG_SEND_STATUS_CHANGE_BROADCAST = 1; 68a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private static final int MSG_UPDATE_NOTIFICATION = 2; 69a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 70a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private static final String ACTION_DISCONNECT = "android.server.display.wfd.DISCONNECT"; 71a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 72a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private final WifiDisplayHandler mHandler; 7377aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown private final PersistentDataStore mPersistentDataStore; 7477aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown private final boolean mSupportsProtectedBuffers; 75a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private final NotificationManager mNotificationManager; 76a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 7766692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown private PendingIntent mSettingsPendingIntent; 7866692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown private PendingIntent mDisconnectPendingIntent; 7989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 80cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private WifiDisplayController mDisplayController; 81f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown private WifiDisplayDevice mDisplayDevice; 82cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 83e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private WifiDisplayStatus mCurrentStatus; 8489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private int mFeatureState; 85180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown private int mScanState; 86180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown private int mActiveDisplayState; 87180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown private WifiDisplay mActiveDisplay; 8889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private WifiDisplay[] mAvailableDisplays = WifiDisplay.EMPTY_ARRAY; 8989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private WifiDisplay[] mRememberedDisplays = WifiDisplay.EMPTY_ARRAY; 90e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 91e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private boolean mPendingStatusChangeBroadcast; 92a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private boolean mPendingNotificationUpdate; 93e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 9466692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown // Called with SyncRoot lock held. 95cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public WifiDisplayAdapter(DisplayManagerService.SyncRoot syncRoot, 9689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown Context context, Handler handler, Listener listener, 9789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown PersistentDataStore persistentDataStore) { 98cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super(syncRoot, context, handler, listener, TAG); 99a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mHandler = new WifiDisplayHandler(handler.getLooper()); 10089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mPersistentDataStore = persistentDataStore; 10177aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown mSupportsProtectedBuffers = context.getResources().getBoolean( 10277aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown com.android.internal.R.bool.config_wifiDisplaySupportsProtectedBuffers); 103a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mNotificationManager = (NotificationManager)context.getSystemService( 104a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown Context.NOTIFICATION_SERVICE); 105cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 106cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 107cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 108cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void dumpLocked(PrintWriter pw) { 109cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super.dumpLocked(pw); 110cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 111e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown pw.println("mCurrentStatus=" + getWifiDisplayStatusLocked()); 11289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown pw.println("mFeatureState=" + mFeatureState); 113180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown pw.println("mScanState=" + mScanState); 114180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown pw.println("mActiveDisplayState=" + mActiveDisplayState); 115180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown pw.println("mActiveDisplay=" + mActiveDisplay); 11689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown pw.println("mAvailableDisplays=" + Arrays.toString(mAvailableDisplays)); 11789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown pw.println("mRememberedDisplays=" + Arrays.toString(mRememberedDisplays)); 118e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown pw.println("mPendingStatusChangeBroadcast=" + mPendingStatusChangeBroadcast); 119a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown pw.println("mPendingNotificationUpdate=" + mPendingNotificationUpdate); 12077aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown pw.println("mSupportsProtectedBuffers=" + mSupportsProtectedBuffers); 121e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 122cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Try to dump the controller state. 123cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mDisplayController == null) { 124cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mDisplayController=null"); 125cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } else { 126cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown pw.println("mDisplayController:"); 127cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " "); 128cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown ipw.increaseIndent(); 129cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown DumpUtils.dumpAsync(getHandler(), mDisplayController, ipw, 200); 130cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 131cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 132cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 133cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 134cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void registerLocked() { 135cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super.registerLocked(); 136cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 13789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateRememberedDisplaysLocked(); 13889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 139cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown getHandler().post(new Runnable() { 140cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 141cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void run() { 142cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mDisplayController = new WifiDisplayController( 143cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown getContext(), getHandler(), mWifiDisplayListener); 14466692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown 14566692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, 14666692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown new IntentFilter(ACTION_DISCONNECT), null, mHandler); 147cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 148cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }); 149cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 150cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 151e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void requestScanLocked() { 1522444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown if (DEBUG) { 1532444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown Slog.d(TAG, "requestScanLocked"); 1542444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown } 1552444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown 156e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getHandler().post(new Runnable() { 157e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 158e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void run() { 159e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mDisplayController != null) { 160e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mDisplayController.requestScan(); 161e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 162e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 163e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }); 164e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 165e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 166bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown public void requestConnectLocked(final String address, final boolean trusted) { 1672444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown if (DEBUG) { 1682444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown Slog.d(TAG, "requestConnectLocked: address=" + address + ", trusted=" + trusted); 1692444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown } 1702444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown 171bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown if (!trusted) { 172bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown synchronized (getSyncRoot()) { 173bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown if (!isRememberedDisplayLocked(address)) { 174bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown Slog.w(TAG, "Ignoring request by an untrusted client to connect to " 175bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown + "an unknown wifi display: " + address); 176bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown return; 177bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown } 178bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown } 179bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown } 180bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown 181e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getHandler().post(new Runnable() { 182e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 183e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void run() { 184e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mDisplayController != null) { 185e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mDisplayController.requestConnect(address); 186e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 187e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 188e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }); 189e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 190e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 191bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown private boolean isRememberedDisplayLocked(String address) { 192bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown for (WifiDisplay display : mRememberedDisplays) { 193bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown if (display.getDeviceAddress().equals(address)) { 194bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown return true; 195bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown } 196bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown } 197bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown return false; 198bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown } 199bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown 200e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void requestDisconnectLocked() { 2012444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown if (DEBUG) { 2022444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown Slog.d(TAG, "requestDisconnectedLocked"); 2032444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown } 2042444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown 205e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown getHandler().post(new Runnable() { 206e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 207e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void run() { 208e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mDisplayController != null) { 209e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mDisplayController.requestDisconnect(); 210e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 211e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 212e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }); 213e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 214e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 21589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void requestRenameLocked(String address, String alias) { 2162444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown if (DEBUG) { 2172444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown Slog.d(TAG, "requestRenameLocked: address=" + address + ", alias=" + alias); 2182444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown } 2192444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown 22089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (alias != null) { 22189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown alias = alias.trim(); 2222444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown if (alias.isEmpty() || alias.equals(address)) { 22389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown alias = null; 22489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 22589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 22689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 22789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mPersistentDataStore.renameWifiDisplay(address, alias)) { 22889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mPersistentDataStore.saveIfNeeded(); 22989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateRememberedDisplaysLocked(); 23089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown scheduleStatusChangedBroadcastLocked(); 23189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 232ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown 233ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown if (mActiveDisplay != null && mActiveDisplay.getDeviceAddress().equals(address) 234ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown && mDisplayDevice != null) { 235ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown mDisplayDevice.setNameLocked(mActiveDisplay.getFriendlyDisplayName()); 236ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_CHANGED); 237ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown } 23889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 23989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 24089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void requestForgetLocked(String address) { 2412444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown if (DEBUG) { 2422444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown Slog.d(TAG, "requestForgetLocked: address=" + address); 2432444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown } 2442444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown 24589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mPersistentDataStore.forgetWifiDisplay(address)) { 24689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mPersistentDataStore.saveIfNeeded(); 24789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateRememberedDisplaysLocked(); 24889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown scheduleStatusChangedBroadcastLocked(); 24989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 25089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 25189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mActiveDisplay != null && mActiveDisplay.getDeviceAddress().equals(address)) { 25289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown requestDisconnectLocked(); 25389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 25489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 25589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 256e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public WifiDisplayStatus getWifiDisplayStatusLocked() { 257e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (mCurrentStatus == null) { 25889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mCurrentStatus = new WifiDisplayStatus( 25989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mFeatureState, mScanState, mActiveDisplayState, 26089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mActiveDisplay, mAvailableDisplays, mRememberedDisplays); 261e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 2622444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown 2632444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown if (DEBUG) { 2642444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown Slog.d(TAG, "getWifiDisplayStatusLocked: result=" + mCurrentStatus); 2652444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown } 266e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown return mCurrentStatus; 267e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 268cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 26989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown private void updateRememberedDisplaysLocked() { 27089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mRememberedDisplays = mPersistentDataStore.getRememberedWifiDisplays(); 27189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mActiveDisplay = mPersistentDataStore.applyWifiDisplayAlias(mActiveDisplay); 27289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mAvailableDisplays = mPersistentDataStore.applyWifiDisplayAliases(mAvailableDisplays); 27389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 27489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 275f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown private void handleConnectLocked(WifiDisplay display, 276f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown Surface surface, int width, int height, int flags) { 277e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown handleDisconnectLocked(); 278e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 27989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mPersistentDataStore.rememberWifiDisplay(display)) { 28089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mPersistentDataStore.saveIfNeeded(); 28189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown updateRememberedDisplaysLocked(); 28289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown scheduleStatusChangedBroadcastLocked(); 28389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown } 28489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 285f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown boolean secure = (flags & RemoteDisplay.DISPLAY_FLAG_SECURE) != 0; 286f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown int deviceFlags = 0; 287f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown if (secure) { 28877aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown deviceFlags |= DisplayDeviceInfo.FLAG_SECURE; 289f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown if (mSupportsProtectedBuffers) { 290f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown deviceFlags |= DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS; 291f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown } 292f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown } 293f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 294f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown float refreshRate = 60.0f; // TODO: get this for real 295f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown 29689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown String name = display.getFriendlyDisplayName(); 29792130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown String address = display.getDeviceAddress(); 298f0681b34dffc1510cbd9c3da5c3a7e695553fa8dJeff Brown IBinder displayToken = Surface.createDisplay(name, secure); 299f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mDisplayDevice = new WifiDisplayDevice(displayToken, name, width, height, 30092130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown refreshRate, deviceFlags, address, surface); 301f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_ADDED); 302a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 303a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown scheduleUpdateNotificationLocked(); 304cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 305cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 306e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private void handleDisconnectLocked() { 307f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown if (mDisplayDevice != null) { 308f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mDisplayDevice.clearSurfaceLocked(); 309f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_REMOVED); 310f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown mDisplayDevice = null; 311a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 312a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown scheduleUpdateNotificationLocked(); 313cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 314cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 315cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 316e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown private void scheduleStatusChangedBroadcastLocked() { 31789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mCurrentStatus = null; 318e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown if (!mPendingStatusChangeBroadcast) { 319e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown mPendingStatusChangeBroadcast = true; 320a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mHandler.sendEmptyMessage(MSG_SEND_STATUS_CHANGE_BROADCAST); 321e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 322e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 323e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 324a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private void scheduleUpdateNotificationLocked() { 325a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown if (!mPendingNotificationUpdate) { 326a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mPendingNotificationUpdate = true; 327a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mHandler.sendEmptyMessage(MSG_UPDATE_NOTIFICATION); 328a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 329a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 330a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 331a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown // Runs on the handler. 332a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private void handleSendStatusChangeBroadcast() { 333a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown final Intent intent; 334a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown synchronized (getSyncRoot()) { 335a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown if (!mPendingStatusChangeBroadcast) { 336a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown return; 337a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 338a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 339a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mPendingStatusChangeBroadcast = false; 340a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown intent = new Intent(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED); 341a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 342a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown intent.putExtra(DisplayManager.EXTRA_WIFI_DISPLAY_STATUS, 343a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown getWifiDisplayStatusLocked()); 344a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 345e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 346a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown // Send protected broadcast about wifi display status to registered receivers. 347a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown getContext().sendBroadcastAsUser(intent, UserHandle.ALL); 348a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 349a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 350a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown // Runs on the handler. 351a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private void handleUpdateNotification() { 352a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown final boolean isConnected; 353a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown synchronized (getSyncRoot()) { 354a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown if (!mPendingNotificationUpdate) { 355a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown return; 356e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 357e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 358a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mPendingNotificationUpdate = false; 359a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown isConnected = (mDisplayDevice != null); 360a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 361a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 36266692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown // Cancel the old notification if there is one. 363a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mNotificationManager.cancelAsUser(null, 364a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown R.string.wifi_display_notification_title, UserHandle.ALL); 365a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 366a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown if (isConnected) { 367a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown Context context = getContext(); 368a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 36966692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown // Initialize pending intents for the notification outside of the lock because 37066692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown // creating a pending intent requires a call into the activity manager. 37166692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown if (mSettingsPendingIntent == null) { 37266692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown Intent settingsIntent = new Intent(Settings.ACTION_WIFI_DISPLAY_SETTINGS); 37366692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 37466692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED 37566692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown | Intent.FLAG_ACTIVITY_CLEAR_TOP); 37666692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown mSettingsPendingIntent = PendingIntent.getActivityAsUser( 37766692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown context, 0, settingsIntent, 0, null, UserHandle.CURRENT); 37866692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown } 37966692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown 38066692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown if (mDisconnectPendingIntent == null) { 38166692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown Intent disconnectIntent = new Intent(ACTION_DISCONNECT); 38266692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown mDisconnectPendingIntent = PendingIntent.getBroadcastAsUser( 38366692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown context, 0, disconnectIntent, 0, UserHandle.CURRENT); 38466692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown } 38566692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown 38666692500344cab2f53cdb6ee1545c567fff7cb16Jeff Brown // Post the notification. 387a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown Resources r = context.getResources(); 388a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown Notification notification = new Notification.Builder(context) 389a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown .setContentTitle(r.getString( 390a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown R.string.wifi_display_notification_title)) 391a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown .setContentText(r.getString( 392a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown R.string.wifi_display_notification_message)) 393a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown .setContentIntent(mSettingsPendingIntent) 394a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown .setSmallIcon(R.drawable.ic_notify_wifidisplay) 395a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown .setOngoing(true) 396a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown .addAction(android.R.drawable.ic_menu_close_clear_cancel, 397a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown r.getString(R.string.wifi_display_notification_disconnect), 398a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mDisconnectPendingIntent) 399a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown .build(); 400a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown mNotificationManager.notifyAsUser(null, 401a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown R.string.wifi_display_notification_title, 402a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown notification, UserHandle.ALL); 403a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 404a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 405a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 406a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 407a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown @Override 408a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown public void onReceive(Context context, Intent intent) { 409a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown if (intent.getAction().equals(ACTION_DISCONNECT)) { 410a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown synchronized (getSyncRoot()) { 411a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown requestDisconnectLocked(); 412a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 413a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 414e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 415e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown }; 416e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 417cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final WifiDisplayController.Listener mWifiDisplayListener = 418cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown new WifiDisplayController.Listener() { 419cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 42089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void onFeatureStateChanged(int featureState) { 421e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 42289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown if (mFeatureState != featureState) { 42389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mFeatureState = featureState; 424e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 425e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 426e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 427e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 428e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 429e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 430e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onScanStarted() { 431e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 432180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mScanState != WifiDisplayStatus.SCAN_STATE_SCANNING) { 433180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mScanState = WifiDisplayStatus.SCAN_STATE_SCANNING; 434e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 435e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 436e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 437e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 438e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 4392444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown @Override 44089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown public void onScanFinished(WifiDisplay[] availableDisplays) { 441e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 44289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown availableDisplays = mPersistentDataStore.applyWifiDisplayAliases( 44389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown availableDisplays); 44489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 445180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mScanState != WifiDisplayStatus.SCAN_STATE_NOT_SCANNING 44689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown || !Arrays.equals(mAvailableDisplays, availableDisplays)) { 447180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mScanState = WifiDisplayStatus.SCAN_STATE_NOT_SCANNING; 44889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown mAvailableDisplays = availableDisplays; 449e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 450e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 451e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 452e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 453e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 454e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 455e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onDisplayConnecting(WifiDisplay display) { 456e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 45789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown display = mPersistentDataStore.applyWifiDisplayAlias(display); 45889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown 459180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTING 460180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay == null 461180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || !mActiveDisplay.equals(display)) { 462180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTING; 463180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = display; 464e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 465e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 466e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 467e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 468e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 469e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 470e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown public void onDisplayConnectionFailed() { 471e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown synchronized (getSyncRoot()) { 472180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED 473180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay != null) { 474180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED; 475180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = null; 476e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 477e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 478e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 479e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 480e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 481e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown @Override 482f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown public void onDisplayConnected(WifiDisplay display, Surface surface, 483f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown int width, int height, int flags) { 484cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown synchronized (getSyncRoot()) { 48589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown display = mPersistentDataStore.applyWifiDisplayAlias(display); 486f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown handleConnectLocked(display, surface, width, height, flags); 487e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 488180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTED 489180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay == null 490180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || !mActiveDisplay.equals(display)) { 491180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTED; 492180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = display; 493e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 494e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 495cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 496cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 497cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 498cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 499cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void onDisplayDisconnected() { 500cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown // Stop listening. 501cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown synchronized (getSyncRoot()) { 502e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown handleDisconnectLocked(); 503e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown 504180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED 505180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown || mActiveDisplay != null) { 506180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED; 507180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown mActiveDisplay = null; 508e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown scheduleStatusChangedBroadcastLocked(); 509e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown } 510cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 511cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 512cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown }; 513cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 514cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final class WifiDisplayDevice extends DisplayDevice { 515ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown private String mName; 516cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final int mWidth; 517cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final int mHeight; 518cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final float mRefreshRate; 519cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private final int mFlags; 52092130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown private final String mAddress; 521cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 522cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private Surface mSurface; 523cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown private DisplayDeviceInfo mInfo; 524cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 525cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public WifiDisplayDevice(IBinder displayToken, String name, 52692130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown int width, int height, float refreshRate, int flags, String address, 527cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown Surface surface) { 528cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown super(WifiDisplayAdapter.this, displayToken); 529cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mName = name; 530cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mWidth = width; 531cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mHeight = height; 532cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mRefreshRate = refreshRate; 533cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mFlags = flags; 53492130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown mAddress = address; 535cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mSurface = surface; 536cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 537cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 538cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void clearSurfaceLocked() { 539cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mSurface = null; 540cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown sendTraversalRequestLocked(); 541cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 542cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 543ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown public void setNameLocked(String name) { 544ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown mName = name; 545ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown mInfo = null; 546ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown } 547ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown 548cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 549cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public void performTraversalInTransactionLocked() { 550cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown setSurfaceInTransactionLocked(mSurface); 551cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 552cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown 553cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown @Override 554cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown public DisplayDeviceInfo getDisplayDeviceInfoLocked() { 555cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown if (mInfo == null) { 556cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo = new DisplayDeviceInfo(); 557cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.name = mName; 558cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.width = mWidth; 559cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.height = mHeight; 560cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.refreshRate = mRefreshRate; 561cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.flags = mFlags; 56292130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown mInfo.type = Display.TYPE_WIFI; 56392130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown mInfo.address = mAddress; 564d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL; 565cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown mInfo.setAssumedDensityForExternalDisplay(mWidth, mHeight); 566cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 567cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown return mInfo; 568cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 569cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown } 570a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 571a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown private final class WifiDisplayHandler extends Handler { 572a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown public WifiDisplayHandler(Looper looper) { 573a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown super(looper, null, true /*async*/); 574a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 575a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 576a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown @Override 577a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown public void handleMessage(Message msg) { 578a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown switch (msg.what) { 579a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown case MSG_SEND_STATUS_CHANGE_BROADCAST: 580a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown handleSendStatusChangeBroadcast(); 581a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown break; 582a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown 583a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown case MSG_UPDATE_NOTIFICATION: 584a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown handleUpdateNotification(); 585a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown break; 586a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 587a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 588a7f9c966bc90e52baaf0cf0c165463e5f44354c5Jeff Brown } 589cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown} 590