Allow getDisplayContentLocked to return null...

... and check for null returns. This prevents DisplayContent objects
from containing null Display references.

Bug: 7368565 fixed.
Change-Id: I830fb4c1349204c366193657a95a92c48ccee66c
diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java
index 3898ebc..68cdbfc 100644
--- a/services/java/com/android/server/wm/DisplayContent.java
+++ b/services/java/com/android/server/wm/DisplayContent.java
@@ -66,14 +66,17 @@
     int mBaseDisplayWidth = 0;
     int mBaseDisplayHeight = 0;
     int mBaseDisplayDensity = 0;
-    final DisplayInfo mDisplayInfo = new DisplayInfo();
-    final Display mDisplay;
+    private final DisplayInfo mDisplayInfo = new DisplayInfo();
+    private final Display mDisplay;
 
     // Accessed directly by all users.
     boolean layoutNeeded;
     int pendingLayoutChanges;
     final boolean isDefaultDisplay;
 
+    /**
+     * @param display May not be null.
+     */
     DisplayContent(Display display) {
         mDisplay = display;
         mDisplayId = display.getDisplayId();
diff --git a/services/java/com/android/server/wm/DragState.java b/services/java/com/android/server/wm/DragState.java
index 545fce5..72fc180 100644
--- a/services/java/com/android/server/wm/DragState.java
+++ b/services/java/com/android/server/wm/DragState.java
@@ -190,9 +190,11 @@
         }
 
         final WindowList windows = mService.getWindowListLocked(mDisplay);
-        final int N = windows.size();
-        for (int i = 0; i < N; i++) {
-            sendDragStartedLw(windows.get(i), touchX, touchY, mDataDescription);
+        if (windows != null) {
+            final int N = windows.size();
+            for (int i = 0; i < N; i++) {
+                sendDragStartedLw(windows.get(i), touchX, touchY, mDataDescription);
+            }
         }
     }
 
@@ -393,6 +395,9 @@
         final int y = (int) yf;
 
         final WindowList windows = mService.getWindowListLocked(mDisplay);
+        if (windows == null) {
+            return null;
+        }
         final int N = windows.size();
         for (int i = N - 1; i >= 0; i--) {
             WindowState child = windows.get(i);
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index fa450ae..d598a3c 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -2092,6 +2092,11 @@
                 throw new IllegalStateException("Display has not been initialialized");
             }
 
+            final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            if (displayContent == null) {
+                return WindowManagerGlobal.ADD_INVALID_DISPLAY;
+            }
+
             if (mWindowMap.containsKey(client.asBinder())) {
                 Slog.w(TAG, "Window " + client + " is already added");
                 return WindowManagerGlobal.ADD_DUPLICATE_ADD;
@@ -2174,7 +2179,6 @@
                 }
             }
 
-            final DisplayContent displayContent = getDisplayContentLocked(displayId);
             win = new WindowState(this, session, client, token,
                     attachedWindow, seq, attrs, viewVisibility, displayContent);
             if (win.mDeathRecipient == null) {
@@ -5704,6 +5708,7 @@
      * @param width the width of the target bitmap
      * @param height the height of the target bitmap
      */
+    @Override
     public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, int height) {
         if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
                 "screenshotApplications()")) {
@@ -5723,6 +5728,9 @@
             long ident = Binder.clearCallingIdentity();
 
             final DisplayContent displayContent = getDisplayContentLocked(displayId);
+            if (displayContent == null) {
+                return null;
+            }
             final DisplayInfo displayInfo = displayContent.getDisplayInfo();
             dw = displayInfo.logicalWidth;
             dh = displayInfo.logicalHeight;
@@ -6465,6 +6473,7 @@
         return success;
     }
 
