Allow use of custom configurations via attachBaseContext
Test: ./gradlew appcompat:connectedCheck
BUG: 138325067
Change-Id: I229a35efaafb85b0f006b5467bb6d6d896dff2b8
diff --git a/appcompat/src/androidTest/AndroidManifest.xml b/appcompat/src/androidTest/AndroidManifest.xml
index bb6f018..09c7dc4 100644
--- a/appcompat/src/androidTest/AndroidManifest.xml
+++ b/appcompat/src/androidTest/AndroidManifest.xml
@@ -165,6 +165,10 @@
android:configChanges="orientation|screenSize"/>
<activity
+ android:name="androidx.appcompat.app.NightModeCustomConfigurationActivity"
+ android:theme="@style/Theme.AppCompat.DayNight"/>
+
+ <activity
android:name="androidx.appcompat.app.AppCompatVectorDrawableIntegrationActivity"/>
<activity
diff --git a/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeCustomConfigurationActivity.java b/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeCustomConfigurationActivity.java
new file mode 100644
index 0000000..ec3d5b7
--- /dev/null
+++ b/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeCustomConfigurationActivity.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 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 androidx.appcompat.app;
+
+import android.content.Context;
+import android.content.res.Configuration;
+
+import java.util.Locale;
+
+public class NightModeCustomConfigurationActivity extends NightModeActivity {
+ public static final float CUSTOM_FONT_SCALE = 4.24f;
+ public static final Locale CUSTOM_LOCALE = Locale.CANADA_FRENCH;
+
+ @Override
+ protected void attachBaseContext(Context newBase) {
+ Configuration config = new Configuration();
+ config.fontScale = CUSTOM_FONT_SCALE;
+ config.locale = CUSTOM_LOCALE;
+
+ Context configContext = newBase.createConfigurationContext(config);
+ super.attachBaseContext(configContext);
+ }
+}
diff --git a/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeCustomFontScaleTestCase.kt b/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeCustomFontScaleTestCase.kt
new file mode 100644
index 0000000..b43493b
--- /dev/null
+++ b/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeCustomFontScaleTestCase.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright 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 androidx.appcompat.app
+
+import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO
+import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES
+import androidx.appcompat.app.NightModeCustomConfigurationActivity.CUSTOM_FONT_SCALE
+import androidx.appcompat.testutils.NightModeUtils
+import androidx.appcompat.testutils.NightModeUtils.NightSetMode
+import androidx.appcompat.testutils.NightModeUtils.setNightModeAndWaitForDestroy
+import androidx.test.filters.LargeTest
+import androidx.test.rule.ActivityTestRule
+import org.junit.After
+import org.junit.Assert.assertEquals
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+@LargeTest
+@RunWith(Parameterized::class)
+class NightModeCustomFontScaleTestCase(private val setMode: NightSetMode) {
+ @get:Rule
+ val rule = ActivityTestRule(NightModeCustomConfigurationActivity::class.java, false, false)
+
+ @Before
+ fun setup() {
+ // By default we'll set the night mode to NO, which allows us to make better
+ // assumptions in the tests below
+ AppCompatDelegate.setDefaultNightMode(MODE_NIGHT_NO)
+ // Launch the test activity
+ rule.launchActivity(null)
+ }
+
+ @Test
+ fun testFontScaleIsMaintained() {
+ // Check that the custom configuration properties are maintained
+ val config = rule.activity.resources.configuration
+ assertEquals(CUSTOM_FONT_SCALE, config.fontScale)
+ }
+
+ @Test
+ fun testFontScaleIsMaintainedInDarkTheme() {
+ // Set local night mode to YES
+ setNightModeAndWaitForDestroy(rule, MODE_NIGHT_YES, setMode)
+
+ // Check that the custom configuration properties are maintained
+ val config = rule.activity.resources.configuration
+ assertEquals(CUSTOM_FONT_SCALE, config.fontScale)
+ }
+
+ @After
+ fun cleanup() {
+ rule.finishActivity()
+ // Reset the default night mode
+ NightModeUtils.setNightModeAndWait(rule, MODE_NIGHT_NO, NightSetMode.DEFAULT)
+ }
+
+ companion object {
+ @JvmStatic
+ @Parameterized.Parameters
+ fun data() = listOf(NightSetMode.DEFAULT, NightSetMode.LOCAL)
+ }
+}
diff --git a/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeTestSuite.kt b/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeTestSuite.kt
index 8c24920..cc8aa03 100644
--- a/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeTestSuite.kt
+++ b/appcompat/src/androidTest/java/androidx/appcompat/app/NightModeTestSuite.kt
@@ -25,6 +25,7 @@
NightModeOrientationConfigChangesTestCase::class,
NightModeLateOnCreateTestCase::class,
NightModePreventOverrideConfigTestCase::class,
- NightModeUiModeConfigChangesTestCase::class
+ NightModeUiModeConfigChangesTestCase::class,
+ NightModeCustomFontScaleTestCase::class
)
class NightModeTestSuite
\ No newline at end of file
diff --git a/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegateImpl.java b/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegateImpl.java
index c33e630..6eb3889 100644
--- a/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegateImpl.java
+++ b/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegateImpl.java
@@ -331,7 +331,7 @@
@Override
public void attachBaseContext(Context context) {
// Activity.recreate() cannot be called before attach is complete.
- applyDayNight(false);
+ applyDayNight(false, context.getResources().getConfiguration());
mBaseContextAttached = true;
}
@@ -343,7 +343,7 @@
// Our implicit call to applyDayNight() should not recreate until after the Activity is
// created
- applyDayNight(false);
+ applyDayNight(false, null);
// We lazily fetch the Window for Activities, to allow DayNight to apply in
// attachBaseContext
@@ -498,7 +498,7 @@
// Re-apply Day/Night with the new configuration but disable recreations. Since this
// configuration change has only just happened we can safely just update the resources now
- applyDayNight(false);
+ applyDayNight(false, null);
}
@Override
@@ -2158,10 +2158,11 @@
@Override
public boolean applyDayNight() {
- return applyDayNight(true);
+ return applyDayNight(true, null);
}
- private boolean applyDayNight(final boolean allowRecreation) {
+ private boolean applyDayNight(final boolean allowRecreation,
+ @Nullable Configuration baseConfiguration) {
if (mIsDestroyed) {
// If we're destroyed, ignore the call
return false;
@@ -2169,7 +2170,7 @@
@NightMode final int nightMode = calculateNightMode();
@ApplyableNightMode final int modeToApply = mapNightMode(nightMode);
- final boolean applied = updateForNightMode(modeToApply, allowRecreation);
+ final boolean applied = updateForNightMode(modeToApply, allowRecreation, baseConfiguration);
if (nightMode == MODE_NIGHT_AUTO_TIME) {
getAutoTimeNightModeManager().setup();
@@ -2240,10 +2241,11 @@
*
* @param mode The new night mode to apply
* @param allowRecreation whether to attempt activity recreate
+ * @param baseConfiguration the base configuration to use, if any
* @return true if an action has been taken (recreation, resources updating, etc)
*/
private boolean updateForNightMode(@ApplyableNightMode final int mode,
- final boolean allowRecreation) {
+ final boolean allowRecreation, @Nullable Configuration baseConfiguration) {
boolean handled = false;
final int applicationNightMode = mContext.getApplicationContext()
@@ -2273,7 +2275,7 @@
&& !mBaseContextAttached
&& mHost instanceof android.view.ContextThemeWrapper) {
// If we're here then we can try and apply an override configuration on the Context.
- final Configuration conf = new Configuration();
+ final Configuration conf = new Configuration(baseConfiguration);
conf.uiMode = newNightMode | (conf.uiMode & ~Configuration.UI_MODE_NIGHT_MASK);
try {
@@ -2322,7 +2324,8 @@
if (DEBUG) {
Log.d(TAG, "updateForNightMode. Updating resources config");
}
- updateResourcesConfigurationForNightMode(newNightMode, activityHandlingUiMode);
+ updateResourcesConfigurationForNightMode(newNightMode, activityHandlingUiMode,
+ baseConfiguration);
handled = true;
}
@@ -2340,11 +2343,15 @@
}
private void updateResourcesConfigurationForNightMode(
- final int uiModeNightModeValue, final boolean callOnConfigChange) {
+ final int uiModeNightModeValue, final boolean callOnConfigChange,
+ @Nullable Configuration baseConfiguration) {
// If the Activity is not set to handle uiMode config changes we will
// update the Resources with a new Configuration with an updated UI Mode
final Resources res = mContext.getResources();
final Configuration conf = new Configuration(res.getConfiguration());
+ if (baseConfiguration != null) {
+ conf.updateFrom(baseConfiguration);
+ }
conf.uiMode = uiModeNightModeValue
| (res.getConfiguration().uiMode & ~Configuration.UI_MODE_NIGHT_MASK);
res.updateConfiguration(conf, null);