ZenModeAutomationSettings.java revision 39b467482d1bf256a111c757e9b7621c6f523271
1d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock/*
2d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock * Copyright (C) 2015 The Android Open Source Project
3d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock *
4d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock * Licensed under the Apache License, Version 2.0 (the "License");
5d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock * you may not use this file except in compliance with the License.
6d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock * You may obtain a copy of the License at
7d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock *
8d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock *      http://www.apache.org/licenses/LICENSE-2.0
9d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock *
10d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock * Unless required by applicable law or agreed to in writing, software
11d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock * distributed under the License is distributed on an "AS IS" BASIS,
12d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock * See the License for the specific language governing permissions and
14d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock * limitations under the License.
15d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock */
16d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock
17d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlockpackage com.android.settings.notification;
18d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock
19cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynoldsimport android.app.AlertDialog;
207d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynoldsimport android.app.AutomaticZenRule;
217d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynoldsimport android.app.NotificationManager;
22c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlockimport android.content.ComponentName;
23cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynoldsimport android.content.Context;
24cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynoldsimport android.content.DialogInterface;
2545fa140b8c6846b4546fdeabebf989ae9102cebbJohn Spurlockimport android.content.Intent;
26cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynoldsimport android.content.pm.ApplicationInfo;
27cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynoldsimport android.content.pm.PackageManager;
28c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlockimport android.content.pm.ServiceInfo;
29beff087b3ac3aae4eb120feef81274d7caeafb58John Spurlockimport android.content.res.Resources;
30cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynoldsimport android.graphics.drawable.Drawable;
31cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynoldsimport android.os.AsyncTask;
32d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlockimport android.os.Bundle;
33c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlockimport android.provider.Settings;
34c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlockimport android.service.notification.ConditionProviderService;
35d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlockimport android.service.notification.ZenModeConfig;
3639b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.support.v7.preference.Preference;
3739b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.support.v7.preference.Preference.OnPreferenceClickListener;
3839b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.support.v7.preference.PreferenceScreen;
3939b467482d1bf256a111c757e9b7621c6f523271Jason Monkimport android.support.v7.preference.PreferenceViewHolder;
40d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlockimport android.util.Log;
41cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynoldsimport android.view.View;
42d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock
43d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlockimport com.android.internal.logging.MetricsLogger;
44d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlockimport com.android.settings.R;
45c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlockimport com.android.settings.notification.ManagedServiceSettings.Config;
46d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock
47cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynoldsimport java.lang.ref.WeakReference;
48f57bad7d5b0f9044231fc52351ed27e14013f491John Spurlockimport java.util.Arrays;
49f57bad7d5b0f9044231fc52351ed27e14013f491John Spurlockimport java.util.Comparator;
50c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlockimport java.util.List;
517d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynoldsimport java.util.Objects;
52d333a7d9f10500ec45377e099955031017d6a158John Spurlock
5345fa140b8c6846b4546fdeabebf989ae9102cebbJohn Spurlockpublic class ZenModeAutomationSettings extends ZenModeSettingsBase {
54d333a7d9f10500ec45377e099955031017d6a158John Spurlock
55c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock    static final Config CONFIG = getConditionProviderConfig();
56c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock
57cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds    private PackageManager mPm;
58c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock    private ServiceListing mServiceListing;
59c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock
60d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock    @Override
61d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock    public void onCreate(Bundle icicle) {
62d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock        super.onCreate(icicle);
63d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock        addPreferencesFromResource(R.xml.zen_mode_automation_settings);
64c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock        mServiceListing = new ServiceListing(mContext, CONFIG);
65c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock        mServiceListing.addCallback(mServiceListingCallback);
66c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock        mServiceListing.reload();
67c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock        mServiceListing.setListening(true);
68cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds        mPm = mContext.getPackageManager();
6945fa140b8c6846b4546fdeabebf989ae9102cebbJohn Spurlock    }
70d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock
71c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock    @Override
72c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock    public void onDestroy() {
73c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock        super.onDestroy();
74c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock        mServiceListing.setListening(false);
75c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock        mServiceListing.removeCallback(mServiceListingCallback);
7645fa140b8c6846b4546fdeabebf989ae9102cebbJohn Spurlock    }
77d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock
7845fa140b8c6846b4546fdeabebf989ae9102cebbJohn Spurlock    @Override
79c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock    protected void onZenModeChanged() {
80c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock        // don't care
81c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock    }
82c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock
83c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock    @Override
84c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock    protected void onZenModeConfigChanged() {
85c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock        updateControls();
86c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock    }
87c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock
88c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock    @Override
89c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock    public void onResume() {
90c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock        super.onResume();
91c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock        updateControls();
92c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock    }
93c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock
9445fa140b8c6846b4546fdeabebf989ae9102cebbJohn Spurlock    private void showAddRuleDialog() {
95f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds        new ZenRuleSelectionDialog(mContext, mServiceListing) {
96f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds            @Override
97f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds            public void onSystemRuleSelected(ZenRuleInfo ri) {
98f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds                showNameRuleDialog(ri);
99f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds            }
100f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds
101f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds            @Override
102f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds            public void onExternalRuleSelected(ZenRuleInfo ri) {
103f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds                Intent intent = new Intent().setComponent(ri.configurationActivity);
104f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds                startActivity(intent);
105f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds            }
106f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds        }.show();
107f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds    }
108f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds
109f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds    private void showNameRuleDialog(final ZenRuleInfo ri) {
11025cb8f06914538f337be66d9a784834a7373b58aJulia Reynolds        new ZenRuleNameDialog(mContext, null) {
111d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock            @Override
112f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds            public void onOk(String ruleName) {
1131b6ffba9e69dc1926e3c4cbcb52d1844c6ccaa32Chris Wren                MetricsLogger.action(mContext, MetricsLogger.ACTION_ZEN_ADD_RULE_OK);
114f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds                AutomaticZenRule rule = new AutomaticZenRule(ruleName, ri.serviceComponent,
115f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds                        ri.defaultConditionId, NotificationManager.INTERRUPTION_FILTER_PRIORITY,
116f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds                        true);
11725cb8f06914538f337be66d9a784834a7373b58aJulia Reynolds                AutomaticZenRule savedRule = addZenRule(rule);
11825cb8f06914538f337be66d9a784834a7373b58aJulia Reynolds                if (savedRule != null) {
11925cb8f06914538f337be66d9a784834a7373b58aJulia Reynolds                    startActivity(getRuleIntent(ri.settingsAction, null, savedRule.getId()));
120d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock                }
121d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock            }
12245fa140b8c6846b4546fdeabebf989ae9102cebbJohn Spurlock        }.show();
123d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock    }
124d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock
12525cb8f06914538f337be66d9a784834a7373b58aJulia Reynolds    private void showDeleteRuleDialog(final String ruleId, final String ruleName) {
126cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds        new AlertDialog.Builder(mContext)
127cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds                .setMessage(getString(R.string.zen_mode_delete_rule_confirmation, ruleName))
128cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds                .setNegativeButton(R.string.cancel, null)
129cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds                .setPositiveButton(R.string.zen_mode_delete_rule_button,
130cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds                        new DialogInterface.OnClickListener() {
131cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds                    @Override
132cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds                    public void onClick(DialogInterface dialog, int which) {
133cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds                        MetricsLogger.action(mContext, MetricsLogger.ACTION_ZEN_DELETE_RULE_OK);
13425cb8f06914538f337be66d9a784834a7373b58aJulia Reynolds                        removeZenRule(ruleId);
135cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds                    }
136cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds                })
137cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds                .show();
138cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds    }
139cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds
140f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds    private Intent getRuleIntent(String settingsAction, ComponentName configurationActivity,
14125cb8f06914538f337be66d9a784834a7373b58aJulia Reynolds            String ruleId) {
142f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds        Intent intent = new Intent()
143c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock                .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
14425cb8f06914538f337be66d9a784834a7373b58aJulia Reynolds                .putExtra(ConditionProviderService.EXTRA_RULE_ID, ruleId);
145f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds        if (configurationActivity != null) {
146f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds            intent.setComponent(configurationActivity);
147f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds        } else {
148f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds            intent.setAction(settingsAction);
149f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds        }
150f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds        return intent;
151b47b2c3f6af650441f8069b87d0d82549913f7c5John Spurlock    }
152b47b2c3f6af650441f8069b87d0d82549913f7c5John Spurlock
1537d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds    private AutomaticZenRule[] sortedRules() {
1547d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds        final AutomaticZenRule[] rt = mRules.toArray(new AutomaticZenRule[mRules.size()]);
155f57bad7d5b0f9044231fc52351ed27e14013f491John Spurlock        Arrays.sort(rt, RULE_COMPARATOR);
156f57bad7d5b0f9044231fc52351ed27e14013f491John Spurlock        return rt;
157f57bad7d5b0f9044231fc52351ed27e14013f491John Spurlock    }
158f57bad7d5b0f9044231fc52351ed27e14013f491John Spurlock
159b47b2c3f6af650441f8069b87d0d82549913f7c5John Spurlock    private void updateControls() {
16045fa140b8c6846b4546fdeabebf989ae9102cebbJohn Spurlock        final PreferenceScreen root = getPreferenceScreen();
16145fa140b8c6846b4546fdeabebf989ae9102cebbJohn Spurlock        root.removeAll();
1627d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds        if (mRules.size() == 0) return;
1637d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds        final AutomaticZenRule[] sortedRules = sortedRules();
1647d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds        for (AutomaticZenRule sortedRule : sortedRules) {
16539b467482d1bf256a111c757e9b7621c6f523271Jason Monk            root.addPreference(new ZenRulePreference(getPrefContext(), sortedRule));
166d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock        }
16739b467482d1bf256a111c757e9b7621c6f523271Jason Monk        final Preference p = new Preference(getPrefContext());
168f57bad7d5b0f9044231fc52351ed27e14013f491John Spurlock        p.setIcon(R.drawable.ic_add);
169f57bad7d5b0f9044231fc52351ed27e14013f491John Spurlock        p.setTitle(R.string.zen_mode_add_rule);
170f57bad7d5b0f9044231fc52351ed27e14013f491John Spurlock        p.setPersistent(false);
171f57bad7d5b0f9044231fc52351ed27e14013f491John Spurlock        p.setOnPreferenceClickListener(new OnPreferenceClickListener() {
172f57bad7d5b0f9044231fc52351ed27e14013f491John Spurlock            @Override
173f57bad7d5b0f9044231fc52351ed27e14013f491John Spurlock            public boolean onPreferenceClick(Preference preference) {
1741b6ffba9e69dc1926e3c4cbcb52d1844c6ccaa32Chris Wren                MetricsLogger.action(mContext, MetricsLogger.ACTION_ZEN_ADD_RULE);
175f57bad7d5b0f9044231fc52351ed27e14013f491John Spurlock                showAddRuleDialog();
176f57bad7d5b0f9044231fc52351ed27e14013f491John Spurlock                return true;
177f57bad7d5b0f9044231fc52351ed27e14013f491John Spurlock            }
178f57bad7d5b0f9044231fc52351ed27e14013f491John Spurlock        });
179f57bad7d5b0f9044231fc52351ed27e14013f491John Spurlock        root.addPreference(p);
18045fa140b8c6846b4546fdeabebf989ae9102cebbJohn Spurlock    }
181d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock
18245fa140b8c6846b4546fdeabebf989ae9102cebbJohn Spurlock    @Override
18345fa140b8c6846b4546fdeabebf989ae9102cebbJohn Spurlock    protected int getMetricsCategory() {
18445fa140b8c6846b4546fdeabebf989ae9102cebbJohn Spurlock        return MetricsLogger.NOTIFICATION_ZEN_MODE_AUTOMATION;
185d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock    }
18645fa140b8c6846b4546fdeabebf989ae9102cebbJohn Spurlock
1877d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds    private String computeRuleSummary(AutomaticZenRule rule, boolean isSystemRule,
188cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds            CharSequence providerLabel) {
1897d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds        final String mode = computeZenModeCaption(getResources(), rule.getInterruptionFilter());
1907d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds        final String ruleState = (rule == null || !rule.isEnabled())
191cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds                ? getString(R.string.switch_off_text)
192cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds                : getString(R.string.zen_mode_rule_summary_enabled_combination, mode);
193d333a7d9f10500ec45377e099955031017d6a158John Spurlock
194cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds        return isSystemRule ? ruleState
195cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds                : getString(R.string.zen_mode_rule_summary_provider_combination,
196cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds                        providerLabel, ruleState);
197d333a7d9f10500ec45377e099955031017d6a158John Spurlock    }
198d333a7d9f10500ec45377e099955031017d6a158John Spurlock
199c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock    private static Config getConditionProviderConfig() {
200c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock        final Config c = new Config();
201c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock        c.tag = TAG;
202c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock        c.setting = Settings.Secure.ENABLED_CONDITION_PROVIDERS;
203c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock        c.intentAction = ConditionProviderService.SERVICE_INTERFACE;
204c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock        c.permission = android.Manifest.permission.BIND_CONDITION_PROVIDER_SERVICE;
205c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock        c.noun = "condition provider";
206c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock        return c;
207c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock    }
208c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock
209beff087b3ac3aae4eb120feef81274d7caeafb58John Spurlock    private static String computeZenModeCaption(Resources res, int zenMode) {
210beff087b3ac3aae4eb120feef81274d7caeafb58John Spurlock        switch (zenMode) {
2117d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds            case NotificationManager.INTERRUPTION_FILTER_ALARMS:
212beff087b3ac3aae4eb120feef81274d7caeafb58John Spurlock                return res.getString(R.string.zen_mode_option_alarms);
2137d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds            case NotificationManager.INTERRUPTION_FILTER_PRIORITY:
214beff087b3ac3aae4eb120feef81274d7caeafb58John Spurlock                return res.getString(R.string.zen_mode_option_important_interruptions);
2157d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds            case NotificationManager.INTERRUPTION_FILTER_NONE:
216beff087b3ac3aae4eb120feef81274d7caeafb58John Spurlock                return res.getString(R.string.zen_mode_option_no_interruptions);
217beff087b3ac3aae4eb120feef81274d7caeafb58John Spurlock            default:
218beff087b3ac3aae4eb120feef81274d7caeafb58John Spurlock                return null;
219beff087b3ac3aae4eb120feef81274d7caeafb58John Spurlock        }
220beff087b3ac3aae4eb120feef81274d7caeafb58John Spurlock    }
221beff087b3ac3aae4eb120feef81274d7caeafb58John Spurlock
222c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock    private final ServiceListing.Callback mServiceListingCallback = new ServiceListing.Callback() {
223c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock        @Override
224c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock        public void onServicesReloaded(List<ServiceInfo> services) {
225c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock            for (ServiceInfo service : services) {
226f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds                final ZenRuleInfo ri = getRuleInfo(service);
227c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock                if (ri != null && ri.serviceComponent != null
228f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds                        && Objects.equals(ri.settingsAction,
229f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds                        Settings.ACTION_ZEN_MODE_EXTERNAL_RULE_SETTINGS)) {
230c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock                    if (!mServiceListing.isEnabled(ri.serviceComponent)) {
231c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock                        Log.i(TAG, "Enabling external condition provider: " + ri.serviceComponent);
232c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock                        mServiceListing.setEnabled(ri.serviceComponent, true);
233c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock                    }
234c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock                }
235c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock            }
236c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock        }
237c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock    };
238c96a5dcbfc3f37f71e8b3e8b962f9571b1e7ceafJohn Spurlock
239f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds    public static ZenRuleInfo getRuleInfo(ServiceInfo si) {
240f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds        if (si == null || si.metaData == null) return null;
241f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds        final String ruleType = si.metaData.getString(ConditionProviderService.META_DATA_RULE_TYPE);
24225cb8f06914538f337be66d9a784834a7373b58aJulia Reynolds        final ComponentName configurationActivity = getSettingsActivity(si);
24325cb8f06914538f337be66d9a784834a7373b58aJulia Reynolds        if (ruleType != null && !ruleType.trim().isEmpty() && configurationActivity != null) {
244f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds            final ZenRuleInfo ri = new ZenRuleInfo();
245f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds            ri.settingsAction = Settings.ACTION_ZEN_MODE_EXTERNAL_RULE_SETTINGS;
246f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds            ri.title = ruleType;
247f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds            ri.packageName = si.packageName;
248f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds            ri.configurationActivity = getSettingsActivity(si);
249f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds
250f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds            return ri;
251f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds        }
252f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds        return null;
253f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds    }
254f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds
255f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds    private static ComponentName getSettingsActivity(ServiceInfo si) {
256f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds        if (si == null || si.metaData == null) return null;
257f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds        final String configurationActivity =
258f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds                si.metaData.getString(ConditionProviderService.META_DATA_CONFIGURATION_ACTIVITY);
259f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds        if (configurationActivity != null) {
260f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds            return ComponentName.unflattenFromString(configurationActivity);
261f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds        }
262f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds        return null;
263f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds    }
264f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds
265cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds    // TODO: Sort by creation date, once that data is available.
2667d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds    private static final Comparator<AutomaticZenRule> RULE_COMPARATOR =
2677d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds            new Comparator<AutomaticZenRule>() {
268f57bad7d5b0f9044231fc52351ed27e14013f491John Spurlock        @Override
2697d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds        public int compare(AutomaticZenRule lhs, AutomaticZenRule rhs) {
270f57bad7d5b0f9044231fc52351ed27e14013f491John Spurlock            return key(lhs).compareTo(key(rhs));
271f57bad7d5b0f9044231fc52351ed27e14013f491John Spurlock        }
272f57bad7d5b0f9044231fc52351ed27e14013f491John Spurlock
2737d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds        private String key(AutomaticZenRule rule) {
2747d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds            final int type = ZenModeConfig.isValidScheduleConditionId(rule.getConditionId()) ? 1
2757d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds                    : ZenModeConfig.isValidEventConditionId(rule.getConditionId()) ? 2
276f57bad7d5b0f9044231fc52351ed27e14013f491John Spurlock                    : 3;
2777d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds            return type + rule.getName();
278f57bad7d5b0f9044231fc52351ed27e14013f491John Spurlock        }
279f57bad7d5b0f9044231fc52351ed27e14013f491John Spurlock    };
280f57bad7d5b0f9044231fc52351ed27e14013f491John Spurlock
281cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds    private class ZenRulePreference extends Preference {
282cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds        final String mName;
28325cb8f06914538f337be66d9a784834a7373b58aJulia Reynolds        final String mId;
284cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds
2857d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds        public ZenRulePreference(Context context, final AutomaticZenRule rule) {
286cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds            super(context);
287cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds
2887d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds            mName = rule.getName();
28925cb8f06914538f337be66d9a784834a7373b58aJulia Reynolds            mId = rule.getId();
290cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds
2917d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds            final boolean isSchedule = ZenModeConfig.isValidScheduleConditionId(
2927d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds                    rule.getConditionId());
2937d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds            final boolean isEvent = ZenModeConfig.isValidEventConditionId(rule.getConditionId());
294cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds            final boolean isSystemRule = isSchedule || isEvent;
295cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds
296cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds            try {
297f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds                ApplicationInfo info = mPm.getApplicationInfo(rule.getOwner().getPackageName(), 0);
298cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds                LoadIconTask task = new LoadIconTask(this);
299cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds                task.execute(info);
300cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds                setSummary(computeRuleSummary(rule, isSystemRule, info.loadLabel(mPm)));
301cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds            } catch (PackageManager.NameNotFoundException e) {
302cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds                setIcon(R.drawable.ic_label);
303cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds            }
304cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds
3057d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds            setTitle(rule.getName());
306cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds            setPersistent(false);
307f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds
308f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds            final String action = isSchedule ? ZenModeScheduleRuleSettings.ACTION
309f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds                    : isEvent ? ZenModeEventRuleSettings.ACTION : "";
310f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds            ServiceInfo si = mServiceListing.findService(mContext, CONFIG, rule.getOwner());
311f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds            ComponentName settingsActivity = getSettingsActivity(si);
31225cb8f06914538f337be66d9a784834a7373b58aJulia Reynolds            setIntent(getRuleIntent(action, settingsActivity, mId));
313f7748e4ae15e49f9f4a9cc15a372e9a6d3c35c56Julia Reynolds
314cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds            setWidgetLayoutResource(R.layout.zen_rule_widget);
315cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds        }
316cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds
317cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds        @Override
31839b467482d1bf256a111c757e9b7621c6f523271Jason Monk        public void onBindViewHolder(PreferenceViewHolder view) {
31939b467482d1bf256a111c757e9b7621c6f523271Jason Monk            super.onBindViewHolder(view);
320cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds
321cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds            View v = view.findViewById(R.id.delete_zen_rule);
3227d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds            if (v != null) {
3237d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds                v.setOnClickListener(mDeleteListener);
3247d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds            }
325cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds        }
326cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds
327cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds        private final View.OnClickListener mDeleteListener = new View.OnClickListener() {
328cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds            @Override
329cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds            public void onClick(View v) {
33025cb8f06914538f337be66d9a784834a7373b58aJulia Reynolds                showDeleteRuleDialog(mId, mName);
331cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds            }
332cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds        };
333cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds    }
334cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds
335cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds    private class LoadIconTask extends AsyncTask<ApplicationInfo, Void, Drawable> {
336cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds        private final WeakReference<Preference> prefReference;
337cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds
338cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds        public LoadIconTask(Preference pref) {
3397d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds            prefReference = new WeakReference<>(pref);
340cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds        }
341cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds
342cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds        @Override
343cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds        protected Drawable doInBackground(ApplicationInfo... params) {
344cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds            return params[0].loadIcon(mPm);
345cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds        }
346cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds
347cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds        @Override
348cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds        protected void onPostExecute(Drawable icon) {
3497d8a9aead53f817c9df14cc5feaae223a8a834e8Julia Reynolds            if (icon != null) {
350cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds                final Preference pref = prefReference.get();
351cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds                pref.setIcon(icon);
352cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds            }
353cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds        }
354cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds    }
355cf92ef10a5821e6cf568da78f2bec7a71effe581Julia Reynolds
356d8b36835707edbeeb9c9fbc30eba855a0b6231c6John Spurlock}
357