• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 static android.app.NotificationManager.EXTRA_AUTOMATIC_RULE_ID;
20 
21 import android.app.AutomaticZenRule;
22 import android.app.NotificationManager;
23 import android.app.settings.SettingsEnums;
24 import android.content.ComponentName;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.content.pm.ActivityInfo;
28 import android.content.pm.ComponentInfo;
29 import android.content.pm.PackageManager;
30 import android.content.pm.ServiceInfo;
31 import android.os.Binder;
32 import android.provider.Settings;
33 import android.service.notification.ConditionProviderService;
34 import android.util.Log;
35 import android.util.Slog;
36 
37 import androidx.fragment.app.Fragment;
38 import androidx.preference.Preference;
39 
40 import com.android.settings.core.PreferenceControllerMixin;
41 import com.android.settingslib.core.lifecycle.Lifecycle;
42 
43 import java.util.Map;
44 import java.util.Objects;
45 
46 abstract public class AbstractZenModeAutomaticRulePreferenceController extends
47         AbstractZenModePreferenceController implements PreferenceControllerMixin {
48 
49     protected ZenModeBackend mBackend;
50     protected Fragment mParent;
51     protected Map.Entry<String, AutomaticZenRule>[] mRules;
52     protected PackageManager mPm;
53 
AbstractZenModeAutomaticRulePreferenceController(Context context, String key, Fragment parent, Lifecycle lifecycle)54     public AbstractZenModeAutomaticRulePreferenceController(Context context, String key, Fragment
55             parent, Lifecycle lifecycle) {
56         super(context, key, lifecycle);
57         mBackend = ZenModeBackend.getInstance(context);
58         mPm = mContext.getPackageManager();
59         mParent = parent;
60     }
61 
62     @Override
updateState(Preference preference)63     public void updateState(Preference preference) {
64         super.updateState(preference);
65         mRules = mBackend.getAutomaticZenRules();
66     }
67 
getRules()68     protected Map.Entry<String, AutomaticZenRule>[] getRules() {
69         if (mRules == null) {
70             mRules = mBackend.getAutomaticZenRules();
71         }
72         return mRules;
73     }
74 
showNameRuleDialog(final ZenRuleInfo ri, Fragment parent)75     protected void showNameRuleDialog(final ZenRuleInfo ri, Fragment parent) {
76         ZenRuleNameDialog.show(parent, null, ri.defaultConditionId, new
77                 RuleNameChangeListener(ri));
78     }
79 
getRuleIntent(String settingsAction, ComponentName configurationActivity, String ruleId)80     protected static Intent getRuleIntent(String settingsAction,
81             ComponentName configurationActivity, String ruleId) {
82         final Intent intent = new Intent()
83                 .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
84                 .putExtra(ConditionProviderService.EXTRA_RULE_ID, ruleId)
85                 .putExtra(EXTRA_AUTOMATIC_RULE_ID, ruleId);
86         if (configurationActivity != null) {
87             intent.setComponent(configurationActivity);
88         } else {
89             intent.setAction(settingsAction);
90         }
91         return intent;
92     }
93 
getRuleInfo(PackageManager pm, ComponentInfo ci)94     public static ZenRuleInfo getRuleInfo(PackageManager pm, ComponentInfo ci) {
95         if (ci == null || ci.metaData == null) {
96             return null;
97         }
98         final String ruleType = (ci instanceof ServiceInfo)
99                 ? ci.metaData.getString(ConditionProviderService.META_DATA_RULE_TYPE)
100                 : ci.metaData.getString(NotificationManager.META_DATA_AUTOMATIC_RULE_TYPE);
101 
102         final ComponentName configurationActivity = getSettingsActivity(pm, null, ci);
103         if (ruleType != null && !ruleType.trim().isEmpty() && configurationActivity != null) {
104             final ZenRuleInfo ri = new ZenRuleInfo();
105             ri.serviceComponent =
106                     (ci instanceof ServiceInfo) ? new ComponentName(ci.packageName, ci.name) : null;
107             ri.settingsAction = Settings.ACTION_ZEN_MODE_EXTERNAL_RULE_SETTINGS;
108             ri.title = ruleType;
109             ri.packageName = ci.packageName;
110             ri.configurationActivity = configurationActivity;
111             ri.packageLabel = ci.applicationInfo.loadLabel(pm);
112             ri.ruleInstanceLimit = (ci instanceof ServiceInfo)
113                     ? ci.metaData.getInt(ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1)
114                     : ci.metaData.getInt(NotificationManager.META_DATA_RULE_INSTANCE_LIMIT, -1);
115             return ri;
116         }
117         return null;
118     }
119 
getSettingsActivity(PackageManager pm, AutomaticZenRule rule, ComponentInfo ci)120     protected static ComponentName getSettingsActivity(PackageManager pm, AutomaticZenRule rule,
121             ComponentInfo ci) {
122         String owner = rule != null ? rule.getPackageName() : ci.packageName;
123         ComponentName settingsActivity = null;
124         // prefer config activity on the rule itself; fallback to manifest definition
125         if (rule != null && rule.getConfigurationActivity() != null) {
126             settingsActivity = rule.getConfigurationActivity();
127         } else {
128             if (ci == null) {
129                 settingsActivity = null;
130             } else if (ci instanceof ActivityInfo) {
131                 // new activity backed rule
132                 settingsActivity = new ComponentName(ci.packageName, ci.name);
133             } else if (ci.metaData != null) {
134                 // old service backed rule
135                 final String configurationActivity = ci.metaData.getString(
136                         ConditionProviderService.META_DATA_CONFIGURATION_ACTIVITY);
137                 if (configurationActivity != null) {
138                     settingsActivity = ComponentName.unflattenFromString(configurationActivity);
139                 }
140             }
141         }
142         if (settingsActivity == null || owner == null) {
143             return settingsActivity;
144         }
145         try {
146             int ownerUid = pm.getPackageUid(owner, 0);
147             int configActivityOwnerUid = pm.getPackageUid(settingsActivity.getPackageName(), 0);
148             if (ownerUid == configActivityOwnerUid) {
149                 return settingsActivity;
150             } else {
151                 Log.w(TAG, "Config activity not in owner package for " + rule.getName());
152                 return null;
153             }
154         } catch (PackageManager.NameNotFoundException e) {
155             Log.e(TAG, "Failed to find config activity");
156             return null;
157         }
158     }
159 
160     public class RuleNameChangeListener implements ZenRuleNameDialog.PositiveClickListener {
161         ZenRuleInfo mRuleInfo;
162 
RuleNameChangeListener(ZenRuleInfo ruleInfo)163         public RuleNameChangeListener(ZenRuleInfo ruleInfo) {
164             mRuleInfo = ruleInfo;
165         }
166 
167         @Override
onOk(String ruleName, Fragment parent)168         public void onOk(String ruleName, Fragment parent) {
169             mMetricsFeatureProvider.action(mContext,
170                     SettingsEnums.ACTION_ZEN_MODE_RULE_NAME_CHANGE_OK);
171             AutomaticZenRule rule = new AutomaticZenRule(ruleName, mRuleInfo.serviceComponent,
172                     mRuleInfo.configurationActivity, mRuleInfo.defaultConditionId, null,
173                     NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
174             String savedRuleId = mBackend.addZenRule(rule);
175             if (savedRuleId != null) {
176                 parent.startActivity(getRuleIntent(mRuleInfo.settingsAction, null,
177                         savedRuleId));
178             }
179         }
180     }
181 }
182