OSDN Git Service

Ambient: Pulse for every noisy notification exactly once
authorAdrian Roos <roosa@google.com>
Mon, 22 Aug 2016 13:31:38 +0000 (15:31 +0200)
committerAdrian Roos <roosa@google.com>
Tue, 23 Aug 2016 11:58:31 +0000 (13:58 +0200)
Also increases the pulse duration and switches timing to
elapsed realtime instead of wall time for robustness. Also
remove triggering for notification light for simplifying code.
Only noisy notifications are able to trigger the light anyway and
noisy notifications already trigger ambient on their own.

Change-Id: I4efbe530bb1a60cabaa46c2b04bcd5e12cdef680
Fixes: 31004875

packages/SystemUI/res/values/config.xml
packages/SystemUI/src/com/android/systemui/doze/DozeLog.java
packages/SystemUI/src/com/android/systemui/doze/DozeService.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java

index c2897cd..8d44048 100644 (file)
     <!-- Doze: should notifications be used as a pulse signal? -->
     <bool name="doze_pulse_on_notifications">true</bool>
 
-    <!-- Doze: when to pulse after a buzzworthy notification arrives -->
-    <string name="doze_pulse_schedule" translatable="false">10s,30s,60s</string>
-
-    <!-- Doze: maximum number of times the notification pulse schedule can be reset -->
-    <integer name="doze_pulse_schedule_resets">2</integer>
-
     <!-- Doze: duration to avoid false pickup gestures triggered by notification vibrations -->
     <integer name="doze_pickup_vibration_threshold">2000</integer>
 
     <integer name="doze_pulse_duration_in_pickup">130</integer>
 
     <!-- Doze: pulse parameter - once faded in, how long does it stay visible? -->
-    <integer name="doze_pulse_duration_visible">3000</integer>
+    <integer name="doze_pulse_duration_visible">6000</integer>
 
     <!-- Doze: pulse parameter - how long does it take to fade out? -->
     <integer name="doze_pulse_duration_out">600</integer>
