AmbientDisplay: Add always on prototype
Test: adb shell settings put secure doze_always_on 1
Change-Id: I3f293b3ef43847b7848af416b44f212fc40514d4
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 03e0ebf..68b7b3a 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6001,6 +6001,12 @@
public static final String DOZE_ENABLED = "doze_enabled";
/**
+ * Whether doze should be always on.
+ * @hide
+ */
+ public static final String DOZE_ALWAYS_ON = "doze_always_on";
+
+ /**
* Whether the device should pulse on pick up gesture.
* @hide
*/
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 1b7a922..d8c8b82 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1667,6 +1667,14 @@
not appear on production builds ever. -->
<string name="plugins" translatable="false">Plugins</string>
+ <!-- Ambient display section of the tuner. Non-translatable since it should
+ not appear on production builds ever. -->
+ <string name="tuner_doze" translatable="false">Ambient Display</string>
+
+ <!-- Ambient display always-on of the tuner. Non-translatable since it should
+ not appear on production builds ever. -->
+ <string name="tuner_doze_always_on" translatable="false">Always on</string>
+
<!-- PIP section of the tuner. Non-translatable since it should
not appear on production builds ever. -->
<string name="picture_in_picture" translatable="false">Picture-in-Picture</string>
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index 46a9ee3..942f847 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -139,6 +139,17 @@
</PreferenceScreen>
+ <PreferenceScreen
+ android:key="doze"
+ android:title="@string/tuner_doze">
+
+ <com.android.systemui.tuner.TunerSwitch
+ android:key="doze_always_on"
+ android:title="@string/tuner_doze_always_on"
+ sysui:defValue="false" />
+
+ </PreferenceScreen>
+
<!--
<Preference
android:key="nav_bar"
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
index 82a1bfe..02a98b0 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java
@@ -27,6 +27,7 @@
void startDozing(@NonNull Runnable ready);
void pulseWhileDozing(@NonNull PulseCallback callback, int reason);
void stopDozing();
+ void dozeTimeTick();
boolean isPowerSaveActive();
boolean isNotificationLightOn();
boolean isPulsingBlocked();
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index 8789845c..cbaf232 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -16,6 +16,7 @@
package com.android.systemui.doze;
+import android.app.AlarmManager;
import android.app.UiModeManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -43,7 +44,9 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.Calendar;
import java.util.Date;
+import java.util.GregorianCalendar;
public class DozeService extends DreamService implements DozeSensors.Callback {
private static final String TAG = "DozeService";
@@ -77,6 +80,7 @@
private long mNotificationPulseTime;
private AmbientDisplayConfiguration mConfig;
+ private AlarmManager mAlarmManager;
public DozeService() {
if (DEBUG) Log.d(mTag, "new DozeService()");
@@ -114,6 +118,7 @@
setWindowless(true);
mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
+ mAlarmManager = (AlarmManager) mContext.getSystemService(AlarmManager.class);
mConfig = new AmbientDisplayConfiguration(mContext);
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
@@ -168,6 +173,10 @@
// stopDozing because can we just keep dozing until the bitter end.
}
}));
+
+ if (mDozeParameters.getAlwaysOn()) {
+ mTimeTick.onAlarm();
+ }
}
@Override
@@ -184,6 +193,7 @@
// Tell the host that it's over.
mHost.stopDozing();
+ mAlarmManager.cancel(mTimeTick);
}
private void requestPulse(final int reason) {
@@ -264,7 +274,11 @@
private void turnDisplayOff() {
if (DEBUG) Log.d(mTag, "Display off");
- setDozeScreenState(Display.STATE_OFF);
+ if (mDozeParameters.getAlwaysOn()) {
+ turnDisplayOn();
+ } else {
+ setDozeScreenState(Display.STATE_OFF);
+ }
}
private void turnDisplayOn() {
@@ -353,6 +367,26 @@
}
};
+ private AlarmManager.OnAlarmListener mTimeTick = new AlarmManager.OnAlarmListener() {
+ @Override
+ public void onAlarm() {
+ mHost.dozeTimeTick();
+
+ // Keep wakelock until a frame has been pushed.
+ mHandler.post(mWakeLock.wrap(()->{}));
+
+ Calendar calendar = GregorianCalendar.getInstance();
+ calendar.setTimeInMillis(System.currentTimeMillis());
+ calendar.set(Calendar.MILLISECOND, 0);
+ calendar.set(Calendar.SECOND, 0);
+ calendar.add(Calendar.MINUTE, 1);
+
+ long delta = calendar.getTimeInMillis() - System.currentTimeMillis();
+ mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+ SystemClock.elapsedRealtime() + delta, "doze_time_tick", mTimeTick, mHandler);
+ }
+ };
+
private final DozeHost.Callback mHostCallback = new DozeHost.Callback() {
@Override
public void onNewNotifications() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index 9e9bdd7..0e074c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -17,20 +17,17 @@
package com.android.systemui.statusbar.phone;
import android.content.Context;
+import android.os.Build;
import android.os.SystemProperties;
import android.os.UserHandle;
+import android.provider.Settings;
import android.text.TextUtils;
-import android.util.Log;
import android.util.MathUtils;
import android.util.SparseBooleanArray;
-import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.systemui.R;
import java.io.PrintWriter;
-import java.util.Arrays;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
public class DozeParameters {
private static final int MAX_DURATION = 60 * 1000;
@@ -115,6 +112,12 @@
return getInt("doze.pickup.vibration.threshold", R.integer.doze_pickup_vibration_threshold);
}
+ public boolean getAlwaysOn() {
+ return Build.IS_DEBUGGABLE
+ && Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.DOZE_ALWAYS_ON, 0, UserHandle.USER_CURRENT) != 0;
+ }
+
private boolean getBoolean(String propName, int resId) {
return SystemProperties.getBoolean(propName, mContext.getResources().getBoolean(resId));
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
index b44f5f7..b141454 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
@@ -23,6 +23,7 @@
import android.content.Context;
import android.os.Handler;
import android.util.Log;
+import android.view.View;
import android.view.animation.Interpolator;
import com.android.systemui.Interpolators;
@@ -40,6 +41,8 @@
private final Handler mHandler = new Handler();
private final ScrimController mScrimController;
+ private final View mStackScroller;
+
private boolean mDozing;
private DozeHost.PulseCallback mPulseCallback;
private int mPulseReason;
@@ -48,7 +51,9 @@
private float mInFrontTarget;
private float mBehindTarget;
- public DozeScrimController(ScrimController scrimController, Context context) {
+ public DozeScrimController(ScrimController scrimController, Context context,
+ View stackScroller) {
+ mStackScroller = stackScroller;
mScrimController = scrimController;
mDozeParameters = new DozeParameters(context);
}
@@ -59,7 +64,11 @@
if (mDozing) {
abortAnimations();
mScrimController.setDozeBehindAlpha(1f);
- mScrimController.setDozeInFrontAlpha(1f);
+ mScrimController.setDozeInFrontAlpha(mDozeParameters.getAlwaysOn() ? 0f : 1f);
+ if (mDozeParameters.getAlwaysOn()) {
+ mStackScroller.setAlpha(0f);
+ mHandler.postDelayed(() -> mStackScroller.setAlpha(0f), 30);
+ }
} else {
cancelPulsing();
if (animate) {
@@ -74,6 +83,9 @@
mScrimController.setDozeBehindAlpha(0f);
mScrimController.setDozeInFrontAlpha(0f);
}
+ if (mDozeParameters.getAlwaysOn()) {
+ mStackScroller.setAlpha(1f);
+ }
}
}
@@ -93,7 +105,9 @@
// be invoked when we're done so that the caller can drop the pulse wakelock.
mPulseCallback = callback;
mPulseReason = reason;
- mHandler.post(mPulseIn);
+ if (mDozeParameters.getAlwaysOn()) {
+ mHandler.post(mPulseIn);
+ }
}
/**
@@ -111,6 +125,9 @@
if (isPulsing()) {
final boolean pickupOrDoubleTap = mPulseReason == DozeLog.PULSE_REASON_SENSOR_PICKUP
|| mPulseReason == DozeLog.PULSE_REASON_SENSOR_DOUBLE_TAP;
+ if (mDozeParameters.getAlwaysOn()) {
+ mStackScroller.setAlpha(1f);
+ }
startScrimAnimation(true /* inFront */, 0f,
mDozeParameters.getPulseInDuration(pickupOrDoubleTap),
pickupOrDoubleTap ? Interpolators.LINEAR_OUT_SLOW_IN : Interpolators.ALPHA_OUT,
@@ -245,6 +262,10 @@
// Signal that the pulse is ready to turn the screen on and draw.
pulseStarted();
+
+ if (mDozeParameters.getAlwaysOn()) {
+ mHandler.post(DozeScrimController.this::onScreenTurnedOn);
+ }
}
};
@@ -262,7 +283,8 @@
public void run() {
if (DEBUG) Log.d(TAG, "Pulse out, mDozing=" + mDozing);
if (!mDozing) return;
- startScrimAnimation(true /* inFront */, 1f, mDozeParameters.getPulseOutDuration(),
+ startScrimAnimation(true /* inFront */, mDozeParameters.getAlwaysOn() ? 0 : 1,
+ mDozeParameters.getPulseOutDuration(),
Interpolators.ALPHA_IN, mPulseOutFinished);
}
};
@@ -271,6 +293,9 @@
@Override
public void run() {
if (DEBUG) Log.d(TAG, "Pulse out finished");
+ if (mDozeParameters.getAlwaysOn()) {
+ mStackScroller.setAlpha(0f);
+ }
DozeLog.tracePulseFinish();
// Signal that the pulse is all finished so we can turn the screen off now.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 28e5f7e..0ef2687 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -123,6 +123,7 @@
import com.android.internal.statusbar.NotificationVisibility;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.keyguard.KeyguardHostView.OnDismissAction;
+import com.android.keyguard.KeyguardStatusView;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.ViewMediatorCallback;
@@ -367,7 +368,7 @@
// top bar
BaseStatusBarHeader mHeader;
protected KeyguardStatusBarView mKeyguardStatusBar;
- View mKeyguardStatusView;
+ KeyguardStatusView mKeyguardStatusView;
KeyguardBottomAreaView mKeyguardBottomArea;
boolean mLeaveOpenOnKeyguardHide;
KeyguardIndicationController mKeyguardIndicationController;
@@ -846,10 +847,11 @@
mHeadsUpManager.addListener(mScrimController);
mStackScroller.setScrimController(mScrimController);
mStatusBarView.setScrimController(mScrimController);
- mDozeScrimController = new DozeScrimController(mScrimController, context);
+ mDozeScrimController = new DozeScrimController(mScrimController, context, mStackScroller);
mKeyguardStatusBar = (KeyguardStatusBarView) mStatusBarWindow.findViewById(R.id.keyguard_header);
- mKeyguardStatusView = mStatusBarWindow.findViewById(R.id.keyguard_status_view);
+ mKeyguardStatusView =
+ (KeyguardStatusView) mStatusBarWindow.findViewById(R.id.keyguard_status_view);
mKeyguardBottomArea =
(KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);
mKeyguardBottomArea.setActivityStarter(this);
@@ -2695,6 +2697,10 @@
mFalsingManager.onScreenOff();
}
+ public boolean isPulsing() {
+ return mDozeScrimController.isPulsing();
+ }
+
/**
* All changes to the status bar and notifications funnel through here and are batched.
*/
@@ -5135,6 +5141,11 @@
}
@Override
+ public void dozeTimeTick() {
+ mKeyguardStatusView.refreshTime();
+ }
+
+ @Override
public boolean isPowerSaveActive() {
return mBatteryController != null && mBatteryController.isPowerSave();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index 4425c5e..5696123 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -248,6 +248,10 @@
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
+ if (mService.isDozing() && !mService.isPulsing()) {
+ // Discard all touch events in always-on.
+ return true;
+ }
boolean intercept = false;
if (mNotificationPanel.isFullyExpanded()
&& mStackScrollLayout.getVisibility() == View.VISIBLE
@@ -274,6 +278,11 @@
@Override
public boolean onTouchEvent(MotionEvent ev) {
+ if (mService.isDozing() && !mService.isPulsing()) {
+ // Discard all touch events in always-on.
+ return true;
+ }
+
boolean handled = false;
if (mService.getBarState() == StatusBarState.KEYGUARD) {
handled = mDragDownHelper.onTouchEvent(ev);