Home | History | Annotate | Download | only in notification
      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 
    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 
    134     public Looper getLooper() {
    135         return mHandler.getLooper();
    136     }
    137 
    138     @Override
    139     public String toString() {
    140         return TAG;
    141     }
    142 
    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 
    151     public boolean isCall(NotificationRecord record) {
    152         return mFiltering.isCall(record);
    153     }
    154 
    155     public void recordCaller(NotificationRecord record) {
    156         mFiltering.recordCall(record);
    157     }
    158 
    159     public boolean shouldIntercept(NotificationRecord record) {
    160         synchronized (mConfig) {
    161             return mFiltering.shouldIntercept(mZenMode, mConfig, record);
    162         }
    163     }
    164 
    165     public boolean shouldSuppressWhenScreenOff() {
    166         synchronized (mConfig) {
    167             return !mConfig.allowWhenScreenOff;
    168         }
    169     }
    170 
    171     public boolean shouldSuppressWhenScreenOn() {
    172         synchronized (mConfig) {
    173             return !mConfig.allowWhenScreenOn;
    174         }
    175     }
    176 
    177     public void addCallback(Callback callback) {
    178         mCallbacks.add(callback);
    179     }
    180 
    181     public void removeCallback(Callback callback) {
    182         mCallbacks.remove(callback);
    183     }
    184 
    185     public void initZenMode() {
    186         if (DEBUG) Log.d(TAG, "initZenMode");
    187         evaluateZenMode("init", true /*setRingerMode*/);
    188     }
    189 
    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 
    202     public void onUserSwitched(int user) {
    203         loadConfigForUser(user, "onUserSwitched");
    204     }
    205 
    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 
    212     public void onUserUnlocked(int user) {
    213         loadConfigForUser(user, "onUserUnlocked");
    214     }
    215 
    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 
    232     public int getZenModeListenerInterruptionFilter() {
    233         return NotificationManager.zenModeToInterruptionFilter(mZenMode);
    234     }
    235 
    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 
    244     public void setSuppressedEffects(long suppressedEffects) {
    245         if (mSuppressedEffects == suppressedEffects) return;
    246         mSuppressedEffects = suppressedEffects;
    247         applyRestrictions();
    248     }
    249 
    250     public long getSuppressedEffects() {
    251         return mSuppressedEffects;
    252     }
    253 
    254     public int getZenMode() {
    255         return mZenMode;
    256     }
    257 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    415     private boolean isSystemRule(AutomaticZenRule rule) {
    416         return ZenModeConfig.SYSTEM_AUTHORITY.equals(rule.getOwner().getPackageName());
    417     }
    418 
    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 
    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 
    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 
    462     public void setManualZenMode(int zenMode, Uri conditionId, String caller, String reason) {
    463         setManualZenMode(zenMode, conditionId, reason, caller, true /*setRingerMode*/);
    464     }
    465 
    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 
    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 
    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 
    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 
    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 
    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 
    590     public Policy getNotificationPolicy() {
    591         return getNotificationPolicy(mConfig);
    592     }
    593 
    594     private static Policy getNotificationPolicy(ZenModeConfig config) {
    595         return config == null ? null : config.toNotificationPolicy();
    596     }
    597 
    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      */
    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      */
    634     public ZenModeConfig getConfig() {
    635         synchronized (mConfig) {
    636             return mConfig.copy();
    637         }
    638     }
    639 
    640     public boolean setConfigLocked(ZenModeConfig config, String reason) {
    641         return setConfigLocked(config, reason, true /*setRingerMode*/);
    642     }
    643 
    644     public void setConfig(ZenModeConfig config, String reason) {
    645         synchronized (mConfig) {
    646             setConfigLocked(config, reason);
    647         }
    648     }
    649 
    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 
    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 
    692     private int getZenModeSetting() {
    693         return Global.getInt(mContext.getContentResolver(), Global.ZEN_MODE, Global.ZEN_MODE_OFF);
    694     }
    695 
    696     private void setZenModeSetting(int zen) {
    697         Global.putInt(mContext.getContentResolver(), Global.ZEN_MODE, zen);
    698     }
    699 
    700     private int getPreviousRingerModeSetting() {
    701         return Global.getInt(mContext.getContentResolver(),
    702                 Global.ZEN_MODE_RINGER_LEVEL, AudioManager.RINGER_MODE_NORMAL);
    703     }
    704 
    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 
    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 
    729     private void updateRingerModeAffectedStreams() {
    730         if (mAudioManager != null) {
    731             mAudioManager.updateRingerModeAffectedStreamsInternal();
    732         }
    733     }
    734 
    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 
    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 
    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 
    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 
    813     private void dispatchOnConfigChanged() {
    814         for (Callback callback : mCallbacks) {
    815             callback.onConfigChanged();
    816         }
    817     }
    818 
    819     private void dispatchOnPolicyChanged() {
    820         for (Callback callback : mCallbacks) {
    821             callback.onPolicyChanged();
    822         }
    823     }
    824 
    825     private void dispatchOnZenModeChanged() {
    826         for (Callback callback : mCallbacks) {
    827             callback.onZenModeChanged();
    828         }
    829     }
    830 
    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 
    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 
    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 
    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
    910         public String toString() {
    911             return TAG;
    912         }
    913 
    914         @Override
    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
    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
    993         public boolean canVolumeDownEnterSilent() {
    994             return mZenMode == Global.ZEN_MODE_OFF;
    995         }
    996 
    997         @Override
    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 
   1019         public SettingsObserver(Handler handler) {
   1020             super(handler);
   1021         }
   1022 
   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
   1030         public void onChange(boolean selfChange, Uri uri) {
   1031             update(uri);
   1032         }
   1033 
   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
   1052         void onZenModeChanged() {
   1053             emit();
   1054         }
   1055 
   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 
   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 
   1089         private H(Looper looper) {
   1090             super(looper);
   1091         }
   1092 
   1093         private void postDispatchOnZenModeChanged() {
   1094             removeMessages(MSG_DISPATCH);
   1095             sendEmptyMessage(MSG_DISPATCH);
   1096         }
   1097 
   1098         private void postMetricsTimer() {
   1099             removeMessages(MSG_METRICS);
   1100             sendEmptyMessageDelayed(MSG_METRICS, METRICS_PERIOD_MS);
   1101         }
   1102 
   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
   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 {
   1126         void onConfigChanged() {}
   1127         void onZenModeChanged() {}
   1128         void onPolicyChanged() {}
   1129     }
   1130 
   1131 }
   1132