Android8.0 Do not disturb(DND)/Zenmode 添加一个新的模式

来源:互联网 发布:linux make安装包下载 编辑:程序博客网 时间:2024/06/08 00:01

这里添加的模式可能涉及的地方不全面,目前把已知的地方都加上。可以搜索ZEN_MODE_ALARMS来看看哪里还需要加代码。目前就改了这些地方,有些地方不知道有什么用,可能只是log信息,有些是显示的图标,根据不同模式显示不同icon。
这里写图片描述

1.在QS中添加选项
打开关闭DND是在quick settings中的,当然也可以按音量下。我们这要在QS中添加,可以按照其他dnd模式来添加代码。

先加数据库。

frameworks/base/core/java/android/provider/Settings.java

        /**         * Defines global zen mode.  ZEN_MODE_OFF, ZEN_MODE_IMPORTANT_INTERRUPTIONS,         * or ZEN_MODE_NO_INTERRUPTIONS.         *         * @hide         */        public static final String ZEN_MODE = "zen_mode";        /** @hide */ public static final int ZEN_MODE_OFF = 0;        /** @hide */ public static final int ZEN_MODE_IMPORTANT_INTERRUPTIONS = 1;        /** @hide */ public static final int ZEN_MODE_NO_INTERRUPTIONS = 2;        /** @hide */ public static final int ZEN_MODE_ALARMS = 3;        /** @hide */ public static final int ZEN_MODE_GAME = 4;        /** @hide */ public static String zenModeToString(int mode) {            if (mode == ZEN_MODE_IMPORTANT_INTERRUPTIONS) return "ZEN_MODE_IMPORTANT_INTERRUPTIONS";            if (mode == ZEN_MODE_ALARMS) return "ZEN_MODE_ALARMS";            if (mode == ZEN_MODE_NO_INTERRUPTIONS) return "ZEN_MODE_NO_INTERRUPTIONS";            if (mode == ZEN_MODE_GAME) return "ZEN_MODE_GAME";            return "ZEN_MODE_OFF";        }        /** @hide */ public static boolean isValidZenMode(int value) {            switch (value) {                case Global.ZEN_MODE_OFF:                case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:                case Global.ZEN_MODE_ALARMS:                case Global.ZEN_MODE_NO_INTERRUPTIONS:                case Global.ZEN_MODE_GAME:                    return true;                default:                    return false;            }        }

然后添加QS
frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java

    @Override    protected void handleUpdateState(BooleanState state, Object arg) {        final int zen = arg instanceof Integer ? (Integer) arg : mController.getZen();        final boolean newValue = zen != ZEN_MODE_OFF;        final boolean valueChanged = state.value != newValue;        state.dualTarget = true;        state.value = newValue;        state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;        checkIfRestrictionEnforcedByAdminOnly(state, UserManager.DISALLOW_ADJUST_VOLUME);        switch (zen) {            case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:                state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on);                state.label = mContext.getString(R.string.quick_settings_dnd_priority_label);                state.contentDescription = mContext.getString(                        R.string.accessibility_quick_settings_dnd_priority_on);                break;            case Global.ZEN_MODE_NO_INTERRUPTIONS:                state.icon = TOTAL_SILENCE;                state.label = mContext.getString(R.string.quick_settings_dnd_none_label);                state.contentDescription = mContext.getString(                        R.string.accessibility_quick_settings_dnd_none_on);                break;            case ZEN_MODE_ALARMS:                state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on);                state.label = mContext.getString(R.string.quick_settings_dnd_alarms_label);                state.contentDescription = mContext.getString(                        R.string.accessibility_quick_settings_dnd_alarms_on);                break;            case Global.ZEN_MODE_GAME:                state.icon = ResourceIcon.get(R.drawable.ic_qs_dnd_on);                state.label = mContext.getString(R.string.quick_settings_dnd_game_label);                state.contentDescription = mContext.getString(                        R.string.accessibility_quick_settings_dnd_game_on);                break;            default:                state.icon = TOTAL_SILENCE.equals(state.icon) ? mDisableTotalSilence : mDisable;                state.label = mContext.getString(R.string.quick_settings_dnd_label);                state.contentDescription = mContext.getString(                        R.string.accessibility_quick_settings_dnd);                break;        }        if (valueChanged) {            fireToggleStateChanged(state.value);        }        state.dualLabelContentDescription = mContext.getResources().getString(                R.string.accessibility_quick_settings_open_settings, getTileLabel());        state.expandedAccessibilityClassName = Switch.class.getName();    }

这里添加的是QS中显示的,也就是dnd没有展开时的。

这里写图片描述

当你点击dnd下面的那个箭头就会展开,和蓝牙类似。下面就是展开的画面。最上面的按钮就是mZenButtons,下面是第一次使用会有个介绍mZenIntroduction,就是绿色的框边上有个x关闭。
这里写图片描述

代码位置在
frameworks/base/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
这里只需要模仿其他dnd模式来添加代码。

