diff options
author | John Spurlock <jspurlock@google.com> | 2014-08-13 09:19:03 -0400 |
---|---|---|
committer | Dan Sandler <dsandler@android.com> | 2014-08-15 15:06:15 +0000 |
commit | 4db0d98b42a723f2e16c6595e85e866fd26c6d98 (patch) | |
tree | 3238267bd845d7e7f171be5bd741e7b6d5a75d19 /services/core | |
parent | 65c09b10ca73d369e836074eeba38e01cd4c05b6 (diff) | |
download | frameworks_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')
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() {} |