DisplayManager.java revision 98365d7663cbd82979a5700faf0050220b01084d
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 17package android.hardware.display; 18 19import android.content.Context; 20import android.os.Handler; 21import android.os.IBinder; 22import android.os.Looper; 23import android.os.Message; 24import android.os.RemoteException; 25import android.os.ServiceManager; 26import android.util.Log; 27import android.util.SparseArray; 28import android.view.CompatibilityInfoHolder; 29import android.view.Display; 30import android.view.DisplayInfo; 31 32import java.util.ArrayList; 33 34/** 35 * Manages the properties, media routing and power state of attached displays. 36 * <p> 37 * Get an instance of this class by calling 38 * {@link android.content.Context#getSystemService(java.lang.String) 39 * Context.getSystemService()} with the argument 40 * {@link android.content.Context#DISPLAY_SERVICE}. 41 * </p> 42 */ 43public final class DisplayManager { 44 private static final String TAG = "DisplayManager"; 45 private static final boolean DEBUG = false; 46 47 private static final int MSG_DISPLAY_ADDED = 1; 48 private static final int MSG_DISPLAY_REMOVED = 2; 49 private static final int MSG_DISPLAY_CHANGED = 3; 50 51 private static DisplayManager sInstance; 52 53 private final IDisplayManager mDm; 54 55 // Guarded by mDisplayLock 56 private final Object mDisplayLock = new Object(); 57 private final ArrayList<DisplayListenerDelegate> mDisplayListeners = 58 new ArrayList<DisplayListenerDelegate>(); 59 60 61 private DisplayManager(IDisplayManager dm) { 62 mDm = dm; 63 } 64 65 /** 66 * Gets an instance of the display manager. 67 * 68 * @return The display manager instance, may be null early in system startup 69 * before the display manager has been fully initialized. 70 * 71 * @hide 72 */ 73 public static DisplayManager getInstance() { 74 synchronized (DisplayManager.class) { 75 if (sInstance == null) { 76 IBinder b = ServiceManager.getService(Context.DISPLAY_SERVICE); 77 if (b != null) { 78 sInstance = new DisplayManager(IDisplayManager.Stub.asInterface(b)); 79 } 80 } 81 return sInstance; 82 } 83 } 84 85 /** 86 * Get information about a particular logical display. 87 * 88 * @param displayId The logical display id. 89 * @param outInfo A structure to populate with the display info. 90 * @return True if the logical display exists, false otherwise. 91 * @hide 92 */ 93 public boolean getDisplayInfo(int displayId, DisplayInfo outInfo) { 94 try { 95 return mDm.getDisplayInfo(displayId, outInfo); 96 } catch (RemoteException ex) { 97 Log.e(TAG, "Could not get display information from display manager.", ex); 98 return false; 99 } 100 } 101 102 /** 103 * Gets information about a logical display. 104 * 105 * The display metrics may be adjusted to provide compatibility 106 * for legacy applications. 107 * 108 * @param displayId The logical display id. 109 * @param applicationContext The application context from which to obtain 110 * compatible metrics. 111 * @return The display object. 112 */ 113 public Display getDisplay(int displayId, Context applicationContext) { 114 if (applicationContext == null) { 115 throw new IllegalArgumentException("applicationContext must not be null"); 116 } 117 118 CompatibilityInfoHolder cih = null; 119 if (displayId == Display.DEFAULT_DISPLAY) { 120 cih = applicationContext.getCompatibilityInfo(); 121 } 122 return getCompatibleDisplay(displayId, cih); 123 } 124 125 /** 126 * Gets information about a logical display. 127 * 128 * The display metrics may be adjusted to provide compatibility 129 * for legacy applications. 130 * 131 * @param displayId The logical display id. 132 * @param cih The compatibility info, or null if none is required. 133 * @return The display object. 134 * 135 * @hide 136 */ 137 public Display getCompatibleDisplay(int displayId, CompatibilityInfoHolder cih) { 138 return new Display(displayId, cih); 139 } 140 141 /** 142 * Gets information about a logical display without applying any compatibility metrics. 143 * 144 * @param displayId The logical display id. 145 * @return The display object. 146 * 147 * @hide 148 */ 149 public Display getRealDisplay(int displayId) { 150 return getCompatibleDisplay(displayId, null); 151 } 152 153 /** 154 * Registers an display listener to receive notifications about when 155 * displays are added, removed or changed. 156 * 157 * @param listener The listener to register. 158 * @param handler The handler on which the listener should be invoked, or null 159 * if the listener should be invoked on the calling thread's looper. 160 * 161 * @see #unregisterDisplayListener 162 */ 163 public void registerDisplayListener(DisplayListener listener, Handler handler) { 164 if (listener == null) { 165 throw new IllegalArgumentException("listener must not be null"); 166 } 167 168 synchronized (mDisplayLock) { 169 int index = findDisplayListenerLocked(listener); 170 if (index < 0) { 171 mDisplayListeners.add(new DisplayListenerDelegate(listener, handler)); 172 } 173 } 174 } 175 176 /** 177 * Unregisters an input device listener. 178 * 179 * @param listener The listener to unregister. 180 * 181 * @see #registerDisplayListener 182 */ 183 public void unregisterDisplayListener(DisplayListener listener) { 184 if (listener == null) { 185 throw new IllegalArgumentException("listener must not be null"); 186 } 187 188 synchronized (mDisplayLock) { 189 int index = findDisplayListenerLocked(listener); 190 if (index >= 0) { 191 DisplayListenerDelegate d = mDisplayListeners.get(index); 192 d.removeCallbacksAndMessages(null); 193 mDisplayListeners.remove(index); 194 } 195 } 196 } 197 198 private int findDisplayListenerLocked(DisplayListener listener) { 199 final int numListeners = mDisplayListeners.size(); 200 for (int i = 0; i < numListeners; i++) { 201 if (mDisplayListeners.get(i).mListener == listener) { 202 return i; 203 } 204 } 205 return -1; 206 } 207 208 /** 209 * Listens for changes in available display devices. 210 */ 211 public interface DisplayListener { 212 /** 213 * Called whenever a logical display has been added to the system. 214 * Use {@link DisplayManager#getDisplay} to get more information about the display. 215 * 216 * @param displayId The id of the logical display that was added. 217 */ 218 void onDisplayAdded(int displayId); 219 220 /** 221 * Called whenever a logical display has been removed from the system. 222 * 223 * @param displayId The id of the logical display that was removed. 224 */ 225 void onDisplayRemoved(int displayId); 226 227 /** 228 * Called whenever the properties of a logical display have changed. 229 * 230 * @param displayId The id of the logical display that changed. 231 */ 232 void onDisplayChanged(int displayId); 233 } 234 235 private static final class DisplayListenerDelegate extends Handler { 236 public final DisplayListener mListener; 237 238 public DisplayListenerDelegate(DisplayListener listener, Handler handler) { 239 super(handler != null ? handler.getLooper() : Looper.myLooper()); 240 mListener = listener; 241 } 242 243 @Override 244 public void handleMessage(Message msg) { 245 switch (msg.what) { 246 case MSG_DISPLAY_ADDED: 247 mListener.onDisplayAdded(msg.arg1); 248 break; 249 case MSG_DISPLAY_REMOVED: 250 mListener.onDisplayRemoved(msg.arg1); 251 break; 252 case MSG_DISPLAY_CHANGED: 253 mListener.onDisplayChanged(msg.arg1); 254 break; 255 } 256 } 257 } 258} 259