public class ZenModePanel extends FrameLayout {    private static final String TAG = "ZenModePanel";    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);    public static final int STATE_MODIFY = 0;    public static final int STATE_AUTO_RULE = 1;    public static final int STATE_OFF = 2;    private static final int SECONDS_MS = 1000;    private static final int MINUTES_MS = 60 * SECONDS_MS;    private static final int[] MINUTE_BUCKETS = ZenModeConfig.MINUTE_BUCKETS;    private static final int MIN_BUCKET_MINUTES = MINUTE_BUCKETS[0];    private static final int MAX_BUCKET_MINUTES = MINUTE_BUCKETS[MINUTE_BUCKETS.length - 1];    private static final int DEFAULT_BUCKET_INDEX = Arrays.binarySearch(MINUTE_BUCKETS, 60);    private static final int FOREVER_CONDITION_INDEX = 0;    private static final int COUNTDOWN_CONDITION_INDEX = 1;    private static final int COUNTDOWN_ALARM_CONDITION_INDEX = 2;    private static final int COUNTDOWN_CONDITION_COUNT = 2;    public static final Intent ZEN_SETTINGS            = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);    public static final Intent ZEN_PRIORITY_SETTINGS            = new Intent(Settings.ACTION_ZEN_MODE_PRIORITY_SETTINGS);    private static final long TRANSITION_DURATION = 300;    private final Context mContext;    protected final LayoutInflater mInflater;    private final H mHandler = new H();    private final ZenPrefs mPrefs;    private final TransitionHelper mTransitionHelper = new TransitionHelper();    private final Uri mForeverId;    private final ConfigurableTexts mConfigurableTexts;    private String mTag = TAG + "/" + Integer.toHexString(System.identityHashCode(this));    protected SegmentedButtons mZenButtons;    private View mZenIntroduction;    private TextView mZenIntroductionMessage;    private View mZenIntroductionConfirm;    private TextView mZenIntroductionCustomize;    protected LinearLayout mZenConditions;    private TextView mZenAlarmWarning;    private RadioGroup mZenRadioGroup;    private LinearLayout mZenRadioGroupContent;    private Callback mCallback;    private ZenModeController mController;    private boolean mCountdownConditionSupported;    private boolean mRequestingConditions;    private Condition mExitCondition;    private int mBucketIndex = -1;    private boolean mExpanded;    private boolean mHidden;    private int mSessionZen;    private int mAttachedZen;    private boolean mAttached;    private Condition mSessionExitCondition;    private Condition[] mConditions;    private Condition mTimeCondition;    private boolean mVoiceCapable;    protected int mZenModeConditionLayoutId;    protected int mZenModeButtonLayoutId;    private View mEmpty;    private TextView mEmptyText;    private ImageView mEmptyIcon;    private View mAutoRule;    private TextView mAutoTitle;    private int mState = STATE_MODIFY;    private ViewGroup mEdit;    public ZenModePanel(Context context, AttributeSet attrs) {        super(context, attrs);        mContext = context;        mPrefs = new ZenPrefs();        mInflater = LayoutInflater.from(mContext.getApplicationContext());        mForeverId = Condition.newId(mContext).appendPath("forever").build();        mConfigurableTexts = new ConfigurableTexts(mContext);        mVoiceCapable = Util.isVoiceCapable(mContext);        mZenModeConditionLayoutId = R.layout.zen_mode_condition;        mZenModeButtonLayoutId = R.layout.zen_mode_button;        if (DEBUG) Log.d(mTag, "new ZenModePanel");    }    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {        pw.println("ZenModePanel state:");        pw.print("  mCountdownConditionSupported="); pw.println(mCountdownConditionSupported);        pw.print("  mRequestingConditions="); pw.println(mRequestingConditions);        pw.print("  mAttached="); pw.println(mAttached);        pw.print("  mHidden="); pw.println(mHidden);        pw.print("  mExpanded="); pw.println(mExpanded);        pw.print("  mSessionZen="); pw.println(mSessionZen);        pw.print("  mAttachedZen="); pw.println(mAttachedZen);        pw.print("  mConfirmedPriorityIntroduction=");        pw.println(mPrefs.mConfirmedPriorityIntroduction);        pw.print("  mConfirmedSilenceIntroduction=");        pw.println(mPrefs.mConfirmedSilenceIntroduction);        pw.print("  mVoiceCapable="); pw.println(mVoiceCapable);        mTransitionHelper.dump(fd, pw, args);    }    protected void createZenButtons() {        mZenButtons = findViewById(R.id.zen_buttons);        mZenButtons.addButton(R.string.interruption_level_none_twoline,                R.string.interruption_level_none_with_warning,                Global.ZEN_MODE_NO_INTERRUPTIONS);        mZenButtons.addButton(R.string.interruption_level_game_twoline,                R.string.interruption_level_game,                Global.ZEN_MODE_GAME);        mZenButtons.addButton(R.string.interruption_level_alarms_twoline,                R.string.interruption_level_alarms,                Global.ZEN_MODE_ALARMS);        mZenButtons.addButton(R.string.interruption_level_priority_twoline,                R.string.interruption_level_priority,                Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);        mZenButtons.setCallback(mZenButtonsCallback);    }    @Override    protected void onFinishInflate() {        super.onFinishInflate();        createZenButtons();        mZenIntroduction = findViewById(R.id.zen_introduction);        mZenIntroductionMessage = findViewById(R.id.zen_introduction_message);        mZenIntroductionConfirm = findViewById(R.id.zen_introduction_confirm);        mZenIntroductionConfirm.setOnClickListener(v -> confirmZenIntroduction());        mZenIntroductionCustomize = findViewById(R.id.zen_introduction_customize);        mZenIntroductionCustomize.setOnClickListener(v -> {            confirmZenIntroduction();            if (mCallback != null) {                mCallback.onPrioritySettings();            }        });        mConfigurableTexts.add(mZenIntroductionCustomize, R.string.zen_priority_customize_button);        mZenConditions = findViewById(R.id.zen_conditions);        mZenAlarmWarning = findViewById(R.id.zen_alarm_warning);        mZenRadioGroup = findViewById(R.id.zen_radio_buttons);        mZenRadioGroupContent = findViewById(R.id.zen_radio_buttons_content);        mEdit = findViewById(R.id.edit_container);        mEmpty = findViewById(android.R.id.empty);        mEmpty.setVisibility(INVISIBLE);        mEmptyText = mEmpty.findViewById(android.R.id.title);        mEmptyIcon = mEmpty.findViewById(android.R.id.icon);        mAutoRule = findViewById(R.id.auto_rule);        mAutoTitle = mAutoRule.findViewById(android.R.id.title);        mAutoRule.setVisibility(INVISIBLE);    }    public void setEmptyState(int icon, int text) {        mEmptyIcon.post(() -> {            mEmptyIcon.setImageResource(icon);            mEmptyText.setText(text);        });    }    public void setAutoText(CharSequence text) {        mAutoTitle.post(() -> mAutoTitle.setText(text));    }    public void setState(int state) {        if (mState == state) return;        transitionFrom(getView(mState), getView(state));        mState = state;    }    private void transitionFrom(View from, View to) {        from.post(() -> {            // TODO: Better transitions            to.setAlpha(0);            to.setVisibility(VISIBLE);            to.bringToFront();            to.animate().cancel();            to.animate().alpha(1)                    .setDuration(TRANSITION_DURATION)                    .withEndAction(() -> from.setVisibility(INVISIBLE))                    .start();        });    }    private View getView(int state) {        switch (state) {            case STATE_AUTO_RULE:                return mAutoRule;            case STATE_OFF:                return mEmpty;            default:                return mEdit;        }    }    @Override    protected void onConfigurationChanged(Configuration newConfig) {        super.onConfigurationChanged(newConfig);        mConfigurableTexts.update();        if (mZenButtons != null) {            mZenButtons.update();        }    }    private void confirmZenIntroduction() {        final String prefKey = prefKeyForConfirmation(getSelectedZen(Global.ZEN_MODE_OFF));        if (prefKey == null) return;        if (DEBUG) Log.d(TAG, "confirmZenIntroduction " + prefKey);        Prefs.putBoolean(mContext, prefKey, true);        mHandler.sendEmptyMessage(H.UPDATE_WIDGETS);    }    private static String prefKeyForConfirmation(int zen) {        switch (zen) {            case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:                return Prefs.Key.DND_CONFIRMED_PRIORITY_INTRODUCTION;            case Global.ZEN_MODE_NO_INTERRUPTIONS:                return Prefs.Key.DND_CONFIRMED_SILENCE_INTRODUCTION;            case Global.ZEN_MODE_ALARMS:                return Prefs.Key.DND_CONFIRMED_ALARM_INTRODUCTION;            case Global.ZEN_MODE_GAME:                return Prefs.Key.DND_CONFIRMED_GAME_INTRODUCTION;            default:                return null;        }    }    private void onAttach() {        setExpanded(true);        mAttached = true;        mAttachedZen = mController.getZen();        ZenRule manualRule = mController.getManualRule();        mExitCondition = manualRule != null ? manualRule.condition : null;        if (DEBUG) Log.d(mTag, "onAttach " + mAttachedZen + " " + manualRule);        handleUpdateManualRule(manualRule);        mZenButtons.setSelectedValue(mAttachedZen, false);        mSessionZen = mAttachedZen;        mTransitionHelper.clear();        mController.addCallback(mZenCallback);        setSessionExitCondition(copy(mExitCondition));        updateWidgets();        setRequestingConditions(!mHidden);        ensureSelection();    }    private void onDetach() {        if (DEBUG) Log.d(mTag, "onDetach");        setExpanded(false);        checkForAttachedZenChange();        mAttached = false;        mAttachedZen = -1;        mSessionZen = -1;        mController.removeCallback(mZenCallback);        setSessionExitCondition(null);        setRequestingConditions(false);        mTransitionHelper.clear();    }    @Override    public void onVisibilityAggregated(boolean isVisible) {        super.onVisibilityAggregated(isVisible);        if (isVisible == mAttached) return;        if (isVisible) {            onAttach();        } else {            onDetach();        }    }    private void setSessionExitCondition(Condition condition) {        if (Objects.equals(condition, mSessionExitCondition)) return;        if (DEBUG) Log.d(mTag, "mSessionExitCondition=" + getConditionId(condition));        mSessionExitCondition = condition;    }    public void setHidden(boolean hidden) {        if (mHidden == hidden) return;        if (DEBUG) Log.d(mTag, "hidden=" + hidden);        mHidden = hidden;        setRequestingConditions(mAttached && !mHidden);        updateWidgets();    }    private void checkForAttachedZenChange() {        final int selectedZen = getSelectedZen(-1);        if (DEBUG) Log.d(mTag, "selectedZen=" + selectedZen);        if (selectedZen != mAttachedZen) {            if (DEBUG) Log.d(mTag, "attachedZen: " + mAttachedZen + " -> " + selectedZen);            if (selectedZen == Global.ZEN_MODE_NO_INTERRUPTIONS) {                mPrefs.trackNoneSelected();            }        }    }    private void setExpanded(boolean expanded) {        if (expanded == mExpanded) return;        if (DEBUG) Log.d(mTag, "setExpanded " + expanded);        mExpanded = expanded;        updateWidgets();        fireExpanded();    }    /** Start or stop requesting relevant zen mode exit conditions */    private void setRequestingConditions(final boolean requesting) {        if (mRequestingConditions == requesting) return;        if (DEBUG) Log.d(mTag, "setRequestingConditions " + requesting);        mRequestingConditions = requesting;        if (mRequestingConditions) {            mTimeCondition = parseExistingTimeCondition(mContext, mExitCondition);            if (mTimeCondition != null) {                mBucketIndex = -1;            } else {                mBucketIndex = DEFAULT_BUCKET_INDEX;                mTimeCondition = ZenModeConfig.toTimeCondition(mContext,                        MINUTE_BUCKETS[mBucketIndex], ActivityManager.getCurrentUser());            }            if (DEBUG) Log.d(mTag, "Initial bucket index: " + mBucketIndex);            mConditions = null; // reset conditions            handleUpdateConditions();        } else {            hideAllConditions();        }    }    protected void addZenConditions(int count) {        for (int i = 0; i < count; i++) {            final View rb = mInflater.inflate(mZenModeButtonLayoutId, mEdit, false);            rb.setId(i);            mZenRadioGroup.addView(rb);            final View rbc = mInflater.inflate(mZenModeConditionLayoutId, mEdit, false);            rbc.setId(i + count);            mZenRadioGroupContent.addView(rbc);        }    }    public void init(ZenModeController controller) {        mController = controller;        mCountdownConditionSupported = mController.isCountdownConditionSupported();        final int countdownDelta = mCountdownConditionSupported ? COUNTDOWN_CONDITION_COUNT : 0;        final int minConditions = 1 /*forever*/ + countdownDelta;        addZenConditions(minConditions);        mSessionZen = getSelectedZen(-1);        handleUpdateManualRule(mController.getManualRule());        if (DEBUG) Log.d(mTag, "init mExitCondition=" + mExitCondition);        hideAllConditions();    }    private void setExitCondition(Condition exitCondition) {        if (Objects.equals(mExitCondition, exitCondition)) return;        mExitCondition = exitCondition;        if (DEBUG) Log.d(mTag, "mExitCondition=" + getConditionId(mExitCondition));        updateWidgets();    }    private static Uri getConditionId(Condition condition) {        return condition != null ? condition.id : null;    }    private Uri getRealConditionId(Condition condition) {        return isForever(condition) ? null : getConditionId(condition);    }    private static boolean sameConditionId(Condition lhs, Condition rhs) {        return lhs == null ? rhs == null : rhs != null && lhs.id.equals(rhs.id);    }    private static Condition copy(Condition condition) {        return condition == null ? null : condition.copy();    }    public void setCallback(Callback callback) {        mCallback = callback;    }    private void handleUpdateManualRule(ZenRule rule) {        final int zen = rule != null ? rule.zenMode : Global.ZEN_MODE_OFF;        handleUpdateZen(zen);        final Condition c = rule == null ? null                : rule.condition != null ? rule.condition                : createCondition(rule.conditionId);        handleExitConditionChanged(c);    }    private Condition createCondition(Uri conditionId) {        if (ZenModeConfig.isValidCountdownConditionId(conditionId)) {            long time = ZenModeConfig.tryParseCountdownConditionId(conditionId);            int mins = (int) ((time - System.currentTimeMillis() + DateUtils.MINUTE_IN_MILLIS / 2)                    / DateUtils.MINUTE_IN_MILLIS);            Condition c = ZenModeConfig.toTimeCondition(mContext, time, mins,                    ActivityManager.getCurrentUser(), false);            return c;        }        // If there is a manual rule, but it has no condition listed then it is forever.        return forever();    }    private void handleUpdateZen(int zen) {        if (mSessionZen != -1 && mSessionZen != zen) {            mSessionZen = zen;        }        mZenButtons.setSelectedValue(zen, false /* fromClick */);        updateWidgets();        handleUpdateConditions();        if (mExpanded) {            final Condition selected = getSelectedCondition();            if (!Objects.equals(mExitCondition, selected)) {                select(selected);            }        }    }    private void handleExitConditionChanged(Condition exitCondition) {        setExitCondition(exitCondition);        if (DEBUG) Log.d(mTag, "handleExitConditionChanged " + mExitCondition);        if (exitCondition == null) return;        final int N = getVisibleConditions();        for (int i = 0; i < N; i++) {            final ConditionTag tag = getConditionTagAt(i);            if (tag != null && sameConditionId(tag.condition, mExitCondition)) {                bind(exitCondition, mZenRadioGroupContent.getChildAt(i), i);                tag.rb.setChecked(true);                return;            }        }        if (mCountdownConditionSupported && ZenModeConfig.isValidCountdownConditionId(                exitCondition.id)) {            bind(exitCondition, mZenRadioGroupContent.getChildAt(COUNTDOWN_CONDITION_INDEX),                    COUNTDOWN_CONDITION_INDEX);            getConditionTagAt(COUNTDOWN_CONDITION_INDEX).rb.setChecked(true);        }    }    private Condition getSelectedCondition() {        final int N = getVisibleConditions();        for (int i = 0; i < N; i++) {            final ConditionTag tag = getConditionTagAt(i);            if (tag != null && tag.rb.isChecked()) {                return tag.condition;            }        }        return null;    }    private int getSelectedZen(int defValue) {        final Object zen = mZenButtons.getSelectedValue();        return zen != null ? (Integer) zen : defValue;    }    private void updateWidgets() {        if (mTransitionHelper.isTransitioning()) {            mTransitionHelper.pendingUpdateWidgets();            return;        }        final int zen = getSelectedZen(Global.ZEN_MODE_OFF);        final boolean zenImportant = zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;        final boolean zenNone = zen == Global.ZEN_MODE_NO_INTERRUPTIONS;        final boolean zenAlarm = zen == Global.ZEN_MODE_ALARMS;        final boolean zenGame = zen == Global.ZEN_MODE_GAME;        final boolean introduction = (zenImportant && !mPrefs.mConfirmedPriorityIntroduction                || zenNone && !mPrefs.mConfirmedSilenceIntroduction                || zenAlarm && !mPrefs.mConfirmedAlarmIntroduction                || zenGame && !mPrefs.mConfirmedGameIntroduction);        mZenButtons.setVisibility(mHidden ? GONE : VISIBLE);        mZenIntroduction.setVisibility(introduction ? VISIBLE : GONE);        if (introduction) {            int message = zenImportant                    ? R.string.zen_priority_introduction                    : zenAlarm                            ? R.string.zen_alarms_introduction                            : zenGame                            ? R.string.zen_game_introduction                                    : mVoiceCapable                                    ? R.string.zen_silence_introduction_voice                                                : R.string.zen_silence_introduction;            mConfigurableTexts.add(mZenIntroductionMessage, message);            mConfigurableTexts.update();            mZenIntroductionCustomize.setVisibility(zenImportant ? VISIBLE : GONE);        }        final String warning = computeAlarmWarningText(zenNone);        mZenAlarmWarning.setVisibility(warning != null ? VISIBLE : GONE);        mZenAlarmWarning.setText(warning);    }    private String computeAlarmWarningText(boolean zenNone) {        if (!zenNone) {            return null;        }        final long now = System.currentTimeMillis();        final long nextAlarm = mController.getNextAlarm();        if (nextAlarm < now) {            return null;        }        int warningRes = 0;        if (mSessionExitCondition == null || isForever(mSessionExitCondition)) {            warningRes = R.string.zen_alarm_warning_indef;        } else {            final long time = ZenModeConfig.tryParseCountdownConditionId(mSessionExitCondition.id);            if (time > now && nextAlarm < time) {                warningRes = R.string.zen_alarm_warning;            }        }        if (warningRes == 0) {            return null;        }        final boolean soon = (nextAlarm - now) < 24 * 60 * 60 * 1000;        final boolean is24 = DateFormat.is24HourFormat(mContext, ActivityManager.getCurrentUser());        final String skeleton = soon ? (is24 ? "Hm" : "hma") : (is24 ? "EEEHm" : "EEEhma");        final String pattern = DateFormat.getBestDateTimePattern(Locale.getDefault(), skeleton);        final CharSequence formattedTime = DateFormat.format(pattern, nextAlarm);        final int templateRes = soon ? R.string.alarm_template : R.string.alarm_template_far;        final String template = getResources().getString(templateRes, formattedTime);        return getResources().getString(warningRes, template);    }    private static Condition parseExistingTimeCondition(Context context, Condition condition) {        if (condition == null) return null;        final long time = ZenModeConfig.tryParseCountdownConditionId(condition.id);        if (time == 0) return null;        final long now = System.currentTimeMillis();        final long span = time - now;        if (span <= 0 || span > MAX_BUCKET_MINUTES * MINUTES_MS) return null;        return ZenModeConfig.toTimeCondition(context,                time, Math.round(span / (float) MINUTES_MS), ActivityManager.getCurrentUser(),                false /*shortVersion*/);    }    private void handleUpdateConditions() {        if (mTransitionHelper.isTransitioning()) {            return;        }        final int conditionCount = mConditions == null ? 0 : mConditions.length;        if (DEBUG) Log.d(mTag, "handleUpdateConditions conditionCount=" + conditionCount);        // forever        bind(forever(), mZenRadioGroupContent.getChildAt(FOREVER_CONDITION_INDEX),                FOREVER_CONDITION_INDEX);        // countdown        if (mCountdownConditionSupported && mTimeCondition != null) {            bind(mTimeCondition, mZenRadioGroupContent.getChildAt(COUNTDOWN_CONDITION_INDEX),                    COUNTDOWN_CONDITION_INDEX);        }        // countdown until alarm        if (mCountdownConditionSupported) {            Condition nextAlarmCondition = getTimeUntilNextAlarmCondition();            if (nextAlarmCondition != null) {                mZenRadioGroup.getChildAt(                        COUNTDOWN_ALARM_CONDITION_INDEX).setVisibility(View.VISIBLE);                mZenRadioGroupContent.getChildAt(                        COUNTDOWN_ALARM_CONDITION_INDEX).setVisibility(View.VISIBLE);                bind(nextAlarmCondition,                        mZenRadioGroupContent.getChildAt(COUNTDOWN_ALARM_CONDITION_INDEX),                        COUNTDOWN_ALARM_CONDITION_INDEX);            } else {                mZenRadioGroup.getChildAt(COUNTDOWN_ALARM_CONDITION_INDEX).setVisibility(View.GONE);                mZenRadioGroupContent.getChildAt(                        COUNTDOWN_ALARM_CONDITION_INDEX).setVisibility(View.GONE);            }        }        // ensure something is selected        if (mExpanded) {            ensureSelection();        }        mZenConditions.setVisibility(mSessionZen != Global.ZEN_MODE_OFF ? View.VISIBLE : View.GONE);    }    private Condition forever() {        return new Condition(mForeverId, foreverSummary(mContext), "", "", 0 /*icon*/,                Condition.STATE_TRUE, 0 /*flags*/);    }    private static String foreverSummary(Context context) {        return context.getString(com.android.internal.R.string.zen_mode_forever);    }    // Returns a time condition if the next alarm is within the next week.    private Condition getTimeUntilNextAlarmCondition() {        GregorianCalendar weekRange = new GregorianCalendar();        final long now = weekRange.getTimeInMillis();        setToMidnight(weekRange);        weekRange.add(Calendar.DATE, 6);        final long nextAlarmMs = mController.getNextAlarm();        if (nextAlarmMs > 0) {            GregorianCalendar nextAlarm = new GregorianCalendar();            nextAlarm.setTimeInMillis(nextAlarmMs);            setToMidnight(nextAlarm);            if (weekRange.compareTo(nextAlarm) >= 0) {                return ZenModeConfig.toTimeCondition(mContext, nextAlarmMs,                        Math.round((nextAlarmMs - now) / (float) MINUTES_MS),                        ActivityManager.getCurrentUser(), true);            }        }        return null;    }    private void setToMidnight(Calendar calendar) {        calendar.set(Calendar.HOUR_OF_DAY, 0);        calendar.set(Calendar.MINUTE, 0);        calendar.set(Calendar.SECOND, 0);        calendar.set(Calendar.MILLISECOND, 0);    }    private ConditionTag getConditionTagAt(int index) {        return (ConditionTag) mZenRadioGroupContent.getChildAt(index).getTag();    }    private int getVisibleConditions() {        int rt = 0;        final int N = mZenRadioGroupContent.getChildCount();        for (int i = 0; i < N; i++) {            rt += mZenRadioGroupContent.getChildAt(i).getVisibility() == VISIBLE ? 1 : 0;        }        return rt;    }    private void hideAllConditions() {        final int N = mZenRadioGroupContent.getChildCount();        for (int i = 0; i < N; i++) {            mZenRadioGroupContent.getChildAt(i).setVisibility(GONE);        }    }    private void ensureSelection() {        // are we left without anything selected?  if so, set a default        final int visibleConditions = getVisibleConditions();        if (visibleConditions == 0) return;        for (int i = 0; i < visibleConditions; i++) {            final ConditionTag tag = getConditionTagAt(i);            if (tag != null && tag.rb.isChecked()) {                if (DEBUG) Log.d(mTag, "Not selecting a default, checked=" + tag.condition);                return;            }        }        final ConditionTag foreverTag = getConditionTagAt(FOREVER_CONDITION_INDEX);        if (foreverTag == null) return;        if (DEBUG) Log.d(mTag, "Selecting a default");        final int favoriteIndex = mPrefs.getMinuteIndex();        if (mExitCondition != null && mExitCondition.equals(mTimeCondition)) {            getConditionTagAt(COUNTDOWN_CONDITION_INDEX).rb.setChecked(true);        } else if (favoriteIndex == -1 || !mCountdownConditionSupported ||                mAttachedZen != Global.ZEN_MODE_OFF) {            foreverTag.rb.setChecked(true);        } else {            mTimeCondition = ZenModeConfig.toTimeCondition(mContext,                    MINUTE_BUCKETS[favoriteIndex], ActivityManager.getCurrentUser());            mBucketIndex = favoriteIndex;            bind(mTimeCondition, mZenRadioGroupContent.getChildAt(COUNTDOWN_CONDITION_INDEX),                    COUNTDOWN_CONDITION_INDEX);            getConditionTagAt(COUNTDOWN_CONDITION_INDEX).rb.setChecked(true);        }    }    private static boolean isCountdown(Condition c) {        return c != null && ZenModeConfig.isValidCountdownConditionId(c.id);    }    private boolean isForever(Condition c) {        return c != null && mForeverId.equals(c.id);    }    private void bind(final Condition condition, final View row, final int rowId) {        if (condition == null) throw new IllegalArgumentException("condition must not be null");        final boolean enabled = condition.state == Condition.STATE_TRUE;        final ConditionTag tag =                row.getTag() != null ? (ConditionTag) row.getTag() : new ConditionTag();        row.setTag(tag);        final boolean first = tag.rb == null;        if (tag.rb == null) {            tag.rb = (RadioButton) mZenRadioGroup.getChildAt(rowId);        }        tag.condition = condition;        final Uri conditionId = getConditionId(tag.condition);        if (DEBUG) Log.d(mTag, "bind i=" + mZenRadioGroupContent.indexOfChild(row) + " first="                + first + " condition=" + conditionId);        tag.rb.setEnabled(enabled);        tag.rb.setOnCheckedChangeListener(new OnCheckedChangeListener() {            @Override            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {                if (mExpanded && isChecked) {                    tag.rb.setChecked(true);                    if (DEBUG) Log.d(mTag, "onCheckedChanged " + conditionId);                    MetricsLogger.action(mContext, MetricsEvent.QS_DND_CONDITION_SELECT);                    select(tag.condition);                    announceConditionSelection(tag);                }            }        });        if (tag.lines == null) {            tag.lines = row.findViewById(android.R.id.content);        }        if (tag.line1 == null) {            tag.line1 = (TextView) row.findViewById(android.R.id.text1);            mConfigurableTexts.add(tag.line1);        }        if (tag.line2 == null) {            tag.line2 = (TextView) row.findViewById(android.R.id.text2);            mConfigurableTexts.add(tag.line2);        }        final String line1 = !TextUtils.isEmpty(condition.line1) ? condition.line1                : condition.summary;        final String line2 = condition.line2;        tag.line1.setText(line1);        if (TextUtils.isEmpty(line2)) {            tag.line2.setVisibility(GONE);        } else {            tag.line2.setVisibility(VISIBLE);            tag.line2.setText(line2);        }        tag.lines.setEnabled(enabled);        tag.lines.setAlpha(enabled ? 1 : .4f);        final ImageView button1 = (ImageView) row.findViewById(android.R.id.button1);        button1.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                onClickTimeButton(row, tag, false /*down*/, rowId);            }        });        final ImageView button2 = (ImageView) row.findViewById(android.R.id.button2);        button2.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                onClickTimeButton(row, tag, true /*up*/, rowId);            }        });        tag.lines.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                tag.rb.setChecked(true);            }        });        final long time = ZenModeConfig.tryParseCountdownConditionId(conditionId);        if (rowId != COUNTDOWN_ALARM_CONDITION_INDEX && time > 0) {            button1.setVisibility(VISIBLE);            button2.setVisibility(VISIBLE);            if (mBucketIndex > -1) {                button1.setEnabled(mBucketIndex > 0);                button2.setEnabled(mBucketIndex < MINUTE_BUCKETS.length - 1);            } else {                final long span = time - System.currentTimeMillis();                button1.setEnabled(span > MIN_BUCKET_MINUTES * MINUTES_MS);                final Condition maxCondition = ZenModeConfig.toTimeCondition(mContext,                        MAX_BUCKET_MINUTES, ActivityManager.getCurrentUser());                button2.setEnabled(!Objects.equals(condition.summary, maxCondition.summary));            }            button1.setAlpha(button1.isEnabled() ? 1f : .5f);            button2.setAlpha(button2.isEnabled() ? 1f : .5f);        } else {            button1.setVisibility(GONE);            button2.setVisibility(GONE);        }        // wire up interaction callbacks for newly-added condition rows        if (first) {            Interaction.register(tag.rb, mInteractionCallback);            Interaction.register(tag.lines, mInteractionCallback);            Interaction.register(button1, mInteractionCallback);            Interaction.register(button2, mInteractionCallback);        }        row.setVisibility(VISIBLE);    }    private void announceConditionSelection(ConditionTag tag) {        final int zen = getSelectedZen(Global.ZEN_MODE_OFF);        String modeText;        switch(zen) {            case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:                modeText = mContext.getString(R.string.interruption_level_priority);                break;            case Global.ZEN_MODE_NO_INTERRUPTIONS:                modeText = mContext.getString(R.string.interruption_level_none);                break;            case Global.ZEN_MODE_ALARMS:                modeText = mContext.getString(R.string.interruption_level_alarms);                break;            case Global.ZEN_MODE_GAME:                modeText = mContext.getString(R.string.interruption_level_game);                break;            default:                return;        }        announceForAccessibility(mContext.getString(R.string.zen_mode_and_condition, modeText,                tag.line1.getText()));    }    private void onClickTimeButton(View row, ConditionTag tag, boolean up, int rowId) {        MetricsLogger.action(mContext, MetricsEvent.QS_DND_TIME, up);        Condition newCondition = null;        final int N = MINUTE_BUCKETS.length;        if (mBucketIndex == -1) {            // not on a known index, search for the next or prev bucket by time            final Uri conditionId = getConditionId(tag.condition);            final long time = ZenModeConfig.tryParseCountdownConditionId(conditionId);            final long now = System.currentTimeMillis();            for (int i = 0; i < N; i++) {                int j = up ? i : N - 1 - i;                final int bucketMinutes = MINUTE_BUCKETS[j];                final long bucketTime = now + bucketMinutes * MINUTES_MS;                if (up && bucketTime > time || !up && bucketTime < time) {                    mBucketIndex = j;                    newCondition = ZenModeConfig.toTimeCondition(mContext,                            bucketTime, bucketMinutes, ActivityManager.getCurrentUser(),                            false /*shortVersion*/);                    break;                }            }            if (newCondition == null) {                mBucketIndex = DEFAULT_BUCKET_INDEX;                newCondition = ZenModeConfig.toTimeCondition(mContext,                        MINUTE_BUCKETS[mBucketIndex], ActivityManager.getCurrentUser());            }        } else {            // on a known index, simply increment or decrement            mBucketIndex = Math.max(0, Math.min(N - 1, mBucketIndex + (up ? 1 : -1)));            newCondition = ZenModeConfig.toTimeCondition(mContext,                    MINUTE_BUCKETS[mBucketIndex], ActivityManager.getCurrentUser());        }        mTimeCondition = newCondition;        bind(mTimeCondition, row, rowId);        tag.rb.setChecked(true);        select(mTimeCondition);        announceConditionSelection(tag);    }    private void select(final Condition condition) {        if (DEBUG) Log.d(mTag, "select " + condition);        if (mSessionZen == -1 || mSessionZen == Global.ZEN_MODE_OFF) {            if (DEBUG) Log.d(mTag, "Ignoring condition selection outside of manual zen");            return;        }        final Uri realConditionId = getRealConditionId(condition);        if (mController != null) {            AsyncTask.execute(new Runnable() {                @Override                public void run() {                    mController.setZen(mSessionZen, realConditionId, TAG + ".selectCondition");                }            });        }        setExitCondition(condition);        if (realConditionId == null) {            mPrefs.setMinuteIndex(-1);        } else if (isCountdown(condition) && mBucketIndex != -1) {            mPrefs.setMinuteIndex(mBucketIndex);        }        setSessionExitCondition(copy(condition));    }    private void fireInteraction() {        if (mCallback != null) {            mCallback.onInteraction();        }    }    private void fireExpanded() {        if (mCallback != null) {            mCallback.onExpanded(mExpanded);        }    }    private final ZenModeController.Callback mZenCallback = new ZenModeController.Callback() {        @Override        public void onManualRuleChanged(ZenRule rule) {            mHandler.obtainMessage(H.MANUAL_RULE_CHANGED, rule).sendToTarget();        }    };    private final class H extends Handler {        private static final int MANUAL_RULE_CHANGED = 2;        private static final int UPDATE_WIDGETS = 3;        private H() {            super(Looper.getMainLooper());        }        @Override        public void handleMessage(Message msg) {            switch (msg.what) {                case MANUAL_RULE_CHANGED: handleUpdateManualRule((ZenRule) msg.obj); break;                case UPDATE_WIDGETS: updateWidgets(); break;            }        }    }    public interface Callback {        void onPrioritySettings();        void onInteraction();        void onExpanded(boolean expanded);    }    // used as the view tag on condition rows    private static class ConditionTag {        RadioButton rb;        View lines;        TextView line1;        TextView line2;        Condition condition;    }    private final class ZenPrefs implements OnSharedPreferenceChangeListener {        private final int mNoneDangerousThreshold;        private int mMinuteIndex;        private int mNoneSelected;        private boolean mConfirmedPriorityIntroduction;        private boolean mConfirmedSilenceIntroduction;        private boolean mConfirmedAlarmIntroduction;        private boolean mConfirmedGameIntroduction;        private ZenPrefs() {            mNoneDangerousThreshold = mContext.getResources()                    .getInteger(R.integer.zen_mode_alarm_warning_threshold);            Prefs.registerListener(mContext, this);            updateMinuteIndex();            updateNoneSelected();            updateConfirmedPriorityIntroduction();            updateConfirmedSilenceIntroduction();            updateConfirmedAlarmIntroduction();            updateConfirmedGameIntroduction();        }        public void trackNoneSelected() {            mNoneSelected = clampNoneSelected(mNoneSelected + 1);            if (DEBUG) Log.d(mTag, "Setting none selected: " + mNoneSelected + " threshold="                    + mNoneDangerousThreshold);            Prefs.putInt(mContext, Prefs.Key.DND_NONE_SELECTED, mNoneSelected);        }        public int getMinuteIndex() {            return mMinuteIndex;        }        public void setMinuteIndex(int minuteIndex) {            minuteIndex = clampIndex(minuteIndex);            if (minuteIndex == mMinuteIndex) return;            mMinuteIndex = clampIndex(minuteIndex);            if (DEBUG) Log.d(mTag, "Setting favorite minute index: " + mMinuteIndex);            Prefs.putInt(mContext, Prefs.Key.DND_FAVORITE_BUCKET_INDEX, mMinuteIndex);        }        @Override        public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {            updateMinuteIndex();            updateNoneSelected();            updateConfirmedPriorityIntroduction();            updateConfirmedSilenceIntroduction();            updateConfirmedAlarmIntroduction();            updateConfirmedGameIntroduction();        }        private void updateMinuteIndex() {            mMinuteIndex = clampIndex(Prefs.getInt(mContext,                    Prefs.Key.DND_FAVORITE_BUCKET_INDEX, DEFAULT_BUCKET_INDEX));            if (DEBUG) Log.d(mTag, "Favorite minute index: " + mMinuteIndex);        }        private int clampIndex(int index) {            return MathUtils.constrain(index, -1, MINUTE_BUCKETS.length - 1);        }        private void updateNoneSelected() {            mNoneSelected = clampNoneSelected(Prefs.getInt(mContext,                    Prefs.Key.DND_NONE_SELECTED, 0));            if (DEBUG) Log.d(mTag, "None selected: " + mNoneSelected);        }        private int clampNoneSelected(int noneSelected) {            return MathUtils.constrain(noneSelected, 0, Integer.MAX_VALUE);        }        private void updateConfirmedPriorityIntroduction() {            final boolean confirmed =  Prefs.getBoolean(mContext,                    Prefs.Key.DND_CONFIRMED_PRIORITY_INTRODUCTION, false);            if (confirmed == mConfirmedPriorityIntroduction) return;            mConfirmedPriorityIntroduction = confirmed;            if (DEBUG) Log.d(mTag, "Confirmed priority introduction: "                    + mConfirmedPriorityIntroduction);        }        private void updateConfirmedSilenceIntroduction() {            final boolean confirmed =  Prefs.getBoolean(mContext,                    Prefs.Key.DND_CONFIRMED_SILENCE_INTRODUCTION, false);            if (confirmed == mConfirmedSilenceIntroduction) return;            mConfirmedSilenceIntroduction = confirmed;            if (DEBUG) Log.d(mTag, "Confirmed silence introduction: "                    + mConfirmedSilenceIntroduction);        }        private void updateConfirmedAlarmIntroduction() {            final boolean confirmed =  Prefs.getBoolean(mContext,                    Prefs.Key.DND_CONFIRMED_ALARM_INTRODUCTION, false);            if (confirmed == mConfirmedAlarmIntroduction) return;            mConfirmedAlarmIntroduction = confirmed;            if (DEBUG) Log.d(mTag, "Confirmed alarm introduction: "                    + mConfirmedAlarmIntroduction);        }        private void updateConfirmedGameIntroduction() {            final boolean confirmed =  Prefs.getBoolean(mContext,                    Prefs.Key.DND_CONFIRMED_GAME_INTRODUCTION, false);            if (confirmed == mConfirmedGameIntroduction) return;            mConfirmedGameIntroduction = confirmed;            if (DEBUG) Log.d(mTag, "Confirmed game introduction: "                    + mConfirmedGameIntroduction);        }    }    protected final SegmentedButtons.Callback mZenButtonsCallback = new SegmentedButtons.Callback() {        @Override        public void onSelected(final Object value, boolean fromClick) {            if (value != null && mZenButtons.isShown() && isAttachedToWindow()) {                final int zen = (Integer) value;                if (fromClick) {                    MetricsLogger.action(mContext, MetricsEvent.QS_DND_ZEN_SELECT, zen);                }                if (DEBUG) Log.d(mTag, "mZenButtonsCallback selected=" + zen);                final Uri realConditionId = getRealConditionId(mSessionExitCondition);                AsyncTask.execute(new Runnable() {                    @Override                    public void run() {                        mController.setZen(zen, realConditionId, TAG + ".selectZen");                        if (zen != Global.ZEN_MODE_OFF) {                            Prefs.putInt(mContext, Prefs.Key.DND_FAVORITE_ZEN, zen);                        }                    }                });            }        }        @Override        public void onInteraction() {            fireInteraction();        }    };    private final Interaction.Callback mInteractionCallback = new Interaction.Callback() {        @Override        public void onInteraction() {            fireInteraction();        }    };    private final class TransitionHelper implements TransitionListener, Runnable {        private final ArraySet<View> mTransitioningViews = new ArraySet<View>();        private boolean mTransitioning;        private boolean mPendingUpdateWidgets;        public void clear() {            mTransitioningViews.clear();            mPendingUpdateWidgets = false;        }        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {            pw.println("  TransitionHelper state:");            pw.print("    mPendingUpdateWidgets="); pw.println(mPendingUpdateWidgets);            pw.print("    mTransitioning="); pw.println(mTransitioning);            pw.print("    mTransitioningViews="); pw.println(mTransitioningViews);        }        public void pendingUpdateWidgets() {            mPendingUpdateWidgets = true;        }        public boolean isTransitioning() {            return !mTransitioningViews.isEmpty();        }        @Override        public void startTransition(LayoutTransition transition,                ViewGroup container, View view, int transitionType) {            mTransitioningViews.add(view);            updateTransitioning();        }        @Override        public void endTransition(LayoutTransition transition,                ViewGroup container, View view, int transitionType) {            mTransitioningViews.remove(view);            updateTransitioning();        }        @Override        public void run() {            if (DEBUG) Log.d(mTag, "TransitionHelper run"                    + " mPendingUpdateWidgets=" + mPendingUpdateWidgets);            if (mPendingUpdateWidgets) {                updateWidgets();            }            mPendingUpdateWidgets = false;        }        private void updateTransitioning() {            final boolean transitioning = isTransitioning();            if (mTransitioning == transitioning) return;            mTransitioning = transitioning;            if (DEBUG) Log.d(mTag, "TransitionHelper mTransitioning=" + mTransitioning);            if (!mTransitioning) {                if (mPendingUpdateWidgets) {                    mHandler.post(this);                } else {                    mPendingUpdateWidgets = false;                }            }        }    }}

2.实现新加的模式
dnd实现的地方在ZenModeHelper.java,这里会根据不同的模式来做不同的处理,还会监听audiomanager模式的改变,就是按音量键打开dnd。

在打开某个模式的时候,首先会看是否要设置applyZenToRingerMode,然后在去applyRestrictions。我们这里加的模式不会去设置RINGER_MODE_SILENT,而是直接applyRestrictions去设置。

frameworks/base/services/core/java/com/android/server/notification/ZenModeHelper.java

    private boolean evaluateZenMode(String reason, boolean setRingerMode) {        if (DEBUG) Log.d(TAG, "evaluateZenMode");        final int zenBefore = mZenMode;        final int zen = computeZenMode();        ZenLog.traceSetZenMode(zen, reason);        mZenMode = zen;        updateRingerModeAffectedStreams();        setZenModeSetting(mZenMode);        if (setRingerMode) {            applyZenToRingerMode();        }        applyRestrictions();        if (zen != zenBefore) {            mHandler.postDispatchOnZenModeChanged();        }        return true;    }    private void applyZenToRingerMode() {        if (mAudioManager == null) return;        // force the ringer mode into compliance        final int ringerModeInternal = mAudioManager.getRingerModeInternal();        int newRingerModeInternal = ringerModeInternal;        switch (mZenMode) {            case Global.ZEN_MODE_NO_INTERRUPTIONS:            case Global.ZEN_MODE_ALARMS:            //case Global.ZEN_MODE_GAME:                if (ringerModeInternal != AudioManager.RINGER_MODE_SILENT) {                    setPreviousRingerModeSetting(ringerModeInternal);                    newRingerModeInternal = AudioManager.RINGER_MODE_SILENT;                }                break;            case Global.ZEN_MODE_GAME:            case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:            case Global.ZEN_MODE_OFF:                if (ringerModeInternal == AudioManager.RINGER_MODE_SILENT) {                    newRingerModeInternal = getPreviousRingerModeSetting();                    setPreviousRingerModeSetting(null);                }                break;        }        if (newRingerModeInternal != -1) {            mAudioManager.setRingerModeInternal(newRingerModeInternal, TAG);        }    }

根据不同模式,设置哪些声音有效,哪些无效。

    private void applyRestrictions() {        final boolean zen = mZenMode != Global.ZEN_MODE_OFF;        // notification restrictions        final boolean muteNotifications =                (mSuppressedEffects & SUPPRESSED_EFFECT_NOTIFICATIONS) != 0;        // call restrictions        final boolean muteCalls = zen && !mConfig.allowCalls && !mConfig.allowRepeatCallers                || (mSuppressedEffects & SUPPRESSED_EFFECT_CALLS) != 0;        // total silence restrictions        final boolean muteEverything = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;        final boolean mGameMode = mZenMode == Global.ZEN_MODE_GAME;        for (int usage : AudioAttributes.SDK_USAGES) {            final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage);            if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NEVER) {                applyRestrictions(false /*mute*/, usage);            } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NOTIFICATION) {                applyRestrictions(muteNotifications || muteEverything||mGameMode, usage);            } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_CALL) {                applyRestrictions(muteCalls || muteEverything||mGameMode, usage);            } else if(usage==AudioAttributes.SDK_USAGES[4]) {                //Alarm                applyRestrictions(mGameMode, usage);            }            else {                applyRestrictions(muteEverything, usage);            }        }    }    private static int zenSeverity(int zen) {        switch (zen) {            case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: return 1;            case Global.ZEN_MODE_ALARMS: return 2;            case Global.ZEN_MODE_NO_INTERRUPTIONS: return 3;            case Global.ZEN_MODE_GAME: return 4;            default: return 0;        }    }

注意RingerModeDelegate这个内部类,当执行applyZenToRingerMode改变了ringermode,就会回调这个内部类里的方法,按音量键也会走这里,所以这里也要加入对我们新加模式的一些处理,否则会发生逻辑错误,导致QS那点击的按钮切换错误。

    private final class RingerModeDelegate implements AudioManagerInternal.RingerModeDelegate {        @Override        public String toString() {            return TAG;        }        @Override        public int onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, String caller,                int ringerModeExternal, VolumePolicy policy) {            final boolean isChange = ringerModeOld != ringerModeNew;            int ringerModeExternalOut = ringerModeNew;            int newZen = -1;            switch (ringerModeNew) {                case AudioManager.RINGER_MODE_SILENT:                    if (isChange && policy.doNotDisturbWhenSilent) {                        if (mZenMode != Global.ZEN_MODE_NO_INTERRUPTIONS                                && mZenMode != Global.ZEN_MODE_ALARMS                                && mZenMode != Global.ZEN_MODE_GAME) {                            newZen = Global.ZEN_MODE_ALARMS;                        }                        setPreviousRingerModeSetting(ringerModeOld);                    }                    break;                case AudioManager.RINGER_MODE_VIBRATE:                case AudioManager.RINGER_MODE_NORMAL:                    if (isChange && ringerModeOld == AudioManager.RINGER_MODE_SILENT                            && (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS                                    || mZenMode == Global.ZEN_MODE_ALARMS                                    /*|| mZenMode == Global.ZEN_MODE_GAME*/)) {                        newZen = Global.ZEN_MODE_OFF;                    } else if (mZenMode != Global.ZEN_MODE_OFF) {                        ringerModeExternalOut = AudioManager.RINGER_MODE_SILENT;                    }                    break;            }            if (newZen != -1) {                setManualZenMode(newZen, null, "ringerModeInternal", null,                        false /*setRingerMode*/);            }            if (isChange || newZen != -1 || ringerModeExternal != ringerModeExternalOut) {                ZenLog.traceSetRingerModeInternal(ringerModeOld, ringerModeNew, caller,                        ringerModeExternal, ringerModeExternalOut);            }            return ringerModeExternalOut;        }        @Override        public int onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller,                int ringerModeInternal, VolumePolicy policy) {            int ringerModeInternalOut = ringerModeNew;            final boolean isChange = ringerModeOld != ringerModeNew;            final boolean isVibrate = ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE;            int newZen = -1;            switch (ringerModeNew) {                case AudioManager.RINGER_MODE_SILENT:                    if (isChange) {                        if (mZenMode == Global.ZEN_MODE_OFF) {                            newZen = Global.ZEN_MODE_ALARMS;                        }                        ringerModeInternalOut = isVibrate ? AudioManager.RINGER_MODE_VIBRATE                                : AudioManager.RINGER_MODE_SILENT;                    } else {                        ringerModeInternalOut = ringerModeInternal;                    }                    break;                case AudioManager.RINGER_MODE_VIBRATE:                case AudioManager.RINGER_MODE_NORMAL:                    if (mZenMode != Global.ZEN_MODE_OFF) {                        newZen = Global.ZEN_MODE_OFF;                    }                    break;            }            if (newZen != -1) {                setManualZenMode(newZen, null, "ringerModeExternal", caller,                        false /*setRingerMode*/);            }            ZenLog.traceSetRingerModeExternal(ringerModeOld, ringerModeNew, caller,                    ringerModeInternal, ringerModeInternalOut);            return ringerModeInternalOut;        }        @Override        public boolean canVolumeDownEnterSilent() {            return mZenMode == Global.ZEN_MODE_OFF;        }        @Override        public int getRingerModeAffectedStreams(int streams) {            // ringtone, notification and system streams are always affected by ringer mode            streams |= (1 << AudioSystem.STREAM_RING) |                       (1 << AudioSystem.STREAM_NOTIFICATION) |                       (1 << AudioSystem.STREAM_SYSTEM);            // alarm and music streams are only affected by ringer mode when in total silence            if (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) {                streams |= (1 << AudioSystem.STREAM_ALARM) |                           (1 << AudioSystem.STREAM_MUSIC);            } else {                streams &= ~((1 << AudioSystem.STREAM_ALARM) |                             (1 << AudioSystem.STREAM_MUSIC));            }            return streams;        }    }

3.音量界面的处理
当你进去某个dnd模式下,在settigns中的sound里面你可以发现,有些音量会滑动条会被disable掉。所以我们在这里也要做些处理。

这里写图片描述

这个界面在
packages/apps/Settings/src/com/android/settings/notification/SoundSettings.java,但是对应的音量滑动条在frameworks/base/core/java/android/preferences/SeekBarVolumizer.java,每个音量条都会对应new一个SeekBarVolumizer,然后SeekBarVolumizer会根据对应音量的stream和zenmode来判断是否要disable掉。

SeekBarVolumizer.java

    private boolean isZenMuted() {        return mNotificationOrRing && mZenMode == Global.ZEN_MODE_ALARMS                || mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS                || (mZenMode == Global.ZEN_MODE_GAME && mStreamType == AudioManager.STREAM_ALARM);    }    protected void updateSeekBar() {        final boolean zenMuted = isZenMuted();        mSeekBar.setEnabled(!zenMuted);        if (zenMuted) {            mSeekBar.setProgress(mLastAudibleStreamVolume, true);        } else if (mNotificationOrRing && mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {            mSeekBar.setProgress(0, true);        } else if (mMuted) {            mSeekBar.setProgress(0, true);        } else {            mSeekBar.setProgress(mLastProgress > -1 ? mLastProgress : mOriginalStreamVolume, true);        }    }

除了settings中有音量,还有个地方也有,就是当你按下音量键时候,从屏幕上方弹下来的界面。
这里写图片描述

frameworks/base/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java

    private void updateVolumeRowH(VolumeRow row) {        if (D.BUG) Log.d(TAG, "updateVolumeRowH s=" + row.stream);        if (mState == null) return;        final StreamState ss = mState.states.get(row.stream);        if (ss == null) return;        row.ss = ss;        if (ss.level > 0) {            row.lastAudibleLevel = ss.level;        }        if (ss.level == row.requestedLevel) {            row.requestedLevel = -1;        }        final boolean isA11yStream = row.stream == AudioManager.STREAM_ACCESSIBILITY;        final boolean isRingStream = row.stream == AudioManager.STREAM_RING;        final boolean isSystemStream = row.stream == AudioManager.STREAM_SYSTEM;        final boolean isAlarmStream = row.stream == AudioManager.STREAM_ALARM;        final boolean isMusicStream = row.stream == AudioManager.STREAM_MUSIC;        final boolean isRingVibrate = isRingStream                && mState.ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE;        final boolean isRingSilent = isRingStream                && mState.ringerModeInternal == AudioManager.RINGER_MODE_SILENT;        final boolean isZenAlarms = mState.zenMode == Global.ZEN_MODE_ALARMS;        final boolean isZenNone = mState.zenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;        final boolean isZenGame = mState.zenMode == Global.ZEN_MODE_GAME;        final boolean zenMuted = isZenAlarms ? (isRingStream || isSystemStream)                : isZenNone ? (isRingStream || isSystemStream || isAlarmStream || isMusicStream)                : isZenGame ? (isAlarmStream)                : false;       ...... }

isZenAlarms ? (isRingStream || isSystemStream) 如果是alarm模式,就disable掉ringstream和SystemStream。

注意:ZenModeFiltering这个类。
matchesCallFilter和shouldIntercept都要加我们的代码,模仿其他模式。

原创粉丝点击