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());
+ }
+}