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 android.app.Flags; 20 import android.content.Context; 21 import android.service.notification.ZenPolicy; 22 import android.util.Log; 23 24 import androidx.annotation.NonNull; 25 import androidx.annotation.Nullable; 26 import androidx.preference.Preference; 27 28 import com.android.settingslib.core.AbstractPreferenceController; 29 30 import com.google.common.base.Preconditions; 31 32 import java.util.function.Function; 33 34 /** 35 * Base class for any preference controllers pertaining to any single Zen mode. 36 */ 37 abstract class AbstractZenModePreferenceController extends AbstractPreferenceController { 38 39 private static final String TAG = "AbstractZenModePreferenceController"; 40 41 @Nullable 42 protected ZenModesBackend mBackend; 43 44 @Nullable // only until setZenMode() is called 45 private ZenMode mZenMode; 46 47 @NonNull 48 private final String mKey; 49 50 // ZenModesBackend should only be passed in if the preference controller may set the user's 51 // policy for this zen mode. Otherwise, if the preference controller is essentially read-only 52 // and leads to a further Settings screen, backend should be null. AbstractZenModePreferenceController(@onNull Context context, @NonNull String key, @Nullable ZenModesBackend backend)53 AbstractZenModePreferenceController(@NonNull Context context, @NonNull String key, 54 @Nullable ZenModesBackend backend) { 55 super(context); 56 mBackend = backend; 57 mKey = key; 58 } 59 60 @Override 61 @NonNull getPreferenceKey()62 public String getPreferenceKey() { 63 return mKey; 64 } 65 66 @Override isAvailable()67 public boolean isAvailable() { 68 if (mZenMode != null) { 69 return Flags.modesUi() && isAvailable(mZenMode); 70 } else { 71 return Flags.modesUi(); 72 } 73 } 74 isAvailable(@onNull ZenMode zenMode)75 public boolean isAvailable(@NonNull ZenMode zenMode) { 76 return true; 77 } 78 79 // Called by parent Fragment onAttach, for any methods (such as isAvailable()) that need 80 // zen mode info before onStart. Most callers should use updateZenMode instead, which will 81 // do any further necessary propagation. setZenMode(@onNull ZenMode zenMode)82 protected final void setZenMode(@NonNull ZenMode zenMode) { 83 mZenMode = zenMode; 84 } 85 86 // Called by the parent Fragment onStart, which means it will happen before resume. updateZenMode(@onNull Preference preference, @NonNull ZenMode zenMode)87 public void updateZenMode(@NonNull Preference preference, @NonNull ZenMode zenMode) { 88 mZenMode = zenMode; 89 updateState(preference); 90 } 91 92 @Override updateState(Preference preference)93 public final void updateState(Preference preference) { 94 super.updateState(preference); 95 if (mZenMode != null) { 96 updateState(preference, mZenMode); 97 } 98 } 99 updateState(Preference preference, @NonNull ZenMode zenMode)100 abstract void updateState(Preference preference, @NonNull ZenMode zenMode); 101 102 @Override getSummary()103 public final CharSequence getSummary() { 104 if (mZenMode != null) { 105 return getSummary(mZenMode); 106 } else { 107 return null; 108 } 109 } 110 111 @Nullable getSummary(@onNull ZenMode zenMode)112 protected CharSequence getSummary(@NonNull ZenMode zenMode) { 113 return null; 114 } 115 116 /** 117 * Subclasses should call this method (or a more specific one, like {@link #savePolicy} from 118 * their {@code onPreferenceChange()} or similar, in order to apply changes to the mode being 119 * edited (e.g. {@code saveMode(mode -> { mode.setX(value); return mode; } }. 120 * 121 * @param updater Function to update the {@link ZenMode}. Modifying and returning the same 122 * instance is ok. 123 */ saveMode(Function<ZenMode, ZenMode> updater)124 protected final boolean saveMode(Function<ZenMode, ZenMode> updater) { 125 Preconditions.checkState(mBackend != null); 126 ZenMode mode = mZenMode; 127 if (mode == null) { 128 Log.wtf(TAG, "Cannot save mode, it hasn't been loaded (" + getClass() + ")"); 129 return false; 130 } 131 mode = updater.apply(mode); 132 mBackend.updateMode(mode); 133 return true; 134 } 135 savePolicy(Function<ZenPolicy.Builder, ZenPolicy.Builder> updater)136 protected final boolean savePolicy(Function<ZenPolicy.Builder, ZenPolicy.Builder> updater) { 137 return saveMode(mode -> { 138 ZenPolicy.Builder policyBuilder = new ZenPolicy.Builder(mode.getPolicy()); 139 policyBuilder = updater.apply(policyBuilder); 140 mode.setPolicy(policyBuilder.build()); 141 return mode; 142 }); 143 } 144 } 145