WifiDisplayAdapter.java revision ee4f029ff4905abbdbc1ce47db2cf2c3510949e9
1cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown/*
2cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Copyright (C) 2012 The Android Open Source Project
3cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown *
4cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
5cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * you may not use this file except in compliance with the License.
6cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * You may obtain a copy of the License at
7cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown *
8cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
9cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown *
10cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Unless required by applicable law or agreed to in writing, software
11cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
12cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * See the License for the specific language governing permissions and
14cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * limitations under the License.
15cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown */
16cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
17cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownpackage com.android.server.display;
18cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
19cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport com.android.internal.util.DumpUtils;
20cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport com.android.internal.util.IndentingPrintWriter;
21cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
22cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.content.Context;
23e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brownimport android.content.Intent;
24e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brownimport android.hardware.display.DisplayManager;
25e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brownimport android.hardware.display.WifiDisplay;
26e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brownimport android.hardware.display.WifiDisplayStatus;
27cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.media.RemoteDisplay;
28cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.os.Handler;
29cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.os.IBinder;
30bc335457462a12434a9df6955de1dd693cdccac7Jeff Brownimport android.util.Slog;
31cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.view.Surface;
32cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
33cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport java.io.PrintWriter;
34e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brownimport java.util.Arrays;
35cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
36cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown/**
37cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Connects to Wifi displays that implement the Miracast protocol.
38cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * <p>
39cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * The Wifi display protocol relies on Wifi direct for discovering and pairing
40cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * with the display.  Once connected, the Media Server opens an RTSP socket and accepts
41cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * a connection from the display.  After session negotiation, the Media Server
42cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * streams encoded buffers to the display.
43cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * </p><p>
44cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * This class is responsible for connecting to Wifi displays and mediating
45cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * the interactions between Media Server, Surface Flinger and the Display Manager Service.
46cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * </p><p>
47cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * Display adapters are guarded by the {@link DisplayManagerService.SyncRoot} lock.
48cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown * </p>
49cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown */
50cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownfinal class WifiDisplayAdapter extends DisplayAdapter {
51cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    private static final String TAG = "WifiDisplayAdapter";
52cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
532444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown    private static final boolean DEBUG = false;
542444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown
5577aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown    private final PersistentDataStore mPersistentDataStore;
5677aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown    private final boolean mSupportsProtectedBuffers;
5789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown
58cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    private WifiDisplayController mDisplayController;
59f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown    private WifiDisplayDevice mDisplayDevice;
60cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
61e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    private WifiDisplayStatus mCurrentStatus;
6289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown    private int mFeatureState;
63180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown    private int mScanState;
64180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown    private int mActiveDisplayState;
65180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown    private WifiDisplay mActiveDisplay;
6689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown    private WifiDisplay[] mAvailableDisplays = WifiDisplay.EMPTY_ARRAY;
6789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown    private WifiDisplay[] mRememberedDisplays = WifiDisplay.EMPTY_ARRAY;
68e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown
69e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    private boolean mPendingStatusChangeBroadcast;
70e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown
71cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    public WifiDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
7289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown            Context context, Handler handler, Listener listener,
7389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown            PersistentDataStore persistentDataStore) {
74cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        super(syncRoot, context, handler, listener, TAG);
7589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        mPersistentDataStore = persistentDataStore;
7677aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown        mSupportsProtectedBuffers = context.getResources().getBoolean(
7777aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown                com.android.internal.R.bool.config_wifiDisplaySupportsProtectedBuffers);
78cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    }
79cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
80cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    @Override
81cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    public void dumpLocked(PrintWriter pw) {
82cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        super.dumpLocked(pw);
83cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
84e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        pw.println("mCurrentStatus=" + getWifiDisplayStatusLocked());
8589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        pw.println("mFeatureState=" + mFeatureState);
86180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown        pw.println("mScanState=" + mScanState);
87180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown        pw.println("mActiveDisplayState=" + mActiveDisplayState);
88180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown        pw.println("mActiveDisplay=" + mActiveDisplay);
8989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        pw.println("mAvailableDisplays=" + Arrays.toString(mAvailableDisplays));
9089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        pw.println("mRememberedDisplays=" + Arrays.toString(mRememberedDisplays));
91e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        pw.println("mPendingStatusChangeBroadcast=" + mPendingStatusChangeBroadcast);
9277aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown        pw.println("mSupportsProtectedBuffers=" + mSupportsProtectedBuffers);
93e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown
94cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        // Try to dump the controller state.
95cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        if (mDisplayController == null) {
96cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            pw.println("mDisplayController=null");
97cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        } else {
98cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            pw.println("mDisplayController:");
99cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
100cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            ipw.increaseIndent();
101cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            DumpUtils.dumpAsync(getHandler(), mDisplayController, ipw, 200);
102cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        }
103cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    }
104cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
105cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    @Override
106cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    public void registerLocked() {
107cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        super.registerLocked();
108cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
10989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        updateRememberedDisplaysLocked();
11089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown
111cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        getHandler().post(new Runnable() {
112cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            @Override
113cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            public void run() {
114cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown                mDisplayController = new WifiDisplayController(
115cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown                        getContext(), getHandler(), mWifiDisplayListener);
116cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            }
117cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        });
118cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    }
119cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
120e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    public void requestScanLocked() {
1212444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown        if (DEBUG) {
1222444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown            Slog.d(TAG, "requestScanLocked");
1232444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown        }
1242444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown
125e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        getHandler().post(new Runnable() {
126e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            @Override
127e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            public void run() {
128e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                if (mDisplayController != null) {
129e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                    mDisplayController.requestScan();
130e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                }
131e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            }
132e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        });
133e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    }
134e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown
135bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown    public void requestConnectLocked(final String address, final boolean trusted) {
1362444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown        if (DEBUG) {
1372444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown            Slog.d(TAG, "requestConnectLocked: address=" + address + ", trusted=" + trusted);
1382444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown        }
1392444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown
140bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown        if (!trusted) {
141bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown            synchronized (getSyncRoot()) {
142bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown                if (!isRememberedDisplayLocked(address)) {
143bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown                    Slog.w(TAG, "Ignoring request by an untrusted client to connect to "
144bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown                            + "an unknown wifi display: " + address);
145bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown                    return;
146bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown                }
147bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown            }
148bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown        }
149bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown
150e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        getHandler().post(new Runnable() {
151e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            @Override
152e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            public void run() {
153e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                if (mDisplayController != null) {
154e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                    mDisplayController.requestConnect(address);
155e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                }
156e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            }
157e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        });
158e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    }
159e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown
160bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown    private boolean isRememberedDisplayLocked(String address) {
161bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown        for (WifiDisplay display : mRememberedDisplays) {
162bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown            if (display.getDeviceAddress().equals(address)) {
163bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown                return true;
164bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown            }
165bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown        }
166bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown        return false;
167bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown    }
168bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown
169e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    public void requestDisconnectLocked() {
1702444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown        if (DEBUG) {
1712444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown            Slog.d(TAG, "requestDisconnectedLocked");
1722444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown        }
1732444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown
174e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        getHandler().post(new Runnable() {
175e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            @Override
176e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            public void run() {
177e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                if (mDisplayController != null) {
178e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                    mDisplayController.requestDisconnect();
179e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                }
180e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            }
181e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        });
182e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    }
183e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown
18489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown    public void requestRenameLocked(String address, String alias) {
1852444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown        if (DEBUG) {
1862444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown            Slog.d(TAG, "requestRenameLocked: address=" + address + ", alias=" + alias);
1872444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown        }
1882444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown
18989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        if (alias != null) {
19089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown            alias = alias.trim();
1912444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown            if (alias.isEmpty() || alias.equals(address)) {
19289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown                alias = null;
19389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown            }
19489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        }
19589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown
19689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        if (mPersistentDataStore.renameWifiDisplay(address, alias)) {
19789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown            mPersistentDataStore.saveIfNeeded();
19889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown            updateRememberedDisplaysLocked();
19989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown            scheduleStatusChangedBroadcastLocked();
20089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        }
201ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown
202ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown        if (mActiveDisplay != null && mActiveDisplay.getDeviceAddress().equals(address)
203ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown                && mDisplayDevice != null) {
204ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown            mDisplayDevice.setNameLocked(mActiveDisplay.getFriendlyDisplayName());
205ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown            sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_CHANGED);
206ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown        }
20789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown    }
20889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown
20989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown    public void requestForgetLocked(String address) {
2102444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown        if (DEBUG) {
2112444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown            Slog.d(TAG, "requestForgetLocked: address=" + address);
2122444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown        }
2132444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown
21489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        if (mPersistentDataStore.forgetWifiDisplay(address)) {
21589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown            mPersistentDataStore.saveIfNeeded();
21689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown            updateRememberedDisplaysLocked();
21789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown            scheduleStatusChangedBroadcastLocked();
21889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        }
21989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown
22089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        if (mActiveDisplay != null && mActiveDisplay.getDeviceAddress().equals(address)) {
22189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown            requestDisconnectLocked();
22289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        }
22389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown    }
22489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown
225e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    public WifiDisplayStatus getWifiDisplayStatusLocked() {
226e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        if (mCurrentStatus == null) {
22789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown            mCurrentStatus = new WifiDisplayStatus(
22889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown                    mFeatureState, mScanState, mActiveDisplayState,
22989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown                    mActiveDisplay, mAvailableDisplays, mRememberedDisplays);
230e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        }
2312444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown
2322444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown        if (DEBUG) {
2332444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown            Slog.d(TAG, "getWifiDisplayStatusLocked: result=" + mCurrentStatus);
2342444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown        }
235e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        return mCurrentStatus;
236e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    }
237cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
23889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown    private void updateRememberedDisplaysLocked() {
23989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        mRememberedDisplays = mPersistentDataStore.getRememberedWifiDisplays();
24089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        mActiveDisplay = mPersistentDataStore.applyWifiDisplayAlias(mActiveDisplay);
24189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        mAvailableDisplays = mPersistentDataStore.applyWifiDisplayAliases(mAvailableDisplays);
24289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown    }
24389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown
244f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown    private void handleConnectLocked(WifiDisplay display,
245f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown            Surface surface, int width, int height, int flags) {
246e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        handleDisconnectLocked();
247e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown
24889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        if (mPersistentDataStore.rememberWifiDisplay(display)) {
24989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown            mPersistentDataStore.saveIfNeeded();
25089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown            updateRememberedDisplaysLocked();
25189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown            scheduleStatusChangedBroadcastLocked();
25289d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        }
25389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown
254f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown        int deviceFlags = 0;
255f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown        if ((flags & RemoteDisplay.DISPLAY_FLAG_SECURE) != 0) {
25677aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown            deviceFlags |= DisplayDeviceInfo.FLAG_SECURE;
25777aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown        }
25877aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown        if (mSupportsProtectedBuffers) {
25977aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown            deviceFlags |= DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
260f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown        }
261f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown
262f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown        float refreshRate = 60.0f; // TODO: get this for real
263f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown
26489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        String name = display.getFriendlyDisplayName();
265f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown        IBinder displayToken = Surface.createDisplay(name);
266f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown        mDisplayDevice = new WifiDisplayDevice(displayToken, name, width, height,
267f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown                refreshRate, deviceFlags, surface);
268f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown        sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_ADDED);
269cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    }
270cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
271e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    private void handleDisconnectLocked() {
272f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown        if (mDisplayDevice != null) {
273f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown            mDisplayDevice.clearSurfaceLocked();
274f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown            sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_REMOVED);
275f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown            mDisplayDevice = null;
276cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        }
277cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    }
278cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
279e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    private void scheduleStatusChangedBroadcastLocked() {
28089d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        mCurrentStatus = null;
281e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        if (!mPendingStatusChangeBroadcast) {
282e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            mPendingStatusChangeBroadcast = true;
283e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            getHandler().post(mStatusChangeBroadcast);
284e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        }
285e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    }
286e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown
287e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    private final Runnable mStatusChangeBroadcast = new Runnable() {
288e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        @Override
289e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        public void run() {
290e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            final Intent intent;
291e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            synchronized (getSyncRoot()) {
292e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                if (!mPendingStatusChangeBroadcast) {
293e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                    return;
294e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                }
295e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown
296e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                mPendingStatusChangeBroadcast = false;
297e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                intent = new Intent(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED);
298e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
299e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                intent.putExtra(DisplayManager.EXTRA_WIFI_DISPLAY_STATUS,
300e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                        getWifiDisplayStatusLocked());
301e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            }
302e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown
303bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown            // Send protected broadcast about wifi display status to registered receivers.
304bc335457462a12434a9df6955de1dd693cdccac7Jeff Brown            getContext().sendBroadcast(intent);
305e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        }
306e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown    };
307e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown
308cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    private final WifiDisplayController.Listener mWifiDisplayListener =
309cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            new WifiDisplayController.Listener() {
310cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        @Override
31189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        public void onFeatureStateChanged(int featureState) {
312e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            synchronized (getSyncRoot()) {
31389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown                if (mFeatureState != featureState) {
31489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown                    mFeatureState = featureState;
315e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                    scheduleStatusChangedBroadcastLocked();
316e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                }
317e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            }
318e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        }
319e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown
320e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        @Override
321e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        public void onScanStarted() {
322e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            synchronized (getSyncRoot()) {
323180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown                if (mScanState != WifiDisplayStatus.SCAN_STATE_SCANNING) {
324180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown                    mScanState = WifiDisplayStatus.SCAN_STATE_SCANNING;
325e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                    scheduleStatusChangedBroadcastLocked();
326e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                }
327e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            }
328e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        }
329e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown
3302444ae7e2b8658a4a90f996e678423558744b4a2Jeff Brown        @Override
33189d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown        public void onScanFinished(WifiDisplay[] availableDisplays) {
332e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            synchronized (getSyncRoot()) {
33389d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown                availableDisplays = mPersistentDataStore.applyWifiDisplayAliases(
33489d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown                        availableDisplays);
33589d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown
336180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown                if (mScanState != WifiDisplayStatus.SCAN_STATE_NOT_SCANNING
33789d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown                        || !Arrays.equals(mAvailableDisplays, availableDisplays)) {
338180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown                    mScanState = WifiDisplayStatus.SCAN_STATE_NOT_SCANNING;
33989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown                    mAvailableDisplays = availableDisplays;
340e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                    scheduleStatusChangedBroadcastLocked();
341e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                }
342e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            }
343e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        }
344e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown
345e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        @Override
346e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        public void onDisplayConnecting(WifiDisplay display) {
347e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            synchronized (getSyncRoot()) {
34889d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown                display = mPersistentDataStore.applyWifiDisplayAlias(display);
34989d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown
350180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown                if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTING
351180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown                        || mActiveDisplay == null
352180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown                        || !mActiveDisplay.equals(display)) {
353180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown                    mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTING;
354180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown                    mActiveDisplay = display;
355e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                    scheduleStatusChangedBroadcastLocked();
356e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                }
357e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            }
358e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        }
359e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown
360e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        @Override
361e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        public void onDisplayConnectionFailed() {
362e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            synchronized (getSyncRoot()) {
363180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown                if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED
364180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown                        || mActiveDisplay != null) {
365180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown                    mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED;
366180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown                    mActiveDisplay = null;
367e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                    scheduleStatusChangedBroadcastLocked();
368e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                }
369e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown            }
370e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        }
371e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown
372e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown        @Override
373f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown        public void onDisplayConnected(WifiDisplay display, Surface surface,
374f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown                int width, int height, int flags) {
375cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            synchronized (getSyncRoot()) {
37689d5546d7fd3a3bb19820c42e8b4527013dd6545Jeff Brown                display = mPersistentDataStore.applyWifiDisplayAlias(display);
377f8f0eddd07d22ab815d97dd32ae6ed52dc31a80cJeff Brown                handleConnectLocked(display, surface, width, height, flags);
378e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown
379180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown                if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_CONNECTED
380180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown                        || mActiveDisplay == null
381180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown                        || !mActiveDisplay.equals(display)) {
382180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown                    mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_CONNECTED;
383180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown                    mActiveDisplay = display;
384e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                    scheduleStatusChangedBroadcastLocked();
385e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                }
386cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            }
387cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        }
388cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
389cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        @Override
390cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        public void onDisplayDisconnected() {
391cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            // Stop listening.
392cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            synchronized (getSyncRoot()) {
393e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                handleDisconnectLocked();
394e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown
395180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown                if (mActiveDisplayState != WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED
396180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown                        || mActiveDisplay != null) {
397180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown                    mActiveDisplayState = WifiDisplayStatus.DISPLAY_STATE_NOT_CONNECTED;
398180bbc71810496e280e9993177bfeddb3ad1f558Jeff Brown                    mActiveDisplay = null;
399e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                    scheduleStatusChangedBroadcastLocked();
400e08ae388d63c4db8f9d9a7ecd634f9a51f6e91b9Jeff Brown                }
401cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            }
402cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        }
403cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    };
404cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
405cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    private final class WifiDisplayDevice extends DisplayDevice {
406ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown        private String mName;
407cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        private final int mWidth;
408cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        private final int mHeight;
409cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        private final float mRefreshRate;
410cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        private final int mFlags;
411cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
412cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        private Surface mSurface;
413cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        private DisplayDeviceInfo mInfo;
414cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
415cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        public WifiDisplayDevice(IBinder displayToken, String name,
416cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown                int width, int height, float refreshRate, int flags,
417cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown                Surface surface) {
418cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            super(WifiDisplayAdapter.this, displayToken);
419cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            mName = name;
420cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            mWidth = width;
421cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            mHeight = height;
422cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            mRefreshRate = refreshRate;
423cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            mFlags = flags;
424cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            mSurface = surface;
425cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        }
426cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
427cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        public void clearSurfaceLocked() {
428cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            mSurface = null;
429cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            sendTraversalRequestLocked();
430cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        }
431cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
432ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown        public void setNameLocked(String name) {
433ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown            mName = name;
434ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown            mInfo = null;
435ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown        }
436ee4f029ff4905abbdbc1ce47db2cf2c3510949e9Jeff Brown
437cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        @Override
438cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        public void performTraversalInTransactionLocked() {
439cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            setSurfaceInTransactionLocked(mSurface);
440cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        }
441cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
442cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        @Override
443cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
444cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            if (mInfo == null) {
445cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown                mInfo = new DisplayDeviceInfo();
446cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown                mInfo.name = mName;
447cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown                mInfo.width = mWidth;
448cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown                mInfo.height = mHeight;
449cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown                mInfo.refreshRate = mRefreshRate;
450cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown                mInfo.flags = mFlags;
451d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown                mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;
452cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown                mInfo.setAssumedDensityForExternalDisplay(mWidth, mHeight);
453cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            }
454cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown            return mInfo;
455cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        }
456cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    }
457cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown}
458