am 8f72b403: Merge "Zen: New event condition data model." into mnc-dev
* commit '8f72b4037022c4f860caafa296e2ac309bde177f': Zen: New event condition data model.
This commit is contained in:
@@ -918,6 +918,15 @@ public final class Settings {
|
||||
public static final String ACTION_ZEN_MODE_SCHEDULE_RULE_SETTINGS
|
||||
= "android.settings.ZEN_MODE_SCHEDULE_RULE_SETTINGS";
|
||||
|
||||
/**
|
||||
* Activity Action: Show Zen Mode event rule configuration settings.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
|
||||
public static final String ACTION_ZEN_MODE_EVENT_RULE_SETTINGS
|
||||
= "android.settings.ZEN_MODE_EVENT_RULE_SETTINGS";
|
||||
|
||||
/**
|
||||
* Activity Action: Show Zen Mode external rule configuration settings.
|
||||
*
|
||||
|
||||
@@ -95,7 +95,7 @@ public class ZenModeConfig implements Parcelable {
|
||||
private static final String MANUAL_TAG = "manual";
|
||||
private static final String AUTOMATIC_TAG = "automatic";
|
||||
|
||||
private static final String RULE_ATT_ID = "id";
|
||||
private static final String RULE_ATT_ID = "ruleId";
|
||||
private static final String RULE_ATT_ENABLED = "enabled";
|
||||
private static final String RULE_ATT_SNOOZING = "snoozing";
|
||||
private static final String RULE_ATT_NAME = "name";
|
||||
@@ -279,6 +279,15 @@ public class ZenModeConfig implements Parcelable {
|
||||
}
|
||||
}
|
||||
|
||||
private static long tryParseLong(String value, long defValue) {
|
||||
if (TextUtils.isEmpty(value)) return defValue;
|
||||
try {
|
||||
return Long.valueOf(value);
|
||||
} catch (NumberFormatException e) {
|
||||
return defValue;
|
||||
}
|
||||
}
|
||||
|
||||
public static ZenModeConfig readXml(XmlPullParser parser, Migration migration)
|
||||
throws XmlPullParserException, IOException {
|
||||
int type = parser.getEventType();
|
||||
@@ -367,7 +376,7 @@ public class ZenModeConfig implements Parcelable {
|
||||
rt.conditionId = safeUri(parser, RULE_ATT_CONDITION_ID);
|
||||
rt.component = safeComponentName(parser, RULE_ATT_COMPONENT);
|
||||
rt.condition = readConditionXml(parser);
|
||||
return rt.condition != null || !conditionRequired ? rt : null;
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static void writeRuleXml(ZenRule rule, XmlSerializer out) throws IOException {
|
||||
@@ -568,10 +577,12 @@ public class ZenModeConfig implements Parcelable {
|
||||
Condition.FLAG_RELEVANT_NOW);
|
||||
}
|
||||
|
||||
// For built-in conditions
|
||||
// ==== Built-in system conditions ====
|
||||
|
||||
public static final String SYSTEM_AUTHORITY = "android";
|
||||
|
||||
// Built-in countdown conditions, e.g. condition://android/countdown/1399917958951
|
||||
// ==== Built-in system condition: countdown ====
|
||||
|
||||
public static final String COUNTDOWN_PATH = "countdown";
|
||||
|
||||
public static Uri toCountdownConditionId(long time) {
|
||||
@@ -598,9 +609,43 @@ public class ZenModeConfig implements Parcelable {
|
||||
return tryParseCountdownConditionId(conditionId) != 0;
|
||||
}
|
||||
|
||||
// built-in schedule conditions
|
||||
// ==== Built-in system condition: schedule ====
|
||||
|
||||
public static final String SCHEDULE_PATH = "schedule";
|
||||
|
||||
public static Uri toScheduleConditionId(ScheduleInfo schedule) {
|
||||
return new Uri.Builder().scheme(Condition.SCHEME)
|
||||
.authority(SYSTEM_AUTHORITY)
|
||||
.appendPath(SCHEDULE_PATH)
|
||||
.appendQueryParameter("days", toDayList(schedule.days))
|
||||
.appendQueryParameter("start", schedule.startHour + "." + schedule.startMinute)
|
||||
.appendQueryParameter("end", schedule.endHour + "." + schedule.endMinute)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static boolean isValidScheduleConditionId(Uri conditionId) {
|
||||
return tryParseScheduleConditionId(conditionId) != null;
|
||||
}
|
||||
|
||||
public static ScheduleInfo tryParseScheduleConditionId(Uri conditionId) {
|
||||
final boolean isSchedule = conditionId != null
|
||||
&& conditionId.getScheme().equals(Condition.SCHEME)
|
||||
&& conditionId.getAuthority().equals(ZenModeConfig.SYSTEM_AUTHORITY)
|
||||
&& conditionId.getPathSegments().size() == 1
|
||||
&& conditionId.getPathSegments().get(0).equals(ZenModeConfig.SCHEDULE_PATH);
|
||||
if (!isSchedule) return null;
|
||||
final int[] start = tryParseHourAndMinute(conditionId.getQueryParameter("start"));
|
||||
final int[] end = tryParseHourAndMinute(conditionId.getQueryParameter("end"));
|
||||
if (start == null || end == null) return null;
|
||||
final ScheduleInfo rt = new ScheduleInfo();
|
||||
rt.days = tryParseDayList(conditionId.getQueryParameter("days"), "\\.");
|
||||
rt.startHour = start[0];
|
||||
rt.startMinute = start[1];
|
||||
rt.endHour = end[0];
|
||||
rt.endMinute = end[1];
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static class ScheduleInfo {
|
||||
public int[] days;
|
||||
public int startHour;
|
||||
@@ -638,39 +683,76 @@ public class ZenModeConfig implements Parcelable {
|
||||
}
|
||||
}
|
||||
|
||||
public static Uri toScheduleConditionId(ScheduleInfo schedule) {
|
||||
// ==== Built-in system condition: event ====
|
||||
|
||||
public static final String EVENT_PATH = "event";
|
||||
|
||||
public static Uri toEventConditionId(EventInfo event) {
|
||||
return new Uri.Builder().scheme(Condition.SCHEME)
|
||||
.authority(SYSTEM_AUTHORITY)
|
||||
.appendPath(SCHEDULE_PATH)
|
||||
.appendQueryParameter("days", toDayList(schedule.days))
|
||||
.appendQueryParameter("start", schedule.startHour + "." + schedule.startMinute)
|
||||
.appendQueryParameter("end", schedule.endHour + "." + schedule.endMinute)
|
||||
.appendPath(EVENT_PATH)
|
||||
.appendQueryParameter("calendar", Long.toString(event.calendar))
|
||||
.appendQueryParameter("attendance", Integer.toString(event.attendance))
|
||||
.appendQueryParameter("reply", Integer.toString(event.reply))
|
||||
.build();
|
||||
}
|
||||
|
||||
public static boolean isValidScheduleConditionId(Uri conditionId) {
|
||||
return tryParseScheduleConditionId(conditionId) != null;
|
||||
public static boolean isValidEventConditionId(Uri conditionId) {
|
||||
return tryParseEventConditionId(conditionId) != null;
|
||||
}
|
||||
|
||||
public static ScheduleInfo tryParseScheduleConditionId(Uri conditionId) {
|
||||
final boolean isSchedule = conditionId != null
|
||||
public static EventInfo tryParseEventConditionId(Uri conditionId) {
|
||||
final boolean isEvent = conditionId != null
|
||||
&& conditionId.getScheme().equals(Condition.SCHEME)
|
||||
&& conditionId.getAuthority().equals(ZenModeConfig.SYSTEM_AUTHORITY)
|
||||
&& conditionId.getPathSegments().size() == 1
|
||||
&& conditionId.getPathSegments().get(0).equals(ZenModeConfig.SCHEDULE_PATH);
|
||||
if (!isSchedule) return null;
|
||||
final int[] start = tryParseHourAndMinute(conditionId.getQueryParameter("start"));
|
||||
final int[] end = tryParseHourAndMinute(conditionId.getQueryParameter("end"));
|
||||
if (start == null || end == null) return null;
|
||||
final ScheduleInfo rt = new ScheduleInfo();
|
||||
rt.days = tryParseDayList(conditionId.getQueryParameter("days"), "\\.");
|
||||
rt.startHour = start[0];
|
||||
rt.startMinute = start[1];
|
||||
rt.endHour = end[0];
|
||||
rt.endMinute = end[1];
|
||||
&& conditionId.getPathSegments().get(0).equals(EVENT_PATH);
|
||||
if (!isEvent) return null;
|
||||
final EventInfo rt = new EventInfo();
|
||||
rt.calendar = tryParseLong(conditionId.getQueryParameter("calendar"), 0L);
|
||||
rt.attendance = tryParseInt(conditionId.getQueryParameter("attendance"), 0);
|
||||
rt.reply = tryParseInt(conditionId.getQueryParameter("reply"), 0);
|
||||
return rt;
|
||||
}
|
||||
|
||||
public static class EventInfo {
|
||||
public static final int ATTENDANCE_REQUIRED_OR_OPTIONAL = 0;
|
||||
public static final int ATTENDANCE_REQUIRED = 1;
|
||||
public static final int ATTENDANCE_OPTIONAL = 2;
|
||||
|
||||
public static final int REPLY_ANY = 0;
|
||||
public static final int REPLY_ANY_EXCEPT_NO = 1;
|
||||
public static final int REPLY_YES = 2;
|
||||
|
||||
public long calendar; // CalendarContract.Calendars._ID, or 0 for any
|
||||
public int attendance;
|
||||
public int reply;
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof EventInfo)) return false;
|
||||
final EventInfo other = (EventInfo) o;
|
||||
return calendar == other.calendar
|
||||
&& attendance == other.attendance
|
||||
&& reply == other.reply;
|
||||
}
|
||||
|
||||
public EventInfo copy() {
|
||||
final EventInfo rt = new EventInfo();
|
||||
rt.calendar = calendar;
|
||||
rt.attendance = attendance;
|
||||
rt.reply = reply;
|
||||
return rt;
|
||||
}
|
||||
}
|
||||
|
||||
// ==== End built-in system conditions ====
|
||||
|
||||
private static int[] tryParseHourAndMinute(String value) {
|
||||
if (TextUtils.isEmpty(value)) return null;
|
||||
final int i = value.indexOf('.');
|
||||
|
||||
@@ -26,11 +26,12 @@ import android.os.Build;
|
||||
*/
|
||||
public class MetricsLogger implements MetricsConstants {
|
||||
// These constants are temporary, they should migrate to MetricsConstants.
|
||||
// next value is 146;
|
||||
// next value is 148;
|
||||
|
||||
public static final int NOTIFICATION_ZEN_MODE_SCHEDULE_RULE = 144;
|
||||
public static final int NOTIFICATION_ZEN_MODE_EXTERNAL_RULE = 145;
|
||||
public static final int ACTION_BAN_APP_NOTES = 146;
|
||||
public static final int NOTIFICATION_ZEN_MODE_EVENT_RULE = 147;
|
||||
|
||||
public static void visible(Context context, int category) throws IllegalArgumentException {
|
||||
if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) {
|
||||
|
||||
@@ -2054,6 +2054,7 @@
|
||||
<string-array translatable="false" name="config_system_condition_providers">
|
||||
<item>countdown</item>
|
||||
<item>schedule</item>
|
||||
<item>event</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Priority repeat caller threshold, in minutes -->
|
||||
|
||||
@@ -64,7 +64,7 @@ public class CountdownConditionProvider extends SystemConditionProviderService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidConditionid(Uri id) {
|
||||
public boolean isValidConditionId(Uri id) {
|
||||
return ZenModeConfig.isValidCountdownConditionId(id);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.notification;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.service.notification.Condition;
|
||||
import android.service.notification.IConditionProvider;
|
||||
import android.service.notification.ZenModeConfig;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.server.notification.NotificationManagerService.DumpFilter;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* Built-in zen condition provider for calendar event-based conditions.
|
||||
*/
|
||||
public class EventConditionProvider extends SystemConditionProviderService {
|
||||
private static final String TAG = "ConditionProviders";
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
|
||||
public static final ComponentName COMPONENT =
|
||||
new ComponentName("android", EventConditionProvider.class.getName());
|
||||
private static final String NOT_SHOWN = "...";
|
||||
|
||||
private final ArraySet<Uri> mSubscriptions = new ArraySet<Uri>();
|
||||
|
||||
private boolean mConnected;
|
||||
private boolean mRegistered;
|
||||
|
||||
public EventConditionProvider() {
|
||||
if (DEBUG) Slog.d(TAG, "new EventConditionProvider()");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComponentName getComponent() {
|
||||
return COMPONENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidConditionId(Uri id) {
|
||||
return ZenModeConfig.isValidEventConditionId(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dump(PrintWriter pw, DumpFilter filter) {
|
||||
pw.println(" EventConditionProvider:");
|
||||
pw.print(" mConnected="); pw.println(mConnected);
|
||||
pw.print(" mRegistered="); pw.println(mRegistered);
|
||||
pw.println(" mSubscriptions=");
|
||||
for (Uri conditionId : mSubscriptions) {
|
||||
pw.print(" ");
|
||||
pw.println(conditionId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnected() {
|
||||
if (DEBUG) Slog.d(TAG, "onConnected");
|
||||
mConnected = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (DEBUG) Slog.d(TAG, "onDestroy");
|
||||
mConnected = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestConditions(int relevance) {
|
||||
if (DEBUG) Slog.d(TAG, "onRequestConditions relevance=" + relevance);
|
||||
// does not advertise conditions
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSubscribe(Uri conditionId) {
|
||||
if (DEBUG) Slog.d(TAG, "onSubscribe " + conditionId);
|
||||
if (!ZenModeConfig.isValidEventConditionId(conditionId)) {
|
||||
notifyCondition(conditionId, Condition.STATE_FALSE, "badCondition");
|
||||
return;
|
||||
}
|
||||
mSubscriptions.add(conditionId);
|
||||
evaluateSubscriptions();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnsubscribe(Uri conditionId) {
|
||||
if (DEBUG) Slog.d(TAG, "onUnsubscribe " + conditionId);
|
||||
if (mSubscriptions.remove(conditionId)) {
|
||||
evaluateSubscriptions();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attachBase(Context base) {
|
||||
attachBaseContext(base);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IConditionProvider asInterface() {
|
||||
return (IConditionProvider) onBind(null);
|
||||
}
|
||||
|
||||
private void evaluateSubscriptions() {
|
||||
for (Uri conditionId : mSubscriptions) {
|
||||
notifyCondition(conditionId, Condition.STATE_FALSE, "notImplemented");
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyCondition(Uri conditionId, int state, String reason) {
|
||||
if (DEBUG) Slog.d(TAG, "notifyCondition " + Condition.stateToString(state)
|
||||
+ " reason=" + reason);
|
||||
notifyCondition(createCondition(conditionId, state));
|
||||
}
|
||||
|
||||
private Condition createCondition(Uri id, int state) {
|
||||
final String summary = NOT_SHOWN;
|
||||
final String line1 = NOT_SHOWN;
|
||||
final String line2 = NOT_SHOWN;
|
||||
return new Condition(id, summary, line1, line2, 0, state, Condition.FLAG_RELEVANT_ALWAYS);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -69,7 +69,7 @@ public class ScheduleConditionProvider extends SystemConditionProviderService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValidConditionid(Uri id) {
|
||||
public boolean isValidConditionId(Uri id) {
|
||||
return ZenModeConfig.isValidScheduleConditionId(id);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,5 +32,5 @@ public abstract class SystemConditionProviderService extends ConditionProviderSe
|
||||
abstract public void attachBase(Context context);
|
||||
abstract public IConditionProvider asInterface();
|
||||
abstract public ComponentName getComponent();
|
||||
abstract public boolean isValidConditionid(Uri id);
|
||||
abstract public boolean isValidConditionId(Uri id);
|
||||
}
|
||||
|
||||
@@ -38,20 +38,19 @@ public class ZenModeConditions implements ConditionProviders.Callback {
|
||||
private final ConditionProviders mConditionProviders;
|
||||
private final ArrayMap<Uri, ComponentName> mSubscriptions = new ArrayMap<>();
|
||||
|
||||
private CountdownConditionProvider mCountdown;
|
||||
private ScheduleConditionProvider mSchedule;
|
||||
private boolean mFirstEvaluation = true;
|
||||
|
||||
public ZenModeConditions(ZenModeHelper helper, ConditionProviders conditionProviders) {
|
||||
mHelper = helper;
|
||||
mConditionProviders = conditionProviders;
|
||||
if (mConditionProviders.isSystemProviderEnabled(ZenModeConfig.COUNTDOWN_PATH)) {
|
||||
mCountdown = new CountdownConditionProvider();
|
||||
mConditionProviders.addSystemProvider(mCountdown);
|
||||
mConditionProviders.addSystemProvider(new CountdownConditionProvider());
|
||||
}
|
||||
if (mConditionProviders.isSystemProviderEnabled(ZenModeConfig.SCHEDULE_PATH)) {
|
||||
mSchedule = new ScheduleConditionProvider();
|
||||
mConditionProviders.addSystemProvider(mSchedule);
|
||||
mConditionProviders.addSystemProvider(new ScheduleConditionProvider());
|
||||
}
|
||||
if (mConditionProviders.isSystemProviderEnabled(ZenModeConfig.EVENT_PATH)) {
|
||||
mConditionProviders.addSystemProvider(new EventConditionProvider());
|
||||
}
|
||||
mConditionProviders.setCallback(this);
|
||||
}
|
||||
@@ -128,7 +127,7 @@ public class ZenModeConditions implements ConditionProviders.Callback {
|
||||
final Uri id = rule.conditionId;
|
||||
boolean isSystemCondition = false;
|
||||
for (SystemConditionProviderService sp : mConditionProviders.getSystemProviders()) {
|
||||
if (sp.isValidConditionid(id)) {
|
||||
if (sp.isValidConditionId(id)) {
|
||||
mConditionProviders.ensureRecordExists(sp.getComponent(), id, sp.asInterface());
|
||||
rule.component = sp.getComponent();
|
||||
isSystemCondition = true;
|
||||
|
||||
Reference in New Issue
Block a user