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