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.AutomaticZenRule;
20 import android.content.Context;
21 import android.os.Bundle;
22 import android.util.Log;
23 import android.widget.Toast;
24 
25 import androidx.annotation.NonNull;
26 import androidx.annotation.Nullable;
27 import androidx.preference.Preference;
28 import androidx.preference.PreferenceScreen;
29 
30 import com.android.settings.R;
31 import com.android.settingslib.core.AbstractPreferenceController;
32 
33 import java.util.List;
34 
35 /**
36  * Base class for Settings pages used to configure individual modes.
37  */
38 abstract class ZenModeFragmentBase extends ZenModesFragmentBase {
39     static final String TAG = "ZenModeSettings";
40     static final String MODE_ID = "MODE_ID";
41 
42     @Nullable  // only until reloadMode() is called
43     private ZenMode mZenMode;
44 
45     @Override
onAttach(@onNull Context context)46     public void onAttach(@NonNull Context context) {
47         super.onAttach(context);
48 
49         // TODO: b/322373473 - Update if modes page ends up using a different method of passing id
50         Bundle bundle = getArguments();
51         if (bundle != null && bundle.containsKey(MODE_ID)) {
52             String id = bundle.getString(MODE_ID);
53             if (!reloadMode(id)) {
54                 Log.e(TAG, "Mode id " + id + " not found");
55                 toastAndFinish();
56                 return;
57             }
58         } else {
59             Log.e(TAG, "Mode id required to set mode config settings");
60             toastAndFinish();
61             return;
62         }
63         if (mZenMode != null) {
64             // Propagate mode info through to controllers.
65             for (List<AbstractPreferenceController> list : getPreferenceControllers()) {
66                 try {
67                     for (AbstractPreferenceController controller : list) {
68                         // mZenMode guaranteed non-null from reloadMode() above
69                         ((AbstractZenModePreferenceController) controller).setZenMode(mZenMode);
70                     }
71                 } catch (ClassCastException e) {
72                     // ignore controllers that aren't AbstractZenModePreferenceController
73                 }
74             }
75         }
76     }
77 
78     /**
79      * Refresh stored ZenMode data.
80      * @param id the mode ID
81      * @return whether we successfully got mode data from the backend.
82      */
reloadMode(String id)83     private boolean reloadMode(String id) {
84         mZenMode = mBackend.getMode(id);
85         if (mZenMode == null) {
86             return false;
87         }
88         return true;
89     }
90 
91     /**
92      * Refresh ZenMode data any time the system's zen mode state changes (either the zen mode value
93      * itself, or the config), and also (once updated) update the info for all controllers.
94      */
95     @Override
updateZenModeState()96     protected void updateZenModeState() {
97         if (mZenMode == null) {
98             // This shouldn't happen, but guard against it in case
99             toastAndFinish();
100             return;
101         }
102         String id = mZenMode.getId();
103         if (!reloadMode(id)) {
104             Log.d(TAG, "Mode id=" + id + " not found");
105             toastAndFinish();
106             return;
107         }
108         updateControllers();
109     }
110 
updateControllers()111     private void updateControllers() {
112         if (getPreferenceControllers() == null || mZenMode == null) {
113             return;
114         }
115 
116         final PreferenceScreen screen = getPreferenceScreen();
117         if (screen == null) {
118             Log.d(TAG, "PreferenceScreen not found");
119             return;
120         }
121         for (List<AbstractPreferenceController> list : getPreferenceControllers()) {
122             for (AbstractPreferenceController controller : list) {
123                 if (!controller.isAvailable()) {
124                     continue;
125                 }
126 
127                 try {
128                     // Find preference associated with controller
129                     final String key = controller.getPreferenceKey();
130                     final Preference preference = screen.findPreference(key);
131                     if (preference != null) {
132                         AbstractZenModePreferenceController zenController =
133                                 (AbstractZenModePreferenceController) controller;
134                         zenController.updateZenMode(preference, mZenMode);
135                     } else {
136                         Log.d(TAG,
137                                 String.format("Cannot find preference with key %s in Controller %s",
138                                         key, controller.getClass().getSimpleName()));
139                     }
140                 } catch (ClassCastException e) {
141                     // Skip any controllers that aren't AbstractZenModePreferenceController.
142                     Log.d(TAG, "Could not cast: " + controller.getClass().getSimpleName());
143                 }
144             }
145         }
146     }
147 
toastAndFinish()148     private void toastAndFinish() {
149         Toast.makeText(mContext, R.string.zen_mode_rule_not_found_text, Toast.LENGTH_SHORT)
150                 .show();
151         this.finish();
152     }
153 
154     /**
155      * Get current mode data.
156      */
157     @Nullable
getMode()158     public ZenMode getMode() {
159         return mZenMode;
160     }
161 
162     /**
163      * Get AutomaticZenRule associated with current mode data, or null if it doesn't exist.
164      */
165     @Nullable
getAZR()166     public AutomaticZenRule getAZR() {
167         if (mZenMode == null) {
168             return null;
169         }
170         return mZenMode.getRule();
171     }
172 }
173