Postpone setting background when window is set.
The DecorView background is the same as the window background.
If a background is set before the DecorView's window is set,
setWindowBackground will throw an NPE.
This happens when the default theme has android:view set with a
non-null value, so the background is set within the super constructor
(in View.java) before the PhoneWindow is set in the constructor of
DecorView.
Fixes: 137764086
Test: regression test DecoreViewTest.setBackgroundWithNoWindow()
Change-Id: I3b3c31cfe50ffa7284a1b37ca4b2f864be77c838
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 480ff4d..599c354 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -249,6 +249,14 @@
private Drawable mOriginalBackgroundDrawable;
private Drawable mLastOriginalBackgroundDrawable;
private Drawable mResizingBackgroundDrawable;
+
+ /**
+ * Temporary holder for a window background when it is set before {@link #mWindow} is
+ * initialized. It will be set as the actual background once {@link #setWindow(PhoneWindow)} is
+ * called.
+ */
+ @Nullable
+ private Drawable mPendingWindowBackground;
private Drawable mCaptionBackgroundDrawable;
private Drawable mUserCaptionBackgroundDrawable;
@@ -961,6 +969,10 @@
}
public void setWindowBackground(Drawable drawable) {
+ if (mWindow == null) {
+ mPendingWindowBackground = drawable;
+ return;
+ }
if (mOriginalBackgroundDrawable != drawable) {
mOriginalBackgroundDrawable = drawable;
updateBackgroundDrawable();
@@ -2003,6 +2015,11 @@
DecorContext decorContext = (DecorContext) context;
decorContext.setPhoneWindow(mWindow);
}
+ if (mPendingWindowBackground != null) {
+ Drawable background = mPendingWindowBackground;
+ mPendingWindowBackground = null;
+ setWindowBackground(background);
+ }
}
@Override
diff --git a/core/tests/coretests/res/values/styles.xml b/core/tests/coretests/res/values/styles.xml
index dbc4626..0bf4b92 100644
--- a/core/tests/coretests/res/values/styles.xml
+++ b/core/tests/coretests/res/values/styles.xml
@@ -39,4 +39,7 @@
<item name="android:colorBackground">@null</item>
<item name="android:windowBackgroundFallback">#0000FF</item>
</style>
+ <style name="ViewDefaultBackground">
+ <item name="android:background">#00000000</item>
+ </style>
</resources>
diff --git a/core/tests/coretests/src/com/android/internal/policy/DecorViewTest.java b/core/tests/coretests/src/com/android/internal/policy/DecorViewTest.java
index f66717e..62e4efe 100644
--- a/core/tests/coretests/src/com/android/internal/policy/DecorViewTest.java
+++ b/core/tests/coretests/src/com/android/internal/policy/DecorViewTest.java
@@ -76,4 +76,13 @@
expectedBitmap.getPixels(expPixels, 0, w, 0, 0, w, h);
assertThat(Arrays.toString(expPixels)).isEqualTo(Arrays.toString(resPixels));
}
+
+ @Test
+ public void setBackgroundWithNoWindow() {
+ PhoneWindow phoneWindow = new PhoneWindow(mContext);
+ // Set a theme that defines a non-null value for android:background
+ mContext.setTheme(R.style.ViewDefaultBackground);
+ DecorView decorView = (DecorView) phoneWindow.getDecorView();
+ assertThat(decorView.getBackground()).isNotNull();
+ }
}