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