1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.systemui.statusbar.phone; 18 19 import android.content.res.Resources; 20 import android.hardware.display.AmbientDisplayConfiguration; 21 import android.os.PowerManager; 22 import android.os.SystemProperties; 23 import android.os.UserHandle; 24 import android.provider.Settings; 25 import android.util.MathUtils; 26 27 import androidx.annotation.NonNull; 28 29 import com.android.systemui.Dumpable; 30 import com.android.systemui.R; 31 import com.android.systemui.dagger.SysUISingleton; 32 import com.android.systemui.dagger.qualifiers.Main; 33 import com.android.systemui.doze.AlwaysOnDisplayPolicy; 34 import com.android.systemui.doze.DozeScreenState; 35 import com.android.systemui.dump.DumpManager; 36 import com.android.systemui.statusbar.FeatureFlags; 37 import com.android.systemui.statusbar.policy.BatteryController; 38 import com.android.systemui.tuner.TunerService; 39 40 import java.io.FileDescriptor; 41 import java.io.PrintWriter; 42 import java.util.HashSet; 43 import java.util.Set; 44 45 import javax.inject.Inject; 46 47 /** 48 * Retrieve doze information 49 */ 50 @SysUISingleton 51 public class DozeParameters implements TunerService.Tunable, 52 com.android.systemui.plugins.statusbar.DozeParameters, Dumpable { 53 private static final int MAX_DURATION = 60 * 1000; 54 public static final boolean FORCE_NO_BLANKING = 55 SystemProperties.getBoolean("debug.force_no_blanking", false); 56 public static final boolean FORCE_BLANKING = 57 SystemProperties.getBoolean("debug.force_blanking", false); 58 59 private final AmbientDisplayConfiguration mAmbientDisplayConfiguration; 60 private final PowerManager mPowerManager; 61 62 private final AlwaysOnDisplayPolicy mAlwaysOnPolicy; 63 private final Resources mResources; 64 private final BatteryController mBatteryController; 65 private final FeatureFlags mFeatureFlags; 66 private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; 67 68 private final Set<Callback> mCallbacks = new HashSet<>(); 69 70 private boolean mDozeAlwaysOn; 71 private boolean mControlScreenOffAnimation; 72 73 @Inject DozeParameters( @ain Resources resources, AmbientDisplayConfiguration ambientDisplayConfiguration, AlwaysOnDisplayPolicy alwaysOnDisplayPolicy, PowerManager powerManager, BatteryController batteryController, TunerService tunerService, DumpManager dumpManager, FeatureFlags featureFlags, UnlockedScreenOffAnimationController unlockedScreenOffAnimationController)74 protected DozeParameters( 75 @Main Resources resources, 76 AmbientDisplayConfiguration ambientDisplayConfiguration, 77 AlwaysOnDisplayPolicy alwaysOnDisplayPolicy, 78 PowerManager powerManager, 79 BatteryController batteryController, 80 TunerService tunerService, 81 DumpManager dumpManager, 82 FeatureFlags featureFlags, 83 UnlockedScreenOffAnimationController unlockedScreenOffAnimationController) { 84 mResources = resources; 85 mAmbientDisplayConfiguration = ambientDisplayConfiguration; 86 mAlwaysOnPolicy = alwaysOnDisplayPolicy; 87 mBatteryController = batteryController; 88 dumpManager.registerDumpable("DozeParameters", this); 89 90 mControlScreenOffAnimation = !getDisplayNeedsBlanking(); 91 mPowerManager = powerManager; 92 mPowerManager.setDozeAfterScreenOff(!mControlScreenOffAnimation); 93 mFeatureFlags = featureFlags; 94 mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController; 95 96 tunerService.addTunable( 97 this, 98 Settings.Secure.DOZE_ALWAYS_ON, 99 Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED); 100 } 101 getDisplayStateSupported()102 public boolean getDisplayStateSupported() { 103 return getBoolean("doze.display.supported", R.bool.doze_display_state_supported); 104 } 105 getDozeSuspendDisplayStateSupported()106 public boolean getDozeSuspendDisplayStateSupported() { 107 return mResources.getBoolean(R.bool.doze_suspend_display_state_supported); 108 } 109 getPulseDuration()110 public int getPulseDuration() { 111 return getPulseInDuration() + getPulseVisibleDuration() + getPulseOutDuration(); 112 } 113 getScreenBrightnessDoze()114 public float getScreenBrightnessDoze() { 115 return mResources.getInteger( 116 com.android.internal.R.integer.config_screenBrightnessDoze) / 255f; 117 } 118 getPulseInDuration()119 public int getPulseInDuration() { 120 return getInt("doze.pulse.duration.in", R.integer.doze_pulse_duration_in); 121 } 122 getPulseVisibleDuration()123 public int getPulseVisibleDuration() { 124 return getInt("doze.pulse.duration.visible", R.integer.doze_pulse_duration_visible); 125 } 126 getPulseOutDuration()127 public int getPulseOutDuration() { 128 return getInt("doze.pulse.duration.out", R.integer.doze_pulse_duration_out); 129 } 130 getPulseOnSigMotion()131 public boolean getPulseOnSigMotion() { 132 return getBoolean("doze.pulse.sigmotion", R.bool.doze_pulse_on_significant_motion); 133 } 134 getVibrateOnSigMotion()135 public boolean getVibrateOnSigMotion() { 136 return SystemProperties.getBoolean("doze.vibrate.sigmotion", false); 137 } 138 getVibrateOnPickup()139 public boolean getVibrateOnPickup() { 140 return SystemProperties.getBoolean("doze.vibrate.pickup", false); 141 } 142 getProxCheckBeforePulse()143 public boolean getProxCheckBeforePulse() { 144 return getBoolean("doze.pulse.proxcheck", R.bool.doze_proximity_check_before_pulse); 145 } 146 147 /** 148 * @return true if we should only register for sensors that use the proximity sensor when the 149 * display state is {@link android.view.Display.STATE_OFF}, 150 * {@link android.view.Display.STATE_DOZE} or {@link android.view.Display.STATE_DOZE_SUSPEND} 151 */ getSelectivelyRegisterSensorsUsingProx()152 public boolean getSelectivelyRegisterSensorsUsingProx() { 153 return getBoolean("doze.prox.selectively_register", 154 R.bool.doze_selectively_register_prox); 155 } 156 getPickupVibrationThreshold()157 public int getPickupVibrationThreshold() { 158 return getInt("doze.pickup.vibration.threshold", R.integer.doze_pickup_vibration_threshold); 159 } 160 getQuickPickupAodDuration()161 public int getQuickPickupAodDuration() { 162 return getInt("doze.gesture.quickpickup.duration", 163 R.integer.doze_quick_pickup_aod_duration); 164 } 165 166 /** 167 * For how long a wallpaper can be visible in AoD before it fades aways. 168 * @return duration in millis. 169 */ getWallpaperAodDuration()170 public long getWallpaperAodDuration() { 171 if (shouldControlScreenOff()) { 172 return DozeScreenState.ENTER_DOZE_HIDE_WALLPAPER_DELAY; 173 } 174 return mAlwaysOnPolicy.wallpaperVisibilityDuration; 175 } 176 177 /** 178 * How long it takes for the wallpaper fade away (Animation duration.) 179 * @return duration in millis. 180 */ getWallpaperFadeOutDuration()181 public long getWallpaperFadeOutDuration() { 182 return mAlwaysOnPolicy.wallpaperFadeOutDuration; 183 } 184 185 /** 186 * Checks if always on is available and enabled for the current user. 187 * @return {@code true} if enabled and available. 188 */ getAlwaysOn()189 public boolean getAlwaysOn() { 190 return mDozeAlwaysOn && !mBatteryController.isAodPowerSave(); 191 } 192 isQuickPickupEnabled()193 public boolean isQuickPickupEnabled() { 194 return mAmbientDisplayConfiguration.quickPickupSensorEnabled(UserHandle.USER_CURRENT); 195 } 196 197 /** 198 * Some screens need to be completely black before changing the display power mode, 199 * unexpected behavior might happen if this parameter isn't respected. 200 * 201 * @return {@code true} if screen needs to be completely black before a power transition. 202 */ getDisplayNeedsBlanking()203 public boolean getDisplayNeedsBlanking() { 204 return FORCE_BLANKING || !FORCE_NO_BLANKING && mResources.getBoolean( 205 com.android.internal.R.bool.config_displayBlanksAfterDoze); 206 } 207 shouldControlScreenOff()208 public boolean shouldControlScreenOff() { 209 return mControlScreenOffAnimation; 210 } 211 setControlScreenOffAnimation(boolean controlScreenOffAnimation)212 public void setControlScreenOffAnimation(boolean controlScreenOffAnimation) { 213 if (mControlScreenOffAnimation == controlScreenOffAnimation) { 214 return; 215 } 216 mControlScreenOffAnimation = controlScreenOffAnimation; 217 mPowerManager.setDozeAfterScreenOff(!controlScreenOffAnimation); 218 } 219 220 /** 221 * Whether we want to control the screen off animation when the device is unlocked. If we do, 222 * we'll animate in AOD before turning off the screen, rather than simply fading to black and 223 * then abruptly showing AOD. 224 */ shouldControlUnlockedScreenOff()225 public boolean shouldControlUnlockedScreenOff() { 226 return mUnlockedScreenOffAnimationController.shouldPlayUnlockedScreenOffAnimation(); 227 } 228 229 /** 230 * Whether we're capable of controlling the screen off animation if we want to. This isn't 231 * possible if AOD isn't even enabled or if the flag is disabled. 232 */ canControlUnlockedScreenOff()233 public boolean canControlUnlockedScreenOff() { 234 return getAlwaysOn() 235 && mFeatureFlags.useNewLockscreenAnimations() 236 && !getDisplayNeedsBlanking(); 237 } 238 getBoolean(String propName, int resId)239 private boolean getBoolean(String propName, int resId) { 240 return SystemProperties.getBoolean(propName, mResources.getBoolean(resId)); 241 } 242 getInt(String propName, int resId)243 private int getInt(String propName, int resId) { 244 int value = SystemProperties.getInt(propName, mResources.getInteger(resId)); 245 return MathUtils.constrain(value, 0, MAX_DURATION); 246 } 247 getPulseVisibleDurationExtended()248 public int getPulseVisibleDurationExtended() { 249 return 2 * getPulseVisibleDuration(); 250 } 251 doubleTapReportsTouchCoordinates()252 public boolean doubleTapReportsTouchCoordinates() { 253 return mResources.getBoolean(R.bool.doze_double_tap_reports_touch_coordinates); 254 } 255 256 /** 257 * Whether the single tap sensor uses the proximity sensor. 258 */ singleTapUsesProx()259 public boolean singleTapUsesProx() { 260 return mResources.getBoolean(R.bool.doze_single_tap_uses_prox); 261 } 262 263 /** 264 * Whether the long press sensor uses the proximity sensor. 265 */ longPressUsesProx()266 public boolean longPressUsesProx() { 267 return mResources.getBoolean(R.bool.doze_long_press_uses_prox); 268 } 269 270 /** 271 * Callback to listen for DozeParameter changes. 272 */ addCallback(Callback callback)273 public void addCallback(Callback callback) { 274 mCallbacks.add(callback); 275 } 276 277 /** 278 * Remove callback that listens for DozeParameter changes. 279 */ removeCallback(Callback callback)280 public void removeCallback(Callback callback) { 281 mCallbacks.remove(callback); 282 } 283 284 @Override onTuningChanged(String key, String newValue)285 public void onTuningChanged(String key, String newValue) { 286 mDozeAlwaysOn = mAmbientDisplayConfiguration.alwaysOnEnabled(UserHandle.USER_CURRENT); 287 for (Callback callback : mCallbacks) { 288 callback.onAlwaysOnChange(); 289 } 290 } 291 292 @Override dump(@onNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args)293 public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) { 294 pw.print("getDisplayStateSupported(): "); pw.println(getDisplayStateSupported()); 295 pw.print("getPulseDuration(): "); pw.println(getPulseDuration()); 296 pw.print("getPulseInDuration(): "); pw.println(getPulseInDuration()); 297 pw.print("getPulseInVisibleDuration(): "); pw.println(getPulseVisibleDuration()); 298 pw.print("getPulseOutDuration(): "); pw.println(getPulseOutDuration()); 299 pw.print("getPulseOnSigMotion(): "); pw.println(getPulseOnSigMotion()); 300 pw.print("getVibrateOnSigMotion(): "); pw.println(getVibrateOnSigMotion()); 301 pw.print("getVibrateOnPickup(): "); pw.println(getVibrateOnPickup()); 302 pw.print("getProxCheckBeforePulse(): "); pw.println(getProxCheckBeforePulse()); 303 pw.print("getPickupVibrationThreshold(): "); pw.println(getPickupVibrationThreshold()); 304 pw.print("getSelectivelyRegisterSensorsUsingProx(): "); 305 pw.println(getSelectivelyRegisterSensorsUsingProx()); 306 } 307 308 interface Callback { 309 /** 310 * Invoked when the value of getAlwaysOn may have changed. 311 */ onAlwaysOnChange()312 void onAlwaysOnChange(); 313 } 314 } 315