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.AutomaticZenRule.TYPE_UNKNOWN; 20 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_ACTIVATED; 21 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_DEACTIVATED; 22 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_DISABLED; 23 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_ENABLED; 24 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_REMOVED; 25 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_UNKNOWN; 26 import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_ANY; 27 import static android.service.notification.Condition.SOURCE_UNKNOWN; 28 import static android.service.notification.Condition.SOURCE_USER_ACTION; 29 import static android.service.notification.Condition.STATE_FALSE; 30 import static android.service.notification.Condition.STATE_TRUE; 31 import static android.service.notification.NotificationServiceProto.ROOT_CONFIG; 32 import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_APP; 33 import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_INIT; 34 import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_INIT_USER; 35 import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_RESTORE_BACKUP; 36 import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI; 37 import static android.service.notification.ZenModeConfig.UPDATE_ORIGIN_USER; 38 39 import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE; 40 import static com.android.internal.util.Preconditions.checkArgument; 41 42 import static java.util.Objects.requireNonNull; 43 44 import android.annotation.DrawableRes; 45 import android.annotation.NonNull; 46 import android.annotation.Nullable; 47 import android.annotation.SuppressLint; 48 import android.annotation.UserIdInt; 49 import android.app.AppOpsManager; 50 import android.app.AutomaticZenRule; 51 import android.app.Flags; 52 import android.app.Notification; 53 import android.app.NotificationManager; 54 import android.app.NotificationManager.Policy; 55 import android.app.PendingIntent; 56 import android.app.compat.CompatChanges; 57 import android.compat.annotation.ChangeId; 58 import android.compat.annotation.EnabledSince; 59 import android.content.ComponentName; 60 import android.content.ContentResolver; 61 import android.content.Context; 62 import android.content.Intent; 63 import android.content.pm.ActivityInfo; 64 import android.content.pm.ApplicationInfo; 65 import android.content.pm.PackageItemInfo; 66 import android.content.pm.PackageManager; 67 import android.content.pm.ResolveInfo; 68 import android.content.pm.ServiceInfo; 69 import android.content.res.Resources; 70 import android.content.res.XmlResourceParser; 71 import android.database.ContentObserver; 72 import android.graphics.drawable.Icon; 73 import android.media.AudioAttributes; 74 import android.media.AudioManager; 75 import android.media.AudioManagerInternal; 76 import android.media.AudioSystem; 77 import android.media.VolumePolicy; 78 import android.net.Uri; 79 import android.os.Binder; 80 import android.os.Build; 81 import android.os.Bundle; 82 import android.os.Handler; 83 import android.os.Looper; 84 import android.os.Message; 85 import android.os.Process; 86 import android.os.SystemClock; 87 import android.os.UserHandle; 88 import android.provider.Settings; 89 import android.provider.Settings.Global; 90 import android.service.notification.Condition; 91 import android.service.notification.ConditionProviderService; 92 import android.service.notification.DeviceEffectsApplier; 93 import android.service.notification.SystemZenRules; 94 import android.service.notification.ZenAdapters; 95 import android.service.notification.ZenDeviceEffects; 96 import android.service.notification.ZenModeConfig; 97 import android.service.notification.ZenModeConfig.ConfigChangeOrigin; 98 import android.service.notification.ZenModeConfig.ZenRule; 99 import android.service.notification.ZenModeProto; 100 import android.service.notification.ZenPolicy; 101 import android.text.TextUtils; 102 import android.util.AndroidRuntimeException; 103 import android.util.ArrayMap; 104 import android.util.Log; 105 import android.util.Slog; 106 import android.util.SparseArray; 107 import android.util.StatsEvent; 108 import android.util.proto.ProtoOutputStream; 109 110 import com.android.internal.R; 111 import com.android.internal.annotations.GuardedBy; 112 import com.android.internal.annotations.VisibleForTesting; 113 import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags; 114 import com.android.internal.logging.MetricsLogger; 115 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; 116 import com.android.internal.notification.SystemNotificationChannels; 117 import com.android.internal.util.FrameworkStatsLog; 118 import com.android.internal.util.XmlUtils; 119 import com.android.modules.utils.TypedXmlPullParser; 120 import com.android.modules.utils.TypedXmlSerializer; 121 import com.android.server.LocalServices; 122 123 import libcore.io.IoUtils; 124 125 import org.xmlpull.v1.XmlPullParser; 126 import org.xmlpull.v1.XmlPullParserException; 127 128 import java.io.IOException; 129 import java.io.PrintWriter; 130 import java.time.Clock; 131 import java.time.Duration; 132 import java.time.Instant; 133 import java.util.ArrayList; 134 import java.util.Collections; 135 import java.util.HashMap; 136 import java.util.List; 137 import java.util.Map; 138 import java.util.Objects; 139 140 /** 141 * NotificationManagerService helper for functionality related to zen mode. 142 */ 143 public class ZenModeHelper { 144 static final String TAG = "ZenModeHelper"; 145 static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 146 147 private static final String PACKAGE_ANDROID = "android"; 148 149 // The amount of time rules instances can exist without their owning app being installed. 150 private static final int RULE_INSTANCE_GRACE_PERIOD = 1000 * 60 * 60 * 72; 151 static final int RULE_LIMIT_PER_PACKAGE = 100; 152 private static final Duration DELETED_RULE_KEPT_FOR = Duration.ofDays(30); 153 154 private static final String IMPLICIT_RULE_ID_PREFIX = "implicit_"; // + pkg_name 155 156 private static final int MAX_ICON_RESOURCE_NAME_LENGTH = 1000; 157 158 /** 159 * Send new activation AutomaticZenRule statuses to apps with a min target SDK version 160 */ 161 @ChangeId 162 @EnabledSince(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) 163 static final long SEND_ACTIVATION_AZR_STATUSES = 308673617L; 164 165 // pkg|userId => uid 166 @VisibleForTesting protected final ArrayMap<String, Integer> mRulesUidCache = new ArrayMap<>(); 167 168 private final Context mContext; 169 private final H mHandler; 170 private final Clock mClock; 171 private final SettingsObserver mSettingsObserver; 172 private final AppOpsManager mAppOps; 173 private final NotificationManager mNotificationManager; 174 private final ZenModeConfig mDefaultConfig; 175 private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>(); 176 private final ZenModeFiltering mFiltering; 177 private final RingerModeDelegate mRingerModeDelegate = new 178 RingerModeDelegate(); 179 @VisibleForTesting protected final ZenModeConditions mConditions; 180 private final Object mConfigsArrayLock = new Object(); 181 @GuardedBy("mConfigsArrayLock") 182 @VisibleForTesting final SparseArray<ZenModeConfig> mConfigs = new SparseArray<>(); 183 private final Metrics mMetrics = new Metrics(); 184 private final ConditionProviders.Config mServiceConfig; 185 private final SystemUiSystemPropertiesFlags.FlagResolver mFlagResolver; 186 private final ZenModeEventLogger mZenModeEventLogger; 187 188 @VisibleForTesting protected int mZenMode; 189 @VisibleForTesting protected NotificationManager.Policy mConsolidatedPolicy; 190 @GuardedBy("mConfigLock") 191 private ZenDeviceEffects mConsolidatedDeviceEffects = new ZenDeviceEffects.Builder().build(); 192 private int mUser = UserHandle.USER_SYSTEM; 193 194 private final Object mConfigLock = new Object(); 195 @GuardedBy("mConfigLock") 196 @VisibleForTesting protected ZenModeConfig mConfig; 197 @VisibleForTesting protected AudioManagerInternal mAudioManager; 198 protected PackageManager mPm; 199 @GuardedBy("mConfigLock") 200 private DeviceEffectsApplier mDeviceEffectsApplier; 201 private long mSuppressedEffects; 202 203 public static final long SUPPRESSED_EFFECT_NOTIFICATIONS = 1; 204 public static final long SUPPRESSED_EFFECT_CALLS = 1 << 1; 205 public static final long SUPPRESSED_EFFECT_ALL = SUPPRESSED_EFFECT_CALLS 206 | SUPPRESSED_EFFECT_NOTIFICATIONS; 207 208 @VisibleForTesting protected boolean mIsSystemServicesReady; 209 210 private String[] mPriorityOnlyDndExemptPackages; 211 ZenModeHelper(Context context, Looper looper, Clock clock, ConditionProviders conditionProviders, SystemUiSystemPropertiesFlags.FlagResolver flagResolver, ZenModeEventLogger zenModeEventLogger)212 public ZenModeHelper(Context context, Looper looper, Clock clock, 213 ConditionProviders conditionProviders, 214 SystemUiSystemPropertiesFlags.FlagResolver flagResolver, 215 ZenModeEventLogger zenModeEventLogger) { 216 mContext = context; 217 mHandler = new H(looper); 218 mClock = clock; 219 addCallback(mMetrics); 220 mAppOps = context.getSystemService(AppOpsManager.class); 221 mNotificationManager = context.getSystemService(NotificationManager.class); 222 223 mDefaultConfig = Flags.modesUi() 224 ? ZenModeConfig.getDefaultConfig() 225 : readDefaultConfig(mContext.getResources()); 226 updateDefaultConfigAutomaticRules(); 227 if (Flags.modesApi()) { 228 updateDefaultAutomaticRulePolicies(); 229 } 230 mConfig = mDefaultConfig.copy(); 231 synchronized (mConfigsArrayLock) { 232 mConfigs.put(UserHandle.USER_SYSTEM, mConfig); 233 } 234 mConsolidatedPolicy = mConfig.toNotificationPolicy(); 235 236 mSettingsObserver = new SettingsObserver(mHandler); 237 mSettingsObserver.observe(); 238 mFiltering = new ZenModeFiltering(mContext); 239 mConditions = new ZenModeConditions(this, conditionProviders); 240 mServiceConfig = conditionProviders.getConfig(); 241 mFlagResolver = flagResolver; 242 mZenModeEventLogger = zenModeEventLogger; 243 } 244 getLooper()245 public Looper getLooper() { 246 return mHandler.getLooper(); 247 } 248 249 @Override toString()250 public String toString() { 251 return TAG; 252 } 253 matchesCallFilter(UserHandle userHandle, Bundle extras, ValidateNotificationPeople validator, int contactsTimeoutMs, float timeoutAffinity, int callingUid)254 public boolean matchesCallFilter(UserHandle userHandle, Bundle extras, 255 ValidateNotificationPeople validator, int contactsTimeoutMs, float timeoutAffinity, 256 int callingUid) { 257 synchronized (mConfigLock) { 258 return ZenModeFiltering.matchesCallFilter(mContext, mZenMode, mConsolidatedPolicy, 259 userHandle, extras, validator, contactsTimeoutMs, timeoutAffinity, 260 callingUid); 261 } 262 } 263 isCall(NotificationRecord record)264 public boolean isCall(NotificationRecord record) { 265 return mFiltering.isCall(record); 266 } 267 recordCaller(NotificationRecord record)268 public void recordCaller(NotificationRecord record) { 269 mFiltering.recordCall(record); 270 } 271 cleanUpCallersAfter(long timeThreshold)272 protected void cleanUpCallersAfter(long timeThreshold) { 273 mFiltering.cleanUpCallersAfter(timeThreshold); 274 } 275 shouldIntercept(NotificationRecord record)276 public boolean shouldIntercept(NotificationRecord record) { 277 synchronized (mConfigLock) { 278 return mFiltering.shouldIntercept(mZenMode, mConsolidatedPolicy, record); 279 } 280 } 281 addCallback(Callback callback)282 public void addCallback(Callback callback) { 283 mCallbacks.add(callback); 284 } 285 removeCallback(Callback callback)286 public void removeCallback(Callback callback) { 287 mCallbacks.remove(callback); 288 } 289 initZenMode()290 public void initZenMode() { 291 if (DEBUG) Log.d(TAG, "initZenMode"); 292 synchronized (mConfigLock) { 293 // "update" config to itself, which will have no effect in the case where a config 294 // was read in via XML, but will initialize zen mode if nothing was read in and the 295 // config remains the default. 296 updateConfigAndZenModeLocked(mConfig, UPDATE_ORIGIN_INIT, "init", 297 true /*setRingerMode*/, Process.SYSTEM_UID /* callingUid */); 298 } 299 } 300 onSystemReady()301 public void onSystemReady() { 302 if (DEBUG) Log.d(TAG, "onSystemReady"); 303 mAudioManager = LocalServices.getService(AudioManagerInternal.class); 304 if (mAudioManager != null) { 305 mAudioManager.setRingerModeDelegate(mRingerModeDelegate); 306 } 307 mPm = mContext.getPackageManager(); 308 mHandler.postMetricsTimer(); 309 cleanUpZenRules(); 310 mIsSystemServicesReady = true; 311 showZenUpgradeNotification(mZenMode); 312 } 313 314 /** 315 * Set the {@link DeviceEffectsApplier} used to apply the consolidated effects. 316 * 317 * <p>Previously calculated effects (as loaded from the user's {@link ZenModeConfig}) will be 318 * applied immediately. 319 */ setDeviceEffectsApplier(@onNull DeviceEffectsApplier deviceEffectsApplier)320 void setDeviceEffectsApplier(@NonNull DeviceEffectsApplier deviceEffectsApplier) { 321 if (!Flags.modesApi()) { 322 return; 323 } 324 synchronized (mConfigLock) { 325 if (mDeviceEffectsApplier != null) { 326 throw new IllegalStateException("Already set up a DeviceEffectsApplier!"); 327 } 328 mDeviceEffectsApplier = deviceEffectsApplier; 329 } 330 applyConsolidatedDeviceEffects(UPDATE_ORIGIN_INIT); 331 } 332 onUserSwitched(int user)333 public void onUserSwitched(int user) { 334 loadConfigForUser(user, "onUserSwitched"); 335 } 336 onUserRemoved(int user)337 public void onUserRemoved(int user) { 338 if (user < UserHandle.USER_SYSTEM) return; 339 if (DEBUG) Log.d(TAG, "onUserRemoved u=" + user); 340 synchronized (mConfigsArrayLock) { 341 mConfigs.remove(user); 342 } 343 } 344 345 // TODO: b/310620812 - Remove when MODES_API is inlined (no more callers). onUserUnlocked(int user)346 public void onUserUnlocked(int user) { 347 loadConfigForUser(user, "onUserUnlocked"); 348 } 349 setPriorityOnlyDndExemptPackages(String[] packages)350 void setPriorityOnlyDndExemptPackages(String[] packages) { 351 mPriorityOnlyDndExemptPackages = packages; 352 } 353 loadConfigForUser(int user, String reason)354 private void loadConfigForUser(int user, String reason) { 355 if (mUser == user || user < UserHandle.USER_SYSTEM) return; 356 mUser = user; 357 if (DEBUG) Log.d(TAG, reason + " u=" + user); 358 ZenModeConfig config = null; 359 synchronized (mConfigsArrayLock) { 360 if (mConfigs.get(user) != null) { 361 config = mConfigs.get(user).copy(); 362 } 363 } 364 if (config == null) { 365 if (DEBUG) Log.d(TAG, reason + " generating default config for user " + user); 366 config = mDefaultConfig.copy(); 367 config.user = user; 368 } 369 synchronized (mConfigLock) { 370 setConfigLocked(config, null, UPDATE_ORIGIN_INIT_USER, reason, 371 Process.SYSTEM_UID); 372 } 373 cleanUpZenRules(); 374 } 375 getZenModeListenerInterruptionFilter()376 public int getZenModeListenerInterruptionFilter() { 377 return NotificationManager.zenModeToInterruptionFilter(mZenMode); 378 } 379 380 // TODO: b/310620812 - Remove when MODES_API is inlined (no more callers). requestFromListener(ComponentName name, int filter, int callingUid, boolean fromSystemOrSystemUi)381 public void requestFromListener(ComponentName name, int filter, int callingUid, 382 boolean fromSystemOrSystemUi) { 383 final int newZen = NotificationManager.zenModeFromInterruptionFilter(filter, -1); 384 if (newZen != -1) { 385 setManualZenMode(newZen, null, 386 fromSystemOrSystemUi ? UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI : UPDATE_ORIGIN_APP, 387 /* reason= */ "listener:" + (name != null ? name.flattenToShortString() : null), 388 /* caller= */ name != null ? name.getPackageName() : null, 389 callingUid); 390 } 391 } 392 setSuppressedEffects(long suppressedEffects)393 public void setSuppressedEffects(long suppressedEffects) { 394 if (mSuppressedEffects == suppressedEffects) return; 395 mSuppressedEffects = suppressedEffects; 396 applyRestrictions(); 397 } 398 getSuppressedEffects()399 public long getSuppressedEffects() { 400 return mSuppressedEffects; 401 } 402 getZenMode()403 public int getZenMode() { 404 return mZenMode; 405 } 406 407 // TODO: b/310620812 - Make private (or inline) when MODES_API is inlined. getZenRules()408 public List<ZenRule> getZenRules() { 409 List<ZenRule> rules = new ArrayList<>(); 410 synchronized (mConfigLock) { 411 if (mConfig == null) return rules; 412 for (ZenRule rule : mConfig.automaticRules.values()) { 413 if (canManageAutomaticZenRule(rule)) { 414 rules.add(rule); 415 } 416 } 417 } 418 return rules; 419 } 420 421 /** 422 * Get the list of {@link AutomaticZenRule} instances that the calling package can manage 423 * (which means the owned rules for a regular app, and every rule for system callers) together 424 * with their ids. 425 */ getAutomaticZenRules()426 Map<String, AutomaticZenRule> getAutomaticZenRules() { 427 List<ZenRule> ruleList = getZenRules(); 428 HashMap<String, AutomaticZenRule> rules = new HashMap<>(ruleList.size()); 429 for (ZenRule rule : ruleList) { 430 rules.put(rule.id, zenRuleToAutomaticZenRule(rule)); 431 } 432 return rules; 433 } 434 getAutomaticZenRule(String id)435 public AutomaticZenRule getAutomaticZenRule(String id) { 436 ZenRule rule; 437 synchronized (mConfigLock) { 438 if (mConfig == null) return null; 439 rule = mConfig.automaticRules.get(id); 440 } 441 if (rule == null) return null; 442 if (canManageAutomaticZenRule(rule)) { 443 return zenRuleToAutomaticZenRule(rule); 444 } 445 return null; 446 } 447 addAutomaticZenRule(String pkg, AutomaticZenRule automaticZenRule, @ConfigChangeOrigin int origin, String reason, int callingUid)448 public String addAutomaticZenRule(String pkg, AutomaticZenRule automaticZenRule, 449 @ConfigChangeOrigin int origin, String reason, int callingUid) { 450 requirePublicOrigin("addAutomaticZenRule", origin); 451 if (!ZenModeConfig.SYSTEM_AUTHORITY.equals(pkg)) { 452 PackageItemInfo component = getServiceInfo(automaticZenRule.getOwner()); 453 if (component == null) { 454 component = getActivityInfo(automaticZenRule.getConfigurationActivity()); 455 } 456 if (component == null) { 457 throw new IllegalArgumentException("Lacking enabled CPS or config activity"); 458 } 459 int ruleInstanceLimit = -1; 460 if (component.metaData != null) { 461 ruleInstanceLimit = component.metaData.getInt( 462 ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1); 463 } 464 int newRuleInstanceCount = getCurrentInstanceCount(automaticZenRule.getOwner()) 465 + getCurrentInstanceCount(automaticZenRule.getConfigurationActivity()) 466 + 1; 467 int newPackageRuleCount = getPackageRuleCount(pkg) + 1; 468 if (newPackageRuleCount > RULE_LIMIT_PER_PACKAGE 469 || (ruleInstanceLimit > 0 && ruleInstanceLimit < newRuleInstanceCount)) { 470 throw new IllegalArgumentException("Rule instance limit exceeded"); 471 } 472 } 473 474 ZenModeConfig newConfig; 475 synchronized (mConfigLock) { 476 if (mConfig == null) { 477 throw new AndroidRuntimeException("Could not create rule"); 478 } 479 if (DEBUG) { 480 Log.d(TAG, "addAutomaticZenRule rule= " + automaticZenRule + " reason=" + reason); 481 } 482 newConfig = mConfig.copy(); 483 ZenRule rule = new ZenRule(); 484 populateZenRule(pkg, automaticZenRule, rule, origin, /* isNew= */ true); 485 rule = maybeRestoreRemovedRule(newConfig, rule, automaticZenRule, origin); 486 newConfig.automaticRules.put(rule.id, rule); 487 maybeReplaceDefaultRule(newConfig, automaticZenRule); 488 489 if (setConfigLocked(newConfig, origin, reason, rule.component, true, callingUid)) { 490 return rule.id; 491 } else { 492 throw new AndroidRuntimeException("Could not create rule"); 493 } 494 } 495 } 496 497 @GuardedBy("mConfigLock") maybeRestoreRemovedRule(ZenModeConfig config, ZenRule ruleToAdd, AutomaticZenRule azrToAdd, @ConfigChangeOrigin int origin)498 private ZenRule maybeRestoreRemovedRule(ZenModeConfig config, ZenRule ruleToAdd, 499 AutomaticZenRule azrToAdd, @ConfigChangeOrigin int origin) { 500 if (!Flags.modesApi()) { 501 return ruleToAdd; 502 } 503 String deletedKey = ZenModeConfig.deletedRuleKey(ruleToAdd); 504 if (deletedKey == null) { 505 // Couldn't calculate the deletedRuleKey (condition or pkg null?). This should 506 // never happen for an app-provided rule because NMS validates both. 507 return ruleToAdd; 508 } 509 ZenRule ruleToRestore = config.deletedRules.get(deletedKey); 510 if (ruleToRestore == null) { 511 return ruleToAdd; // Cannot restore. 512 } 513 514 // We have found a previous rule to maybe restore. Whether we do that or not, we don't need 515 // to keep it around (if not restored now, it won't be in future calls either). 516 config.deletedRules.remove(deletedKey); 517 ruleToRestore.deletionInstant = null; 518 519 if (origin != UPDATE_ORIGIN_APP) { 520 return ruleToAdd; // Okay to create anew. 521 } 522 523 // "Preserve" the previous rule by considering the azrToAdd an update instead. 524 // Only app-modifiable fields will actually be modified. 525 populateZenRule(ruleToRestore.pkg, azrToAdd, ruleToRestore, origin, /* isNew= */ false); 526 return ruleToRestore; 527 } 528 maybeReplaceDefaultRule(ZenModeConfig config, AutomaticZenRule addedRule)529 private static void maybeReplaceDefaultRule(ZenModeConfig config, AutomaticZenRule addedRule) { 530 if (!Flags.modesApi()) { 531 return; 532 } 533 if (addedRule.getType() == AutomaticZenRule.TYPE_BEDTIME) { 534 // Delete a built-in disabled "Sleeping" rule when a BEDTIME rule is added; it may have 535 // smarter triggers and it will prevent confusion about which one to use. 536 // Note: we must not verify canManageAutomaticZenRule here, since most likely they 537 // won't have the same owner (sleeping - system; bedtime - DWB). 538 ZenRule sleepingRule = config.automaticRules.get( 539 ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID); 540 if (sleepingRule != null 541 && !sleepingRule.enabled 542 && sleepingRule.canBeUpdatedByApp() /* meaning it's not user-customized */) { 543 config.automaticRules.remove(ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID); 544 } 545 } 546 } 547 updateAutomaticZenRule(String ruleId, AutomaticZenRule automaticZenRule, @ConfigChangeOrigin int origin, String reason, int callingUid)548 public boolean updateAutomaticZenRule(String ruleId, AutomaticZenRule automaticZenRule, 549 @ConfigChangeOrigin int origin, String reason, int callingUid) { 550 requirePublicOrigin("updateAutomaticZenRule", origin); 551 if (ruleId == null) { 552 throw new IllegalArgumentException("ruleId cannot be null"); 553 } 554 synchronized (mConfigLock) { 555 if (mConfig == null) return false; 556 if (DEBUG) { 557 Log.d(TAG, "updateAutomaticZenRule zenRule=" + automaticZenRule 558 + " reason=" + reason); 559 } 560 ZenModeConfig.ZenRule oldRule = mConfig.automaticRules.get(ruleId); 561 if (oldRule == null || !canManageAutomaticZenRule(oldRule)) { 562 throw new SecurityException( 563 "Cannot update rules not owned by your condition provider"); 564 } 565 ZenModeConfig newConfig = mConfig.copy(); 566 ZenModeConfig.ZenRule newRule = requireNonNull(newConfig.automaticRules.get(ruleId)); 567 if (!Flags.modesApi()) { 568 if (newRule.enabled != automaticZenRule.isEnabled()) { 569 dispatchOnAutomaticRuleStatusChanged(mConfig.user, newRule.getPkg(), ruleId, 570 automaticZenRule.isEnabled() 571 ? AUTOMATIC_RULE_STATUS_ENABLED 572 : AUTOMATIC_RULE_STATUS_DISABLED); 573 } 574 } 575 576 boolean updated = populateZenRule(newRule.pkg, automaticZenRule, newRule, 577 origin, /* isNew= */ false); 578 if (Flags.modesApi() && !updated) { 579 // Bail out so we don't have the side effects of updating a rule (i.e. dropping 580 // condition) when no changes happen. 581 return true; 582 } 583 return setConfigLocked(newConfig, origin, reason, 584 newRule.component, true, callingUid); 585 } 586 } 587 588 /** 589 * Create (or activate, or deactivate) an "implicit" {@link ZenRule} when an app that has 590 * Notification Policy Access but is not allowed to manage the global zen state 591 * calls {@link NotificationManager#setInterruptionFilter}. 592 * 593 * <p>When the {@code zenMode} is {@link Global#ZEN_MODE_OFF}, an existing implicit rule will be 594 * deactivated (if there is no implicit rule, the call will be ignored). For other modes, the 595 * rule's interruption filter will match the supplied {@code zenMode}. The policy of the last 596 * call to {@link NotificationManager#setNotificationPolicy} will be used (or, if never called, 597 * the global policy). 598 * 599 * <p>The created rule is owned by the calling package, but it has neither a 600 * {@link ConditionProviderService} nor an associated 601 * {@link AutomaticZenRule#configurationActivity}. 602 * 603 * @param zenMode one of the {@code Global#ZEN_MODE_x} values 604 */ applyGlobalZenModeAsImplicitZenRule(String callingPkg, int callingUid, int zenMode)605 void applyGlobalZenModeAsImplicitZenRule(String callingPkg, int callingUid, int zenMode) { 606 if (!android.app.Flags.modesApi()) { 607 Log.wtf(TAG, "applyGlobalZenModeAsImplicitZenRule called with flag off!"); 608 return; 609 } 610 synchronized (mConfigLock) { 611 if (mConfig == null) { 612 return; 613 } 614 ZenModeConfig newConfig = mConfig.copy(); 615 ZenRule rule = newConfig.automaticRules.get(implicitRuleId(callingPkg)); 616 if (zenMode == Global.ZEN_MODE_OFF) { 617 // Deactivate implicit rule if it exists and is active; otherwise ignore. 618 if (rule != null) { 619 Condition deactivated = new Condition(rule.conditionId, 620 mContext.getString(R.string.zen_mode_implicit_deactivated), 621 STATE_FALSE); 622 setAutomaticZenRuleStateLocked(newConfig, Collections.singletonList(rule), 623 deactivated, UPDATE_ORIGIN_APP, callingUid); 624 } 625 } else { 626 // Either create a new rule with a default ZenPolicy, or update an existing rule's 627 // filter value. In both cases, also activate (and unsnooze) it. 628 if (rule == null) { 629 rule = newImplicitZenRule(callingPkg); 630 631 // For new implicit rules, create a policy matching the current global 632 // (manual rule) settings, for consistency with the policy that 633 // would apply if changing the global interruption filter. We only do this 634 // for newly created rules, as existing rules have a pre-existing policy 635 // (whether initialized here or set via app or user). 636 rule.zenPolicy = mConfig.getZenPolicy().copy(); 637 newConfig.automaticRules.put(rule.id, rule); 638 } 639 // If the user has changed the rule's *zenMode*, then don't let app overwrite it. 640 // We allow the update if the user has only changed other aspects of the rule. 641 if ((rule.userModifiedFields & AutomaticZenRule.FIELD_INTERRUPTION_FILTER) == 0) { 642 rule.zenMode = zenMode; 643 } 644 rule.snoozing = false; 645 rule.condition = new Condition(rule.conditionId, 646 mContext.getString(R.string.zen_mode_implicit_activated), 647 STATE_TRUE); 648 649 setConfigLocked(newConfig, /* triggeringComponent= */ null, UPDATE_ORIGIN_APP, 650 "applyGlobalZenModeAsImplicitZenRule", callingUid); 651 } 652 } 653 } 654 655 /** 656 * Create (or update) an "implicit" {@link ZenRule} when an app that has Notification Policy 657 * Access but is not allowed to manage the global zen state calls 658 * {@link NotificationManager#setNotificationPolicy}. 659 * 660 * <p>The created rule is owned by the calling package and has the {@link ZenPolicy} 661 * corresponding to the supplied {@code policy}, but it has neither a 662 * {@link ConditionProviderService} nor an associated 663 * {@link AutomaticZenRule#configurationActivity}. Its zen mode will be set to 664 * {@link Global#ZEN_MODE_IMPORTANT_INTERRUPTIONS}. 665 */ applyGlobalPolicyAsImplicitZenRule(String callingPkg, int callingUid, NotificationManager.Policy policy)666 void applyGlobalPolicyAsImplicitZenRule(String callingPkg, int callingUid, 667 NotificationManager.Policy policy) { 668 if (!android.app.Flags.modesApi()) { 669 Log.wtf(TAG, "applyGlobalPolicyAsImplicitZenRule called with flag off!"); 670 return; 671 } 672 synchronized (mConfigLock) { 673 if (mConfig == null) { 674 return; 675 } 676 ZenModeConfig newConfig = mConfig.copy(); 677 boolean isNew = false; 678 ZenRule rule = newConfig.automaticRules.get(implicitRuleId(callingPkg)); 679 if (rule == null) { 680 isNew = true; 681 rule = newImplicitZenRule(callingPkg); 682 rule.zenMode = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; 683 newConfig.automaticRules.put(rule.id, rule); 684 } 685 // If the user has changed the rule's *ZenPolicy*, then don't let app overwrite it. 686 // We allow the update if the user has only changed other aspects of the rule. 687 if (rule.zenPolicyUserModifiedFields == 0) { 688 ZenPolicy newZenPolicy = ZenAdapters.notificationPolicyToZenPolicy(policy); 689 if (isNew) { 690 // For new rules only, fill anything underspecified in the new policy with 691 // values from the global configuration, for consistency with the policy that 692 // would take effect if changing the global policy. 693 // Note that NotificationManager.Policy cannot have any unset priority 694 // categories, but *can* have unset visual effects, which is why we do this. 695 newZenPolicy = mConfig.getZenPolicy().overwrittenWith(newZenPolicy); 696 } 697 updatePolicy( 698 rule, 699 newZenPolicy, 700 /* updateBitmask= */ false, 701 isNew); 702 703 setConfigLocked(newConfig, /* triggeringComponent= */ null, UPDATE_ORIGIN_APP, 704 "applyGlobalPolicyAsImplicitZenRule", callingUid); 705 } 706 } 707 } 708 709 /** 710 * Returns the {@link Policy} associated to the "implicit" {@link ZenRule} of a package that has 711 * Notification Policy Access but is not allowed to manage the global zen state. 712 * 713 * <p>If the implicit rule doesn't exist, or it doesn't specify a {@link ZenPolicy} (because the 714 * app never called {@link NotificationManager#setNotificationPolicy}) then the default policy 715 * is returned (i.e. same as {@link #getNotificationPolicy}. 716 * 717 * <p>Any unset values in the {@link ZenPolicy} will be mapped to their current defaults. 718 */ 719 @Nullable getNotificationPolicyFromImplicitZenRule(String callingPkg)720 Policy getNotificationPolicyFromImplicitZenRule(String callingPkg) { 721 if (!android.app.Flags.modesApi()) { 722 Log.wtf(TAG, "getNotificationPolicyFromImplicitZenRule called with flag off!"); 723 return getNotificationPolicy(); 724 } 725 synchronized (mConfigLock) { 726 if (mConfig == null) { 727 return null; 728 } 729 ZenRule implicitRule = mConfig.automaticRules.get(implicitRuleId(callingPkg)); 730 if (implicitRule != null && implicitRule.zenPolicy != null) { 731 // toNotificationPolicy takes defaults from mConfig, and technically, those are not 732 // the defaults that would apply if any fields were unset. However, all rules should 733 // have all fields set in their ZenPolicy objects upon rule creation, so in 734 // practice, this is only filling in the areChannelsBypassingDnd field, which is a 735 // state rather than a part of the policy. 736 return mConfig.toNotificationPolicy(implicitRule.zenPolicy); 737 } else { 738 return getNotificationPolicy(); 739 } 740 } 741 } 742 743 /** 744 * Creates an empty {@link ZenRule} to be used as the implicit rule for {@code pkg}. 745 * Both {@link ZenRule#zenMode} and {@link ZenRule#zenPolicy} are unset. 746 */ newImplicitZenRule(String pkg)747 private ZenRule newImplicitZenRule(String pkg) { 748 ZenRule rule = new ZenRule(); 749 rule.id = implicitRuleId(pkg); 750 rule.pkg = pkg; 751 rule.creationTime = mClock.millis(); 752 753 Binder.withCleanCallingIdentity(() -> { 754 try { 755 ApplicationInfo applicationInfo = mPm.getApplicationInfo(pkg, 0); 756 rule.name = applicationInfo.loadLabel(mPm).toString(); 757 rule.iconResName = drawableResIdToResName(pkg, applicationInfo.icon); 758 } catch (PackageManager.NameNotFoundException e) { 759 // Should not happen, since it's the app calling us (?) 760 Log.w(TAG, "Package not found for creating implicit zen rule"); 761 rule.name = "Unknown"; 762 } 763 }); 764 765 rule.type = AutomaticZenRule.TYPE_OTHER; 766 rule.triggerDescription = mContext.getString(R.string.zen_mode_implicit_trigger_description, 767 rule.name); 768 rule.condition = null; 769 rule.conditionId = new Uri.Builder() 770 .scheme(Condition.SCHEME) 771 .authority(PACKAGE_ANDROID) 772 .appendPath("implicit") 773 .appendPath(pkg) 774 .build(); 775 rule.enabled = true; 776 rule.modified = false; 777 rule.component = null; 778 rule.configurationActivity = null; 779 return rule; 780 } 781 implicitRuleId(String forPackage)782 private static String implicitRuleId(String forPackage) { 783 return IMPLICIT_RULE_ID_PREFIX + forPackage; 784 } 785 isImplicitRuleId(@onNull String ruleId)786 static boolean isImplicitRuleId(@NonNull String ruleId) { 787 return ruleId.startsWith(IMPLICIT_RULE_ID_PREFIX); 788 } 789 removeAutomaticZenRule(String id, @ConfigChangeOrigin int origin, String reason, int callingUid)790 boolean removeAutomaticZenRule(String id, @ConfigChangeOrigin int origin, String reason, 791 int callingUid) { 792 requirePublicOrigin("removeAutomaticZenRule", origin); 793 ZenModeConfig newConfig; 794 synchronized (mConfigLock) { 795 if (mConfig == null) return false; 796 newConfig = mConfig.copy(); 797 ZenRule ruleToRemove = newConfig.automaticRules.get(id); 798 if (ruleToRemove == null) return false; 799 if (canManageAutomaticZenRule(ruleToRemove)) { 800 newConfig.automaticRules.remove(id); 801 maybePreserveRemovedRule(newConfig, ruleToRemove, origin); 802 if (ruleToRemove.getPkg() != null 803 && !PACKAGE_ANDROID.equals(ruleToRemove.getPkg())) { 804 for (ZenRule currRule : newConfig.automaticRules.values()) { 805 if (currRule.getPkg() != null 806 && currRule.getPkg().equals(ruleToRemove.getPkg())) { 807 break; // no need to remove from cache 808 } 809 } 810 mRulesUidCache.remove(getPackageUserKey(ruleToRemove.getPkg(), newConfig.user)); 811 } 812 if (DEBUG) Log.d(TAG, "removeZenRule zenRule=" + id + " reason=" + reason); 813 } else { 814 throw new SecurityException( 815 "Cannot delete rules not owned by your condition provider"); 816 } 817 dispatchOnAutomaticRuleStatusChanged( 818 mConfig.user, ruleToRemove.getPkg(), id, AUTOMATIC_RULE_STATUS_REMOVED); 819 return setConfigLocked(newConfig, origin, reason, null, true, callingUid); 820 } 821 } 822 removeAutomaticZenRules(String packageName, @ConfigChangeOrigin int origin, String reason, int callingUid)823 boolean removeAutomaticZenRules(String packageName, @ConfigChangeOrigin int origin, 824 String reason, int callingUid) { 825 requirePublicOrigin("removeAutomaticZenRules", origin); 826 ZenModeConfig newConfig; 827 synchronized (mConfigLock) { 828 if (mConfig == null) return false; 829 newConfig = mConfig.copy(); 830 for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) { 831 ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i)); 832 if (Objects.equals(rule.getPkg(), packageName) && canManageAutomaticZenRule(rule)) { 833 newConfig.automaticRules.removeAt(i); 834 maybePreserveRemovedRule(newConfig, rule, origin); 835 } 836 } 837 // If the system is clearing all rules this means DND access is revoked or the package 838 // was uninstalled, so also clear the preserved-deleted rules. 839 if (origin == UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI) { 840 for (int i = newConfig.deletedRules.size() - 1; i >= 0; i--) { 841 ZenRule rule = newConfig.deletedRules.get(newConfig.deletedRules.keyAt(i)); 842 if (Objects.equals(rule.getPkg(), packageName)) { 843 newConfig.deletedRules.removeAt(i); 844 } 845 } 846 } 847 return setConfigLocked(newConfig, origin, reason, null, true, callingUid); 848 } 849 } 850 maybePreserveRemovedRule(ZenModeConfig config, ZenRule ruleToRemove, @ConfigChangeOrigin int origin)851 private void maybePreserveRemovedRule(ZenModeConfig config, ZenRule ruleToRemove, 852 @ConfigChangeOrigin int origin) { 853 if (!Flags.modesApi()) { 854 return; 855 } 856 // If an app deletes a previously customized rule, keep it around to preserve 857 // the user's customization when/if it's recreated later. 858 // We don't try to preserve system-owned rules because their conditionIds (used as 859 // deletedRuleKey) are not stable. This is almost moot anyway because an app cannot 860 // delete a system-owned rule. 861 if (origin == UPDATE_ORIGIN_APP && !ruleToRemove.canBeUpdatedByApp() 862 && !PACKAGE_ANDROID.equals(ruleToRemove.pkg)) { 863 String deletedKey = ZenModeConfig.deletedRuleKey(ruleToRemove); 864 if (deletedKey != null) { 865 ZenRule deletedRule = ruleToRemove.copy(); 866 deletedRule.deletionInstant = Instant.now(mClock); 867 // If the rule is restored it shouldn't be active (or snoozed). 868 deletedRule.snoozing = false; 869 deletedRule.condition = null; 870 // Overwrites a previously-deleted rule with the same conditionId, but that's okay. 871 config.deletedRules.put(deletedKey, deletedRule); 872 } 873 } 874 } 875 876 @Condition.State getAutomaticZenRuleState(String id)877 int getAutomaticZenRuleState(String id) { 878 synchronized (mConfigLock) { 879 if (mConfig == null) { 880 return Condition.STATE_UNKNOWN; 881 } 882 ZenRule rule = mConfig.automaticRules.get(id); 883 if (rule == null || !canManageAutomaticZenRule(rule)) { 884 return Condition.STATE_UNKNOWN; 885 } 886 return rule.condition != null ? rule.condition.state : STATE_FALSE; 887 } 888 } 889 setAutomaticZenRuleState(String id, Condition condition, @ConfigChangeOrigin int origin, int callingUid)890 void setAutomaticZenRuleState(String id, Condition condition, @ConfigChangeOrigin int origin, 891 int callingUid) { 892 requirePublicOrigin("setAutomaticZenRuleState", origin); 893 ZenModeConfig newConfig; 894 synchronized (mConfigLock) { 895 if (mConfig == null) return; 896 897 newConfig = mConfig.copy(); 898 ZenRule rule = newConfig.automaticRules.get(id); 899 if (Flags.modesApi()) { 900 if (rule != null && canManageAutomaticZenRule(rule)) { 901 setAutomaticZenRuleStateLocked(newConfig, Collections.singletonList(rule), 902 condition, origin, callingUid); 903 } 904 } else { 905 ArrayList<ZenRule> rules = new ArrayList<>(); 906 rules.add(rule); // rule may be null and throw NPE in the next method. 907 setAutomaticZenRuleStateLocked(newConfig, rules, condition, origin, callingUid); 908 } 909 } 910 } 911 setAutomaticZenRuleState(Uri ruleDefinition, Condition condition, @ConfigChangeOrigin int origin, int callingUid)912 void setAutomaticZenRuleState(Uri ruleDefinition, Condition condition, 913 @ConfigChangeOrigin int origin, int callingUid) { 914 requirePublicOrigin("setAutomaticZenRuleState", origin); 915 ZenModeConfig newConfig; 916 synchronized (mConfigLock) { 917 if (mConfig == null) return; 918 newConfig = mConfig.copy(); 919 920 List<ZenRule> matchingRules = findMatchingRules(newConfig, ruleDefinition, condition); 921 if (Flags.modesApi()) { 922 for (int i = matchingRules.size() - 1; i >= 0; i--) { 923 if (!canManageAutomaticZenRule(matchingRules.get(i))) { 924 matchingRules.remove(i); 925 } 926 } 927 } 928 setAutomaticZenRuleStateLocked(newConfig, matchingRules, condition, origin, callingUid); 929 } 930 } 931 932 @GuardedBy("mConfigLock") setAutomaticZenRuleStateLocked(ZenModeConfig config, List<ZenRule> rules, Condition condition, @ConfigChangeOrigin int origin, int callingUid)933 private void setAutomaticZenRuleStateLocked(ZenModeConfig config, List<ZenRule> rules, 934 Condition condition, @ConfigChangeOrigin int origin, int callingUid) { 935 if (rules == null || rules.isEmpty()) return; 936 937 if (Flags.modesApi() && condition.source == SOURCE_USER_ACTION) { 938 origin = UPDATE_ORIGIN_USER; // Although coming from app, it's actually a user action. 939 } 940 941 for (ZenRule rule : rules) { 942 rule.condition = condition; 943 updateSnoozing(rule); 944 setConfigLocked(config, rule.component, origin, "conditionChanged", callingUid); 945 } 946 } 947 findMatchingRules(ZenModeConfig config, Uri id, Condition condition)948 private static List<ZenRule> findMatchingRules(ZenModeConfig config, Uri id, 949 Condition condition) { 950 List<ZenRule> matchingRules = new ArrayList<>(); 951 if (ruleMatches(id, condition, config.manualRule)) { 952 matchingRules.add(config.manualRule); 953 } else { 954 for (ZenRule automaticRule : config.automaticRules.values()) { 955 if (ruleMatches(id, condition, automaticRule)) { 956 matchingRules.add(automaticRule); 957 } 958 } 959 } 960 return matchingRules; 961 } 962 ruleMatches(Uri id, Condition condition, ZenRule rule)963 private static boolean ruleMatches(Uri id, Condition condition, ZenRule rule) { 964 if (id == null || rule == null || rule.conditionId == null) return false; 965 if (!rule.conditionId.equals(id)) return false; 966 if (Objects.equals(condition, rule.condition)) return false; 967 return true; 968 } 969 updateSnoozing(ZenRule rule)970 private boolean updateSnoozing(ZenRule rule) { 971 if (rule != null && rule.snoozing && !rule.isTrueOrUnknown()) { 972 rule.snoozing = false; 973 if (DEBUG) Log.d(TAG, "Snoozing reset for " + rule.conditionId); 974 return true; 975 } 976 return false; 977 } 978 getCurrentInstanceCount(ComponentName cn)979 public int getCurrentInstanceCount(ComponentName cn) { 980 if (cn == null) { 981 return 0; 982 } 983 int count = 0; 984 synchronized (mConfigLock) { 985 for (ZenRule rule : mConfig.automaticRules.values()) { 986 if (cn.equals(rule.component) || cn.equals(rule.configurationActivity)) { 987 count++; 988 } 989 } 990 } 991 return count; 992 } 993 994 // Equivalent method to getCurrentInstanceCount, but for all rules associated with a specific 995 // package rather than a condition provider service or activity. getPackageRuleCount(String pkg)996 private int getPackageRuleCount(String pkg) { 997 if (pkg == null) { 998 return 0; 999 } 1000 int count = 0; 1001 synchronized (mConfigLock) { 1002 for (ZenRule rule : mConfig.automaticRules.values()) { 1003 if (pkg.equals(rule.getPkg())) { 1004 count++; 1005 } 1006 } 1007 } 1008 return count; 1009 } 1010 canManageAutomaticZenRule(ZenRule rule)1011 public boolean canManageAutomaticZenRule(ZenRule rule) { 1012 final int callingUid = Binder.getCallingUid(); 1013 if (callingUid == 0 || callingUid == Process.SYSTEM_UID) { 1014 return true; 1015 } else if (mContext.checkCallingPermission(android.Manifest.permission.MANAGE_NOTIFICATIONS) 1016 == PackageManager.PERMISSION_GRANTED) { 1017 return true; 1018 } else { 1019 String[] packages = mPm.getPackagesForUid(Binder.getCallingUid()); 1020 if (packages != null) { 1021 final int packageCount = packages.length; 1022 for (int i = 0; i < packageCount; i++) { 1023 if (packages[i].equals(rule.getPkg())) { 1024 return true; 1025 } 1026 } 1027 } 1028 return false; 1029 } 1030 } 1031 updateZenRulesOnLocaleChange()1032 void updateZenRulesOnLocaleChange() { 1033 updateDefaultConfigAutomaticRules(); 1034 synchronized (mConfigLock) { 1035 if (mConfig == null) { 1036 return; 1037 } 1038 ZenModeConfig config = mConfig.copy(); 1039 boolean updated = false; 1040 for (ZenRule defaultRule : mDefaultConfig.automaticRules.values()) { 1041 ZenRule currRule = config.automaticRules.get(defaultRule.id); 1042 // if default rule wasn't user-modified use localized name 1043 // instead of previous system name 1044 if (currRule != null 1045 && !currRule.modified 1046 && (currRule.zenPolicyUserModifiedFields & AutomaticZenRule.FIELD_NAME) == 0 1047 && !defaultRule.name.equals(currRule.name)) { 1048 if (DEBUG) { 1049 Slog.d(TAG, "Locale change - updating default zen rule name " 1050 + "from " + currRule.name + " to " + defaultRule.name); 1051 } 1052 currRule.name = defaultRule.name; 1053 updated = true; 1054 } 1055 } 1056 if (Flags.modesApi() && Flags.modesUi()) { 1057 for (ZenRule rule : config.automaticRules.values()) { 1058 if (SystemZenRules.isSystemOwnedRule(rule)) { 1059 updated |= SystemZenRules.updateTriggerDescription(mContext, rule); 1060 } 1061 } 1062 } 1063 if (updated) { 1064 setConfigLocked(config, null, UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, 1065 "updateZenRulesOnLocaleChange", Process.SYSTEM_UID); 1066 } 1067 } 1068 } 1069 getServiceInfo(ComponentName owner)1070 private ServiceInfo getServiceInfo(ComponentName owner) { 1071 Intent queryIntent = new Intent(); 1072 queryIntent.setComponent(owner); 1073 List<ResolveInfo> installedServices = mPm.queryIntentServicesAsUser( 1074 queryIntent, 1075 PackageManager.GET_SERVICES | PackageManager.GET_META_DATA, 1076 UserHandle.getCallingUserId()); 1077 if (installedServices != null) { 1078 for (int i = 0, count = installedServices.size(); i < count; i++) { 1079 ResolveInfo resolveInfo = installedServices.get(i); 1080 ServiceInfo info = resolveInfo.serviceInfo; 1081 if (mServiceConfig.bindPermission.equals(info.permission)) { 1082 return info; 1083 } 1084 } 1085 } 1086 return null; 1087 } 1088 getActivityInfo(ComponentName configActivity)1089 private ActivityInfo getActivityInfo(ComponentName configActivity) { 1090 Intent queryIntent = new Intent(); 1091 queryIntent.setComponent(configActivity); 1092 List<ResolveInfo> installedComponents = mPm.queryIntentActivitiesAsUser( 1093 queryIntent, 1094 PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA, 1095 UserHandle.getCallingUserId()); 1096 if (installedComponents != null) { 1097 for (int i = 0, count = installedComponents.size(); i < count; i++) { 1098 ResolveInfo resolveInfo = installedComponents.get(i); 1099 return resolveInfo.activityInfo; 1100 } 1101 } 1102 return null; 1103 } 1104 1105 /** 1106 * Populates a {@code ZenRule} with the content of the {@link AutomaticZenRule}. Can be used for 1107 * both rule creation or update (distinguished by the {@code isNew} parameter. The change is 1108 * applied differently depending on the origin; for example app-provided changes might be 1109 * ignored (if the rule was previously customized by the user), while user-provided changes 1110 * update the user-modified bitmasks for any modifications. 1111 * 1112 * <p>Returns {@code true} if the rule was modified. Note that this is not equivalent to 1113 * {@link ZenRule#equals} or {@link AutomaticZenRule#equals}, for various reasons: 1114 * <ul> 1115 * <li>some metadata-related fields are not considered 1116 * <li>some fields (like {@code condition} are normally reset, and ignored for this result 1117 * <li>an app may provide changes that are not actually applied, as described above 1118 * </ul> 1119 * 1120 * <p>The rule's {@link ZenRule#condition} is cleared (meaning that an active rule will be 1121 * deactivated) unless the update has origin == {@link ZenModeConfig#UPDATE_ORIGIN_USER}. 1122 */ 1123 @GuardedBy("mConfigLock") populateZenRule(String pkg, AutomaticZenRule azr, ZenRule rule, @ConfigChangeOrigin int origin, boolean isNew)1124 private boolean populateZenRule(String pkg, AutomaticZenRule azr, ZenRule rule, 1125 @ConfigChangeOrigin int origin, boolean isNew) { 1126 if (Flags.modesApi()) { 1127 boolean modified = false; 1128 // These values can always be edited by the app, so we apply changes immediately. 1129 if (isNew) { 1130 rule.id = ZenModeConfig.newRuleId(); 1131 rule.creationTime = mClock.millis(); 1132 rule.component = azr.getOwner(); 1133 rule.pkg = pkg; 1134 modified = true; 1135 } 1136 1137 if (!Objects.equals(rule.conditionId, azr.getConditionId())) { 1138 rule.conditionId = azr.getConditionId(); 1139 modified = true; 1140 } 1141 boolean shouldPreserveCondition = Flags.modesApi() && Flags.modesUi() 1142 && !isNew && origin == UPDATE_ORIGIN_USER 1143 && rule.enabled == azr.isEnabled() 1144 && rule.conditionId != null && rule.condition != null 1145 && rule.conditionId.equals(rule.condition.id); 1146 if (!shouldPreserveCondition) { 1147 // Do not update 'modified'. If only this changes we treat it as a no-op updateAZR. 1148 rule.condition = null; 1149 } 1150 1151 if (rule.enabled != azr.isEnabled()) { 1152 rule.enabled = azr.isEnabled(); 1153 rule.snoozing = false; 1154 modified = true; 1155 } 1156 if (!Objects.equals(rule.configurationActivity, azr.getConfigurationActivity())) { 1157 rule.configurationActivity = azr.getConfigurationActivity(); 1158 modified = true; 1159 } 1160 if (rule.allowManualInvocation != azr.isManualInvocationAllowed()) { 1161 rule.allowManualInvocation = azr.isManualInvocationAllowed(); 1162 modified = true; 1163 } 1164 if (!Flags.modesUi()) { 1165 String iconResName = drawableResIdToResName(rule.pkg, azr.getIconResId()); 1166 if (!Objects.equals(rule.iconResName, iconResName)) { 1167 rule.iconResName = iconResName; 1168 modified = true; 1169 } 1170 } 1171 if (!Objects.equals(rule.triggerDescription, azr.getTriggerDescription())) { 1172 rule.triggerDescription = azr.getTriggerDescription(); 1173 modified = true; 1174 } 1175 if (rule.type != azr.getType()) { 1176 rule.type = azr.getType(); 1177 modified = true; 1178 } 1179 // TODO: b/310620812 - Remove this once FLAG_MODES_API is inlined. 1180 rule.modified = azr.isModified(); 1181 1182 // Name is treated differently than other values: 1183 // App is allowed to update name if the name was not modified by the user (even if 1184 // other values have been modified). In this way, if the locale of an app changes, 1185 // i18n of the rule name can still occur even if the user has customized the rule 1186 // contents. 1187 String previousName = rule.name; 1188 if (isNew || doesOriginAlwaysUpdateValues(origin) 1189 || (rule.userModifiedFields & AutomaticZenRule.FIELD_NAME) == 0) { 1190 rule.name = azr.getName(); 1191 modified |= !Objects.equals(rule.name, previousName); 1192 } 1193 1194 // For the remaining values, rules can always have all values updated if: 1195 // * the rule is newly added, or 1196 // * the request comes from an origin that can always update values, like the user, or 1197 // * the rule has not yet been user modified, and thus can be updated by the app. 1198 boolean updateValues = isNew || doesOriginAlwaysUpdateValues(origin) 1199 || rule.canBeUpdatedByApp(); 1200 1201 // For all other values, if updates are not allowed, we discard the update. 1202 if (!updateValues) { 1203 return modified; 1204 } 1205 1206 // Updates the bitmasks if the origin of the change is the user. 1207 boolean updateBitmask = (origin == UPDATE_ORIGIN_USER); 1208 1209 if (updateBitmask && !TextUtils.equals(previousName, azr.getName())) { 1210 rule.userModifiedFields |= AutomaticZenRule.FIELD_NAME; 1211 } 1212 int newZenMode = NotificationManager.zenModeFromInterruptionFilter( 1213 azr.getInterruptionFilter(), Global.ZEN_MODE_OFF); 1214 if (rule.zenMode != newZenMode) { 1215 rule.zenMode = newZenMode; 1216 if (updateBitmask) { 1217 rule.userModifiedFields |= AutomaticZenRule.FIELD_INTERRUPTION_FILTER; 1218 } 1219 modified = true; 1220 } 1221 1222 if (Flags.modesUi()) { 1223 String iconResName = drawableResIdToResName(rule.pkg, azr.getIconResId()); 1224 if (!Objects.equals(rule.iconResName, iconResName)) { 1225 rule.iconResName = iconResName; 1226 if (updateBitmask) { 1227 rule.userModifiedFields |= AutomaticZenRule.FIELD_ICON; 1228 } 1229 modified = true; 1230 } 1231 } 1232 1233 // Updates the bitmask and values for all policy fields, based on the origin. 1234 modified |= updatePolicy(rule, azr.getZenPolicy(), updateBitmask, isNew); 1235 1236 // Updates the bitmask and values for all device effect fields, based on the origin. 1237 modified |= updateZenDeviceEffects(rule, azr.getDeviceEffects(), 1238 origin == UPDATE_ORIGIN_APP, updateBitmask); 1239 1240 return modified; 1241 } else { 1242 if (rule.enabled != azr.isEnabled()) { 1243 rule.snoozing = false; 1244 } 1245 rule.name = azr.getName(); 1246 rule.condition = null; 1247 rule.conditionId = azr.getConditionId(); 1248 rule.enabled = azr.isEnabled(); 1249 rule.modified = azr.isModified(); 1250 rule.zenPolicy = azr.getZenPolicy(); 1251 rule.zenMode = NotificationManager.zenModeFromInterruptionFilter( 1252 azr.getInterruptionFilter(), Global.ZEN_MODE_OFF); 1253 rule.configurationActivity = azr.getConfigurationActivity(); 1254 1255 if (isNew) { 1256 rule.id = ZenModeConfig.newRuleId(); 1257 rule.creationTime = System.currentTimeMillis(); 1258 rule.component = azr.getOwner(); 1259 rule.pkg = pkg; 1260 } 1261 1262 // Only the MODES_API path cares about the result, so just return whatever here. 1263 return true; 1264 } 1265 } 1266 1267 /** 1268 * Returns true when fields can always be updated, based on the provided origin of an AZR 1269 * change. (Note that regardless of origin, fields can always be updated if they're not already 1270 * user modified.) 1271 */ doesOriginAlwaysUpdateValues(@onfigChangeOrigin int origin)1272 private static boolean doesOriginAlwaysUpdateValues(@ConfigChangeOrigin int origin) { 1273 return origin == UPDATE_ORIGIN_USER || origin == UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI; 1274 } 1275 1276 /** 1277 * Modifies the {@link ZenPolicy} associated to a new or updated ZenRule. 1278 * 1279 * <p>The update takes any set fields in {@code newPolicy} as new policy settings for the 1280 * provided {@code ZenRule}, keeping any pre-existing settings from {@code zenRule.zenPolicy} 1281 * for any unset policy fields in {@code newPolicy}. The user-modified bitmask is updated to 1282 * reflect the changes being applied (if applicable, i.e. if the update is from the user). 1283 * 1284 * <p>Returns {@code true} if the policy of the rule was modified. 1285 */ 1286 @GuardedBy("mConfigLock") updatePolicy(ZenRule zenRule, @Nullable ZenPolicy newPolicy, boolean updateBitmask, boolean isNew)1287 private boolean updatePolicy(ZenRule zenRule, @Nullable ZenPolicy newPolicy, 1288 boolean updateBitmask, boolean isNew) { 1289 if (newPolicy == null) { 1290 if (isNew) { 1291 // Newly created rule with no provided policy; fill in with the default. 1292 zenRule.zenPolicy = 1293 Flags.modesUi() ? mDefaultConfig.getZenPolicy() : mConfig.getZenPolicy(); 1294 return true; 1295 } 1296 // Otherwise, a null policy means no policy changes, so we can stop here. 1297 return false; 1298 } 1299 1300 // If oldPolicy is null, we compare against the default policy when determining which 1301 // fields in the bitmask should be marked as updated. 1302 ZenPolicy oldPolicy = zenRule.zenPolicy != null 1303 ? zenRule.zenPolicy 1304 : (Flags.modesUi() ? mDefaultConfig.getZenPolicy() : mConfig.getZenPolicy()); 1305 1306 // If this is updating a rule rather than creating a new one, keep any fields from the 1307 // old policy if they are unspecified in the new policy. For newly created rules, oldPolicy 1308 // has been set to the default settings above, so any unspecified fields in a newly created 1309 // policy are filled with default values. Then use the fully-specified version of the new 1310 // policy for comparison below. 1311 // 1312 // Although we do not expect a policy update from the user to contain any unset fields, 1313 // filling in fields here also guards against any unset fields counting as a "diff" when 1314 // comparing fields for bitmask editing below. 1315 newPolicy = oldPolicy.overwrittenWith(newPolicy); 1316 zenRule.zenPolicy = newPolicy; 1317 1318 if (updateBitmask) { 1319 int userModifiedFields = zenRule.zenPolicyUserModifiedFields; 1320 if (oldPolicy.getPriorityMessageSenders() != newPolicy.getPriorityMessageSenders()) { 1321 userModifiedFields |= ZenPolicy.FIELD_MESSAGES; 1322 } 1323 if (oldPolicy.getPriorityCallSenders() != newPolicy.getPriorityCallSenders()) { 1324 userModifiedFields |= ZenPolicy.FIELD_CALLS; 1325 } 1326 if (oldPolicy.getPriorityConversationSenders() 1327 != newPolicy.getPriorityConversationSenders()) { 1328 userModifiedFields |= ZenPolicy.FIELD_CONVERSATIONS; 1329 } 1330 if (oldPolicy.getPriorityChannelsAllowed() != newPolicy.getPriorityChannelsAllowed()) { 1331 userModifiedFields |= ZenPolicy.FIELD_ALLOW_CHANNELS; 1332 } 1333 if (oldPolicy.getPriorityCategoryReminders() 1334 != newPolicy.getPriorityCategoryReminders()) { 1335 userModifiedFields |= ZenPolicy.FIELD_PRIORITY_CATEGORY_REMINDERS; 1336 } 1337 if (oldPolicy.getPriorityCategoryEvents() != newPolicy.getPriorityCategoryEvents()) { 1338 userModifiedFields |= ZenPolicy.FIELD_PRIORITY_CATEGORY_EVENTS; 1339 } 1340 if (oldPolicy.getPriorityCategoryRepeatCallers() 1341 != newPolicy.getPriorityCategoryRepeatCallers()) { 1342 userModifiedFields |= ZenPolicy.FIELD_PRIORITY_CATEGORY_REPEAT_CALLERS; 1343 } 1344 if (oldPolicy.getPriorityCategoryAlarms() != newPolicy.getPriorityCategoryAlarms()) { 1345 userModifiedFields |= ZenPolicy.FIELD_PRIORITY_CATEGORY_ALARMS; 1346 } 1347 if (oldPolicy.getPriorityCategoryMedia() != newPolicy.getPriorityCategoryMedia()) { 1348 userModifiedFields |= ZenPolicy.FIELD_PRIORITY_CATEGORY_MEDIA; 1349 } 1350 if (oldPolicy.getPriorityCategorySystem() != newPolicy.getPriorityCategorySystem()) { 1351 userModifiedFields |= ZenPolicy.FIELD_PRIORITY_CATEGORY_SYSTEM; 1352 } 1353 // Visual effects 1354 if (oldPolicy.getVisualEffectFullScreenIntent() 1355 != newPolicy.getVisualEffectFullScreenIntent()) { 1356 userModifiedFields |= ZenPolicy.FIELD_VISUAL_EFFECT_FULL_SCREEN_INTENT; 1357 } 1358 if (oldPolicy.getVisualEffectLights() != newPolicy.getVisualEffectLights()) { 1359 userModifiedFields |= ZenPolicy.FIELD_VISUAL_EFFECT_LIGHTS; 1360 } 1361 if (oldPolicy.getVisualEffectPeek() != newPolicy.getVisualEffectPeek()) { 1362 userModifiedFields |= ZenPolicy.FIELD_VISUAL_EFFECT_PEEK; 1363 } 1364 if (oldPolicy.getVisualEffectStatusBar() != newPolicy.getVisualEffectStatusBar()) { 1365 userModifiedFields |= ZenPolicy.FIELD_VISUAL_EFFECT_STATUS_BAR; 1366 } 1367 if (oldPolicy.getVisualEffectBadge() != newPolicy.getVisualEffectBadge()) { 1368 userModifiedFields |= ZenPolicy.FIELD_VISUAL_EFFECT_BADGE; 1369 } 1370 if (oldPolicy.getVisualEffectAmbient() != newPolicy.getVisualEffectAmbient()) { 1371 userModifiedFields |= ZenPolicy.FIELD_VISUAL_EFFECT_AMBIENT; 1372 } 1373 if (oldPolicy.getVisualEffectNotificationList() 1374 != newPolicy.getVisualEffectNotificationList()) { 1375 userModifiedFields |= ZenPolicy.FIELD_VISUAL_EFFECT_NOTIFICATION_LIST; 1376 } 1377 zenRule.zenPolicyUserModifiedFields = userModifiedFields; 1378 } 1379 1380 return !newPolicy.equals(oldPolicy); 1381 } 1382 1383 /** 1384 * Modifies the {@link ZenDeviceEffects} associated to a new or updated ZenRule. 1385 * 1386 * <p>The new value is {@code newEffects}, while the user-modified bitmask is updated to reflect 1387 * the changes being applied (if applicable, i.e. if the update is from the user). 1388 * 1389 * <p>Apps cannot turn on hidden effects (those tagged as {@code @hide}), so those fields are 1390 * treated especially: for a new rule, they are blanked out; for an updated rule, previous 1391 * values are preserved. 1392 * 1393 * <p>Returns {@code true} if the device effects of the rule were modified. 1394 */ updateZenDeviceEffects(ZenRule zenRule, @Nullable ZenDeviceEffects newEffects, boolean isFromApp, boolean updateBitmask)1395 private static boolean updateZenDeviceEffects(ZenRule zenRule, 1396 @Nullable ZenDeviceEffects newEffects, boolean isFromApp, boolean updateBitmask) { 1397 // Same as with ZenPolicy, supplying null effects means keeping the previous ones. 1398 if (newEffects == null) { 1399 return false; 1400 } 1401 1402 ZenDeviceEffects oldEffects = zenRule.zenDeviceEffects != null 1403 ? zenRule.zenDeviceEffects 1404 : new ZenDeviceEffects.Builder().build(); 1405 1406 if (isFromApp) { 1407 // Don't allow apps to toggle hidden (non-public-API) effects. 1408 newEffects = new ZenDeviceEffects.Builder(newEffects) 1409 .setShouldDisableAutoBrightness(oldEffects.shouldDisableAutoBrightness()) 1410 .setShouldDisableTapToWake(oldEffects.shouldDisableTapToWake()) 1411 .setShouldDisableTiltToWake(oldEffects.shouldDisableTiltToWake()) 1412 .setShouldDisableTouch(oldEffects.shouldDisableTouch()) 1413 .setShouldMinimizeRadioUsage(oldEffects.shouldMinimizeRadioUsage()) 1414 .setShouldMaximizeDoze(oldEffects.shouldMaximizeDoze()) 1415 .setExtraEffects(oldEffects.getExtraEffects()) 1416 .build(); 1417 } 1418 1419 zenRule.zenDeviceEffects = newEffects; 1420 1421 if (updateBitmask) { 1422 int userModifiedFields = zenRule.zenDeviceEffectsUserModifiedFields; 1423 if (oldEffects.shouldDisplayGrayscale() != newEffects.shouldDisplayGrayscale()) { 1424 userModifiedFields |= ZenDeviceEffects.FIELD_GRAYSCALE; 1425 } 1426 if (oldEffects.shouldSuppressAmbientDisplay() 1427 != newEffects.shouldSuppressAmbientDisplay()) { 1428 userModifiedFields |= ZenDeviceEffects.FIELD_SUPPRESS_AMBIENT_DISPLAY; 1429 } 1430 if (oldEffects.shouldDimWallpaper() != newEffects.shouldDimWallpaper()) { 1431 userModifiedFields |= ZenDeviceEffects.FIELD_DIM_WALLPAPER; 1432 } 1433 if (oldEffects.shouldUseNightMode() != newEffects.shouldUseNightMode()) { 1434 userModifiedFields |= ZenDeviceEffects.FIELD_NIGHT_MODE; 1435 } 1436 if (oldEffects.shouldDisableAutoBrightness() 1437 != newEffects.shouldDisableAutoBrightness()) { 1438 userModifiedFields |= ZenDeviceEffects.FIELD_DISABLE_AUTO_BRIGHTNESS; 1439 } 1440 if (oldEffects.shouldDisableTapToWake() != newEffects.shouldDisableTapToWake()) { 1441 userModifiedFields |= ZenDeviceEffects.FIELD_DISABLE_TAP_TO_WAKE; 1442 } 1443 if (oldEffects.shouldDisableTiltToWake() != newEffects.shouldDisableTiltToWake()) { 1444 userModifiedFields |= ZenDeviceEffects.FIELD_DISABLE_TILT_TO_WAKE; 1445 } 1446 if (oldEffects.shouldDisableTouch() != newEffects.shouldDisableTouch()) { 1447 userModifiedFields |= ZenDeviceEffects.FIELD_DISABLE_TOUCH; 1448 } 1449 if (oldEffects.shouldMinimizeRadioUsage() != newEffects.shouldMinimizeRadioUsage()) { 1450 userModifiedFields |= ZenDeviceEffects.FIELD_MINIMIZE_RADIO_USAGE; 1451 } 1452 if (oldEffects.shouldMaximizeDoze() != newEffects.shouldMaximizeDoze()) { 1453 userModifiedFields |= ZenDeviceEffects.FIELD_MAXIMIZE_DOZE; 1454 } 1455 if (!Objects.equals(oldEffects.getExtraEffects(), newEffects.getExtraEffects())) { 1456 userModifiedFields |= ZenDeviceEffects.FIELD_EXTRA_EFFECTS; 1457 } 1458 zenRule.zenDeviceEffectsUserModifiedFields = userModifiedFields; 1459 } 1460 1461 return !newEffects.equals(oldEffects); 1462 } 1463 zenRuleToAutomaticZenRule(ZenRule rule)1464 private AutomaticZenRule zenRuleToAutomaticZenRule(ZenRule rule) { 1465 AutomaticZenRule azr; 1466 if (Flags.modesApi()) { 1467 azr = new AutomaticZenRule.Builder(rule.name, rule.conditionId) 1468 .setManualInvocationAllowed(rule.allowManualInvocation) 1469 .setPackage(rule.pkg) 1470 .setCreationTime(rule.creationTime) 1471 .setIconResId(drawableResNameToResId(rule.pkg, rule.iconResName)) 1472 .setType(rule.type) 1473 .setZenPolicy(rule.zenPolicy) 1474 .setDeviceEffects(rule.zenDeviceEffects) 1475 .setEnabled(rule.enabled) 1476 .setInterruptionFilter( 1477 NotificationManager.zenModeToInterruptionFilter(rule.zenMode)) 1478 .setOwner(rule.component) 1479 .setConfigurationActivity(rule.configurationActivity) 1480 .setTriggerDescription(rule.triggerDescription) 1481 .build(); 1482 } else { 1483 azr = new AutomaticZenRule(rule.name, rule.component, 1484 rule.configurationActivity, 1485 rule.conditionId, rule.zenPolicy, 1486 NotificationManager.zenModeToInterruptionFilter(rule.zenMode), 1487 rule.enabled, rule.creationTime); 1488 azr.setPackageName(rule.pkg); 1489 } 1490 return azr; 1491 } 1492 1493 @SuppressLint("MissingPermission") scheduleActivationBroadcast(String pkg, @UserIdInt int userId, String ruleId, boolean activated)1494 void scheduleActivationBroadcast(String pkg, @UserIdInt int userId, String ruleId, 1495 boolean activated) { 1496 if (CompatChanges.isChangeEnabled( 1497 SEND_ACTIVATION_AZR_STATUSES, pkg, UserHandle.of(userId))) { 1498 dispatchOnAutomaticRuleStatusChanged(userId, pkg, ruleId, activated 1499 ? AUTOMATIC_RULE_STATUS_ACTIVATED 1500 : AUTOMATIC_RULE_STATUS_DEACTIVATED); 1501 } else { 1502 dispatchOnAutomaticRuleStatusChanged( 1503 userId, pkg, ruleId, AUTOMATIC_RULE_STATUS_UNKNOWN); 1504 } 1505 } 1506 scheduleEnabledBroadcast(String pkg, @UserIdInt int userId, String ruleId, boolean enabled)1507 void scheduleEnabledBroadcast(String pkg, @UserIdInt int userId, String ruleId, 1508 boolean enabled) { 1509 dispatchOnAutomaticRuleStatusChanged(userId, pkg, ruleId, enabled 1510 ? AUTOMATIC_RULE_STATUS_ENABLED 1511 : AUTOMATIC_RULE_STATUS_DISABLED); 1512 } 1513 setManualZenMode(int zenMode, Uri conditionId, @ConfigChangeOrigin int origin, String reason, @Nullable String caller, int callingUid)1514 void setManualZenMode(int zenMode, Uri conditionId, @ConfigChangeOrigin int origin, 1515 String reason, @Nullable String caller, int callingUid) { 1516 setManualZenMode(zenMode, conditionId, origin, reason, caller, true /*setRingerMode*/, 1517 callingUid); 1518 Settings.Secure.putInt(mContext.getContentResolver(), 1519 Settings.Secure.SHOW_ZEN_SETTINGS_SUGGESTION, 0); 1520 } 1521 setManualZenMode(int zenMode, Uri conditionId, @ConfigChangeOrigin int origin, String reason, @Nullable String caller, boolean setRingerMode, int callingUid)1522 private void setManualZenMode(int zenMode, Uri conditionId, @ConfigChangeOrigin int origin, 1523 String reason, @Nullable String caller, boolean setRingerMode, int callingUid) { 1524 ZenModeConfig newConfig; 1525 synchronized (mConfigLock) { 1526 if (mConfig == null) return; 1527 if (!Global.isValidZenMode(zenMode)) return; 1528 if (DEBUG) Log.d(TAG, "setManualZenMode " + Global.zenModeToString(zenMode) 1529 + " conditionId=" + conditionId + " reason=" + reason 1530 + " setRingerMode=" + setRingerMode); 1531 newConfig = mConfig.copy(); 1532 if (Flags.modesUi()) { 1533 newConfig.manualRule.enabler = caller; 1534 newConfig.manualRule.conditionId = conditionId != null ? conditionId : Uri.EMPTY; 1535 newConfig.manualRule.pkg = PACKAGE_ANDROID; 1536 newConfig.manualRule.zenMode = zenMode; 1537 newConfig.manualRule.condition = new Condition(newConfig.manualRule.conditionId, "", 1538 zenMode == Global.ZEN_MODE_OFF ? STATE_FALSE : STATE_TRUE, 1539 origin == UPDATE_ORIGIN_USER ? SOURCE_USER_ACTION : SOURCE_UNKNOWN); 1540 if (zenMode == Global.ZEN_MODE_OFF && origin != UPDATE_ORIGIN_USER) { 1541 // User deactivation of DND means just turning off the manual DND rule. 1542 // For API calls (different origin) keep old behavior of snoozing all rules. 1543 for (ZenRule automaticRule : newConfig.automaticRules.values()) { 1544 if (automaticRule.isAutomaticActive()) { 1545 automaticRule.snoozing = true; 1546 } 1547 } 1548 } 1549 } else { 1550 if (zenMode == Global.ZEN_MODE_OFF) { 1551 newConfig.manualRule = null; 1552 // User deactivation of DND means just turning off the manual DND rule. 1553 // For API calls (different origin) keep old behavior of snoozing all rules. 1554 for (ZenRule automaticRule : newConfig.automaticRules.values()) { 1555 if (automaticRule.isAutomaticActive()) { 1556 automaticRule.snoozing = true; 1557 } 1558 } 1559 1560 } else { 1561 final ZenRule newRule = new ZenRule(); 1562 newRule.enabled = true; 1563 newRule.zenMode = zenMode; 1564 newRule.conditionId = conditionId; 1565 newRule.enabler = caller; 1566 if (Flags.modesApi()) { 1567 newRule.allowManualInvocation = true; 1568 } 1569 newConfig.manualRule = newRule; 1570 } 1571 } 1572 setConfigLocked(newConfig, origin, reason, null, setRingerMode, callingUid); 1573 } 1574 } 1575 setManualZenRuleDeviceEffects(ZenDeviceEffects deviceEffects, @ConfigChangeOrigin int origin, String reason, int callingUid)1576 public void setManualZenRuleDeviceEffects(ZenDeviceEffects deviceEffects, 1577 @ConfigChangeOrigin int origin, String reason, int callingUid) { 1578 if (!Flags.modesUi()) { 1579 return; 1580 } 1581 ZenModeConfig newConfig; 1582 synchronized (mConfigLock) { 1583 if (mConfig == null) return; 1584 if (DEBUG) Log.d(TAG, "updateManualRule " + deviceEffects 1585 + " reason=" + reason 1586 + " callingUid=" + callingUid); 1587 newConfig = mConfig.copy(); 1588 1589 newConfig.manualRule.pkg = PACKAGE_ANDROID; 1590 newConfig.manualRule.zenDeviceEffects = deviceEffects; 1591 setConfigLocked(newConfig, origin, reason, null, true, callingUid); 1592 } 1593 } 1594 dump(ProtoOutputStream proto)1595 void dump(ProtoOutputStream proto) { 1596 proto.write(ZenModeProto.ZEN_MODE, mZenMode); 1597 synchronized (mConfigLock) { 1598 if (mConfig.manualRule != null) { 1599 mConfig.manualRule.dumpDebug(proto, ZenModeProto.ENABLED_ACTIVE_CONDITIONS); 1600 } 1601 for (ZenRule rule : mConfig.automaticRules.values()) { 1602 if (rule.enabled && rule.condition != null 1603 && rule.condition.state == STATE_TRUE 1604 && !rule.snoozing) { 1605 rule.dumpDebug(proto, ZenModeProto.ENABLED_ACTIVE_CONDITIONS); 1606 } 1607 } 1608 mConfig.toNotificationPolicy().dumpDebug(proto, ZenModeProto.POLICY); 1609 proto.write(ZenModeProto.SUPPRESSED_EFFECTS, mSuppressedEffects); 1610 } 1611 } 1612 dump(PrintWriter pw, String prefix)1613 public void dump(PrintWriter pw, String prefix) { 1614 pw.print(prefix); 1615 pw.print("mZenMode="); 1616 pw.println(Global.zenModeToString(mZenMode)); 1617 pw.print(prefix); 1618 pw.println("mConsolidatedPolicy=" + mConsolidatedPolicy.toString()); 1619 synchronized (mConfigsArrayLock) { 1620 final int N = mConfigs.size(); 1621 for (int i = 0; i < N; i++) { 1622 dump(pw, prefix, "mConfigs[u=" + mConfigs.keyAt(i) + "]", mConfigs.valueAt(i)); 1623 } 1624 } 1625 pw.print(prefix); pw.print("mUser="); pw.println(mUser); 1626 synchronized (mConfigLock) { 1627 dump(pw, prefix, "mConfig", mConfig); 1628 } 1629 1630 pw.print(prefix); pw.print("mSuppressedEffects="); pw.println(mSuppressedEffects); 1631 mFiltering.dump(pw, prefix); 1632 mConditions.dump(pw, prefix); 1633 } 1634 dump(PrintWriter pw, String prefix, String var, ZenModeConfig config)1635 private static void dump(PrintWriter pw, String prefix, String var, ZenModeConfig config) { 1636 pw.print(prefix); pw.print(var); pw.print('='); 1637 pw.println(config); 1638 } 1639 readXml(TypedXmlPullParser parser, boolean forRestore, int userId)1640 public void readXml(TypedXmlPullParser parser, boolean forRestore, int userId) 1641 throws XmlPullParserException, IOException { 1642 ZenModeConfig config = ZenModeConfig.readXml(parser); 1643 String reason = "readXml"; 1644 1645 if (config != null) { 1646 if (forRestore) { 1647 config.user = userId; 1648 if (!Flags.modesUi()) { 1649 config.manualRule = null; // don't restore the manual rule 1650 } 1651 } 1652 1653 // booleans to determine whether to reset the rules to the default rules 1654 boolean allRulesDisabled = true; 1655 boolean hasDefaultRules = config.automaticRules.containsAll( 1656 ZenModeConfig.DEFAULT_RULE_IDS); 1657 1658 long time = Flags.modesApi() ? mClock.millis() : System.currentTimeMillis(); 1659 if (config.automaticRules != null && config.automaticRules.size() > 0) { 1660 for (ZenRule automaticRule : config.automaticRules.values()) { 1661 if (forRestore) { 1662 // don't restore transient state from restored automatic rules 1663 automaticRule.snoozing = false; 1664 automaticRule.condition = null; 1665 automaticRule.creationTime = time; 1666 } 1667 1668 allRulesDisabled &= !automaticRule.enabled; 1669 1670 // Upon upgrading to a version with modes_api enabled, keep all behaviors of 1671 // rules with null ZenPolicies explicitly as a copy of the global policy. 1672 if (Flags.modesApi() && config.version < ZenModeConfig.XML_VERSION_MODES_API) { 1673 // Keep the manual ("global") policy that from config. 1674 ZenPolicy manualRulePolicy = config.getZenPolicy(); 1675 if (automaticRule.zenPolicy == null) { 1676 automaticRule.zenPolicy = manualRulePolicy; 1677 } else { 1678 // newPolicy is a policy with all unset fields in the rule's zenPolicy 1679 // set to their values from the values in config. Then convert that back 1680 // to ZenPolicy to store with the automatic zen rule. 1681 automaticRule.zenPolicy = 1682 manualRulePolicy.overwrittenWith(automaticRule.zenPolicy); 1683 } 1684 } 1685 } 1686 } 1687 1688 if (!hasDefaultRules && allRulesDisabled 1689 && (forRestore || config.version < ZenModeConfig.XML_VERSION_ZEN_UPGRADE)) { 1690 // reset zen automatic rules to default on restore or upgrade if: 1691 // - doesn't already have default rules and 1692 // - all previous automatic rules were disabled 1693 // 1694 // Note: we don't need to check to avoid restoring the Sleeping rule if there is a 1695 // TYPE_BEDTIME rule because the config is from an old version and thus by 1696 // definition cannot have a rule with TYPE_BEDTIME (or any other type). 1697 config.automaticRules = new ArrayMap<>(); 1698 for (ZenRule rule : mDefaultConfig.automaticRules.values()) { 1699 config.automaticRules.put(rule.id, rule); 1700 } 1701 reason += ", reset to default rules"; 1702 } 1703 1704 if (Flags.modesApi() && Flags.modesUi()) { 1705 SystemZenRules.maybeUpgradeRules(mContext, config); 1706 } 1707 1708 // Resolve user id for settings. 1709 userId = userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId; 1710 if (config.version < ZenModeConfig.XML_VERSION_ZEN_UPGRADE) { 1711 Settings.Secure.putIntForUser(mContext.getContentResolver(), 1712 Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 1, userId); 1713 } else { 1714 // devices not restoring/upgrading already have updated zen settings 1715 Settings.Secure.putIntForUser(mContext.getContentResolver(), 1716 Settings.Secure.ZEN_SETTINGS_UPDATED, 1, userId); 1717 } 1718 1719 if (Flags.modesApi() && forRestore) { 1720 // Note: forBackup doesn't write deletedRules, but just in case. 1721 config.deletedRules.clear(); 1722 } 1723 1724 if (DEBUG) Log.d(TAG, reason); 1725 synchronized (mConfigLock) { 1726 setConfigLocked(config, null, 1727 forRestore ? UPDATE_ORIGIN_RESTORE_BACKUP : UPDATE_ORIGIN_INIT, reason, 1728 Process.SYSTEM_UID); 1729 } 1730 } 1731 } 1732 writeXml(TypedXmlSerializer out, boolean forBackup, Integer version, int userId)1733 public void writeXml(TypedXmlSerializer out, boolean forBackup, Integer version, int userId) 1734 throws IOException { 1735 synchronized (mConfigsArrayLock) { 1736 final int n = mConfigs.size(); 1737 for (int i = 0; i < n; i++) { 1738 if (forBackup && mConfigs.keyAt(i) != userId) { 1739 continue; 1740 } 1741 mConfigs.valueAt(i).writeXml(out, version, forBackup); 1742 } 1743 } 1744 } 1745 1746 /** 1747 * @return user-specified default notification policy for priority only do not disturb 1748 */ getNotificationPolicy()1749 public Policy getNotificationPolicy() { 1750 synchronized (mConfigLock) { 1751 return getNotificationPolicy(mConfig); 1752 } 1753 } 1754 getNotificationPolicy(ZenModeConfig config)1755 private static Policy getNotificationPolicy(ZenModeConfig config) { 1756 return config == null ? null : config.toNotificationPolicy(); 1757 } 1758 1759 /** 1760 * Sets the global notification policy used for priority only do not disturb 1761 */ setNotificationPolicy(Policy policy, @ConfigChangeOrigin int origin, int callingUid)1762 public void setNotificationPolicy(Policy policy, @ConfigChangeOrigin int origin, 1763 int callingUid) { 1764 synchronized (mConfigLock) { 1765 if (policy == null || mConfig == null) return; 1766 final ZenModeConfig newConfig = mConfig.copy(); 1767 if (Flags.modesApi() && !Flags.modesUi()) { 1768 // Fix for b/337193321 -- propagate changes to notificationPolicy to rules where 1769 // the user cannot edit zen policy to emulate the previous "inheritance". 1770 ZenPolicy previousPolicy = ZenAdapters.notificationPolicyToZenPolicy( 1771 newConfig.toNotificationPolicy()); 1772 ZenPolicy newPolicy = ZenAdapters.notificationPolicyToZenPolicy(policy); 1773 1774 newConfig.applyNotificationPolicy(policy); 1775 1776 if (!previousPolicy.equals(newPolicy)) { 1777 for (ZenRule rule : newConfig.automaticRules.values()) { 1778 if (!SystemZenRules.isSystemOwnedRule(rule) 1779 && rule.zenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS 1780 && (rule.zenPolicy == null || rule.zenPolicy.equals(previousPolicy) 1781 || rule.zenPolicy.equals(getDefaultZenPolicy()))) { 1782 rule.zenPolicy = newPolicy; 1783 } 1784 } 1785 } 1786 } else { 1787 newConfig.applyNotificationPolicy(policy); 1788 } 1789 setConfigLocked(newConfig, null, origin, "setNotificationPolicy", callingUid); 1790 } 1791 } 1792 1793 /** 1794 * Cleans up obsolete rules: 1795 * <ul> 1796 * <li>Rule instances whose owner is not installed. 1797 * <li>Deleted rules that were deleted more than 30 days ago. 1798 * </ul> 1799 */ cleanUpZenRules()1800 private void cleanUpZenRules() { 1801 Instant keptRuleThreshold = mClock.instant().minus(DELETED_RULE_KEPT_FOR); 1802 synchronized (mConfigLock) { 1803 final ZenModeConfig newConfig = mConfig.copy(); 1804 1805 deleteRulesWithoutOwner(newConfig.automaticRules); 1806 if (Flags.modesApi()) { 1807 deleteRulesWithoutOwner(newConfig.deletedRules); 1808 for (int i = newConfig.deletedRules.size() - 1; i >= 0; i--) { 1809 ZenRule deletedRule = newConfig.deletedRules.valueAt(i); 1810 if (deletedRule.deletionInstant == null 1811 || deletedRule.deletionInstant.isBefore(keptRuleThreshold)) { 1812 newConfig.deletedRules.removeAt(i); 1813 } 1814 } 1815 } 1816 1817 if (!newConfig.equals(mConfig)) { 1818 setConfigLocked(newConfig, null, UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, 1819 "cleanUpZenRules", Process.SYSTEM_UID); 1820 } 1821 } 1822 } 1823 deleteRulesWithoutOwner(ArrayMap<String, ZenRule> ruleList)1824 private void deleteRulesWithoutOwner(ArrayMap<String, ZenRule> ruleList) { 1825 long currentTime = Flags.modesApi() ? mClock.millis() : System.currentTimeMillis(); 1826 if (ruleList != null) { 1827 for (int i = ruleList.size() - 1; i >= 0; i--) { 1828 ZenRule rule = ruleList.valueAt(i); 1829 if (RULE_INSTANCE_GRACE_PERIOD < (currentTime - rule.creationTime)) { 1830 try { 1831 if (rule.getPkg() != null) { 1832 mPm.getPackageInfo(rule.getPkg(), PackageManager.MATCH_ANY_USER); 1833 } 1834 } catch (PackageManager.NameNotFoundException e) { 1835 ruleList.removeAt(i); 1836 } 1837 } 1838 } 1839 } 1840 } 1841 1842 /** 1843 * @return a copy of the zen mode configuration 1844 */ getConfig()1845 public ZenModeConfig getConfig() { 1846 synchronized (mConfigLock) { 1847 return mConfig.copy(); 1848 } 1849 } 1850 1851 /** 1852 * @return a copy of the zen mode consolidated policy 1853 */ getConsolidatedNotificationPolicy()1854 public Policy getConsolidatedNotificationPolicy() { 1855 return mConsolidatedPolicy.copy(); 1856 } 1857 1858 /** 1859 * Returns a copy of the device default policy as a ZenPolicy object. 1860 */ 1861 @VisibleForTesting getDefaultZenPolicy()1862 protected ZenPolicy getDefaultZenPolicy() { 1863 return mDefaultConfig.getZenPolicy(); 1864 } 1865 1866 @GuardedBy("mConfigLock") setConfigLocked(ZenModeConfig config, ComponentName triggeringComponent, @ConfigChangeOrigin int origin, String reason, int callingUid)1867 private boolean setConfigLocked(ZenModeConfig config, ComponentName triggeringComponent, 1868 @ConfigChangeOrigin int origin, String reason, int callingUid) { 1869 return setConfigLocked(config, origin, reason, triggeringComponent, true /*setRingerMode*/, 1870 callingUid); 1871 } 1872 setConfig(ZenModeConfig config, ComponentName triggeringComponent, @ConfigChangeOrigin int origin, String reason, int callingUid)1873 void setConfig(ZenModeConfig config, ComponentName triggeringComponent, 1874 @ConfigChangeOrigin int origin, String reason, int callingUid) { 1875 synchronized (mConfigLock) { 1876 setConfigLocked(config, triggeringComponent, origin, reason, callingUid); 1877 } 1878 } 1879 1880 @GuardedBy("mConfigLock") setConfigLocked(ZenModeConfig config, @ConfigChangeOrigin int origin, String reason, ComponentName triggeringComponent, boolean setRingerMode, int callingUid)1881 private boolean setConfigLocked(ZenModeConfig config, @ConfigChangeOrigin int origin, 1882 String reason, ComponentName triggeringComponent, boolean setRingerMode, 1883 int callingUid) { 1884 final long identity = Binder.clearCallingIdentity(); 1885 try { 1886 if (config == null || !config.isValid()) { 1887 Log.w(TAG, "Invalid config in setConfigLocked; " + config); 1888 return false; 1889 } 1890 if (config.user != mUser) { 1891 // simply store away for background users 1892 synchronized (mConfigsArrayLock) { 1893 mConfigs.put(config.user, config); 1894 } 1895 if (DEBUG) Log.d(TAG, "setConfigLocked: store config for user " + config.user); 1896 return true; 1897 } 1898 // handle CPS backed conditions - danger! may modify config 1899 mConditions.evaluateConfig(config, null, false /*processSubscriptions*/); 1900 1901 synchronized (mConfigsArrayLock) { 1902 mConfigs.put(config.user, config); 1903 } 1904 if (DEBUG) Log.d(TAG, "setConfigLocked reason=" + reason, new Throwable()); 1905 ZenLog.traceConfig(reason, triggeringComponent, mConfig, config, callingUid); 1906 1907 // send some broadcasts 1908 Policy newPolicy = getNotificationPolicy(config); 1909 boolean policyChanged = !Objects.equals(getNotificationPolicy(mConfig), newPolicy); 1910 if (policyChanged) { 1911 dispatchOnPolicyChanged(newPolicy); 1912 } 1913 updateConfigAndZenModeLocked(config, origin, reason, setRingerMode, callingUid); 1914 mConditions.evaluateConfig(config, triggeringComponent, true /*processSubscriptions*/); 1915 return true; 1916 } catch (SecurityException e) { 1917 Log.wtf(TAG, "Invalid rule in config", e); 1918 return false; 1919 } finally { 1920 Binder.restoreCallingIdentity(identity); 1921 } 1922 } 1923 1924 /** 1925 * Carries out a config update (if needed) and (re-)evaluates the zen mode value afterwards. 1926 * If logging is enabled, will also request logging of the outcome of this change if needed. 1927 */ 1928 @GuardedBy("mConfigLock") updateConfigAndZenModeLocked(ZenModeConfig config, @ConfigChangeOrigin int origin, String reason, boolean setRingerMode, int callingUid)1929 private void updateConfigAndZenModeLocked(ZenModeConfig config, @ConfigChangeOrigin int origin, 1930 String reason, boolean setRingerMode, int callingUid) { 1931 final boolean logZenModeEvents = mFlagResolver.isEnabled( 1932 SystemUiSystemPropertiesFlags.NotificationFlags.LOG_DND_STATE_EVENTS); 1933 // Store (a copy of) all config and zen mode info prior to any changes taking effect 1934 ZenModeEventLogger.ZenModeInfo prevInfo = new ZenModeEventLogger.ZenModeInfo( 1935 mZenMode, mConfig, mConsolidatedPolicy); 1936 if (!config.equals(mConfig)) { 1937 // Schedule broadcasts. Cannot be sent during boot, though. 1938 if (Flags.modesApi() && origin != UPDATE_ORIGIN_INIT) { 1939 for (ZenRule rule : config.automaticRules.values()) { 1940 ZenRule original = mConfig.automaticRules.get(rule.id); 1941 if (original != null) { 1942 if (original.enabled != rule.enabled) { 1943 scheduleEnabledBroadcast( 1944 rule.getPkg(), config.user, rule.id, rule.enabled); 1945 } 1946 if (original.isAutomaticActive() != rule.isAutomaticActive()) { 1947 scheduleActivationBroadcast( 1948 rule.getPkg(), config.user, rule.id, rule.isAutomaticActive()); 1949 } 1950 } 1951 } 1952 } 1953 1954 mConfig = config; 1955 dispatchOnConfigChanged(); 1956 updateAndApplyConsolidatedPolicyAndDeviceEffects(origin, reason); 1957 } 1958 final String val = Integer.toString(config.hashCode()); 1959 Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_CONFIG_ETAG, val); 1960 evaluateZenModeLocked(origin, reason, setRingerMode); 1961 // After all changes have occurred, log if requested 1962 if (logZenModeEvents) { 1963 ZenModeEventLogger.ZenModeInfo newInfo = new ZenModeEventLogger.ZenModeInfo( 1964 mZenMode, mConfig, mConsolidatedPolicy); 1965 mZenModeEventLogger.maybeLogZenChange(prevInfo, newInfo, callingUid, 1966 origin); 1967 } 1968 } 1969 getZenModeSetting()1970 private int getZenModeSetting() { 1971 return Global.getInt(mContext.getContentResolver(), Global.ZEN_MODE, Global.ZEN_MODE_OFF); 1972 } 1973 1974 @VisibleForTesting setZenModeSetting(int zen)1975 protected void setZenModeSetting(int zen) { 1976 Global.putInt(mContext.getContentResolver(), Global.ZEN_MODE, zen); 1977 ZenLog.traceSetZenMode(Global.getInt(mContext.getContentResolver(), Global.ZEN_MODE, -1), 1978 "updated setting"); 1979 showZenUpgradeNotification(zen); 1980 } 1981 getPreviousRingerModeSetting()1982 private int getPreviousRingerModeSetting() { 1983 return Global.getInt(mContext.getContentResolver(), 1984 Global.ZEN_MODE_RINGER_LEVEL, AudioManager.RINGER_MODE_NORMAL); 1985 } 1986 setPreviousRingerModeSetting(Integer previousRingerLevel)1987 private void setPreviousRingerModeSetting(Integer previousRingerLevel) { 1988 Global.putString( 1989 mContext.getContentResolver(), Global.ZEN_MODE_RINGER_LEVEL, 1990 previousRingerLevel == null ? null : Integer.toString(previousRingerLevel)); 1991 } 1992 1993 @VisibleForTesting 1994 @GuardedBy("mConfigLock") evaluateZenModeLocked(@onfigChangeOrigin int origin, String reason, boolean setRingerMode)1995 protected void evaluateZenModeLocked(@ConfigChangeOrigin int origin, String reason, 1996 boolean setRingerMode) { 1997 if (DEBUG) Log.d(TAG, "evaluateZenMode"); 1998 if (mConfig == null) return; 1999 final int policyHashBefore = mConsolidatedPolicy == null ? 0 2000 : mConsolidatedPolicy.hashCode(); 2001 final int zenBefore = mZenMode; 2002 final int zen = computeZenMode(); 2003 ZenLog.traceSetZenMode(zen, reason); 2004 mZenMode = zen; 2005 setZenModeSetting(mZenMode); 2006 updateAndApplyConsolidatedPolicyAndDeviceEffects(origin, reason); 2007 boolean shouldApplyToRinger = setRingerMode && (zen != zenBefore || ( 2008 zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS 2009 && policyHashBefore != mConsolidatedPolicy.hashCode())); 2010 mHandler.postUpdateRingerAndAudio(shouldApplyToRinger); 2011 if (zen != zenBefore) { 2012 mHandler.postDispatchOnZenModeChanged(); 2013 } 2014 } 2015 updateRingerAndAudio(boolean shouldApplyToRinger)2016 private void updateRingerAndAudio(boolean shouldApplyToRinger) { 2017 if (mAudioManager != null) { 2018 mAudioManager.updateRingerModeAffectedStreamsInternal(); 2019 } 2020 if (shouldApplyToRinger) { 2021 applyZenToRingerMode(); 2022 } 2023 applyRestrictions(); 2024 } 2025 computeZenMode()2026 private int computeZenMode() { 2027 synchronized (mConfigLock) { 2028 if (mConfig == null) return Global.ZEN_MODE_OFF; 2029 if (mConfig.isManualActive()) return mConfig.manualRule.zenMode; 2030 int zen = Global.ZEN_MODE_OFF; 2031 for (ZenRule automaticRule : mConfig.automaticRules.values()) { 2032 if (automaticRule.isAutomaticActive()) { 2033 if (zenSeverity(automaticRule.zenMode) > zenSeverity(zen)) { 2034 // automatic rule triggered dnd and user hasn't seen update dnd dialog 2035 if (Settings.Secure.getInt(mContext.getContentResolver(), 2036 Settings.Secure.ZEN_SETTINGS_SUGGESTION_VIEWED, 1) == 0) { 2037 Settings.Secure.putInt(mContext.getContentResolver(), 2038 Settings.Secure.SHOW_ZEN_SETTINGS_SUGGESTION, 1); 2039 } 2040 zen = automaticRule.zenMode; 2041 } 2042 } 2043 } 2044 return zen; 2045 } 2046 } 2047 2048 @GuardedBy("mConfigLock") applyCustomPolicy(ZenPolicy policy, ZenRule rule, boolean useManualConfig)2049 private void applyCustomPolicy(ZenPolicy policy, ZenRule rule, boolean useManualConfig) { 2050 if (rule.zenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) { 2051 policy.apply(new ZenPolicy.Builder() 2052 .disallowAllSounds() 2053 .allowPriorityChannels(false) 2054 .build()); 2055 } else if (rule.zenMode == Global.ZEN_MODE_ALARMS) { 2056 policy.apply(new ZenPolicy.Builder() 2057 .disallowAllSounds() 2058 .allowAlarms(true) 2059 .allowMedia(true) 2060 .allowPriorityChannels(false) 2061 .build()); 2062 } else if (rule.zenPolicy != null) { 2063 policy.apply(rule.zenPolicy); 2064 } else { 2065 if (Flags.modesApi()) { 2066 if (useManualConfig) { 2067 // manual rule is configured using the settings stored directly in mConfig 2068 policy.apply(mConfig.getZenPolicy()); 2069 } else { 2070 // under modes_api flag, an active automatic rule with no specified policy 2071 // inherits the device default settings as stored in mDefaultConfig. While the 2072 // rule's policy fields should be set upon creation, this is a fallback to 2073 // catch any that may have fallen through the cracks. 2074 Log.wtf(TAG, "active automatic rule found with no specified policy: " + rule); 2075 policy.apply(Flags.modesUi() 2076 ? mDefaultConfig.getZenPolicy() : mConfig.getZenPolicy()); 2077 } 2078 } else { 2079 // active rule with no specified policy inherits the manual rule config settings 2080 policy.apply(mConfig.getZenPolicy()); 2081 } 2082 } 2083 } 2084 2085 @GuardedBy("mConfigLock") updateAndApplyConsolidatedPolicyAndDeviceEffects(@onfigChangeOrigin int origin, String reason)2086 private void updateAndApplyConsolidatedPolicyAndDeviceEffects(@ConfigChangeOrigin int origin, 2087 String reason) { 2088 synchronized (mConfigLock) { 2089 if (mConfig == null) return; 2090 ZenPolicy policy = new ZenPolicy(); 2091 ZenDeviceEffects.Builder deviceEffectsBuilder = new ZenDeviceEffects.Builder(); 2092 if (mConfig.isManualActive()) { 2093 applyCustomPolicy(policy, mConfig.manualRule, true); 2094 if (Flags.modesApi()) { 2095 deviceEffectsBuilder.add(mConfig.manualRule.zenDeviceEffects); 2096 } 2097 } 2098 2099 for (ZenRule automaticRule : mConfig.automaticRules.values()) { 2100 if (automaticRule.isAutomaticActive()) { 2101 // Active rules with INTERRUPTION_FILTER_ALL are not included in consolidated 2102 // policy. This is relevant in case some other active rule has a more 2103 // restrictive INTERRUPTION_FILTER but a more lenient ZenPolicy! 2104 if (!Flags.modesApi() || automaticRule.zenMode != Global.ZEN_MODE_OFF) { 2105 applyCustomPolicy(policy, automaticRule, false); 2106 } 2107 if (Flags.modesApi()) { 2108 deviceEffectsBuilder.add(automaticRule.zenDeviceEffects); 2109 } 2110 } 2111 } 2112 2113 // While mConfig.toNotificationPolicy fills in any unset fields from the provided 2114 // config (which, in this case is the manual "global" config), under modes API changes, 2115 // we should have no remaining unset fields: the manual policy gets every field from 2116 // the global policy, and each automatic rule has all policy fields filled in on 2117 // creation or update. 2118 // However, the piece of information that comes from mConfig that we must keep is the 2119 // areChannelsBypassingDnd bit, which is a state, rather than a policy, and even when 2120 // all policy fields are set, this state comes to the new policy from this call. 2121 Policy newPolicy = mConfig.toNotificationPolicy(policy); 2122 if (!Objects.equals(mConsolidatedPolicy, newPolicy)) { 2123 mConsolidatedPolicy = newPolicy; 2124 dispatchOnConsolidatedPolicyChanged(newPolicy); 2125 ZenLog.traceSetConsolidatedZenPolicy(mConsolidatedPolicy, reason); 2126 } 2127 2128 if (Flags.modesApi()) { 2129 ZenDeviceEffects deviceEffects = deviceEffectsBuilder.build(); 2130 if (!deviceEffects.equals(mConsolidatedDeviceEffects)) { 2131 mConsolidatedDeviceEffects = deviceEffects; 2132 mHandler.postApplyDeviceEffects(origin); 2133 } 2134 } 2135 } 2136 } 2137 applyConsolidatedDeviceEffects(@onfigChangeOrigin int source)2138 private void applyConsolidatedDeviceEffects(@ConfigChangeOrigin int source) { 2139 if (!Flags.modesApi()) { 2140 return; 2141 } 2142 DeviceEffectsApplier applier; 2143 ZenDeviceEffects effects; 2144 synchronized (mConfigLock) { 2145 applier = mDeviceEffectsApplier; 2146 effects = mConsolidatedDeviceEffects; 2147 } 2148 if (applier != null) { 2149 applier.apply(effects, source); 2150 } 2151 } 2152 updateDefaultConfigAutomaticRules()2153 private void updateDefaultConfigAutomaticRules() { 2154 for (ZenRule rule : mDefaultConfig.automaticRules.values()) { 2155 if (ZenModeConfig.EVENTS_DEFAULT_RULE_ID.equals(rule.id)) { 2156 rule.name = mContext.getResources() 2157 .getString(R.string.zen_mode_default_events_name); 2158 } else if (ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID.equals(rule.id)) { 2159 rule.name = mContext.getResources() 2160 .getString(R.string.zen_mode_default_every_night_name); 2161 } 2162 if (Flags.modesApi() && Flags.modesUi()) { 2163 SystemZenRules.updateTriggerDescription(mContext, rule); 2164 } 2165 } 2166 } 2167 2168 // Updates the policies in the default automatic rules (provided via default XML config) to 2169 // be fully filled in default values. updateDefaultAutomaticRulePolicies()2170 private void updateDefaultAutomaticRulePolicies() { 2171 if (!Flags.modesApi()) { 2172 // Should be checked before calling, but just in case. 2173 return; 2174 } 2175 ZenPolicy defaultPolicy = mDefaultConfig.getZenPolicy(); 2176 for (ZenRule rule : mDefaultConfig.automaticRules.values()) { 2177 if (ZenModeConfig.DEFAULT_RULE_IDS.contains(rule.id) && rule.zenPolicy == null) { 2178 rule.zenPolicy = defaultPolicy.copy(); 2179 } 2180 } 2181 } 2182 2183 @VisibleForTesting applyRestrictions()2184 protected void applyRestrictions() { 2185 final boolean zenOn = mZenMode != Global.ZEN_MODE_OFF; 2186 final boolean zenPriorityOnly = mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; 2187 final boolean zenSilence = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS; 2188 final boolean zenAlarmsOnly = mZenMode == Global.ZEN_MODE_ALARMS; 2189 final boolean allowCalls = mConsolidatedPolicy.allowCalls() 2190 && mConsolidatedPolicy.allowCallsFrom() == PRIORITY_SENDERS_ANY; 2191 final boolean allowRepeatCallers = mConsolidatedPolicy.allowRepeatCallers(); 2192 final boolean allowSystem = mConsolidatedPolicy.allowSystem(); 2193 final boolean allowMedia = mConsolidatedPolicy.allowMedia(); 2194 final boolean allowAlarms = mConsolidatedPolicy.allowAlarms(); 2195 2196 // notification restrictions 2197 final boolean muteNotifications = zenOn 2198 || (mSuppressedEffects & SUPPRESSED_EFFECT_NOTIFICATIONS) != 0; 2199 // call restrictions 2200 final boolean muteCalls = zenAlarmsOnly 2201 || (zenPriorityOnly && !(allowCalls || allowRepeatCallers)) 2202 || (mSuppressedEffects & SUPPRESSED_EFFECT_CALLS) != 0; 2203 // alarm restrictions 2204 final boolean muteAlarms = zenPriorityOnly && !allowAlarms; 2205 // media restrictions 2206 final boolean muteMedia = zenPriorityOnly && !allowMedia; 2207 // system restrictions 2208 final boolean muteSystem = zenAlarmsOnly || (zenPriorityOnly && !allowSystem); 2209 // total silence restrictions 2210 final boolean muteEverything = zenSilence || (zenPriorityOnly 2211 && ZenModeConfig.areAllZenBehaviorSoundsMuted(mConsolidatedPolicy)); 2212 2213 for (int usage : AudioAttributes.SDK_USAGES.toArray()) { 2214 final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage); 2215 if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NEVER) { 2216 applyRestrictions(zenPriorityOnly, false /*mute*/, usage); 2217 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NOTIFICATION) { 2218 applyRestrictions(zenPriorityOnly, muteNotifications || muteEverything, usage); 2219 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_CALL) { 2220 applyRestrictions(zenPriorityOnly, muteCalls || muteEverything, usage); 2221 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_ALARM) { 2222 applyRestrictions(zenPriorityOnly, muteAlarms || muteEverything, usage); 2223 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_MEDIA) { 2224 applyRestrictions(zenPriorityOnly, muteMedia || muteEverything, usage); 2225 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_SYSTEM) { 2226 if (usage == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) { 2227 // normally DND will only restrict touch sounds, not haptic feedback/vibrations 2228 applyRestrictions(zenPriorityOnly, muteSystem || muteEverything, usage, 2229 AppOpsManager.OP_PLAY_AUDIO); 2230 applyRestrictions(zenPriorityOnly, false, usage, AppOpsManager.OP_VIBRATE); 2231 } else { 2232 applyRestrictions(zenPriorityOnly, muteSystem || muteEverything, usage); 2233 } 2234 } else { 2235 applyRestrictions(zenPriorityOnly, muteEverything, usage); 2236 } 2237 } 2238 } 2239 2240 2241 @VisibleForTesting applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage, int code)2242 protected void applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage, int code) { 2243 final long ident = Binder.clearCallingIdentity(); 2244 try { 2245 mAppOps.setRestriction(code, usage, 2246 mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED, 2247 zenPriorityOnly ? mPriorityOnlyDndExemptPackages : null); 2248 } finally { 2249 Binder.restoreCallingIdentity(ident); 2250 } 2251 } 2252 2253 @VisibleForTesting applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage)2254 protected void applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage) { 2255 applyRestrictions(zenPriorityOnly, mute, usage, AppOpsManager.OP_VIBRATE); 2256 applyRestrictions(zenPriorityOnly, mute, usage, AppOpsManager.OP_PLAY_AUDIO); 2257 } 2258 2259 2260 @VisibleForTesting applyZenToRingerMode()2261 protected void applyZenToRingerMode() { 2262 if (mAudioManager == null) return; 2263 // force the ringer mode into compliance 2264 final int ringerModeInternal = mAudioManager.getRingerModeInternal(); 2265 int newRingerModeInternal = ringerModeInternal; 2266 switch (mZenMode) { 2267 case Global.ZEN_MODE_NO_INTERRUPTIONS: 2268 case Global.ZEN_MODE_ALARMS: 2269 if (ringerModeInternal != AudioManager.RINGER_MODE_SILENT) { 2270 setPreviousRingerModeSetting(ringerModeInternal); 2271 newRingerModeInternal = AudioManager.RINGER_MODE_SILENT; 2272 } 2273 break; 2274 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: 2275 // do not apply zen to ringer, streams zen muted in AudioService 2276 break; 2277 case Global.ZEN_MODE_OFF: 2278 if (ringerModeInternal == AudioManager.RINGER_MODE_SILENT) { 2279 newRingerModeInternal = getPreviousRingerModeSetting(); 2280 setPreviousRingerModeSetting(null); 2281 } 2282 break; 2283 } 2284 if (newRingerModeInternal != -1) { 2285 mAudioManager.setRingerModeInternal(newRingerModeInternal, TAG); 2286 } 2287 } 2288 dispatchOnConfigChanged()2289 private void dispatchOnConfigChanged() { 2290 for (Callback callback : mCallbacks) { 2291 callback.onConfigChanged(); 2292 } 2293 } 2294 dispatchOnPolicyChanged(Policy newPolicy)2295 private void dispatchOnPolicyChanged(Policy newPolicy) { 2296 for (Callback callback : mCallbacks) { 2297 callback.onPolicyChanged(newPolicy); 2298 } 2299 } 2300 dispatchOnConsolidatedPolicyChanged(Policy newConsolidatedPolicy)2301 private void dispatchOnConsolidatedPolicyChanged(Policy newConsolidatedPolicy) { 2302 for (Callback callback : mCallbacks) { 2303 callback.onConsolidatedPolicyChanged(newConsolidatedPolicy); 2304 } 2305 } 2306 dispatchOnZenModeChanged()2307 private void dispatchOnZenModeChanged() { 2308 for (Callback callback : mCallbacks) { 2309 callback.onZenModeChanged(); 2310 } 2311 } 2312 dispatchOnAutomaticRuleStatusChanged(int userId, String pkg, String id, int status)2313 private void dispatchOnAutomaticRuleStatusChanged(int userId, String pkg, String id, 2314 int status) { 2315 for (Callback callback : mCallbacks) { 2316 callback.onAutomaticRuleStatusChanged(userId, pkg, id, status); 2317 } 2318 } 2319 readDefaultConfig(Resources resources)2320 private ZenModeConfig readDefaultConfig(Resources resources) { 2321 XmlResourceParser parser = null; 2322 try { 2323 parser = resources.getXml(R.xml.default_zen_mode_config); 2324 while (parser.next() != XmlPullParser.END_DOCUMENT) { 2325 final ZenModeConfig config = ZenModeConfig.readXml(XmlUtils.makeTyped(parser)); 2326 if (config != null) return config; 2327 } 2328 } catch (Exception e) { 2329 Log.w(TAG, "Error reading default zen mode config from resource", e); 2330 } finally { 2331 IoUtils.closeQuietly(parser); 2332 } 2333 return new ZenModeConfig(); 2334 } 2335 zenSeverity(int zen)2336 private static int zenSeverity(int zen) { 2337 switch (zen) { 2338 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: return 1; 2339 case Global.ZEN_MODE_ALARMS: return 2; 2340 case Global.ZEN_MODE_NO_INTERRUPTIONS: return 3; 2341 default: return 0; 2342 } 2343 } 2344 2345 /** 2346 * Generate pulled atoms about do not disturb configurations. 2347 */ pullRules(List<StatsEvent> events)2348 public void pullRules(List<StatsEvent> events) { 2349 synchronized (mConfigsArrayLock) { 2350 final int numConfigs = mConfigs.size(); 2351 for (int i = 0; i < numConfigs; i++) { 2352 final int user = mConfigs.keyAt(i); 2353 final ZenModeConfig config = mConfigs.valueAt(i); 2354 events.add(FrameworkStatsLog.buildStatsEvent(DND_MODE_RULE, 2355 /* optional int32 user = 1 */ user, 2356 /* optional bool enabled = 2 */ config.isManualActive(), 2357 /* optional bool channels_bypassing = 3 */ config.areChannelsBypassingDnd, 2358 /* optional LoggedZenMode zen_mode = 4 */ ROOT_CONFIG, 2359 /* optional string id = 5 */ "", // empty for root config 2360 /* optional int32 uid = 6 */ Process.SYSTEM_UID, // system owns root config 2361 /* optional DNDPolicyProto policy = 7 */ config.getZenPolicy().toProto(), 2362 /* optional int32 rule_modified_fields = 8 */ 0, 2363 /* optional int32 policy_modified_fields = 9 */ 0, 2364 /* optional int32 device_effects_modified_fields = 10 */ 0, 2365 /* optional ActiveRuleType rule_type = 11 */ TYPE_UNKNOWN)); 2366 if (config.isManualActive()) { 2367 ruleToProtoLocked(user, config.manualRule, true, events); 2368 } 2369 for (ZenRule rule : config.automaticRules.values()) { 2370 ruleToProtoLocked(user, rule, false, events); 2371 } 2372 } 2373 } 2374 } 2375 2376 @GuardedBy("mConfigsArrayLock") ruleToProtoLocked(int user, ZenRule rule, boolean isManualRule, List<StatsEvent> events)2377 private void ruleToProtoLocked(int user, ZenRule rule, boolean isManualRule, 2378 List<StatsEvent> events) { 2379 // Make the ID safe. 2380 String id = rule.id == null ? "" : rule.id; 2381 if (!ZenModeConfig.DEFAULT_RULE_IDS.contains(id)) { 2382 id = ""; 2383 } 2384 2385 // Look for packages and enablers, enablers get priority. 2386 String pkg = rule.getPkg() == null ? "" : rule.getPkg(); 2387 if (rule.enabler != null) { 2388 pkg = rule.enabler; 2389 } 2390 2391 int ruleType = rule.type; 2392 if (isManualRule) { 2393 id = ZenModeConfig.MANUAL_RULE_ID; 2394 ruleType = ZenModeEventLogger.ACTIVE_RULE_TYPE_MANUAL; 2395 } 2396 2397 SysUiStatsEvent.Builder data; 2398 byte[] policyProto = new byte[]{}; 2399 if (rule.zenPolicy != null) { 2400 policyProto = rule.zenPolicy.toProto(); 2401 } 2402 events.add(FrameworkStatsLog.buildStatsEvent(DND_MODE_RULE, 2403 /* optional int32 user = 1 */ user, 2404 /* optional bool enabled = 2 */ rule.enabled, 2405 /* optional bool channels_bypassing = 3 */ false, // unused for rules 2406 /* optional android.stats.dnd.ZenMode zen_mode = 4 */ rule.zenMode, 2407 /* optional string id = 5 */ id, 2408 /* optional int32 uid = 6 */ getPackageUid(pkg, user), 2409 /* optional DNDPolicyProto policy = 7 */ policyProto, 2410 /* optional int32 rule_modified_fields = 8 */ rule.userModifiedFields, 2411 /* optional int32 policy_modified_fields = 9 */ rule.zenPolicyUserModifiedFields, 2412 /* optional int32 device_effects_modified_fields = 10 */ 2413 rule.zenDeviceEffectsUserModifiedFields, 2414 /* optional ActiveRuleType rule_type = 11 */ ruleType)); 2415 } 2416 getPackageUid(String pkg, int user)2417 private int getPackageUid(String pkg, int user) { 2418 if ("android".equals(pkg)) { 2419 return Process.SYSTEM_UID; 2420 } 2421 final String key = getPackageUserKey(pkg, user); 2422 if (mRulesUidCache.get(key) == null) { 2423 try { 2424 mRulesUidCache.put(key, mPm.getPackageUidAsUser(pkg, user)); 2425 } catch (PackageManager.NameNotFoundException e) { 2426 } 2427 } 2428 return mRulesUidCache.getOrDefault(key, -1); 2429 } 2430 getPackageUserKey(String pkg, int user)2431 private static String getPackageUserKey(String pkg, int user) { 2432 return pkg + "|" + user; 2433 } 2434 2435 @VisibleForTesting 2436 protected final class RingerModeDelegate implements AudioManagerInternal.RingerModeDelegate { 2437 @Override toString()2438 public String toString() { 2439 return TAG; 2440 } 2441 2442 @Override onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, @Nullable String caller, int ringerModeExternal, VolumePolicy policy)2443 public int onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, 2444 @Nullable String caller, int ringerModeExternal, VolumePolicy policy) { 2445 final boolean isChange = ringerModeOld != ringerModeNew; 2446 2447 int ringerModeExternalOut = ringerModeNew; 2448 2449 if (mZenMode == Global.ZEN_MODE_OFF 2450 || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS 2451 && !areAllPriorityOnlyRingerSoundsMuted())) { 2452 // in priority only with ringer not muted, save ringer mode changes 2453 // in dnd off, save ringer mode changes 2454 setPreviousRingerModeSetting(ringerModeNew); 2455 } 2456 int newZen = -1; 2457 switch (ringerModeNew) { 2458 case AudioManager.RINGER_MODE_SILENT: 2459 if (isChange && policy.doNotDisturbWhenSilent) { 2460 if (mZenMode == Global.ZEN_MODE_OFF) { 2461 newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; 2462 } 2463 setPreviousRingerModeSetting(ringerModeOld); 2464 } 2465 break; 2466 case AudioManager.RINGER_MODE_VIBRATE: 2467 case AudioManager.RINGER_MODE_NORMAL: 2468 if (isChange && ringerModeOld == AudioManager.RINGER_MODE_SILENT 2469 && (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS 2470 || mZenMode == Global.ZEN_MODE_ALARMS 2471 || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS 2472 && areAllPriorityOnlyRingerSoundsMuted()))) { 2473 newZen = Global.ZEN_MODE_OFF; 2474 } else if (mZenMode != Global.ZEN_MODE_OFF) { 2475 ringerModeExternalOut = AudioManager.RINGER_MODE_SILENT; 2476 } 2477 break; 2478 } 2479 2480 if (newZen != -1) { 2481 setManualZenMode(newZen, null, UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, 2482 "ringerModeInternal", /* caller= */ null, /* setRingerMode= */ false, 2483 Process.SYSTEM_UID); 2484 } 2485 if (isChange || newZen != -1 || ringerModeExternal != ringerModeExternalOut) { 2486 ZenLog.traceSetRingerModeInternal(ringerModeOld, ringerModeNew, caller, 2487 ringerModeExternal, ringerModeExternalOut); 2488 } 2489 return ringerModeExternalOut; 2490 } 2491 areAllPriorityOnlyRingerSoundsMuted()2492 private boolean areAllPriorityOnlyRingerSoundsMuted() { 2493 synchronized (mConfigLock) { 2494 return ZenModeConfig.areAllPriorityOnlyRingerSoundsMuted(mConfig); 2495 } 2496 } 2497 2498 @Override onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, @Nullable String caller, int ringerModeInternal, VolumePolicy policy)2499 public int onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, 2500 @Nullable String caller, int ringerModeInternal, VolumePolicy policy) { 2501 int ringerModeInternalOut = ringerModeNew; 2502 final boolean isChange = ringerModeOld != ringerModeNew; 2503 final boolean isVibrate = ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE; 2504 2505 int newZen = -1; 2506 switch (ringerModeNew) { 2507 case AudioManager.RINGER_MODE_SILENT: 2508 if (isChange) { 2509 if (mZenMode == Global.ZEN_MODE_OFF) { 2510 newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; 2511 } 2512 ringerModeInternalOut = isVibrate ? AudioManager.RINGER_MODE_VIBRATE 2513 : AudioManager.RINGER_MODE_SILENT; 2514 } else { 2515 ringerModeInternalOut = ringerModeInternal; 2516 } 2517 break; 2518 case AudioManager.RINGER_MODE_VIBRATE: 2519 case AudioManager.RINGER_MODE_NORMAL: 2520 if (mZenMode != Global.ZEN_MODE_OFF) { 2521 newZen = Global.ZEN_MODE_OFF; 2522 } 2523 break; 2524 } 2525 if (newZen != -1) { 2526 setManualZenMode(newZen, null, UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, 2527 "ringerModeExternal", caller, false /*setRingerMode*/, Process.SYSTEM_UID); 2528 } 2529 2530 ZenLog.traceSetRingerModeExternal(ringerModeOld, ringerModeNew, caller, 2531 ringerModeInternal, ringerModeInternalOut); 2532 return ringerModeInternalOut; 2533 } 2534 2535 @Override canVolumeDownEnterSilent()2536 public boolean canVolumeDownEnterSilent() { 2537 return mZenMode == Global.ZEN_MODE_OFF; 2538 } 2539 2540 @Override getRingerModeAffectedStreams(int streams)2541 public int getRingerModeAffectedStreams(int streams) { 2542 // ringtone, notification and system streams are always affected by ringer mode 2543 // zen muting is handled in AudioService.java's mZenModeAffectedStreams 2544 streams |= (1 << AudioSystem.STREAM_RING) | 2545 (1 << AudioSystem.STREAM_NOTIFICATION) | 2546 (1 << AudioSystem.STREAM_SYSTEM); 2547 2548 if (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) { 2549 // alarm and music and streams affected by ringer mode (cannot be adjusted) when in 2550 // total silence 2551 streams |= (1 << AudioSystem.STREAM_ALARM) | 2552 (1 << AudioSystem.STREAM_MUSIC) | 2553 (1 << AudioSystem.STREAM_ASSISTANT); 2554 } else { 2555 streams &= ~((1 << AudioSystem.STREAM_ALARM) | 2556 (1 << AudioSystem.STREAM_MUSIC) | 2557 (1 << AudioSystem.STREAM_ASSISTANT) 2558 ); 2559 } 2560 return streams; 2561 } 2562 } 2563 2564 private final class SettingsObserver extends ContentObserver { 2565 private final Uri ZEN_MODE = Global.getUriFor(Global.ZEN_MODE); 2566 SettingsObserver(Handler handler)2567 public SettingsObserver(Handler handler) { 2568 super(handler); 2569 } 2570 observe()2571 public void observe() { 2572 final ContentResolver resolver = mContext.getContentResolver(); 2573 resolver.registerContentObserver(ZEN_MODE, false /*notifyForDescendents*/, this); 2574 update(null); 2575 } 2576 2577 @Override onChange(boolean selfChange, Uri uri)2578 public void onChange(boolean selfChange, Uri uri) { 2579 update(uri); 2580 } 2581 update(Uri uri)2582 public void update(Uri uri) { 2583 if (ZEN_MODE.equals(uri)) { 2584 if (mZenMode != getZenModeSetting()) { 2585 if (DEBUG) Log.d(TAG, "Fixing zen mode setting"); 2586 setZenModeSetting(mZenMode); 2587 } 2588 } 2589 } 2590 } 2591 showZenUpgradeNotification(int zen)2592 private void showZenUpgradeNotification(int zen) { 2593 final boolean isWatch = mContext.getPackageManager().hasSystemFeature( 2594 PackageManager.FEATURE_WATCH); 2595 final boolean showNotification = mIsSystemServicesReady 2596 && zen != Global.ZEN_MODE_OFF 2597 && !isWatch 2598 && Settings.Secure.getInt(mContext.getContentResolver(), 2599 Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0 2600 && Settings.Secure.getInt(mContext.getContentResolver(), 2601 Settings.Secure.ZEN_SETTINGS_UPDATED, 0) != 1; 2602 2603 if (isWatch) { 2604 Settings.Secure.putInt(mContext.getContentResolver(), 2605 Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0); 2606 } 2607 2608 if (showNotification) { 2609 mNotificationManager.notify(TAG, SystemMessage.NOTE_ZEN_UPGRADE, 2610 createZenUpgradeNotification()); 2611 Settings.Secure.putInt(mContext.getContentResolver(), 2612 Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0); 2613 } 2614 } 2615 2616 @VisibleForTesting createZenUpgradeNotification()2617 protected Notification createZenUpgradeNotification() { 2618 final Bundle extras = new Bundle(); 2619 extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, 2620 mContext.getResources().getString(R.string.global_action_settings)); 2621 int title = R.string.zen_upgrade_notification_title; 2622 int content = R.string.zen_upgrade_notification_content; 2623 int drawable = R.drawable.ic_zen_24dp; 2624 if (NotificationManager.Policy.areAllVisualEffectsSuppressed( 2625 getConsolidatedNotificationPolicy().suppressedVisualEffects)) { 2626 title = R.string.zen_upgrade_notification_visd_title; 2627 content = R.string.zen_upgrade_notification_visd_content; 2628 drawable = R.drawable.ic_dnd_block_notifications; 2629 } 2630 2631 Intent onboardingIntent = new Intent(Settings.ZEN_MODE_ONBOARDING); 2632 onboardingIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 2633 return new Notification.Builder(mContext, SystemNotificationChannels.DO_NOT_DISTURB) 2634 .setAutoCancel(true) 2635 .setSmallIcon(R.drawable.ic_settings_24dp) 2636 .setLargeIcon(Icon.createWithResource(mContext, drawable)) 2637 .setContentTitle(mContext.getResources().getString(title)) 2638 .setContentText(mContext.getResources().getString(content)) 2639 .setContentIntent(PendingIntent.getActivity(mContext, 0, onboardingIntent, 2640 PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE)) 2641 .setAutoCancel(true) 2642 .setLocalOnly(true) 2643 .addExtras(extras) 2644 .setStyle(new Notification.BigTextStyle()) 2645 .build(); 2646 } 2647 drawableResNameToResId(String packageName, String resourceName)2648 private int drawableResNameToResId(String packageName, String resourceName) { 2649 if (TextUtils.isEmpty(resourceName)) { 2650 return 0; 2651 } 2652 try { 2653 final Resources res = mPm.getResourcesForApplication(packageName); 2654 return res.getIdentifier(resourceName, null, null); 2655 } catch (PackageManager.NameNotFoundException e) { 2656 Slog.w(TAG, "cannot load rule icon for pkg", e); 2657 } 2658 return 0; 2659 } 2660 drawableResIdToResName(String packageName, @DrawableRes int resId)2661 private String drawableResIdToResName(String packageName, @DrawableRes int resId) { 2662 if (resId == 0) { 2663 return null; 2664 } 2665 requireNonNull(packageName); 2666 try { 2667 final Resources res = mPm.getResourcesForApplication(packageName); 2668 String resourceName = res.getResourceName(resId); 2669 if (resourceName != null && resourceName.length() > MAX_ICON_RESOURCE_NAME_LENGTH) { 2670 Slog.e(TAG, "Resource name for ID=" + resId + " in package " + packageName 2671 + " is too long (" + resourceName.length() + "); ignoring it"); 2672 return null; 2673 } 2674 return resourceName; 2675 } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) { 2676 Slog.e(TAG, "Resource name for ID=" + resId + " not found in package " + packageName 2677 + ". Resource IDs may change when the application is upgraded, and the system" 2678 + " may not be able to find the correct resource."); 2679 return null; 2680 } 2681 } 2682 2683 /** Checks that the {@code origin} supplied to a ZenModeHelper "API" method makes sense. */ requirePublicOrigin(String method, @ConfigChangeOrigin int origin)2684 private static void requirePublicOrigin(String method, @ConfigChangeOrigin int origin) { 2685 if (!Flags.modesApi()) { 2686 return; 2687 } 2688 checkArgument(origin == UPDATE_ORIGIN_APP || origin == UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI 2689 || origin == UPDATE_ORIGIN_USER, 2690 "Expected one of UPDATE_ORIGIN_APP, UPDATE_ORIGIN_SYSTEM_OR_SYSTEMUI, or " 2691 + "UPDATE_ORIGIN_USER for %s, but received '%s'.", 2692 method, origin); 2693 } 2694 2695 private final class Metrics extends Callback { 2696 private static final String COUNTER_MODE_PREFIX = "dnd_mode_"; 2697 private static final String COUNTER_TYPE_PREFIX = "dnd_type_"; 2698 private static final int DND_OFF = 0; 2699 private static final int DND_ON_MANUAL = 1; 2700 private static final int DND_ON_AUTOMATIC = 2; 2701 private static final String COUNTER_RULE = "dnd_rule_count"; 2702 private static final long MINIMUM_LOG_PERIOD_MS = 60 * 1000; 2703 2704 // Total silence, alarms only, priority only 2705 private int mPreviousZenMode = -1; 2706 private long mModeLogTimeMs = 0L; 2707 2708 private int mNumZenRules = -1; 2709 private long mRuleCountLogTime = 0L; 2710 2711 // automatic (1) vs manual (0) vs dnd off (2) 2712 private int mPreviousZenType = -1; 2713 private long mTypeLogTimeMs = 0L; 2714 2715 @Override onZenModeChanged()2716 void onZenModeChanged() { 2717 emit(); 2718 } 2719 2720 @Override onConfigChanged()2721 void onConfigChanged() { 2722 emit(); 2723 } 2724 emit()2725 private void emit() { 2726 mHandler.postMetricsTimer(); 2727 emitZenMode(); 2728 emitRules(); 2729 emitDndType(); 2730 } 2731 emitZenMode()2732 private void emitZenMode() { 2733 final long now = SystemClock.elapsedRealtime(); 2734 final long since = (now - mModeLogTimeMs); 2735 if (mPreviousZenMode != mZenMode || since > MINIMUM_LOG_PERIOD_MS) { 2736 if (mPreviousZenMode != -1) { 2737 MetricsLogger.count( 2738 mContext, COUNTER_MODE_PREFIX + mPreviousZenMode, (int) since); 2739 } 2740 mPreviousZenMode = mZenMode; 2741 mModeLogTimeMs = now; 2742 } 2743 } 2744 emitRules()2745 private void emitRules() { 2746 final long now = SystemClock.elapsedRealtime(); 2747 final long since = (now - mRuleCountLogTime); 2748 synchronized (mConfigLock) { 2749 int numZenRules = mConfig.automaticRules.size(); 2750 if (mNumZenRules != numZenRules 2751 || since > MINIMUM_LOG_PERIOD_MS) { 2752 if (mNumZenRules != -1) { 2753 MetricsLogger.count(mContext, COUNTER_RULE, 2754 numZenRules - mNumZenRules); 2755 } 2756 mNumZenRules = numZenRules; 2757 2758 mRuleCountLogTime = since; 2759 } 2760 } 2761 } 2762 emitDndType()2763 private void emitDndType() { 2764 final long now = SystemClock.elapsedRealtime(); 2765 final long since = (now - mTypeLogTimeMs); 2766 synchronized (mConfigLock) { 2767 boolean dndOn = mZenMode != Global.ZEN_MODE_OFF; 2768 int zenType = !dndOn ? DND_OFF 2769 : (mConfig.manualRule != null) ? DND_ON_MANUAL : DND_ON_AUTOMATIC; 2770 if (zenType != mPreviousZenType 2771 || since > MINIMUM_LOG_PERIOD_MS) { 2772 if (mPreviousZenType != -1) { 2773 MetricsLogger.count( 2774 mContext, COUNTER_TYPE_PREFIX + mPreviousZenType, (int) since); 2775 } 2776 mTypeLogTimeMs = now; 2777 mPreviousZenType = zenType; 2778 } 2779 } 2780 } 2781 } 2782 2783 private final class H extends Handler { 2784 private static final int MSG_DISPATCH = 1; 2785 private static final int MSG_METRICS = 2; 2786 private static final int MSG_RINGER_AUDIO = 5; 2787 private static final int MSG_APPLY_EFFECTS = 6; 2788 2789 private static final long METRICS_PERIOD_MS = 6 * 60 * 60 * 1000; 2790 H(Looper looper)2791 private H(Looper looper) { 2792 super(looper); 2793 } 2794 postDispatchOnZenModeChanged()2795 private void postDispatchOnZenModeChanged() { 2796 removeMessages(MSG_DISPATCH); 2797 sendEmptyMessage(MSG_DISPATCH); 2798 } 2799 postMetricsTimer()2800 private void postMetricsTimer() { 2801 removeMessages(MSG_METRICS); 2802 sendEmptyMessageDelayed(MSG_METRICS, METRICS_PERIOD_MS); 2803 } 2804 postUpdateRingerAndAudio(boolean shouldApplyToRinger)2805 private void postUpdateRingerAndAudio(boolean shouldApplyToRinger) { 2806 removeMessages(MSG_RINGER_AUDIO); 2807 sendMessage(obtainMessage(MSG_RINGER_AUDIO, shouldApplyToRinger)); 2808 } 2809 postApplyDeviceEffects(@onfigChangeOrigin int origin)2810 private void postApplyDeviceEffects(@ConfigChangeOrigin int origin) { 2811 removeMessages(MSG_APPLY_EFFECTS); 2812 sendMessage(obtainMessage(MSG_APPLY_EFFECTS, origin, 0)); 2813 } 2814 2815 @Override handleMessage(Message msg)2816 public void handleMessage(Message msg) { 2817 switch (msg.what) { 2818 case MSG_DISPATCH: 2819 dispatchOnZenModeChanged(); 2820 break; 2821 case MSG_METRICS: 2822 mMetrics.emit(); 2823 break; 2824 case MSG_RINGER_AUDIO: 2825 boolean shouldApplyToRinger = (boolean) msg.obj; 2826 updateRingerAndAudio(shouldApplyToRinger); 2827 break; 2828 case MSG_APPLY_EFFECTS: 2829 @ConfigChangeOrigin int origin = msg.arg1; 2830 applyConsolidatedDeviceEffects(origin); 2831 break; 2832 } 2833 } 2834 } 2835 2836 public static class Callback { onConfigChanged()2837 void onConfigChanged() {} onZenModeChanged()2838 void onZenModeChanged() {} onPolicyChanged(Policy newPolicy)2839 void onPolicyChanged(Policy newPolicy) {} onConsolidatedPolicyChanged(Policy newConsolidatedPolicy)2840 void onConsolidatedPolicyChanged(Policy newConsolidatedPolicy) {} onAutomaticRuleStatusChanged(int userId, String pkg, String id, int status)2841 void onAutomaticRuleStatusChanged(int userId, String pkg, String id, int status) {} 2842 } 2843 } 2844