Fix app crash while running in second display

Launch DocumentsUI at second display,then crash happened after
pressing right button of mouse to trigger conext menu.

Create a new DecorContext instance for external display.

Bug: b/117215434
Test: atest PhoneWindowTest, DecorContextTest and manual test
Change-Id: I2f1dc1ac3721a20a7a49cfcde97fb168fcbfcc56
diff --git a/core/java/com/android/internal/policy/DecorContext.java b/core/java/com/android/internal/policy/DecorContext.java
index 67cdd5d..56a40a3 100644
--- a/core/java/com/android/internal/policy/DecorContext.java
+++ b/core/java/com/android/internal/policy/DecorContext.java
@@ -25,6 +25,8 @@
 import android.view.WindowManagerImpl;
 import android.view.contentcapture.ContentCaptureManager;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.lang.ref.WeakReference;
 
 /**
@@ -34,7 +36,8 @@
  *
  * @hide
  */
-class DecorContext extends ContextThemeWrapper {
+@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+public class DecorContext extends ContextThemeWrapper {
     private PhoneWindow mPhoneWindow;
     private WindowManager mWindowManager;
     private Resources mActivityResources;
@@ -42,8 +45,9 @@
 
     private WeakReference<Context> mActivityContext;
 
+    @VisibleForTesting
     public DecorContext(Context context, Context activityContext) {
-        super(context, null);
+        super(context.createDisplayContext(activityContext.getDisplay()), null);
         mActivityContext = new WeakReference<>(activityContext);
         mActivityResources = activityContext.getResources();
     }
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index d945e13..d50a70e 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -1943,6 +1943,13 @@
         initializeElevation();
     }
 
+    @Override
+    public void onMovedToDisplay(int displayId, Configuration config) {
+        super.onMovedToDisplay(displayId, config);
+        // Have to explicitly update displayId because it may use DecorContext
+        getContext().updateDisplay(displayId);
+    }
+
     /**
      * Determines if the workspace is entirely covered by the window.
      * @return {@code true} when the window is filling the entire screen/workspace.
diff --git a/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java b/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java
new file mode 100644
index 0000000..cd70608
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.policy;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import static org.junit.Assert.assertEquals;
+
+import android.content.Context;
+import android.hardware.display.DisplayManagerGlobal;
+import android.platform.test.annotations.Presubmit;
+import android.view.Display;
+import android.view.DisplayAdjustments;
+import android.view.DisplayInfo;
+import android.view.WindowManager;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests {@link DecorContext}.
+ */
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public final class DecorContextTest {
+    private Context mContext;
+    private static final int EXTERNAL_DISPLAY = DEFAULT_DISPLAY + 1;
+
+    @Before
+    public void setUp() throws Exception {
+        mContext = InstrumentationRegistry.getContext();
+    }
+
+    @Test
+    public void testDecorContextWithDefaultDisplay() {
+        DecorContext context = new DecorContext(mContext.getApplicationContext(), mContext);
+
+        assertDecorContextDisplay(DEFAULT_DISPLAY, context);
+    }
+
+    @Test
+    public void testDecorContextWithExternalDisplay() {
+        Display display = new Display(DisplayManagerGlobal.getInstance(), EXTERNAL_DISPLAY,
+                new DisplayInfo(), DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
+        DecorContext context = new DecorContext(mContext.getApplicationContext(),
+                mContext.createDisplayContext(display));
+
+        assertDecorContextDisplay(EXTERNAL_DISPLAY, context);
+    }
+
+    private static void assertDecorContextDisplay(int expectedDisplayId,
+            DecorContext decorContext) {
+        WindowManager wm = (WindowManager) decorContext.getSystemService(Context.WINDOW_SERVICE);
+        Display associatedDisplay = wm.getDefaultDisplay();
+        assertEquals(expectedDisplayId, associatedDisplay.getDisplayId());
+    }
+}