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