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