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.Notification; 22 import android.app.NotificationManager; 23 import android.app.NotificationManager.Policy; 24 import android.app.PendingIntent; 25 import android.content.ComponentName; 26 import android.content.ContentResolver; 27 import android.content.Context; 28 import android.content.Intent; 29 import android.content.pm.ActivityInfo; 30 import android.content.pm.PackageItemInfo; 31 import android.content.pm.PackageManager; 32 import android.content.pm.ResolveInfo; 33 import android.content.pm.ServiceInfo; 34 import android.content.res.Resources; 35 import android.content.res.XmlResourceParser; 36 import android.database.ContentObserver; 37 import android.graphics.drawable.Icon; 38 import android.media.AudioAttributes; 39 import android.media.AudioManager; 40 import android.media.AudioManagerInternal; 41 import android.media.AudioSystem; 42 import android.media.VolumePolicy; 43 import android.net.Uri; 44 import android.os.Binder; 45 import android.os.Bundle; 46 import android.os.Handler; 47 import android.os.Looper; 48 import android.os.Message; 49 import android.os.Process; 50 import android.os.SystemClock; 51 import android.os.UserHandle; 52 import android.provider.Settings; 53 import android.provider.Settings.Global; 54 import android.service.notification.Condition; 55 import android.service.notification.ConditionProviderService; 56 import android.service.notification.ZenModeConfig; 57 import android.service.notification.ZenModeConfig.ZenRule; 58 import android.service.notification.ZenModeProto; 59 import android.service.notification.ZenPolicy; 60 import android.util.AndroidRuntimeException; 61 import android.util.ArrayMap; 62 import android.util.Log; 63 import android.util.Slog; 64 import android.util.SparseArray; 65 import android.util.proto.ProtoOutputStream; 66 67 import com.android.internal.R; 68 import com.android.internal.annotations.VisibleForTesting; 69 import com.android.internal.logging.MetricsLogger; 70 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; 71 import com.android.internal.notification.SystemNotificationChannels; 72 import com.android.server.LocalServices; 73 74 import libcore.io.IoUtils; 75 76 import org.xmlpull.v1.XmlPullParser; 77 import org.xmlpull.v1.XmlPullParserException; 78 import org.xmlpull.v1.XmlSerializer; 79 80 import java.io.IOException; 81 import java.io.PrintWriter; 82 import java.util.ArrayList; 83 import java.util.List; 84 import java.util.Objects; 85 86 /** 87 * NotificationManagerService helper for functionality related to zen mode. 88 */ 89 public class ZenModeHelper { 90 static final String TAG = "ZenModeHelper"; 91 static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 92 93 // The amount of time rules instances can exist without their owning app being installed. 94 private static final int RULE_INSTANCE_GRACE_PERIOD = 1000 * 60 * 60 * 72; 95 96 private final Context mContext; 97 private final H mHandler; 98 private final SettingsObserver mSettingsObserver; 99 private final AppOpsManager mAppOps; 100 @VisibleForTesting protected final NotificationManager mNotificationManager; 101 @VisibleForTesting protected ZenModeConfig mDefaultConfig; 102 private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>(); 103 private final ZenModeFiltering mFiltering; 104 protected final RingerModeDelegate mRingerModeDelegate = new 105 RingerModeDelegate(); 106 @VisibleForTesting protected final ZenModeConditions mConditions; 107 @VisibleForTesting final SparseArray<ZenModeConfig> mConfigs = new SparseArray<>(); 108 private final Metrics mMetrics = new Metrics(); 109 private final ConditionProviders.Config mServiceConfig; 110 111 @VisibleForTesting protected int mZenMode; 112 @VisibleForTesting protected NotificationManager.Policy mConsolidatedPolicy; 113 private int mUser = UserHandle.USER_SYSTEM; 114 @VisibleForTesting protected ZenModeConfig mConfig; 115 @VisibleForTesting protected AudioManagerInternal mAudioManager; 116 protected PackageManager mPm; 117 private long mSuppressedEffects; 118 119 public static final long SUPPRESSED_EFFECT_NOTIFICATIONS = 1; 120 public static final long SUPPRESSED_EFFECT_CALLS = 1 << 1; 121 public static final long SUPPRESSED_EFFECT_ALL = SUPPRESSED_EFFECT_CALLS 122 | SUPPRESSED_EFFECT_NOTIFICATIONS; 123 124 @VisibleForTesting protected boolean mIsBootComplete; 125 126 private String[] mPriorityOnlyDndExemptPackages; 127 ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders)128 public ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders) { 129 mContext = context; 130 mHandler = new H(looper); 131 addCallback(mMetrics); 132 mAppOps = context.getSystemService(AppOpsManager.class); 133 mNotificationManager = context.getSystemService(NotificationManager.class); 134 135 mDefaultConfig = readDefaultConfig(mContext.getResources()); 136 updateDefaultAutomaticRuleNames(); 137 mConfig = mDefaultConfig.copy(); 138 mConfigs.put(UserHandle.USER_SYSTEM, mConfig); 139 140 mSettingsObserver = new SettingsObserver(mHandler); 141 mSettingsObserver.observe(); 142 mFiltering = new ZenModeFiltering(mContext); 143 mConditions = new ZenModeConditions(this, conditionProviders); 144 mServiceConfig = conditionProviders.getConfig(); 145 } 146 getLooper()147 public Looper getLooper() { 148 return mHandler.getLooper(); 149 } 150 151 @Override toString()152 public String toString() { 153 return TAG; 154 } 155 matchesCallFilter(UserHandle userHandle, Bundle extras, ValidateNotificationPeople validator, int contactsTimeoutMs, float timeoutAffinity)156 public boolean matchesCallFilter(UserHandle userHandle, Bundle extras, 157 ValidateNotificationPeople validator, int contactsTimeoutMs, float timeoutAffinity) { 158 synchronized (mConfig) { 159 return ZenModeFiltering.matchesCallFilter(mContext, mZenMode, mConsolidatedPolicy, 160 userHandle, extras, validator, contactsTimeoutMs, timeoutAffinity); 161 } 162 } 163 isCall(NotificationRecord record)164 public boolean isCall(NotificationRecord record) { 165 return mFiltering.isCall(record); 166 } 167 recordCaller(NotificationRecord record)168 public void recordCaller(NotificationRecord record) { 169 mFiltering.recordCall(record); 170 } 171 shouldIntercept(NotificationRecord record)172 public boolean shouldIntercept(NotificationRecord record) { 173 synchronized (mConfig) { 174 return mFiltering.shouldIntercept(mZenMode, mConsolidatedPolicy, record); 175 } 176 } 177 addCallback(Callback callback)178 public void addCallback(Callback callback) { 179 mCallbacks.add(callback); 180 } 181 removeCallback(Callback callback)182 public void removeCallback(Callback callback) { 183 mCallbacks.remove(callback); 184 } 185 initZenMode()186 public void initZenMode() { 187 if (DEBUG) Log.d(TAG, "initZenMode"); 188 evaluateZenMode("init", true /*setRingerMode*/); 189 } 190 onSystemReady()191 public void onSystemReady() { 192 if (DEBUG) Log.d(TAG, "onSystemReady"); 193 mAudioManager = LocalServices.getService(AudioManagerInternal.class); 194 if (mAudioManager != null) { 195 mAudioManager.setRingerModeDelegate(mRingerModeDelegate); 196 } 197 mPm = mContext.getPackageManager(); 198 mHandler.postMetricsTimer(); 199 cleanUpZenRules(); 200 evaluateZenMode("onSystemReady", true); 201 mIsBootComplete = true; 202 showZenUpgradeNotification(mZenMode); 203 } 204 onUserSwitched(int user)205 public void onUserSwitched(int user) { 206 loadConfigForUser(user, "onUserSwitched"); 207 } 208 onUserRemoved(int user)209 public void onUserRemoved(int user) { 210 if (user < UserHandle.USER_SYSTEM) return; 211 if (DEBUG) Log.d(TAG, "onUserRemoved u=" + user); 212 mConfigs.remove(user); 213 } 214 onUserUnlocked(int user)215 public void onUserUnlocked(int user) { 216 loadConfigForUser(user, "onUserUnlocked"); 217 } 218 setPriorityOnlyDndExemptPackages(String[] packages)219 void setPriorityOnlyDndExemptPackages(String[] packages) { 220 mPriorityOnlyDndExemptPackages = packages; 221 } 222 loadConfigForUser(int user, String reason)223 private void loadConfigForUser(int user, String reason) { 224 if (mUser == user || user < UserHandle.USER_SYSTEM) return; 225 mUser = user; 226 if (DEBUG) Log.d(TAG, reason + " u=" + user); 227 ZenModeConfig config = mConfigs.get(user); 228 if (config == null) { 229 if (DEBUG) Log.d(TAG, reason + " generating default config for user " + user); 230 config = mDefaultConfig.copy(); 231 config.user = user; 232 } 233 synchronized (mConfig) { 234 setConfigLocked(config, null, reason); 235 } 236 cleanUpZenRules(); 237 } 238 getZenModeListenerInterruptionFilter()239 public int getZenModeListenerInterruptionFilter() { 240 return NotificationManager.zenModeToInterruptionFilter(mZenMode); 241 } 242 requestFromListener(ComponentName name, int filter)243 public void requestFromListener(ComponentName name, int filter) { 244 final int newZen = NotificationManager.zenModeFromInterruptionFilter(filter, -1); 245 if (newZen != -1) { 246 setManualZenMode(newZen, null, name != null ? name.getPackageName() : null, 247 "listener:" + (name != null ? name.flattenToShortString() : null)); 248 } 249 } 250 setSuppressedEffects(long suppressedEffects)251 public void setSuppressedEffects(long suppressedEffects) { 252 if (mSuppressedEffects == suppressedEffects) return; 253 mSuppressedEffects = suppressedEffects; 254 applyRestrictions(); 255 } 256 getSuppressedEffects()257 public long getSuppressedEffects() { 258 return mSuppressedEffects; 259 } 260 getZenMode()261 public int getZenMode() { 262 return mZenMode; 263 } 264 getZenRules()265 public List<ZenRule> getZenRules() { 266 List<ZenRule> rules = new ArrayList<>(); 267 synchronized (mConfig) { 268 if (mConfig == null) return rules; 269 for (ZenRule rule : mConfig.automaticRules.values()) { 270 if (canManageAutomaticZenRule(rule)) { 271 rules.add(rule); 272 } 273 } 274 } 275 return rules; 276 } 277 getAutomaticZenRule(String id)278 public AutomaticZenRule getAutomaticZenRule(String id) { 279 ZenRule rule; 280 synchronized (mConfig) { 281 if (mConfig == null) return null; 282 rule = mConfig.automaticRules.get(id); 283 } 284 if (rule == null) return null; 285 if (canManageAutomaticZenRule(rule)) { 286 return createAutomaticZenRule(rule); 287 } 288 return null; 289 } 290 addAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason)291 public String addAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason) { 292 if (!isSystemRule(automaticZenRule)) { 293 PackageItemInfo component = getServiceInfo(automaticZenRule.getOwner()); 294 if (component == null) { 295 component = getActivityInfo(automaticZenRule.getConfigurationActivity()); 296 } 297 if (component == null) { 298 throw new IllegalArgumentException("Lacking enabled CPS or config activity"); 299 } 300 int ruleInstanceLimit = -1; 301 if (component.metaData != null) { 302 ruleInstanceLimit = component.metaData.getInt( 303 ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1); 304 } 305 int newRuleInstanceCount = getCurrentInstanceCount(automaticZenRule.getOwner()) 306 + getCurrentInstanceCount(automaticZenRule.getConfigurationActivity()) 307 + 1; 308 if (ruleInstanceLimit > 0 && ruleInstanceLimit < newRuleInstanceCount) { 309 throw new IllegalArgumentException("Rule instance limit exceeded"); 310 } 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, rule.component, true)) { 327 return rule.id; 328 } else { 329 throw new AndroidRuntimeException("Could not create rule"); 330 } 331 } 332 } 333 updateAutomaticZenRule(String ruleId, AutomaticZenRule automaticZenRule, String reason)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 return setConfigLocked(newConfig, reason, rule.component, true); 356 } 357 } 358 removeAutomaticZenRule(String id, String reason)359 public boolean removeAutomaticZenRule(String id, String reason) { 360 ZenModeConfig newConfig; 361 synchronized (mConfig) { 362 if (mConfig == null) return false; 363 newConfig = mConfig.copy(); 364 ZenRule rule = newConfig.automaticRules.get(id); 365 if (rule == null) return false; 366 if (canManageAutomaticZenRule(rule)) { 367 newConfig.automaticRules.remove(id); 368 if (DEBUG) Log.d(TAG, "removeZenRule zenRule=" + id + " reason=" + reason); 369 } else { 370 throw new SecurityException( 371 "Cannot delete rules not owned by your condition provider"); 372 } 373 return setConfigLocked(newConfig, reason, null, true); 374 } 375 } 376 removeAutomaticZenRules(String packageName, String reason)377 public boolean removeAutomaticZenRules(String packageName, String reason) { 378 ZenModeConfig newConfig; 379 synchronized (mConfig) { 380 if (mConfig == null) return false; 381 newConfig = mConfig.copy(); 382 for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) { 383 ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i)); 384 if (rule.pkg.equals(packageName) && canManageAutomaticZenRule(rule)) { 385 newConfig.automaticRules.removeAt(i); 386 } 387 } 388 return setConfigLocked(newConfig, reason, null, true); 389 } 390 } 391 setAutomaticZenRuleState(String id, Condition condition)392 public void setAutomaticZenRuleState(String id, Condition condition) { 393 ZenModeConfig newConfig; 394 synchronized (mConfig) { 395 if (mConfig == null) return; 396 397 newConfig = mConfig.copy(); 398 setAutomaticZenRuleStateLocked(newConfig, newConfig.automaticRules.get(id), condition); 399 } 400 } 401 setAutomaticZenRuleState(Uri ruleDefinition, Condition condition)402 public void setAutomaticZenRuleState(Uri ruleDefinition, Condition condition) { 403 ZenModeConfig newConfig; 404 synchronized (mConfig) { 405 if (mConfig == null) return; 406 newConfig = mConfig.copy(); 407 408 setAutomaticZenRuleStateLocked(newConfig, 409 findMatchingRule(newConfig, ruleDefinition, condition), 410 condition); 411 } 412 } 413 setAutomaticZenRuleStateLocked(ZenModeConfig config, ZenRule rule, Condition condition)414 private void setAutomaticZenRuleStateLocked(ZenModeConfig config, ZenRule rule, 415 Condition condition) { 416 if (rule == null) return; 417 418 rule.condition = condition; 419 updateSnoozing(rule); 420 setConfigLocked(config, rule.component, "conditionChanged"); 421 } 422 findMatchingRule(ZenModeConfig config, Uri id, Condition condition)423 private ZenRule findMatchingRule(ZenModeConfig config, Uri id, Condition condition) { 424 if (ruleMatches(id, condition, config.manualRule)) { 425 return config.manualRule; 426 } else { 427 for (ZenRule automaticRule : config.automaticRules.values()) { 428 if (ruleMatches(id, condition, automaticRule)) { 429 return automaticRule; 430 } 431 } 432 } 433 return null; 434 } 435 ruleMatches(Uri id, Condition condition, ZenRule rule)436 private boolean ruleMatches(Uri id, Condition condition, ZenRule rule) { 437 if (id == null || rule == null || rule.conditionId == null) return false; 438 if (!rule.conditionId.equals(id)) return false; 439 if (Objects.equals(condition, rule.condition)) return false; 440 return true; 441 } 442 updateSnoozing(ZenRule rule)443 private boolean updateSnoozing(ZenRule rule) { 444 if (rule != null && rule.snoozing && !rule.isTrueOrUnknown()) { 445 rule.snoozing = false; 446 if (DEBUG) Log.d(TAG, "Snoozing reset for " + rule.conditionId); 447 return true; 448 } 449 return false; 450 } 451 getCurrentInstanceCount(ComponentName cn)452 public int getCurrentInstanceCount(ComponentName cn) { 453 if (cn == null) { 454 return 0; 455 } 456 int count = 0; 457 synchronized (mConfig) { 458 for (ZenRule rule : mConfig.automaticRules.values()) { 459 if (cn.equals(rule.component) || cn.equals(rule.configurationActivity)) { 460 count++; 461 } 462 } 463 } 464 return count; 465 } 466 canManageAutomaticZenRule(ZenRule rule)467 public boolean canManageAutomaticZenRule(ZenRule rule) { 468 final int callingUid = Binder.getCallingUid(); 469 if (callingUid == 0 || callingUid == Process.SYSTEM_UID) { 470 return true; 471 } else if (mContext.checkCallingPermission(android.Manifest.permission.MANAGE_NOTIFICATIONS) 472 == PackageManager.PERMISSION_GRANTED) { 473 return true; 474 } else { 475 String[] packages = mPm.getPackagesForUid(Binder.getCallingUid()); 476 if (packages != null) { 477 final int packageCount = packages.length; 478 for (int i = 0; i < packageCount; i++) { 479 if (packages[i].equals(rule.pkg)) { 480 return true; 481 } 482 } 483 } 484 return false; 485 } 486 } 487 updateDefaultZenRules()488 protected void updateDefaultZenRules() { 489 updateDefaultAutomaticRuleNames(); 490 for (ZenRule defaultRule : mDefaultConfig.automaticRules.values()) { 491 ZenRule currRule = mConfig.automaticRules.get(defaultRule.id); 492 // if default rule wasn't user-modified nor enabled, use localized name 493 // instead of previous system name 494 if (currRule != null && !currRule.modified && !currRule.enabled 495 && !defaultRule.name.equals(currRule.name)) { 496 if (canManageAutomaticZenRule(currRule)) { 497 if (DEBUG) Slog.d(TAG, "Locale change - updating default zen rule name " 498 + "from " + currRule.name + " to " + defaultRule.name); 499 // update default rule (if locale changed, name of rule will change) 500 currRule.name = defaultRule.name; 501 updateAutomaticZenRule(defaultRule.id, createAutomaticZenRule(currRule), 502 "locale changed"); 503 } 504 } 505 } 506 } 507 isSystemRule(AutomaticZenRule rule)508 private boolean isSystemRule(AutomaticZenRule rule) { 509 return rule.getOwner() != null 510 && ZenModeConfig.SYSTEM_AUTHORITY.equals(rule.getOwner().getPackageName()); 511 } 512 getServiceInfo(ComponentName owner)513 private ServiceInfo getServiceInfo(ComponentName owner) { 514 Intent queryIntent = new Intent(); 515 queryIntent.setComponent(owner); 516 List<ResolveInfo> installedServices = mPm.queryIntentServicesAsUser( 517 queryIntent, 518 PackageManager.GET_SERVICES | PackageManager.GET_META_DATA, 519 UserHandle.getCallingUserId()); 520 if (installedServices != null) { 521 for (int i = 0, count = installedServices.size(); i < count; i++) { 522 ResolveInfo resolveInfo = installedServices.get(i); 523 ServiceInfo info = resolveInfo.serviceInfo; 524 if (mServiceConfig.bindPermission.equals(info.permission)) { 525 return info; 526 } 527 } 528 } 529 return null; 530 } 531 getActivityInfo(ComponentName configActivity)532 private ActivityInfo getActivityInfo(ComponentName configActivity) { 533 Intent queryIntent = new Intent(); 534 queryIntent.setComponent(configActivity); 535 List<ResolveInfo> installedComponents = mPm.queryIntentActivitiesAsUser( 536 queryIntent, 537 PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA, 538 UserHandle.getCallingUserId()); 539 if (installedComponents != null) { 540 for (int i = 0, count = installedComponents.size(); i < count; i++) { 541 ResolveInfo resolveInfo = installedComponents.get(i); 542 return resolveInfo.activityInfo; 543 } 544 } 545 return null; 546 } 547 populateZenRule(AutomaticZenRule automaticZenRule, ZenRule rule, boolean isNew)548 private void populateZenRule(AutomaticZenRule automaticZenRule, ZenRule rule, boolean isNew) { 549 if (isNew) { 550 rule.id = ZenModeConfig.newRuleId(); 551 rule.creationTime = System.currentTimeMillis(); 552 rule.component = automaticZenRule.getOwner(); 553 rule.configurationActivity = automaticZenRule.getConfigurationActivity(); 554 rule.pkg = (rule.component != null) 555 ? rule.component.getPackageName() 556 : rule.configurationActivity.getPackageName(); 557 } 558 559 if (rule.enabled != automaticZenRule.isEnabled()) { 560 rule.snoozing = false; 561 } 562 rule.name = automaticZenRule.getName(); 563 rule.condition = null; 564 rule.conditionId = automaticZenRule.getConditionId(); 565 rule.enabled = automaticZenRule.isEnabled(); 566 rule.modified = automaticZenRule.isModified(); 567 rule.zenPolicy = automaticZenRule.getZenPolicy(); 568 rule.zenMode = NotificationManager.zenModeFromInterruptionFilter( 569 automaticZenRule.getInterruptionFilter(), Global.ZEN_MODE_OFF); 570 } 571 createAutomaticZenRule(ZenRule rule)572 protected AutomaticZenRule createAutomaticZenRule(ZenRule rule) { 573 return new AutomaticZenRule(rule.name, rule.component, rule.configurationActivity, 574 rule.conditionId, rule.zenPolicy, 575 NotificationManager.zenModeToInterruptionFilter(rule.zenMode), 576 rule.enabled, rule.creationTime); 577 } 578 setManualZenMode(int zenMode, Uri conditionId, String caller, String reason)579 public void setManualZenMode(int zenMode, Uri conditionId, String caller, String reason) { 580 setManualZenMode(zenMode, conditionId, reason, caller, true /*setRingerMode*/); 581 Settings.Secure.putInt(mContext.getContentResolver(), 582 Settings.Secure.SHOW_ZEN_SETTINGS_SUGGESTION, 0); 583 } 584 setManualZenMode(int zenMode, Uri conditionId, String reason, String caller, boolean setRingerMode)585 private void setManualZenMode(int zenMode, Uri conditionId, String reason, String caller, 586 boolean setRingerMode) { 587 ZenModeConfig newConfig; 588 synchronized (mConfig) { 589 if (mConfig == null) return; 590 if (!Global.isValidZenMode(zenMode)) return; 591 if (DEBUG) Log.d(TAG, "setManualZenMode " + Global.zenModeToString(zenMode) 592 + " conditionId=" + conditionId + " reason=" + reason 593 + " setRingerMode=" + setRingerMode); 594 newConfig = mConfig.copy(); 595 if (zenMode == Global.ZEN_MODE_OFF) { 596 newConfig.manualRule = null; 597 for (ZenRule automaticRule : newConfig.automaticRules.values()) { 598 if (automaticRule.isAutomaticActive()) { 599 automaticRule.snoozing = true; 600 } 601 } 602 } else { 603 final ZenRule newRule = new ZenRule(); 604 newRule.enabled = true; 605 newRule.zenMode = zenMode; 606 newRule.conditionId = conditionId; 607 newRule.enabler = caller; 608 newConfig.manualRule = newRule; 609 } 610 setConfigLocked(newConfig, reason, null, setRingerMode); 611 } 612 } 613 dump(ProtoOutputStream proto)614 void dump(ProtoOutputStream proto) { 615 proto.write(ZenModeProto.ZEN_MODE, mZenMode); 616 synchronized (mConfig) { 617 if (mConfig.manualRule != null) { 618 mConfig.manualRule.writeToProto(proto, ZenModeProto.ENABLED_ACTIVE_CONDITIONS); 619 } 620 for (ZenRule rule : mConfig.automaticRules.values()) { 621 if (rule.enabled && rule.condition.state == Condition.STATE_TRUE 622 && !rule.snoozing) { 623 rule.writeToProto(proto, ZenModeProto.ENABLED_ACTIVE_CONDITIONS); 624 } 625 } 626 mConfig.toNotificationPolicy().writeToProto(proto, ZenModeProto.POLICY); 627 proto.write(ZenModeProto.SUPPRESSED_EFFECTS, mSuppressedEffects); 628 } 629 } 630 dump(PrintWriter pw, String prefix)631 public void dump(PrintWriter pw, String prefix) { 632 pw.print(prefix); pw.print("mZenMode="); 633 pw.println(Global.zenModeToString(mZenMode)); 634 pw.print("mConsolidatedPolicy=" + mConsolidatedPolicy.toString()); 635 final int N = mConfigs.size(); 636 for (int i = 0; i < N; i++) { 637 dump(pw, prefix, "mConfigs[u=" + mConfigs.keyAt(i) + "]", mConfigs.valueAt(i)); 638 } 639 pw.print(prefix); pw.print("mUser="); pw.println(mUser); 640 synchronized (mConfig) { 641 dump(pw, prefix, "mConfig", mConfig); 642 } 643 644 pw.print(prefix); pw.print("mSuppressedEffects="); pw.println(mSuppressedEffects); 645 mFiltering.dump(pw, prefix); 646 mConditions.dump(pw, prefix); 647 } 648 dump(PrintWriter pw, String prefix, String var, ZenModeConfig config)649 private static void dump(PrintWriter pw, String prefix, String var, ZenModeConfig config) { 650 pw.print(prefix); pw.print(var); pw.print('='); 651 if (config == null) { 652 pw.println(config); 653 return; 654 } 655 pw.printf("allow(alarms=%b,media=%b,system=%b,calls=%b,callsFrom=%s,repeatCallers=%b," 656 + "messages=%b,messagesFrom=%s,events=%b,reminders=%b)\n", 657 config.allowAlarms, config.allowMedia, config.allowSystem, 658 config.allowCalls, ZenModeConfig.sourceToString(config.allowCallsFrom), 659 config.allowRepeatCallers, config.allowMessages, 660 ZenModeConfig.sourceToString(config.allowMessagesFrom), 661 config.allowEvents, config.allowReminders); 662 pw.printf(" disallow(visualEffects=%s)\n", config.suppressedVisualEffects); 663 pw.print(prefix); pw.print(" manualRule="); pw.println(config.manualRule); 664 if (config.automaticRules.isEmpty()) return; 665 final int N = config.automaticRules.size(); 666 for (int i = 0; i < N; i++) { 667 pw.print(prefix); pw.print(i == 0 ? " automaticRules=" : " "); 668 pw.println(config.automaticRules.valueAt(i)); 669 } 670 } 671 readXml(XmlPullParser parser, boolean forRestore, int userId)672 public void readXml(XmlPullParser parser, boolean forRestore, int userId) 673 throws XmlPullParserException, IOException { 674 ZenModeConfig config = ZenModeConfig.readXml(parser); 675 String reason = "readXml"; 676 677 if (config != null) { 678 if (forRestore) { 679 config.user = userId; 680 config.manualRule = null; // don't restore the manual rule 681 } 682 683 // booleans to determine whether to reset the rules to the default rules 684 boolean allRulesDisabled = true; 685 boolean hasDefaultRules = config.automaticRules.containsAll( 686 ZenModeConfig.DEFAULT_RULE_IDS); 687 688 long time = System.currentTimeMillis(); 689 if (config.automaticRules != null && config.automaticRules.size() > 0) { 690 for (ZenRule automaticRule : config.automaticRules.values()) { 691 if (forRestore) { 692 // don't restore transient state from restored automatic rules 693 automaticRule.snoozing = false; 694 automaticRule.condition = null; 695 automaticRule.creationTime = time; 696 } 697 698 allRulesDisabled &= !automaticRule.enabled; 699 } 700 } 701 702 if (!hasDefaultRules && allRulesDisabled 703 && (forRestore || config.version < ZenModeConfig.XML_VERSION)) { 704 // reset zen automatic rules to default on restore or upgrade if: 705 // - doesn't already have default rules and 706 // - all previous automatic rules were disabled 707 config.automaticRules = new ArrayMap<>(); 708 for (ZenRule rule : mDefaultConfig.automaticRules.values()) { 709 config.automaticRules.put(rule.id, rule); 710 } 711 reason += ", reset to default rules"; 712 } 713 714 // Resolve user id for settings. 715 userId = userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId; 716 if (config.version < ZenModeConfig.XML_VERSION) { 717 Settings.Secure.putIntForUser(mContext.getContentResolver(), 718 Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 1, userId); 719 } else { 720 // devices not restoring/upgrading already have updated zen settings 721 Settings.Secure.putIntForUser(mContext.getContentResolver(), 722 Settings.Secure.ZEN_SETTINGS_UPDATED, 1, userId); 723 } 724 if (DEBUG) Log.d(TAG, reason); 725 synchronized (mConfig) { 726 setConfigLocked(config, null, reason); 727 } 728 } 729 } 730 writeXml(XmlSerializer out, boolean forBackup, Integer version, int userId)731 public void writeXml(XmlSerializer out, boolean forBackup, Integer version, int userId) 732 throws IOException { 733 synchronized (mConfigs) { 734 final int n = mConfigs.size(); 735 for (int i = 0; i < n; i++) { 736 if (forBackup && mConfigs.keyAt(i) != userId) { 737 continue; 738 } 739 mConfigs.valueAt(i).writeXml(out, version); 740 } 741 } 742 } 743 744 /** 745 * @return user-specified default notification policy for priority only do not disturb 746 */ getNotificationPolicy()747 public Policy getNotificationPolicy() { 748 return getNotificationPolicy(mConfig); 749 } 750 getNotificationPolicy(ZenModeConfig config)751 private static Policy getNotificationPolicy(ZenModeConfig config) { 752 return config == null ? null : config.toNotificationPolicy(); 753 } 754 755 /** 756 * Sets the global notification policy used for priority only do not disturb 757 */ setNotificationPolicy(Policy policy)758 public void setNotificationPolicy(Policy policy) { 759 if (policy == null || mConfig == null) return; 760 synchronized (mConfig) { 761 final ZenModeConfig newConfig = mConfig.copy(); 762 newConfig.applyNotificationPolicy(policy); 763 setConfigLocked(newConfig, null, "setNotificationPolicy"); 764 } 765 } 766 767 /** 768 * Removes old rule instances whose owner is not installed. 769 */ cleanUpZenRules()770 private void cleanUpZenRules() { 771 long currentTime = System.currentTimeMillis(); 772 synchronized (mConfig) { 773 final ZenModeConfig newConfig = mConfig.copy(); 774 if (newConfig.automaticRules != null) { 775 for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) { 776 ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i)); 777 if (RULE_INSTANCE_GRACE_PERIOD < (currentTime - rule.creationTime)) { 778 try { 779 if (rule.pkg != null) { 780 mPm.getPackageInfo(rule.pkg, PackageManager.MATCH_ANY_USER); 781 } 782 } catch (PackageManager.NameNotFoundException e) { 783 newConfig.automaticRules.removeAt(i); 784 } 785 } 786 } 787 } 788 setConfigLocked(newConfig, null, "cleanUpZenRules"); 789 } 790 } 791 792 /** 793 * @return a copy of the zen mode configuration 794 */ getConfig()795 public ZenModeConfig getConfig() { 796 synchronized (mConfig) { 797 return mConfig.copy(); 798 } 799 } 800 801 /** 802 * @return a copy of the zen mode consolidated policy 803 */ getConsolidatedNotificationPolicy()804 public Policy getConsolidatedNotificationPolicy() { 805 if (mConsolidatedPolicy == null) { 806 return null; 807 } 808 return mConsolidatedPolicy.copy(); 809 } 810 setConfigLocked(ZenModeConfig config, ComponentName triggeringComponent, String reason)811 public boolean setConfigLocked(ZenModeConfig config, ComponentName triggeringComponent, 812 String reason) { 813 return setConfigLocked(config, reason, triggeringComponent, true /*setRingerMode*/); 814 } 815 setConfig(ZenModeConfig config, ComponentName triggeringComponent, String reason)816 public void setConfig(ZenModeConfig config, ComponentName triggeringComponent, String reason) { 817 synchronized (mConfig) { 818 setConfigLocked(config, triggeringComponent, reason); 819 } 820 } 821 setConfigLocked(ZenModeConfig config, String reason, ComponentName triggeringComponent, boolean setRingerMode)822 private boolean setConfigLocked(ZenModeConfig config, String reason, 823 ComponentName triggeringComponent, boolean setRingerMode) { 824 final long identity = Binder.clearCallingIdentity(); 825 try { 826 if (config == null || !config.isValid()) { 827 Log.w(TAG, "Invalid config in setConfigLocked; " + config); 828 return false; 829 } 830 if (config.user != mUser) { 831 // simply store away for background users 832 mConfigs.put(config.user, config); 833 if (DEBUG) Log.d(TAG, "setConfigLocked: store config for user " + config.user); 834 return true; 835 } 836 // handle CPS backed conditions - danger! may modify config 837 mConditions.evaluateConfig(config, null, false /*processSubscriptions*/); 838 839 mConfigs.put(config.user, config); 840 if (DEBUG) Log.d(TAG, "setConfigLocked reason=" + reason, new Throwable()); 841 ZenLog.traceConfig(reason, mConfig, config); 842 843 // send some broadcasts 844 final boolean policyChanged = !Objects.equals(getNotificationPolicy(mConfig), 845 getNotificationPolicy(config)); 846 if (!config.equals(mConfig)) { 847 mConfig = config; 848 dispatchOnConfigChanged(); 849 updateConsolidatedPolicy(reason); 850 } 851 if (policyChanged) { 852 dispatchOnPolicyChanged(); 853 } 854 mHandler.postApplyConfig(config, reason, triggeringComponent, setRingerMode); 855 return true; 856 } catch (SecurityException e) { 857 Log.wtf(TAG, "Invalid rule in config", e); 858 return false; 859 } finally { 860 Binder.restoreCallingIdentity(identity); 861 } 862 } 863 applyConfig(ZenModeConfig config, String reason, ComponentName triggeringComponent, boolean setRingerMode)864 private void applyConfig(ZenModeConfig config, String reason, 865 ComponentName triggeringComponent, boolean setRingerMode) { 866 final String val = Integer.toString(config.hashCode()); 867 Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_CONFIG_ETAG, val); 868 evaluateZenMode(reason, setRingerMode); 869 mConditions.evaluateConfig(config, triggeringComponent, true /*processSubscriptions*/); 870 } 871 getZenModeSetting()872 private int getZenModeSetting() { 873 return Global.getInt(mContext.getContentResolver(), Global.ZEN_MODE, Global.ZEN_MODE_OFF); 874 } 875 876 @VisibleForTesting setZenModeSetting(int zen)877 protected void setZenModeSetting(int zen) { 878 Global.putInt(mContext.getContentResolver(), Global.ZEN_MODE, zen); 879 showZenUpgradeNotification(zen); 880 } 881 getPreviousRingerModeSetting()882 private int getPreviousRingerModeSetting() { 883 return Global.getInt(mContext.getContentResolver(), 884 Global.ZEN_MODE_RINGER_LEVEL, AudioManager.RINGER_MODE_NORMAL); 885 } 886 setPreviousRingerModeSetting(Integer previousRingerLevel)887 private void setPreviousRingerModeSetting(Integer previousRingerLevel) { 888 Global.putString( 889 mContext.getContentResolver(), Global.ZEN_MODE_RINGER_LEVEL, 890 previousRingerLevel == null ? null : Integer.toString(previousRingerLevel)); 891 } 892 893 @VisibleForTesting evaluateZenMode(String reason, boolean setRingerMode)894 protected void evaluateZenMode(String reason, boolean setRingerMode) { 895 if (DEBUG) Log.d(TAG, "evaluateZenMode"); 896 if (mConfig == null) return; 897 final int policyHashBefore = mConsolidatedPolicy == null ? 0 898 : mConsolidatedPolicy.hashCode(); 899 final int zenBefore = mZenMode; 900 final int zen = computeZenMode(); 901 ZenLog.traceSetZenMode(zen, reason); 902 mZenMode = zen; 903 setZenModeSetting(mZenMode); 904 updateConsolidatedPolicy(reason); 905 updateRingerModeAffectedStreams(); 906 if (setRingerMode && (zen != zenBefore || (zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS 907 && policyHashBefore != mConsolidatedPolicy.hashCode()))) { 908 applyZenToRingerMode(); 909 } 910 applyRestrictions(); 911 if (zen != zenBefore) { 912 mHandler.postDispatchOnZenModeChanged(); 913 } 914 } 915 updateRingerModeAffectedStreams()916 private void updateRingerModeAffectedStreams() { 917 if (mAudioManager != null) { 918 mAudioManager.updateRingerModeAffectedStreamsInternal(); 919 } 920 } 921 computeZenMode()922 private int computeZenMode() { 923 if (mConfig == null) return Global.ZEN_MODE_OFF; 924 synchronized (mConfig) { 925 if (mConfig.manualRule != null) return mConfig.manualRule.zenMode; 926 int zen = Global.ZEN_MODE_OFF; 927 for (ZenRule automaticRule : mConfig.automaticRules.values()) { 928 if (automaticRule.isAutomaticActive()) { 929 if (zenSeverity(automaticRule.zenMode) > zenSeverity(zen)) { 930 // automatic rule triggered dnd and user hasn't seen update dnd dialog 931 if (Settings.Secure.getInt(mContext.getContentResolver(), 932 Settings.Secure.ZEN_SETTINGS_SUGGESTION_VIEWED, 1) == 0) { 933 Settings.Secure.putInt(mContext.getContentResolver(), 934 Settings.Secure.SHOW_ZEN_SETTINGS_SUGGESTION, 1); 935 } 936 zen = automaticRule.zenMode; 937 } 938 } 939 } 940 return zen; 941 } 942 } 943 applyCustomPolicy(ZenPolicy policy, ZenRule rule)944 private void applyCustomPolicy(ZenPolicy policy, ZenRule rule) { 945 if (rule.zenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) { 946 policy.apply(new ZenPolicy.Builder() 947 .disallowAllSounds() 948 .build()); 949 } else if (rule.zenMode == Global.ZEN_MODE_ALARMS) { 950 policy.apply(new ZenPolicy.Builder() 951 .disallowAllSounds() 952 .allowAlarms(true) 953 .allowMedia(true) 954 .build()); 955 } else { 956 policy.apply(rule.zenPolicy); 957 } 958 } 959 updateConsolidatedPolicy(String reason)960 private void updateConsolidatedPolicy(String reason) { 961 if (mConfig == null) return; 962 synchronized (mConfig) { 963 ZenPolicy policy = new ZenPolicy(); 964 if (mConfig.manualRule != null) { 965 applyCustomPolicy(policy, mConfig.manualRule); 966 } 967 968 for (ZenRule automaticRule : mConfig.automaticRules.values()) { 969 if (automaticRule.isAutomaticActive()) { 970 applyCustomPolicy(policy, automaticRule); 971 } 972 } 973 Policy newPolicy = mConfig.toNotificationPolicy(policy); 974 if (!Objects.equals(mConsolidatedPolicy, newPolicy)) { 975 mConsolidatedPolicy = newPolicy; 976 dispatchOnConsolidatedPolicyChanged(); 977 ZenLog.traceSetConsolidatedZenPolicy(mConsolidatedPolicy, reason); 978 } 979 } 980 } 981 updateDefaultAutomaticRuleNames()982 private void updateDefaultAutomaticRuleNames() { 983 for (ZenRule rule : mDefaultConfig.automaticRules.values()) { 984 if (ZenModeConfig.EVENTS_DEFAULT_RULE_ID.equals(rule.id)) { 985 rule.name = mContext.getResources() 986 .getString(R.string.zen_mode_default_events_name); 987 } else if (ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID.equals(rule.id)) { 988 rule.name = mContext.getResources() 989 .getString(R.string.zen_mode_default_every_night_name); 990 } 991 } 992 } 993 994 @VisibleForTesting applyRestrictions()995 protected void applyRestrictions() { 996 final boolean zenPriorityOnly = mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; 997 final boolean zenSilence = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS; 998 final boolean zenAlarmsOnly = mZenMode == Global.ZEN_MODE_ALARMS; 999 final boolean allowCalls = mConsolidatedPolicy.allowCalls(); 1000 final boolean allowRepeatCallers = mConsolidatedPolicy.allowRepeatCallers(); 1001 final boolean allowSystem = mConsolidatedPolicy.allowSystem(); 1002 final boolean allowMedia = mConsolidatedPolicy.allowMedia(); 1003 final boolean allowAlarms = mConsolidatedPolicy.allowAlarms(); 1004 1005 // notification restrictions 1006 final boolean muteNotifications = 1007 (mSuppressedEffects & SUPPRESSED_EFFECT_NOTIFICATIONS) != 0; 1008 // call restrictions 1009 final boolean muteCalls = zenAlarmsOnly 1010 || (zenPriorityOnly && !allowCalls && !allowRepeatCallers) 1011 || (mSuppressedEffects & SUPPRESSED_EFFECT_CALLS) != 0; 1012 // alarm restrictions 1013 final boolean muteAlarms = zenPriorityOnly && !allowAlarms; 1014 // media restrictions 1015 final boolean muteMedia = zenPriorityOnly && !allowMedia; 1016 // system restrictions 1017 final boolean muteSystem = zenAlarmsOnly || (zenPriorityOnly && !allowSystem); 1018 // total silence restrictions 1019 final boolean muteEverything = zenSilence || (zenPriorityOnly 1020 && ZenModeConfig.areAllZenBehaviorSoundsMuted(mConsolidatedPolicy)); 1021 1022 for (int usage : AudioAttributes.SDK_USAGES) { 1023 final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage); 1024 if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NEVER) { 1025 applyRestrictions(zenPriorityOnly, false /*mute*/, usage); 1026 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NOTIFICATION) { 1027 applyRestrictions(zenPriorityOnly, muteNotifications || muteEverything, usage); 1028 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_CALL) { 1029 applyRestrictions(zenPriorityOnly, muteCalls || muteEverything, usage); 1030 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_ALARM) { 1031 applyRestrictions(zenPriorityOnly, muteAlarms || muteEverything, usage); 1032 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_MEDIA) { 1033 applyRestrictions(zenPriorityOnly, muteMedia || muteEverything, usage); 1034 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_SYSTEM) { 1035 if (usage == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) { 1036 // normally DND will only restrict touch sounds, not haptic feedback/vibrations 1037 applyRestrictions(zenPriorityOnly, muteSystem || muteEverything, usage, 1038 AppOpsManager.OP_PLAY_AUDIO); 1039 applyRestrictions(zenPriorityOnly, false, usage, AppOpsManager.OP_VIBRATE); 1040 } else { 1041 applyRestrictions(zenPriorityOnly, muteSystem || muteEverything, usage); 1042 } 1043 } else { 1044 applyRestrictions(zenPriorityOnly, muteEverything, usage); 1045 } 1046 } 1047 } 1048 1049 1050 @VisibleForTesting applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage, int code)1051 protected void applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage, int code) { 1052 final long ident = Binder.clearCallingIdentity(); 1053 try { 1054 mAppOps.setRestriction(code, usage, 1055 mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED, 1056 zenPriorityOnly ? mPriorityOnlyDndExemptPackages : null); 1057 } finally { 1058 Binder.restoreCallingIdentity(ident); 1059 } 1060 } 1061 1062 @VisibleForTesting applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage)1063 protected void applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage) { 1064 applyRestrictions(zenPriorityOnly, mute, usage, AppOpsManager.OP_VIBRATE); 1065 applyRestrictions(zenPriorityOnly, mute, usage, AppOpsManager.OP_PLAY_AUDIO); 1066 } 1067 1068 1069 @VisibleForTesting applyZenToRingerMode()1070 protected void applyZenToRingerMode() { 1071 if (mAudioManager == null) return; 1072 // force the ringer mode into compliance 1073 final int ringerModeInternal = mAudioManager.getRingerModeInternal(); 1074 int newRingerModeInternal = ringerModeInternal; 1075 switch (mZenMode) { 1076 case Global.ZEN_MODE_NO_INTERRUPTIONS: 1077 case Global.ZEN_MODE_ALARMS: 1078 if (ringerModeInternal != AudioManager.RINGER_MODE_SILENT) { 1079 setPreviousRingerModeSetting(ringerModeInternal); 1080 newRingerModeInternal = AudioManager.RINGER_MODE_SILENT; 1081 } 1082 break; 1083 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: 1084 // do not apply zen to ringer, streams zen muted in AudioService 1085 break; 1086 case Global.ZEN_MODE_OFF: 1087 if (ringerModeInternal == AudioManager.RINGER_MODE_SILENT) { 1088 newRingerModeInternal = getPreviousRingerModeSetting(); 1089 setPreviousRingerModeSetting(null); 1090 } 1091 break; 1092 } 1093 if (newRingerModeInternal != -1) { 1094 mAudioManager.setRingerModeInternal(newRingerModeInternal, TAG); 1095 } 1096 } 1097 dispatchOnConfigChanged()1098 private void dispatchOnConfigChanged() { 1099 for (Callback callback : mCallbacks) { 1100 callback.onConfigChanged(); 1101 } 1102 } 1103 dispatchOnPolicyChanged()1104 private void dispatchOnPolicyChanged() { 1105 for (Callback callback : mCallbacks) { 1106 callback.onPolicyChanged(); 1107 } 1108 } 1109 dispatchOnConsolidatedPolicyChanged()1110 private void dispatchOnConsolidatedPolicyChanged() { 1111 for (Callback callback : mCallbacks) { 1112 callback.onConsolidatedPolicyChanged(); 1113 } 1114 } 1115 dispatchOnZenModeChanged()1116 private void dispatchOnZenModeChanged() { 1117 for (Callback callback : mCallbacks) { 1118 callback.onZenModeChanged(); 1119 } 1120 } 1121 readDefaultConfig(Resources resources)1122 private ZenModeConfig readDefaultConfig(Resources resources) { 1123 XmlResourceParser parser = null; 1124 try { 1125 parser = resources.getXml(R.xml.default_zen_mode_config); 1126 while (parser.next() != XmlPullParser.END_DOCUMENT) { 1127 final ZenModeConfig config = ZenModeConfig.readXml(parser); 1128 if (config != null) return config; 1129 } 1130 } catch (Exception e) { 1131 Log.w(TAG, "Error reading default zen mode config from resource", e); 1132 } finally { 1133 IoUtils.closeQuietly(parser); 1134 } 1135 return new ZenModeConfig(); 1136 } 1137 zenSeverity(int zen)1138 private static int zenSeverity(int zen) { 1139 switch (zen) { 1140 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: return 1; 1141 case Global.ZEN_MODE_ALARMS: return 2; 1142 case Global.ZEN_MODE_NO_INTERRUPTIONS: return 3; 1143 default: return 0; 1144 } 1145 } 1146 1147 @VisibleForTesting 1148 protected final class RingerModeDelegate implements AudioManagerInternal.RingerModeDelegate { 1149 @Override toString()1150 public String toString() { 1151 return TAG; 1152 } 1153 1154 @Override onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, String caller, int ringerModeExternal, VolumePolicy policy)1155 public int onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, String caller, 1156 int ringerModeExternal, VolumePolicy policy) { 1157 final boolean isChange = ringerModeOld != ringerModeNew; 1158 1159 int ringerModeExternalOut = ringerModeNew; 1160 1161 if (mZenMode == Global.ZEN_MODE_OFF 1162 || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS 1163 && !ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(mConfig))) { 1164 // in priority only with ringer not muted, save ringer mode changes 1165 // in dnd off, save ringer mode changes 1166 setPreviousRingerModeSetting(ringerModeNew); 1167 } 1168 int newZen = -1; 1169 switch (ringerModeNew) { 1170 case AudioManager.RINGER_MODE_SILENT: 1171 if (isChange && policy.doNotDisturbWhenSilent) { 1172 if (mZenMode == Global.ZEN_MODE_OFF) { 1173 newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; 1174 } 1175 setPreviousRingerModeSetting(ringerModeOld); 1176 } 1177 break; 1178 case AudioManager.RINGER_MODE_VIBRATE: 1179 case AudioManager.RINGER_MODE_NORMAL: 1180 if (isChange && ringerModeOld == AudioManager.RINGER_MODE_SILENT 1181 && (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS 1182 || mZenMode == Global.ZEN_MODE_ALARMS 1183 || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS 1184 && ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted( 1185 mConfig)))) { 1186 newZen = Global.ZEN_MODE_OFF; 1187 } else if (mZenMode != Global.ZEN_MODE_OFF) { 1188 ringerModeExternalOut = AudioManager.RINGER_MODE_SILENT; 1189 } 1190 break; 1191 } 1192 1193 if (newZen != -1) { 1194 setManualZenMode(newZen, null, "ringerModeInternal", null, 1195 false /*setRingerMode*/); 1196 } 1197 if (isChange || newZen != -1 || ringerModeExternal != ringerModeExternalOut) { 1198 ZenLog.traceSetRingerModeInternal(ringerModeOld, ringerModeNew, caller, 1199 ringerModeExternal, ringerModeExternalOut); 1200 } 1201 return ringerModeExternalOut; 1202 } 1203 1204 @Override onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller, int ringerModeInternal, VolumePolicy policy)1205 public int onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller, 1206 int ringerModeInternal, VolumePolicy policy) { 1207 int ringerModeInternalOut = ringerModeNew; 1208 final boolean isChange = ringerModeOld != ringerModeNew; 1209 final boolean isVibrate = ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE; 1210 1211 int newZen = -1; 1212 switch (ringerModeNew) { 1213 case AudioManager.RINGER_MODE_SILENT: 1214 if (isChange) { 1215 if (mZenMode == Global.ZEN_MODE_OFF) { 1216 newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; 1217 } 1218 ringerModeInternalOut = isVibrate ? AudioManager.RINGER_MODE_VIBRATE 1219 : AudioManager.RINGER_MODE_SILENT; 1220 } else { 1221 ringerModeInternalOut = ringerModeInternal; 1222 } 1223 break; 1224 case AudioManager.RINGER_MODE_VIBRATE: 1225 case AudioManager.RINGER_MODE_NORMAL: 1226 if (mZenMode != Global.ZEN_MODE_OFF) { 1227 newZen = Global.ZEN_MODE_OFF; 1228 } 1229 break; 1230 } 1231 if (newZen != -1) { 1232 setManualZenMode(newZen, null, "ringerModeExternal", caller, 1233 false /*setRingerMode*/); 1234 } 1235 1236 ZenLog.traceSetRingerModeExternal(ringerModeOld, ringerModeNew, caller, 1237 ringerModeInternal, ringerModeInternalOut); 1238 return ringerModeInternalOut; 1239 } 1240 1241 @Override canVolumeDownEnterSilent()1242 public boolean canVolumeDownEnterSilent() { 1243 return mZenMode == Global.ZEN_MODE_OFF; 1244 } 1245 1246 @Override getRingerModeAffectedStreams(int streams)1247 public int getRingerModeAffectedStreams(int streams) { 1248 // ringtone and notification streams are always affected by ringer mode 1249 // system stream is affected by ringer mode when not in priority-only 1250 streams |= (1 << AudioSystem.STREAM_RING) | 1251 (1 << AudioSystem.STREAM_NOTIFICATION) | 1252 (1 << AudioSystem.STREAM_SYSTEM); 1253 1254 if (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) { 1255 // alarm and music streams affected by ringer mode when in total silence 1256 streams |= (1 << AudioSystem.STREAM_ALARM) | 1257 (1 << AudioSystem.STREAM_MUSIC); 1258 } else { 1259 streams &= ~((1 << AudioSystem.STREAM_ALARM) | 1260 (1 << AudioSystem.STREAM_MUSIC)); 1261 } 1262 1263 if (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS 1264 && ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(mConfig)) { 1265 // system stream is not affected by ringer mode in priority only when the ringer 1266 // is zen muted (all other notification categories are muted) 1267 streams &= ~(1 << AudioSystem.STREAM_SYSTEM); 1268 } else { 1269 streams |= (1 << AudioSystem.STREAM_SYSTEM); 1270 } 1271 return streams; 1272 } 1273 } 1274 1275 private final class SettingsObserver extends ContentObserver { 1276 private final Uri ZEN_MODE = Global.getUriFor(Global.ZEN_MODE); 1277 SettingsObserver(Handler handler)1278 public SettingsObserver(Handler handler) { 1279 super(handler); 1280 } 1281 observe()1282 public void observe() { 1283 final ContentResolver resolver = mContext.getContentResolver(); 1284 resolver.registerContentObserver(ZEN_MODE, false /*notifyForDescendents*/, this); 1285 update(null); 1286 } 1287 1288 @Override onChange(boolean selfChange, Uri uri)1289 public void onChange(boolean selfChange, Uri uri) { 1290 update(uri); 1291 } 1292 update(Uri uri)1293 public void update(Uri uri) { 1294 if (ZEN_MODE.equals(uri)) { 1295 if (mZenMode != getZenModeSetting()) { 1296 if (DEBUG) Log.d(TAG, "Fixing zen mode setting"); 1297 setZenModeSetting(mZenMode); 1298 } 1299 } 1300 } 1301 } 1302 showZenUpgradeNotification(int zen)1303 private void showZenUpgradeNotification(int zen) { 1304 final boolean isWatch = mContext.getPackageManager().hasSystemFeature( 1305 PackageManager.FEATURE_WATCH); 1306 final boolean showNotification = mIsBootComplete 1307 && zen != Global.ZEN_MODE_OFF 1308 && !isWatch 1309 && Settings.Secure.getInt(mContext.getContentResolver(), 1310 Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0 1311 && Settings.Secure.getInt(mContext.getContentResolver(), 1312 Settings.Secure.ZEN_SETTINGS_UPDATED, 0) != 1; 1313 1314 if (isWatch) { 1315 Settings.Secure.putInt(mContext.getContentResolver(), 1316 Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0); 1317 } 1318 1319 if (showNotification) { 1320 mNotificationManager.notify(TAG, SystemMessage.NOTE_ZEN_UPGRADE, 1321 createZenUpgradeNotification()); 1322 Settings.Secure.putInt(mContext.getContentResolver(), 1323 Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0); 1324 } 1325 } 1326 1327 @VisibleForTesting createZenUpgradeNotification()1328 protected Notification createZenUpgradeNotification() { 1329 final Bundle extras = new Bundle(); 1330 extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, 1331 mContext.getResources().getString(R.string.global_action_settings)); 1332 int title = R.string.zen_upgrade_notification_title; 1333 int content = R.string.zen_upgrade_notification_content; 1334 int drawable = R.drawable.ic_zen_24dp; 1335 if (NotificationManager.Policy.areAllVisualEffectsSuppressed( 1336 getConsolidatedNotificationPolicy().suppressedVisualEffects)) { 1337 title = R.string.zen_upgrade_notification_visd_title; 1338 content = R.string.zen_upgrade_notification_visd_content; 1339 drawable = R.drawable.ic_dnd_block_notifications; 1340 } 1341 1342 Intent onboardingIntent = new Intent(Settings.ZEN_MODE_ONBOARDING); 1343 onboardingIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 1344 return new Notification.Builder(mContext, SystemNotificationChannels.DO_NOT_DISTURB) 1345 .setAutoCancel(true) 1346 .setSmallIcon(R.drawable.ic_settings_24dp) 1347 .setLargeIcon(Icon.createWithResource(mContext, drawable)) 1348 .setContentTitle(mContext.getResources().getString(title)) 1349 .setContentText(mContext.getResources().getString(content)) 1350 .setContentIntent(PendingIntent.getActivity(mContext, 0, onboardingIntent, 1351 PendingIntent.FLAG_UPDATE_CURRENT)) 1352 .setAutoCancel(true) 1353 .setLocalOnly(true) 1354 .addExtras(extras) 1355 .setStyle(new Notification.BigTextStyle()) 1356 .build(); 1357 } 1358 1359 private final class Metrics extends Callback { 1360 private static final String COUNTER_MODE_PREFIX = "dnd_mode_"; 1361 private static final String COUNTER_TYPE_PREFIX = "dnd_type_"; 1362 private static final int DND_OFF = 0; 1363 private static final int DND_ON_MANUAL = 1; 1364 private static final int DND_ON_AUTOMATIC = 2; 1365 private static final String COUNTER_RULE = "dnd_rule_count"; 1366 private static final long MINIMUM_LOG_PERIOD_MS = 60 * 1000; 1367 1368 // Total silence, alarms only, priority only 1369 private int mPreviousZenMode = -1; 1370 private long mModeLogTimeMs = 0L; 1371 1372 private int mNumZenRules = -1; 1373 private long mRuleCountLogTime = 0L; 1374 1375 // automatic (1) vs manual (0) vs dnd off (2) 1376 private int mPreviousZenType = -1; 1377 private long mTypeLogTimeMs = 0L; 1378 1379 @Override onZenModeChanged()1380 void onZenModeChanged() { 1381 emit(); 1382 } 1383 1384 @Override onConfigChanged()1385 void onConfigChanged() { 1386 emit(); 1387 } 1388 emit()1389 private void emit() { 1390 mHandler.postMetricsTimer(); 1391 emitZenMode(); 1392 emitRules(); 1393 emitDndType(); 1394 } 1395 emitZenMode()1396 private void emitZenMode() { 1397 final long now = SystemClock.elapsedRealtime(); 1398 final long since = (now - mModeLogTimeMs); 1399 if (mPreviousZenMode != mZenMode || since > MINIMUM_LOG_PERIOD_MS) { 1400 if (mPreviousZenMode != -1) { 1401 MetricsLogger.count( 1402 mContext, COUNTER_MODE_PREFIX + mPreviousZenMode, (int) since); 1403 } 1404 mPreviousZenMode = mZenMode; 1405 mModeLogTimeMs = now; 1406 } 1407 } 1408 emitRules()1409 private void emitRules() { 1410 final long now = SystemClock.elapsedRealtime(); 1411 final long since = (now - mRuleCountLogTime); 1412 synchronized (mConfig) { 1413 int numZenRules = mConfig.automaticRules.size(); 1414 if (mNumZenRules != numZenRules 1415 || since > MINIMUM_LOG_PERIOD_MS) { 1416 if (mNumZenRules != -1) { 1417 MetricsLogger.count(mContext, COUNTER_RULE, 1418 numZenRules - mNumZenRules); 1419 } 1420 mNumZenRules = numZenRules; 1421 1422 mRuleCountLogTime = since; 1423 } 1424 } 1425 } 1426 emitDndType()1427 private void emitDndType() { 1428 final long now = SystemClock.elapsedRealtime(); 1429 final long since = (now - mTypeLogTimeMs); 1430 synchronized (mConfig) { 1431 boolean dndOn = mZenMode != Global.ZEN_MODE_OFF; 1432 int zenType = !dndOn ? DND_OFF 1433 : (mConfig.manualRule != null) ? DND_ON_MANUAL : DND_ON_AUTOMATIC; 1434 if (zenType != mPreviousZenType 1435 || since > MINIMUM_LOG_PERIOD_MS) { 1436 if (mPreviousZenType != -1) { 1437 MetricsLogger.count( 1438 mContext, COUNTER_TYPE_PREFIX + mPreviousZenType, (int) since); 1439 } 1440 mTypeLogTimeMs = now; 1441 mPreviousZenType = zenType; 1442 } 1443 } 1444 } 1445 } 1446 1447 private final class H extends Handler { 1448 private static final int MSG_DISPATCH = 1; 1449 private static final int MSG_METRICS = 2; 1450 private static final int MSG_APPLY_CONFIG = 4; 1451 1452 private final class ConfigMessageData { 1453 public final ZenModeConfig config; 1454 public ComponentName triggeringComponent; 1455 public final String reason; 1456 public final boolean setRingerMode; 1457 ConfigMessageData(ZenModeConfig config, String reason, ComponentName triggeringComponent, boolean setRingerMode)1458 ConfigMessageData(ZenModeConfig config, String reason, 1459 ComponentName triggeringComponent, boolean setRingerMode) { 1460 this.config = config; 1461 this.reason = reason; 1462 this.setRingerMode = setRingerMode; 1463 this.triggeringComponent = triggeringComponent; 1464 } 1465 } 1466 1467 private static final long METRICS_PERIOD_MS = 6 * 60 * 60 * 1000; 1468 H(Looper looper)1469 private H(Looper looper) { 1470 super(looper); 1471 } 1472 postDispatchOnZenModeChanged()1473 private void postDispatchOnZenModeChanged() { 1474 removeMessages(MSG_DISPATCH); 1475 sendEmptyMessage(MSG_DISPATCH); 1476 } 1477 postMetricsTimer()1478 private void postMetricsTimer() { 1479 removeMessages(MSG_METRICS); 1480 sendEmptyMessageDelayed(MSG_METRICS, METRICS_PERIOD_MS); 1481 } 1482 postApplyConfig(ZenModeConfig config, String reason, ComponentName triggeringComponent, boolean setRingerMode)1483 private void postApplyConfig(ZenModeConfig config, String reason, 1484 ComponentName triggeringComponent, boolean setRingerMode) { 1485 sendMessage(obtainMessage(MSG_APPLY_CONFIG, 1486 new ConfigMessageData(config, reason, triggeringComponent, setRingerMode))); 1487 } 1488 1489 @Override handleMessage(Message msg)1490 public void handleMessage(Message msg) { 1491 switch (msg.what) { 1492 case MSG_DISPATCH: 1493 dispatchOnZenModeChanged(); 1494 break; 1495 case MSG_METRICS: 1496 mMetrics.emit(); 1497 break; 1498 case MSG_APPLY_CONFIG: 1499 ConfigMessageData applyConfigData = (ConfigMessageData) msg.obj; 1500 applyConfig(applyConfigData.config, applyConfigData.reason, 1501 applyConfigData.triggeringComponent, applyConfigData.setRingerMode); 1502 } 1503 } 1504 } 1505 1506 public static class Callback { onConfigChanged()1507 void onConfigChanged() {} onZenModeChanged()1508 void onZenModeChanged() {} onPolicyChanged()1509 void onPolicyChanged() {} onConsolidatedPolicyChanged()1510 void onConsolidatedPolicyChanged() {} 1511 } 1512 } 1513