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 dispatchOnConfigChanged(); 848 updateConsolidatedPolicy(reason); 849 } 850 if (policyChanged) { 851 dispatchOnPolicyChanged(); 852 } 853 mConfig = config; 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 == NotificationManager.INTERRUPTION_FILTER_NONE) { 946 policy.apply(new ZenPolicy.Builder() 947 .disallowAllSounds() 948 .build()); 949 } else if (rule.zenMode 950 == NotificationManager.INTERRUPTION_FILTER_ALARMS) { 951 policy.apply(new ZenPolicy.Builder() 952 .disallowAllSounds() 953 .allowAlarms(true) 954 .allowMedia(true) 955 .build()); 956 } else { 957 policy.apply(rule.zenPolicy); 958 } 959 } 960 updateConsolidatedPolicy(String reason)961 private void updateConsolidatedPolicy(String reason) { 962 if (mConfig == null) return; 963 synchronized (mConfig) { 964 ZenPolicy policy = new ZenPolicy(); 965 if (mConfig.manualRule != null) { 966 applyCustomPolicy(policy, mConfig.manualRule); 967 } 968 969 for (ZenRule automaticRule : mConfig.automaticRules.values()) { 970 if (automaticRule.isAutomaticActive()) { 971 applyCustomPolicy(policy, automaticRule); 972 } 973 } 974 Policy newPolicy = mConfig.toNotificationPolicy(policy); 975 if (!Objects.equals(mConsolidatedPolicy, newPolicy)) { 976 mConsolidatedPolicy = newPolicy; 977 dispatchOnConsolidatedPolicyChanged(); 978 ZenLog.traceSetConsolidatedZenPolicy(mConsolidatedPolicy, reason); 979 } 980 } 981 } 982 updateDefaultAutomaticRuleNames()983 private void updateDefaultAutomaticRuleNames() { 984 for (ZenRule rule : mDefaultConfig.automaticRules.values()) { 985 if (ZenModeConfig.EVENTS_DEFAULT_RULE_ID.equals(rule.id)) { 986 rule.name = mContext.getResources() 987 .getString(R.string.zen_mode_default_events_name); 988 } else if (ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID.equals(rule.id)) { 989 rule.name = mContext.getResources() 990 .getString(R.string.zen_mode_default_every_night_name); 991 } 992 } 993 } 994 995 @VisibleForTesting applyRestrictions()996 protected void applyRestrictions() { 997 final boolean zenPriorityOnly = mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; 998 final boolean zenSilence = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS; 999 final boolean zenAlarmsOnly = mZenMode == Global.ZEN_MODE_ALARMS; 1000 final boolean allowCalls = mConsolidatedPolicy.allowCalls(); 1001 final boolean allowRepeatCallers = mConsolidatedPolicy.allowRepeatCallers(); 1002 final boolean allowSystem = mConsolidatedPolicy.allowSystem(); 1003 final boolean allowMedia = mConsolidatedPolicy.allowMedia(); 1004 final boolean allowAlarms = mConsolidatedPolicy.allowAlarms(); 1005 1006 // notification restrictions 1007 final boolean muteNotifications = 1008 (mSuppressedEffects & SUPPRESSED_EFFECT_NOTIFICATIONS) != 0; 1009 // call restrictions 1010 final boolean muteCalls = zenAlarmsOnly 1011 || (zenPriorityOnly && !allowCalls && !allowRepeatCallers) 1012 || (mSuppressedEffects & SUPPRESSED_EFFECT_CALLS) != 0; 1013 // alarm restrictions 1014 final boolean muteAlarms = zenPriorityOnly && !allowAlarms; 1015 // media restrictions 1016 final boolean muteMedia = zenPriorityOnly && !allowMedia; 1017 // system restrictions 1018 final boolean muteSystem = zenAlarmsOnly || (zenPriorityOnly && !allowSystem); 1019 // total silence restrictions 1020 final boolean muteEverything = zenSilence || (zenPriorityOnly 1021 && ZenModeConfig.areAllZenBehaviorSoundsMuted(mConsolidatedPolicy)); 1022 1023 for (int usage : AudioAttributes.SDK_USAGES) { 1024 final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage); 1025 if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NEVER) { 1026 applyRestrictions(zenPriorityOnly, false /*mute*/, usage); 1027 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NOTIFICATION) { 1028 applyRestrictions(zenPriorityOnly, muteNotifications || muteEverything, usage); 1029 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_CALL) { 1030 applyRestrictions(zenPriorityOnly, muteCalls || muteEverything, usage); 1031 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_ALARM) { 1032 applyRestrictions(zenPriorityOnly, muteAlarms || muteEverything, usage); 1033 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_MEDIA) { 1034 applyRestrictions(zenPriorityOnly, muteMedia || muteEverything, usage); 1035 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_SYSTEM) { 1036 if (usage == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) { 1037 // normally DND will only restrict touch sounds, not haptic feedback/vibrations 1038 applyRestrictions(zenPriorityOnly, muteSystem || muteEverything, usage, 1039 AppOpsManager.OP_PLAY_AUDIO); 1040 applyRestrictions(zenPriorityOnly, false, usage, AppOpsManager.OP_VIBRATE); 1041 } else { 1042 applyRestrictions(zenPriorityOnly, muteSystem || muteEverything, usage); 1043 } 1044 } else { 1045 applyRestrictions(zenPriorityOnly, muteEverything, usage); 1046 } 1047 } 1048 } 1049 1050 1051 @VisibleForTesting applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage, int code)1052 protected void applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage, int code) { 1053 final long ident = Binder.clearCallingIdentity(); 1054 try { 1055 mAppOps.setRestriction(code, usage, 1056 mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED, 1057 zenPriorityOnly ? mPriorityOnlyDndExemptPackages : null); 1058 } finally { 1059 Binder.restoreCallingIdentity(ident); 1060 } 1061 } 1062 1063 @VisibleForTesting applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage)1064 protected void applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage) { 1065 applyRestrictions(zenPriorityOnly, mute, usage, AppOpsManager.OP_VIBRATE); 1066 applyRestrictions(zenPriorityOnly, mute, usage, AppOpsManager.OP_PLAY_AUDIO); 1067 } 1068 1069 1070 @VisibleForTesting applyZenToRingerMode()1071 protected void applyZenToRingerMode() { 1072 if (mAudioManager == null) return; 1073 // force the ringer mode into compliance 1074 final int ringerModeInternal = mAudioManager.getRingerModeInternal(); 1075 int newRingerModeInternal = ringerModeInternal; 1076 switch (mZenMode) { 1077 case Global.ZEN_MODE_NO_INTERRUPTIONS: 1078 case Global.ZEN_MODE_ALARMS: 1079 if (ringerModeInternal != AudioManager.RINGER_MODE_SILENT) { 1080 setPreviousRingerModeSetting(ringerModeInternal); 1081 newRingerModeInternal = AudioManager.RINGER_MODE_SILENT; 1082 } 1083 break; 1084 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: 1085 // do not apply zen to ringer, streams zen muted in AudioService 1086 break; 1087 case Global.ZEN_MODE_OFF: 1088 if (ringerModeInternal == AudioManager.RINGER_MODE_SILENT) { 1089 newRingerModeInternal = getPreviousRingerModeSetting(); 1090 setPreviousRingerModeSetting(null); 1091 } 1092 break; 1093 } 1094 if (newRingerModeInternal != -1) { 1095 mAudioManager.setRingerModeInternal(newRingerModeInternal, TAG); 1096 } 1097 } 1098 dispatchOnConfigChanged()1099 private void dispatchOnConfigChanged() { 1100 for (Callback callback : mCallbacks) { 1101 callback.onConfigChanged(); 1102 } 1103 } 1104 dispatchOnPolicyChanged()1105 private void dispatchOnPolicyChanged() { 1106 for (Callback callback : mCallbacks) { 1107 callback.onPolicyChanged(); 1108 } 1109 } 1110 dispatchOnConsolidatedPolicyChanged()1111 private void dispatchOnConsolidatedPolicyChanged() { 1112 for (Callback callback : mCallbacks) { 1113 callback.onConsolidatedPolicyChanged(); 1114 } 1115 } 1116 dispatchOnZenModeChanged()1117 private void dispatchOnZenModeChanged() { 1118 for (Callback callback : mCallbacks) { 1119 callback.onZenModeChanged(); 1120 } 1121 } 1122 readDefaultConfig(Resources resources)1123 private ZenModeConfig readDefaultConfig(Resources resources) { 1124 XmlResourceParser parser = null; 1125 try { 1126 parser = resources.getXml(R.xml.default_zen_mode_config); 1127 while (parser.next() != XmlPullParser.END_DOCUMENT) { 1128 final ZenModeConfig config = ZenModeConfig.readXml(parser); 1129 if (config != null) return config; 1130 } 1131 } catch (Exception e) { 1132 Log.w(TAG, "Error reading default zen mode config from resource", e); 1133 } finally { 1134 IoUtils.closeQuietly(parser); 1135 } 1136 return new ZenModeConfig(); 1137 } 1138 zenSeverity(int zen)1139 private static int zenSeverity(int zen) { 1140 switch (zen) { 1141 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: return 1; 1142 case Global.ZEN_MODE_ALARMS: return 2; 1143 case Global.ZEN_MODE_NO_INTERRUPTIONS: return 3; 1144 default: return 0; 1145 } 1146 } 1147 1148 @VisibleForTesting 1149 protected final class RingerModeDelegate implements AudioManagerInternal.RingerModeDelegate { 1150 @Override toString()1151 public String toString() { 1152 return TAG; 1153 } 1154 1155 @Override onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, String caller, int ringerModeExternal, VolumePolicy policy)1156 public int onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, String caller, 1157 int ringerModeExternal, VolumePolicy policy) { 1158 final boolean isChange = ringerModeOld != ringerModeNew; 1159 1160 int ringerModeExternalOut = ringerModeNew; 1161 1162 if (mZenMode == Global.ZEN_MODE_OFF 1163 || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS 1164 && !ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(mConfig))) { 1165 // in priority only with ringer not muted, save ringer mode changes 1166 // in dnd off, save ringer mode changes 1167 setPreviousRingerModeSetting(ringerModeNew); 1168 } 1169 int newZen = -1; 1170 switch (ringerModeNew) { 1171 case AudioManager.RINGER_MODE_SILENT: 1172 if (isChange && policy.doNotDisturbWhenSilent) { 1173 if (mZenMode == Global.ZEN_MODE_OFF) { 1174 newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; 1175 } 1176 setPreviousRingerModeSetting(ringerModeOld); 1177 } 1178 break; 1179 case AudioManager.RINGER_MODE_VIBRATE: 1180 case AudioManager.RINGER_MODE_NORMAL: 1181 if (isChange && ringerModeOld == AudioManager.RINGER_MODE_SILENT 1182 && (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS 1183 || mZenMode == Global.ZEN_MODE_ALARMS 1184 || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS 1185 && ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted( 1186 mConfig)))) { 1187 newZen = Global.ZEN_MODE_OFF; 1188 } else if (mZenMode != Global.ZEN_MODE_OFF) { 1189 ringerModeExternalOut = AudioManager.RINGER_MODE_SILENT; 1190 } 1191 break; 1192 } 1193 1194 if (newZen != -1) { 1195 setManualZenMode(newZen, null, "ringerModeInternal", null, 1196 false /*setRingerMode*/); 1197 } 1198 if (isChange || newZen != -1 || ringerModeExternal != ringerModeExternalOut) { 1199 ZenLog.traceSetRingerModeInternal(ringerModeOld, ringerModeNew, caller, 1200 ringerModeExternal, ringerModeExternalOut); 1201 } 1202 return ringerModeExternalOut; 1203 } 1204 1205 @Override onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller, int ringerModeInternal, VolumePolicy policy)1206 public int onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller, 1207 int ringerModeInternal, VolumePolicy policy) { 1208 int ringerModeInternalOut = ringerModeNew; 1209 final boolean isChange = ringerModeOld != ringerModeNew; 1210 final boolean isVibrate = ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE; 1211 1212 int newZen = -1; 1213 switch (ringerModeNew) { 1214 case AudioManager.RINGER_MODE_SILENT: 1215 if (isChange) { 1216 if (mZenMode == Global.ZEN_MODE_OFF) { 1217 newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; 1218 } 1219 ringerModeInternalOut = isVibrate ? AudioManager.RINGER_MODE_VIBRATE 1220 : AudioManager.RINGER_MODE_SILENT; 1221 } else { 1222 ringerModeInternalOut = ringerModeInternal; 1223 } 1224 break; 1225 case AudioManager.RINGER_MODE_VIBRATE: 1226 case AudioManager.RINGER_MODE_NORMAL: 1227 if (mZenMode != Global.ZEN_MODE_OFF) { 1228 newZen = Global.ZEN_MODE_OFF; 1229 } 1230 break; 1231 } 1232 if (newZen != -1) { 1233 setManualZenMode(newZen, null, "ringerModeExternal", caller, 1234 false /*setRingerMode*/); 1235 } 1236 1237 ZenLog.traceSetRingerModeExternal(ringerModeOld, ringerModeNew, caller, 1238 ringerModeInternal, ringerModeInternalOut); 1239 return ringerModeInternalOut; 1240 } 1241 1242 @Override canVolumeDownEnterSilent()1243 public boolean canVolumeDownEnterSilent() { 1244 return mZenMode == Global.ZEN_MODE_OFF; 1245 } 1246 1247 @Override getRingerModeAffectedStreams(int streams)1248 public int getRingerModeAffectedStreams(int streams) { 1249 // ringtone and notification streams are always affected by ringer mode 1250 // system stream is affected by ringer mode when not in priority-only 1251 streams |= (1 << AudioSystem.STREAM_RING) | 1252 (1 << AudioSystem.STREAM_NOTIFICATION) | 1253 (1 << AudioSystem.STREAM_SYSTEM); 1254 1255 if (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) { 1256 // alarm and music streams affected by ringer mode when in total silence 1257 streams |= (1 << AudioSystem.STREAM_ALARM) | 1258 (1 << AudioSystem.STREAM_MUSIC); 1259 } else { 1260 streams &= ~((1 << AudioSystem.STREAM_ALARM) | 1261 (1 << AudioSystem.STREAM_MUSIC)); 1262 } 1263 1264 if (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS 1265 && ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(mConfig)) { 1266 // system stream is not affected by ringer mode in priority only when the ringer 1267 // is zen muted (all other notification categories are muted) 1268 streams &= ~(1 << AudioSystem.STREAM_SYSTEM); 1269 } else { 1270 streams |= (1 << AudioSystem.STREAM_SYSTEM); 1271 } 1272 return streams; 1273 } 1274 } 1275 1276 private final class SettingsObserver extends ContentObserver { 1277 private final Uri ZEN_MODE = Global.getUriFor(Global.ZEN_MODE); 1278 SettingsObserver(Handler handler)1279 public SettingsObserver(Handler handler) { 1280 super(handler); 1281 } 1282 observe()1283 public void observe() { 1284 final ContentResolver resolver = mContext.getContentResolver(); 1285 resolver.registerContentObserver(ZEN_MODE, false /*notifyForDescendents*/, this); 1286 update(null); 1287 } 1288 1289 @Override onChange(boolean selfChange, Uri uri)1290 public void onChange(boolean selfChange, Uri uri) { 1291 update(uri); 1292 } 1293 update(Uri uri)1294 public void update(Uri uri) { 1295 if (ZEN_MODE.equals(uri)) { 1296 if (mZenMode != getZenModeSetting()) { 1297 if (DEBUG) Log.d(TAG, "Fixing zen mode setting"); 1298 setZenModeSetting(mZenMode); 1299 } 1300 } 1301 } 1302 } 1303 showZenUpgradeNotification(int zen)1304 private void showZenUpgradeNotification(int zen) { 1305 final boolean isWatch = mContext.getPackageManager().hasSystemFeature( 1306 PackageManager.FEATURE_WATCH); 1307 final boolean showNotification = mIsBootComplete 1308 && zen != Global.ZEN_MODE_OFF 1309 && !isWatch 1310 && Settings.Secure.getInt(mContext.getContentResolver(), 1311 Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0 1312 && Settings.Secure.getInt(mContext.getContentResolver(), 1313 Settings.Secure.ZEN_SETTINGS_UPDATED, 0) != 1; 1314 1315 if (isWatch) { 1316 Settings.Secure.putInt(mContext.getContentResolver(), 1317 Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0); 1318 } 1319 1320 if (showNotification) { 1321 mNotificationManager.notify(TAG, SystemMessage.NOTE_ZEN_UPGRADE, 1322 createZenUpgradeNotification()); 1323 Settings.Secure.putInt(mContext.getContentResolver(), 1324 Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0); 1325 } 1326 } 1327 1328 @VisibleForTesting createZenUpgradeNotification()1329 protected Notification createZenUpgradeNotification() { 1330 final Bundle extras = new Bundle(); 1331 extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, 1332 mContext.getResources().getString(R.string.global_action_settings)); 1333 int title = R.string.zen_upgrade_notification_title; 1334 int content = R.string.zen_upgrade_notification_content; 1335 int drawable = R.drawable.ic_zen_24dp; 1336 if (NotificationManager.Policy.areAllVisualEffectsSuppressed( 1337 getConsolidatedNotificationPolicy().suppressedVisualEffects)) { 1338 title = R.string.zen_upgrade_notification_visd_title; 1339 content = R.string.zen_upgrade_notification_visd_content; 1340 drawable = R.drawable.ic_dnd_block_notifications; 1341 } 1342 1343 Intent onboardingIntent = new Intent(Settings.ZEN_MODE_ONBOARDING); 1344 onboardingIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 1345 return new Notification.Builder(mContext, SystemNotificationChannels.DO_NOT_DISTURB) 1346 .setAutoCancel(true) 1347 .setSmallIcon(R.drawable.ic_settings_24dp) 1348 .setLargeIcon(Icon.createWithResource(mContext, drawable)) 1349 .setContentTitle(mContext.getResources().getString(title)) 1350 .setContentText(mContext.getResources().getString(content)) 1351 .setContentIntent(PendingIntent.getActivity(mContext, 0, onboardingIntent, 1352 PendingIntent.FLAG_UPDATE_CURRENT)) 1353 .setAutoCancel(true) 1354 .setLocalOnly(true) 1355 .addExtras(extras) 1356 .setStyle(new Notification.BigTextStyle()) 1357 .build(); 1358 } 1359 1360 private final class Metrics extends Callback { 1361 private static final String COUNTER_MODE_PREFIX = "dnd_mode_"; 1362 private static final String COUNTER_TYPE_PREFIX = "dnd_type_"; 1363 private static final int DND_OFF = 0; 1364 private static final int DND_ON_MANUAL = 1; 1365 private static final int DND_ON_AUTOMATIC = 2; 1366 private static final String COUNTER_RULE = "dnd_rule_count"; 1367 private static final long MINIMUM_LOG_PERIOD_MS = 60 * 1000; 1368 1369 // Total silence, alarms only, priority only 1370 private int mPreviousZenMode = -1; 1371 private long mModeLogTimeMs = 0L; 1372 1373 private int mNumZenRules = -1; 1374 private long mRuleCountLogTime = 0L; 1375 1376 // automatic (1) vs manual (0) vs dnd off (2) 1377 private int mPreviousZenType = -1; 1378 private long mTypeLogTimeMs = 0L; 1379 1380 @Override onZenModeChanged()1381 void onZenModeChanged() { 1382 emit(); 1383 } 1384 1385 @Override onConfigChanged()1386 void onConfigChanged() { 1387 emit(); 1388 } 1389 emit()1390 private void emit() { 1391 mHandler.postMetricsTimer(); 1392 emitZenMode(); 1393 emitRules(); 1394 emitDndType(); 1395 } 1396 emitZenMode()1397 private void emitZenMode() { 1398 final long now = SystemClock.elapsedRealtime(); 1399 final long since = (now - mModeLogTimeMs); 1400 if (mPreviousZenMode != mZenMode || since > MINIMUM_LOG_PERIOD_MS) { 1401 if (mPreviousZenMode != -1) { 1402 MetricsLogger.count( 1403 mContext, COUNTER_MODE_PREFIX + mPreviousZenMode, (int) since); 1404 } 1405 mPreviousZenMode = mZenMode; 1406 mModeLogTimeMs = now; 1407 } 1408 } 1409 emitRules()1410 private void emitRules() { 1411 final long now = SystemClock.elapsedRealtime(); 1412 final long since = (now - mRuleCountLogTime); 1413 synchronized (mConfig) { 1414 int numZenRules = mConfig.automaticRules.size(); 1415 if (mNumZenRules != numZenRules 1416 || since > MINIMUM_LOG_PERIOD_MS) { 1417 if (mNumZenRules != -1) { 1418 MetricsLogger.count(mContext, COUNTER_RULE, 1419 numZenRules - mNumZenRules); 1420 } 1421 mNumZenRules = numZenRules; 1422 1423 mRuleCountLogTime = since; 1424 } 1425 } 1426 } 1427 emitDndType()1428 private void emitDndType() { 1429 final long now = SystemClock.elapsedRealtime(); 1430 final long since = (now - mTypeLogTimeMs); 1431 synchronized (mConfig) { 1432 boolean dndOn = mZenMode != Global.ZEN_MODE_OFF; 1433 int zenType = !dndOn ? DND_OFF 1434 : (mConfig.manualRule != null) ? DND_ON_MANUAL : DND_ON_AUTOMATIC; 1435 if (zenType != mPreviousZenType 1436 || since > MINIMUM_LOG_PERIOD_MS) { 1437 if (mPreviousZenType != -1) { 1438 MetricsLogger.count( 1439 mContext, COUNTER_TYPE_PREFIX + mPreviousZenType, (int) since); 1440 } 1441 mTypeLogTimeMs = now; 1442 mPreviousZenType = zenType; 1443 } 1444 } 1445 } 1446 } 1447 1448 private final class H extends Handler { 1449 private static final int MSG_DISPATCH = 1; 1450 private static final int MSG_METRICS = 2; 1451 private static final int MSG_APPLY_CONFIG = 4; 1452 1453 private final class ConfigMessageData { 1454 public final ZenModeConfig config; 1455 public ComponentName triggeringComponent; 1456 public final String reason; 1457 public final boolean setRingerMode; 1458 ConfigMessageData(ZenModeConfig config, String reason, ComponentName triggeringComponent, boolean setRingerMode)1459 ConfigMessageData(ZenModeConfig config, String reason, 1460 ComponentName triggeringComponent, boolean setRingerMode) { 1461 this.config = config; 1462 this.reason = reason; 1463 this.setRingerMode = setRingerMode; 1464 this.triggeringComponent = triggeringComponent; 1465 } 1466 } 1467 1468 private static final long METRICS_PERIOD_MS = 6 * 60 * 60 * 1000; 1469 H(Looper looper)1470 private H(Looper looper) { 1471 super(looper); 1472 } 1473 postDispatchOnZenModeChanged()1474 private void postDispatchOnZenModeChanged() { 1475 removeMessages(MSG_DISPATCH); 1476 sendEmptyMessage(MSG_DISPATCH); 1477 } 1478 postMetricsTimer()1479 private void postMetricsTimer() { 1480 removeMessages(MSG_METRICS); 1481 sendEmptyMessageDelayed(MSG_METRICS, METRICS_PERIOD_MS); 1482 } 1483 postApplyConfig(ZenModeConfig config, String reason, ComponentName triggeringComponent, boolean setRingerMode)1484 private void postApplyConfig(ZenModeConfig config, String reason, 1485 ComponentName triggeringComponent, boolean setRingerMode) { 1486 sendMessage(obtainMessage(MSG_APPLY_CONFIG, 1487 new ConfigMessageData(config, reason, triggeringComponent, setRingerMode))); 1488 } 1489 1490 @Override handleMessage(Message msg)1491 public void handleMessage(Message msg) { 1492 switch (msg.what) { 1493 case MSG_DISPATCH: 1494 dispatchOnZenModeChanged(); 1495 break; 1496 case MSG_METRICS: 1497 mMetrics.emit(); 1498 break; 1499 case MSG_APPLY_CONFIG: 1500 ConfigMessageData applyConfigData = (ConfigMessageData) msg.obj; 1501 applyConfig(applyConfigData.config, applyConfigData.reason, 1502 applyConfigData.triggeringComponent, applyConfigData.setRingerMode); 1503 } 1504 } 1505 } 1506 1507 public static class Callback { onConfigChanged()1508 void onConfigChanged() {} onZenModeChanged()1509 void onZenModeChanged() {} onPolicyChanged()1510 void onPolicyChanged() {} onConsolidatedPolicyChanged()1511 void onConsolidatedPolicyChanged() {} 1512 } 1513 } 1514