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