• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.notification.modes;
18 
19 import static com.google.common.base.Preconditions.checkState;
20 
21 import android.app.Flags;
22 import android.content.Context;
23 import android.service.notification.ZenPolicy;
24 import android.util.Log;
25 
26 import androidx.annotation.NonNull;
27 import androidx.annotation.Nullable;
28 import androidx.annotation.VisibleForTesting;
29 import androidx.preference.Preference;
30 
31 import com.android.settings.overlay.FeatureFactory;
32 import com.android.settingslib.core.AbstractPreferenceController;
33 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
34 import com.android.settingslib.notification.modes.ZenMode;
35 import com.android.settingslib.notification.modes.ZenModesBackend;
36 
37 import java.util.function.Function;
38 
39 /**
40  * Base class for any preference controllers pertaining to any single Zen mode.
41  */
42 abstract class AbstractZenModePreferenceController extends AbstractPreferenceController {
43 
44     private static final String TAG = "AbstractZenModePreferenceController";
45 
46     @Nullable protected final ZenModesBackend mBackend;
47 
48     @Nullable  // only until setZenMode() is called
49     private ZenMode mZenMode;
50 
51     @NonNull
52     private final String mKey;
53 
54     @NonNull private final MetricsFeatureProvider mMetricsFeatureProvider;
55 
56     /**
57      * Constructor suitable for "read-only" controllers (e.g. link to a different sub-screen.
58      * Controllers that call this constructor to initialize themselves <em>cannot</em> call
59      * {@link #saveMode} or {@link #savePolicy} later.
60      */
AbstractZenModePreferenceController(@onNull Context context, @NonNull String key)61     AbstractZenModePreferenceController(@NonNull Context context, @NonNull String key) {
62         super(context);
63         mKey = key;
64         mBackend = null;
65         mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider();
66     }
67 
68     /**
69      * Constructor suitable for controllers that will update the associated {@link ZenMode}.
70      * Controllers that call this constructor to initialize themselves may call {@link #saveMode} or
71      * {@link #savePolicy} later.
72      */
AbstractZenModePreferenceController(@onNull Context context, @NonNull String key, @NonNull ZenModesBackend backend)73     AbstractZenModePreferenceController(@NonNull Context context, @NonNull String key,
74             @NonNull ZenModesBackend backend) {
75         super(context);
76         mKey = key;
77         mBackend = backend;
78         mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider();
79     }
80 
81     @Override
82     @NonNull
getPreferenceKey()83     public String getPreferenceKey() {
84         return mKey;
85     }
86 
87     @NonNull
getMetricsFeatureProvider()88     public MetricsFeatureProvider getMetricsFeatureProvider() {
89         return mMetricsFeatureProvider;
90     }
91 
92     @Override
isAvailable()93     public boolean isAvailable() {
94         if (mZenMode != null) {
95             return Flags.modesUi() && isAvailable(mZenMode);
96         } else {
97             return Flags.modesUi();
98         }
99     }
100 
isAvailable(@onNull ZenMode zenMode)101     public boolean isAvailable(@NonNull ZenMode zenMode) {
102         return true;
103     }
104 
105     /**
106      * Assigns the {@link ZenMode} of this controller, so that it can be used later from
107      * {@link #isAvailable()} and {@link #updateState(Preference)}.
108      */
setZenMode(@onNull ZenMode zenMode)109     final void setZenMode(@NonNull ZenMode zenMode) {
110         mZenMode = zenMode;
111     }
112 
113     @Override
updateState(Preference preference)114     public final void updateState(Preference preference) {
115         super.updateState(preference);
116         if (mZenMode != null) {
117             updateState(preference, mZenMode);
118         }
119     }
120 
updateState(Preference preference, @NonNull ZenMode zenMode)121     abstract void updateState(Preference preference, @NonNull ZenMode zenMode);
122 
123     @Override
getSummary()124     public final CharSequence getSummary() {
125         if (mZenMode != null) {
126             return getSummary(mZenMode);
127         } else {
128             return null;
129         }
130     }
131 
132     @Nullable
getSummary(@onNull ZenMode zenMode)133     protected CharSequence getSummary(@NonNull ZenMode zenMode) {
134         return null;
135     }
136 
137     /**
138      * Subclasses should call this method (or a more specific one, like {@link #savePolicy} from
139      * their {@code onPreferenceChange()} or similar, in order to apply changes to the mode being
140      * edited (e.g. {@code saveMode(mode -> { mode.setX(value); return mode; } }.
141      *
142      * @param updater Function to update the {@link ZenMode}. Modifying and returning the same
143      *                instance is ok.
144      */
saveMode(Function<ZenMode, ZenMode> updater)145     protected final boolean saveMode(Function<ZenMode, ZenMode> updater) {
146         checkState(mBackend != null);
147         ZenMode mode = mZenMode;
148         if (mode == null) {
149             Log.wtf(TAG, "Cannot save mode, it hasn't been loaded (" + getClass() + ")");
150             return false;
151         }
152         mode = updater.apply(mode);
153         mBackend.updateMode(mode);
154         return true;
155     }
156 
savePolicy(Function<ZenPolicy.Builder, ZenPolicy.Builder> updater)157     protected final boolean savePolicy(Function<ZenPolicy.Builder, ZenPolicy.Builder> updater) {
158         return saveMode(mode -> {
159             ZenPolicy.Builder policyBuilder = new ZenPolicy.Builder(mode.getPolicy());
160             policyBuilder = updater.apply(policyBuilder);
161             mode.setPolicy(policyBuilder.build());
162             return mode;
163         });
164     }
165 
166     @VisibleForTesting(otherwise = VisibleForTesting.NONE)
167     @Nullable
getZenMode()168     ZenMode getZenMode() {
169         return mZenMode;
170     }
171 
172     /**
173      * Convenience method for tests. Assigns the {@link ZenMode} of this controller, and calls
174      * {@link #updateState(Preference)} immediately.
175      */
176     @VisibleForTesting(otherwise = VisibleForTesting.NONE)
updateZenMode(@onNull Preference preference, @NonNull ZenMode zenMode)177     final void updateZenMode(@NonNull Preference preference, @NonNull ZenMode zenMode) {
178         mZenMode = zenMode;
179         updateState(preference);
180     }
181 }
182