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 android.app.AppOpsManager; 20 import android.app.AutomaticZenRule; 21 import android.app.Notification; 22 import android.app.NotificationManager; 23 import android.app.NotificationManager.Policy; 24 import android.app.PendingIntent; 25 import android.content.ComponentName; 26 import android.content.ContentResolver; 27 import android.content.Context; 28 import android.content.Intent; 29 import android.content.pm.PackageManager; 30 import android.content.pm.ResolveInfo; 31 import android.content.pm.ServiceInfo; 32 import android.content.res.Resources; 33 import android.content.res.XmlResourceParser; 34 import android.database.ContentObserver; 35 import android.graphics.drawable.Icon; 36 import android.media.AudioAttributes; 37 import android.media.AudioManager; 38 import android.media.AudioManagerInternal; 39 import android.media.AudioSystem; 40 import android.media.VolumePolicy; 41 import android.net.Uri; 42 import android.os.Binder; 43 import android.os.Bundle; 44 import android.os.Handler; 45 import android.os.Looper; 46 import android.os.Message; 47 import android.os.Process; 48 import android.os.SystemClock; 49 import android.os.UserHandle; 50 import android.provider.Settings; 51 import android.provider.Settings.Global; 52 import android.service.notification.Condition; 53 import android.service.notification.ConditionProviderService; 54 import android.service.notification.ZenModeConfig; 55 import android.service.notification.ZenModeConfig.EventInfo; 56 import android.service.notification.ZenModeConfig.ScheduleInfo; 57 import android.service.notification.ZenModeConfig.ZenRule; 58 import android.service.notification.ZenModeProto; 59 import android.util.AndroidRuntimeException; 60 import android.util.ArrayMap; 61 import android.util.Log; 62 import android.util.Slog; 63 import android.util.SparseArray; 64 import android.util.proto.ProtoOutputStream; 65 66 import com.android.internal.R; 67 import com.android.internal.annotations.VisibleForTesting; 68 import com.android.internal.logging.MetricsLogger; 69 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; 70 import com.android.internal.notification.SystemNotificationChannels; 71 import com.android.server.LocalServices; 72 73 import libcore.io.IoUtils; 74 75 import org.xmlpull.v1.XmlPullParser; 76 import org.xmlpull.v1.XmlPullParserException; 77 import org.xmlpull.v1.XmlSerializer; 78 79 import java.io.IOException; 80 import java.io.PrintWriter; 81 import java.util.ArrayList; 82 import java.util.List; 83 import java.util.Objects; 84 85 /** 86 * NotificationManagerService helper for functionality related to zen mode. 87 */ 88 public class ZenModeHelper { 89 static final String TAG = "ZenModeHelper"; 90 static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 91 92 // The amount of time rules instances can exist without their owning app being installed. 93 private static final int RULE_INSTANCE_GRACE_PERIOD = 1000 * 60 * 60 * 72; 94 95 private final Context mContext; 96 private final H mHandler; 97 private final SettingsObserver mSettingsObserver; 98 @VisibleForTesting protected final AppOpsManager mAppOps; 99 @VisibleForTesting protected final NotificationManager mNotificationManager; 100 protected ZenModeConfig mDefaultConfig; 101 private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>(); 102 private final ZenModeFiltering mFiltering; 103 protected final RingerModeDelegate mRingerModeDelegate = new 104 RingerModeDelegate(); 105 private final ZenModeConditions mConditions; 106 private final SparseArray<ZenModeConfig> mConfigs = new SparseArray<>(); 107 private final Metrics mMetrics = new Metrics(); 108 private final ConditionProviders.Config mServiceConfig; 109 110 @VisibleForTesting protected int mZenMode; 111 private int mUser = UserHandle.USER_SYSTEM; 112 @VisibleForTesting protected ZenModeConfig mConfig; 113 @VisibleForTesting protected AudioManagerInternal mAudioManager; 114 protected PackageManager mPm; 115 private long mSuppressedEffects; 116 117 public static final long SUPPRESSED_EFFECT_NOTIFICATIONS = 1; 118 public static final long SUPPRESSED_EFFECT_CALLS = 1 << 1; 119 public static final long SUPPRESSED_EFFECT_ALL = SUPPRESSED_EFFECT_CALLS 120 | SUPPRESSED_EFFECT_NOTIFICATIONS; 121 122 protected String mDefaultRuleEveryNightName; 123 protected String mDefaultRuleEventsName; 124 @VisibleForTesting protected boolean mIsBootComplete; 125 ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders)126 public ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders) { 127 mContext = context; 128 mHandler = new H(looper); 129 addCallback(mMetrics); 130 mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); 131 mNotificationManager = context.getSystemService(NotificationManager.class); 132 133 mDefaultConfig = new ZenModeConfig(); 134 setDefaultZenRules(mContext); 135 mConfig = mDefaultConfig; 136 mConfigs.put(UserHandle.USER_SYSTEM, mConfig); 137 138 mSettingsObserver = new SettingsObserver(mHandler); 139 mSettingsObserver.observe(); 140 mFiltering = new ZenModeFiltering(mContext); 141 mConditions = new ZenModeConditions(this, conditionProviders); 142 mServiceConfig = conditionProviders.getConfig(); 143 } 144 getLooper()145 public Looper getLooper() { 146 return mHandler.getLooper(); 147 } 148 149 @Override toString()150 public String toString() { 151 return TAG; 152 } 153 matchesCallFilter(UserHandle userHandle, Bundle extras, ValidateNotificationPeople validator, int contactsTimeoutMs, float timeoutAffinity)154 public boolean matchesCallFilter(UserHandle userHandle, Bundle extras, 155 ValidateNotificationPeople validator, int contactsTimeoutMs, float timeoutAffinity) { 156 synchronized (mConfig) { 157 return ZenModeFiltering.matchesCallFilter(mContext, mZenMode, mConfig, userHandle, 158 extras, validator, contactsTimeoutMs, timeoutAffinity); 159 } 160 } 161 isCall(NotificationRecord record)162 public boolean isCall(NotificationRecord record) { 163 return mFiltering.isCall(record); 164 } 165 recordCaller(NotificationRecord record)166 public void recordCaller(NotificationRecord record) { 167 mFiltering.recordCall(record); 168 } 169 shouldIntercept(NotificationRecord record)170 public boolean shouldIntercept(NotificationRecord record) { 171 synchronized (mConfig) { 172 return mFiltering.shouldIntercept(mZenMode, mConfig, record); 173 } 174 } 175 addCallback(Callback callback)176 public void addCallback(Callback callback) { 177 mCallbacks.add(callback); 178 } 179 removeCallback(Callback callback)180 public void removeCallback(Callback callback) { 181 mCallbacks.remove(callback); 182 } 183 initZenMode()184 public void initZenMode() { 185 if (DEBUG) Log.d(TAG, "initZenMode"); 186 evaluateZenMode("init", true /*setRingerMode*/); 187 } 188 onSystemReady()189 public void onSystemReady() { 190 if (DEBUG) Log.d(TAG, "onSystemReady"); 191 mAudioManager = LocalServices.getService(AudioManagerInternal.class); 192 if (mAudioManager != null) { 193 mAudioManager.setRingerModeDelegate(mRingerModeDelegate); 194 } 195 mPm = mContext.getPackageManager(); 196 mHandler.postMetricsTimer(); 197 cleanUpZenRules(); 198 evaluateZenMode("onSystemReady", true); 199 mIsBootComplete = true; 200 showZenUpgradeNotification(mZenMode); 201 } 202 onUserSwitched(int user)203 public void onUserSwitched(int user) { 204 loadConfigForUser(user, "onUserSwitched"); 205 } 206 onUserRemoved(int user)207 public void onUserRemoved(int user) { 208 if (user < UserHandle.USER_SYSTEM) return; 209 if (DEBUG) Log.d(TAG, "onUserRemoved u=" + user); 210 mConfigs.remove(user); 211 } 212 onUserUnlocked(int user)213 public void onUserUnlocked(int user) { 214 loadConfigForUser(user, "onUserUnlocked"); 215 } 216 loadConfigForUser(int user, String reason)217 private void loadConfigForUser(int user, String reason) { 218 if (mUser == user || user < UserHandle.USER_SYSTEM) return; 219 mUser = user; 220 if (DEBUG) Log.d(TAG, reason + " u=" + user); 221 ZenModeConfig config = mConfigs.get(user); 222 if (config == null) { 223 if (DEBUG) Log.d(TAG, reason + " generating default config for user " + user); 224 config = mDefaultConfig.copy(); 225 config.user = user; 226 } 227 synchronized (mConfig) { 228 setConfigLocked(config, reason); 229 } 230 cleanUpZenRules(); 231 } 232 getZenModeListenerInterruptionFilter()233 public int getZenModeListenerInterruptionFilter() { 234 return NotificationManager.zenModeToInterruptionFilter(mZenMode); 235 } 236 requestFromListener(ComponentName name, int filter)237 public void requestFromListener(ComponentName name, int filter) { 238 final int newZen = NotificationManager.zenModeFromInterruptionFilter(filter, -1); 239 if (newZen != -1) { 240 setManualZenMode(newZen, null, name != null ? name.getPackageName() : null, 241 "listener:" + (name != null ? name.flattenToShortString() : null)); 242 } 243 } 244 setSuppressedEffects(long suppressedEffects)245 public void setSuppressedEffects(long suppressedEffects) { 246 if (mSuppressedEffects == suppressedEffects) return; 247 mSuppressedEffects = suppressedEffects; 248 applyRestrictions(); 249 } 250 getSuppressedEffects()251 public long getSuppressedEffects() { 252 return mSuppressedEffects; 253 } 254 getZenMode()255 public int getZenMode() { 256 return mZenMode; 257 } 258 getZenRules()259 public List<ZenRule> getZenRules() { 260 List<ZenRule> rules = new ArrayList<>(); 261 synchronized (mConfig) { 262 if (mConfig == null) return rules; 263 for (ZenRule rule : mConfig.automaticRules.values()) { 264 if (canManageAutomaticZenRule(rule)) { 265 rules.add(rule); 266 } 267 } 268 } 269 return rules; 270 } 271 getAutomaticZenRule(String id)272 public AutomaticZenRule getAutomaticZenRule(String id) { 273 ZenRule rule; 274 synchronized (mConfig) { 275 if (mConfig == null) return null; 276 rule = mConfig.automaticRules.get(id); 277 } 278 if (rule == null) return null; 279 if (canManageAutomaticZenRule(rule)) { 280 return createAutomaticZenRule(rule); 281 } 282 return null; 283 } 284 addAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason)285 public String addAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason) { 286 if (!isSystemRule(automaticZenRule)) { 287 ServiceInfo owner = getServiceInfo(automaticZenRule.getOwner()); 288 if (owner == null) { 289 throw new IllegalArgumentException("Owner is not a condition provider service"); 290 } 291 292 int ruleInstanceLimit = -1; 293 if (owner.metaData != null) { 294 ruleInstanceLimit = owner.metaData.getInt( 295 ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1); 296 } 297 if (ruleInstanceLimit > 0 && ruleInstanceLimit 298 < (getCurrentInstanceCount(automaticZenRule.getOwner()) + 1)) { 299 throw new IllegalArgumentException("Rule instance limit exceeded"); 300 } 301 } 302 303 ZenModeConfig newConfig; 304 synchronized (mConfig) { 305 if (mConfig == null) { 306 throw new AndroidRuntimeException("Could not create rule"); 307 } 308 if (DEBUG) { 309 Log.d(TAG, "addAutomaticZenRule rule= " + automaticZenRule + " reason=" + reason); 310 } 311 newConfig = mConfig.copy(); 312 ZenRule rule = new ZenRule(); 313 populateZenRule(automaticZenRule, rule, true); 314 newConfig.automaticRules.put(rule.id, rule); 315 if (setConfigLocked(newConfig, reason, true)) { 316 return rule.id; 317 } else { 318 throw new AndroidRuntimeException("Could not create rule"); 319 } 320 } 321 } 322 updateAutomaticZenRule(String ruleId, AutomaticZenRule automaticZenRule, String reason)323 public boolean updateAutomaticZenRule(String ruleId, AutomaticZenRule automaticZenRule, 324 String reason) { 325 ZenModeConfig newConfig; 326 synchronized (mConfig) { 327 if (mConfig == null) return false; 328 if (DEBUG) { 329 Log.d(TAG, "updateAutomaticZenRule zenRule=" + automaticZenRule 330 + " reason=" + reason); 331 } 332 newConfig = mConfig.copy(); 333 ZenModeConfig.ZenRule rule; 334 if (ruleId == null) { 335 throw new IllegalArgumentException("Rule doesn't exist"); 336 } else { 337 rule = newConfig.automaticRules.get(ruleId); 338 if (rule == null || !canManageAutomaticZenRule(rule)) { 339 throw new SecurityException( 340 "Cannot update rules not owned by your condition provider"); 341 } 342 } 343 populateZenRule(automaticZenRule, rule, false); 344 newConfig.automaticRules.put(ruleId, rule); 345 return setConfigLocked(newConfig, reason, true); 346 } 347 } 348 removeAutomaticZenRule(String id, String reason)349 public boolean removeAutomaticZenRule(String id, String reason) { 350 ZenModeConfig newConfig; 351 synchronized (mConfig) { 352 if (mConfig == null) return false; 353 newConfig = mConfig.copy(); 354 ZenRule rule = newConfig.automaticRules.get(id); 355 if (rule == null) return false; 356 if (canManageAutomaticZenRule(rule)) { 357 newConfig.automaticRules.remove(id); 358 if (DEBUG) Log.d(TAG, "removeZenRule zenRule=" + id + " reason=" + reason); 359 } else { 360 throw new SecurityException( 361 "Cannot delete rules not owned by your condition provider"); 362 } 363 return setConfigLocked(newConfig, reason, true); 364 } 365 } 366 removeAutomaticZenRules(String packageName, String reason)367 public boolean removeAutomaticZenRules(String packageName, String reason) { 368 ZenModeConfig newConfig; 369 synchronized (mConfig) { 370 if (mConfig == null) return false; 371 newConfig = mConfig.copy(); 372 for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) { 373 ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i)); 374 if (rule.component.getPackageName().equals(packageName) 375 && canManageAutomaticZenRule(rule)) { 376 newConfig.automaticRules.removeAt(i); 377 } 378 } 379 return setConfigLocked(newConfig, reason, true); 380 } 381 } 382 getCurrentInstanceCount(ComponentName owner)383 public int getCurrentInstanceCount(ComponentName owner) { 384 int count = 0; 385 synchronized (mConfig) { 386 for (ZenRule rule : mConfig.automaticRules.values()) { 387 if (rule.component != null && rule.component.equals(owner)) { 388 count++; 389 } 390 } 391 } 392 return count; 393 } 394 canManageAutomaticZenRule(ZenRule rule)395 public boolean canManageAutomaticZenRule(ZenRule rule) { 396 final int callingUid = Binder.getCallingUid(); 397 if (callingUid == 0 || callingUid == Process.SYSTEM_UID) { 398 return true; 399 } else if (mContext.checkCallingPermission(android.Manifest.permission.MANAGE_NOTIFICATIONS) 400 == PackageManager.PERMISSION_GRANTED) { 401 return true; 402 } else { 403 String[] packages = mPm.getPackagesForUid(Binder.getCallingUid()); 404 if (packages != null) { 405 final int packageCount = packages.length; 406 for (int i = 0; i < packageCount; i++) { 407 if (packages[i].equals(rule.component.getPackageName())) { 408 return true; 409 } 410 } 411 } 412 return false; 413 } 414 } 415 setDefaultZenRules(Context context)416 public void setDefaultZenRules(Context context) { 417 mDefaultConfig = readDefaultConfig(context.getResources()); 418 appendDefaultRules(mDefaultConfig); 419 } 420 appendDefaultRules(ZenModeConfig config)421 private void appendDefaultRules (ZenModeConfig config) { 422 getDefaultRuleNames(); 423 appendDefaultEveryNightRule(config); 424 appendDefaultEventRules(config); 425 } 426 427 // Checks zen rule properties are the same (doesn't check creation time, name nor enabled) 428 // used to check if default rules were customized or not ruleValuesEqual(AutomaticZenRule rule, ZenRule defaultRule)429 private boolean ruleValuesEqual(AutomaticZenRule rule, ZenRule defaultRule) { 430 if (rule == null || defaultRule == null) { 431 return false; 432 } 433 return rule.getInterruptionFilter() == 434 NotificationManager.zenModeToInterruptionFilter(defaultRule.zenMode) 435 && rule.getConditionId().equals(defaultRule.conditionId) 436 && rule.getOwner().equals(defaultRule.component); 437 } 438 updateDefaultZenRules()439 protected void updateDefaultZenRules() { 440 ZenModeConfig configDefaultRules = new ZenModeConfig(); 441 appendDefaultRules(configDefaultRules); // "new" localized default rules 442 for (String ruleId : ZenModeConfig.DEFAULT_RULE_IDS) { 443 AutomaticZenRule currRule = getAutomaticZenRule(ruleId); 444 ZenRule defaultRule = configDefaultRules.automaticRules.get(ruleId); 445 // if default rule wasn't customized, use localized name instead of previous 446 if (ruleValuesEqual(currRule, defaultRule) && 447 !defaultRule.name.equals(currRule.getName())) { 448 if (canManageAutomaticZenRule(defaultRule)) { 449 if (DEBUG) Slog.d(TAG, "Locale change - updating default zen rule name " 450 + "from " + currRule.getName() + " to " + defaultRule.name); 451 // update default rule (if locale changed, name of rule will change) 452 AutomaticZenRule defaultAutoRule = createAutomaticZenRule(defaultRule); 453 // ensure enabled state is carried over from current rule 454 defaultAutoRule.setEnabled(currRule.isEnabled()); 455 updateAutomaticZenRule(ruleId, defaultAutoRule, 456 "locale changed"); 457 } 458 } 459 } 460 } 461 isSystemRule(AutomaticZenRule rule)462 private boolean isSystemRule(AutomaticZenRule rule) { 463 return ZenModeConfig.SYSTEM_AUTHORITY.equals(rule.getOwner().getPackageName()); 464 } 465 getServiceInfo(ComponentName owner)466 private ServiceInfo getServiceInfo(ComponentName owner) { 467 Intent queryIntent = new Intent(); 468 queryIntent.setComponent(owner); 469 List<ResolveInfo> installedServices = mPm.queryIntentServicesAsUser( 470 queryIntent, 471 PackageManager.GET_SERVICES | PackageManager.GET_META_DATA, 472 UserHandle.getCallingUserId()); 473 if (installedServices != null) { 474 for (int i = 0, count = installedServices.size(); i < count; i++) { 475 ResolveInfo resolveInfo = installedServices.get(i); 476 ServiceInfo info = resolveInfo.serviceInfo; 477 if (mServiceConfig.bindPermission.equals(info.permission)) { 478 return info; 479 } 480 } 481 } 482 return null; 483 } 484 populateZenRule(AutomaticZenRule automaticZenRule, ZenRule rule, boolean isNew)485 private void populateZenRule(AutomaticZenRule automaticZenRule, ZenRule rule, boolean isNew) { 486 if (isNew) { 487 rule.id = ZenModeConfig.newRuleId(); 488 rule.creationTime = System.currentTimeMillis(); 489 rule.component = automaticZenRule.getOwner(); 490 } 491 492 if (rule.enabled != automaticZenRule.isEnabled()) { 493 rule.snoozing = false; 494 } 495 rule.name = automaticZenRule.getName(); 496 rule.condition = null; 497 rule.conditionId = automaticZenRule.getConditionId(); 498 rule.enabled = automaticZenRule.isEnabled(); 499 rule.zenMode = NotificationManager.zenModeFromInterruptionFilter( 500 automaticZenRule.getInterruptionFilter(), Global.ZEN_MODE_OFF); 501 } 502 createAutomaticZenRule(ZenRule rule)503 protected AutomaticZenRule createAutomaticZenRule(ZenRule rule) { 504 return new AutomaticZenRule(rule.name, rule.component, rule.conditionId, 505 NotificationManager.zenModeToInterruptionFilter(rule.zenMode), rule.enabled, 506 rule.creationTime); 507 } 508 setManualZenMode(int zenMode, Uri conditionId, String caller, String reason)509 public void setManualZenMode(int zenMode, Uri conditionId, String caller, String reason) { 510 setManualZenMode(zenMode, conditionId, reason, caller, true /*setRingerMode*/); 511 Settings.Global.putInt(mContext.getContentResolver(), Global.SHOW_ZEN_SETTINGS_SUGGESTION, 512 0); 513 } 514 setManualZenMode(int zenMode, Uri conditionId, String reason, String caller, boolean setRingerMode)515 private void setManualZenMode(int zenMode, Uri conditionId, String reason, String caller, 516 boolean setRingerMode) { 517 ZenModeConfig newConfig; 518 synchronized (mConfig) { 519 if (mConfig == null) return; 520 if (!Global.isValidZenMode(zenMode)) return; 521 if (DEBUG) Log.d(TAG, "setManualZenMode " + Global.zenModeToString(zenMode) 522 + " conditionId=" + conditionId + " reason=" + reason 523 + " setRingerMode=" + setRingerMode); 524 newConfig = mConfig.copy(); 525 if (zenMode == Global.ZEN_MODE_OFF) { 526 newConfig.manualRule = null; 527 for (ZenRule automaticRule : newConfig.automaticRules.values()) { 528 if (automaticRule.isAutomaticActive()) { 529 automaticRule.snoozing = true; 530 } 531 } 532 } else { 533 final ZenRule newRule = new ZenRule(); 534 newRule.enabled = true; 535 newRule.zenMode = zenMode; 536 newRule.conditionId = conditionId; 537 newRule.enabler = caller; 538 newConfig.manualRule = newRule; 539 } 540 setConfigLocked(newConfig, reason, setRingerMode); 541 } 542 } 543 dump(ProtoOutputStream proto)544 void dump(ProtoOutputStream proto) { 545 proto.write(ZenModeProto.ZEN_MODE, mZenMode); 546 synchronized (mConfig) { 547 if (mConfig.manualRule != null) { 548 mConfig.manualRule.writeToProto(proto, ZenModeProto.ENABLED_ACTIVE_CONDITIONS); 549 } 550 for (ZenRule rule : mConfig.automaticRules.values()) { 551 if (rule.enabled && rule.condition.state == Condition.STATE_TRUE 552 && !rule.snoozing) { 553 rule.writeToProto(proto, ZenModeProto.ENABLED_ACTIVE_CONDITIONS); 554 } 555 } 556 mConfig.toNotificationPolicy().writeToProto(proto, ZenModeProto.POLICY); 557 proto.write(ZenModeProto.SUPPRESSED_EFFECTS, mSuppressedEffects); 558 } 559 } 560 dump(PrintWriter pw, String prefix)561 public void dump(PrintWriter pw, String prefix) { 562 pw.print(prefix); pw.print("mZenMode="); 563 pw.println(Global.zenModeToString(mZenMode)); 564 final int N = mConfigs.size(); 565 for (int i = 0; i < N; i++) { 566 dump(pw, prefix, "mConfigs[u=" + mConfigs.keyAt(i) + "]", mConfigs.valueAt(i)); 567 } 568 pw.print(prefix); pw.print("mUser="); pw.println(mUser); 569 synchronized (mConfig) { 570 dump(pw, prefix, "mConfig", mConfig); 571 } 572 573 pw.print(prefix); pw.print("mSuppressedEffects="); pw.println(mSuppressedEffects); 574 mFiltering.dump(pw, prefix); 575 mConditions.dump(pw, prefix); 576 } 577 dump(PrintWriter pw, String prefix, String var, ZenModeConfig config)578 private static void dump(PrintWriter pw, String prefix, String var, ZenModeConfig config) { 579 pw.print(prefix); pw.print(var); pw.print('='); 580 if (config == null) { 581 pw.println(config); 582 return; 583 } 584 pw.printf("allow(alarms=%b,media=%b,system=%b,calls=%b,callsFrom=%s,repeatCallers=%b," 585 + "messages=%b,messagesFrom=%s,events=%b,reminders=%b)\n", 586 config.allowAlarms, config.allowMedia, config.allowSystem, 587 config.allowCalls, ZenModeConfig.sourceToString(config.allowCallsFrom), 588 config.allowRepeatCallers, config.allowMessages, 589 ZenModeConfig.sourceToString(config.allowMessagesFrom), 590 config.allowEvents, config.allowReminders); 591 pw.printf(" disallow(visualEffects=%s)\n", config.suppressedVisualEffects); 592 pw.print(prefix); pw.print(" manualRule="); pw.println(config.manualRule); 593 if (config.automaticRules.isEmpty()) return; 594 final int N = config.automaticRules.size(); 595 for (int i = 0; i < N; i++) { 596 pw.print(prefix); pw.print(i == 0 ? " automaticRules=" : " "); 597 pw.println(config.automaticRules.valueAt(i)); 598 } 599 } 600 readXml(XmlPullParser parser, boolean forRestore)601 public void readXml(XmlPullParser parser, boolean forRestore) 602 throws XmlPullParserException, IOException { 603 ZenModeConfig config = ZenModeConfig.readXml(parser); 604 String reason = "readXml"; 605 606 if (config != null) { 607 if (forRestore) { 608 //TODO: http://b/22388012 609 if (config.user != UserHandle.USER_SYSTEM) { 610 return; 611 } 612 config.manualRule = null; // don't restore the manual rule 613 } 614 615 boolean resetToDefaultRules = true; 616 long time = System.currentTimeMillis(); 617 if (config.automaticRules != null && config.automaticRules.size() > 0) { 618 for (ZenRule automaticRule : config.automaticRules.values()) { 619 if (forRestore) { 620 // don't restore transient state from restored automatic rules 621 automaticRule.snoozing = false; 622 automaticRule.condition = null; 623 automaticRule.creationTime = time; 624 } 625 resetToDefaultRules &= !automaticRule.enabled; 626 } 627 } 628 629 if (config.version < ZenModeConfig.XML_VERSION || forRestore) { 630 Settings.Global.putInt(mContext.getContentResolver(), 631 Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 1); 632 633 // resets zen automatic rules to default 634 // if all prev auto rules were disabled on update 635 if (resetToDefaultRules) { 636 config.automaticRules = new ArrayMap<>(); 637 appendDefaultRules(config); 638 reason += ", reset to default rules"; 639 } 640 } else { 641 // devices not restoring/upgrading already have updated zen settings 642 Settings.Global.putInt(mContext.getContentResolver(), 643 Global.ZEN_SETTINGS_UPDATED, 1); 644 } 645 if (DEBUG) Log.d(TAG, reason); 646 synchronized (mConfig) { 647 setConfigLocked(config, reason); 648 } 649 } 650 } 651 writeXml(XmlSerializer out, boolean forBackup, Integer version)652 public void writeXml(XmlSerializer out, boolean forBackup, Integer version) throws IOException { 653 final int N = mConfigs.size(); 654 for (int i = 0; i < N; i++) { 655 //TODO: http://b/22388012 656 if (forBackup && mConfigs.keyAt(i) != UserHandle.USER_SYSTEM) { 657 continue; 658 } 659 mConfigs.valueAt(i).writeXml(out, version); 660 } 661 } 662 getNotificationPolicy()663 public Policy getNotificationPolicy() { 664 return getNotificationPolicy(mConfig); 665 } 666 getNotificationPolicy(ZenModeConfig config)667 private static Policy getNotificationPolicy(ZenModeConfig config) { 668 return config == null ? null : config.toNotificationPolicy(); 669 } 670 setNotificationPolicy(Policy policy)671 public void setNotificationPolicy(Policy policy) { 672 if (policy == null || mConfig == null) return; 673 synchronized (mConfig) { 674 final ZenModeConfig newConfig = mConfig.copy(); 675 newConfig.applyNotificationPolicy(policy); 676 setConfigLocked(newConfig, "setNotificationPolicy"); 677 } 678 } 679 680 /** 681 * Removes old rule instances whose owner is not installed. 682 */ cleanUpZenRules()683 private void cleanUpZenRules() { 684 long currentTime = System.currentTimeMillis(); 685 synchronized (mConfig) { 686 final ZenModeConfig newConfig = mConfig.copy(); 687 if (newConfig.automaticRules != null) { 688 for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) { 689 ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i)); 690 if (RULE_INSTANCE_GRACE_PERIOD < (currentTime - rule.creationTime)) { 691 try { 692 mPm.getPackageInfo(rule.component.getPackageName(), 693 PackageManager.MATCH_ANY_USER); 694 } catch (PackageManager.NameNotFoundException e) { 695 newConfig.automaticRules.removeAt(i); 696 } 697 } 698 } 699 } 700 setConfigLocked(newConfig, "cleanUpZenRules"); 701 } 702 } 703 704 /** 705 * @return a copy of the zen mode configuration 706 */ getConfig()707 public ZenModeConfig getConfig() { 708 synchronized (mConfig) { 709 return mConfig.copy(); 710 } 711 } 712 setConfigLocked(ZenModeConfig config, String reason)713 public boolean setConfigLocked(ZenModeConfig config, String reason) { 714 return setConfigLocked(config, reason, true /*setRingerMode*/); 715 } 716 setConfig(ZenModeConfig config, String reason)717 public void setConfig(ZenModeConfig config, String reason) { 718 synchronized (mConfig) { 719 setConfigLocked(config, reason); 720 } 721 } 722 setConfigLocked(ZenModeConfig config, String reason, boolean setRingerMode)723 private boolean setConfigLocked(ZenModeConfig config, String reason, boolean setRingerMode) { 724 final long identity = Binder.clearCallingIdentity(); 725 try { 726 if (config == null || !config.isValid()) { 727 Log.w(TAG, "Invalid config in setConfigLocked; " + config); 728 return false; 729 } 730 if (config.user != mUser) { 731 // simply store away for background users 732 mConfigs.put(config.user, config); 733 if (DEBUG) Log.d(TAG, "setConfigLocked: store config for user " + config.user); 734 return true; 735 } 736 mConditions.evaluateConfig(config, false /*processSubscriptions*/); // may modify config 737 mConfigs.put(config.user, config); 738 if (DEBUG) Log.d(TAG, "setConfigLocked reason=" + reason, new Throwable()); 739 ZenLog.traceConfig(reason, mConfig, config); 740 final boolean policyChanged = !Objects.equals(getNotificationPolicy(mConfig), 741 getNotificationPolicy(config)); 742 if (!config.equals(mConfig)) { 743 dispatchOnConfigChanged(); 744 } 745 if (policyChanged) { 746 dispatchOnPolicyChanged(); 747 } 748 mConfig = config; 749 mHandler.postApplyConfig(config, reason, setRingerMode); 750 return true; 751 } catch (SecurityException e) { 752 Log.wtf(TAG, "Invalid rule in config", e); 753 return false; 754 } finally { 755 Binder.restoreCallingIdentity(identity); 756 } 757 } 758 applyConfig(ZenModeConfig config, String reason, boolean setRingerMode)759 private void applyConfig(ZenModeConfig config, String reason, boolean setRingerMode) { 760 final String val = Integer.toString(config.hashCode()); 761 Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_CONFIG_ETAG, val); 762 if (!evaluateZenMode(reason, setRingerMode)) { 763 applyRestrictions(); // evaluateZenMode will also apply restrictions if changed 764 } 765 mConditions.evaluateConfig(config, true /*processSubscriptions*/); 766 } 767 getZenModeSetting()768 private int getZenModeSetting() { 769 return Global.getInt(mContext.getContentResolver(), Global.ZEN_MODE, Global.ZEN_MODE_OFF); 770 } 771 772 @VisibleForTesting setZenModeSetting(int zen)773 protected void setZenModeSetting(int zen) { 774 Global.putInt(mContext.getContentResolver(), Global.ZEN_MODE, zen); 775 showZenUpgradeNotification(zen); 776 } 777 getPreviousRingerModeSetting()778 private int getPreviousRingerModeSetting() { 779 return Global.getInt(mContext.getContentResolver(), 780 Global.ZEN_MODE_RINGER_LEVEL, AudioManager.RINGER_MODE_NORMAL); 781 } 782 setPreviousRingerModeSetting(Integer previousRingerLevel)783 private void setPreviousRingerModeSetting(Integer previousRingerLevel) { 784 Global.putString( 785 mContext.getContentResolver(), Global.ZEN_MODE_RINGER_LEVEL, 786 previousRingerLevel == null ? null : Integer.toString(previousRingerLevel)); 787 } 788 789 @VisibleForTesting evaluateZenMode(String reason, boolean setRingerMode)790 protected boolean evaluateZenMode(String reason, boolean setRingerMode) { 791 if (DEBUG) Log.d(TAG, "evaluateZenMode"); 792 final int zenBefore = mZenMode; 793 final int zen = computeZenMode(); 794 ZenLog.traceSetZenMode(zen, reason); 795 mZenMode = zen; 796 setZenModeSetting(mZenMode); 797 updateRingerModeAffectedStreams(); 798 if (setRingerMode && zen != zenBefore) { 799 applyZenToRingerMode(); 800 } 801 applyRestrictions(); 802 if (zen != zenBefore) { 803 mHandler.postDispatchOnZenModeChanged(); 804 } 805 return true; 806 } 807 updateRingerModeAffectedStreams()808 private void updateRingerModeAffectedStreams() { 809 if (mAudioManager != null) { 810 mAudioManager.updateRingerModeAffectedStreamsInternal(); 811 } 812 } 813 computeZenMode()814 private int computeZenMode() { 815 if (mConfig == null) return Global.ZEN_MODE_OFF; 816 synchronized (mConfig) { 817 if (mConfig.manualRule != null) return mConfig.manualRule.zenMode; 818 int zen = Global.ZEN_MODE_OFF; 819 for (ZenRule automaticRule : mConfig.automaticRules.values()) { 820 if (automaticRule.isAutomaticActive()) { 821 if (zenSeverity(automaticRule.zenMode) > zenSeverity(zen)) { 822 // automatic rule triggered dnd and user hasn't seen update dnd dialog 823 if (Settings.Global.getInt(mContext.getContentResolver(), 824 Global.ZEN_SETTINGS_SUGGESTION_VIEWED, 1) == 0) { 825 Settings.Global.putInt(mContext.getContentResolver(), 826 Global.SHOW_ZEN_SETTINGS_SUGGESTION, 1); 827 } 828 zen = automaticRule.zenMode; 829 } 830 } 831 } 832 return zen; 833 } 834 } 835 getDefaultRuleNames()836 private void getDefaultRuleNames() { 837 // on locale-change, these values differ 838 mDefaultRuleEveryNightName = mContext.getResources() 839 .getString(R.string.zen_mode_default_every_night_name); 840 mDefaultRuleEventsName = mContext.getResources() 841 .getString(R.string.zen_mode_default_events_name); 842 } 843 844 @VisibleForTesting applyRestrictions()845 protected void applyRestrictions() { 846 final boolean zenPriorityOnly = mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; 847 final boolean zenSilence = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS; 848 final boolean zenAlarmsOnly = mZenMode == Global.ZEN_MODE_ALARMS; 849 850 // notification restrictions 851 final boolean muteNotifications = 852 (mSuppressedEffects & SUPPRESSED_EFFECT_NOTIFICATIONS) != 0; 853 // call restrictions 854 final boolean muteCalls = zenAlarmsOnly 855 || (zenPriorityOnly && !mConfig.allowCalls && !mConfig.allowRepeatCallers) 856 || (mSuppressedEffects & SUPPRESSED_EFFECT_CALLS) != 0; 857 // alarm restrictions 858 final boolean muteAlarms = zenPriorityOnly && !mConfig.allowAlarms; 859 // media restrictions 860 final boolean muteMedia = zenPriorityOnly && !mConfig.allowMedia; 861 // system restrictions 862 final boolean muteSystem = zenAlarmsOnly || (zenPriorityOnly && !mConfig.allowSystem); 863 // total silence restrictions 864 final boolean muteEverything = zenSilence 865 || (zenPriorityOnly && ZenModeConfig.areAllZenBehaviorSoundsMuted(mConfig)); 866 867 for (int usage : AudioAttributes.SDK_USAGES) { 868 final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage); 869 if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NEVER) { 870 applyRestrictions(false /*mute*/, usage); 871 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NOTIFICATION) { 872 applyRestrictions(muteNotifications || muteEverything, usage); 873 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_CALL) { 874 applyRestrictions(muteCalls || muteEverything, usage); 875 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_ALARM) { 876 applyRestrictions(muteAlarms || muteEverything, usage); 877 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_MEDIA) { 878 applyRestrictions(muteMedia || muteEverything, usage); 879 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_SYSTEM) { 880 if (usage == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) { 881 // normally DND will only restrict touch sounds, not haptic feedback/vibrations 882 applyRestrictions(muteSystem || muteEverything, usage, 883 AppOpsManager.OP_PLAY_AUDIO); 884 applyRestrictions(false, usage, AppOpsManager.OP_VIBRATE); 885 } else { 886 applyRestrictions(muteSystem || muteEverything, usage); 887 } 888 } else { 889 applyRestrictions(muteEverything, usage); 890 } 891 } 892 } 893 894 895 @VisibleForTesting applyRestrictions(boolean mute, int usage, int code)896 protected void applyRestrictions(boolean mute, int usage, int code) { 897 final String[] exceptionPackages = null; // none (for now) 898 899 // Only do this if we are executing within the system process... otherwise 900 // we are running as test code, so don't have access to the protected call. 901 if (Process.myUid() == Process.SYSTEM_UID) { 902 final long ident = Binder.clearCallingIdentity(); 903 try { 904 mAppOps.setRestriction(code, usage, 905 mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED, 906 exceptionPackages); 907 } finally { 908 Binder.restoreCallingIdentity(ident); 909 } 910 } 911 } 912 913 @VisibleForTesting applyRestrictions(boolean mute, int usage)914 protected void applyRestrictions(boolean mute, int usage) { 915 applyRestrictions(mute, usage, AppOpsManager.OP_VIBRATE); 916 applyRestrictions(mute, usage, AppOpsManager.OP_PLAY_AUDIO); 917 } 918 919 920 @VisibleForTesting applyZenToRingerMode()921 protected void applyZenToRingerMode() { 922 if (mAudioManager == null) return; 923 // force the ringer mode into compliance 924 final int ringerModeInternal = mAudioManager.getRingerModeInternal(); 925 int newRingerModeInternal = ringerModeInternal; 926 switch (mZenMode) { 927 case Global.ZEN_MODE_NO_INTERRUPTIONS: 928 case Global.ZEN_MODE_ALARMS: 929 if (ringerModeInternal != AudioManager.RINGER_MODE_SILENT) { 930 setPreviousRingerModeSetting(ringerModeInternal); 931 newRingerModeInternal = AudioManager.RINGER_MODE_SILENT; 932 } 933 break; 934 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: 935 // do not apply zen to ringer, streams zen muted in AudioService 936 break; 937 case Global.ZEN_MODE_OFF: 938 if (ringerModeInternal == AudioManager.RINGER_MODE_SILENT) { 939 newRingerModeInternal = getPreviousRingerModeSetting(); 940 setPreviousRingerModeSetting(null); 941 } 942 break; 943 } 944 if (newRingerModeInternal != -1) { 945 mAudioManager.setRingerModeInternal(newRingerModeInternal, TAG); 946 } 947 } 948 dispatchOnConfigChanged()949 private void dispatchOnConfigChanged() { 950 for (Callback callback : mCallbacks) { 951 callback.onConfigChanged(); 952 } 953 } 954 dispatchOnPolicyChanged()955 private void dispatchOnPolicyChanged() { 956 for (Callback callback : mCallbacks) { 957 callback.onPolicyChanged(); 958 } 959 } 960 dispatchOnZenModeChanged()961 private void dispatchOnZenModeChanged() { 962 for (Callback callback : mCallbacks) { 963 callback.onZenModeChanged(); 964 } 965 } 966 readDefaultConfig(Resources resources)967 private ZenModeConfig readDefaultConfig(Resources resources) { 968 XmlResourceParser parser = null; 969 try { 970 parser = resources.getXml(R.xml.default_zen_mode_config); 971 while (parser.next() != XmlPullParser.END_DOCUMENT) { 972 final ZenModeConfig config = ZenModeConfig.readXml(parser); 973 if (config != null) return config; 974 } 975 } catch (Exception e) { 976 Log.w(TAG, "Error reading default zen mode config from resource", e); 977 } finally { 978 IoUtils.closeQuietly(parser); 979 } 980 return new ZenModeConfig(); 981 } 982 appendDefaultEveryNightRule(ZenModeConfig config)983 private void appendDefaultEveryNightRule(ZenModeConfig config) { 984 if (config == null) return; 985 986 final ScheduleInfo weeknights = new ScheduleInfo(); 987 weeknights.days = ZenModeConfig.ALL_DAYS; 988 weeknights.startHour = 22; 989 weeknights.endHour = 7; 990 weeknights.exitAtAlarm = true; 991 final ZenRule rule = new ZenRule(); 992 rule.enabled = false; 993 rule.name = mDefaultRuleEveryNightName; 994 rule.conditionId = ZenModeConfig.toScheduleConditionId(weeknights); 995 rule.zenMode = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; 996 rule.component = ScheduleConditionProvider.COMPONENT; 997 rule.id = ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID; 998 rule.creationTime = System.currentTimeMillis(); 999 config.automaticRules.put(rule.id, rule); 1000 } 1001 appendDefaultEventRules(ZenModeConfig config)1002 private void appendDefaultEventRules(ZenModeConfig config) { 1003 if (config == null) return; 1004 1005 final EventInfo events = new EventInfo(); 1006 events.calendar = null; // any calendar 1007 events.reply = EventInfo.REPLY_YES_OR_MAYBE; 1008 final ZenRule rule = new ZenRule(); 1009 rule.enabled = false; 1010 rule.name = mDefaultRuleEventsName; 1011 rule.conditionId = ZenModeConfig.toEventConditionId(events); 1012 rule.zenMode = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; 1013 rule.component = EventConditionProvider.COMPONENT; 1014 rule.id = ZenModeConfig.EVENTS_DEFAULT_RULE_ID; 1015 rule.creationTime = System.currentTimeMillis(); 1016 config.automaticRules.put(rule.id, rule); 1017 } 1018 zenSeverity(int zen)1019 private static int zenSeverity(int zen) { 1020 switch (zen) { 1021 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: return 1; 1022 case Global.ZEN_MODE_ALARMS: return 2; 1023 case Global.ZEN_MODE_NO_INTERRUPTIONS: return 3; 1024 default: return 0; 1025 } 1026 } 1027 1028 @VisibleForTesting 1029 protected final class RingerModeDelegate implements AudioManagerInternal.RingerModeDelegate { 1030 @Override toString()1031 public String toString() { 1032 return TAG; 1033 } 1034 1035 @Override onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, String caller, int ringerModeExternal, VolumePolicy policy)1036 public int onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, String caller, 1037 int ringerModeExternal, VolumePolicy policy) { 1038 final boolean isChange = ringerModeOld != ringerModeNew; 1039 1040 int ringerModeExternalOut = ringerModeNew; 1041 1042 if (mZenMode == Global.ZEN_MODE_OFF 1043 || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS 1044 && !ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(mConfig))) { 1045 // in priority only with ringer not muted, save ringer mode changes 1046 // in dnd off, save ringer mode changes 1047 setPreviousRingerModeSetting(ringerModeNew); 1048 } 1049 int newZen = -1; 1050 switch (ringerModeNew) { 1051 case AudioManager.RINGER_MODE_SILENT: 1052 if (isChange && policy.doNotDisturbWhenSilent) { 1053 if (mZenMode == Global.ZEN_MODE_OFF) { 1054 newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; 1055 } 1056 setPreviousRingerModeSetting(ringerModeOld); 1057 } 1058 break; 1059 case AudioManager.RINGER_MODE_VIBRATE: 1060 case AudioManager.RINGER_MODE_NORMAL: 1061 if (isChange && ringerModeOld == AudioManager.RINGER_MODE_SILENT 1062 && (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS 1063 || mZenMode == Global.ZEN_MODE_ALARMS 1064 || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS 1065 && ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted( 1066 mConfig)))) { 1067 newZen = Global.ZEN_MODE_OFF; 1068 } else if (mZenMode != Global.ZEN_MODE_OFF) { 1069 ringerModeExternalOut = AudioManager.RINGER_MODE_SILENT; 1070 } 1071 break; 1072 } 1073 1074 if (newZen != -1) { 1075 setManualZenMode(newZen, null, "ringerModeInternal", null, 1076 false /*setRingerMode*/); 1077 } 1078 if (isChange || newZen != -1 || ringerModeExternal != ringerModeExternalOut) { 1079 ZenLog.traceSetRingerModeInternal(ringerModeOld, ringerModeNew, caller, 1080 ringerModeExternal, ringerModeExternalOut); 1081 } 1082 return ringerModeExternalOut; 1083 } 1084 1085 @Override onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller, int ringerModeInternal, VolumePolicy policy)1086 public int onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller, 1087 int ringerModeInternal, VolumePolicy policy) { 1088 int ringerModeInternalOut = ringerModeNew; 1089 final boolean isChange = ringerModeOld != ringerModeNew; 1090 final boolean isVibrate = ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE; 1091 1092 int newZen = -1; 1093 switch (ringerModeNew) { 1094 case AudioManager.RINGER_MODE_SILENT: 1095 if (isChange) { 1096 if (mZenMode == Global.ZEN_MODE_OFF) { 1097 newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; 1098 } 1099 ringerModeInternalOut = isVibrate ? AudioManager.RINGER_MODE_VIBRATE 1100 : AudioManager.RINGER_MODE_SILENT; 1101 } else { 1102 ringerModeInternalOut = ringerModeInternal; 1103 } 1104 break; 1105 case AudioManager.RINGER_MODE_VIBRATE: 1106 case AudioManager.RINGER_MODE_NORMAL: 1107 if (mZenMode != Global.ZEN_MODE_OFF) { 1108 newZen = Global.ZEN_MODE_OFF; 1109 } 1110 break; 1111 } 1112 if (newZen != -1) { 1113 setManualZenMode(newZen, null, "ringerModeExternal", caller, 1114 false /*setRingerMode*/); 1115 } 1116 1117 ZenLog.traceSetRingerModeExternal(ringerModeOld, ringerModeNew, caller, 1118 ringerModeInternal, ringerModeInternalOut); 1119 return ringerModeInternalOut; 1120 } 1121 1122 @Override canVolumeDownEnterSilent()1123 public boolean canVolumeDownEnterSilent() { 1124 return mZenMode == Global.ZEN_MODE_OFF; 1125 } 1126 1127 @Override getRingerModeAffectedStreams(int streams)1128 public int getRingerModeAffectedStreams(int streams) { 1129 // ringtone and notification streams are always affected by ringer mode 1130 // system stream is affected by ringer mode when not in priority-only 1131 streams |= (1 << AudioSystem.STREAM_RING) | 1132 (1 << AudioSystem.STREAM_NOTIFICATION) | 1133 (1 << AudioSystem.STREAM_SYSTEM); 1134 1135 if (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) { 1136 // alarm and music streams affected by ringer mode when in total silence 1137 streams |= (1 << AudioSystem.STREAM_ALARM) | 1138 (1 << AudioSystem.STREAM_MUSIC); 1139 } else { 1140 streams &= ~((1 << AudioSystem.STREAM_ALARM) | 1141 (1 << AudioSystem.STREAM_MUSIC)); 1142 } 1143 1144 if (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS 1145 && ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(mConfig)) { 1146 // system stream is not affected by ringer mode in priority only when the ringer 1147 // is zen muted (all other notification categories are muted) 1148 streams &= ~(1 << AudioSystem.STREAM_SYSTEM); 1149 } else { 1150 streams |= (1 << AudioSystem.STREAM_SYSTEM); 1151 } 1152 return streams; 1153 } 1154 } 1155 1156 private final class SettingsObserver extends ContentObserver { 1157 private final Uri ZEN_MODE = Global.getUriFor(Global.ZEN_MODE); 1158 SettingsObserver(Handler handler)1159 public SettingsObserver(Handler handler) { 1160 super(handler); 1161 } 1162 observe()1163 public void observe() { 1164 final ContentResolver resolver = mContext.getContentResolver(); 1165 resolver.registerContentObserver(ZEN_MODE, false /*notifyForDescendents*/, this); 1166 update(null); 1167 } 1168 1169 @Override onChange(boolean selfChange, Uri uri)1170 public void onChange(boolean selfChange, Uri uri) { 1171 update(uri); 1172 } 1173 update(Uri uri)1174 public void update(Uri uri) { 1175 if (ZEN_MODE.equals(uri)) { 1176 if (mZenMode != getZenModeSetting()) { 1177 if (DEBUG) Log.d(TAG, "Fixing zen mode setting"); 1178 setZenModeSetting(mZenMode); 1179 } 1180 } 1181 } 1182 } 1183 showZenUpgradeNotification(int zen)1184 private void showZenUpgradeNotification(int zen) { 1185 final boolean showNotification = mIsBootComplete 1186 && zen != Global.ZEN_MODE_OFF 1187 && Settings.Global.getInt(mContext.getContentResolver(), 1188 Settings.Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0; 1189 1190 if (showNotification) { 1191 mNotificationManager.notify(TAG, SystemMessage.NOTE_ZEN_UPGRADE, 1192 createZenUpgradeNotification()); 1193 Settings.Global.putInt(mContext.getContentResolver(), 1194 Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 0); 1195 } 1196 } 1197 1198 @VisibleForTesting createZenUpgradeNotification()1199 protected Notification createZenUpgradeNotification() { 1200 final Bundle extras = new Bundle(); 1201 extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, 1202 mContext.getResources().getString(R.string.global_action_settings)); 1203 int title = R.string.zen_upgrade_notification_title; 1204 int content = R.string.zen_upgrade_notification_content; 1205 int drawable = R.drawable.ic_zen_24dp; 1206 if (NotificationManager.Policy.areAllVisualEffectsSuppressed( 1207 getNotificationPolicy().suppressedVisualEffects)) { 1208 title = R.string.zen_upgrade_notification_visd_title; 1209 content = R.string.zen_upgrade_notification_visd_content; 1210 drawable = R.drawable.ic_dnd_block_notifications; 1211 } 1212 1213 Intent onboardingIntent = new Intent(Settings.ZEN_MODE_ONBOARDING); 1214 onboardingIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 1215 return new Notification.Builder(mContext, SystemNotificationChannels.DO_NOT_DISTURB) 1216 .setAutoCancel(true) 1217 .setSmallIcon(R.drawable.ic_settings_24dp) 1218 .setLargeIcon(Icon.createWithResource(mContext, drawable)) 1219 .setContentTitle(mContext.getResources().getString(title)) 1220 .setContentText(mContext.getResources().getString(content)) 1221 .setContentIntent(PendingIntent.getActivity(mContext, 0, onboardingIntent, 1222 PendingIntent.FLAG_UPDATE_CURRENT)) 1223 .setAutoCancel(true) 1224 .setLocalOnly(true) 1225 .addExtras(extras) 1226 .setStyle(new Notification.BigTextStyle()) 1227 .build(); 1228 } 1229 1230 private final class Metrics extends Callback { 1231 private static final String COUNTER_PREFIX = "dnd_mode_"; 1232 private static final long MINIMUM_LOG_PERIOD_MS = 60 * 1000; 1233 1234 private int mPreviousZenMode = -1; 1235 private long mBeginningMs = 0L; 1236 1237 @Override onZenModeChanged()1238 void onZenModeChanged() { 1239 emit(); 1240 } 1241 emit()1242 private void emit() { 1243 mHandler.postMetricsTimer(); 1244 final long now = SystemClock.elapsedRealtime(); 1245 final long since = (now - mBeginningMs); 1246 if (mPreviousZenMode != mZenMode || since > MINIMUM_LOG_PERIOD_MS) { 1247 if (mPreviousZenMode != -1) { 1248 MetricsLogger.count(mContext, COUNTER_PREFIX + mPreviousZenMode, (int) since); 1249 } 1250 mPreviousZenMode = mZenMode; 1251 mBeginningMs = now; 1252 } 1253 } 1254 } 1255 1256 private final class H extends Handler { 1257 private static final int MSG_DISPATCH = 1; 1258 private static final int MSG_METRICS = 2; 1259 private static final int MSG_APPLY_CONFIG = 4; 1260 1261 private final class ConfigMessageData { 1262 public final ZenModeConfig config; 1263 public final String reason; 1264 public final boolean setRingerMode; 1265 ConfigMessageData(ZenModeConfig config, String reason, boolean setRingerMode)1266 ConfigMessageData(ZenModeConfig config, String reason, boolean setRingerMode) { 1267 this.config = config; 1268 this.reason = reason; 1269 this.setRingerMode = setRingerMode; 1270 } 1271 } 1272 1273 private static final long METRICS_PERIOD_MS = 6 * 60 * 60 * 1000; 1274 H(Looper looper)1275 private H(Looper looper) { 1276 super(looper); 1277 } 1278 postDispatchOnZenModeChanged()1279 private void postDispatchOnZenModeChanged() { 1280 removeMessages(MSG_DISPATCH); 1281 sendEmptyMessage(MSG_DISPATCH); 1282 } 1283 postMetricsTimer()1284 private void postMetricsTimer() { 1285 removeMessages(MSG_METRICS); 1286 sendEmptyMessageDelayed(MSG_METRICS, METRICS_PERIOD_MS); 1287 } 1288 postApplyConfig(ZenModeConfig config, String reason, boolean setRingerMode)1289 private void postApplyConfig(ZenModeConfig config, String reason, boolean setRingerMode) { 1290 sendMessage(obtainMessage(MSG_APPLY_CONFIG, 1291 new ConfigMessageData(config, reason, setRingerMode))); 1292 } 1293 1294 @Override handleMessage(Message msg)1295 public void handleMessage(Message msg) { 1296 switch (msg.what) { 1297 case MSG_DISPATCH: 1298 dispatchOnZenModeChanged(); 1299 break; 1300 case MSG_METRICS: 1301 mMetrics.emit(); 1302 break; 1303 case MSG_APPLY_CONFIG: 1304 ConfigMessageData applyConfigData = (ConfigMessageData) msg.obj; 1305 applyConfig(applyConfigData.config, applyConfigData.reason, 1306 applyConfigData.setRingerMode); 1307 } 1308 } 1309 } 1310 1311 public static class Callback { onConfigChanged()1312 void onConfigChanged() {} onZenModeChanged()1313 void onZenModeChanged() {} onPolicyChanged()1314 void onPolicyChanged() {} 1315 } 1316 1317 } 1318