+    @Override
     public void addDisplayContentChangeListener(int displayId,
             IDisplayContentChangeListener listener) {
         if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
@@ -6473,14 +6482,17 @@
         }
         synchronized(mWindowMap) {
             DisplayContent displayContent = getDisplayContentLocked(displayId);
-            if (displayContent.mDisplayContentChangeListeners == null) {
-                displayContent.mDisplayContentChangeListeners =
-                        new RemoteCallbackList<IDisplayContentChangeListener>();
-            displayContent.mDisplayContentChangeListeners.register(listener);
+            if (displayContent != null) {
+                if (displayContent.mDisplayContentChangeListeners == null) {
+                    displayContent.mDisplayContentChangeListeners =
+                            new RemoteCallbackList<IDisplayContentChangeListener>();
+                    displayContent.mDisplayContentChangeListeners.register(listener);
+                }
             }
         }
     }
 
+    @Override
     public void removeDisplayContentChangeListener(int displayId,
             IDisplayContentChangeListener listener) {
         if (!checkCallingPermission(android.Manifest.permission.RETRIEVE_WINDOW_INFO,
@@ -6489,11 +6501,13 @@
         }
         synchronized(mWindowMap) {
             DisplayContent displayContent = getDisplayContentLocked(displayId);
-            if (displayContent.mDisplayContentChangeListeners != null) {
-                displayContent.mDisplayContentChangeListeners.unregister(listener);
-                if (displayContent.mDisplayContentChangeListeners
-                        .getRegisteredCallbackCount() == 0) {
-                    displayContent.mDisplayContentChangeListeners = null;
+            if (displayContent != null) {
+                if (displayContent.mDisplayContentChangeListeners != null) {
+                    displayContent.mDisplayContentChangeListeners.unregister(listener);
+                    if (displayContent.mDisplayContentChangeListeners
+                            .getRegisteredCallbackCount() == 0) {
+                        displayContent.mDisplayContentChangeListeners = null;
+                    }
                 }
             }
         }
@@ -7149,7 +7163,6 @@
 
         synchronized(mWindowMap) {
             final DisplayContent displayContent = getDefaultDisplayContentLocked();
-            final Display display = displayContent.getDisplay();
             readForcedDisplaySizeAndDensityLocked(displayContent);
 
             mDisplayReady = true;
@@ -7173,24 +7186,25 @@
         }
     }
 
-    public void displayReady(int displayId) {
+    private void displayReady(int displayId) {
         synchronized(mWindowMap) {
             final DisplayContent displayContent = getDisplayContentLocked(displayId);
-            final DisplayInfo displayInfo;
-            mAnimator.addDisplayLocked(displayId);
-            synchronized(displayContent.mDisplaySizeLock) {
-                // Bootstrap the default logical display from the display manager.
-                displayInfo = displayContent.getDisplayInfo();
-                DisplayInfo newDisplayInfo = mDisplayManagerService.getDisplayInfo(displayId);
-                if (newDisplayInfo != null) {
-                    displayInfo.copyFrom(newDisplayInfo);
+            if (displayContent != null) {
+                mAnimator.addDisplayLocked(displayId);
+                synchronized(displayContent.mDisplaySizeLock) {
+                    // Bootstrap the default logical display from the display manager.
+                    final DisplayInfo displayInfo = displayContent.getDisplayInfo();
+                    DisplayInfo newDisplayInfo = mDisplayManagerService.getDisplayInfo(displayId);
+                    if (newDisplayInfo != null) {
+                        displayInfo.copyFrom(newDisplayInfo);
+                    }
+                    displayContent.mInitialDisplayWidth = displayInfo.logicalWidth;
+                    displayContent.mInitialDisplayHeight = displayInfo.logicalHeight;
+                    displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi;
+                    displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth;
+                    displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight;
+                    displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity;
                 }
-                displayContent.mInitialDisplayWidth = displayInfo.logicalWidth;
-                displayContent.mInitialDisplayHeight = displayInfo.logicalHeight;
-                displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi;
-                displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth;
-                displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight;
-                displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity;
             }
         }
     }
@@ -7831,12 +7845,15 @@
         // TODO(cmautner): Access to DisplayContent should be locked on mWindowMap. Doing that
         //  could lead to deadlock since this is called from ActivityManager.
         final DisplayContent displayContent = getDisplayContentLocked(displayId);
-        synchronized(displayContent.mDisplaySizeLock) {
-            size.x = displayContent.mInitialDisplayWidth;
-            size.y = displayContent.mInitialDisplayHeight;
+        if (displayContent != null) {
+            synchronized(displayContent.mDisplaySizeLock) {
+                size.x = displayContent.mInitialDisplayWidth;
+                size.y = displayContent.mInitialDisplayHeight;
+            }
         }
     }
 
+    @Override
     public void setForcedDisplaySize(int displayId, int width, int height) {
         synchronized(mWindowMap) {
             // Set some sort of reasonable bounds on the size of the display that we
@@ -7845,14 +7862,15 @@
             final int MIN_HEIGHT = 200;
             final int MAX_SCALE = 2;
             final DisplayContent displayContent = getDisplayContentLocked(displayId);
-
-            width = Math.min(Math.max(width, MIN_WIDTH),
-                    displayContent.mInitialDisplayWidth * MAX_SCALE);
-            height = Math.min(Math.max(height, MIN_HEIGHT),
-                    displayContent.mInitialDisplayHeight * MAX_SCALE);
-            setForcedDisplaySizeLocked(displayContent, width, height);
-            Settings.Global.putString(mContext.getContentResolver(),
-                    Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
+            if (displayContent != null) {
+                width = Math.min(Math.max(width, MIN_WIDTH),
+                        displayContent.mInitialDisplayWidth * MAX_SCALE);
+                height = Math.min(Math.max(height, MIN_HEIGHT),
+                        displayContent.mInitialDisplayHeight * MAX_SCALE);
+                setForcedDisplaySizeLocked(displayContent, width, height);
+                Settings.Global.putString(mContext.getContentResolver(),
+                        Settings.Global.DISPLAY_SIZE_FORCED, width + "," + height);
+            }
         }
     }
 
@@ -7895,6 +7913,7 @@
         }
     }
 
+    // displayContent must not be null
     private void setForcedDisplaySizeLocked(DisplayContent displayContent, int width, int height) {
         Slog.i(TAG, "Using new display size: " + width + "x" + height);
 
@@ -7905,25 +7924,32 @@
         reconfigureDisplayLocked(displayContent);
     }
 
+    @Override
     public void clearForcedDisplaySize(int displayId) {
         synchronized(mWindowMap) {
             final DisplayContent displayContent = getDisplayContentLocked(displayId);
-            setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
-                    displayContent.mInitialDisplayHeight);
-            Settings.Global.putString(mContext.getContentResolver(),
-                    Settings.Global.DISPLAY_SIZE_FORCED, "");
+            if (displayContent != null) {
+                setForcedDisplaySizeLocked(displayContent, displayContent.mInitialDisplayWidth,
+                        displayContent.mInitialDisplayHeight);
+                Settings.Global.putString(mContext.getContentResolver(),
+                        Settings.Global.DISPLAY_SIZE_FORCED, "");
+            }
         }
     }
 
+    @Override
     public void setForcedDisplayDensity(int displayId, int density) {
         synchronized(mWindowMap) {
             final DisplayContent displayContent = getDisplayContentLocked(displayId);
-            setForcedDisplayDensityLocked(displayContent, density);
-            Settings.Global.putString(mContext.getContentResolver(),
-                    Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density));
+            if (displayContent != null) {
+                setForcedDisplayDensityLocked(displayContent, density);
+                Settings.Global.putString(mContext.getContentResolver(),
+                        Settings.Global.DISPLAY_DENSITY_FORCED, Integer.toString(density));
+            }
         }
     }
 
+    // displayContent must not be null
     private void setForcedDisplayDensityLocked(DisplayContent displayContent, int density) {
         Slog.i(TAG, "Using new display density: " + density);
 
@@ -7933,15 +7959,19 @@
         reconfigureDisplayLocked(displayContent);
     }
 
+    @Override
     public void clearForcedDisplayDensity(int displayId) {
         synchronized(mWindowMap) {
             final DisplayContent displayContent = getDisplayContentLocked(displayId);
-            setForcedDisplayDensityLocked(displayContent, displayContent.mInitialDisplayDensity);
-            Settings.Global.putString(mContext.getContentResolver(),
-                    Settings.Global.DISPLAY_DENSITY_FORCED, "");
+            if (displayContent != null) {
+                setForcedDisplayDensityLocked(displayContent, displayContent.mInitialDisplayDensity);
+                Settings.Global.putString(mContext.getContentResolver(),
+                        Settings.Global.DISPLAY_DENSITY_FORCED, "");
+            }
         }
     }
 
+    // displayContent must not be null
     private void reconfigureDisplayLocked(DisplayContent displayContent) {
         // TODO: Multidisplay: for now only use with default display.
         mPolicy.setInitialDisplaySize(displayContent.getDisplay(),
@@ -9711,7 +9741,9 @@
             for (int i = 0; i < count; ++i) {
                 final DisplayContent displayContent =
                         getDisplayContentLocked(pendingLayouts.keyAt(i));
-                displayContent.pendingLayoutChanges |= pendingLayouts.valueAt(i);
+                if (displayContent != null) {
+                    displayContent.pendingLayoutChanges |= pendingLayouts.valueAt(i);
+                }
             }
 
             mWindowDetachedWallpaper = animToLayout.mWindowDetachedWallpaper;
@@ -10837,11 +10869,20 @@
         mDisplayContents.put(display.getDisplayId(), displayContent);
     }
 
+    /**
+     * Retrieve the DisplayContent for the specified displayId. Will create a new DisplayContent if
+     * there is a Display for the displayId.
+     * @param displayId The display the caller is interested in.
+     * @return The DisplayContent associated with displayId or null if there is no Display for it.
+     */
     public DisplayContent getDisplayContentLocked(final int displayId) {
         DisplayContent displayContent = mDisplayContents.get(displayId);
         if (displayContent == null) {
-            displayContent = new DisplayContent(mDisplayManager.getDisplay(displayId));
-            mDisplayContents.put(displayId, displayContent);
+            final Display display = mDisplayManager.getDisplay(displayId);
+            if (display != null) {
+                displayContent = new DisplayContent(display);
+                mDisplayContents.put(displayId, displayContent);
+            }
         }
         return displayContent;
     }
@@ -10927,6 +10968,7 @@
         }
     }
 
+    // There is an inherent assumption that this will never return null.
     public DisplayContent getDefaultDisplayContentLocked() {
         return getDisplayContentLocked(Display.DEFAULT_DISPLAY);
     }
@@ -10939,8 +10981,14 @@
         return getDefaultDisplayContentLocked().getDisplayInfo();
     }
 
+    /**
+     * Return the list of WindowStates associated on the passed display.
+     * @param display The screen to return windows from.
+     * @return The list of WindowStates on the screen, or null if the there is no screen.
+     */
     public WindowList getWindowListLocked(final Display display) {
-        return getDisplayContentLocked(display.getDisplayId()).getWindowList();
+        final DisplayContent displayContent = getDisplayContentLocked(display.getDisplayId());
+        return displayContent != null ? displayContent.getWindowList() : null;
     }
 
     @Override
@@ -10949,8 +10997,11 @@
     }
 
     private void handleDisplayAddedLocked(int displayId) {
-        createDisplayContentLocked(mDisplayManager.getDisplay(displayId));
-        displayReady(displayId);
+        final Display display = mDisplayManager.getDisplay(displayId);
+        if (display != null) {
+            createDisplayContentLocked(display);
+            displayReady(displayId);
+        }
     }
 
     @Override
@@ -10960,11 +11011,13 @@
 
     private void handleDisplayRemovedLocked(int displayId) {
         final DisplayContent displayContent = getDisplayContentLocked(displayId);
-        mDisplayContents.delete(displayId);
-        WindowList windows = displayContent.getWindowList();
-        while (!windows.isEmpty()) {
-            final WindowState win = windows.get(windows.size() - 1);
-            removeWindowLocked(win.mSession, win);
+        if (displayContent != null) {
+            mDisplayContents.delete(displayId);
+            WindowList windows = displayContent.getWindowList();
+            while (!windows.isEmpty()) {
+                final WindowState win = windows.get(windows.size() - 1);
+                removeWindowLocked(win.mSession, win);
+            }
         }
         mAnimator.removeDisplayLocked(displayId);
     }