1 /*
2  * Copyright (C) 2017 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.zen;
18 
19 import android.app.AutomaticZenRule;
20 import android.app.Flags;
21 import android.content.ComponentName;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.pm.ComponentInfo;
25 import android.content.pm.PackageManager;
26 import android.content.pm.ResolveInfo;
27 import android.service.notification.ZenModeConfig;
28 import android.service.notification.ZenModeConfig.ScheduleInfo;
29 import android.text.TextUtils;
30 import android.util.Log;
31 
32 import androidx.fragment.app.Fragment;
33 import androidx.preference.Preference;
34 
35 import com.android.settings.R;
36 import com.android.settings.utils.ManagedServiceSettings;
37 import com.android.settings.utils.ZenServiceListing;
38 import com.android.settingslib.PrimarySwitchPreference;
39 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
40 
41 import java.util.List;
42 import java.util.Map;
43 
44 public class ZenRulePreference extends PrimarySwitchPreference {
45     private static final String TAG = "ZenRulePreference";
46     private static final ManagedServiceSettings.Config CONFIG =
47             ZenModeAutomationSettings.getConditionProviderConfig();
48     final String mId;
49     final Fragment mParent;
50     final Preference mPref;
51     final Context mContext;
52     final ZenModeBackend mBackend;
53     final ZenServiceListing mServiceListing;
54     final PackageManager mPm;
55     final MetricsFeatureProvider mMetricsFeatureProvider;
56     AutomaticZenRule mRule;
57     CharSequence mName;
58 
59     private Intent mIntent;
60 
61     private final ZenRuleScheduleHelper mScheduleHelper = new ZenRuleScheduleHelper();
62 
ZenRulePreference(Context context, final Map.Entry<String, AutomaticZenRule> ruleEntry, Fragment parent, MetricsFeatureProvider metricsProvider, ZenModeBackend backend)63     public ZenRulePreference(Context context,
64             final Map.Entry<String, AutomaticZenRule> ruleEntry,
65             Fragment parent, MetricsFeatureProvider metricsProvider,
66             ZenModeBackend backend) {
67         super(context);
68         mBackend = backend;
69         mContext = context;
70         mRule = ruleEntry.getValue();
71         mName = mRule.getName();
72         mId = ruleEntry.getKey();
73         setKey(mId);
74         mParent = parent;
75         mPm = mContext.getPackageManager();
76         mServiceListing = new ZenServiceListing(mContext, CONFIG);
77         mServiceListing.reloadApprovedServices();
78         mPref = this;
79         mMetricsFeatureProvider = metricsProvider;
80         setAttributes(mRule);
81         setWidgetLayoutResource(getSecondTargetResId());
82 
83         // initialize the checked state of the preference
84         super.setChecked(mRule.isEnabled());
85     }
86 
updatePreference(AutomaticZenRule rule)87     public void updatePreference(AutomaticZenRule rule) {
88         if (!mRule.getName().equals(rule.getName())) {
89             mName = rule.getName();
90             setTitle(mName);
91         }
92 
93         if (mRule.isEnabled() != rule.isEnabled()) {
94             setChecked(rule.isEnabled());
95         }
96         setSummary(computeRuleSummary(rule));
97         mRule = rule;
98     }
99 
100     @Override
onClick()101     public void onClick() {
102         if (mIntent != null) {
103             mContext.startActivity(mIntent);
104         }
105     }
106 
107     @Override
setChecked(boolean checked)108     public void setChecked(boolean checked) {
109         mRule.setEnabled(checked);
110         mBackend.updateZenRule(mId, mRule);
111         setAttributes(mRule);
112         super.setChecked(checked);
113     }
114 
setAttributes(AutomaticZenRule rule)115     protected void setAttributes(AutomaticZenRule rule) {
116         final boolean isSchedule = ZenModeConfig.isValidScheduleConditionId(
117                 rule.getConditionId(), true);
118         final boolean isEvent = ZenModeConfig.isValidEventConditionId(rule.getConditionId());
119 
120         setSummary(computeRuleSummary(rule));
121 
122         setTitle(mName);
123         setPersistent(false);
124 
125         final String action = isSchedule ? ZenModeScheduleRuleSettings.ACTION
126                 : isEvent ? ZenModeEventRuleSettings.ACTION : "";
127         ComponentInfo si = mServiceListing.findService(rule.getOwner());
128         ComponentName settingsActivity = AbstractZenModeAutomaticRulePreferenceController.
129                 getSettingsActivity(mPm, rule, si);
130         mIntent = AbstractZenModeAutomaticRulePreferenceController.getRuleIntent(action,
131                 settingsActivity, mId);
132         // If the intent's activity for this rule doesn't exist or resolve to anything, disable the
133         // preference and rule.
134         List<ResolveInfo> results = mPm.queryIntentActivities(
135                 mIntent, PackageManager.ResolveInfoFlags.of(0));
136         if (mIntent.resolveActivity(mPm) == null || results.size() == 0) {
137             Log.w(TAG, "intent for zen rule invalid: " + mIntent);
138             mIntent = null;
139             setEnabled(false);
140         }
141         setKey(mId);
142     }
143 
computeRuleSummary(AutomaticZenRule rule)144     private String computeRuleSummary(AutomaticZenRule rule) {
145         if (rule != null) {
146             if (Flags.modesApi() && Flags.modesUi()
147                     && !TextUtils.isEmpty(rule.getTriggerDescription())) {
148                 return rule.getTriggerDescription();
149             }
150 
151             // handle schedule-based rules
152             ScheduleInfo schedule =
153                     ZenModeConfig.tryParseScheduleConditionId(rule.getConditionId());
154             if (schedule != null) {
155                 String desc = mScheduleHelper.getDaysAndTimeSummary(mContext, schedule);
156                 return (desc != null) ? desc :
157                         mContext.getResources().getString(
158                                 R.string.zen_mode_schedule_rule_days_none);
159             }
160 
161             // handle event-based rules
162             ZenModeConfig.EventInfo event =
163                     ZenModeConfig.tryParseEventConditionId(rule.getConditionId());
164             if (event != null) {
165                 if (event.calName != null) {
166                     return event.calName;
167                 } else {
168                     return mContext.getResources().getString(
169                             R.string.zen_mode_event_rule_calendar_any);
170                 }
171             }
172         }
173 
174         return (rule == null || !rule.isEnabled())
175                 ? mContext.getResources().getString(R.string.switch_off_text)
176                 : mContext.getResources().getString(R.string.switch_on_text);
177     }
178 }
179