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