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