1 /** 2 * Copyright (c) 2014, 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.server.notification; 18 19 import android.app.AppOpsManager; 20 import android.app.AutomaticZenRule; 21 import android.app.NotificationManager; 22 import android.app.NotificationManager.Policy; 23 import android.content.ComponentName; 24 import android.content.ContentResolver; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.content.pm.PackageManager; 28 import android.content.pm.ResolveInfo; 29 import android.content.pm.ServiceInfo; 30 import android.content.res.Resources; 31 import android.content.res.XmlResourceParser; 32 import android.database.ContentObserver; 33 import android.media.AudioAttributes; 34 import android.media.AudioManager; 35 import android.media.AudioManagerInternal; 36 import android.media.AudioSystem; 37 import android.media.VolumePolicy; 38 import android.net.Uri; 39 import android.os.Binder; 40 import android.os.Bundle; 41 import android.os.Handler; 42 import android.os.Looper; 43 import android.os.Message; 44 import android.os.Process; 45 import android.os.SystemClock; 46 import android.os.UserHandle; 47 import android.provider.Settings.Global; 48 import android.service.notification.Condition; 49 import android.service.notification.ConditionProviderService; 50 import android.service.notification.ZenModeConfig; 51 import android.service.notification.ZenModeConfig.EventInfo; 52 import android.service.notification.ZenModeConfig.ScheduleInfo; 53 import android.service.notification.ZenModeConfig.ZenRule; 54 import android.service.notification.ZenModeProto; 55 import android.util.AndroidRuntimeException; 56 import android.util.Log; 57 import android.util.Slog; 58 import android.util.SparseArray; 59 import android.util.proto.ProtoOutputStream; 60 61 import com.android.internal.R; 62 import com.android.internal.logging.MetricsLogger; 63 import com.android.server.LocalServices; 64 65 import libcore.io.IoUtils; 66 67 import org.xmlpull.v1.XmlPullParser; 68 import org.xmlpull.v1.XmlPullParserException; 69 import org.xmlpull.v1.XmlSerializer; 70 71 import java.io.IOException; 72 import java.io.PrintWriter; 73 import java.util.ArrayList; 74 import java.util.List; 75 import java.util.Objects; 76 77 /** 78 * NotificationManagerService helper for functionality related to zen mode. 79 */ 80 public class ZenModeHelper { 81 static final String TAG = "ZenModeHelper"; 82 static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 83 84 // The amount of time rules instances can exist without their owning app being installed. 85 private static final int RULE_INSTANCE_GRACE_PERIOD = 1000 * 60 * 60 * 72; 86 87 private final Context mContext; 88 private final H mHandler; 89 private final SettingsObserver mSettingsObserver; 90 private final AppOpsManager mAppOps; 91 protected ZenModeConfig mDefaultConfig; 92 private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>(); 93 private final ZenModeFiltering mFiltering; 94 private final RingerModeDelegate mRingerModeDelegate = new RingerModeDelegate(); 95 private final ZenModeConditions mConditions; 96 private final SparseArray<ZenModeConfig> mConfigs = new SparseArray<>(); 97 private final Metrics mMetrics = new Metrics(); 98 private final ConditionProviders.Config mServiceConfig; 99 100 protected final ArrayList<String> mDefaultRuleIds = new ArrayList<>(); 101 private final String EVENTS_DEFAULT_RULE = "EVENTS_DEFAULT_RULE"; 102 private final String SCHEDULED_DEFAULT_RULE_1 = "SCHEDULED_DEFAULT_RULE_1"; 103 private final String SCHEDULED_DEFAULT_RULE_2 = "SCHEDULED_DEFAULT_RULE_2"; 104 105 private int mZenMode; 106 private int mUser = UserHandle.USER_SYSTEM; 107 protected ZenModeConfig mConfig; 108 private AudioManagerInternal mAudioManager; 109 protected PackageManager mPm; 110 private long mSuppressedEffects; 111 112 public static final long SUPPRESSED_EFFECT_NOTIFICATIONS = 1; 113 public static final long SUPPRESSED_EFFECT_CALLS = 1 << 1; 114 public static final long SUPPRESSED_EFFECT_ALL = SUPPRESSED_EFFECT_CALLS 115 | SUPPRESSED_EFFECT_NOTIFICATIONS; 116 117 protected String mDefaultRuleWeeknightsName; 118 protected String mDefaultRuleEventsName; 119 protected String mDefaultRuleWeekendsName; 120 121 public ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders) { 122 mContext = context; 123 mHandler = new H(looper); 124 addCallback(mMetrics); 125 mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); 126 127 mDefaultConfig = new ZenModeConfig(); 128 mDefaultRuleWeeknightsName = mContext.getResources() 129 .getString(R.string.zen_mode_default_weeknights_name); 130 mDefaultRuleWeekendsName = mContext.getResources() 131 .getString(R.string.zen_mode_default_weekends_name); 132 mDefaultRuleEventsName = mContext.getResources() 133 .getString(R.string.zen_mode_default_events_name); 134 setDefaultZenRules(mContext); 135 mConfig = mDefaultConfig; 136 mConfigs.put(UserHandle.USER_SYSTEM, mConfig); 137 138 mSettingsObserver = new SettingsObserver(mHandler); 139 mSettingsObserver.observe(); 140 mFiltering = new ZenModeFiltering(mContext); 141 mConditions = new ZenModeConditions(this, conditionProviders); 142 mServiceConfig = conditionProviders.getConfig(); 143 144 } 145 146 public Looper getLooper() { 147 return mHandler.getLooper(); 148 } 149 150 @Override 151 public String toString() { 152 return TAG; 153 } 154 155 public boolean matchesCallFilter(UserHandle userHandle, Bundle extras, 156 ValidateNotificationPeople validator, int contactsTimeoutMs, float timeoutAffinity) { 157 synchronized (mConfig) { 158 return ZenModeFiltering.matchesCallFilter(mContext, mZenMode, mConfig, userHandle, 159 extras, validator, contactsTimeoutMs, timeoutAffinity); 160 } 161 } 162 163 public boolean isCall(NotificationRecord record) { 164 return mFiltering.isCall(record); 165 } 166 167 public void recordCaller(NotificationRecord record) { 168 mFiltering.recordCall(record); 169 } 170 171 public boolean shouldIntercept(NotificationRecord record) { 172 synchronized (mConfig) { 173 return mFiltering.shouldIntercept(mZenMode, mConfig, record); 174 } 175 } 176 177 public boolean shouldSuppressWhenScreenOff() { 178 synchronized (mConfig) { 179 return !mConfig.allowWhenScreenOff; 180 } 181 } 182 183 public boolean shouldSuppressWhenScreenOn() { 184 synchronized (mConfig) { 185 return !mConfig.allowWhenScreenOn; 186 } 187 } 188 189 public void addCallback(Callback callback) { 190 mCallbacks.add(callback); 191 } 192 193 public void removeCallback(Callback callback) { 194 mCallbacks.remove(callback); 195 } 196 197 public void initZenMode() { 198 if (DEBUG) Log.d(TAG, "initZenMode"); 199 evaluateZenMode("init", true /*setRingerMode*/); 200 } 201 202 public void onSystemReady() { 203 if (DEBUG) Log.d(TAG, "onSystemReady"); 204 mAudioManager = LocalServices.getService(AudioManagerInternal.class); 205 if (mAudioManager != null) { 206 mAudioManager.setRingerModeDelegate(mRingerModeDelegate); 207 } 208 mPm = mContext.getPackageManager(); 209 mHandler.postMetricsTimer(); 210 cleanUpZenRules(); 211 evaluateZenMode("onSystemReady", true); 212 } 213 214 public void onUserSwitched(int user) { 215 loadConfigForUser(user, "onUserSwitched"); 216 } 217 218 public void onUserRemoved(int user) { 219 if (user < UserHandle.USER_SYSTEM) return; 220 if (DEBUG) Log.d(TAG, "onUserRemoved u=" + user); 221 mConfigs.remove(user); 222 } 223 224 public void onUserUnlocked(int user) { 225 loadConfigForUser(user, "onUserUnlocked"); 226 } 227 228 private void loadConfigForUser(int user, String reason) { 229 if (mUser == user || user < UserHandle.USER_SYSTEM) return; 230 mUser = user; 231 if (DEBUG) Log.d(TAG, reason + " u=" + user); 232 ZenModeConfig config = mConfigs.get(user); 233 if (config == null) { 234 if (DEBUG) Log.d(TAG, reason + " generating default config for user " + user); 235 config = mDefaultConfig.copy(); 236 config.user = user; 237 } 238 synchronized (mConfig) { 239 setConfigLocked(config, reason); 240 } 241 cleanUpZenRules(); 242 } 243 244 public int getZenModeListenerInterruptionFilter() { 245 return NotificationManager.zenModeToInterruptionFilter(mZenMode); 246 } 247 248 public void requestFromListener(ComponentName name, int filter) { 249 final int newZen = NotificationManager.zenModeFromInterruptionFilter(filter, -1); 250 if (newZen != -1) { 251 setManualZenMode(newZen, null, name != null ? name.getPackageName() : null, 252 "listener:" + (name != null ? name.flattenToShortString() : null)); 253 } 254 } 255 256 public void setSuppressedEffects(long suppressedEffects) { 257 if (mSuppressedEffects == suppressedEffects) return; 258 mSuppressedEffects = suppressedEffects; 259 applyRestrictions(); 260 } 261 262 public long getSuppressedEffects() { 263 return mSuppressedEffects; 264 } 265 266 public int getZenMode() { 267 return mZenMode; 268 } 269 270 public List<ZenRule> getZenRules() { 271 List<ZenRule> rules = new ArrayList<>(); 272 synchronized (mConfig) { 273 if (mConfig == null) return rules; 274 for (ZenRule rule : mConfig.automaticRules.values()) { 275 if (canManageAutomaticZenRule(rule)) { 276 rules.add(rule); 277 } 278 } 279 } 280 return rules; 281 } 282 283 public AutomaticZenRule getAutomaticZenRule(String id) { 284 ZenRule rule; 285 synchronized (mConfig) { 286 if (mConfig == null) return null; 287 rule = mConfig.automaticRules.get(id); 288 } 289 if (rule == null) return null; 290 if (canManageAutomaticZenRule(rule)) { 291 return createAutomaticZenRule(rule); 292 } 293 return null; 294 } 295 296 public String addAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason) { 297 if (!isSystemRule(automaticZenRule)) { 298 ServiceInfo owner = getServiceInfo(automaticZenRule.getOwner()); 299 if (owner == null) { 300 throw new IllegalArgumentException("Owner is not a condition provider service"); 301 } 302 303 int ruleInstanceLimit = -1; 304 if (owner.metaData != null) { 305 ruleInstanceLimit = owner.metaData.getInt( 306 ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1); 307 } 308 if (ruleInstanceLimit > 0 && ruleInstanceLimit 309 < (getCurrentInstanceCount(automaticZenRule.getOwner()) + 1)) { 310 throw new IllegalArgumentException("Rule instance limit exceeded"); 311 } 312 } 313 314 ZenModeConfig newConfig; 315 synchronized (mConfig) { 316 if (mConfig == null) { 317 throw new AndroidRuntimeException("Could not create rule"); 318 } 319 if (DEBUG) { 320 Log.d(TAG, "addAutomaticZenRule rule= " + automaticZenRule + " reason=" + reason); 321 } 322 newConfig = mConfig.copy(); 323 ZenRule rule = new ZenRule(); 324 populateZenRule(automaticZenRule, rule, true); 325 newConfig.automaticRules.put(rule.id, rule); 326 if (setConfigLocked(newConfig, reason, true)) { 327 return rule.id; 328 } else { 329 throw new AndroidRuntimeException("Could not create rule"); 330 } 331 } 332 } 333 334 public boolean updateAutomaticZenRule(String ruleId, AutomaticZenRule automaticZenRule, 335 String reason) { 336 ZenModeConfig newConfig; 337 synchronized (mConfig) { 338 if (mConfig == null) return false; 339 if (DEBUG) { 340 Log.d(TAG, "updateAutomaticZenRule zenRule=" + automaticZenRule 341 + " reason=" + reason); 342 } 343 newConfig = mConfig.copy(); 344 ZenModeConfig.ZenRule rule; 345 if (ruleId == null) { 346 throw new IllegalArgumentException("Rule doesn't exist"); 347 } else { 348 rule = newConfig.automaticRules.get(ruleId); 349 if (rule == null || !canManageAutomaticZenRule(rule)) { 350 throw new SecurityException( 351 "Cannot update rules not owned by your condition provider"); 352 } 353 } 354 populateZenRule(automaticZenRule, rule, false); 355 newConfig.automaticRules.put(ruleId, rule); 356 return setConfigLocked(newConfig, reason, true); 357 } 358 } 359 360 public boolean removeAutomaticZenRule(String id, String reason) { 361 ZenModeConfig newConfig; 362 synchronized (mConfig) { 363 if (mConfig == null) return false; 364 newConfig = mConfig.copy(); 365 ZenRule rule = newConfig.automaticRules.get(id); 366 if (rule == null) return false; 367 if (canManageAutomaticZenRule(rule)) { 368 newConfig.automaticRules.remove(id); 369 if (DEBUG) Log.d(TAG, "removeZenRule zenRule=" + id + " reason=" + reason); 370 } else { 371 throw new SecurityException( 372 "Cannot delete rules not owned by your condition provider"); 373 } 374 return setConfigLocked(newConfig, reason, true); 375 } 376 } 377 378 public boolean removeAutomaticZenRules(String packageName, String reason) { 379 ZenModeConfig newConfig; 380 synchronized (mConfig) { 381 if (mConfig == null) return false; 382 newConfig = mConfig.copy(); 383 for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) { 384 ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i)); 385 if (rule.component.getPackageName().equals(packageName) 386 && canManageAutomaticZenRule(rule)) { 387 newConfig.automaticRules.removeAt(i); 388 } 389 } 390 return setConfigLocked(newConfig, reason, true); 391 } 392 } 393 394 public int getCurrentInstanceCount(ComponentName owner) { 395 int count = 0; 396 synchronized (mConfig) { 397 for (ZenRule rule : mConfig.automaticRules.values()) { 398 if (rule.component != null && rule.component.equals(owner)) { 399 count++; 400 } 401 } 402 } 403 return count; 404 } 405 406 public boolean canManageAutomaticZenRule(ZenRule rule) { 407 final int callingUid = Binder.getCallingUid(); 408 if (callingUid == 0 || callingUid == Process.SYSTEM_UID) { 409 return true; 410 } else if (mContext.checkCallingPermission(android.Manifest.permission.MANAGE_NOTIFICATIONS) 411 == PackageManager.PERMISSION_GRANTED) { 412 return true; 413 } else { 414 String[] packages = mPm.getPackagesForUid(Binder.getCallingUid()); 415 if (packages != null) { 416 final int packageCount = packages.length; 417 for (int i = 0; i < packageCount; i++) { 418 if (packages[i].equals(rule.component.getPackageName())) { 419 return true; 420 } 421 } 422 } 423 return false; 424 } 425 } 426 427 public void setDefaultZenRules(Context context) { 428 mDefaultConfig = readDefaultConfig(context.getResources()); 429 430 mDefaultRuleIds.add(EVENTS_DEFAULT_RULE); 431 mDefaultRuleIds.add(SCHEDULED_DEFAULT_RULE_1); 432 mDefaultRuleIds.add(SCHEDULED_DEFAULT_RULE_2); 433 434 appendDefaultRules(mDefaultConfig); 435 } 436 437 private void appendDefaultRules (ZenModeConfig config) { 438 appendDefaultScheduleRules(config); 439 appendDefaultEventRules(config); 440 } 441 442 // Checks zen rule properties are the same (doesn't check creation time, name nor enabled) 443 // used to check if default rules were customized or not 444 private boolean ruleValuesEqual(AutomaticZenRule rule, ZenRule defaultRule) { 445 if (rule == null || defaultRule == null) { 446 return false; 447 } 448 return rule.getInterruptionFilter() == 449 NotificationManager.zenModeToInterruptionFilter(defaultRule.zenMode) 450 && rule.getConditionId().equals(defaultRule.conditionId) 451 && rule.getOwner().equals(defaultRule.component); 452 } 453 454 protected void updateDefaultZenRules() { 455 ZenModeConfig configDefaultRules = new ZenModeConfig(); 456 appendDefaultRules(configDefaultRules); // "new" localized default rules 457 for (String ruleId : mDefaultRuleIds) { 458 AutomaticZenRule currRule = getAutomaticZenRule(ruleId); 459 ZenRule defaultRule = configDefaultRules.automaticRules.get(ruleId); 460 // if default rule wasn't customized, use localized name instead of previous 461 if (ruleValuesEqual(currRule, defaultRule) && 462 !defaultRule.name.equals(currRule.getName())) { 463 if (canManageAutomaticZenRule(defaultRule)) { 464 if (DEBUG) Slog.d(TAG, "Locale change - updating default zen rule name " 465 + "from " + currRule.getName() + " to " + defaultRule.name); 466 // update default rule (if locale changed, name of rule will change) 467 AutomaticZenRule defaultAutoRule = createAutomaticZenRule(defaultRule); 468 // ensure enabled state is carried over from current rule 469 defaultAutoRule.setEnabled(currRule.isEnabled()); 470 updateAutomaticZenRule(ruleId, defaultAutoRule, 471 "locale changed"); 472 } 473 } 474 } 475 } 476 477 private boolean isSystemRule(AutomaticZenRule rule) { 478 return ZenModeConfig.SYSTEM_AUTHORITY.equals(rule.getOwner().getPackageName()); 479 } 480 481 private ServiceInfo getServiceInfo(ComponentName owner) { 482 Intent queryIntent = new Intent(); 483 queryIntent.setComponent(owner); 484 List<ResolveInfo> installedServices = mPm.queryIntentServicesAsUser( 485 queryIntent, 486 PackageManager.GET_SERVICES | PackageManager.GET_META_DATA, 487 UserHandle.getCallingUserId()); 488 if (installedServices != null) { 489 for (int i = 0, count = installedServices.size(); i < count; i++) { 490 ResolveInfo resolveInfo = installedServices.get(i); 491 ServiceInfo info = resolveInfo.serviceInfo; 492 if (mServiceConfig.bindPermission.equals(info.permission)) { 493 return info; 494 } 495 } 496 } 497 return null; 498 } 499 500 private void populateZenRule(AutomaticZenRule automaticZenRule, ZenRule rule, boolean isNew) { 501 if (isNew) { 502 rule.id = ZenModeConfig.newRuleId(); 503 rule.creationTime = System.currentTimeMillis(); 504 rule.component = automaticZenRule.getOwner(); 505 } 506 507 if (rule.enabled != automaticZenRule.isEnabled()) { 508 rule.snoozing = false; 509 } 510 rule.name = automaticZenRule.getName(); 511 rule.condition = null; 512 rule.conditionId = automaticZenRule.getConditionId(); 513 rule.enabled = automaticZenRule.isEnabled(); 514 rule.zenMode = NotificationManager.zenModeFromInterruptionFilter( 515 automaticZenRule.getInterruptionFilter(), Global.ZEN_MODE_OFF); 516 } 517 518 protected AutomaticZenRule createAutomaticZenRule(ZenRule rule) { 519 return new AutomaticZenRule(rule.name, rule.component, rule.conditionId, 520 NotificationManager.zenModeToInterruptionFilter(rule.zenMode), rule.enabled, 521 rule.creationTime); 522 } 523 524 public void setManualZenMode(int zenMode, Uri conditionId, String caller, String reason) { 525 setManualZenMode(zenMode, conditionId, reason, caller, true /*setRingerMode*/); 526 } 527 528 private void setManualZenMode(int zenMode, Uri conditionId, String reason, String caller, 529 boolean setRingerMode) { 530 ZenModeConfig newConfig; 531 synchronized (mConfig) { 532 if (mConfig == null) return; 533 if (!Global.isValidZenMode(zenMode)) return; 534 if (DEBUG) Log.d(TAG, "setManualZenMode " + Global.zenModeToString(zenMode) 535 + " conditionId=" + conditionId + " reason=" + reason 536 + " setRingerMode=" + setRingerMode); 537 newConfig = mConfig.copy(); 538 if (zenMode == Global.ZEN_MODE_OFF) { 539 newConfig.manualRule = null; 540 for (ZenRule automaticRule : newConfig.automaticRules.values()) { 541 if (automaticRule.isAutomaticActive()) { 542 automaticRule.snoozing = true; 543 } 544 } 545 } else { 546 final ZenRule newRule = new ZenRule(); 547 newRule.enabled = true; 548 newRule.zenMode = zenMode; 549 newRule.conditionId = conditionId; 550 newRule.enabler = caller; 551 newConfig.manualRule = newRule; 552 } 553 setConfigLocked(newConfig, reason, setRingerMode); 554 } 555 } 556 557 void dump(ProtoOutputStream proto) { 558 559 proto.write(ZenModeProto.ZEN_MODE, mZenMode); 560 synchronized (mConfig) { 561 if (mConfig.manualRule != null) { 562 proto.write(ZenModeProto.ENABLED_ACTIVE_CONDITIONS, mConfig.manualRule.toString()); 563 } 564 for (ZenRule rule : mConfig.automaticRules.values()) { 565 if (rule.enabled && rule.condition.state == Condition.STATE_TRUE 566 && !rule.snoozing) { 567 proto.write(ZenModeProto.ENABLED_ACTIVE_CONDITIONS, rule.toString()); 568 } 569 } 570 proto.write(ZenModeProto.POLICY, mConfig.toNotificationPolicy().toString()); 571 proto.write(ZenModeProto.SUPPRESSED_EFFECTS, mSuppressedEffects); 572 } 573 } 574 575 public void dump(PrintWriter pw, String prefix) { 576 pw.print(prefix); pw.print("mZenMode="); 577 pw.println(Global.zenModeToString(mZenMode)); 578 final int N = mConfigs.size(); 579 for (int i = 0; i < N; i++) { 580 dump(pw, prefix, "mConfigs[u=" + mConfigs.keyAt(i) + "]", mConfigs.valueAt(i)); 581 } 582 pw.print(prefix); pw.print("mUser="); pw.println(mUser); 583 synchronized (mConfig) { 584 dump(pw, prefix, "mConfig", mConfig); 585 } 586 587 pw.print(prefix); pw.print("mSuppressedEffects="); pw.println(mSuppressedEffects); 588 mFiltering.dump(pw, prefix); 589 mConditions.dump(pw, prefix); 590 } 591 592 private static void dump(PrintWriter pw, String prefix, String var, ZenModeConfig config) { 593 pw.print(prefix); pw.print(var); pw.print('='); 594 if (config == null) { 595 pw.println(config); 596 return; 597 } 598 pw.printf("allow(calls=%b,callsFrom=%s,repeatCallers=%b,messages=%b,messagesFrom=%s," 599 + "events=%b,reminders=%b,whenScreenOff=%b,whenScreenOn=%b)\n", 600 config.allowCalls, ZenModeConfig.sourceToString(config.allowCallsFrom), 601 config.allowRepeatCallers, config.allowMessages, 602 ZenModeConfig.sourceToString(config.allowMessagesFrom), 603 config.allowEvents, config.allowReminders, config.allowWhenScreenOff, 604 config.allowWhenScreenOn); 605 pw.print(prefix); pw.print(" manualRule="); pw.println(config.manualRule); 606 if (config.automaticRules.isEmpty()) return; 607 final int N = config.automaticRules.size(); 608 for (int i = 0; i < N; i++) { 609 pw.print(prefix); pw.print(i == 0 ? " automaticRules=" : " "); 610 pw.println(config.automaticRules.valueAt(i)); 611 } 612 } 613 614 public void readXml(XmlPullParser parser, boolean forRestore) 615 throws XmlPullParserException, IOException { 616 final ZenModeConfig config = ZenModeConfig.readXml(parser); 617 if (config != null) { 618 if (forRestore) { 619 //TODO: http://b/22388012 620 if (config.user != UserHandle.USER_SYSTEM) { 621 return; 622 } 623 config.manualRule = null; // don't restore the manual rule 624 long time = System.currentTimeMillis(); 625 if (config.automaticRules != null) { 626 for (ZenRule automaticRule : config.automaticRules.values()) { 627 // don't restore transient state from restored automatic rules 628 automaticRule.snoozing = false; 629 automaticRule.condition = null; 630 automaticRule.creationTime = time; 631 } 632 } 633 } 634 if (DEBUG) Log.d(TAG, "readXml"); 635 synchronized (mConfig) { 636 setConfigLocked(config, "readXml"); 637 } 638 } 639 } 640 641 public void writeXml(XmlSerializer out, boolean forBackup) throws IOException { 642 final int N = mConfigs.size(); 643 for (int i = 0; i < N; i++) { 644 //TODO: http://b/22388012 645 if (forBackup && mConfigs.keyAt(i) != UserHandle.USER_SYSTEM) { 646 continue; 647 } 648 mConfigs.valueAt(i).writeXml(out); 649 } 650 } 651 652 public Policy getNotificationPolicy() { 653 return getNotificationPolicy(mConfig); 654 } 655 656 private static Policy getNotificationPolicy(ZenModeConfig config) { 657 return config == null ? null : config.toNotificationPolicy(); 658 } 659 660 public void setNotificationPolicy(Policy policy) { 661 if (policy == null || mConfig == null) return; 662 synchronized (mConfig) { 663 final ZenModeConfig newConfig = mConfig.copy(); 664 newConfig.applyNotificationPolicy(policy); 665 setConfigLocked(newConfig, "setNotificationPolicy"); 666 } 667 } 668 669 /** 670 * Removes old rule instances whose owner is not installed. 671 */ 672 private void cleanUpZenRules() { 673 long currentTime = System.currentTimeMillis(); 674 synchronized (mConfig) { 675 final ZenModeConfig newConfig = mConfig.copy(); 676 if (newConfig.automaticRules != null) { 677 for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) { 678 ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i)); 679 if (RULE_INSTANCE_GRACE_PERIOD < (currentTime - rule.creationTime)) { 680 try { 681 mPm.getPackageInfo(rule.component.getPackageName(), 682 PackageManager.MATCH_ANY_USER); 683 } catch (PackageManager.NameNotFoundException e) { 684 newConfig.automaticRules.removeAt(i); 685 } 686 } 687 } 688 } 689 setConfigLocked(newConfig, "cleanUpZenRules"); 690 } 691 } 692 693 /** 694 * @return a copy of the zen mode configuration 695 */ 696 public ZenModeConfig getConfig() { 697 synchronized (mConfig) { 698 return mConfig.copy(); 699 } 700 } 701 702 public boolean setConfigLocked(ZenModeConfig config, String reason) { 703 return setConfigLocked(config, reason, true /*setRingerMode*/); 704 } 705 706 public void setConfig(ZenModeConfig config, String reason) { 707 synchronized (mConfig) { 708 setConfigLocked(config, reason); 709 } 710 } 711 712 private boolean setConfigLocked(ZenModeConfig config, String reason, boolean setRingerMode) { 713 final long identity = Binder.clearCallingIdentity(); 714 try { 715 if (config == null || !config.isValid()) { 716 Log.w(TAG, "Invalid config in setConfigLocked; " + config); 717 return false; 718 } 719 if (config.user != mUser) { 720 // simply store away for background users 721 mConfigs.put(config.user, config); 722 if (DEBUG) Log.d(TAG, "setConfigLocked: store config for user " + config.user); 723 return true; 724 } 725 mConditions.evaluateConfig(config, false /*processSubscriptions*/); // may modify config 726 mConfigs.put(config.user, config); 727 if (DEBUG) Log.d(TAG, "setConfigLocked reason=" + reason, new Throwable()); 728 ZenLog.traceConfig(reason, mConfig, config); 729 final boolean policyChanged = !Objects.equals(getNotificationPolicy(mConfig), 730 getNotificationPolicy(config)); 731 if (!config.equals(mConfig)) { 732 dispatchOnConfigChanged(); 733 } 734 if (policyChanged) { 735 dispatchOnPolicyChanged(); 736 } 737 mConfig = config; 738 mHandler.postApplyConfig(config, reason, setRingerMode); 739 return true; 740 } catch (SecurityException e) { 741 Log.wtf(TAG, "Invalid rule in config", e); 742 return false; 743 } finally { 744 Binder.restoreCallingIdentity(identity); 745 } 746 } 747 748 private void applyConfig(ZenModeConfig config, String reason, boolean setRingerMode) { 749 final String val = Integer.toString(config.hashCode()); 750 Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_CONFIG_ETAG, val); 751 if (!evaluateZenMode(reason, setRingerMode)) { 752 applyRestrictions(); // evaluateZenMode will also apply restrictions if changed 753 } 754 mConditions.evaluateConfig(config, true /*processSubscriptions*/); 755 } 756 757 private int getZenModeSetting() { 758 return Global.getInt(mContext.getContentResolver(), Global.ZEN_MODE, Global.ZEN_MODE_OFF); 759 } 760 761 private void setZenModeSetting(int zen) { 762 Global.putInt(mContext.getContentResolver(), Global.ZEN_MODE, zen); 763 } 764 765 private int getPreviousRingerModeSetting() { 766 return Global.getInt(mContext.getContentResolver(), 767 Global.ZEN_MODE_RINGER_LEVEL, AudioManager.RINGER_MODE_NORMAL); 768 } 769 770 private void setPreviousRingerModeSetting(Integer previousRingerLevel) { 771 Global.putString( 772 mContext.getContentResolver(), Global.ZEN_MODE_RINGER_LEVEL, 773 previousRingerLevel == null ? null : Integer.toString(previousRingerLevel)); 774 } 775 776 private boolean evaluateZenMode(String reason, boolean setRingerMode) { 777 if (DEBUG) Log.d(TAG, "evaluateZenMode"); 778 final int zenBefore = mZenMode; 779 final int zen = computeZenMode(); 780 ZenLog.traceSetZenMode(zen, reason); 781 mZenMode = zen; 782 updateRingerModeAffectedStreams(); 783 setZenModeSetting(mZenMode); 784 if (setRingerMode) { 785 applyZenToRingerMode(); 786 } 787 applyRestrictions(); 788 if (zen != zenBefore) { 789 mHandler.postDispatchOnZenModeChanged(); 790 } 791 return true; 792 } 793 794 private void updateRingerModeAffectedStreams() { 795 if (mAudioManager != null) { 796 mAudioManager.updateRingerModeAffectedStreamsInternal(); 797 } 798 } 799 800 private int computeZenMode() { 801 synchronized (mConfig) { 802 if (mConfig == null) return Global.ZEN_MODE_OFF; 803 if (mConfig.manualRule != null) return mConfig.manualRule.zenMode; 804 int zen = Global.ZEN_MODE_OFF; 805 for (ZenRule automaticRule : mConfig.automaticRules.values()) { 806 if (automaticRule.isAutomaticActive()) { 807 if (zenSeverity(automaticRule.zenMode) > zenSeverity(zen)) { 808 zen = automaticRule.zenMode; 809 } 810 } 811 } 812 return zen; 813 } 814 } 815 816 private void applyRestrictions() { 817 final boolean zen = mZenMode != Global.ZEN_MODE_OFF; 818 819 // notification restrictions 820 final boolean muteNotifications = 821 (mSuppressedEffects & SUPPRESSED_EFFECT_NOTIFICATIONS) != 0; 822 // call restrictions 823 final boolean muteCalls = zen && !mConfig.allowCalls && !mConfig.allowRepeatCallers 824 || (mSuppressedEffects & SUPPRESSED_EFFECT_CALLS) != 0; 825 // total silence restrictions 826 final boolean muteEverything = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS; 827 828 for (int usage : AudioAttributes.SDK_USAGES) { 829 final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage); 830 if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NEVER) { 831 applyRestrictions(false /*mute*/, usage); 832 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NOTIFICATION) { 833 applyRestrictions(muteNotifications || muteEverything, usage); 834 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_CALL) { 835 applyRestrictions(muteCalls || muteEverything, usage); 836 } else { 837 applyRestrictions(muteEverything, usage); 838 } 839 } 840 } 841 842 private void applyRestrictions(boolean mute, int usage) { 843 final String[] exceptionPackages = null; // none (for now) 844 mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, usage, 845 mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED, 846 exceptionPackages); 847 mAppOps.setRestriction(AppOpsManager.OP_PLAY_AUDIO, usage, 848 mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED, 849 exceptionPackages); 850 } 851 852 private void applyZenToRingerMode() { 853 if (mAudioManager == null) return; 854 // force the ringer mode into compliance 855 final int ringerModeInternal = mAudioManager.getRingerModeInternal(); 856 int newRingerModeInternal = ringerModeInternal; 857 switch (mZenMode) { 858 case Global.ZEN_MODE_NO_INTERRUPTIONS: 859 case Global.ZEN_MODE_ALARMS: 860 if (ringerModeInternal != AudioManager.RINGER_MODE_SILENT) { 861 setPreviousRingerModeSetting(ringerModeInternal); 862 newRingerModeInternal = AudioManager.RINGER_MODE_SILENT; 863 } 864 break; 865 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: 866 case Global.ZEN_MODE_OFF: 867 if (ringerModeInternal == AudioManager.RINGER_MODE_SILENT) { 868 newRingerModeInternal = getPreviousRingerModeSetting(); 869 setPreviousRingerModeSetting(null); 870 } 871 break; 872 } 873 if (newRingerModeInternal != -1) { 874 mAudioManager.setRingerModeInternal(newRingerModeInternal, TAG); 875 } 876 } 877 878 private void dispatchOnConfigChanged() { 879 for (Callback callback : mCallbacks) { 880 callback.onConfigChanged(); 881 } 882 } 883 884 private void dispatchOnPolicyChanged() { 885 for (Callback callback : mCallbacks) { 886 callback.onPolicyChanged(); 887 } 888 } 889 890 private void dispatchOnZenModeChanged() { 891 for (Callback callback : mCallbacks) { 892 callback.onZenModeChanged(); 893 } 894 } 895 896 private ZenModeConfig readDefaultConfig(Resources resources) { 897 XmlResourceParser parser = null; 898 try { 899 parser = resources.getXml(R.xml.default_zen_mode_config); 900 while (parser.next() != XmlPullParser.END_DOCUMENT) { 901 final ZenModeConfig config = ZenModeConfig.readXml(parser); 902 if (config != null) return config; 903 } 904 } catch (Exception e) { 905 Log.w(TAG, "Error reading default zen mode config from resource", e); 906 } finally { 907 IoUtils.closeQuietly(parser); 908 } 909 return new ZenModeConfig(); 910 } 911 912 private void appendDefaultScheduleRules(ZenModeConfig config) { 913 if (config == null) return; 914 915 final ScheduleInfo weeknights = new ScheduleInfo(); 916 weeknights.days = ZenModeConfig.WEEKNIGHT_DAYS; 917 weeknights.startHour = 22; 918 weeknights.endHour = 7; 919 final ZenRule rule1 = new ZenRule(); 920 rule1.enabled = false; 921 rule1.name = mDefaultRuleWeeknightsName; 922 rule1.conditionId = ZenModeConfig.toScheduleConditionId(weeknights); 923 rule1.zenMode = Global.ZEN_MODE_ALARMS; 924 rule1.component = ScheduleConditionProvider.COMPONENT; 925 rule1.id = SCHEDULED_DEFAULT_RULE_1; 926 rule1.creationTime = System.currentTimeMillis(); 927 config.automaticRules.put(rule1.id, rule1); 928 929 final ScheduleInfo weekends = new ScheduleInfo(); 930 weekends.days = ZenModeConfig.WEEKEND_DAYS; 931 weekends.startHour = 23; 932 weekends.startMinute = 30; 933 weekends.endHour = 10; 934 final ZenRule rule2 = new ZenRule(); 935 rule2.enabled = false; 936 rule2.name = mDefaultRuleWeekendsName; 937 rule2.conditionId = ZenModeConfig.toScheduleConditionId(weekends); 938 rule2.zenMode = Global.ZEN_MODE_ALARMS; 939 rule2.component = ScheduleConditionProvider.COMPONENT; 940 rule2.id = SCHEDULED_DEFAULT_RULE_2; 941 rule2.creationTime = System.currentTimeMillis(); 942 config.automaticRules.put(rule2.id, rule2); 943 } 944 945 private void appendDefaultEventRules(ZenModeConfig config) { 946 if (config == null) return; 947 948 final EventInfo events = new EventInfo(); 949 events.calendar = null; // any calendar 950 events.reply = EventInfo.REPLY_YES_OR_MAYBE; 951 final ZenRule rule = new ZenRule(); 952 rule.enabled = false; 953 rule.name = mDefaultRuleEventsName; 954 rule.conditionId = ZenModeConfig.toEventConditionId(events); 955 rule.zenMode = Global.ZEN_MODE_ALARMS; 956 rule.component = EventConditionProvider.COMPONENT; 957 rule.id = EVENTS_DEFAULT_RULE; 958 rule.creationTime = System.currentTimeMillis(); 959 config.automaticRules.put(rule.id, rule); 960 } 961 962 private static int zenSeverity(int zen) { 963 switch (zen) { 964 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: return 1; 965 case Global.ZEN_MODE_ALARMS: return 2; 966 case Global.ZEN_MODE_NO_INTERRUPTIONS: return 3; 967 default: return 0; 968 } 969 } 970 971 private final class RingerModeDelegate implements AudioManagerInternal.RingerModeDelegate { 972 @Override 973 public String toString() { 974 return TAG; 975 } 976 977 @Override 978 public int onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, String caller, 979 int ringerModeExternal, VolumePolicy policy) { 980 final boolean isChange = ringerModeOld != ringerModeNew; 981 982 int ringerModeExternalOut = ringerModeNew; 983 984 int newZen = -1; 985 switch (ringerModeNew) { 986 case AudioManager.RINGER_MODE_SILENT: 987 if (isChange && policy.doNotDisturbWhenSilent) { 988 if (mZenMode != Global.ZEN_MODE_NO_INTERRUPTIONS 989 && mZenMode != Global.ZEN_MODE_ALARMS) { 990 newZen = Global.ZEN_MODE_ALARMS; 991 } 992 setPreviousRingerModeSetting(ringerModeOld); 993 } 994 break; 995 case AudioManager.RINGER_MODE_VIBRATE: 996 case AudioManager.RINGER_MODE_NORMAL: 997 if (isChange && ringerModeOld == AudioManager.RINGER_MODE_SILENT 998 && (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS 999 || mZenMode == Global.ZEN_MODE_ALARMS)) { 1000 newZen = Global.ZEN_MODE_OFF; 1001 } else if (mZenMode != Global.ZEN_MODE_OFF) { 1002 ringerModeExternalOut = AudioManager.RINGER_MODE_SILENT; 1003 } 1004 break; 1005 } 1006 if (newZen != -1) { 1007 setManualZenMode(newZen, null, "ringerModeInternal", null, 1008 false /*setRingerMode*/); 1009 } 1010 1011 if (isChange || newZen != -1 || ringerModeExternal != ringerModeExternalOut) { 1012 ZenLog.traceSetRingerModeInternal(ringerModeOld, ringerModeNew, caller, 1013 ringerModeExternal, ringerModeExternalOut); 1014 } 1015 return ringerModeExternalOut; 1016 } 1017 1018 @Override 1019 public int onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller, 1020 int ringerModeInternal, VolumePolicy policy) { 1021 int ringerModeInternalOut = ringerModeNew; 1022 final boolean isChange = ringerModeOld != ringerModeNew; 1023 final boolean isVibrate = ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE; 1024 1025 int newZen = -1; 1026 switch (ringerModeNew) { 1027 case AudioManager.RINGER_MODE_SILENT: 1028 if (isChange) { 1029 if (mZenMode == Global.ZEN_MODE_OFF) { 1030 newZen = Global.ZEN_MODE_ALARMS; 1031 } 1032 ringerModeInternalOut = isVibrate ? AudioManager.RINGER_MODE_VIBRATE 1033 : AudioManager.RINGER_MODE_SILENT; 1034 } else { 1035 ringerModeInternalOut = ringerModeInternal; 1036 } 1037 break; 1038 case AudioManager.RINGER_MODE_VIBRATE: 1039 case AudioManager.RINGER_MODE_NORMAL: 1040 if (mZenMode != Global.ZEN_MODE_OFF) { 1041 newZen = Global.ZEN_MODE_OFF; 1042 } 1043 break; 1044 } 1045 if (newZen != -1) { 1046 setManualZenMode(newZen, null, "ringerModeExternal", caller, 1047 false /*setRingerMode*/); 1048 } 1049 1050 ZenLog.traceSetRingerModeExternal(ringerModeOld, ringerModeNew, caller, 1051 ringerModeInternal, ringerModeInternalOut); 1052 return ringerModeInternalOut; 1053 } 1054 1055 @Override 1056 public boolean canVolumeDownEnterSilent() { 1057 return mZenMode == Global.ZEN_MODE_OFF; 1058 } 1059 1060 @Override 1061 public int getRingerModeAffectedStreams(int streams) { 1062 // ringtone, notification and system streams are always affected by ringer mode 1063 streams |= (1 << AudioSystem.STREAM_RING) | 1064 (1 << AudioSystem.STREAM_NOTIFICATION) | 1065 (1 << AudioSystem.STREAM_SYSTEM); 1066 1067 // alarm and music streams are only affected by ringer mode when in total silence 1068 if (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) { 1069 streams |= (1 << AudioSystem.STREAM_ALARM) | 1070 (1 << AudioSystem.STREAM_MUSIC); 1071 } else { 1072 streams &= ~((1 << AudioSystem.STREAM_ALARM) | 1073 (1 << AudioSystem.STREAM_MUSIC)); 1074 } 1075 return streams; 1076 } 1077 } 1078 1079 private final class SettingsObserver extends ContentObserver { 1080 private final Uri ZEN_MODE = Global.getUriFor(Global.ZEN_MODE); 1081 1082 public SettingsObserver(Handler handler) { 1083 super(handler); 1084 } 1085 1086 public void observe() { 1087 final ContentResolver resolver = mContext.getContentResolver(); 1088 resolver.registerContentObserver(ZEN_MODE, false /*notifyForDescendents*/, this); 1089 update(null); 1090 } 1091 1092 @Override 1093 public void onChange(boolean selfChange, Uri uri) { 1094 update(uri); 1095 } 1096 1097 public void update(Uri uri) { 1098 if (ZEN_MODE.equals(uri)) { 1099 if (mZenMode != getZenModeSetting()) { 1100 if (DEBUG) Log.d(TAG, "Fixing zen mode setting"); 1101 setZenModeSetting(mZenMode); 1102 } 1103 } 1104 } 1105 } 1106 1107 private final class Metrics extends Callback { 1108 private static final String COUNTER_PREFIX = "dnd_mode_"; 1109 private static final long MINIMUM_LOG_PERIOD_MS = 60 * 1000; 1110 1111 private int mPreviousZenMode = -1; 1112 private long mBeginningMs = 0L; 1113 1114 @Override 1115 void onZenModeChanged() { 1116 emit(); 1117 } 1118 1119 private void emit() { 1120 mHandler.postMetricsTimer(); 1121 final long now = SystemClock.elapsedRealtime(); 1122 final long since = (now - mBeginningMs); 1123 if (mPreviousZenMode != mZenMode || since > MINIMUM_LOG_PERIOD_MS) { 1124 if (mPreviousZenMode != -1) { 1125 MetricsLogger.count(mContext, COUNTER_PREFIX + mPreviousZenMode, (int) since); 1126 } 1127 mPreviousZenMode = mZenMode; 1128 mBeginningMs = now; 1129 } 1130 } 1131 } 1132 1133 private final class H extends Handler { 1134 private static final int MSG_DISPATCH = 1; 1135 private static final int MSG_METRICS = 2; 1136 private static final int MSG_APPLY_CONFIG = 4; 1137 1138 private final class ConfigMessageData { 1139 public final ZenModeConfig config; 1140 public final String reason; 1141 public final boolean setRingerMode; 1142 1143 ConfigMessageData(ZenModeConfig config, String reason, boolean setRingerMode) { 1144 this.config = config; 1145 this.reason = reason; 1146 this.setRingerMode = setRingerMode; 1147 } 1148 } 1149 1150 private static final long METRICS_PERIOD_MS = 6 * 60 * 60 * 1000; 1151 1152 private H(Looper looper) { 1153 super(looper); 1154 } 1155 1156 private void postDispatchOnZenModeChanged() { 1157 removeMessages(MSG_DISPATCH); 1158 sendEmptyMessage(MSG_DISPATCH); 1159 } 1160 1161 private void postMetricsTimer() { 1162 removeMessages(MSG_METRICS); 1163 sendEmptyMessageDelayed(MSG_METRICS, METRICS_PERIOD_MS); 1164 } 1165 1166 private void postApplyConfig(ZenModeConfig config, String reason, boolean setRingerMode) { 1167 sendMessage(obtainMessage(MSG_APPLY_CONFIG, 1168 new ConfigMessageData(config, reason, setRingerMode))); 1169 } 1170 1171 @Override 1172 public void handleMessage(Message msg) { 1173 switch (msg.what) { 1174 case MSG_DISPATCH: 1175 dispatchOnZenModeChanged(); 1176 break; 1177 case MSG_METRICS: 1178 mMetrics.emit(); 1179 break; 1180 case MSG_APPLY_CONFIG: 1181 ConfigMessageData applyConfigData = (ConfigMessageData) msg.obj; 1182 applyConfig(applyConfigData.config, applyConfigData.reason, 1183 applyConfigData.setRingerMode); 1184 } 1185 } 1186 } 1187 1188 public static class Callback { 1189 void onConfigChanged() {} 1190 void onZenModeChanged() {} 1191 void onPolicyChanged() {} 1192 } 1193 1194 } 1195