index 7c8d0f6..874021a 100644 (file)
@@ -33,7 +33,7 @@ public class DozeLog {
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     private static final boolean ENABLED = true;
     private static final int SIZE = Build.IS_DEBUGGABLE ? 400 : 50;
-    private static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
+    static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
 
     private static final int PULSE_REASONS = 4;
 
index fc0d8bb..ec4f447 100644 (file)
@@ -16,8 +16,6 @@
 
 package com.android.systemui.doze;
 
-import android.app.AlarmManager;
-import android.app.PendingIntent;
 import android.app.UiModeManager;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -43,7 +41,6 @@ import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.MetricsProto.MetricsEvent;
 import com.android.systemui.SystemUIApplication;
 import com.android.systemui.statusbar.phone.DozeParameters;
-import com.android.systemui.statusbar.phone.DozeParameters.PulseSchedule;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -55,19 +52,6 @@ public class DozeService extends DreamService {
 
     private static final String ACTION_BASE = "com.android.systemui.doze";
     private static final String PULSE_ACTION = ACTION_BASE + ".pulse";
-    private static final String NOTIFICATION_PULSE_ACTION = ACTION_BASE + ".notification_pulse";
-    private static final String EXTRA_INSTANCE = "instance";
-
-    /**
-     * Earliest time we pulse due to a notification light after the service started.
-     *
-     * <p>Incoming notification light events during the blackout period are
-     * delayed to the earliest time defined by this constant.</p>
-     *
-     * <p>This delay avoids a pulse immediately after screen off, at which
-     * point the notification light is re-enabled again by NoMan.</p>
-     */
-    private static final int EARLIEST_LIGHT_PULSE_AFTER_START_MS = 10 * 1000;
 
     private final String mTag = String.format(TAG + ".%08x", hashCode());
     private final Context mContext = this;
@@ -80,19 +64,14 @@ public class DozeService extends DreamService {
     private TriggerSensor mPickupSensor;
     private PowerManager mPowerManager;
     private PowerManager.WakeLock mWakeLock;
-    private AlarmManager mAlarmManager;
     private UiModeManager mUiModeManager;
     private boolean mDreaming;
     private boolean mPulsing;
     private boolean mBroadcastReceiverRegistered;
     private boolean mDisplayStateSupported;
-    private boolean mNotificationLightOn;
     private boolean mPowerSaveActive;
     private boolean mCarMode;
     private long mNotificationPulseTime;
-    private long mLastScheduleResetTime;
-    private long mEarliestPulseDueToLight;
-    private int mScheduleResetsRemaining;
 
     public DozeService() {
         if (DEBUG) Log.d(mTag, "new DozeService()");
@@ -110,11 +89,11 @@ public class DozeService extends DreamService {
         pw.print("  mSigMotionSensor: "); pw.println(mSigMotionSensor);
         pw.print("  mPickupSensor:"); pw.println(mPickupSensor);
         pw.print("  mDisplayStateSupported: "); pw.println(mDisplayStateSupported);
-        pw.print("  mNotificationLightOn: "); pw.println(mNotificationLightOn);
         pw.print("  mPowerSaveActive: "); pw.println(mPowerSaveActive);
         pw.print("  mCarMode: "); pw.println(mCarMode);
-        pw.print("  mNotificationPulseTime: "); pw.println(mNotificationPulseTime);
-        pw.print("  mScheduleResetsRemaining: "); pw.println(mScheduleResetsRemaining);
+        pw.print("  mNotificationPulseTime: "); pw.println(
+                DozeLog.FORMAT.format(new Date(mNotificationPulseTime
+                        - SystemClock.elapsedRealtime() + System.currentTimeMillis())));
         mDozeParameters.dump(pw);
     }
 
@@ -141,7 +120,6 @@ public class DozeService extends DreamService {
         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
         mWakeLock.setReferenceCounted(true);
-        mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
         mDisplayStateSupported = mDozeParameters.getDisplayStateSupported();
         mUiModeManager = (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE);
         turnDisplayOff();
@@ -176,8 +154,6 @@ public class DozeService extends DreamService {
         }
 
         mDreaming = true;
-        rescheduleNotificationPulse(false /*predicate*/);  // cancel any pending pulse alarms
-        mEarliestPulseDueToLight = System.currentTimeMillis() + EARLIEST_LIGHT_PULSE_AFTER_START_MS;
         listenForPulseSignals(true);
 
         // Ask the host to get things ready to start dozing.
@@ -316,7 +292,6 @@ public class DozeService extends DreamService {
     private void listenForBroadcasts(boolean listen) {
         if (listen) {
             final IntentFilter filter = new IntentFilter(PULSE_ACTION);
-            filter.addAction(NOTIFICATION_PULSE_ACTION);
             filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
             mContext.registerReceiver(mBroadcastReceiver, filter);
             mBroadcastReceiverRegistered = true;
@@ -330,93 +305,17 @@ public class DozeService extends DreamService {
 
     private void listenForNotifications(boolean listen) {
         if (listen) {
-            resetNotificationResets();
             mHost.addCallback(mHostCallback);
-
-            // Continue to pulse for existing LEDs.
-            mNotificationLightOn = mHost.isNotificationLightOn();
-            if (mNotificationLightOn) {
-                updateNotificationPulseDueToLight();
-            }
         } else {
             mHost.removeCallback(mHostCallback);
         }
     }
 
-    private void resetNotificationResets() {
-        if (DEBUG) Log.d(mTag, "resetNotificationResets");
-        mScheduleResetsRemaining = mDozeParameters.getPulseScheduleResets();
-    }
-
-    private void updateNotificationPulseDueToLight() {
-        long timeMs = System.currentTimeMillis();
-        timeMs = Math.max(timeMs, mEarliestPulseDueToLight);
-        updateNotificationPulse(timeMs);
-    }
-
-    private void updateNotificationPulse(long notificationTimeMs) {
-        if (DEBUG) Log.d(mTag, "updateNotificationPulse notificationTimeMs=" + notificationTimeMs);
+    private void requestNotificationPulse() {
+        if (DEBUG) Log.d(mTag, "requestNotificationPulse");
         if (!mDozeParameters.getPulseOnNotifications()) return;
-        if (mScheduleResetsRemaining <= 0) {
-            if (DEBUG) Log.d(mTag, "No more schedule resets remaining");
-            return;
-        }
-        final long pulseDuration = mDozeParameters.getPulseDuration(false /*pickup*/);
-        boolean pulseImmediately = System.currentTimeMillis() >= notificationTimeMs;
-        if ((notificationTimeMs - mLastScheduleResetTime) >= pulseDuration) {
-            mScheduleResetsRemaining--;
-            mLastScheduleResetTime = notificationTimeMs;
-        } else if (!pulseImmediately){
-            if (DEBUG) Log.d(mTag, "Recently updated, not resetting schedule");
-            return;
-        }
-        if (DEBUG) Log.d(mTag, "mScheduleResetsRemaining = " + mScheduleResetsRemaining);
-        mNotificationPulseTime = notificationTimeMs;
-        if (pulseImmediately) {
-            DozeLog.traceNotificationPulse(mContext, 0);
-            requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
-        }
-        // schedule the rest of the pulses
-        rescheduleNotificationPulse(true /*predicate*/);
-    }
-
-    private PendingIntent notificationPulseIntent(long instance) {
-        return PendingIntent.getBroadcast(mContext, 0,
-                new Intent(NOTIFICATION_PULSE_ACTION)
-                        .setPackage(getPackageName())
-                        .putExtra(EXTRA_INSTANCE, instance)
-                        .setFlags(Intent.FLAG_RECEIVER_FOREGROUND),
-                PendingIntent.FLAG_UPDATE_CURRENT);
-    }
-
-    private void rescheduleNotificationPulse(boolean predicate) {
-        if (DEBUG) Log.d(mTag, "rescheduleNotificationPulse predicate=" + predicate);
-        final PendingIntent notificationPulseIntent = notificationPulseIntent(0);
-        mAlarmManager.cancel(notificationPulseIntent);
-        if (!predicate) {
-            if (DEBUG) Log.d(mTag, "  don't reschedule: predicate is false");
-            return;
-        }
-        final PulseSchedule schedule = mDozeParameters.getPulseSchedule();
-        if (schedule == null) {
-            if (DEBUG) Log.d(mTag, "  don't reschedule: schedule is null");
-            return;
-        }
-        final long now = System.currentTimeMillis();
-        final long time = schedule.getNextTime(now, mNotificationPulseTime);
-        if (time <= 0) {
-            if (DEBUG) Log.d(mTag, "  don't reschedule: time is " + time);
-            return;
-        }
-        final long delta = time - now;
-        if (delta <= 0) {
-            if (DEBUG) Log.d(mTag, "  don't reschedule: delta is " + delta);
-            return;
-        }
-        final long instance = time - mNotificationPulseTime;
-        if (DEBUG) Log.d(mTag, "Scheduling pulse " + instance + " in " + delta + "ms for "
-                + new Date(time));
-        mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, time, notificationPulseIntent(instance));
+        mNotificationPulseTime = SystemClock.elapsedRealtime();
+        requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
     }
 
     private static String triggerEventToString(TriggerEvent event) {
@@ -439,13 +338,6 @@ public class DozeService extends DreamService {
                 if (DEBUG) Log.d(mTag, "Received pulse intent");
                 requestPulse(DozeLog.PULSE_REASON_INTENT);
             }
-            if (NOTIFICATION_PULSE_ACTION.equals(intent.getAction())) {
-                final long instance = intent.getLongExtra(EXTRA_INSTANCE, -1);
-                if (DEBUG) Log.d(mTag, "Received notification pulse intent instance=" + instance);
-                DozeLog.traceNotificationPulse(mContext, instance);
-                requestPulse(DozeLog.PULSE_REASON_NOTIFICATION);
-                rescheduleNotificationPulse(mNotificationLightOn);
-            }
             if (UiModeManager.ACTION_ENTER_CAR_MODE.equals(intent.getAction())) {
                 mCarMode = true;
                 if (mCarMode && mDreaming) {
@@ -465,17 +357,13 @@ public class DozeService extends DreamService {
         @Override
         public void onBuzzBeepBlinked() {
             if (DEBUG) Log.d(mTag, "onBuzzBeepBlinked");
-            updateNotificationPulse(System.currentTimeMillis());
+            requestNotificationPulse();
         }
 
         @Override
         public void onNotificationLight(boolean on) {
-            if (DEBUG) Log.d(mTag, "onNotificationLight on=" + on);
-            if (mNotificationLightOn == on) return;
-            mNotificationLightOn = on;
-            if (mNotificationLightOn) {
-                updateNotificationPulseDueToLight();
-            }
+            if (DEBUG) Log.d(mTag, "onNotificationLight (noop) on=" + on);
+            // noop for now
         }
 
         @Override
@@ -564,17 +452,12 @@ public class DozeService extends DreamService {
                 requestPulse(mPulseReason, sensorPerformsProxCheck);
                 updateListener();  // reregister, this sensor only fires once
 
-                // reset the notification pulse schedule, but only if we think we were not triggered
-                // by a notification-related vibration
-                final long timeSinceNotification = System.currentTimeMillis()
+                // record pickup gesture, also keep track of whether we might have been triggered
+                // by recent vibration.
+                final long timeSinceNotification = SystemClock.elapsedRealtime()
                         - mNotificationPulseTime;
                 final boolean withinVibrationThreshold =
                         timeSinceNotification < mDozeParameters.getPickupVibrationThreshold();
-                if (withinVibrationThreshold) {
-                   if (DEBUG) Log.d(mTag, "Not resetting schedule, recent notification");
-                } else {
-                    resetNotificationResets();
-                }
                 if (mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) {
                     DozeLog.tracePickupPulse(mContext, withinVibrationThreshold);
                 }
index 9b3ed33..efceed1 100644 (file)
@@ -38,8 +38,6 @@ public class DozeParameters {
 
     private final Context mContext;
 
-    private static PulseSchedule sPulseSchedule;
-
     private static IntInOutMatcher sPickupSubtypePerformsProxMatcher;
 
     public DozeParameters(Context context) {
@@ -61,8 +59,6 @@ public class DozeParameters {
         pw.print("    getVibrateOnPickup(): "); pw.println(getVibrateOnPickup());
         pw.print("    getProxCheckBeforePulse(): "); pw.println(getProxCheckBeforePulse());
         pw.print("    getPulseOnNotifications(): "); pw.println(getPulseOnNotifications());
-        pw.print("    getPulseSchedule(): "); pw.println(getPulseSchedule());
-        pw.print("    getPulseScheduleResets(): "); pw.println(getPulseScheduleResets());
         pw.print("    getPickupVibrationThreshold(): "); pw.println(getPickupVibrationThreshold());
         pw.print("    getPickupSubtypePerformsProxCheck(): ");pw.println(
                 dumpPickupSubtypePerformsProxCheck());
@@ -126,18 +122,6 @@ public class DozeParameters {
         return getBoolean("doze.pulse.notifications", R.bool.doze_pulse_on_notifications);
     }
 
-    public PulseSchedule getPulseSchedule() {
-        final String spec = getString("doze.pulse.schedule", R.string.doze_pulse_schedule);
-        if (sPulseSchedule == null || !sPulseSchedule.mSpec.equals(spec)) {
-            sPulseSchedule = PulseSchedule.parse(spec);
-        }
-        return sPulseSchedule;
-    }
-
-    public int getPulseScheduleResets() {
-        return getInt("doze.pulse.schedule.resets", R.integer.doze_pulse_schedule_resets);
-    }
-
     public int getPickupVibrationThreshold() {
         return getInt("doze.pickup.vibration.threshold", R.integer.doze_pickup_vibration_threshold);
     }
@@ -249,44 +233,4 @@ public class DozeParameters {
             return (mIsIn.get(value, mDefaultIsIn));
         }
     }
-
-    public static class PulseSchedule {
-        private static final Pattern PATTERN = Pattern.compile("(\\d+?)s", 0);
-
-        private String mSpec;
-        private int[] mSchedule;
-
-        public static PulseSchedule parse(String spec) {
-            if (TextUtils.isEmpty(spec)) return null;
-            try {
-                final PulseSchedule rt = new PulseSchedule();
-                rt.mSpec = spec;
-                final String[] tokens = spec.split(",");
-                rt.mSchedule = new int[tokens.length];
-                for (int i = 0; i < tokens.length; i++) {
-                    final Matcher m = PATTERN.matcher(tokens[i]);
-                    if (!m.matches()) throw new IllegalArgumentException("Bad token: " + tokens[i]);
-                    rt.mSchedule[i] = Integer.parseInt(m.group(1));
-                }
-                if (DEBUG) Log.d(TAG, "Parsed spec [" + spec + "] as: " + rt);
-                return rt;
-            } catch (RuntimeException e) {
-                Log.w(TAG, "Error parsing spec: " + spec, e);
-                return null;
-            }
-        }
-
-        @Override
-        public String toString() {
-            return Arrays.toString(mSchedule);
-        }
-
-        public long getNextTime(long now, long notificationTime) {
-            for (int i = 0; i < mSchedule.length; i++) {
-                final long time = notificationTime + mSchedule[i] * 1000;
-                if (time > now) return time;
-            }
-            return 0;
-        }
-    }
 }