blob: 45fff303b7c6b5fd268a99df3cf277676e70feee [file] [log] [blame]
Jeff Browncbad9762012-09-04 21:57:59 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.display;
18
Jeff Browna7f9c962012-10-17 15:15:12 -070019import com.android.internal.R;
Jeff Browncbad9762012-09-04 21:57:59 -070020import com.android.internal.util.DumpUtils;
21import com.android.internal.util.IndentingPrintWriter;
22
Jeff Browna7f9c962012-10-17 15:15:12 -070023import android.app.Notification;
24import android.app.NotificationManager;
25import android.app.PendingIntent;
26import android.content.BroadcastReceiver;
Jeff Browncbad9762012-09-04 21:57:59 -070027import android.content.Context;
Jeff Browne08ae382012-09-07 20:36:36 -070028import android.content.Intent;
Jeff Browna7f9c962012-10-17 15:15:12 -070029import android.content.IntentFilter;
30import android.content.res.Resources;
Jeff Browne08ae382012-09-07 20:36:36 -070031import android.hardware.display.DisplayManager;
32import android.hardware.display.WifiDisplay;
33import android.hardware.display.WifiDisplayStatus;
Jeff Browncbad9762012-09-04 21:57:59 -070034import android.media.RemoteDisplay;
35import android.os.Handler;
36import android.os.IBinder;
Jeff Browna7f9c962012-10-17 15:15:12 -070037import android.os.Looper;
38import android.os.Message;
39import android.os.UserHandle;
40import android.provider.Settings;
Jeff Brownbc335452012-09-26 18:34:47 -070041import android.util.Slog;
Jeff Brown92130f62012-10-24 21:28:33 -070042import android.view.Display;
Jeff Browncbad9762012-09-04 21:57:59 -070043import android.view.Surface;
44
45import java.io.PrintWriter;
Jeff Browne08ae382012-09-07 20:36:36 -070046import java.util.Arrays;
Jeff Browncbad9762012-09-04 21:57:59 -070047
48/**
49 * Connects to Wifi displays that implement the Miracast protocol.
50 * <p>
51 * The Wifi display protocol relies on Wifi direct for discovering and pairing
52 * with the display. Once connected, the Media Server opens an RTSP socket and accepts
53 * a connection from the display. After session negotiation, the Media Server
54 * streams encoded buffers to the display.
55 * </p><p>
56 * This class is responsible for connecting to Wifi displays and mediating
57 * the interactions between Media Server, Surface Flinger and the Display Manager Service.
58 * </p><p>
59 * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock.
60 * </p>
61 */
62final class WifiDisplayAdapter extends DisplayAdapter {
63 private static final String TAG = "WifiDisplayAdapter";
64
Jeff Brown2444ae72012-10-11 14:30:21 -070065 private static final boolean DEBUG = false;
66
Jeff Browna7f9c962012-10-17 15:15:12 -070067 private static final int MSG_SEND_STATUS_CHANGE_BROADCAST = 1;
68 private static final int MSG_UPDATE_NOTIFICATION = 2;
69
70 private static final String ACTION_DISCONNECT = "android.server.display.wfd.DISCONNECT";
71
72 private final WifiDisplayHandler mHandler;
Jeff Brown77aebfd2012-10-01 21:07:03 -070073 private final PersistentDataStore mPersistentDataStore;
74 private final boolean mSupportsProtectedBuffers;
Jeff Browna7f9c962012-10-17 15:15:12 -070075 private final NotificationManager mNotificationManager;
76
Jeff Brown66692502012-10-18 16:13:44 -070077 private PendingIntent mSettingsPendingIntent;
78 private PendingIntent mDisconnectPendingIntent;
Jeff Brown89d55462012-09-19 11:33:42 -070079
Jeff Browncbad9762012-09-04 21:57:59 -070080 private WifiDisplayController mDisplayController;
Jeff Brownf8f0edd2012-09-11 17:05:11 -070081 private WifiDisplayDevice mDisplayDevice;
Jeff Browncbad9762012-09-04 21:57:59 -070082
Jeff Browne08ae382012-09-07 20:36:36 -070083 private WifiDisplayStatus mCurrentStatus;
Jeff Brown89d55462012-09-19 11:33:42 -070084 private int mFeatureState;
Jeff Brown180bbc72012-09-08 23:15:00 -070085 private int mScanState;
86 private int mActiveDisplayState;
87 private WifiDisplay mActiveDisplay;
Jeff Brown89d55462012-09-19 11:33:42 -070088 private WifiDisplay[] mAvailableDisplays = WifiDisplay.EMPTY_ARRAY;
89 private WifiDisplay[] mRememberedDisplays = WifiDisplay.EMPTY_ARRAY;
Jeff Browne08ae382012-09-07 20:36:36 -070090
91 private boolean mPendingStatusChangeBroadcast;
Jeff Browna7f9c962012-10-17 15:15:12 -070092 private boolean mPendingNotificationUpdate;
Jeff Browne08ae382012-09-07 20:36:36 -070093
Jeff Brown66692502012-10-18 16:13:44 -070094 // Called with SyncRoot lock held.
Jeff Browncbad9762012-09-04 21:57:59 -070095 public WifiDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
Jeff Brown89d55462012-09-19 11:33:42 -070096 Context context, Handler handler, Listener listener,
97 PersistentDataStore persistentDataStore) {
Jeff Browncbad9762012-09-04 21:57:59 -070098 super(syncRoot, context, handler, listener, TAG);
Jeff Browna7f9c962012-10-17 15:15:12 -070099 mHandler = new WifiDisplayHandler(handler.getLooper());
Jeff Brown89d55462012-09-19 11:33:42 -0700100 mPersistentDataStore = persistentDataStore;
Jeff Brown77aebfd2012-10-01 21:07:03 -0700101 mSupportsProtectedBuffers = context.getResources().getBoolean(
102 com.android.internal.R.bool.config_wifiDisplaySupportsProtectedBuffers);
Jeff Browna7f9c962012-10-17 15:15:12 -0700103 mNotificationManager = (NotificationManager)context.getSystemService(
104 Context.NOTIFICATION_SERVICE);
Jeff Browncbad9762012-09-04 21:57:59 -0700105 }
106
107 @Override
108 public void dumpLocked(PrintWriter pw) {
109 super.dumpLocked(pw);
110
Jeff Browne08ae382012-09-07 20:36:36 -0700111 pw.println("mCurrentStatus=" + getWifiDisplayStatusLocked());
Jeff Brown89d55462012-09-19 11:33:42 -0700112 pw.println("mFeatureState=" + mFeatureState);
Jeff Brown180bbc72012-09-08 23:15:00 -0700113 pw.println("mScanState=" + mScanState);
114 pw.println("mActiveDisplayState=" + mActiveDisplayState);
115 pw.println("mActiveDisplay=" + mActiveDisplay);
Jeff Brown89d55462012-09-19 11:33:42 -0700116 pw.println("mAvailableDisplays=" + Arrays.toString(mAvailableDisplays));
117 pw.println("mRememberedDisplays=" + Arrays.toString(mRememberedDisplays));
Jeff Browne08ae382012-09-07 20:36:36 -0700118 pw.println("mPendingStatusChangeBroadcast=" + mPendingStatusChangeBroadcast);
Jeff Browna7f9c962012-10-17 15:15:12 -0700119 pw.println("mPendingNotificationUpdate=" + mPendingNotificationUpdate);
Jeff Brown77aebfd2012-10-01 21:07:03 -0700120 pw.println("mSupportsProtectedBuffers=" + mSupportsProtectedBuffers);
Jeff Browne08ae382012-09-07 20:36:36 -0700121
Jeff Browncbad9762012-09-04 21:57:59 -0700122 // Try to dump the controller state.
123 if (mDisplayController == null) {
124 pw.println("mDisplayController=null");
125 } else {
126 pw.println("mDisplayController:");
127 final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
128 ipw.increaseIndent();
129 DumpUtils.dumpAsync(getHandler(), mDisplayController, ipw, 200);
130 }
131 }
132
133 @Override
134 public void registerLocked() {
135 super.registerLocked();
136
Jeff Brown89d55462012-09-19 11:33:42 -0700137 updateRememberedDisplaysLocked();
138
Jeff Browncbad9762012-09-04 21:57:59 -0700139 getHandler().post(new Runnable() {
140 @Override
141 public void run() {
142 mDisplayController = new WifiDisplayController(
143 getContext(), getHandler(), mWifiDisplayListener);
Jeff Brown66692502012-10-18 16:13:44 -0700144
145 getContext().registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL,
146 new IntentFilter(ACTION_DISCONNECT), null, mHandler);
Jeff Browncbad9762012-09-04 21:57:59 -0700147 }
148 });
149 }
150
Jeff Browne08ae382012-09-07 20:36:36 -0700151 public void requestScanLocked() {
Jeff Brown2444ae72012-10-11 14:30:21 -0700152 if (DEBUG) {
153 Slog.d(TAG, "requestScanLocked");
154 }
155
Jeff Browne08ae382012-09-07 20:36:36 -0700156 getHandler().post(new Runnable() {
157 @Override
158 public void run() {
159 if (mDisplayController != null) {
160 mDisplayController.requestScan();
161 }
162 }
163 });
Jeff Browncbad9762012-09-04 21:57:59 -0700164 }
165
Jeff Brownbc335452012-09-26 18:34:47 -0700166 public void requestConnectLocked(final String address, final boolean trusted) {
Jeff Brown2444ae72012-10-11 14:30:21 -0700167 if (DEBUG) {
168 Slog.d(TAG, "requestConnectLocked: address=" + address + ", trusted=" + trusted);
169 }
170
Jeff Brownbc335452012-09-26 18:34:47 -0700171 if (!trusted) {
172 synchronized (getSyncRoot()) {
173 if (!isRememberedDisplayLocked(address)) {
174 Slog.w(TAG, "Ignoring request by an untrusted client to connect to "
175 + "an unknown wifi display: " + address);
176 return;
177 }
178 }
179 }
180
Jeff Browne08ae382012-09-07 20:36:36 -0700181 getHandler().post(new Runnable() {
182 @Override
183 public void run() {
184 if (mDisplayController != null) {
185 mDisplayController.requestConnect(address);
186 }
187 }
188 });
189 }
190
Jeff Brownbc335452012-09-26 18:34:47 -0700191 private boolean isRememberedDisplayLocked(String address) {
192 for (WifiDisplay display : mRememberedDisplays) {
193 if (display.getDeviceAddress().equals(address)) {
194 return true;
195 }
196 }
197 return false;
198 }
199
Jeff Browne08ae382012-09-07 20:36:36 -0700200 public void requestDisconnectLocked() {
Jeff Brown2444ae72012-10-11 14:30:21 -0700201 if (DEBUG) {
202 Slog.d(TAG, "requestDisconnectedLocked");
203 }
204
Jeff Browne08ae382012-09-07 20:36:36 -0700205 getHandler().post(new Runnable() {
206 @Override
207 public void run() {
208 if (mDisplayController != null) {
209 mDisplayController.requestDisconnect();
210 }
211 }
212 });
213 }
214
Jeff Brown89d55462012-09-19 11:33:42 -0700215 public void requestRenameLocked(String address, String alias) {
Jeff Brown2444ae72012-10-11 14:30:21 -0700216 if (DEBUG) {
217 Slog.d(TAG, "requestRenameLocked: address=" + address + ", alias=" + alias);
218 }
219
Jeff Brown89d55462012-09-19 11:33:42 -0700220 if (alias != null) {
221 alias = alias.trim();
Jeff Brown2444ae72012-10-11 14:30:21 -0700222 if (alias.isEmpty() || alias.equals(address)) {
Jeff Brown89d55462012-09-19 11:33:42 -0700223 alias = null;
224 }
225 }
226
227 if (mPersistentDataStore.renameWifiDisplay(address, alias)) {
228 mPersistentDataStore.saveIfNeeded();
229 updateRememberedDisplaysLocked();
230 scheduleStatusChangedBroadcastLocked();
231 }
Jeff Brownee4f0292012-10-15 15:31:59 -0700232
233 if (mActiveDisplay != null && mActiveDisplay.getDeviceAddress().equals(address)
234 && mDisplayDevice != null) {
235 mDisplayDevice.setNameLocked(mActiveDisplay.getFriendlyDisplayName());
236 sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_CHANGED);
237 }
Jeff Brown89d55462012-09-19 11:33:42 -0700238 }
239
240 public void requestForgetLocked(String address) {
Jeff Brown2444ae72012-10-11 14:30:21 -0700241 if (DEBUG) {
242 Slog.d(TAG, "requestForgetLocked: address=" + address);
243 }
244
Jeff Brown89d55462012-09-19 11:33:42 -0700245 if (mPersistentDataStore.forgetWifiDisplay(address)) {
246 mPersistentDataStore.saveIfNeeded();
247 updateRememberedDisplaysLocked();
248 scheduleStatusChangedBroadcastLocked();
249 }
250
251 if (mActiveDisplay != null && mActiveDisplay.getDeviceAddress().equals(address)) {
252 requestDisconnectLocked();
253 }
254 }
255
Jeff Browne08ae382012-09-07 20:36:36 -0700256 public WifiDisplayStatus getWifiDisplayStatusLocked() {
257 if (mCurrentStatus == null) {
Jeff Brown89d55462012-09-19 11:33:42 -0700258 mCurrentStatus = new WifiDisplayStatus(
259 mFeatureState, mScanState, mActiveDisplayState,
260 mActiveDisplay, mAvailableDisplays, mRememberedDisplays);
Jeff Browne08ae382012-09-07 20:36:36 -0700261 }
Jeff Brown2444ae72012-10-11 14:30:21 -0700262
263 if (DEBUG) {
264 Slog.d(TAG, "getWifiDisplayStatusLocked: result=" + mCurrentStatus);
265 }
Jeff Browne08ae382012-09-07 20:36:36 -0700266 return mCurrentStatus;
267 }
268
Jeff Brown89d55462012-09-19 11:33:42 -0700269 private void updateRememberedDisplaysLocked() {
270 mRememberedDisplays = mPersistentDataStore.getRememberedWifiDisplays();
271 mActiveDisplay = mPersistentDataStore.applyWifiDisplayAlias(mActiveDisplay);
272 mAvailableDisplays = mPersistentDataStore.applyWifiDisplayAliases(mAvailableDisplays);
273 }
274
Jeff Brownf8f0edd2012-09-11 17:05:11 -0700275 private void handleConnectLocked(WifiDisplay display,
276 Surface surface, int width, int height, int flags) {
Jeff Browne08ae382012-09-07 20:36:36 -0700277 handleDisconnectLocked();
278
Jeff Brown89d55462012-09-19 11:33:42 -0700279 if (mPersistentDataStore.rememberWifiDisplay(display)) {
280 mPersistentDataStore.saveIfNeeded();
281 updateRememberedDisplaysLocked();
282 scheduleStatusChangedBroadcastLocked();
283 }
284
Jeff Brownf0681b32012-10-23 17:35:57 -0700285 boolean secure = (flags & RemoteDisplay.DISPLAY_FLAG_SECURE) != 0;
Jeff Brownf8f0edd2012-09-11 17:05:11 -0700286 int deviceFlags = 0;
Jeff Brownf0681b32012-10-23 17:35:57 -0700287 if (secure) {
Jeff Brown77aebfd2012-10-01 21:07:03 -0700288 deviceFlags |= DisplayDeviceInfo.FLAG_SECURE;
Jeff Brownf0681b32012-10-23 17:35:57 -0700289 if (mSupportsProtectedBuffers) {
290 deviceFlags |= DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
291 }
Jeff Brownf8f0edd2012-09-11 17:05:11 -0700292 }
293
294 float refreshRate = 60.0f; // TODO: get this for real
295
Jeff Brown89d55462012-09-19 11:33:42 -0700296 String name = display.getFriendlyDisplayName();
Jeff Brown92130f62012-10-24 21:28:33 -0700297 String address = display.getDeviceAddress();
Jeff Brownf0681b32012-10-23 17:35:57 -0700298 IBinder displayToken = Surface.createDisplay(name, secure);
Jeff Brownf8f0edd2012-09-11 17:05:11 -0700299 mDisplayDevice = new WifiDisplayDevice(displayToken, name, width, height,
Jeff Brown92130f62012-10-24 21:28:33 -0700300 refreshRate, deviceFlags, address, surface);
Jeff Brownf8f0edd2012-09-11 17:05:11 -0700301 sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_ADDED);
Jeff Browna7f9c962012-10-17 15:15:12 -0700302
303 scheduleUpdateNotificationLocked();
Jeff Browne08ae382012-09-07 20:36:36 -0700304 }
305
306 private void handleDisconnectLocked() {
Jeff Brownf8f0edd2012-09-11 17:05:11 -0700307 if (mDisplayDevice != null) {
308 mDisplayDevice.clearSurfaceLocked();
309 sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_REMOVED);
310 mDisplayDevice = null;
Jeff Browna7f9c962012-10-17 15:15:12 -0700311
312 scheduleUpdateNotificationLocked();
Jeff Browncbad9762012-09-04 21:57:59 -0700313 }
314 }
315
Jeff Browne08ae382012-09-07 20:36:36 -0700316 private void scheduleStatusChangedBroadcastLocked() {
Jeff Brown89d55462012-09-19 11:33:42 -0700317 mCurrentStatus = null;
Jeff Browne08ae382012-09-07 20:36:36 -0700318 if (!mPendingStatusChangeBroadcast) {
319 mPendingStatusChangeBroadcast = true;
Jeff Browna7f9c962012-10-17 15:15:12 -0700320 mHandler.sendEmptyMessage(MSG_SEND_STATUS_CHANGE_BROADCAST);
Jeff Browne08ae382012-09-07 20:36:36 -0700321 }
322 }
323
Jeff Browna7f9c962012-10-17 15:15:12 -0700324 private void scheduleUpdateNotificationLocked() {
325 if (!mPendingNotificationUpdate) {
326 mPendingNotificationUpdate = true;
327 mHandler.sendEmptyMessage(MSG_UPDATE_NOTIFICATION);
328 }
329 }
Jeff Browne08ae382012-09-07 20:36:36 -0700330
Jeff Browna7f9c962012-10-17 15:15:12 -0700331 // Runs on the handler.
332 private void handleSendStatusChangeBroadcast() {
333 final Intent intent;
334 synchronized (getSyncRoot()) {
335 if (!mPendingStatusChangeBroadcast) {
336 return;
Jeff Browne08ae382012-09-07 20:36:36 -0700337 }
338
Jeff Browna7f9c962012-10-17 15:15:12 -0700339 mPendingStatusChangeBroadcast = false;
340 intent = new Intent(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED);
341 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
342 intent.putExtra(DisplayManager.EXTRA_WIFI_DISPLAY_STATUS,
343 getWifiDisplayStatusLocked());
344 }
345
346 // Send protected broadcast about wifi display status to registered receivers.
347 getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
348 }
349
350 // Runs on the handler.
351 private void handleUpdateNotification() {
352 final boolean isConnected;
353 synchronized (getSyncRoot()) {
354 if (!mPendingNotificationUpdate) {
355 return;
356 }
357
358 mPendingNotificationUpdate = false;
359 isConnected = (mDisplayDevice != null);
360 }
361
Jeff Brown66692502012-10-18 16:13:44 -0700362 // Cancel the old notification if there is one.
Jeff Browna7f9c962012-10-17 15:15:12 -0700363 mNotificationManager.cancelAsUser(null,
364 R.string.wifi_display_notification_title, UserHandle.ALL);
365
366 if (isConnected) {
367 Context context = getContext();
368
Jeff Brown66692502012-10-18 16:13:44 -0700369 // Initialize pending intents for the notification outside of the lock because
370 // creating a pending intent requires a call into the activity manager.
371 if (mSettingsPendingIntent == null) {
372 Intent settingsIntent = new Intent(Settings.ACTION_WIFI_DISPLAY_SETTINGS);
373 settingsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
374 | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
375 | Intent.FLAG_ACTIVITY_CLEAR_TOP);
376 mSettingsPendingIntent = PendingIntent.getActivityAsUser(
377 context, 0, settingsIntent, 0, null, UserHandle.CURRENT);
378 }
379
380 if (mDisconnectPendingIntent == null) {
381 Intent disconnectIntent = new Intent(ACTION_DISCONNECT);
382 mDisconnectPendingIntent = PendingIntent.getBroadcastAsUser(
383 context, 0, disconnectIntent, 0, UserHandle.CURRENT);
384 }
385
386 // Post the notification.
Jeff Browna7f9c962012-10-17 15:15:12 -0700387 Resources r = context.getResources();
388 Notification notification = new Notification.Builder(context)
389 .setContentTitle(r.getString(
390 R.string.wifi_display_notification_title))
391 .setContentText(r.getString(
392 R.string.wifi_display_notification_message))
393 .setContentIntent(mSettingsPendingIntent)
394 .setSmallIcon(R.drawable.ic_notify_wifidisplay)
395 .setOngoing(true)
396 .addAction(android.R.drawable.ic_menu_close_clear_cancel,
397 r.getString(R.string.wifi_display_notification_disconnect),
398 mDisconnectPendingIntent)
399 .build();
400 mNotificationManager.notifyAsUser(null,
401 R.string.wifi_display_notification_title,
402 notification, UserHandle.ALL);
403 }
404 }
405
406 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
407 @Override
408 public void onReceive(Context context, Intent intent) {
409 if (intent.getAction().equals(ACTION_DISCONNECT)) {
410 synchronized (getSyncRoot()) {
411 requestDisconnectLocked();
412 }
413 }
Jeff Browne08ae382012-09-07 20:36:36 -0700414 }
415 };
416
Jeff Browncbad9762012-09-04 21:57:59 -0700417 private final WifiDisplayController.Listener mWifiDisplayListener =
418 new WifiDisplayController.Listener() {
419 @Override
Jeff Brown89d55462012-09-19 11:33:42 -0700420 public void onFeatureStateChanged(int featureState) {
Jeff Browncbad9762012-09-04 21:57:59 -0700421 synchronized (getSyncRoot()) {
Jeff Brown89d55462012-09-19 11:33:42 -0700422 if (mFeatureState != featureState) {
423 mFeatureState = featureState;
Jeff Browne08ae382012-09-07 20:36:36 -0700424 scheduleStatusChangedBroadcastLocked();
425 }
426 }
427 }
428
429 @Override
430 public void onScanStarted() {
431 synchronized (getSyncRoot()) {
Jeff Brown180bbc72012-09-08 23:15:00 -0700432 if (mScanState != WifiDisplayStatus.SCAN_STATE_SCANNING) {
Jeff Brown180bbc72012-09-08 23:15:00 -0700433 mScanState = WifiDisplayStatus.SCAN_STATE_SCANNING;
Jeff Browne08ae382012-09-07 20:36:36 -0700434 scheduleStatusChangedBroadcastLocked();
435 }
436 }
437 }
438
Jeff Brown2444ae72012-10-11 14:30:21 -0700439 @Override
Jeff Brown89d55462012-09-19 11:33:42 -0700440 public void onScanFinished(WifiDisplay[] availableDisplays) {
Jeff Browne08ae382012-09-07 20:36:36 -0700441 synchronized (getSyncRoot()) {
Jeff Brown89d55462012-09-19 11:33:42 -0700442 availableDisplays = mPersistentDataStore.applyWifiDisplayAliases(
443 availableDisplays);
444
Jeff Brown180bbc72012-09-08 23:15:00 -0700445 if (mScanState != WifiDisplayStatus.SCAN_STATE_NOT_SCANNING
Jeff Brown89d55462012-09-19 11:33:42 -0700446 || !Arrays.equals(mAvailableDisplays, availableDisplays)) {
Jeff Brown180bbc72012-09-08 23:15:00 -0700447 mScanState = WifiDisplayStatus.SCAN_STATE_NOT_SCANNING;
Jeff Brown89d55462012-09-19 11:33:42 -0700448 mAvailableDisplays = availableDisplays;
Jeff Browne08ae382012-09-07 20:36:36 -0700449 scheduleStatusChangedBroadcastLocked();
450 }
451 }
452 }
453
454 @Override
455 public void onDisplayConnecting(WifiDisplay display) {
456 synchronized (getSyncRoot()) {
Jeff Brown89d55462012-09-19 11:33:42 -0700457 display = mPersistentDataStore.applyWifiDisplayAlias(display);
458
Jeff Brown180bbc72012-09-08 23:15:00 -0700459 if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTING
460 || mActiveDisplay == null
461 || !mActiveDisplay.equals(display)) {
Jeff Brown180bbc72012-09-08 23:15:00 -0700462 mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTING;
463 mActiveDisplay = display;
Jeff Browne08ae382012-09-07 20:36:36 -0700464 scheduleStatusChangedBroadcastLocked();
465 }
466 }
467 }
468
469 @Override
470 public void onDisplayConnectionFailed() {
471 synchronized (getSyncRoot()) {
Jeff Brown180bbc72012-09-08 23:15:00 -0700472 if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED
473 || mActiveDisplay != null) {
Jeff Brown180bbc72012-09-08 23:15:00 -0700474 mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED;
475 mActiveDisplay = null;
Jeff Browne08ae382012-09-07 20:36:36 -0700476 scheduleStatusChangedBroadcastLocked();
477 }
478 }
479 }
480
481 @Override
Jeff Brownf8f0edd2012-09-11 17:05:11 -0700482 public void onDisplayConnected(WifiDisplay display, Surface surface,
483 int width, int height, int flags) {
Jeff Browne08ae382012-09-07 20:36:36 -0700484 synchronized (getSyncRoot()) {
Jeff Brown89d55462012-09-19 11:33:42 -0700485 display = mPersistentDataStore.applyWifiDisplayAlias(display);
Jeff Brownf8f0edd2012-09-11 17:05:11 -0700486 handleConnectLocked(display, surface, width, height, flags);
Jeff Browne08ae382012-09-07 20:36:36 -0700487
Jeff Brown180bbc72012-09-08 23:15:00 -0700488 if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTED
489 || mActiveDisplay == null
490 || !mActiveDisplay.equals(display)) {
Jeff Brown180bbc72012-09-08 23:15:00 -0700491 mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTED;
492 mActiveDisplay = display;
Jeff Browne08ae382012-09-07 20:36:36 -0700493 scheduleStatusChangedBroadcastLocked();
494 }
Jeff Browncbad9762012-09-04 21:57:59 -0700495 }
496 }
497
498 @Override
499 public void onDisplayDisconnected() {
500 // Stop listening.
501 synchronized (getSyncRoot()) {
Jeff Browne08ae382012-09-07 20:36:36 -0700502 handleDisconnectLocked();
503
Jeff Brown180bbc72012-09-08 23:15:00 -0700504 if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED
505 || mActiveDisplay != null) {
Jeff Brown180bbc72012-09-08 23:15:00 -0700506 mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED;
507 mActiveDisplay = null;
Jeff Browne08ae382012-09-07 20:36:36 -0700508 scheduleStatusChangedBroadcastLocked();
509 }
Jeff Browncbad9762012-09-04 21:57:59 -0700510 }
511 }
512 };
513
514 private final class WifiDisplayDevice extends DisplayDevice {
Jeff Brownee4f0292012-10-15 15:31:59 -0700515 private String mName;
Jeff Browncbad9762012-09-04 21:57:59 -0700516 private final int mWidth;
517 private final int mHeight;
518 private final float mRefreshRate;
519 private final int mFlags;
Jeff Brown92130f62012-10-24 21:28:33 -0700520 private final String mAddress;
Jeff Browncbad9762012-09-04 21:57:59 -0700521
522 private Surface mSurface;
523 private DisplayDeviceInfo mInfo;
524
525 public WifiDisplayDevice(IBinder displayToken, String name,
Jeff Brown92130f62012-10-24 21:28:33 -0700526 int width, int height, float refreshRate, int flags, String address,
Jeff Browncbad9762012-09-04 21:57:59 -0700527 Surface surface) {
528 super(WifiDisplayAdapter.this, displayToken);
529 mName = name;
530 mWidth = width;
531 mHeight = height;
532 mRefreshRate = refreshRate;
533 mFlags = flags;
Jeff Brown92130f62012-10-24 21:28:33 -0700534 mAddress = address;
Jeff Browncbad9762012-09-04 21:57:59 -0700535 mSurface = surface;
536 }
537
538 public void clearSurfaceLocked() {
539 mSurface = null;
540 sendTraversalRequestLocked();
541 }
542
Jeff Brownee4f0292012-10-15 15:31:59 -0700543 public void setNameLocked(String name) {
544 mName = name;
545 mInfo = null;
546 }
547
Jeff Browncbad9762012-09-04 21:57:59 -0700548 @Override
549 public void performTraversalInTransactionLocked() {
550 setSurfaceInTransactionLocked(mSurface);
551 }
552
553 @Override
554 public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
555 if (mInfo == null) {
556 mInfo = new DisplayDeviceInfo();
557 mInfo.name = mName;
558 mInfo.width = mWidth;
559 mInfo.height = mHeight;
560 mInfo.refreshRate = mRefreshRate;
561 mInfo.flags = mFlags;
Jeff Brown92130f62012-10-24 21:28:33 -0700562 mInfo.type = Display.TYPE_WIFI;
563 mInfo.address = mAddress;
Jeff Brownd728bf52012-09-08 18:05:28 -0700564 mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;
Jeff Browncbad9762012-09-04 21:57:59 -0700565 mInfo.setAssumedDensityForExternalDisplay(mWidth, mHeight);
566 }
567 return mInfo;
568 }
569 }
Jeff Browna7f9c962012-10-17 15:15:12 -0700570
571 private final class WifiDisplayHandler extends Handler {
572 public WifiDisplayHandler(Looper looper) {
573 super(looper, null, true /*async*/);
574 }
575
576 @Override
577 public void handleMessage(Message msg) {
578 switch (msg.what) {
579 case MSG_SEND_STATUS_CHANGE_BROADCAST:
580 handleSendStatusChangeBroadcast();
581 break;
582
583 case MSG_UPDATE_NOTIFICATION:
584 handleUpdateNotification();
585 break;
586 }
587 }
588 }
Jeff Browncbad9762012-09-04 21:57:59 -0700589}