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