Merge "Clean up EuiccPreferenceController" into main
diff --git a/res/layout-sw600dp/mode_interstitial_layout.xml b/res/layout-sw600dp/mode_interstitial_layout.xml
new file mode 100644
index 0000000..595f353
--- /dev/null
+++ b/res/layout-sw600dp/mode_interstitial_layout.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2024 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.
+ -->
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingHorizontal="80dp" >
+
+ <include
+ layout="@layout/mode_interstitial_layout_base"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center_horizontal" />
+</FrameLayout>
\ No newline at end of file
diff --git a/res/layout/mode_interstitial_layout.xml b/res/layout/mode_interstitial_layout_base.xml
similarity index 100%
rename from res/layout/mode_interstitial_layout.xml
rename to res/layout/mode_interstitial_layout_base.xml
diff --git a/res/values/aliases.xml b/res/values/aliases.xml
index e17198b..3356977 100644
--- a/res/values/aliases.xml
+++ b/res/values/aliases.xml
@@ -23,5 +23,6 @@
<item name="fingerprint_enroll_finish" type="layout">@layout/fingerprint_enroll_finish_base</item>
<item name="sfps_enroll_finish" type="layout">@layout/sfps_enroll_finish_base</item>
<item name="choose_lock_pattern" type="layout">@layout/choose_lock_pattern_common</item>
+ <item name="mode_interstitial_layout" type="layout">@layout/mode_interstitial_layout_base</item>
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0fcb0d6..ac63cbf 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -3071,10 +3071,9 @@
<string name="sim_change_data_ok">
Use <xliff:g id="carrier" example="Verizon">%1$s</xliff:g>
</string>
- <!-- Title for the dialog asking to user to change the preferred SIM [CHAR LIMIT=30] -->
- <string name="sim_preferred_title">Update preferred SIM?</string>
+
<!-- Message for the dialog asking to user to change the preferred SIM [CHAR LIMIT=NONE] -->
- <string name="sim_preferred_message"><xliff:g id="new_sim">%1$s</xliff:g> is the only SIM in your device. Do you want to use this SIM for mobile data, calls, and SMS messages?</string>
+ <string name="sim_preferred_message"><xliff:g id="new_sim">%1$s</xliff:g> is now your primary SIM</string>
<!-- Title for the dialog asking user to enable auto data switch upon enabling multi-SIM [CHAR LIMIT=30] -->
<string name="enable_auto_data_switch_dialog_title">Improve mobile data coverage?</string>
@@ -7531,7 +7530,7 @@
<string name="select_sim_for_sms">Select a SIM for SMS</string>
<!-- Message for switching data SIM; switching takes a while -->
<string name="data_switch_started">Switching data SIM, this may take up to a minute\u2026</string>
- <!-- Title for selecting specific sim for data in settings. [CHAR LIMIT=40] -->
+ <!-- Title for selecting specific sim/preferred sim for data in settings. [CHAR LIMIT=40] -->
<string name="select_specific_sim_for_data_title">Use <xliff:g id="new_sim" example="carrierA">%1$s</xliff:g> for mobile data?</string>
<!-- Message for selecting specific sim for data in settings. [CHAR LIMIT=NONE] -->
<string name="select_specific_sim_for_data_msg">If you switch to <xliff:g id="new_sim" example="carrierA">%1$s</xliff:g>, <xliff:g id="old_sim" example="carrierB">%2$s</xliff:g> will no longer be used for mobile data.</string>
diff --git a/src/com/android/settings/ResetNetwork.java b/src/com/android/settings/ResetNetwork.java
index c1e3494..ad9f35e 100644
--- a/src/com/android/settings/ResetNetwork.java
+++ b/src/com/android/settings/ResetNetwork.java
@@ -132,7 +132,6 @@
if (Flags.resetMobileNetworkSettings()) {
resetOptions |= ResetNetworkRequest.RESET_IMS_STACK;
resetOptions |= ResetNetworkRequest.RESET_PHONE_PROCESS;
- resetOptions |= ResetNetworkRequest.RESET_RILD;
}
ResetNetworkRequest request = new ResetNetworkRequest(resetOptions);
if (mSubscriptions != null && mSubscriptions.size() > 0) {
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 24d9525..493a27b 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -27,6 +27,8 @@
import android.text.TextUtils;
import android.util.Log;
+import androidx.annotation.Nullable;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.biometrics.face.FaceSettings;
import com.android.settings.communal.CommunalPreferenceController;
@@ -35,6 +37,7 @@
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.safetycenter.SafetyCenterManagerWrapper;
import com.android.settings.security.SecuritySettingsFeatureProvider;
+import com.android.settings.wifi.WifiUtils;
import com.google.android.setupdesign.util.ThemeHelper;
@@ -73,7 +76,18 @@
public static class NetworkProviderSettingsActivity extends SettingsActivity { /* empty */ }
public static class NetworkSelectActivity extends SettingsActivity { /* empty */ }
/** Activity for the Wi-Fi network details settings. */
- public static class WifiDetailsSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class WifiDetailsSettingsActivity extends SettingsActivity {
+ @Override
+ protected void createUiFromIntent(@Nullable Bundle savedState, Intent intent) {
+ Bundle bundle = intent.getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
+ if (TextUtils.isEmpty(bundle.getString(WifiUtils.KEY_CHOSEN_WIFIENTRY_KEY))) {
+ Log.e(getLocalClassName(), "The key of WifiEntry is empty!");
+ finishAndRemoveTask();
+ return;
+ }
+ super.createUiFromIntent(savedState, intent);
+ }
+ }
public static class WifiP2pSettingsActivity extends SettingsActivity { /* empty */ }
public static class AvailableVirtualKeyboardActivity extends SettingsActivity { /* empty */ }
public static class KeyboardLayoutPickerActivity extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/inputmethod/TouchGesturesButtonPreferenceController.java b/src/com/android/settings/inputmethod/TouchGesturesButtonPreferenceController.java
index 12dc076..71fa28b 100644
--- a/src/com/android/settings/inputmethod/TouchGesturesButtonPreferenceController.java
+++ b/src/com/android/settings/inputmethod/TouchGesturesButtonPreferenceController.java
@@ -21,11 +21,13 @@
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
+import android.os.UserHandle;
import android.util.FeatureFlagUtils;
import androidx.fragment.app.Fragment;
import androidx.preference.PreferenceScreen;
+import com.android.settings.Utils;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
@@ -79,10 +81,12 @@
private void showTouchpadGestureEducation() {
mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_LEARN_TOUCHPAD_GESTURE_CLICK);
if (newTouchpadGesturesTutorial()) {
- Intent intent = new Intent(TUTORIAL_ACTION);
- intent.addCategory(Intent.CATEGORY_DEFAULT);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivity(intent);
+ Intent intent = new Intent(TUTORIAL_ACTION)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ .setPackage(Utils.SYSTEMUI_PACKAGE_NAME);
+ // touchpad tutorial must be started as system user as it needs to have access to state
+ // of user 0 sysui instance
+ mContext.startActivityAsUser(intent, UserHandle.SYSTEM);
} else {
TrackpadGestureDialogFragment fragment = new TrackpadGestureDialogFragment();
fragment.setTargetFragment(mParent, 0);
diff --git a/src/com/android/settings/notification/modes/AbstractZenModePreferenceController.java b/src/com/android/settings/notification/modes/AbstractZenModePreferenceController.java
index c473456..b27292a 100644
--- a/src/com/android/settings/notification/modes/AbstractZenModePreferenceController.java
+++ b/src/com/android/settings/notification/modes/AbstractZenModePreferenceController.java
@@ -28,7 +28,9 @@
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
+import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.notification.modes.ZenModesBackend;
@@ -43,13 +45,14 @@
@Nullable protected final ZenModesBackend mBackend;
-
@Nullable // only until setZenMode() is called
private ZenMode mZenMode;
@NonNull
private final String mKey;
+ @NonNull private final MetricsFeatureProvider mMetricsFeatureProvider;
+
/**
* Constructor suitable for "read-only" controllers (e.g. link to a different sub-screen.
* Controllers that call this constructor to initialize themselves <em>cannot</em> call
@@ -59,6 +62,7 @@
super(context);
mKey = key;
mBackend = null;
+ mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider();
}
/**
@@ -71,6 +75,7 @@
super(context);
mKey = key;
mBackend = backend;
+ mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider();
}
@Override
@@ -79,6 +84,11 @@
return mKey;
}
+ @NonNull
+ public MetricsFeatureProvider getMetricsFeatureProvider() {
+ return mMetricsFeatureProvider;
+ }
+
@Override
public boolean isAvailable() {
if (mZenMode != null) {
diff --git a/src/com/android/settings/notification/modes/SetupInterstitialActivity.java b/src/com/android/settings/notification/modes/SetupInterstitialActivity.java
index 8408624..c5beb36 100644
--- a/src/com/android/settings/notification/modes/SetupInterstitialActivity.java
+++ b/src/com/android/settings/notification/modes/SetupInterstitialActivity.java
@@ -29,6 +29,7 @@
import android.annotation.SuppressLint;
import android.app.ActionBar;
+import android.app.AutomaticZenRule;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
@@ -184,22 +185,28 @@
private void setupButton(Button button, @NonNull ZenMode mode) {
button.setText(getString(R.string.zen_mode_setup_button_label, mode.getName()));
- button.setOnClickListener(enableButtonListener(mode.getId()));
+ button.setOnClickListener(enableButtonListener(mode.getId(), mode.getType()));
}
@VisibleForTesting
- View.OnClickListener enableButtonListener(String modeId) {
+ View.OnClickListener enableButtonListener(String modeId, @AutomaticZenRule.Type int modeType) {
return unused -> {
// When clicked, we first reload mode info in case it has changed in the interim,
// then enable the mode and then send the user to the mode's configuration page.
boolean updated = enableMode(modeId);
+ int metricsCategory = switch (modeType) {
+ case TYPE_BEDTIME -> SettingsEnums.ZEN_MODE_INTERSTITIAL_BEDTIME;
+ case TYPE_DRIVING -> SettingsEnums.ZEN_MODE_INTERSTITIAL_DRIVING;
+ default -> SettingsEnums.ZEN_MODE_INTERSTITIAL;
+ };
+
// Don't come back to this activity after sending the user to the modes page, if
// they happen to go back. Forward the activity result in case we got here (indirectly)
// from some app that is waiting for the result.
if (updated) {
ZenSubSettingLauncher.forModeFragment(this, ZenModeFragment.class, modeId,
- SettingsEnums.ZEN_MODE_INTERSTITIAL)
+ metricsCategory)
.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT).launch();
}
finish();
diff --git a/src/com/android/settings/notification/modes/ZenModeTriggerUpdatePreferenceController.java b/src/com/android/settings/notification/modes/ZenModeTriggerUpdatePreferenceController.java
index 1add488..f2302c0 100644
--- a/src/com/android/settings/notification/modes/ZenModeTriggerUpdatePreferenceController.java
+++ b/src/com/android/settings/notification/modes/ZenModeTriggerUpdatePreferenceController.java
@@ -218,6 +218,8 @@
}
return zenMode;
});
+ getMetricsFeatureProvider().action(mContext, SettingsEnums.ACTION_ZEN_MODE_ENABLE_TOGGLE,
+ enabled);
}
private void undoToggleSwitch(Preference preference, boolean wasSwitchedTo) {
diff --git a/src/com/android/settings/notification/modes/ZenModesListFragment.java b/src/com/android/settings/notification/modes/ZenModesListFragment.java
index 2b58f8e..588b320 100644
--- a/src/com/android/settings/notification/modes/ZenModesListFragment.java
+++ b/src/com/android/settings/notification/modes/ZenModesListFragment.java
@@ -23,6 +23,7 @@
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.Lifecycle;
import com.android.settings.R;
import com.android.settings.core.SubSettingLauncher;
@@ -62,9 +63,12 @@
@Override
protected void onUpdatedZenModeState() {
- // TODO: b/322373473 -- update any overall description of modes state here if necessary.
- // Note the preferences linking to individual rules do not need to be updated, as
- // updateState() is called on all preference controllers whenever the page is resumed.
+ // Preferences linking to individual rules do not need to be updated as part of onStart(),
+ // because DashboardFragment does that in onResume(). However, we force the update if we
+ // detect Modes changes in the background with the page open.
+ if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)) {
+ forceUpdatePreferences();
+ }
}
@Override
diff --git a/src/com/android/settings/notification/modes/ZenSettingsObserver.java b/src/com/android/settings/notification/modes/ZenSettingsObserver.java
index a853646..0f22d7d 100644
--- a/src/com/android/settings/notification/modes/ZenSettingsObserver.java
+++ b/src/com/android/settings/notification/modes/ZenSettingsObserver.java
@@ -16,6 +16,7 @@
package com.android.settings.notification.modes;
+import android.app.Flags;
import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
@@ -42,13 +43,17 @@
}
void register() {
- mContext.getContentResolver().registerContentObserver(ZEN_MODE_URI, false, this);
- mContext.getContentResolver().registerContentObserver(ZEN_MODE_CONFIG_ETAG_URI, false,
- this);
+ if (Flags.modesApi() && Flags.modesUi()) {
+ mContext.getContentResolver().registerContentObserver(ZEN_MODE_URI, false, this);
+ mContext.getContentResolver().registerContentObserver(ZEN_MODE_CONFIG_ETAG_URI, false,
+ this);
+ }
}
void unregister() {
- mContext.getContentResolver().unregisterContentObserver(this);
+ if (Flags.modesApi() && Flags.modesUi()) {
+ mContext.getContentResolver().unregisterContentObserver(this);
+ }
}
void setOnChangeListener(@Nullable Runnable callback) {
diff --git a/src/com/android/settings/sim/PreferredSimDialogFragment.java b/src/com/android/settings/sim/PreferredSimDialogFragment.java
index bb69440..96c0eb6 100644
--- a/src/com/android/settings/sim/PreferredSimDialogFragment.java
+++ b/src/com/android/settings/sim/PreferredSimDialogFragment.java
@@ -37,8 +37,8 @@
import com.android.settings.network.SubscriptionUtil;
/**
- * Presents a dialog asking the user if they want to update all services to use a given "preferred"
- * SIM. Typically this would be used in a case where a device goes from having multiple SIMs down to
+ * After androidV, presents a dialog asking the user if they want to update the mobile data.
+ * Typically this would be used in a case where a device goes from having multiple SIMs down to
* only one.
*/
public class PreferredSimDialogFragment extends SimDialogFragment implements
@@ -48,7 +48,7 @@
public static PreferredSimDialogFragment newInstance() {
final PreferredSimDialogFragment fragment = new PreferredSimDialogFragment();
final Bundle args = initArguments(SimDialogActivity.PREFERRED_PICK,
- R.string.sim_preferred_title);
+ R.string.select_specific_sim_for_data_title);
fragment.setArguments(args);
return fragment;
}
@@ -57,7 +57,6 @@
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
final AlertDialog dialog = new AlertDialog.Builder(getContext())
- .setTitle(getTitleResId())
.setPositiveButton(R.string.yes, this)
.setNegativeButton(R.string.no, null)
.create();
@@ -104,10 +103,18 @@
dismiss();
return;
}
+ Log.d(TAG, "SubscriptionInfo: " + info);
+ final CharSequence simName =
+ SubscriptionUtil.getUniqueSubscriptionDisplayName(info, getContext());
+ final String title =
+ getContext().getString(
+ getTitleResId(),
+ simName);
final String message =
getContext().getString(
R.string.sim_preferred_message,
- SubscriptionUtil.getUniqueSubscriptionDisplayName(info, getContext()));
+ simName);
+ dialog.setTitle(title);
dialog.setMessage(message);
}
diff --git a/src/com/android/settings/sim/SimDialogActivity.java b/src/com/android/settings/sim/SimDialogActivity.java
index 2e19641..5512117 100644
--- a/src/com/android/settings/sim/SimDialogActivity.java
+++ b/src/com/android/settings/sim/SimDialogActivity.java
@@ -122,6 +122,7 @@
private void showOrUpdateDialog() {
final int dialogType = getIntent().getIntExtra(DIALOG_TYPE_KEY, INVALID_PICK);
+ Log.d(TAG, "dialogType:" + dialogType);
if (dialogType == PICK_DISMISS) {
finishAndRemoveTask();
@@ -379,8 +380,6 @@
private void setPreferredSim(final int subId) {
setDefaultDataSubId(subId);
- setDefaultSmsSubId(subId);
- setDefaultCallsSubId(subId);
}
private PhoneAccountHandle subscriptionIdToPhoneAccountHandle(final int subId) {
diff --git a/src/com/android/settings/wifi/details2/WifiPrivacyPageProvider.kt b/src/com/android/settings/wifi/details2/WifiPrivacyPageProvider.kt
index e41863c..7744a73 100644
--- a/src/com/android/settings/wifi/details2/WifiPrivacyPageProvider.kt
+++ b/src/com/android/settings/wifi/details2/WifiPrivacyPageProvider.kt
@@ -17,7 +17,6 @@
package com.android.settings.wifi.details2
import android.content.Context
-import android.net.wifi.WifiConfiguration
import android.net.wifi.WifiManager
import android.os.Bundle
import android.os.Handler
@@ -114,19 +113,19 @@
}
})
wifiEntry.wifiConfiguration?.let {
- DeviceNameSwitchPreference(it)
+ DeviceNameSwitchPreference(wifiEntry)
}
}
}
}
@Composable
-fun DeviceNameSwitchPreference(wifiConfiguration: WifiConfiguration){
+fun DeviceNameSwitchPreference(wifiEntry: WifiEntry) {
Spacer(modifier = Modifier.width(SettingsDimension.itemDividerHeight))
CategoryTitle(title = stringResource(R.string.wifi_privacy_device_name_settings))
Spacer(modifier = Modifier.width(SettingsDimension.itemDividerHeight))
var checked by remember {
- mutableStateOf(wifiConfiguration.isSendDhcpHostnameEnabled)
+ mutableStateOf(wifiEntry.wifiConfiguration?.isSendDhcpHostnameEnabled)
}
val context = LocalContext.current
val wifiManager = context.getSystemService(WifiManager::class.java)!!
@@ -143,9 +142,11 @@
}
override val checked = { checked }
override val onCheckedChange: (Boolean) -> Unit = { newChecked ->
- wifiConfiguration.isSendDhcpHostnameEnabled = newChecked
- wifiManager.save(wifiConfiguration, null /* listener */)
- checked = newChecked
+ wifiEntry.wifiConfiguration?.let {
+ it.isSendDhcpHostnameEnabled = newChecked
+ wifiManager.save(it, null /* listener */)
+ checked = newChecked
+ }
}
})
}
diff --git a/tests/robotests/src/com/android/settings/notification/modes/SetupInterstitialActivityTest.java b/tests/robotests/src/com/android/settings/notification/modes/SetupInterstitialActivityTest.java
index 40bf1c7..d60f073 100644
--- a/tests/robotests/src/com/android/settings/notification/modes/SetupInterstitialActivityTest.java
+++ b/tests/robotests/src/com/android/settings/notification/modes/SetupInterstitialActivityTest.java
@@ -128,7 +128,7 @@
SetupInterstitialActivity.class)
.putExtra(EXTRA_AUTOMATIC_ZEN_RULE_ID, MODE_ID));
scenario.onActivity(activity -> {
- View.OnClickListener listener = activity.enableButtonListener(MODE_ID);
+ View.OnClickListener listener = activity.enableButtonListener(MODE_ID, mode.getType());
// simulate button press even though we don't actually have a button
listener.onClick(null);
diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenSettingsObserverTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenSettingsObserverTest.java
new file mode 100644
index 0000000..7fd47d9
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/modes/ZenSettingsObserverTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2024 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.settings.notification.modes;
+
+import static android.provider.Settings.Global.ZEN_MODE_CONFIG_ETAG;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.robolectric.Shadows.shadowOf;
+
+import android.app.Flags;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
+import android.provider.Settings;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.google.common.collect.ImmutableList;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.shadows.ShadowLooper;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+@RunWith(RobolectricTestRunner.class)
+public class ZenSettingsObserverTest {
+
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
+ private static final Uri SETTINGS_URI = Settings.Global.getUriFor(
+ ZEN_MODE_CONFIG_ETAG);
+
+ private Context mContext;
+ private ZenSettingsObserver mObserver;
+
+ @Before
+ public void setUp() {
+ mContext = ApplicationProvider.getApplicationContext();
+ mObserver = new ZenSettingsObserver(mContext);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_MODES_UI)
+ public void register_withFlagEnabled_registersAndCallsBack() {
+ AtomicInteger someValue = new AtomicInteger();
+ mObserver.setOnChangeListener(someValue::incrementAndGet);
+ assertThat(getSettingsContentObservers()).isEmpty();
+
+ mObserver.register();
+ assertThat(getSettingsContentObservers()).hasSize(1);
+
+ getSettingsContentObservers().forEach(o -> o.dispatchChange(false, SETTINGS_URI));
+ ShadowLooper.idleMainLooper();
+ assertThat(someValue.get()).isEqualTo(1);
+
+ mObserver.unregister();
+ assertThat(getSettingsContentObservers()).isEmpty();
+ }
+
+ @Test
+ @DisableFlags(Flags.FLAG_MODES_UI)
+ public void register_withFlagDisabled_doesNotRegister() {
+ mObserver.register();
+ assertThat(getSettingsContentObservers()).isEmpty();
+ mObserver.unregister();
+ assertThat(getSettingsContentObservers()).isEmpty();
+ }
+
+ private ImmutableList<ContentObserver> getSettingsContentObservers() {
+ return ImmutableList.copyOf(
+ shadowOf(mContext.getContentResolver())
+ .getContentObservers(SETTINGS_URI));
+ }
+}