summaryrefslogtreecommitdiffstats
path: root/services/core
diff options
context:
space:
mode:
authorJohn Spurlock <jspurlock@google.com>2014-08-13 09:19:03 -0400
committerDan Sandler <dsandler@android.com>2014-08-15 15:06:15 +0000
commit4db0d98b42a723f2e16c6595e85e866fd26c6d98 (patch)
tree3238267bd845d7e7f171be5bd741e7b6d5a75d19 /services/core
parent65c09b10ca73d369e836074eeba38e01cd4c05b6 (diff)
downloadframeworks_base-4db0d98b42a723f2e16c6595e85e866fd26c6d98.zip
frameworks_base-4db0d98b42a723f2e16c6595e85e866fd26c6d98.tar.gz
frameworks_base-4db0d98b42a723f2e16c6595e85e866fd26c6d98.tar.bz2
Zen: Downtime now a condition provider, persist conditions.
- Persist the entire exit condition instead of only the id. - Make downtime a proper condition provider (similar to the existing countdown provider for time-based conditions) - Move all downtime-related items out of ZenModeHelper and into the new condition provider. - Reevaluate downtime more often, when any of its inputs change. - Make sure downtime appears as an available condition in the condition panel when applicable. Bug:16296125 Bug:16211189 Bug:17031767 Change-Id: I1d8269a4e6fe170ce776bf932dbbdfb29dd25dd7
Diffstat (limited to 'services/core')
-rw-r--r--services/core/java/com/android/server/notification/ConditionProviders.java90
-rw-r--r--services/core/java/com/android/server/notification/CountdownConditionProvider.java5
-rw-r--r--services/core/java/com/android/server/notification/DowntimeConditionProvider.java289
-rw-r--r--services/core/java/com/android/server/notification/ManagedServices.java3
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java4
-rw-r--r--services/core/java/com/android/server/notification/ZenLog.java35
-rw-r--r--services/core/java/com/android/server/notification/ZenModeHelper.java108
7 files changed, 396 insertions, 138 deletions
diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java
index a06daf6..189131c 100644
--- a/services/core/java/com/android/server/notification/ConditionProviders.java
+++ b/services/core/java/com/android/server/notification/ConditionProviders.java
@@ -51,8 +51,9 @@ public class ConditionProviders extends ManagedServices {
= new ArrayMap<IBinder, IConditionListener>();
private final ArrayList<ConditionRecord> mRecords = new ArrayList<ConditionRecord>();
private final CountdownConditionProvider mCountdown = new CountdownConditionProvider();
+ private final DowntimeConditionProvider mDowntime = new DowntimeConditionProvider();
- private Uri mExitConditionId;
+ private Condition mExitCondition;
private ComponentName mExitConditionComponent;
public ConditionProviders(Context context, Handler handler,
@@ -97,6 +98,7 @@ public class ConditionProviders extends ManagedServices {
}
}
mCountdown.dump(pw, filter);
+ mDowntime.dump(pw, filter);
}
@Override
@@ -110,6 +112,10 @@ public class ConditionProviders extends ManagedServices {
mCountdown.attachBase(mContext);
registerService(mCountdown.asInterface(), CountdownConditionProvider.COMPONENT,
UserHandle.USER_OWNER);
+ mDowntime.attachBase(mContext);
+ registerService(mDowntime.asInterface(), DowntimeConditionProvider.COMPONENT,
+ UserHandle.USER_OWNER);
+ mDowntime.setCallback(new DowntimeCallback());
}
@Override
@@ -125,7 +131,7 @@ public class ConditionProviders extends ManagedServices {
if (info.component.equals(mExitConditionComponent)) {
// ensure record exists, we'll wire it up and subscribe below
final ConditionRecord manualRecord =
- getRecordLocked(mExitConditionId, mExitConditionComponent);
+ getRecordLocked(mExitCondition.id, mExitConditionComponent);
manualRecord.isManual = true;
}
final int N = mRecords.size();
@@ -149,11 +155,11 @@ public class ConditionProviders extends ManagedServices {
if (!r.component.equals(removed.component)) continue;
if (r.isManual) {
// removing the current manual condition, exit zen
- mZenModeHelper.setZenMode(Global.ZEN_MODE_OFF);
+ mZenModeHelper.setZenMode(Global.ZEN_MODE_OFF, "manualServiceRemoved");
}
if (r.isAutomatic) {
// removing an automatic condition, exit zen
- mZenModeHelper.setZenMode(Global.ZEN_MODE_OFF);
+ mZenModeHelper.setZenMode(Global.ZEN_MODE_OFF, "automaticServiceRemoved");
}
mRecords.remove(i);
}
@@ -249,7 +255,8 @@ public class ConditionProviders extends ManagedServices {
} else if (DEBUG) {
Slog.d(TAG, "Exit zen: manual condition false: " + c);
}
- mZenModeHelper.setZenMode(Settings.Global.ZEN_MODE_OFF);
+ mZenModeHelper.setZenMode(Settings.Global.ZEN_MODE_OFF,
+ "manualConditionExit");
unsubscribeLocked(r);
r.isManual = false;
}
@@ -263,33 +270,46 @@ public class ConditionProviders extends ManagedServices {
} else if (DEBUG) {
Slog.d(TAG, "Exit zen: automatic condition false: " + c);
}
- mZenModeHelper.setZenMode(Settings.Global.ZEN_MODE_OFF);
+ mZenModeHelper.setZenMode(Settings.Global.ZEN_MODE_OFF,
+ "automaticConditionExit");
} else if (c.state == Condition.STATE_TRUE) {
Slog.d(TAG, "Enter zen: automatic condition true: " + c);
- mZenModeHelper.setZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
+ mZenModeHelper.setZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ "automaticConditionEnter");
}
}
}
}
}
- public void setZenModeCondition(Uri conditionId, String reason) {
- if (DEBUG) Slog.d(TAG, "setZenModeCondition " + conditionId);
+ public void setZenModeCondition(Condition condition, String reason) {
+ if (DEBUG) Slog.d(TAG, "setZenModeCondition " + condition);
synchronized(mMutex) {
ComponentName conditionComponent = null;
- if (ZenModeConfig.isValidCountdownConditionId(conditionId)) {
- // constructed by the client, make sure the record exists...
- final ConditionRecord r = getRecordLocked(conditionId,
- CountdownConditionProvider.COMPONENT);
- if (r.info == null) {
- // ... and is associated with the in-process service
- r.info = checkServiceTokenLocked(mCountdown.asInterface());
+ if (condition != null) {
+ if (ZenModeConfig.isValidCountdownConditionId(condition.id)) {
+ // constructed by the client, make sure the record exists...
+ final ConditionRecord r = getRecordLocked(condition.id,
+ CountdownConditionProvider.COMPONENT);
+ if (r.info == null) {
+ // ... and is associated with the in-process service
+ r.info = checkServiceTokenLocked(mCountdown.asInterface());
+ }
+ }
+ if (ZenModeConfig.isValidDowntimeConditionId(condition.id)) {
+ // constructed by the client, make sure the record exists...
+ final ConditionRecord r = getRecordLocked(condition.id,
+ DowntimeConditionProvider.COMPONENT);
+ if (r.info == null) {
+ // ... and is associated with the in-process service
+ r.info = checkServiceTokenLocked(mDowntime.asInterface());
+ }
}
}
final int N = mRecords.size();
for (int i = 0; i < N; i++) {
final ConditionRecord r = mRecords.get(i);
- final boolean idEqual = r.id.equals(conditionId);
+ final boolean idEqual = condition != null && r.id.equals(condition.id);
if (r.isManual && !idEqual) {
// was previous manual condition, unsubscribe
unsubscribeLocked(r);
@@ -303,10 +323,10 @@ public class ConditionProviders extends ManagedServices {
conditionComponent = r.component;
}
}
- if (!Objects.equals(mExitConditionId, conditionId)) {
- mExitConditionId = conditionId;
+ if (!Objects.equals(mExitCondition, condition)) {
+ mExitCondition = condition;
mExitConditionComponent = conditionComponent;
- ZenLog.traceExitCondition(mExitConditionId, mExitConditionComponent, reason);
+ ZenLog.traceExitCondition(mExitCondition, mExitConditionComponent, reason);
saveZenConfigLocked();
}
}
@@ -318,6 +338,7 @@ public class ConditionProviders extends ManagedServices {
RemoteException re = null;
if (provider != null) {
try {
+ Slog.d(TAG, "Subscribing to " + r.id + " with " + provider);
provider.onSubscribe(r.id);
} catch (RemoteException e) {
Slog.w(TAG, "Error subscribing to " + r, e);
@@ -436,12 +457,13 @@ public class ConditionProviders extends ManagedServices {
return;
}
synchronized (mMutex) {
- final boolean changingExit = !Objects.equals(mExitConditionId, config.exitConditionId);
- mExitConditionId = config.exitConditionId;
+ final boolean changingExit = !Objects.equals(mExitCondition, config.exitCondition);
+ mExitCondition = config.exitCondition;
mExitConditionComponent = config.exitConditionComponent;
if (changingExit) {
- ZenLog.traceExitCondition(mExitConditionId, mExitConditionComponent, "config");
+ ZenLog.traceExitCondition(mExitCondition, mExitConditionComponent, "config");
}
+ mDowntime.setConfig(config);
if (config.conditionComponents == null || config.conditionIds == null
|| config.conditionComponents.length != config.conditionIds.length) {
if (DEBUG) Slog.d(TAG, "loadZenConfig: no conditions");
@@ -488,7 +510,7 @@ public class ConditionProviders extends ManagedServices {
config.conditionIds[i] = r.id;
}
}
- config.exitConditionId = mExitConditionId;
+ config.exitCondition = mExitCondition;
config.exitConditionComponent = mExitConditionComponent;
if (DEBUG) Slog.d(TAG, "Setting zen config to: " + config);
mZenModeHelper.setConfig(config);
@@ -510,6 +532,26 @@ public class ConditionProviders extends ManagedServices {
}
}
+ private class DowntimeCallback implements DowntimeConditionProvider.Callback {
+ @Override
+ public void onDowntimeChanged(boolean inDowntime) {
+ final int mode = mZenModeHelper.getZenMode();
+ final ZenModeConfig config = mZenModeHelper.getConfig();
+ // enter downtime
+ if (inDowntime && mode == Global.ZEN_MODE_OFF && config != null) {
+ final Condition condition = mDowntime.createCondition(config.toDowntimeInfo(),
+ Condition.STATE_TRUE);
+ mZenModeHelper.setZenMode(Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, "downtimeEnter");
+ setZenModeCondition(condition, "downtime");
+ }
+ // exit downtime
+ if (!inDowntime && mode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
+ && mDowntime.isDowntimeCondition(mExitCondition)) {
+ mZenModeHelper.setZenMode(Global.ZEN_MODE_OFF, "downtimeExit");
+ }
+ }
+ }
+
private static class ConditionRecord {
public final Uri id;
public final ComponentName component;
diff --git a/services/core/java/com/android/server/notification/CountdownConditionProvider.java b/services/core/java/com/android/server/notification/CountdownConditionProvider.java
index aaf7cfc..37aacaa 100644
--- a/services/core/java/com/android/server/notification/CountdownConditionProvider.java
+++ b/services/core/java/com/android/server/notification/CountdownConditionProvider.java
@@ -29,6 +29,7 @@ import android.service.notification.ConditionProviderService;
import android.service.notification.IConditionProvider;
import android.service.notification.ZenModeConfig;
import android.text.format.DateUtils;
+import android.util.Log;
import android.util.Slog;
import com.android.server.notification.NotificationManagerService.DumpFilter;
@@ -38,8 +39,8 @@ import java.util.Date;
/** Built-in zen condition provider for simple time-based conditions */
public class CountdownConditionProvider extends ConditionProviderService {
- private static final String TAG = "CountdownConditionProvider";
- private static final boolean DEBUG = false;
+ private static final String TAG = "CountdownConditions";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
public static final ComponentName COMPONENT =
new ComponentName("android", CountdownConditionProvider.class.getName());
diff --git a/services/core/java/com/android/server/notification/DowntimeConditionProvider.java b/services/core/java/com/android/server/notification/DowntimeConditionProvider.java
new file mode 100644
index 0000000..317ebef
--- /dev/null
+++ b/services/core/java/com/android/server/notification/DowntimeConditionProvider.java
@@ -0,0 +1,289 @@
+/**
+ * Copyright (c) 2014, 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.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+import android.service.notification.Condition;
+import android.service.notification.ConditionProviderService;
+import android.service.notification.IConditionProvider;
+import android.service.notification.ZenModeConfig;
+import android.service.notification.ZenModeConfig.DowntimeInfo;
+import android.text.format.DateFormat;
+import android.util.ArraySet;
+import android.util.Log;
+import android.util.Slog;
+
+import com.android.internal.R;
+import com.android.server.notification.NotificationManagerService.DumpFilter;
+
+import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+import java.util.Objects;
+
+/** Built-in zen condition provider for managing downtime */
+public class DowntimeConditionProvider extends ConditionProviderService {
+ private static final String TAG = "DowntimeConditions";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ public static final ComponentName COMPONENT =
+ new ComponentName("android", DowntimeConditionProvider.class.getName());
+
+ private static final String ENTER_ACTION = TAG + ".enter";
+ private static final int ENTER_CODE = 100;
+ private static final String EXIT_ACTION = TAG + ".exit";
+ private static final int EXIT_CODE = 101;
+ private static final String EXTRA_TIME = "time";
+
+ private final Calendar mCalendar = Calendar.getInstance();
+ private final Context mContext = this;
+ private final ArraySet<Integer> mDays = new ArraySet<Integer>();
+
+ private boolean mConnected;
+ private boolean mInDowntime;
+ private ZenModeConfig mConfig;
+ private Callback mCallback;
+
+ public DowntimeConditionProvider() {
+ if (DEBUG) Slog.d(TAG, "new DowntimeConditionProvider()");
+ }
+
+ public void dump(PrintWriter pw, DumpFilter filter) {
+ pw.println(" DowntimeConditionProvider:");
+ pw.print(" mConnected="); pw.println(mConnected);
+ pw.print(" mInDowntime="); pw.println(mInDowntime);
+ }
+
+ public void attachBase(Context base) {
+ attachBaseContext(base);
+ }
+
+ public IConditionProvider asInterface() {
+ return (IConditionProvider) onBind(null);
+ }
+
+ public void setCallback(Callback callback) {
+ mCallback = callback;
+ }
+
+ @Override
+ public void onConnected() {
+ if (DEBUG) Slog.d(TAG, "onConnected");
+ mConnected = true;
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(ENTER_ACTION);
+ filter.addAction(EXIT_ACTION);
+ filter.addAction(Intent.ACTION_TIME_CHANGED);
+ filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
+ mContext.registerReceiver(mReceiver, filter);
+ init();
+ }
+
+ @Override
+ public void onDestroy() {
+ if (DEBUG) Slog.d(TAG, "onDestroy");
+ mConnected = false;
+ }
+
+ @Override
+ public void onRequestConditions(int relevance) {
+ if (DEBUG) Slog.d(TAG, "onRequestConditions relevance=" + relevance);
+ if ((relevance & Condition.FLAG_RELEVANT_NOW) != 0) {
+ if (mInDowntime && mConfig != null) {
+ notifyCondition(createCondition(mConfig.toDowntimeInfo(), Condition.STATE_TRUE));
+ }
+ }
+ }
+
+ @Override
+ public void onSubscribe(Uri conditionId) {
+ if (DEBUG) Slog.d(TAG, "onSubscribe conditionId=" + conditionId);
+ final DowntimeInfo downtime = ZenModeConfig.tryParseDowntimeConditionId(conditionId);
+ if (downtime != null && mConfig != null) {
+ final int state = mConfig.toDowntimeInfo().equals(downtime) && mInDowntime
+ ? Condition.STATE_TRUE : Condition.STATE_FALSE;
+ if (DEBUG) Slog.d(TAG, "notify condition state: " + Condition.stateToString(state));
+ notifyCondition(createCondition(downtime, state));
+ }
+ }
+
+ @Override
+ public void onUnsubscribe(Uri conditionId) {
+ if (DEBUG) Slog.d(TAG, "onUnsubscribe conditionId=" + conditionId);
+ }
+
+ public void setConfig(ZenModeConfig config) {
+ if (Objects.equals(mConfig, config)) return;
+ if (DEBUG) Slog.d(TAG, "setConfig");
+ mConfig = config;
+ if (mConnected) {
+ init();
+ }
+ }
+
+ public boolean isInDowntime() {
+ return mInDowntime;
+ }
+
+ public Condition createCondition(DowntimeInfo downtime, int state) {
+ if (downtime == null) return null;
+ final Uri id = ZenModeConfig.toDowntimeConditionId(downtime);
+ final String skeleton = DateFormat.is24HourFormat(mContext) ? "Hm" : "hma";
+ final Locale locale = Locale.getDefault();
+ final String pattern = DateFormat.getBestDateTimePattern(locale, skeleton);
+ final long time = getTime(System.currentTimeMillis(), downtime.endHour, downtime.endMinute);
+ final String formatted = new SimpleDateFormat(pattern, locale).format(new Date(time));
+ final String summary = mContext.getString(R.string.downtime_condition_summary, formatted);
+ return new Condition(id, summary, "", "", 0, state, Condition.FLAG_RELEVANT_NOW);
+ }
+
+ public boolean isDowntimeCondition(Condition condition) {
+ return condition != null && ZenModeConfig.isValidDowntimeConditionId(condition.id);
+ }
+
+ private void init() {
+ updateDays();
+ reevaluateDowntime();
+ updateAlarms();
+ }
+
+ private void updateDays() {
+ mDays.clear();
+ if (mConfig != null) {
+ final int[] days = ZenModeConfig.tryParseDays(mConfig.sleepMode);
+ for (int i = 0; days != null && i < days.length; i++) {
+ mDays.add(days[i]);
+ }
+ }
+ }
+
+ private boolean isInDowntime(long time) {
+ if (mConfig == null || mDays.size() == 0) return false;
+ final long start = getTime(time, mConfig.sleepStartHour, mConfig.sleepStartMinute);
+ long end = getTime(time, mConfig.sleepEndHour, mConfig.sleepEndMinute);
+ if (start == end) return false;
+ if (end < start) {
+ end = addDays(end, 1);
+ }
+ return isInDowntime(-1, time, start, end) || isInDowntime(0, time, start, end);
+ }
+
+ private boolean isInDowntime(int daysOffset, long time, long start, long end) {
+ final int day = ((getDayOfWeek(time) + daysOffset - 1) % Calendar.SATURDAY) + 1;
+ start = addDays(start, daysOffset);
+ end = addDays(end, daysOffset);
+ return mDays.contains(day) && time >= start && time < end;
+ }
+
+ private void reevaluateDowntime() {
+ final boolean inDowntime = isInDowntime(System.currentTimeMillis());
+ if (DEBUG) Slog.d(TAG, "inDowntime=" + inDowntime);
+ if (inDowntime == mInDowntime) return;
+ Slog.i(TAG, (inDowntime ? "Entering" : "Exiting" ) + " downtime");
+ mInDowntime = inDowntime;
+ ZenLog.traceDowntime(mInDowntime, getDayOfWeek(System.currentTimeMillis()), mDays);
+ fireDowntimeChanged();
+ }
+
+ private void fireDowntimeChanged() {
+ if (mCallback != null) {
+ mCallback.onDowntimeChanged(mInDowntime);
+ }
+ }
+
+ private void updateAlarms() {
+ if (mConfig == null) return;
+ updateAlarm(ENTER_ACTION, ENTER_CODE, mConfig.sleepStartHour, mConfig.sleepStartMinute);
+ updateAlarm(EXIT_ACTION, EXIT_CODE, mConfig.sleepEndHour, mConfig.sleepEndMinute);
+ }
+
+ private int getDayOfWeek(long time) {
+ mCalendar.setTimeInMillis(time);
+ return mCalendar.get(Calendar.DAY_OF_WEEK);
+ }
+
+ private long getTime(long millis, int hour, int min) {
+ mCalendar.setTimeInMillis(millis);
+ mCalendar.set(Calendar.HOUR_OF_DAY, hour);
+ mCalendar.set(Calendar.MINUTE, min);
+ mCalendar.set(Calendar.SECOND, 0);
+ mCalendar.set(Calendar.MILLISECOND, 0);
+ return mCalendar.getTimeInMillis();
+ }
+
+ private long addDays(long time, int days) {
+ mCalendar.setTimeInMillis(time);
+ mCalendar.add(Calendar.DATE, days);
+ return mCalendar.getTimeInMillis();
+ }
+
+ private void updateAlarm(String action, int requestCode, int hr, int min) {
+ final AlarmManager alarms = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
+ final long now = System.currentTimeMillis();
+ mCalendar.setTimeInMillis(now);
+ mCalendar.set(Calendar.HOUR_OF_DAY, hr);
+ mCalendar.set(Calendar.MINUTE, min);
+ mCalendar.set(Calendar.SECOND, 0);
+ mCalendar.set(Calendar.MILLISECOND, 0);
+ long time = mCalendar.getTimeInMillis();
+ if (time <= now) {
+ time = addDays(time, 1);
+ }
+ final PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, requestCode,
+ new Intent(action).putExtra(EXTRA_TIME, time), PendingIntent.FLAG_UPDATE_CURRENT);
+ alarms.cancel(pendingIntent);
+ if (mConfig.sleepMode != null) {
+ if (DEBUG) Slog.d(TAG, String.format("Scheduling %s for %s, %s in the future, now=%s",
+ action, ts(time), time - now, ts(now)));
+ alarms.setExact(AlarmManager.RTC_WAKEUP, time, pendingIntent);
+ }
+ }
+
+ private static String ts(long time) {
+ return new Date(time) + " (" + time + ")";
+ }
+
+ private BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ final long now = System.currentTimeMillis();
+ if (ENTER_ACTION.equals(action) || EXIT_ACTION.equals(action)) {
+ final long schTime = intent.getLongExtra(EXTRA_TIME, 0);
+ if (DEBUG) Slog.d(TAG, String.format("%s scheduled for %s, fired at %s, delta=%s",
+ action, ts(schTime), ts(now), now - schTime));
+ } else {
+ if (DEBUG) Slog.d(TAG, action + " fired at " + now);
+ }
+ reevaluateDowntime();
+ updateAlarms();
+ }
+ };
+
+ public interface Callback {
+ void onDowntimeChanged(boolean inDowntime);
+ }
+}
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 36be21f..f647037 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -41,6 +41,7 @@ import android.os.UserManager;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArraySet;
+import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
@@ -64,7 +65,7 @@ import java.util.Set;
*/
abstract public class ManagedServices {
protected final String TAG = getClass().getSimpleName();
- protected static final boolean DEBUG = true;
+ protected final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final String ENABLED_SERVICES_SEPARATOR = ":";
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index d6afe68..f2ac963 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1351,11 +1351,11 @@ public class NotificationManagerService extends SystemService {
}
@Override
- public void setZenModeCondition(Uri conditionId) {
+ public void setZenModeCondition(Condition condition) {
enforceSystemOrSystemUI("INotificationManager.setZenModeCondition");
final long identity = Binder.clearCallingIdentity();
try {
- mConditionProviders.setZenModeCondition(conditionId, "binderCall");
+ mConditionProviders.setZenModeCondition(condition, "binderCall");
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/services/core/java/com/android/server/notification/ZenLog.java b/services/core/java/com/android/server/notification/ZenLog.java
index b22ed2d..525f5f8 100644
--- a/services/core/java/com/android/server/notification/ZenLog.java
+++ b/services/core/java/com/android/server/notification/ZenLog.java
@@ -22,8 +22,10 @@ import android.net.Uri;
import android.os.Build;
import android.os.RemoteException;
import android.provider.Settings.Global;
+import android.service.notification.Condition;
import android.service.notification.IConditionProvider;
import android.service.notification.ZenModeConfig;
+import android.util.ArraySet;
import android.util.Slog;
import java.io.PrintWriter;
@@ -52,13 +54,14 @@ public class ZenLog {
private static final int TYPE_ALLOW_DISABLE = 2;
private static final int TYPE_SET_RINGER_MODE = 3;
private static final int TYPE_DOWNTIME = 4;
- private static final int TYPE_ZEN_MODE = 5;
- private static final int TYPE_EXIT_CONDITION = 6;
- private static final int TYPE_SUBSCRIBE = 7;
- private static final int TYPE_UNSUBSCRIBE = 8;
- private static final int TYPE_CONFIG = 9;
- private static final int TYPE_FOLLOW_RINGER_MODE = 10;
- private static final int TYPE_NOT_INTERCEPTED = 11;
+ private static final int TYPE_SET_ZEN_MODE = 5;
+ private static final int TYPE_UPDATE_ZEN_MODE = 6;
+ private static final int TYPE_EXIT_CONDITION = 7;
+ private static final int TYPE_SUBSCRIBE = 8;
+ private static final int TYPE_UNSUBSCRIBE = 9;
+ private static final int TYPE_CONFIG = 10;
+ private static final int TYPE_FOLLOW_RINGER_MODE = 11;
+ private static final int TYPE_NOT_INTERCEPTED = 12;
private static int sNext;
private static int sSize;
@@ -82,17 +85,20 @@ public class ZenLog {
append(TYPE_SET_RINGER_MODE, ringerModeToString(ringerMode));
}
- public static void traceDowntime(boolean enter, int day, int[] days) {
- append(TYPE_DOWNTIME, enter + ",day=" + day + ",days=" + (days != null ? Arrays.asList(days)
- : null));
+ public static void traceDowntime(boolean inDowntime, int day, ArraySet<Integer> days) {
+ append(TYPE_DOWNTIME, inDowntime + ",day=" + day + ",days=" + days);
+ }
+
+ public static void traceSetZenMode(int mode, String reason) {
+ append(TYPE_SET_ZEN_MODE, zenModeToString(mode) + "," + reason);
}
public static void traceUpdateZenMode(int fromMode, int toMode) {
- append(TYPE_ZEN_MODE, zenModeToString(fromMode) + " -> " + zenModeToString(toMode));
+ append(TYPE_UPDATE_ZEN_MODE, zenModeToString(fromMode) + " -> " + zenModeToString(toMode));
}
- public static void traceExitCondition(Uri id, ComponentName component, String reason) {
- append(TYPE_EXIT_CONDITION, id + "," + componentToString(component) + "," + reason);
+ public static void traceExitCondition(Condition c, ComponentName component, String reason) {
+ append(TYPE_EXIT_CONDITION, c + "," + componentToString(component) + "," + reason);
}
public static void traceSubscribe(Uri uri, IConditionProvider provider, RemoteException e) {
@@ -122,7 +128,8 @@ public class ZenLog {
case TYPE_ALLOW_DISABLE: return "allow_disable";
case TYPE_SET_RINGER_MODE: return "set_ringer_mode";
case TYPE_DOWNTIME: return "downtime";
- case TYPE_ZEN_MODE: return "zen_mode";
+ case TYPE_SET_ZEN_MODE: return "set_zen_mode";
+ case TYPE_UPDATE_ZEN_MODE: return "update_zen_mode";
case TYPE_EXIT_CONDITION: return "exit_condition";
case TYPE_SUBSCRIBE: return "subscribe";
case TYPE_UNSUBSCRIBE: return "unsubscribe";
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 9282283..b7b5f98 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -20,10 +20,8 @@ import static android.media.AudioAttributes.USAGE_ALARM;
import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
import static android.media.AudioAttributes.USAGE_UNKNOWN;
-import android.app.AlarmManager;
import android.app.AppOpsManager;
import android.app.Notification;
-import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -44,6 +42,7 @@ import android.provider.Settings.Secure;
import android.service.notification.NotificationListenerService;
import android.service.notification.ZenModeConfig;
import android.telecomm.TelecommManager;
+import android.util.Log;
import android.util.Slog;
import com.android.internal.R;
@@ -57,8 +56,6 @@ import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
import java.util.Objects;
/**
@@ -66,12 +63,7 @@ import java.util.Objects;
*/
public class ZenModeHelper {
private static final String TAG = "ZenModeHelper";
-
- private static final String ACTION_ENTER_ZEN = "enter_zen";
- private static final int REQUEST_CODE_ENTER = 100;
- private static final String ACTION_EXIT_ZEN = "exit_zen";
- private static final int REQUEST_CODE_EXIT = 101;
- private static final String EXTRA_TIME = "time";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private final Context mContext;
private final Handler mHandler;
@@ -96,10 +88,8 @@ public class ZenModeHelper {
mSettingsObserver.observe();
final IntentFilter filter = new IntentFilter();
- filter.addAction(ACTION_ENTER_ZEN);
- filter.addAction(ACTION_EXIT_ZEN);
filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
- mContext.registerReceiver(new ZenBroadcastReceiver(), filter);
+ mContext.registerReceiver(mReceiver, filter);
}
public static ZenModeConfig readDefaultConfig(Resources resources) {
@@ -156,7 +146,7 @@ public class ZenModeHelper {
public void requestFromListener(int hints) {
final int newZen = zenFromListenerHint(hints, -1);
if (newZen != -1) {
- setZenMode(newZen);
+ setZenMode(newZen, "listener");
}
}
@@ -208,7 +198,8 @@ public class ZenModeHelper {
return mZenMode;
}
- public void setZenMode(int zenModeValue) {
+ public void setZenMode(int zenModeValue, String reason) {
+ ZenLog.traceSetZenMode(zenModeValue, reason);
Global.putInt(mContext.getContentResolver(), Global.ZEN_MODE, zenModeValue);
}
@@ -216,9 +207,6 @@ public class ZenModeHelper {
final int mode = Global.getInt(mContext.getContentResolver(),
Global.ZEN_MODE, Global.ZEN_MODE_OFF);
if (mode != mZenMode) {
- Slog.d(TAG, String.format("updateZenMode: %s -> %s",
- Global.zenModeToString(mZenMode),
- Global.zenModeToString(mode)));
ZenLog.traceUpdateZenMode(mZenMode, mode);
}
mZenMode = mode;
@@ -255,12 +243,12 @@ public class ZenModeHelper {
if (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) {
if (ringerMode != AudioManager.RINGER_MODE_SILENT) {
mPreviousRingerMode = ringerMode;
- Slog.d(TAG, "Silencing ringer");
+ if (DEBUG) Slog.d(TAG, "Silencing ringer");
forcedRingerMode = AudioManager.RINGER_MODE_SILENT;
}
} else {
if (ringerMode == AudioManager.RINGER_MODE_SILENT) {
- Slog.d(TAG, "Unsilencing ringer");
+ if (DEBUG) Slog.d(TAG, "Unsilencing ringer");
forcedRingerMode = mPreviousRingerMode != -1 ? mPreviousRingerMode
: AudioManager.RINGER_MODE_NORMAL;
mPreviousRingerMode = -1;
@@ -318,7 +306,6 @@ public class ZenModeHelper {
dispatchOnConfigChanged();
final String val = Integer.toString(mConfig.hashCode());
Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_CONFIG_ETAG, val);
- updateAlarms();
updateZenMode();
return true;
}
@@ -339,7 +326,7 @@ public class ZenModeHelper {
}
if (newZen != -1) {
ZenLog.traceFollowRingerMode(ringerMode, mZenMode, newZen);
- setZenMode(newZen);
+ setZenMode(newZen, "ringerMode");
}
}
}
@@ -377,7 +364,7 @@ public class ZenModeHelper {
final TelecommManager telecomm =
(TelecommManager) mContext.getSystemService(Context.TELECOMM_SERVICE);
mDefaultPhoneApp = telecomm != null ? telecomm.getDefaultPhoneApp() : null;
- Slog.d(TAG, "Default phone app: " + mDefaultPhoneApp);
+ if (DEBUG) Slog.d(TAG, "Default phone app: " + mDefaultPhoneApp);
}
return pkg != null && mDefaultPhoneApp != null
&& pkg.equals(mDefaultPhoneApp.getPackageName());
@@ -409,40 +396,6 @@ public class ZenModeHelper {
}
}
- private void updateAlarms() {
- updateAlarm(ACTION_ENTER_ZEN, REQUEST_CODE_ENTER,
- mConfig.sleepStartHour, mConfig.sleepStartMinute);
- updateAlarm(ACTION_EXIT_ZEN, REQUEST_CODE_EXIT,
- mConfig.sleepEndHour, mConfig.sleepEndMinute);
- }
-
- private void updateAlarm(String action, int requestCode, int hr, int min) {
- final AlarmManager alarms = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
- final long now = System.currentTimeMillis();
- final Calendar c = Calendar.getInstance();
- c.setTimeInMillis(now);
- c.set(Calendar.HOUR_OF_DAY, hr);
- c.set(Calendar.MINUTE, min);
- c.set(Calendar.SECOND, 0);
- c.set(Calendar.MILLISECOND, 0);
- if (c.getTimeInMillis() <= now) {
- c.add(Calendar.DATE, 1);
- }
- final long time = c.getTimeInMillis();
- final PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, requestCode,
- new Intent(action).putExtra(EXTRA_TIME, time), PendingIntent.FLAG_UPDATE_CURRENT);
- alarms.cancel(pendingIntent);
- if (mConfig.sleepMode != null) {
- Slog.d(TAG, String.format("Scheduling %s for %s, %s in the future, now=%s",
- action, ts(time), time - now, ts(now)));
- alarms.setExact(AlarmManager.RTC_WAKEUP, time, pendingIntent);
- }
- }
-
- private static String ts(long time) {
- return new Date(time) + " (" + time + ")";
- }
-
private final Runnable mRingerModeChanged = new Runnable() {
@Override
public void run() {
@@ -475,47 +428,12 @@ public class ZenModeHelper {
}
}
- private class ZenBroadcastReceiver extends BroadcastReceiver {
- private final Calendar mCalendar = Calendar.getInstance();
-
+ private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- if (ACTION_ENTER_ZEN.equals(intent.getAction())) {
- setZenMode(intent, Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
- } else if (ACTION_EXIT_ZEN.equals(intent.getAction())) {
- setZenMode(intent, Global.ZEN_MODE_OFF);
- } else if (AudioManager.RINGER_MODE_CHANGED_ACTION.equals(intent.getAction())) {
- mHandler.post(mRingerModeChanged);
- }
- }
-
- private void setZenMode(Intent intent, int zenModeValue) {
- final long schTime = intent.getLongExtra(EXTRA_TIME, 0);
- final long now = System.currentTimeMillis();
- Slog.d(TAG, String.format("%s scheduled for %s, fired at %s, delta=%s",
- intent.getAction(), ts(schTime), ts(now), now - schTime));
-
- final int[] days = ZenModeConfig.tryParseDays(mConfig.sleepMode);
- boolean enter = false;
- final int day = getDayOfWeek(schTime);
- if (days != null) {
- for (int i = 0; i < days.length; i++) {
- if (days[i] == day) {
- enter = true;
- ZenModeHelper.this.setZenMode(zenModeValue);
- break;
- }
- }
- }
- ZenLog.traceDowntime(enter, day, days);
- updateAlarms();
+ mHandler.post(mRingerModeChanged);
}
-
- private int getDayOfWeek(long time) {
- mCalendar.setTimeInMillis(time);
- return mCalendar.get(Calendar.DAY_OF_WEEK);
- }
- }
+ };
public static class Callback {
void onConfigChanged() {}