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
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index c471dd2..a117b06 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -155,13 +155,12 @@
             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));
diff --git a/services/java/com/android/server/display/DisplayAdapter.java b/services/java/com/android/server/display/DisplayAdapter.java
index b623906..f9fa7a8 100644
--- a/services/java/com/android/server/display/DisplayAdapter.java
+++ b/services/java/com/android/server/display/DisplayAdapter.java
@@ -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);
+    }
 }
diff --git a/services/java/com/android/server/display/DisplayDevice.java b/services/java/com/android/server/display/DisplayDevice.java
index 6d723f2..57002ff 100644
--- a/services/java/com/android/server/display/DisplayDevice.java
+++ b/services/java/com/android/server/display/DisplayDevice.java
@@ -18,8 +18,20 @@
 
 /**
  * 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);
 }
diff --git a/services/java/com/android/server/display/DisplayDeviceInfo.java b/services/java/com/android/server/display/DisplayDeviceInfo.java
index c60c2e9..9c0f964 100644
--- a/services/java/com/android/server/display/DisplayDeviceInfo.java
+++ b/services/java/com/android/server/display/DisplayDeviceInfo.java
@@ -21,6 +21,12 @@
  */
 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 float yDpi;
 
     public void copyFrom(DisplayDeviceInfo other) {
+        name = other.name;
         width = other.width;
         height = other.height;
         refreshRate = other.refreshRate;
@@ -46,9 +53,10 @@
         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";
     }
 }
diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/java/com/android/server/display/DisplayManagerService.java
index 468bf21..7c0f8fd 100644
--- a/services/java/com/android/server/display/DisplayManagerService.java
+++ b/services/java/com/android/server/display/DisplayManagerService.java
@@ -22,8 +22,6 @@
 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 @@
 
     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 @@
         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 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 @@
     @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 @@
 
         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());
+            }
 
-    public interface DisplayCallback {
-        public void displayAdded(int displayId);
-        public void displayRemoved(int displayId);
+            pw.println("Default display: " + mDefaultDisplayInfo);
+        }
     }
 }
diff --git a/services/java/com/android/server/display/HeadlessDisplayAdapter.java b/services/java/com/android/server/display/HeadlessDisplayAdapter.java
index 3eaf40f..17c2360 100644
--- a/services/java/com/android/server/display/HeadlessDisplayAdapter.java
+++ b/services/java/com/android/server/display/HeadlessDisplayAdapter.java
@@ -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 @@
     }
 
     @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;
+        }
     }
 }
diff --git a/services/java/com/android/server/display/SurfaceFlingerDisplayAdapter.java b/services/java/com/android/server/display/SurfaceFlingerDisplayAdapter.java
index 539f7c1..9531acb 100644
--- a/services/java/com/android/server/display/SurfaceFlingerDisplayAdapter.java
+++ b/services/java/com/android/server/display/SurfaceFlingerDisplayAdapter.java
@@ -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 @@
     }
 
     @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);
+        }
     }
 }