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.Context;
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 com.android.internal.annotations.VisibleForTesting;
28 import com.android.systemui.Dependency;
29 import com.android.systemui.R;
30 import com.android.systemui.doze.AlwaysOnDisplayPolicy;
31 import com.android.systemui.doze.DozeScreenState;
32 import com.android.systemui.tuner.TunerService;
33 
34 import java.io.PrintWriter;
35 
36 /**
37  * Retrieve doze information
38  */
39 public class DozeParameters implements TunerService.Tunable,
40         com.android.systemui.plugins.statusbar.DozeParameters {
41     private static final int MAX_DURATION = 60 * 1000;
42     public static final boolean FORCE_NO_BLANKING =
43             SystemProperties.getBoolean("debug.force_no_blanking", false);
44     public static final boolean FORCE_BLANKING =
45             SystemProperties.getBoolean("debug.force_blanking", false);
46 
47     private static DozeParameters sInstance;
48 
49     private final Context mContext;
50     private final AmbientDisplayConfiguration mAmbientDisplayConfiguration;
51     private final PowerManager mPowerManager;
52 
53     private final AlwaysOnDisplayPolicy mAlwaysOnPolicy;
54 
55     private boolean mDozeAlwaysOn;
56     private boolean mControlScreenOffAnimation;
57 
getInstance(Context context)58     public static DozeParameters getInstance(Context context) {
59         if (sInstance == null) {
60             sInstance = new DozeParameters(context);
61         }
62         return sInstance;
63     }
64 
65     @VisibleForTesting
DozeParameters(Context context)66     protected DozeParameters(Context context) {
67         mContext = context.getApplicationContext();
68         mAmbientDisplayConfiguration = new AmbientDisplayConfiguration(mContext);
69         mAlwaysOnPolicy = new AlwaysOnDisplayPolicy(mContext);
70 
71         mControlScreenOffAnimation = !getDisplayNeedsBlanking();
72         mPowerManager = mContext.getSystemService(PowerManager.class);
73         mPowerManager.setDozeAfterScreenOff(!mControlScreenOffAnimation);
74 
75         Dependency.get(TunerService.class).addTunable(this, Settings.Secure.DOZE_ALWAYS_ON,
76                 Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
77     }
78 
dump(PrintWriter pw)79     public void dump(PrintWriter pw) {
80         pw.println("  DozeParameters:");
81         pw.print("    getDisplayStateSupported(): "); pw.println(getDisplayStateSupported());
82         pw.print("    getPulseDuration(): "); pw.println(getPulseDuration());
83         pw.print("    getPulseInDuration(): "); pw.println(getPulseInDuration());
84         pw.print("    getPulseInVisibleDuration(): "); pw.println(getPulseVisibleDuration());
85         pw.print("    getPulseOutDuration(): "); pw.println(getPulseOutDuration());
86         pw.print("    getPulseOnSigMotion(): "); pw.println(getPulseOnSigMotion());
87         pw.print("    getVibrateOnSigMotion(): "); pw.println(getVibrateOnSigMotion());
88         pw.print("    getVibrateOnPickup(): "); pw.println(getVibrateOnPickup());
89         pw.print("    getProxCheckBeforePulse(): "); pw.println(getProxCheckBeforePulse());
90         pw.print("    getPickupVibrationThreshold(): "); pw.println(getPickupVibrationThreshold());
91     }
92 
getDisplayStateSupported()93     public boolean getDisplayStateSupported() {
94         return getBoolean("doze.display.supported", R.bool.doze_display_state_supported);
95     }
96 
getDozeSuspendDisplayStateSupported()97     public boolean getDozeSuspendDisplayStateSupported() {
98         return mContext.getResources().getBoolean(R.bool.doze_suspend_display_state_supported);
99     }
100 
getPulseDuration()101     public int getPulseDuration() {
102         return getPulseInDuration() + getPulseVisibleDuration() + getPulseOutDuration();
103     }
104 
getScreenBrightnessDoze()105     public float getScreenBrightnessDoze() {
106         return mContext.getResources().getInteger(
107                 com.android.internal.R.integer.config_screenBrightnessDoze) / 255f;
108     }
109 
getPulseInDuration()110     public int getPulseInDuration() {
111         return getInt("doze.pulse.duration.in", R.integer.doze_pulse_duration_in);
112     }
113 
getPulseVisibleDuration()114     public int getPulseVisibleDuration() {
115         return getInt("doze.pulse.duration.visible", R.integer.doze_pulse_duration_visible);
116     }
117 
getPulseOutDuration()118     public int getPulseOutDuration() {
119         return getInt("doze.pulse.duration.out", R.integer.doze_pulse_duration_out);
120     }
121 
getPulseOnSigMotion()122     public boolean getPulseOnSigMotion() {
123         return getBoolean("doze.pulse.sigmotion", R.bool.doze_pulse_on_significant_motion);
124     }
125 
getVibrateOnSigMotion()126     public boolean getVibrateOnSigMotion() {
127         return SystemProperties.getBoolean("doze.vibrate.sigmotion", false);
128     }
129 
getVibrateOnPickup()130     public boolean getVibrateOnPickup() {
131         return SystemProperties.getBoolean("doze.vibrate.pickup", false);
132     }
133 
getProxCheckBeforePulse()134     public boolean getProxCheckBeforePulse() {
135         return getBoolean("doze.pulse.proxcheck", R.bool.doze_proximity_check_before_pulse);
136     }
137 
getPickupVibrationThreshold()138     public int getPickupVibrationThreshold() {
139         return getInt("doze.pickup.vibration.threshold", R.integer.doze_pickup_vibration_threshold);
140     }
141 
142     /**
143      * For how long a wallpaper can be visible in AoD before it fades aways.
144      * @return duration in millis.
145      */
getWallpaperAodDuration()146     public long getWallpaperAodDuration() {
147         if (shouldControlScreenOff()) {
148             return DozeScreenState.ENTER_DOZE_HIDE_WALLPAPER_DELAY;
149         }
150         return mAlwaysOnPolicy.wallpaperVisibilityDuration;
151     }
152 
153     /**
154      * How long it takes for the wallpaper fade away (Animation duration.)
155      * @return duration in millis.
156      */
getWallpaperFadeOutDuration()157     public long getWallpaperFadeOutDuration() {
158         return mAlwaysOnPolicy.wallpaperFadeOutDuration;
159     }
160 
161     /**
162      * Checks if always on is available and enabled for the current user.
163      * @return {@code true} if enabled and available.
164      */
getAlwaysOn()165     public boolean getAlwaysOn() {
166         return mDozeAlwaysOn;
167     }
168 
169     /**
170      * Some screens need to be completely black before changing the display power mode,
171      * unexpected behavior might happen if this parameter isn't respected.
172      *
173      * @return {@code true} if screen needs to be completely black before a power transition.
174      */
getDisplayNeedsBlanking()175     public boolean getDisplayNeedsBlanking() {
176         return FORCE_BLANKING || !FORCE_NO_BLANKING && mContext.getResources().getBoolean(
177                 com.android.internal.R.bool.config_displayBlanksAfterDoze);
178     }
179 
shouldControlScreenOff()180     public boolean shouldControlScreenOff() {
181         return mControlScreenOffAnimation;
182     }
183 
setControlScreenOffAnimation(boolean controlScreenOffAnimation)184     public void setControlScreenOffAnimation(boolean controlScreenOffAnimation) {
185         if (mControlScreenOffAnimation == controlScreenOffAnimation) {
186             return;
187         }
188         mControlScreenOffAnimation = controlScreenOffAnimation;
189         getPowerManager().setDozeAfterScreenOff(!controlScreenOffAnimation);
190     }
191 
192     @VisibleForTesting
getPowerManager()193     protected PowerManager getPowerManager() {
194         return mPowerManager;
195     }
196 
getBoolean(String propName, int resId)197     private boolean getBoolean(String propName, int resId) {
198         return SystemProperties.getBoolean(propName, mContext.getResources().getBoolean(resId));
199     }
200 
getInt(String propName, int resId)201     private int getInt(String propName, int resId) {
202         int value = SystemProperties.getInt(propName, mContext.getResources().getInteger(resId));
203         return MathUtils.constrain(value, 0, MAX_DURATION);
204     }
205 
getString(String propName, int resId)206     private String getString(String propName, int resId) {
207         return SystemProperties.get(propName, mContext.getString(resId));
208     }
209 
getPulseVisibleDurationExtended()210     public int getPulseVisibleDurationExtended() {
211         return 2 * getPulseVisibleDuration();
212     }
213 
doubleTapReportsTouchCoordinates()214     public boolean doubleTapReportsTouchCoordinates() {
215         return mContext.getResources().getBoolean(R.bool.doze_double_tap_reports_touch_coordinates);
216     }
217 
218     @Override
onTuningChanged(String key, String newValue)219     public void onTuningChanged(String key, String newValue) {
220         mDozeAlwaysOn = mAmbientDisplayConfiguration.alwaysOnEnabled(UserHandle.USER_CURRENT);
221     }
222 
getPolicy()223     public AlwaysOnDisplayPolicy getPolicy() {
224         return mAlwaysOnPolicy;
225     }
226 }
227