NextAlarmConditionProviderpublic class NextAlarmConditionProvider extends android.service.notification.ConditionProviderService Built-in zen condition provider for alarm-clock-based conditions.
If the user's next alarm is within a lookahead threshold (config, default 12hrs), advertise
it as an exit condition for zen mode.
The next alarm is defined as {@link AlarmManager#getNextAlarmClock(int)}, which does not
survive a reboot. Maintain the illusion of a consistent next alarm value by holding on to
a persisted condition until we receive the first value after reboot, or timeout with no value. |
Fields Summary |
---|
private static final String | TAG | private static final boolean | DEBUG | private static final long | SECONDS | private static final long | MINUTES | private static final long | HOURS | private static final long | BAD_CONDITION | public static final android.content.ComponentName | COMPONENT | private final android.content.Context | mContext | private final NextAlarmTracker | mTracker | private final android.util.ArraySet | mSubscriptions | private boolean | mConnected | private long | mLookaheadThreshold | private boolean | mRequesting | private final NextAlarmTracker.Callback | mTrackerCallback |
Constructors Summary |
---|
public NextAlarmConditionProvider(NextAlarmTracker tracker)
if (DEBUG) Slog.d(TAG, "new NextAlarmConditionProvider()");
mTracker = tracker;
|
Methods Summary |
---|
public android.service.notification.IConditionProvider | asInterface()
return (IConditionProvider) onBind(null);
| public void | attachBase(android.content.Context base)
attachBaseContext(base);
| public void | dump(java.io.PrintWriter pw, com.android.server.notification.NotificationManagerService.DumpFilter filter)
pw.println(" NextAlarmConditionProvider:");
pw.print(" mConnected="); pw.println(mConnected);
pw.print(" mLookaheadThreshold="); pw.print(mLookaheadThreshold);
pw.print(" ("); TimeUtils.formatDuration(mLookaheadThreshold, pw); pw.println(")");
pw.print(" mSubscriptions="); pw.println(mSubscriptions);
pw.print(" mRequesting="); pw.println(mRequesting);
| private boolean | isWithinLookaheadThreshold(android.app.AlarmManager.AlarmClockInfo alarm)
if (alarm == null) return false;
final long delta = NextAlarmTracker.getEarlyTriggerTime(alarm) - System.currentTimeMillis();
return delta > 0 && (mLookaheadThreshold <= 0 || delta < mLookaheadThreshold);
| private android.net.Uri | newConditionId(android.app.AlarmManager.AlarmClockInfo nextAlarm)
return new Uri.Builder().scheme(Condition.SCHEME)
.authority(ZenModeConfig.SYSTEM_AUTHORITY)
.appendPath(ZenModeConfig.NEXT_ALARM_PATH)
.appendPath(Integer.toString(mTracker.getCurrentUserId()))
.appendPath(Long.toString(nextAlarm.getTriggerTime()))
.build();
| private void | notifyCondition(android.net.Uri id, android.app.AlarmManager.AlarmClockInfo alarm, int state, java.lang.String reason)
final String formattedAlarm = alarm == null ? "" : mTracker.formatAlarm(alarm);
if (DEBUG) Slog.d(TAG, "notifyCondition " + Condition.stateToString(state)
+ " alarm=" + formattedAlarm + " reason=" + reason);
notifyCondition(new Condition(id,
mContext.getString(R.string.zen_mode_next_alarm_summary, formattedAlarm),
mContext.getString(R.string.zen_mode_next_alarm_line_one),
formattedAlarm, 0, state, Condition.FLAG_RELEVANT_NOW));
| public void | onConnected()
if (DEBUG) Slog.d(TAG, "onConnected");
mLookaheadThreshold = PropConfig.getInt(mContext, "nextalarm.condition.lookahead",
R.integer.config_next_alarm_condition_lookahead_threshold_hrs) * HOURS;
mConnected = true;
mTracker.addCallback(mTrackerCallback);
| public void | onDestroy()
super.onDestroy();
if (DEBUG) Slog.d(TAG, "onDestroy");
mTracker.removeCallback(mTrackerCallback);
mConnected = false;
| private void | onEvaluate(android.app.AlarmManager.AlarmClockInfo nextAlarm, long wakeupTime, boolean booted)
final boolean withinThreshold = isWithinLookaheadThreshold(nextAlarm);
final long nextAlarmTime = nextAlarm != null ? nextAlarm.getTriggerTime() : 0;
if (DEBUG) Slog.d(TAG, "onEvaluate mSubscriptions=" + mSubscriptions
+ " nextAlarmTime=" + mTracker.formatAlarmDebug(nextAlarmTime)
+ " nextAlarmWakeup=" + mTracker.formatAlarmDebug(wakeupTime)
+ " withinThreshold=" + withinThreshold
+ " booted=" + booted);
ArraySet<Uri> conditions = mSubscriptions;
if (mRequesting && nextAlarm != null && withinThreshold) {
final Uri id = newConditionId(nextAlarm);
if (!conditions.contains(id)) {
conditions = new ArraySet<Uri>(conditions);
conditions.add(id);
}
}
for (Uri conditionId : conditions) {
final long time = tryParseNextAlarmCondition(conditionId);
if (time == BAD_CONDITION) {
notifyCondition(conditionId, nextAlarm, Condition.STATE_FALSE, "badCondition");
} else if (!booted) {
// we don't know yet
if (mSubscriptions.contains(conditionId)) {
notifyCondition(conditionId, nextAlarm, Condition.STATE_UNKNOWN, "!booted");
}
} else if (time != nextAlarmTime) {
// next alarm changed since subscription, consider obsolete
notifyCondition(conditionId, nextAlarm, Condition.STATE_FALSE, "changed");
} else if (!withinThreshold) {
// next alarm outside threshold or in the past, condition = false
notifyCondition(conditionId, nextAlarm, Condition.STATE_FALSE, "!within");
} else {
// next alarm within threshold and in the future, condition = true
notifyCondition(conditionId, nextAlarm, Condition.STATE_TRUE, "within");
}
}
| public void | onRequestConditions(int relevance)
if (DEBUG) Slog.d(TAG, "onRequestConditions relevance=" + relevance);
if (!mConnected) return;
mRequesting = (relevance & Condition.FLAG_RELEVANT_NOW) != 0;
mTracker.evaluate();
| public void | onSubscribe(android.net.Uri conditionId)
if (DEBUG) Slog.d(TAG, "onSubscribe " + conditionId);
if (tryParseNextAlarmCondition(conditionId) == BAD_CONDITION) {
notifyCondition(conditionId, null, Condition.STATE_FALSE, "badCondition");
return;
}
mSubscriptions.add(conditionId);
mTracker.evaluate();
| public void | onUnsubscribe(android.net.Uri conditionId)
if (DEBUG) Slog.d(TAG, "onUnsubscribe " + conditionId);
mSubscriptions.remove(conditionId);
| private static long | tryParseLong(java.lang.String value, long defValue)
if (TextUtils.isEmpty(value)) return defValue;
try {
return Long.valueOf(value);
} catch (NumberFormatException e) {
return defValue;
}
| private long | tryParseNextAlarmCondition(android.net.Uri conditionId)
return conditionId != null && conditionId.getScheme().equals(Condition.SCHEME)
&& conditionId.getAuthority().equals(ZenModeConfig.SYSTEM_AUTHORITY)
&& conditionId.getPathSegments().size() == 3
&& conditionId.getPathSegments().get(0).equals(ZenModeConfig.NEXT_ALARM_PATH)
&& conditionId.getPathSegments().get(1)
.equals(Integer.toString(mTracker.getCurrentUserId()))
? tryParseLong(conditionId.getPathSegments().get(2), BAD_CONDITION)
: BAD_CONDITION;
|
|