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