Redirect to new modes page when modes_ui is on.
The new modes page has essentially no content yet, but this is a rough proof of concept for the existing abstract classes and hopefully serves as a building block for future changes. It lists modes and those preferences lead to contentless pages that will be fleshed out later.. Flag: android.app.modes_ui Bug: 327260745 Test: ZenModePreferenceControllerTest Test: manual; individual pages only have skeleton functionality and should be unit tested in future CLs Change-Id: I12f48b48f761e3c9ff1a173445b15f7536d34edb
This commit is contained in:
@@ -7882,6 +7882,9 @@
|
||||
<!-- Sound: Title for the Do not Disturb option and associated settings page. [CHAR LIMIT=50]-->
|
||||
<string name="zen_mode_settings_title">Do Not Disturb</string>
|
||||
|
||||
<!-- Sound: Title for the Modes option and associated settings page. [CHAR LIMIT=50]-->
|
||||
<string name="zen_modes_list_title">Priority Modes</string>
|
||||
|
||||
<!-- Sound: Summary for the Do not Disturb option and associated settings page. [CHAR LIMIT=240]-->
|
||||
<string name="zen_mode_settings_summary">Only get notified by important people and apps</string>
|
||||
|
||||
|
28
res/xml/modes_list_settings.xml
Normal file
28
res/xml/modes_list_settings.xml
Normal file
@@ -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.
|
||||
-->
|
||||
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:title="@string/zen_modes_list_title" >
|
||||
|
||||
<!-- TODO: b/333682392 - add strings for summary as appropriate -->
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="zen_modes_list">
|
||||
<!-- Preferences leading to rules are added in this PreferenceCategory. -->
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
25
res/xml/modes_rule_settings.xml
Normal file
25
res/xml/modes_rule_settings.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?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.
|
||||
-->
|
||||
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:title="@string/zen_modes_list_title" >
|
||||
|
||||
<!-- TODO: b/308819292 - implement page, delete this test preference -->
|
||||
<Preference
|
||||
android:key="zen_mode_test" />
|
||||
|
||||
</PreferenceScreen>
|
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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 android.app.AutomaticZenRule;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ZenModeFragment extends ZenModeFragmentBase {
|
||||
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
return R.xml.modes_rule_settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
|
||||
// TODO: fill in with all the elements of this page. Each should be an instance of
|
||||
// {@link AbstractZenModePreferenceController}.
|
||||
List<AbstractPreferenceController> prefControllers = new ArrayList<>();
|
||||
return prefControllers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
||||
// Set title for the entire screen
|
||||
ZenMode mode = getMode();
|
||||
AutomaticZenRule azr = getAZR();
|
||||
if (mode == null || azr == null) {
|
||||
return;
|
||||
}
|
||||
getActivity().setTitle(azr.getName());
|
||||
|
||||
// TODO: b/308819292 - implement the real screen!
|
||||
final PreferenceScreen screen = getPreferenceScreen();
|
||||
if (screen == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Preference tmpPref = screen.findPreference("zen_mode_test");
|
||||
if (tmpPref == null) {
|
||||
return;
|
||||
}
|
||||
tmpPref.setTitle(azr.getTriggerDescription());
|
||||
tmpPref.setSummary("active?: " + mode.isActive());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
// TODO: b/332937635 - make this the correct metrics category
|
||||
return SettingsEnums.NOTIFICATION_ZEN_MODE_AUTOMATION;
|
||||
}
|
||||
}
|
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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 com.android.settings.notification.modes.ZenModeFragmentBase.MODE_ID;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.android.settings.core.SubSettingLauncher;
|
||||
import com.android.settings.notification.zen.ZenModeSettings;
|
||||
import com.android.settingslib.RestrictedPreference;
|
||||
|
||||
/**
|
||||
* Preference representing a single mode item on the modes aggregator page. Clicking on this
|
||||
* preference leads to an individual mode's configuration page.
|
||||
*/
|
||||
public class ZenModeListPreference extends RestrictedPreference {
|
||||
final Context mContext;
|
||||
ZenMode mZenMode;
|
||||
|
||||
ZenModeListPreference(Context context, ZenMode zenMode) {
|
||||
super(context);
|
||||
mContext = context;
|
||||
mZenMode = zenMode;
|
||||
setTitle(mZenMode.getRule().getName());
|
||||
setSummary((mZenMode.isActive() ? "ACTIVE" : "inactive") + ": "
|
||||
+ mZenMode.getRule().getTriggerDescription());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick() {
|
||||
// TODO: b/322373473 - This implementation is a hack that just leads to the old DND page
|
||||
// for manual only; remove this in favor of the real implementation.
|
||||
if (mZenMode.isManualDnd()) {
|
||||
new SubSettingLauncher(mContext)
|
||||
.setDestination(ZenModeSettings.class.getName())
|
||||
.setSourceMetricsCategory(SettingsEnums.NOTIFICATION_ZEN_MODE)
|
||||
.launch();
|
||||
} else {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString(MODE_ID, mZenMode.getId());
|
||||
new SubSettingLauncher(mContext)
|
||||
.setDestination(ZenModeFragment.class.getName())
|
||||
.setArguments(bundle)
|
||||
.setSourceMetricsCategory(SettingsEnums.NOTIFICATION_ZEN_MODE_AUTOMATION)
|
||||
.launch();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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 android.app.NotificationManager;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.Context;
|
||||
import android.service.notification.ConditionProviderService;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.utils.ManagedServiceSettings;
|
||||
import com.android.settings.utils.ZenServiceListing;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.search.SearchIndexable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@SearchIndexable
|
||||
public class ZenModesListFragment extends ZenModesFragmentBase {
|
||||
protected final ManagedServiceSettings.Config CONFIG = getConditionProviderConfig();
|
||||
|
||||
@Override
|
||||
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
|
||||
ZenServiceListing serviceListing = new ZenServiceListing(getContext(), CONFIG);
|
||||
serviceListing.reloadApprovedServices();
|
||||
return buildPreferenceControllers(context, this, serviceListing);
|
||||
}
|
||||
|
||||
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
|
||||
@Nullable Fragment parent, @Nullable ZenServiceListing serviceListing) {
|
||||
// We need to redefine ZenModesBackend here even though mBackend exists so that this method
|
||||
// can be static; it must be static to be able to be used in SEARCH_INDEX_DATA_PROVIDER.
|
||||
ZenModesBackend backend = ZenModesBackend.getInstance(context);
|
||||
List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
controllers.add(new ZenModesListPreferenceController(
|
||||
context, parent, backend));
|
||||
|
||||
// TODO: b/326442408 - Add controller for "Add Mode" preference/flow, which is what uses
|
||||
// the ZenServiceListing.
|
||||
return controllers;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateZenModeState() {
|
||||
// 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.
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
return R.xml.modes_list_settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
// TODO: b/332937635 - add new & set metrics categories correctly
|
||||
return SettingsEnums.NOTIFICATION_ZEN_MODE_AUTOMATION;
|
||||
}
|
||||
|
||||
protected static ManagedServiceSettings.Config getConditionProviderConfig() {
|
||||
return new ManagedServiceSettings.Config.Builder()
|
||||
.setTag(TAG)
|
||||
.setIntentAction(ConditionProviderService.SERVICE_INTERFACE)
|
||||
.setConfigurationIntentAction(NotificationManager.ACTION_AUTOMATIC_ZEN_RULE)
|
||||
.setPermission(android.Manifest.permission.BIND_CONDITION_PROVIDER_SERVICE)
|
||||
.setNoun("condition provider")
|
||||
.build();
|
||||
}
|
||||
|
||||
// TODO: b/322373473 - Add 3-dot options menu with capability to delete modes.
|
||||
|
||||
/**
|
||||
* For Search.
|
||||
*/
|
||||
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider(R.xml.modes_list_settings) {
|
||||
|
||||
@Override
|
||||
public List<String> getNonIndexableKeys(Context context) {
|
||||
final List<String> keys = super.getNonIndexableKeys(context);
|
||||
// TODO: b/332937523 - determine if this should be removed once the preference
|
||||
// controller adds dynamic data to index
|
||||
keys.add(ZenModesListPreferenceController.KEY);
|
||||
return keys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AbstractPreferenceController> createPreferenceControllers(
|
||||
Context context) {
|
||||
return buildPreferenceControllers(context, null, null);
|
||||
}
|
||||
};
|
||||
}
|
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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 android.app.Flags;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
/**
|
||||
* Controller for the PreferenceCategory on the modes aggregator page ({@link ZenModesListFragment})
|
||||
* containing links to each individual mode. This is a central controller that populates and updates
|
||||
* all the preferences that then lead to a mode configuration page.
|
||||
*/
|
||||
public class ZenModesListPreferenceController extends AbstractPreferenceController {
|
||||
protected static final String KEY = "zen_modes_list";
|
||||
|
||||
@Nullable
|
||||
protected Fragment mParent;
|
||||
protected ZenModesBackend mBackend;
|
||||
|
||||
public ZenModesListPreferenceController(Context context, @Nullable Fragment parent,
|
||||
@NonNull ZenModesBackend backend) {
|
||||
super(context);
|
||||
mParent = parent;
|
||||
mBackend = backend;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return Flags.modesUi();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
if (mBackend == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The preference given us is a PreferenceCategory; create one preference inside the
|
||||
// category for each rule that exists.
|
||||
PreferenceCategory category = (PreferenceCategory) preference;
|
||||
|
||||
// TODO: b/322373473 - This is not the right way to replace these preferences; we should
|
||||
// follow something similar to what
|
||||
// ZenModeAutomaticRulesPreferenceController does to change rules
|
||||
// only as necessary and update them.
|
||||
category.removeAll();
|
||||
|
||||
for (ZenMode mode : mBackend.getModes()) {
|
||||
Preference pref = new ZenModeListPreference(mContext, mode);
|
||||
category.addPreference(pref);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.settings.notification.zen;
|
||||
|
||||
import android.app.Flags;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.ContentObserver;
|
||||
@@ -27,7 +28,9 @@ import android.provider.Settings;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.notification.modes.ZenModesListFragment;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnPause;
|
||||
import com.android.settingslib.core.lifecycle.events.OnResume;
|
||||
@@ -46,7 +49,9 @@ public class ZenModePreferenceController extends BasePreferenceController
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
mSettingObserver = new SettingObserver(screen.findPreference(getPreferenceKey()));
|
||||
Preference preference = screen.findPreference(getPreferenceKey());
|
||||
mSettingObserver = new SettingObserver(preference);
|
||||
maybeSetTitleAndDestination(preference);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -71,11 +76,22 @@ public class ZenModePreferenceController extends BasePreferenceController
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
super.updateState(preference);
|
||||
maybeSetTitleAndDestination(preference);
|
||||
if (preference.isEnabled()) {
|
||||
preference.setSummary(mSummaryBuilder.getSoundSummary());
|
||||
}
|
||||
}
|
||||
|
||||
// Only when modes_ui is active: change title & target fragment.
|
||||
private void maybeSetTitleAndDestination(Preference preference) {
|
||||
if (!Flags.modesUi()) {
|
||||
return;
|
||||
}
|
||||
|
||||
preference.setTitle(R.string.zen_modes_list_title);
|
||||
preference.setFragment(ZenModesListFragment.class.getCanonicalName());
|
||||
}
|
||||
|
||||
class SettingObserver extends ContentObserver {
|
||||
private final Uri ZEN_MODE_URI = Settings.Global.getUriFor(Settings.Global.ZEN_MODE);
|
||||
private final Uri ZEN_MODE_CONFIG_ETAG_URI = Settings.Global.getUriFor(
|
||||
|
@@ -16,10 +16,13 @@
|
||||
|
||||
package com.android.settings.notification.zen;
|
||||
|
||||
import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT;
|
||||
|
||||
import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.never;
|
||||
@@ -27,13 +30,20 @@ import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Flags;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.NotificationManager.Policy;
|
||||
import android.content.Context;
|
||||
import android.platform.test.annotations.DisableFlags;
|
||||
import android.platform.test.annotations.EnableFlags;
|
||||
import android.platform.test.flag.junit.SetFlagsRule;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.android.settings.notification.modes.ZenModesListFragment;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
@@ -46,6 +56,9 @@ import org.robolectric.util.ReflectionHelpers;
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class ZenModePreferenceControllerTest {
|
||||
|
||||
@Rule
|
||||
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT);
|
||||
|
||||
@Mock
|
||||
private Preference mPreference;
|
||||
@Mock
|
||||
@@ -96,4 +109,20 @@ public class ZenModePreferenceControllerTest {
|
||||
|
||||
verify(mPreference, never()).setSummary(anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnableFlags(Flags.FLAG_MODES_UI)
|
||||
public void updateState_modesUi_resetsTitleAndFragment() {
|
||||
mController.updateState(mPreference);
|
||||
verify(mPreference).setTitle(anyInt()); // Resource IDs are ints
|
||||
verify(mPreference).setFragment(ZenModesListFragment.class.getCanonicalName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisableFlags(Flags.FLAG_MODES_UI)
|
||||
public void updateState_noModesUi_doesNotSetTitleAndFragment() {
|
||||
mController.updateState(mPreference);
|
||||
verify(mPreference, never()).setTitle(anyInt());
|
||||
verify(mPreference, never()).setFragment(anyString());
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user