• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package android.hardware.display;
18 
19 import android.content.Context;
20 import android.os.Handler;
21 import android.util.SparseArray;
22 import android.view.Display;
23 
24 import java.util.ArrayList;
25 
26 /**
27  * Manages the properties of attached displays.
28  * <p>
29  * Get an instance of this class by calling
30  * {@link android.content.Context#getSystemService(java.lang.String)
31  * Context.getSystemService()} with the argument
32  * {@link android.content.Context#DISPLAY_SERVICE}.
33  * </p>
34  */
35 public final class DisplayManager {
36     private static final String TAG = "DisplayManager";
37     private static final boolean DEBUG = false;
38 
39     private final Context mContext;
40     private final DisplayManagerGlobal mGlobal;
41 
42     private final Object mLock = new Object();
43     private final SparseArray<Display> mDisplays = new SparseArray<Display>();
44 
45     private final ArrayList<Display> mTempDisplays = new ArrayList<Display>();
46 
47     /**
48      * Broadcast receiver that indicates when the Wifi display status changes.
49      * <p>
50      * The status is provided as a {@link WifiDisplayStatus} object in the
51      * {@link #EXTRA_WIFI_DISPLAY_STATUS} extra.
52      * </p><p>
53      * This broadcast is only sent to registered receivers and can only be sent by the system.
54      * </p>
55      * @hide
56      */
57     public static final String ACTION_WIFI_DISPLAY_STATUS_CHANGED =
58             "android.hardware.display.action.WIFI_DISPLAY_STATUS_CHANGED";
59 
60     /**
61      * Contains a {@link WifiDisplayStatus} object.
62      * @hide
63      */
64     public static final String EXTRA_WIFI_DISPLAY_STATUS =
65             "android.hardware.display.extra.WIFI_DISPLAY_STATUS";
66 
67     /**
68      * Display category: Presentation displays.
69      * <p>
70      * This category can be used to identify secondary displays that are suitable for
71      * use as presentation displays.
72      * </p>
73      *
74      * @see android.app.Presentation for information about presenting content
75      * on secondary displays.
76      * @see #getDisplays(String)
77      */
78     public static final String DISPLAY_CATEGORY_PRESENTATION =
79             "android.hardware.display.category.PRESENTATION";
80 
81     /** @hide */
DisplayManager(Context context)82     public DisplayManager(Context context) {
83         mContext = context;
84         mGlobal = DisplayManagerGlobal.getInstance();
85     }
86 
87     /**
88      * Gets information about a logical display.
89      *
90      * The display metrics may be adjusted to provide compatibility
91      * for legacy applications.
92      *
93      * @param displayId The logical display id.
94      * @return The display object, or null if there is no valid display with the given id.
95      */
getDisplay(int displayId)96     public Display getDisplay(int displayId) {
97         synchronized (mLock) {
98             return getOrCreateDisplayLocked(displayId, false /*assumeValid*/);
99         }
100     }
101 
102     /**
103      * Gets all currently valid logical displays.
104      *
105      * @return An array containing all displays.
106      */
getDisplays()107     public Display[] getDisplays() {
108         return getDisplays(null);
109     }
110 
111     /**
112      * Gets all currently valid logical displays of the specified category.
113      * <p>
114      * When there are multiple displays in a category the returned displays are sorted
115      * of preference.  For example, if the requested category is
116      * {@link #DISPLAY_CATEGORY_PRESENTATION} and there are multiple presentation displays
117      * then the displays are sorted so that the first display in the returned array
118      * is the most preferred presentation display.  The application may simply
119      * use the first display or allow the user to choose.
120      * </p>
121      *
122      * @param category The requested display category or null to return all displays.
123      * @return An array containing all displays sorted by order of preference.
124      *
125      * @see #DISPLAY_CATEGORY_PRESENTATION
126      */
getDisplays(String category)127     public Display[] getDisplays(String category) {
128         final int[] displayIds = mGlobal.getDisplayIds();
129         synchronized (mLock) {
130             try {
131                 if (category == null) {
132                     addMatchingDisplaysLocked(mTempDisplays, displayIds, -1);
133                 } else if (category.equals(DISPLAY_CATEGORY_PRESENTATION)) {
134                     addMatchingDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_WIFI);
135                     addMatchingDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_HDMI);
136                     addMatchingDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_OVERLAY);
137                 }
138                 return mTempDisplays.toArray(new Display[mTempDisplays.size()]);
139             } finally {
140                 mTempDisplays.clear();
141             }
142         }
143     }
144 
addMatchingDisplaysLocked( ArrayList<Display> displays, int[] displayIds, int matchType)145     private void addMatchingDisplaysLocked(
146             ArrayList<Display> displays, int[] displayIds, int matchType) {
147         for (int i = 0; i < displayIds.length; i++) {
148             Display display = getOrCreateDisplayLocked(displayIds[i], true /*assumeValid*/);
149             if (display != null
150                     && (matchType < 0 || display.getType() == matchType)) {
151                 displays.add(display);
152             }
153         }
154     }
155 
getOrCreateDisplayLocked(int displayId, boolean assumeValid)156     private Display getOrCreateDisplayLocked(int displayId, boolean assumeValid) {
157         Display display = mDisplays.get(displayId);
158         if (display == null) {
159             display = mGlobal.getCompatibleDisplay(displayId,
160                     mContext.getCompatibilityInfo(displayId));
161             if (display != null) {
162                 mDisplays.put(displayId, display);
163             }
164         } else if (!assumeValid && !display.isValid()) {
165             display = null;
166         }
167         return display;
168     }
169 
170     /**
171      * Registers an display listener to receive notifications about when
172      * displays are added, removed or changed.
173      *
174      * @param listener The listener to register.
175      * @param handler The handler on which the listener should be invoked, or null
176      * if the listener should be invoked on the calling thread's looper.
177      *
178      * @see #unregisterDisplayListener
179      */
registerDisplayListener(DisplayListener listener, Handler handler)180     public void registerDisplayListener(DisplayListener listener, Handler handler) {
181         mGlobal.registerDisplayListener(listener, handler);
182     }
183 
184     /**
185      * Unregisters an input device listener.
186      *
187      * @param listener The listener to unregister.
188      *
189      * @see #registerDisplayListener
190      */
unregisterDisplayListener(DisplayListener listener)191     public void unregisterDisplayListener(DisplayListener listener) {
192         mGlobal.unregisterDisplayListener(listener);
193     }
194 
195     /**
196      * Initiates a fresh scan of availble Wifi displays.
197      * The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast.
198      * @hide
199      */
scanWifiDisplays()200     public void scanWifiDisplays() {
201         mGlobal.scanWifiDisplays();
202     }
203 
204     /**
205      * Connects to a Wifi display.
206      * The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast.
207      * <p>
208      * Automatically remembers the display after a successful connection, if not
209      * already remembered.
210      * </p><p>
211      * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY} to connect
212      * to unknown displays.  No permissions are required to connect to already known displays.
213      * </p>
214      *
215      * @param deviceAddress The MAC address of the device to which we should connect.
216      * @hide
217      */
connectWifiDisplay(String deviceAddress)218     public void connectWifiDisplay(String deviceAddress) {
219         mGlobal.connectWifiDisplay(deviceAddress);
220     }
221 
222     /**
223      * Disconnects from the current Wifi display.
224      * The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast.
225      * @hide
226      */
disconnectWifiDisplay()227     public void disconnectWifiDisplay() {
228         mGlobal.disconnectWifiDisplay();
229     }
230 
231     /**
232      * Renames a Wifi display.
233      * <p>
234      * The display must already be remembered for this call to succeed.  In other words,
235      * we must already have successfully connected to the display at least once and then
236      * not forgotten it.
237      * </p><p>
238      * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}.
239      * </p>
240      *
241      * @param deviceAddress The MAC address of the device to rename.
242      * @param alias The alias name by which to remember the device, or null
243      * or empty if no alias should be used.
244      * @hide
245      */
renameWifiDisplay(String deviceAddress, String alias)246     public void renameWifiDisplay(String deviceAddress, String alias) {
247         mGlobal.renameWifiDisplay(deviceAddress, alias);
248     }
249 
250     /**
251      * Forgets a previously remembered Wifi display.
252      * <p>
253      * Automatically disconnects from the display if currently connected to it.
254      * </p><p>
255      * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}.
256      * </p>
257      *
258      * @param deviceAddress The MAC address of the device to forget.
259      * @hide
260      */
forgetWifiDisplay(String deviceAddress)261     public void forgetWifiDisplay(String deviceAddress) {
262         mGlobal.forgetWifiDisplay(deviceAddress);
263     }
264 
265     /**
266      * Gets the current Wifi display status.
267      * Watch for changes in the status by registering a broadcast receiver for
268      * {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED}.
269      *
270      * @return The current Wifi display status.
271      * @hide
272      */
getWifiDisplayStatus()273     public WifiDisplayStatus getWifiDisplayStatus() {
274         return mGlobal.getWifiDisplayStatus();
275     }
276 
277     /**
278      * Listens for changes in available display devices.
279      */
280     public interface DisplayListener {
281         /**
282          * Called whenever a logical display has been added to the system.
283          * Use {@link DisplayManager#getDisplay} to get more information about
284          * the display.
285          *
286          * @param displayId The id of the logical display that was added.
287          */
onDisplayAdded(int displayId)288         void onDisplayAdded(int displayId);
289 
290         /**
291          * Called whenever a logical display has been removed from the system.
292          *
293          * @param displayId The id of the logical display that was removed.
294          */
onDisplayRemoved(int displayId)295         void onDisplayRemoved(int displayId);
296 
297         /**
298          * Called whenever the properties of a logical display have changed.
299          *
300          * @param displayId The id of the logical display that changed.
301          */
onDisplayChanged(int displayId)302         void onDisplayChanged(int displayId);
303     }
304 }
305