android zenmode 通知,【Android系统】Android M ZenMode(禅模式)分析(2)

在上一节我们说到了ZenModeConditions里面的evaluateConfig()方法 。

调到了另一个类ZenModeConditions里面的evaluateConfig()方法 。这个文件的目录:\framework\base\services\core\java\com\android\server\notification\ZenModeConditions.java,具体方法实现的代码如下,

public

void

evaluateConfig(ZenModeConfig

config, boolean

processSubscriptions) {

if (config

==

null)

return;

if (config.manualRule

!= null

&&

config.manualRule.condition !=

null

&&

!config.manualRule.isTrueOrUnknown()) {

if (DEBUG)

Log.d(TAG, "evaluateConfig: clearing

manual rule");

config.manualRule =

null;

}

final ArraySet current

= new

ArraySet<>();

evaluateRule(config.manualRule, current,

processSubscriptions);

for (ZenRule

automaticRule : config.automaticRules.values()) {

evaluateRule(automaticRule, current,

processSubscriptions);

updateSnoozing(automaticRule);

}

final

int N =

mSubscriptions.size();

for

(int

i = N - 1; i >= 0; i--)

{

final Uri id =

mSubscriptions.keyAt(i);

final ComponentName

component = mSubscriptions.valueAt(i);

if

(processSubscriptions) {

if

(!current.contains(id)) {

mConditionProviders.unsubscribeIfNecessary(component,

id);

mSubscriptions.removeAt(i);

}

}

}

mFirstEvaluation =

false;

}

而这个方法,其实在处理的时候,又调到另一个方法evaluateRule(),该方法的具体实现如下,所以看代码跟流程就需要这样一个一个方法调用往里面跟,好,继续看代码。

private

void

evaluateRule(ZenRule rule, ArraySet

current, boolean

processSubscriptions) {

if (rule

== null

|| rule.conditionId ==

null)

return;

final Uri id =

rule.conditionId;

boolean

isSystemCondition =

false;

for

(SystemConditionProviderService sp :

mConditionProviders.getSystemProviders()) {

if

(sp.isValidConditionId(id)) {

mConditionProviders.ensureRecordExists(sp.getComponent(), id,

sp.asInterface());

rule.component = sp.getComponent();

isSystemCondition =

true;

}

}

if

(!isSystemCondition) {

final

IConditionProvider cp =

mConditionProviders.findConditionProvider(rule.component);

if (DEBUG)

Log.d(TAG, "Ensure external rule exists:

" + (cp !=

null) +

" for " +

id);

if (cp

!= null)

{

mConditionProviders.ensureRecordExists(rule.component, id,

cp);

}

}

if (rule.component

== null)

{

Log.w(TAG, "No component found for

automatic rule: " +

rule.conditionId);

rule.enabled =

false;

return;

}

if (current

!= null)

{

current.add(id);

}

if

(processSubscriptions)

{

if

(mConditionProviders.subscribeIfNecessary(rule.component,

rule.conditionId)) {

mSubscriptions.put(rule.conditionId,

rule.component);

} else

{

if (DEBUG)

Log.d(TAG, "zmc failed to

subscribe");

}

}

if (rule.condition

== null)

{

rule.condition = mConditionProviders.findCondition(rule.component,

rule.conditionId);

if (rule.condition

!= null

&& DEBUG)

Log.d(TAG, "Found existing condition for:

"

+ rule.conditionId);

}

}

那上面的这个方法主要的处理又调到了另一个文件里面了,ConditionProviders,这个类中的ensureRecordExists 和subscribeIfNecessary

方法,最后将数据记录到HashMap中,这个文件的目录:\framework\base\services\core\java\com\android\server\notification\ConditionProviders

.java。那我们所要说的ZenMode的设置过程就是如此,通过NotificationManager调到了NotificationManagerService ,然后调到了ZenModeHelper,主要的处理在ZenModeHelper,设置完成后,相关注册的Callback会进行相关消息的通知,最后数据库的mode值被改写,到此设置模式结束。那勿扰模式是怎么生效的,我们需要继续查看代码了,我们在之前也说过,勿扰模式和通知有关系,那我们就看下NotificationManagerService是如何通过勿扰模式,来屏蔽通知提醒的,首先我们找到文件NotificationManagerService,对应的目录:\framework\base\services\core\java\com\android\server\notification\NotificationManagerService.java。我们知道Notification的数据结构封装成了3个类,Notification,NotificationRecord和StatusBarNotification,具体的Notification流程,我们在此就不详细分析。而NotificationRecord有定义一个属性:mIntercept,看注释也就是这个通知是否需要被ZenMode影响的属性。

// is this

notification currently being intercepted by Zen

Mode?

private

boolean

mIntercept;

而这个属性被设置的位置我们在NotificationManagerService可以看到如下方法的处理,其中ZenModeHelper对象调用的shouldIntercept()方法就是在我们之前讲的类,这个方法最后其实调用到了ZenModeFiltering中的方法shouldIntercept(),这个方法也就是根据当前的模式和配置ZenModeConfig来判断这个NotificationRecord是否需要被intercept(阻截)。如果是true表示这条通知就会被屏蔽阻截掉。然后这个返回结果最后是记录在NotificationRecord的mIntercept属性中,然后我们继续看代码。NotificationRecord还有一个取这个值的方法isIntercepted(),我们继续看这个方法在NotificationManagerService调用的处理。

// let zen mode evaluate this record

private

void

applyZenModeLocked(NotificationRecord

record) {

record.setIntercepted(mZenModeHelper.shouldIntercept(record));

}

主要的处理就在NotificationManagerService 这个类的buzzBeepBlinkLocked()方法中处理,由于方法代码有点多少,所以只是贴上了前面一部分,我们的前面说的NotificationRecord 这个通知是否需要被屏蔽阻截掉的属性调用的方法isIntercepted() ,最后的值就这个地方被调用,canInterrupt

= aboveThreshold &&

!record.isIntercepted();所以canInterrupt最后其实就是这个是否需要屏蔽阻截的值取反。当aboveThreshold为true的时候,canInterrupt 的值就取决于isIntercepted() 的结果,这个值被使用的地方,也就是下面的那个if条件。这个if后面的处理就包括播放声音、振动的提醒具体的代码这里就不贴出来了。所以我们看这个if条件,当canInterrupt为true,这个时候才会去播放声音和振动,也就是不是勿扰模式,那么isIntercepted()取到的值应该为false,所以这样的逻辑就走通了。具体返回的值,可查阅ZenModeFiltering中方法shouldIntercept()的处理。这个文件对应的目录为:\framework\base\services\core\java\com\android\server\notification\ZenModeFiltering.java

private

void

buzzBeepBlinkLocked(NotificationRecord

record) {

boolean buzz

=

false;

boolean beep

=

false;

boolean blink

=

false;

final Notification

notification = record.sbn.getNotification();

// Should this notification make noise, vibe, or use

the LED?

final

boolean aboveThreshold

= record.score >=

SCORE_INTERRUPTION_THRESHOLD;

final

boolean canInterrupt =

aboveThreshold &&

!record.isIntercepted();

if (DBG ||

record.isIntercepted())

Slog.v(TAG,

"pkg=" +

record.sbn.getPackageName() + "

canInterrupt=" + canInterrupt

+

" intercept=" +

record.isIntercepted()

);

final

int

currentUser;

final

long token =

Binder.clearCallingIdentity();

try

{

currentUser = ActivityManager.getCurrentUser();

} finally

{

Binder.restoreCallingIdentity(token);

}

// If we're not supposed to beep, vibrate, etc. then

don't.

final String

disableEffects =

disableNotificationEffects(record);

if (disableEffects

!= null)

{

ZenLog.traceDisableEffects(record,

disableEffects);

}

/// M: Determine if we should play

alerts

final

boolean enableAlerts =

(((mDisabledNotifications

& StatusBarManager.DISABLE_NOTIFICATION_ALERTS) ==

0)

// Phone app will disable alerts but we need the alert

of mms

||

record.sbn.getPackageName().equals("com.android.mms"))

&& !mDmLock

&& !mPplLock;

// Never play alerts when DM/PPL lock

// if (disableEffects == null

if (enableAlerts

&& disableEffects ==

null

&&

(!(record.isUpdate

&& (notification.flags

& Notification.FLAG_ONLY_ALERT_ONCE) != 0

))

&& (record.getUserId() ==

UserHandle.USER_ALL ||

record.getUserId() == currentUser ||

mUserProfiles.isCurrentProfile(record.getUserId()))

&& canInterrupt

&& mSystemReady

&& mAudioManager !=

null)

{

if (DBG)

Slog.v(TAG,

"Interrupting!");

sendAccessibilityEvent(notification,

record.sbn.getPackageName());

//省略部分代码 ···

}

本次ZenMode(禅模式)勿扰模式的设置和生效的流程分析就到此了,那下一次我们将介绍定时勿扰的实现流程和机制。本次介绍到此结束,祝你工作学习愉快!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值