am cd9eb9be: am 27ef0188: Merge "NoMan/SysUI: Clear LEDs only when entering the shade" into lmp-mr1-dev

* commit 'cd9eb9bee788252cd6d6bcdb7fcdc5a5d0dcfe5c':
  NoMan/SysUI: Clear LEDs only when entering the shade
This commit is contained in:
Christoph Studer
2014-12-02 19:08:13 +00:00
committed by Android Git Automerger
8 changed files with 97 additions and 26 deletions

View File

@@ -40,8 +40,10 @@ interface IStatusBarService
// You need the STATUS_BAR_SERVICE permission // You need the STATUS_BAR_SERVICE permission
void registerStatusBar(IStatusBar callbacks, out StatusBarIconList iconList, void registerStatusBar(IStatusBar callbacks, out StatusBarIconList iconList,
out int[] switches, out List<IBinder> binders); out int[] switches, out List<IBinder> binders);
void onPanelRevealed(); void onPanelRevealed(boolean clearNotificationEffects);
void onPanelHidden(); void onPanelHidden();
// Mark current notifications as "seen" and stop ringing, vibrating, blinking.
void clearNotificationEffects();
void onNotificationClick(String key); void onNotificationClick(String key);
void onNotificationActionClick(String key, int actionIndex); void onNotificationActionClick(String key, int actionIndex);
void onNotificationError(String pkg, String tag, int id, void onNotificationError(String pkg, String tag, int id,

View File

@@ -28,6 +28,7 @@ public interface DozeHost {
void pulseWhileDozing(@NonNull PulseCallback callback, int reason); void pulseWhileDozing(@NonNull PulseCallback callback, int reason);
void stopDozing(); void stopDozing();
boolean isPowerSaveActive(); boolean isPowerSaveActive();
boolean isNotificationLightOn();
public interface Callback { public interface Callback {
void onNewNotifications(); void onNewNotifications();
@@ -40,4 +41,4 @@ public interface DozeHost {
void onPulseStarted(); void onPulseStarted();
void onPulseFinished(); void onPulseFinished();
} }
} }

View File

@@ -56,6 +56,17 @@ public class DozeService extends DreamService {
private static final String NOTIFICATION_PULSE_ACTION = ACTION_BASE + ".notification_pulse"; private static final String NOTIFICATION_PULSE_ACTION = ACTION_BASE + ".notification_pulse";
private static final String EXTRA_INSTANCE = "instance"; 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 String mTag = String.format(TAG + ".%08x", hashCode());
private final Context mContext = this; private final Context mContext = this;
private final DozeParameters mDozeParameters = new DozeParameters(mContext); private final DozeParameters mDozeParameters = new DozeParameters(mContext);
@@ -77,6 +88,7 @@ public class DozeService extends DreamService {
private boolean mPowerSaveActive; private boolean mPowerSaveActive;
private boolean mCarMode; private boolean mCarMode;
private long mNotificationPulseTime; private long mNotificationPulseTime;
private long mEarliestPulseDueToLight;
private int mScheduleResetsRemaining; private int mScheduleResetsRemaining;
public DozeService() { public DozeService() {
@@ -161,8 +173,9 @@ public class DozeService extends DreamService {
} }
mDreaming = true; mDreaming = true;
listenForPulseSignals(true);
rescheduleNotificationPulse(false /*predicate*/); // cancel any pending pulse alarms 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. // Ask the host to get things ready to start dozing.
// Once ready, we call startDozing() at which point the CPU may suspend // Once ready, we call startDozing() at which point the CPU may suspend
@@ -298,6 +311,12 @@ public class DozeService extends DreamService {
if (listen) { if (listen) {
resetNotificationResets(); resetNotificationResets();
mHost.addCallback(mHostCallback); mHost.addCallback(mHostCallback);
// Continue to pulse for existing LEDs.
mNotificationLightOn = mHost.isNotificationLightOn();
if (mNotificationLightOn) {
updateNotificationPulseDueToLight();
}
} else { } else {
mHost.removeCallback(mHostCallback); mHost.removeCallback(mHostCallback);
} }
@@ -308,21 +327,26 @@ public class DozeService extends DreamService {
mScheduleResetsRemaining = mDozeParameters.getPulseScheduleResets(); mScheduleResetsRemaining = mDozeParameters.getPulseScheduleResets();
} }
private void updateNotificationPulse() { private void updateNotificationPulseDueToLight() {
if (DEBUG) Log.d(mTag, "updateNotificationPulse"); long timeMs = System.currentTimeMillis();
timeMs = Math.max(timeMs, mEarliestPulseDueToLight);
updateNotificationPulse(timeMs);
}
private void updateNotificationPulse(long notificationTimeMs) {
if (DEBUG) Log.d(mTag, "updateNotificationPulse notificationTimeMs=" + notificationTimeMs);
if (!mDozeParameters.getPulseOnNotifications()) return; if (!mDozeParameters.getPulseOnNotifications()) return;
if (mScheduleResetsRemaining <= 0) { if (mScheduleResetsRemaining <= 0) {
if (DEBUG) Log.d(mTag, "No more schedule resets remaining"); if (DEBUG) Log.d(mTag, "No more schedule resets remaining");
return; return;
} }
final long now = System.currentTimeMillis(); if ((notificationTimeMs - mNotificationPulseTime) < mDozeParameters.getPulseDuration()) {
if ((now - mNotificationPulseTime) < mDozeParameters.getPulseDuration()) {
if (DEBUG) Log.d(mTag, "Recently updated, not resetting schedule"); if (DEBUG) Log.d(mTag, "Recently updated, not resetting schedule");
return; return;
} }
mScheduleResetsRemaining--; mScheduleResetsRemaining--;
if (DEBUG) Log.d(mTag, "mScheduleResetsRemaining = " + mScheduleResetsRemaining); if (DEBUG) Log.d(mTag, "mScheduleResetsRemaining = " + mScheduleResetsRemaining);
mNotificationPulseTime = now; mNotificationPulseTime = notificationTimeMs;
rescheduleNotificationPulse(true /*predicate*/); rescheduleNotificationPulse(true /*predicate*/);
} }
@@ -404,14 +428,14 @@ public class DozeService extends DreamService {
private final DozeHost.Callback mHostCallback = new DozeHost.Callback() { private final DozeHost.Callback mHostCallback = new DozeHost.Callback() {
@Override @Override
public void onNewNotifications() { public void onNewNotifications() {
if (DEBUG) Log.d(mTag, "onNewNotifications"); if (DEBUG) Log.d(mTag, "onNewNotifications (noop)");
// noop for now // noop for now
} }
@Override @Override
public void onBuzzBeepBlinked() { public void onBuzzBeepBlinked() {
if (DEBUG) Log.d(mTag, "onBuzzBeepBlinked"); if (DEBUG) Log.d(mTag, "onBuzzBeepBlinked");
updateNotificationPulse(); updateNotificationPulse(System.currentTimeMillis());
} }
@Override @Override
@@ -420,7 +444,7 @@ public class DozeService extends DreamService {
if (mNotificationLightOn == on) return; if (mNotificationLightOn == on) return;
mNotificationLightOn = on; mNotificationLightOn = on;
if (mNotificationLightOn) { if (mNotificationLightOn) {
updateNotificationPulse(); updateNotificationPulseDueToLight();
} }
} }

View File

@@ -1648,7 +1648,11 @@ public abstract class BaseStatusBar extends SystemUI implements
protected void handleVisibleToUserChanged(boolean visibleToUser) { protected void handleVisibleToUserChanged(boolean visibleToUser) {
try { try {
if (visibleToUser) { if (visibleToUser) {
mBarService.onPanelRevealed(); // Only stop blinking, vibrating, ringing when the user went into the shade
// manually (SHADE or SHADE_LOCKED).
boolean clearNotificationEffects =
(mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED);
mBarService.onPanelRevealed(clearNotificationEffects);
} else { } else {
mBarService.onPanelHidden(); mBarService.onPanelHidden();
} }

View File

@@ -3795,6 +3795,16 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
* @param state The {@link StatusBarState} to set. * @param state The {@link StatusBarState} to set.
*/ */
public void setBarState(int state) { public void setBarState(int state) {
// If we're visible and switched to SHADE_LOCKED (the user dragged down
// on the lockscreen), clear notification LED, vibration, ringing.
// Other transitions are covered in handleVisibleToUserChanged().
if (mVisible && mState != state && state == StatusBarState.SHADE_LOCKED) {
try {
mBarService.clearNotificationEffects();
} catch (RemoteException e) {
// Ignore.
}
}
mState = state; mState = state;
mStatusBarWindowManager.setStatusBarState(state); mStatusBarWindowManager.setStatusBarState(state);
} }
@@ -4126,6 +4136,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>(); private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
private final H mHandler = new H(); private final H mHandler = new H();
// Keeps the last reported state by fireNotificationLight.
private boolean mNotificationLightOn;
@Override @Override
public String toString() { public String toString() {
return "PSB.DozeServiceHost[mCallbacks=" + mCallbacks.size() + "]"; return "PSB.DozeServiceHost[mCallbacks=" + mCallbacks.size() + "]";
@@ -4144,6 +4157,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
} }
public void fireNotificationLight(boolean on) { public void fireNotificationLight(boolean on) {
mNotificationLightOn = on;
for (Callback callback : mCallbacks) { for (Callback callback : mCallbacks) {
callback.onNotificationLight(on); callback.onNotificationLight(on);
} }
@@ -4185,6 +4199,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
return mBatteryController != null && mBatteryController.isPowerSave(); return mBatteryController != null && mBatteryController.isPowerSave();
} }
@Override
public boolean isNotificationLightOn() {
return mNotificationLightOn;
}
private void handleStartDozing(@NonNull Runnable ready) { private void handleStartDozing(@NonNull Runnable ready) {
if (!mDozing) { if (!mDozing) {
mDozing = true; mDozing = true;

View File

@@ -26,8 +26,9 @@ public interface NotificationDelegate {
void onNotificationError(int callingUid, int callingPid, void onNotificationError(int callingUid, int callingPid,
String pkg, String tag, int id, String pkg, String tag, int id,
int uid, int initialPid, String message, int userId); int uid, int initialPid, String message, int userId);
void onPanelRevealed(); void onPanelRevealed(boolean clearEffects);
void onPanelHidden(); void onPanelHidden();
void clearEffects();
void onNotificationVisibilityChanged( void onNotificationVisibilityChanged(
String[] newlyVisibleKeys, String[] noLongerVisibleKeys); String[] newlyVisibleKeys, String[] noLongerVisibleKeys);
void onNotificationExpansionChanged(String key, boolean userAction, boolean expanded); void onNotificationExpansionChanged(String key, boolean userAction, boolean expanded);

View File

@@ -123,7 +123,7 @@ import java.util.Objects;
/** {@hide} */ /** {@hide} */
public class NotificationManagerService extends SystemService { public class NotificationManagerService extends SystemService {
static final String TAG = "NotificationService"; static final String TAG = "NotificationService";
static final boolean DBG = false; static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
static final int MAX_PACKAGE_NOTIFICATIONS = 50; static final int MAX_PACKAGE_NOTIFICATIONS = 50;
@@ -577,9 +577,23 @@ public class NotificationManagerService extends SystemService {
} }
@Override @Override
public void onPanelRevealed() { public void onPanelRevealed(boolean clearEffects) {
EventLogTags.writeNotificationPanelRevealed(); EventLogTags.writeNotificationPanelRevealed();
if (clearEffects) {
clearEffects();
}
}
@Override
public void onPanelHidden() {
EventLogTags.writeNotificationPanelHidden();
}
@Override
public void clearEffects() {
synchronized (mNotificationList) { synchronized (mNotificationList) {
if (DBG) Slog.d(TAG, "clearEffects");
// sound // sound
mSoundNotification = null; mSoundNotification = null;
@@ -610,11 +624,6 @@ public class NotificationManagerService extends SystemService {
} }
} }
@Override
public void onPanelHidden() {
EventLogTags.writeNotificationPanelHidden();
}
@Override @Override
public void onNotificationError(int callingUid, int callingPid, String pkg, String tag, int id, public void onNotificationError(int callingUid, int callingPid, String pkg, String tag, int id,
int uid, int initialPid, String message, int userId) { int uid, int initialPid, String message, int userId) {
@@ -753,8 +762,10 @@ public class NotificationManagerService extends SystemService {
// Keep track of screen on/off state, but do not turn off the notification light // Keep track of screen on/off state, but do not turn off the notification light
// until user passes through the lock screen or views the notification. // until user passes through the lock screen or views the notification.
mScreenOn = true; mScreenOn = true;
updateNotificationPulse();
} else if (action.equals(Intent.ACTION_SCREEN_OFF)) { } else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
mScreenOn = false; mScreenOn = false;
updateNotificationPulse();
} else if (action.equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) { } else if (action.equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) {
mInCall = TelephonyManager.EXTRA_STATE_OFFHOOK mInCall = TelephonyManager.EXTRA_STATE_OFFHOOK
.equals(intent.getStringExtra(TelephonyManager.EXTRA_STATE)); .equals(intent.getStringExtra(TelephonyManager.EXTRA_STATE));

View File

@@ -26,7 +26,6 @@ import android.content.Context;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.res.Resources; import android.content.res.Resources;
import android.util.Slog; import android.util.Slog;
import android.view.WindowManager;
import com.android.internal.statusbar.IStatusBar; import com.android.internal.statusbar.IStatusBar;
import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.IStatusBarService;
@@ -495,16 +494,26 @@ public class StatusBarManagerService extends IStatusBarService.Stub {
} }
/** /**
* The status bar service should call this each time the user brings the panel from * @param clearNotificationEffects whether to consider notifications as "shown" and stop
* invisible to visible in order to clear the notification light. * LED, vibration, and ringing
*/ */
@Override @Override
public void onPanelRevealed() { public void onPanelRevealed(boolean clearNotificationEffects) {
enforceStatusBarService(); enforceStatusBarService();
long identity = Binder.clearCallingIdentity(); long identity = Binder.clearCallingIdentity();
try { try {
// tell the notification manager to turn off the lights. mNotificationDelegate.onPanelRevealed(clearNotificationEffects);
mNotificationDelegate.onPanelRevealed(); } finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public void clearNotificationEffects() throws RemoteException {
enforceStatusBarService();
long identity = Binder.clearCallingIdentity();
try {
mNotificationDelegate.clearEffects();
} finally { } finally {
Binder.restoreCallingIdentity(identity); Binder.restoreCallingIdentity(identity);
} }