Stub out display manager service implementation.

Reverting to the previous stub as the display adapter registration
and the logical to physical mapping is not at all what we are going
to need moving forward.

Fixed up the service initialization order so that the display manager
service has a context from the start.

Change-Id: I717f2f1099c7a77180ef207c371ec8329258850a
This commit is contained in:
Jeff Brown
2012-08-19 20:18:08 -07:00
parent 82d53ce283
commit 848c2dc93b
9 changed files with 150 additions and 253 deletions

View File

@@ -1553,10 +1553,20 @@ public final class ActivityThread {
if (dm != null && !forceUpdate) {
return dm;
}
DisplayManager displayManager = DisplayManager.getInstance();
if (displayManager == null) {
// may be null early in system startup
dm = new DisplayMetrics();
dm.setToDefaults();
return dm;
}
if (dm == null) {
dm = new DisplayMetrics();
mDisplayMetrics.put(ci, dm);
}
CompatibilityInfoHolder cih = new CompatibilityInfoHolder();
cih.set(ci);
Display d = WindowManagerImpl.getDefault().makeCompatible(cih).getDefaultDisplay();

View File

@@ -45,14 +45,19 @@ public final class DisplayManager {
/**
* Gets an instance of the display manager.
* @return The display manager instance.
*
* @return The display manager instance, may be null early in system startup
* before the display manager has been fully initialized.
*
* @hide
*/
public static DisplayManager getInstance() {
synchronized (DisplayManager.class) {
if (sInstance == null) {
IBinder b = ServiceManager.getService(Context.DISPLAY_SERVICE);
sInstance = new DisplayManager(IDisplayManager.Stub.asInterface(b));
if (b != null) {
sInstance = new DisplayManager(IDisplayManager.Stub.asInterface(b));
}
}
return sInstance;
}

View File

@@ -155,13 +155,12 @@ class ServerThread extends Thread {
power = new PowerManagerService();
ServiceManager.addService(Context.POWER_SERVICE, power);
Slog.i(TAG, "Display Manager");
display = new DisplayManagerService();
ServiceManager.addService(Context.DISPLAY_SERVICE, display, true);
Slog.i(TAG, "Activity Manager");
context = ActivityManagerService.main(factoryTest);
display.setContext(context);
Slog.i(TAG, "Display Manager");
display = new DisplayManagerService(context);
ServiceManager.addService(Context.DISPLAY_SERVICE, display, true);
Slog.i(TAG, "Telephony Registry");
ServiceManager.addService("telephony.registry", new TelephonyRegistry(context));

View File

@@ -16,38 +16,33 @@
package com.android.server.display;
import android.view.Display;
/**
* A display adapter makes a single display devices available to the system.
* A display adapter makes zero or more display devices available to the system
* and provides facilities for discovering when displays are connected or disconnected.
* <p>
* For now, all display adapters are registered in the system server but
* in principle it could be done from other processes.
* </p>
*/
public abstract class DisplayAdapter {
/** The current logical Display assignment for this adapter. Will change if other logical
* display is assigned to this adapter */
private int mDisplayId = Display.NO_DISPLAY;
/** Assign the displayId
* @hide */
public void setDisplayId(int displayId) {
mDisplayId = displayId;
}
/** Retrieve the displayId
* @hide */
public int getDisplayId() {
return mDisplayId;
}
/**
* Gets the display adapter name.
* Gets the display adapter name for debugging purposes.
*
* @return The display adapter name.
*/
public abstract String getName();
// TODO: dynamically register display devices
public abstract DisplayDevice getDisplayDevice();
/**
* Registers the display adapter with the display manager.
* The display adapter should register any built-in display devices now.
* Other display devices can be registered dynamically later.
*
* @param listener The listener for callbacks.
*/
public abstract void register(Listener listener);
public interface Listener {
public void onDisplayDeviceAdded(DisplayDevice device);
public void onDisplayDeviceRemoved(DisplayDevice device);
}
}

View File

@@ -18,8 +18,20 @@ package com.android.server.display;
/**
* Represents a physical display device such as the built-in display
* or an external monitor.
* an external monitor, or a WiFi display.
*/
public abstract class DisplayDevice {
/**
* Gets the display adapter that makes the display device available.
*
* @return The display adapter.
*/
public abstract DisplayAdapter getAdapter();
/**
* Gets information about the display device.
*
* @param outInfo The object to populate with the information.
*/
public abstract void getInfo(DisplayDeviceInfo outInfo);
}

View File

@@ -20,6 +20,12 @@ package com.android.server.display;
* Describes the characteristics of a physical display device.
*/
public final class DisplayDeviceInfo {
/**
* Gets the name of the display device, which may be derived from
* EDID or other sources. The name may be displayed to the user.
*/
public String name;
/**
* The width of the display in its natural orientation, in pixels.
* This value is not affected by display rotation.
@@ -38,6 +44,7 @@ public final class DisplayDeviceInfo {
public float yDpi;
public void copyFrom(DisplayDeviceInfo other) {
name = other.name;
width = other.width;
height = other.height;
refreshRate = other.refreshRate;
@@ -46,9 +53,10 @@ public final class DisplayDeviceInfo {
yDpi = other.yDpi;
}
// For debugging purposes
@Override
public String toString() {
return width + " x " + height + ", " + refreshRate + " fps, "
return "\"" + name + "\": " + width + " x " + height + ", " + refreshRate + " fps, "
+ "density " + densityDpi + ", " + xDpi + " x " + yDpi + " dpi";
}
}

View File

@@ -22,8 +22,6 @@ import android.content.pm.PackageManager;
import android.hardware.display.IDisplayManager;
import android.os.Binder;
import android.os.SystemProperties;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.Surface;
@@ -47,41 +45,27 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
private final Object mLock = new Object();
private Context mContext;
private final Context mContext;
private final boolean mHeadless;
private int mDisplayIdSeq = Display.DEFAULT_DISPLAY;
/** All registered DisplayAdapters. */
private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();
private final DisplayInfo mDefaultDisplayInfo = new DisplayInfo();
/** All the DisplayAdapters showing the given displayId. */
private final SparseArray<ArrayList<DisplayAdapter>> mLogicalToPhysicals =
new SparseArray<ArrayList<DisplayAdapter>>();
/** All the DisplayInfos in the system indexed by deviceId */
private final SparseArray<DisplayInfo> mDisplayInfos = new SparseArray<DisplayInfo>();
private final ArrayList<DisplayCallback> mCallbacks =
new ArrayList<DisplayManagerService.DisplayCallback>();
public DisplayManagerService() {
public DisplayManagerService(Context context) {
mContext = context;
mHeadless = SystemProperties.get(SYSTEM_HEADLESS).equals("1");
registerDefaultDisplayAdapter();
}
private void registerDefaultDisplayAdapter() {
if (mHeadless) {
registerDisplayAdapter(new HeadlessDisplayAdapter());
registerDisplayAdapter(new HeadlessDisplayAdapter(mContext));
} else {
registerDisplayAdapter(new SurfaceFlingerDisplayAdapter());
registerDisplayAdapter(new SurfaceFlingerDisplayAdapter(mContext));
}
}
public void setContext(Context context) {
mContext = context;
}
// FIXME: this isn't the right API for the long term
public void getDefaultExternalDisplayDeviceInfo(DisplayDeviceInfo info) {
// hardcoded assuming 720p touch screen plugged into HDMI and USB
@@ -90,6 +74,11 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
info.height = 720;
}
/**
* Returns true if the device is headless.
*
* @return True if the device is headless.
*/
public boolean isHeadless() {
return mHeadless;
}
@@ -101,12 +90,10 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
*/
public void setDisplayInfo(int displayId, DisplayInfo info) {
synchronized (mLock) {
DisplayInfo localInfo = mDisplayInfos.get(displayId);
if (localInfo == null) {
localInfo = new DisplayInfo();
mDisplayInfos.put(displayId, localInfo);
if (displayId != Display.DEFAULT_DISPLAY) {
throw new UnsupportedOperationException();
}
localInfo.copyFrom(info);
mDefaultDisplayInfo.copyFrom(info);
}
}
@@ -118,177 +105,32 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
@Override // Binder call
public boolean getDisplayInfo(int displayId, DisplayInfo outInfo) {
synchronized (mLock) {
DisplayInfo localInfo = mDisplayInfos.get(displayId);
if (localInfo == null) {
if (displayId != Display.DEFAULT_DISPLAY) {
return false;
}
outInfo.copyFrom(localInfo);
outInfo.copyFrom(mDefaultDisplayInfo);
return true;
}
}
/**
* Inform the service of a new physical display. A new logical displayId is created and the new
* physical display is immediately bound to it. Use removeAdapterFromDisplay to disconnect it.
*
* @param adapter The wrapper for information associated with the physical display.
*/
public void registerDisplayAdapter(DisplayAdapter adapter) {
int displayId;
DisplayCallback[] callbacks;
synchronized (mLock) {
displayId = mDisplayIdSeq;
do {
// Find the next unused displayId. (Pretend like it might ever wrap around).
mDisplayIdSeq++;
if (mDisplayIdSeq < 0) {
mDisplayIdSeq = Display.DEFAULT_DISPLAY + 1;
}
} while (mDisplayInfos.get(mDisplayIdSeq) != null);
adapter.setDisplayId(displayId);
createDisplayInfoLocked(displayId, adapter);
ArrayList<DisplayAdapter> list = new ArrayList<DisplayAdapter>();
list.add(adapter);
mLogicalToPhysicals.put(displayId, list);
mDisplayAdapters.add(adapter);
callbacks = mCallbacks.toArray(new DisplayCallback[mCallbacks.size()]);
}
for (int i = callbacks.length - 1; i >= 0; i--) {
callbacks[i].displayAdded(displayId);
}
// TODO: Notify SurfaceFlinger of new addition.
}
/**
* Connect a logical display to a physical display. Will remove the physical display from any
* logical display it is currently attached to.
*
* @param displayId The logical display. Will be created if it does not already exist.
* @param adapter The physical display.
*/
public void addAdapterToDisplay(int displayId, DisplayAdapter adapter) {
if (adapter == null) {
// TODO: Or throw NPE?
Slog.e(TAG, "addDeviceToDisplay: Attempt to add null adapter");
return;
}
synchronized (mLock) {
if (!mDisplayAdapters.contains(adapter)) {
// TOOD: Handle unregistered adapter with exception or return value.
Slog.e(TAG, "addDeviceToDisplay: Attempt to add an unregistered adapter");
return;
private void registerDisplayAdapter(DisplayAdapter adapter) {
mDisplayAdapters.add(adapter);
adapter.register(new DisplayAdapter.Listener() {
@Override
public void onDisplayDeviceAdded(DisplayDevice device) {
DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo();
device.getInfo(deviceInfo);
copyDisplayInfoFromDeviceInfo(mDefaultDisplayInfo, deviceInfo);
}
DisplayInfo displayInfo = mDisplayInfos.get(displayId);
if (displayInfo == null) {
createDisplayInfoLocked(displayId, adapter);
@Override
public void onDisplayDeviceRemoved(DisplayDevice device) {
}
Integer oldDisplayId = adapter.getDisplayId();
if (oldDisplayId != Display.NO_DISPLAY) {
if (oldDisplayId == displayId) {
// adapter already added to displayId.
return;
}
removeAdapterLocked(adapter);
}
ArrayList<DisplayAdapter> list = mLogicalToPhysicals.get(displayId);
if (list == null) {
list = new ArrayList<DisplayAdapter>();
mLogicalToPhysicals.put(displayId, list);
}
list.add(adapter);
adapter.setDisplayId(displayId);
}
// TODO: Notify SurfaceFlinger of new addition.
});
}
/**
* Disconnect the physical display from whichever logical display it is attached to.
* @param adapter The physical display to detach.
*/
public void removeAdapterFromDisplay(DisplayAdapter adapter) {
if (adapter == null) {
// TODO: Or throw NPE?
return;
}
synchronized (mLock) {
if (!mDisplayAdapters.contains(adapter)) {
// TOOD: Handle unregistered adapter with exception or return value.
Slog.e(TAG, "removeDeviceFromDisplay: Attempt to remove an unregistered adapter");
return;
}
removeAdapterLocked(adapter);
}
// TODO: Notify SurfaceFlinger of removal.
}
public void registerDisplayCallback(final DisplayCallback callback) {
synchronized (mLock) {
if (!mCallbacks.contains(callback)) {
mCallbacks.add(callback);
}
}
}
public void unregisterDisplayCallback(final DisplayCallback callback) {
synchronized (mLock) {
mCallbacks.remove(callback);
}
}
/**
* Create a new logical DisplayInfo and fill it in with information from the physical display.
* @param displayId The logical identifier.
* @param adapter The physical display for initial values.
*/
private void createDisplayInfoLocked(int displayId, DisplayAdapter adapter) {
DisplayInfo displayInfo = new DisplayInfo();
DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo();
adapter.getDisplayDevice().getInfo(deviceInfo);
copyDisplayInfoFromDeviceInfo(displayInfo, deviceInfo);
mDisplayInfos.put(displayId, displayInfo);
}
/**
* Disconnect a physical display from its logical display. If there are no more physical
* displays attached to the logical display, delete the logical display.
* @param adapter The physical display to detach.
*/
void removeAdapterLocked(DisplayAdapter adapter) {
int displayId = adapter.getDisplayId();
adapter.setDisplayId(Display.NO_DISPLAY);
ArrayList<DisplayAdapter> list = mLogicalToPhysicals.get(displayId);
if (list != null) {
list.remove(adapter);
if (list.isEmpty()) {
mLogicalToPhysicals.remove(displayId);
// TODO: Keep count of Windows attached to logical display and don't delete if
// there are any outstanding. Also, what keeps the WindowManager from continuing
// to use the logical display?
mDisplayInfos.remove(displayId);
}
}
}
private void copyDisplayInfoFromDeviceInfo(DisplayInfo displayInfo,
DisplayDeviceInfo deviceInfo) {
private void copyDisplayInfoFromDeviceInfo(
DisplayInfo displayInfo, DisplayDeviceInfo deviceInfo) {
// Bootstrap the logical display using the physical display.
displayInfo.appWidth = deviceInfo.width;
displayInfo.appHeight = deviceInfo.height;
@@ -319,19 +161,12 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
pw.println("Headless: " + mHeadless);
DisplayDeviceInfo info = new DisplayDeviceInfo();
for (DisplayAdapter adapter : mDisplayAdapters) {
pw.println("Display for adapter " + adapter.getName()
+ " assigned to Display " + adapter.getDisplayId());
DisplayDevice device = adapter.getDisplayDevice();
pw.print(" ");
device.getInfo(info);
pw.println(info);
synchronized (mLock) {
for (DisplayAdapter adapter : mDisplayAdapters) {
pw.println("Adapter: " + adapter.getName());
}
pw.println("Default display: " + mDefaultDisplayInfo);
}
}
public interface DisplayCallback {
public void displayAdded(int displayId);
public void displayRemoved(int displayId);
}
}

View File

@@ -16,23 +16,20 @@
package com.android.server.display;
import android.content.Context;
import android.util.DisplayMetrics;
/**
* Provides a fake default display for headless systems.
*/
public final class HeadlessDisplayAdapter extends DisplayAdapter {
private final DisplayDevice mDefaultDisplay = new DisplayDevice() {
@Override
public void getInfo(DisplayDeviceInfo outInfo) {
outInfo.width = 640;
outInfo.height = 480;
outInfo.refreshRate = 60;
outInfo.densityDpi = DisplayMetrics.DENSITY_DEFAULT;
outInfo.xDpi = 160;
outInfo.yDpi = 160;
}
};
private final Context mContext;
private final HeadlessDisplayDevice mDefaultDisplayDevice;
public HeadlessDisplayAdapter(Context context) {
mContext = context;
mDefaultDisplayDevice = new HeadlessDisplayDevice();
}
@Override
public String getName() {
@@ -40,7 +37,26 @@ public final class HeadlessDisplayAdapter extends DisplayAdapter {
}
@Override
public DisplayDevice getDisplayDevice() {
return mDefaultDisplay;
public void register(Listener listener) {
listener.onDisplayDeviceAdded(mDefaultDisplayDevice);
}
private final class HeadlessDisplayDevice extends DisplayDevice {
@Override
public DisplayAdapter getAdapter() {
return HeadlessDisplayAdapter.this;
}
@Override
public void getInfo(DisplayDeviceInfo outInfo) {
outInfo.name = mContext.getResources().getString(
com.android.internal.R.string.display_manager_built_in_display);
outInfo.width = 640;
outInfo.height = 480;
outInfo.refreshRate = 60;
outInfo.densityDpi = DisplayMetrics.DENSITY_DEFAULT;
outInfo.xDpi = 160;
outInfo.yDpi = 160;
}
}
}

View File

@@ -16,18 +16,21 @@
package com.android.server.display;
import android.content.Context;
/**
* A display adapter for the displays managed by Surface Flinger.
*/
public final class SurfaceFlingerDisplayAdapter extends DisplayAdapter {
private final Context mContext;
private final SurfaceFlingerDisplayDevice mDefaultDisplayDevice;
private static native void nativeGetDefaultDisplayDeviceInfo(DisplayDeviceInfo outInfo);
private final DisplayDevice mDefaultDisplay = new DisplayDevice() {
@Override
public void getInfo(DisplayDeviceInfo outInfo) {
nativeGetDefaultDisplayDeviceInfo(outInfo);
}
};
public SurfaceFlingerDisplayAdapter(Context context) {
mContext = context;
mDefaultDisplayDevice = new SurfaceFlingerDisplayDevice();
}
@Override
public String getName() {
@@ -35,7 +38,21 @@ public final class SurfaceFlingerDisplayAdapter extends DisplayAdapter {
}
@Override
public DisplayDevice getDisplayDevice() {
return mDefaultDisplay;
public void register(Listener listener) {
listener.onDisplayDeviceAdded(mDefaultDisplayDevice);
}
private final class SurfaceFlingerDisplayDevice extends DisplayDevice {
@Override
public DisplayAdapter getAdapter() {
return SurfaceFlingerDisplayAdapter.this;
}
@Override
public void getInfo(DisplayDeviceInfo outInfo) {
outInfo.name = mContext.getResources().getString(
com.android.internal.R.string.display_manager_built_in_display);
nativeGetDefaultDisplayDeviceInfo(outInfo);
}
}
}