blob: 0affb7a900f3af3f97a1cc8e8a4de1516a48c86d [file] [log] [blame]
Adrian Roos12c1ef52014-06-04 13:54:08 +02001/*
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
17package com.android.systemui.statusbar;
18
Adrian Roos12c1ef52014-06-04 13:54:08 +020019import android.content.BroadcastReceiver;
20import android.content.Context;
21import android.content.Intent;
22import android.content.IntentFilter;
Adrian Roos7b043112015-07-10 13:00:33 -070023import android.content.res.Resources;
Jorim Jaggi27c9b742015-04-09 10:34:49 -070024import android.graphics.Color;
Selim Cinekcfafe4e2015-08-11 14:58:44 -070025import android.hardware.fingerprint.FingerprintManager;
Adrian Roos12c1ef52014-06-04 13:54:08 +020026import android.os.BatteryManager;
27import android.os.BatteryStats;
28import android.os.Handler;
29import android.os.Message;
30import android.os.RemoteException;
31import android.os.ServiceManager;
32import android.os.UserHandle;
33import android.text.TextUtils;
34import android.text.format.Formatter;
35import android.util.Log;
36import android.view.View;
37
Selim Cinekcfafe4e2015-08-11 14:58:44 -070038import com.android.internal.app.IBatteryStats;
39import com.android.keyguard.KeyguardUpdateMonitor;
40import com.android.keyguard.KeyguardUpdateMonitorCallback;
41import com.android.systemui.R;
42import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
43import com.android.systemui.statusbar.phone.LockIcon;
44import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
45
Adrian Roos12c1ef52014-06-04 13:54:08 +020046/**
Selim Cinekcfafe4e2015-08-11 14:58:44 -070047 * Controls the indications and error messages shown on the Keyguard
Adrian Roos12c1ef52014-06-04 13:54:08 +020048 */
49public class KeyguardIndicationController {
50
Adrian Roos0c859ae2015-11-23 16:47:50 -080051 private static final String TAG = "KeyguardIndication";
52 private static final boolean DEBUG_CHARGING_SPEED = false;
Adrian Roos12c1ef52014-06-04 13:54:08 +020053
54 private static final int MSG_HIDE_TRANSIENT = 1;
Selim Cinekcfafe4e2015-08-11 14:58:44 -070055 private static final int MSG_CLEAR_FP_MSG = 2;
56 private static final long TRANSIENT_FP_ERROR_TIMEOUT = 1300;
Adrian Roos12c1ef52014-06-04 13:54:08 +020057
58 private final Context mContext;
59 private final KeyguardIndicationTextView mTextView;
60 private final IBatteryStats mBatteryInfo;
61
Adrian Roos7b043112015-07-10 13:00:33 -070062 private final int mSlowThreshold;
63 private final int mFastThreshold;
Selim Cinekcfafe4e2015-08-11 14:58:44 -070064 private final LockIcon mLockIcon;
65 private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
Adrian Roos7b043112015-07-10 13:00:33 -070066
Adrian Roos12c1ef52014-06-04 13:54:08 +020067 private String mRestingIndication;
68 private String mTransientIndication;
Jorim Jaggi27c9b742015-04-09 10:34:49 -070069 private int mTransientTextColor;
Adrian Roos12c1ef52014-06-04 13:54:08 +020070 private boolean mVisible;
71
72 private boolean mPowerPluggedIn;
73 private boolean mPowerCharged;
Adrian Roos7b043112015-07-10 13:00:33 -070074 private int mChargingSpeed;
Adrian Roos0c859ae2015-11-23 16:47:50 -080075 private int mChargingWattage;
Selim Cinekcfafe4e2015-08-11 14:58:44 -070076 private String mMessageToShowOnScreenOn;
Adrian Roos12c1ef52014-06-04 13:54:08 +020077
Selim Cinekcfafe4e2015-08-11 14:58:44 -070078 public KeyguardIndicationController(Context context, KeyguardIndicationTextView textView,
79 LockIcon lockIcon) {
Adrian Roos12c1ef52014-06-04 13:54:08 +020080 mContext = context;
81 mTextView = textView;
Selim Cinekcfafe4e2015-08-11 14:58:44 -070082 mLockIcon = lockIcon;
Adrian Roos12c1ef52014-06-04 13:54:08 +020083
Adrian Roos7b043112015-07-10 13:00:33 -070084 Resources res = context.getResources();
85 mSlowThreshold = res.getInteger(R.integer.config_chargingSlowlyThreshold);
86 mFastThreshold = res.getInteger(R.integer.config_chargingFastThreshold);
87
88
Adrian Roos12c1ef52014-06-04 13:54:08 +020089 mBatteryInfo = IBatteryStats.Stub.asInterface(
90 ServiceManager.getService(BatteryStats.SERVICE_NAME));
91 KeyguardUpdateMonitor.getInstance(context).registerCallback(mUpdateMonitor);
92 context.registerReceiverAsUser(
93 mReceiver, UserHandle.OWNER, new IntentFilter(Intent.ACTION_TIME_TICK), null, null);
94 }
95
96 public void setVisible(boolean visible) {
97 mVisible = visible;
98 mTextView.setVisibility(visible ? View.VISIBLE : View.GONE);
99 if (visible) {
100 hideTransientIndication();
101 updateIndication();
102 }
103 }
104
105 /**
106 * Sets the indication that is shown if nothing else is showing.
107 */
108 public void setRestingIndication(String restingIndication) {
109 mRestingIndication = restingIndication;
110 updateIndication();
111 }
112
113 /**
114 * Hides transient indication in {@param delayMs}.
115 */
116 public void hideTransientIndicationDelayed(long delayMs) {
117 mHandler.sendMessageDelayed(
118 mHandler.obtainMessage(MSG_HIDE_TRANSIENT), delayMs);
119 }
120
121 /**
122 * Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}.
123 */
124 public void showTransientIndication(int transientIndication) {
125 showTransientIndication(mContext.getResources().getString(transientIndication));
126 }
127
128 /**
129 * Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}.
130 */
131 public void showTransientIndication(String transientIndication) {
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700132 showTransientIndication(transientIndication, Color.WHITE);
133 }
134
135 /**
136 * Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}.
137 */
138 public void showTransientIndication(String transientIndication, int textColor) {
Adrian Roos12c1ef52014-06-04 13:54:08 +0200139 mTransientIndication = transientIndication;
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700140 mTransientTextColor = textColor;
Adrian Roos12c1ef52014-06-04 13:54:08 +0200141 mHandler.removeMessages(MSG_HIDE_TRANSIENT);
142 updateIndication();
143 }
144
145 /**
146 * Hides transient indication.
147 */
148 public void hideTransientIndication() {
149 if (mTransientIndication != null) {
150 mTransientIndication = null;
151 mHandler.removeMessages(MSG_HIDE_TRANSIENT);
152 updateIndication();
153 }
154 }
155
156 private void updateIndication() {
157 if (mVisible) {
158 mTextView.switchIndication(computeIndication());
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700159 mTextView.setTextColor(computeColor());
Adrian Roos12c1ef52014-06-04 13:54:08 +0200160 }
161 }
162
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700163 private int computeColor() {
164 if (!TextUtils.isEmpty(mTransientIndication)) {
165 return mTransientTextColor;
166 }
167 return Color.WHITE;
168 }
169
Adrian Roos12c1ef52014-06-04 13:54:08 +0200170 private String computeIndication() {
171 if (!TextUtils.isEmpty(mTransientIndication)) {
172 return mTransientIndication;
173 }
174 if (mPowerPluggedIn) {
Adrian Roos7b043112015-07-10 13:00:33 -0700175 String indication = computePowerIndication();
Adrian Roos0c859ae2015-11-23 16:47:50 -0800176 if (DEBUG_CHARGING_SPEED) {
177 indication += ", " + (mChargingWattage / 1000) + " mW";
Adrian Roos7b043112015-07-10 13:00:33 -0700178 }
179 return indication;
Adrian Roos12c1ef52014-06-04 13:54:08 +0200180 }
181 return mRestingIndication;
182 }
183
184 private String computePowerIndication() {
185 if (mPowerCharged) {
186 return mContext.getResources().getString(R.string.keyguard_charged);
187 }
188
189 // Try fetching charging time from battery stats.
Adrian Roos7e39e592015-09-23 17:03:47 -0700190 long chargingTimeRemaining = 0;
Adrian Roos12c1ef52014-06-04 13:54:08 +0200191 try {
Adrian Roos7e39e592015-09-23 17:03:47 -0700192 chargingTimeRemaining = mBatteryInfo.computeChargeTimeRemaining();
193
Adrian Roos12c1ef52014-06-04 13:54:08 +0200194 } catch (RemoteException e) {
195 Log.e(TAG, "Error calling IBatteryStats: ", e);
196 }
Adrian Roos7e39e592015-09-23 17:03:47 -0700197 final boolean hasChargingTime = chargingTimeRemaining > 0;
Adrian Roos12c1ef52014-06-04 13:54:08 +0200198
Adrian Roos7b043112015-07-10 13:00:33 -0700199 int chargingId;
200 switch (mChargingSpeed) {
201 case KeyguardUpdateMonitor.BatteryStatus.CHARGING_FAST:
Adrian Roos7e39e592015-09-23 17:03:47 -0700202 chargingId = hasChargingTime
Adrian Roosf142cac2015-09-25 15:15:17 -0700203 ? R.string.keyguard_indication_charging_time_fast
Adrian Roos7e39e592015-09-23 17:03:47 -0700204 : R.string.keyguard_plugged_in_charging_fast;
Adrian Roos7b043112015-07-10 13:00:33 -0700205 break;
206 case KeyguardUpdateMonitor.BatteryStatus.CHARGING_SLOWLY:
Adrian Roos7e39e592015-09-23 17:03:47 -0700207 chargingId = hasChargingTime
Adrian Roosf142cac2015-09-25 15:15:17 -0700208 ? R.string.keyguard_indication_charging_time_slowly
Adrian Roos7e39e592015-09-23 17:03:47 -0700209 : R.string.keyguard_plugged_in_charging_slowly;
Adrian Roos7b043112015-07-10 13:00:33 -0700210 break;
211 default:
Adrian Roos7e39e592015-09-23 17:03:47 -0700212 chargingId = hasChargingTime
213 ? R.string.keyguard_indication_charging_time
214 : R.string.keyguard_plugged_in;
Adrian Roos7b043112015-07-10 13:00:33 -0700215 break;
216 }
Adrian Roos7e39e592015-09-23 17:03:47 -0700217
218 if (hasChargingTime) {
219 String chargingTimeFormatted = Formatter.formatShortElapsedTimeRoundingUpToMinutes(
220 mContext, chargingTimeRemaining);
221 return mContext.getResources().getString(chargingId, chargingTimeFormatted);
222 } else {
223 return mContext.getResources().getString(chargingId);
224 }
Adrian Roos12c1ef52014-06-04 13:54:08 +0200225 }
226
227 KeyguardUpdateMonitorCallback mUpdateMonitor = new KeyguardUpdateMonitorCallback() {
228 @Override
229 public void onRefreshBatteryInfo(KeyguardUpdateMonitor.BatteryStatus status) {
Adrian Roosad3bc7f2014-10-30 18:29:38 +0100230 boolean isChargingOrFull = status.status == BatteryManager.BATTERY_STATUS_CHARGING
Adrian Roos12c1ef52014-06-04 13:54:08 +0200231 || status.status == BatteryManager.BATTERY_STATUS_FULL;
Adrian Roosad3bc7f2014-10-30 18:29:38 +0100232 mPowerPluggedIn = status.isPluggedIn() && isChargingOrFull;
Adrian Roos12c1ef52014-06-04 13:54:08 +0200233 mPowerCharged = status.isCharged();
Adrian Roos0c859ae2015-11-23 16:47:50 -0800234 mChargingWattage = status.maxChargingWattage;
Adrian Roos7b043112015-07-10 13:00:33 -0700235 mChargingSpeed = status.getChargingSpeed(mSlowThreshold, mFastThreshold);
Adrian Roos12c1ef52014-06-04 13:54:08 +0200236 updateIndication();
237 }
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700238
239 @Override
240 public void onFingerprintHelp(int msgId, String helpString) {
241 KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
242 if (!updateMonitor.isUnlockingWithFingerprintAllowed()) {
243 return;
244 }
245 int errorColor = mContext.getResources().getColor(R.color.system_warning_color, null);
246 if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
247 mStatusBarKeyguardViewManager.showBouncerMessage(helpString, errorColor);
248 } else if (updateMonitor.isDeviceInteractive()) {
249 mLockIcon.setTransientFpError(true);
250 showTransientIndication(helpString, errorColor);
251 mHandler.removeMessages(MSG_CLEAR_FP_MSG);
252 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CLEAR_FP_MSG),
253 TRANSIENT_FP_ERROR_TIMEOUT);
254 }
255 }
256
257 @Override
258 public void onFingerprintError(int msgId, String errString) {
259 KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
260 if (!updateMonitor.isUnlockingWithFingerprintAllowed()
261 || msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
262 return;
263 }
264 int errorColor = mContext.getResources().getColor(R.color.system_warning_color, null);
265 if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
266 mStatusBarKeyguardViewManager.showBouncerMessage(errString, errorColor);
267 } else if (updateMonitor.isDeviceInteractive()) {
268 showTransientIndication(errString, errorColor);
269 // We want to keep this message around in case the screen was off
270 mHandler.removeMessages(MSG_HIDE_TRANSIENT);
271 hideTransientIndicationDelayed(5000);
272 } else {
273 mMessageToShowOnScreenOn = errString;
274 }
275 }
276
277 @Override
278 public void onScreenTurnedOn() {
279 if (mMessageToShowOnScreenOn != null) {
280 int errorColor = mContext.getResources().getColor(R.color.system_warning_color,
281 null);
282 showTransientIndication(mMessageToShowOnScreenOn, errorColor);
283 // We want to keep this message around in case the screen was off
284 mHandler.removeMessages(MSG_HIDE_TRANSIENT);
285 hideTransientIndicationDelayed(5000);
286 mMessageToShowOnScreenOn = null;
287 }
288 }
289
290 @Override
291 public void onFingerprintRunningStateChanged(boolean running) {
292 if (running) {
293 mMessageToShowOnScreenOn = null;
294 }
295 }
Adrian Roos12c1ef52014-06-04 13:54:08 +0200296 };
297
298 BroadcastReceiver mReceiver = new BroadcastReceiver() {
299 @Override
300 public void onReceive(Context context, Intent intent) {
301 if (mVisible) {
302 updateIndication();
303 }
304 }
305 };
306
307 private final Handler mHandler = new Handler() {
308 @Override
309 public void handleMessage(Message msg) {
310 if (msg.what == MSG_HIDE_TRANSIENT && mTransientIndication != null) {
311 mTransientIndication = null;
312 updateIndication();
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700313 } else if (msg.what == MSG_CLEAR_FP_MSG) {
314 mLockIcon.setTransientFpError(false);
315 hideTransientIndication();
Adrian Roos12c1ef52014-06-04 13:54:08 +0200316 }
317 }
318 };
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700319
320 public void setStatusBarKeyguardViewManager(
321 StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
322 mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
323 }
Adrian Roos12c1ef52014-06-04 13:54:08 +0200324}