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

This commit is contained in:
Christoph Studer
2014-12-02 18:49:49 +00:00
committed by Android (Google) Code Review
8 changed files with 97 additions and 26 deletions

View File

@@ -40,8 +40,10 @@ interface IStatusBarService
// You need the STATUS_BAR_SERVICE permission
void registerStatusBar(IStatusBar callbacks, out StatusBarIconList iconList,
out int[] switches, out List<IBinder> binders);
void onPanelRevealed();
void onPanelRevealed(boolean clearNotificationEffects);
void onPanelHidden();
// Mark current notifications as "seen" and stop ringing, vibrating, blinking.
void clearNotificationEffects();
void onNotificationClick(String key);
void onNotificationActionClick(String key, int actionIndex);
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 stopDozing();
boolean isPowerSaveActive();
boolean isNotificationLightOn();
public interface Callback {
void onNewNotifications();
@@ -40,4 +41,4 @@ public interface DozeHost {
void onPulseStarted();
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 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;
private final DozeParameters mDozeParameters = new DozeParameters(mContext);
@@ -77,6 +88,7 @@ public class DozeService extends DreamService {
private boolean mPowerSaveActive;
private boolean mCarMode;
private long mNotificationPulseTime;
private long mEarliestPulseDueToLight;
private int mScheduleResetsRemaining;
public DozeService() {
@@ -161,8 +173,9 @@ public class DozeService extends DreamService {
}
mDreaming = true;
listenForPulseSignals(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.
// Once ready, we call startDozing() at which point the CPU may suspend
@@ -298,6 +311,12 @@ public class DozeService extends DreamService {
if (listen) {
resetNotificationResets();
mHost.addCallback(mHostCallback);
// Continue to pulse for existing LEDs.
mNotificationLightOn = mHost.isNotificationLightOn();
if (mNotificationLightOn) {
updateNotificationPulseDueToLight();
}
} else {
mHost.removeCallback(mHostCallback);
}
@@ -308,21 +327,26 @@ public class DozeService extends DreamService {
mScheduleResetsRemaining = mDozeParameters.getPulseScheduleResets();
}
private void updateNotificationPulse() {
if (DEBUG) Log.d(mTag, "updateNotificationPulse");
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);
if (!mDozeParameters.getPulseOnNotifications()) return;
if (mScheduleResetsRemaining <= 0) {
if (DEBUG) Log.d(mTag, "No more schedule resets remaining");
return;
}
final long now = System.currentTimeMillis();
if ((now - mNotificationPulseTime) < mDozeParameters.getPulseDuration()) {
if ((notificationTimeMs - mNotificationPulseTime) < mDozeParameters.getPulseDuration()) {
if (DEBUG) Log.d(mTag, "Recently updated, not resetting schedule");
return;
}
mScheduleResetsRemaining--;
if (DEBUG) Log.d(mTag, "mScheduleResetsRemaining = " + mScheduleResetsRemaining);
mNotificationPulseTime = now;
mNotificationPulseTime = notificationTimeMs;
rescheduleNotificationPulse(true /*predicate*/);
}
@@ -404,14 +428,14 @@ public class DozeService extends DreamService {
private final DozeHost.Callback mHostCallback = new DozeHost.Callback() {
@Override
public void onNewNotifications() {
if (DEBUG) Log.d(mTag, "onNewNotifications");
if (DEBUG) Log.d(mTag, "onNewNotifications (noop)");
// noop for now
}
@Override
public void onBuzzBeepBlinked() {
if (DEBUG) Log.d(mTag, "onBuzzBeepBlinked");
updateNotificationPulse();
updateNotificationPulse(System.currentTimeMillis());
}
@Override
@@ -420,7 +444,7 @@ public class DozeService extends DreamService {
if (mNotificationLightOn == on) return;
mNotificationLightOn = on;
if (mNotificationLightOn) {
updateNotificationPulse();
updateNotificationPulseDueToLight();
}
}

View File

@@ -1648,7 +1648,11 @@ public abstract class BaseStatusBar extends SystemUI implements
protected void handleVisibleToUserChanged(boolean visibleToUser) {
try {
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 {
mBarService.onPanelHidden();
}

View File

@@ -3795,6 +3795,16 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
* @param state The {@link StatusBarState} to set.
*/
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;
mStatusBarWindowManager.setStatusBarState(state);
}
@@ -4126,6 +4136,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
private final H mHandler = new H();
// Keeps the last reported state by fireNotificationLight.
private boolean mNotificationLightOn;
@Override
public String toString() {
return "PSB.DozeServiceHost[mCallbacks=" + mCallbacks.size() + "]";
@@ -4144,6 +4157,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
public void fireNotificationLight(boolean on) {
mNotificationLightOn = on;
for (Callback callback : mCallbacks) {
callback.onNotificationLight(on);
}
@@ -4185,6 +4199,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
return mBatteryController != null && mBatteryController.isPowerSave();
}
@Override
public boolean isNotificationLightOn() {
return mNotificationLightOn;
}
private void handleStartDozing(@NonNull Runnable ready) {
if (!mDozing) {
mDozing = true;

View File

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

View File

@@ -123,7 +123,7 @@ import java.util.Objects;
/** {@hide} */
public class NotificationManagerService extends SystemService {
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;
@@ -577,9 +577,23 @@ public class NotificationManagerService extends SystemService {
}
@Override
public void onPanelRevealed() {
public void onPanelRevealed(boolean clearEffects) {
EventLogTags.writeNotificationPanelRevealed();
if (clearEffects) {
clearEffects();
}
}
@Override
public void onPanelHidden() {
EventLogTags.writeNotificationPanelHidden();
}
@Override
public void clearEffects() {
synchronized (mNotificationList) {
if (DBG) Slog.d(TAG, "clearEffects");
// sound
mSoundNotification = null;
@@ -610,11 +624,6 @@ public class NotificationManagerService extends SystemService {
}
}
@Override
public void onPanelHidden() {
EventLogTags.writeNotificationPanelHidden();
}
@Override
public void onNotificationError(int callingUid, int callingPid, String pkg, String tag, int id,
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
// until user passes through the lock screen or views the notification.
mScreenOn = true;
updateNotificationPulse();
} else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
mScreenOn = false;
updateNotificationPulse();
} else if (action.equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) {
mInCall = TelephonyManager.EXTRA_STATE_OFFHOOK
.equals(intent.getStringExtra(TelephonyManager.EXTRA_STATE));

View File

@@ -26,7 +26,6 @@ import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.util.Slog;
import android.view.WindowManager;
import com.android.internal.statusbar.IStatusBar;
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
* invisible to visible in order to clear the notification light.
* @param clearNotificationEffects whether to consider notifications as "shown" and stop
* LED, vibration, and ringing
*/
@Override
public void onPanelRevealed() {
public void onPanelRevealed(boolean clearNotificationEffects) {
enforceStatusBarService();
long identity = Binder.clearCallingIdentity();
try {
// tell the notification manager to turn off the lights.
mNotificationDelegate.onPanelRevealed();
mNotificationDelegate.onPanelRevealed(clearNotificationEffects);
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public void clearNotificationEffects() throws RemoteException {
enforceStatusBarService();
long identity = Binder.clearCallingIdentity();
try {
mNotificationDelegate.clearEffects();
} finally {
Binder.restoreCallingIdentity(identity);
}