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