1 /* 2 * Copyright (C) 2015 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; 18 19 import android.app.AutomaticZenRule; 20 import android.content.Context; 21 import android.content.pm.PackageManager.NameNotFoundException; 22 import android.database.Cursor; 23 import android.os.UserHandle; 24 import android.os.UserManager; 25 import android.provider.CalendarContract.Calendars; 26 import android.provider.Settings; 27 import android.service.notification.ZenModeConfig; 28 import android.service.notification.ZenModeConfig.EventInfo; 29 import android.support.v7.preference.DropDownPreference; 30 import android.support.v7.preference.Preference; 31 import android.support.v7.preference.Preference.OnPreferenceChangeListener; 32 import android.support.v7.preference.PreferenceScreen; 33 34 import com.android.internal.logging.MetricsProto.MetricsEvent; 35 import com.android.settings.R; 36 37 import java.util.ArrayList; 38 import java.util.Collections; 39 import java.util.Comparator; 40 import java.util.List; 41 42 public class ZenModeEventRuleSettings extends ZenModeRuleSettingsBase { 43 private static final String KEY_CALENDAR = "calendar"; 44 private static final String KEY_REPLY = "reply"; 45 46 public static final String ACTION = Settings.ACTION_ZEN_MODE_EVENT_RULE_SETTINGS; 47 48 private DropDownPreference mCalendar; 49 private DropDownPreference mReply; 50 51 private EventInfo mEvent; 52 private List<CalendarInfo> mCalendars; 53 private boolean mCreate; 54 55 @Override 56 protected boolean setRule(AutomaticZenRule rule) { 57 mEvent = rule != null ? ZenModeConfig.tryParseEventConditionId(rule.getConditionId()) 58 : null; 59 return mEvent != null; 60 } 61 62 @Override 63 protected String getZenModeDependency() { 64 return null; 65 } 66 67 @Override 68 protected int getEnabledToastText() { 69 return R.string.zen_event_rule_enabled_toast; 70 } 71 72 @Override 73 public void onResume() { 74 super.onResume(); 75 if (isUiRestricted()) { 76 return; 77 } 78 if (!mCreate) { 79 reloadCalendar(); 80 } 81 mCreate = false; 82 } 83 84 private void reloadCalendar() { 85 mCalendars = getCalendars(mContext); 86 ArrayList<CharSequence> entries = new ArrayList<>(); 87 ArrayList<CharSequence> values = new ArrayList<>(); 88 entries.add(getString(R.string.zen_mode_event_rule_calendar_any)); 89 values.add(key(0, null)); 90 final String eventCalendar = mEvent != null ? mEvent.calendar : null; 91 boolean found = false; 92 for (CalendarInfo calendar : mCalendars) { 93 entries.add(calendar.name); 94 values.add(key(calendar)); 95 if (eventCalendar != null && eventCalendar.equals(calendar.name)) { 96 found = true; 97 } 98 } 99 if (eventCalendar != null && !found) { 100 entries.add(eventCalendar); 101 values.add(key(mEvent.userId, eventCalendar)); 102 } 103 mCalendar.setEntries(entries.toArray(new CharSequence[entries.size()])); 104 mCalendar.setEntryValues(values.toArray(new CharSequence[values.size()])); 105 } 106 107 @Override 108 protected void onCreateInternal() { 109 mCreate = true; 110 addPreferencesFromResource(R.xml.zen_mode_event_rule_settings); 111 final PreferenceScreen root = getPreferenceScreen(); 112 113 mCalendar = (DropDownPreference) root.findPreference(KEY_CALENDAR); 114 mCalendar.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { 115 @Override 116 public boolean onPreferenceChange(Preference preference, Object newValue) { 117 final String calendarKey = (String) newValue; 118 if (calendarKey.equals(key(mEvent))) return false; 119 final int i = calendarKey.indexOf(':'); 120 mEvent.userId = Integer.parseInt(calendarKey.substring(0, i)); 121 mEvent.calendar = calendarKey.substring(i + 1); 122 if (mEvent.calendar.isEmpty()) { 123 mEvent.calendar = null; 124 } 125 updateRule(ZenModeConfig.toEventConditionId(mEvent)); 126 return true; 127 } 128 }); 129 130 mReply = (DropDownPreference) root.findPreference(KEY_REPLY); 131 mReply.setEntries(new CharSequence[] { 132 getString(R.string.zen_mode_event_rule_reply_any_except_no), 133 getString(R.string.zen_mode_event_rule_reply_yes_or_maybe), 134 getString(R.string.zen_mode_event_rule_reply_yes), 135 }); 136 mReply.setEntryValues(new CharSequence[] { 137 Integer.toString(EventInfo.REPLY_ANY_EXCEPT_NO), 138 Integer.toString(EventInfo.REPLY_YES_OR_MAYBE), 139 Integer.toString(EventInfo.REPLY_YES), 140 }); 141 mReply.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { 142 @Override 143 public boolean onPreferenceChange(Preference preference, Object newValue) { 144 final int reply = Integer.parseInt((String) newValue); 145 if (reply == mEvent.reply) return false; 146 mEvent.reply = reply; 147 updateRule(ZenModeConfig.toEventConditionId(mEvent)); 148 return true; 149 } 150 }); 151 152 reloadCalendar(); 153 updateControlsInternal(); 154 } 155 156 @Override 157 protected void updateControlsInternal() { 158 mCalendar.setValue(key(mEvent)); 159 mReply.setValue(Integer.toString(mEvent.reply)); 160 } 161 162 @Override 163 protected int getMetricsCategory() { 164 return MetricsEvent.NOTIFICATION_ZEN_MODE_EVENT_RULE; 165 } 166 167 public static CalendarInfo findCalendar(Context context, EventInfo event) { 168 if (context == null || event == null) return null; 169 final String eventKey = key(event); 170 for (CalendarInfo calendar : getCalendars(context)) { 171 if (eventKey.equals(key(calendar))) { 172 return calendar; 173 } 174 } 175 return null; 176 } 177 178 private static List<CalendarInfo> getCalendars(Context context) { 179 final List<CalendarInfo> calendars = new ArrayList<>(); 180 for (UserHandle user : UserManager.get(context).getUserProfiles()) { 181 final Context userContext = getContextForUser(context, user); 182 if (userContext != null) { 183 addCalendars(userContext, calendars); 184 } 185 } 186 Collections.sort(calendars, CALENDAR_NAME); 187 return calendars; 188 } 189 190 private static Context getContextForUser(Context context, UserHandle user) { 191 try { 192 return context.createPackageContextAsUser(context.getPackageName(), 0, user); 193 } catch (NameNotFoundException e) { 194 return null; 195 } 196 } 197 198 public static void addCalendars(Context context, List<CalendarInfo> outCalendars) { 199 final String primary = "\"primary\""; 200 final String[] projection = { Calendars._ID, Calendars.CALENDAR_DISPLAY_NAME, 201 "(" + Calendars.ACCOUNT_NAME + "=" + Calendars.OWNER_ACCOUNT + ") AS " + primary }; 202 final String selection = primary + " = 1"; 203 Cursor cursor = null; 204 try { 205 cursor = context.getContentResolver().query(Calendars.CONTENT_URI, projection, 206 selection, null, null); 207 if (cursor == null) { 208 return; 209 } 210 while (cursor.moveToNext()) { 211 final CalendarInfo ci = new CalendarInfo(); 212 ci.name = cursor.getString(1); 213 ci.userId = context.getUserId(); 214 outCalendars.add(ci); 215 } 216 } finally { 217 if (cursor != null) { 218 cursor.close(); 219 } 220 } 221 } 222 223 private static String key(CalendarInfo calendar) { 224 return key(calendar.userId, calendar.name); 225 } 226 227 private static String key(EventInfo event) { 228 return key(event.userId, event.calendar); 229 } 230 231 private static String key(int userId, String calendar) { 232 return EventInfo.resolveUserId(userId) + ":" + (calendar == null ? "" : calendar); 233 } 234 235 private static final Comparator<CalendarInfo> CALENDAR_NAME = new Comparator<CalendarInfo>() { 236 @Override 237 public int compare(CalendarInfo lhs, CalendarInfo rhs) { 238 return lhs.name.compareTo(rhs.name); 239 } 240 }; 241 242 public static class CalendarInfo { 243 public String name; 244 public int userId; 245 } 246 247 } 248