blob: 43047ed6a5c561c38fd2709609e0f27fffa6ecb8 [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
Bartosz Fabianowski5f045002016-12-01 10:36:18 +010019import android.app.admin.DevicePolicyManager;
Adrian Roos12c1ef52014-06-04 13:54:08 +020020import android.content.BroadcastReceiver;
21import android.content.Context;
22import android.content.Intent;
23import android.content.IntentFilter;
Adrian Roos7b043112015-07-10 13:00:33 -070024import android.content.res.Resources;
Jorim Jaggi27c9b742015-04-09 10:34:49 -070025import android.graphics.Color;
Selim Cinekcfafe4e2015-08-11 14:58:44 -070026import android.hardware.fingerprint.FingerprintManager;
Adrian Roos12c1ef52014-06-04 13:54:08 +020027import android.os.BatteryManager;
28import android.os.BatteryStats;
29import android.os.Handler;
30import android.os.Message;
31import android.os.RemoteException;
32import android.os.ServiceManager;
33import android.os.UserHandle;
Jeff Sharkeyb6edaa92016-07-27 15:51:31 -060034import android.os.UserManager;
Adrian Roos12c1ef52014-06-04 13:54:08 +020035import android.text.TextUtils;
36import android.text.format.Formatter;
37import android.util.Log;
38import android.view.View;
Bartosz Fabianowski5f045002016-12-01 10:36:18 +010039import android.view.ViewGroup;
Adrian Roos12c1ef52014-06-04 13:54:08 +020040
Adrian Roosc1b50322017-02-27 21:07:58 +010041import com.android.internal.annotations.VisibleForTesting;
Selim Cinekcfafe4e2015-08-11 14:58:44 -070042import com.android.internal.app.IBatteryStats;
43import com.android.keyguard.KeyguardUpdateMonitor;
44import com.android.keyguard.KeyguardUpdateMonitorCallback;
Jason Monk58be7a62017-02-01 20:17:51 -050045import com.android.settingslib.Utils;
Jason Monk9c7844c2017-01-18 15:21:53 -050046import com.android.systemui.Dependency;
Selim Cinekcfafe4e2015-08-11 14:58:44 -070047import com.android.systemui.R;
48import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
49import com.android.systemui.statusbar.phone.LockIcon;
50import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
Zachary Iqbalf50284c2017-01-22 18:54:46 -080051import com.android.systemui.statusbar.policy.UserInfoController;
Adrian Roosc1b50322017-02-27 21:07:58 +010052import com.android.systemui.util.wakelock.SettableWakeLock;
53import com.android.systemui.util.wakelock.WakeLock;
Selim Cinekcfafe4e2015-08-11 14:58:44 -070054
Lucas Dupin4272f442018-01-13 22:00:35 -080055import java.text.NumberFormat;
56
Adrian Roos12c1ef52014-06-04 13:54:08 +020057/**
Selim Cinekcfafe4e2015-08-11 14:58:44 -070058 * Controls the indications and error messages shown on the Keyguard
Adrian Roos12c1ef52014-06-04 13:54:08 +020059 */
60public class KeyguardIndicationController {
61
Adrian Roos0c859ae2015-11-23 16:47:50 -080062 private static final String TAG = "KeyguardIndication";
63 private static final boolean DEBUG_CHARGING_SPEED = false;
Adrian Roos12c1ef52014-06-04 13:54:08 +020064
65 private static final int MSG_HIDE_TRANSIENT = 1;
Selim Cinekcfafe4e2015-08-11 14:58:44 -070066 private static final int MSG_CLEAR_FP_MSG = 2;
67 private static final long TRANSIENT_FP_ERROR_TIMEOUT = 1300;
Adrian Roos12c1ef52014-06-04 13:54:08 +020068
69 private final Context mContext;
Lucas Dupin987f1932017-05-13 21:02:52 -070070 private ViewGroup mIndicationArea;
71 private KeyguardIndicationTextView mTextView;
72 private KeyguardIndicationTextView mDisclosure;
Jeff Sharkeyb6edaa92016-07-27 15:51:31 -060073 private final UserManager mUserManager;
Adrian Roos12c1ef52014-06-04 13:54:08 +020074 private final IBatteryStats mBatteryInfo;
Adrian Roosc1b50322017-02-27 21:07:58 +010075 private final SettableWakeLock mWakeLock;
Adrian Roos12c1ef52014-06-04 13:54:08 +020076
Adrian Roos7b043112015-07-10 13:00:33 -070077 private final int mSlowThreshold;
78 private final int mFastThreshold;
Lucas Dupin987f1932017-05-13 21:02:52 -070079 private LockIcon mLockIcon;
Selim Cinekcfafe4e2015-08-11 14:58:44 -070080 private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
Adrian Roos7b043112015-07-10 13:00:33 -070081
Adrian Roos12c1ef52014-06-04 13:54:08 +020082 private String mRestingIndication;
Lucas Dupinef886542018-01-03 16:03:07 -080083 private CharSequence mTransientIndication;
Jorim Jaggi27c9b742015-04-09 10:34:49 -070084 private int mTransientTextColor;
Lucas Dupin53d50622017-05-13 15:54:14 -070085 private int mInitialTextColor;
Adrian Roos12c1ef52014-06-04 13:54:08 +020086 private boolean mVisible;
87
88 private boolean mPowerPluggedIn;
89 private boolean mPowerCharged;
Adrian Roos7b043112015-07-10 13:00:33 -070090 private int mChargingSpeed;
Adrian Roos0c859ae2015-11-23 16:47:50 -080091 private int mChargingWattage;
Lucas Dupin4272f442018-01-13 22:00:35 -080092 private int mBatteryLevel;
Selim Cinekcfafe4e2015-08-11 14:58:44 -070093 private String mMessageToShowOnScreenOn;
Adrian Roos12c1ef52014-06-04 13:54:08 +020094
Zachary Iqbal8f4c2422017-04-20 17:56:42 -070095 private KeyguardUpdateMonitorCallback mUpdateMonitorCallback;
Zachary Iqbalf50284c2017-01-22 18:54:46 -080096
Bartosz Fabianowski5f045002016-12-01 10:36:18 +010097 private final DevicePolicyManager mDevicePolicyManager;
Adrian Roos91ba3072017-02-14 16:50:46 +010098 private boolean mDozing;
Bartosz Fabianowski5f045002016-12-01 10:36:18 +010099
Adrian Roosaf45b602017-03-14 13:10:25 -0700100 /**
101 * Creates a new KeyguardIndicationController and registers callbacks.
102 */
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100103 public KeyguardIndicationController(Context context, ViewGroup indicationArea,
104 LockIcon lockIcon) {
Adrian Roosc1b50322017-02-27 21:07:58 +0100105 this(context, indicationArea, lockIcon,
106 WakeLock.createPartial(context, "Doze:KeyguardIndication"));
Adrian Roosaf45b602017-03-14 13:10:25 -0700107
108 registerCallbacks(KeyguardUpdateMonitor.getInstance(context));
Adrian Roosc1b50322017-02-27 21:07:58 +0100109 }
110
Adrian Roosaf45b602017-03-14 13:10:25 -0700111 /**
112 * Creates a new KeyguardIndicationController for testing. Does *not* register callbacks.
113 */
Adrian Roosc1b50322017-02-27 21:07:58 +0100114 @VisibleForTesting
115 KeyguardIndicationController(Context context, ViewGroup indicationArea, LockIcon lockIcon,
116 WakeLock wakeLock) {
Adrian Roos12c1ef52014-06-04 13:54:08 +0200117 mContext = context;
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100118 mIndicationArea = indicationArea;
119 mTextView = (KeyguardIndicationTextView) indicationArea.findViewById(
120 R.id.keyguard_indication_text);
Lucas Dupin987f1932017-05-13 21:02:52 -0700121 mInitialTextColor = mTextView != null ? mTextView.getCurrentTextColor() : Color.WHITE;
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100122 mDisclosure = (KeyguardIndicationTextView) indicationArea.findViewById(
123 R.id.keyguard_indication_enterprise_disclosure);
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700124 mLockIcon = lockIcon;
Adrian Roosc1b50322017-02-27 21:07:58 +0100125 mWakeLock = new SettableWakeLock(wakeLock);
Adrian Roos12c1ef52014-06-04 13:54:08 +0200126
Adrian Roos7b043112015-07-10 13:00:33 -0700127 Resources res = context.getResources();
128 mSlowThreshold = res.getInteger(R.integer.config_chargingSlowlyThreshold);
129 mFastThreshold = res.getInteger(R.integer.config_chargingFastThreshold);
130
Jeff Sharkeyb6edaa92016-07-27 15:51:31 -0600131 mUserManager = context.getSystemService(UserManager.class);
Adrian Roos12c1ef52014-06-04 13:54:08 +0200132 mBatteryInfo = IBatteryStats.Stub.asInterface(
133 ServiceManager.getService(BatteryStats.SERVICE_NAME));
Jeff Sharkeyb6edaa92016-07-27 15:51:31 -0600134
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100135 mDevicePolicyManager = (DevicePolicyManager) context.getSystemService(
136 Context.DEVICE_POLICY_SERVICE);
137
Adrian Roosaf45b602017-03-14 13:10:25 -0700138 updateDisclosure();
139 }
140
141 private void registerCallbacks(KeyguardUpdateMonitor monitor) {
142 monitor.registerCallback(getKeyguardCallback());
143
144 mContext.registerReceiverAsUser(mTickReceiver, UserHandle.SYSTEM,
Jason Monkcd26af72017-01-11 14:32:58 -0500145 new IntentFilter(Intent.ACTION_TIME_TICK), null,
Jason Monk9c7844c2017-01-18 15:21:53 -0500146 Dependency.get(Dependency.TIME_TICK_HANDLER));
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100147 }
148
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800149 /**
150 * Gets the {@link KeyguardUpdateMonitorCallback} instance associated with this
151 * {@link KeyguardIndicationController}.
152 *
153 * <p>Subclasses may override this method to extend or change the callback behavior by extending
154 * the {@link BaseKeyguardCallback}.
155 *
156 * @return A KeyguardUpdateMonitorCallback. Multiple calls to this method <b>must</b> return the
157 * same instance.
158 */
159 protected KeyguardUpdateMonitorCallback getKeyguardCallback() {
Zachary Iqbal8f4c2422017-04-20 17:56:42 -0700160 if (mUpdateMonitorCallback == null) {
161 mUpdateMonitorCallback = new BaseKeyguardCallback();
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800162 }
Zachary Iqbal8f4c2422017-04-20 17:56:42 -0700163 return mUpdateMonitorCallback;
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800164 }
165
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100166 private void updateDisclosure() {
167 if (mDevicePolicyManager == null) {
168 return;
169 }
170
Adrian Roos91ba3072017-02-14 16:50:46 +0100171 if (!mDozing && mDevicePolicyManager.isDeviceManaged()) {
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100172 final CharSequence organizationName =
173 mDevicePolicyManager.getDeviceOwnerOrganizationName();
174 if (organizationName != null) {
175 mDisclosure.switchIndication(mContext.getResources().getString(
176 R.string.do_disclosure_with_name, organizationName));
177 } else {
178 mDisclosure.switchIndication(R.string.do_disclosure_generic);
179 }
180 mDisclosure.setVisibility(View.VISIBLE);
181 } else {
182 mDisclosure.setVisibility(View.GONE);
183 }
Adrian Roos12c1ef52014-06-04 13:54:08 +0200184 }
185
186 public void setVisible(boolean visible) {
187 mVisible = visible;
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100188 mIndicationArea.setVisibility(visible ? View.VISIBLE : View.GONE);
Adrian Roos12c1ef52014-06-04 13:54:08 +0200189 if (visible) {
Kevin Chyn4c4001c2017-08-25 14:23:36 -0700190 // If this is called after an error message was already shown, we should not clear it.
191 // Otherwise the error message won't be shown
192 if (!mHandler.hasMessages(MSG_HIDE_TRANSIENT)) {
193 hideTransientIndication();
194 }
Adrian Roos12c1ef52014-06-04 13:54:08 +0200195 updateIndication();
Kevin Chyn4c4001c2017-08-25 14:23:36 -0700196 } else if (!visible) {
197 // If we unlock and return to keyguard quickly, previous error should not be shown
198 hideTransientIndication();
Adrian Roos12c1ef52014-06-04 13:54:08 +0200199 }
200 }
201
202 /**
203 * Sets the indication that is shown if nothing else is showing.
204 */
205 public void setRestingIndication(String restingIndication) {
206 mRestingIndication = restingIndication;
207 updateIndication();
208 }
209
210 /**
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800211 * Sets the active controller managing changes and callbacks to user information.
212 */
213 public void setUserInfoController(UserInfoController userInfoController) {
214 }
215
216 /**
Zachary Iqbal8f4c2422017-04-20 17:56:42 -0700217 * Returns the indication text indicating that trust has been granted.
218 *
219 * @return {@code null} or an empty string if a trust indication text should not be shown.
220 */
Zachary Iqbaldc05aa02017-05-17 18:52:49 -0700221 protected String getTrustGrantedIndication() {
222 return null;
223 }
224
225 /**
226 * Returns the indication text indicating that trust is currently being managed.
227 *
228 * @return {@code null} or an empty string if a trust managed text should not be shown.
229 */
230 protected String getTrustManagedIndication() {
Zachary Iqbal8f4c2422017-04-20 17:56:42 -0700231 return null;
232 }
233
234 /**
Adrian Roos12c1ef52014-06-04 13:54:08 +0200235 * Hides transient indication in {@param delayMs}.
236 */
237 public void hideTransientIndicationDelayed(long delayMs) {
238 mHandler.sendMessageDelayed(
239 mHandler.obtainMessage(MSG_HIDE_TRANSIENT), delayMs);
240 }
241
242 /**
243 * Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}.
244 */
245 public void showTransientIndication(int transientIndication) {
246 showTransientIndication(mContext.getResources().getString(transientIndication));
247 }
248
249 /**
250 * Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}.
251 */
Lucas Dupinef886542018-01-03 16:03:07 -0800252 public void showTransientIndication(CharSequence transientIndication) {
Lucas Dupin53d50622017-05-13 15:54:14 -0700253 showTransientIndication(transientIndication, mInitialTextColor);
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700254 }
255
256 /**
257 * Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}.
258 */
Lucas Dupinef886542018-01-03 16:03:07 -0800259 public void showTransientIndication(CharSequence transientIndication, int textColor) {
Adrian Roos12c1ef52014-06-04 13:54:08 +0200260 mTransientIndication = transientIndication;
Jorim Jaggi27c9b742015-04-09 10:34:49 -0700261 mTransientTextColor = textColor;
Adrian Roos12c1ef52014-06-04 13:54:08 +0200262 mHandler.removeMessages(MSG_HIDE_TRANSIENT);
Adrian Roosc1b50322017-02-27 21:07:58 +0100263 if (mDozing && !TextUtils.isEmpty(mTransientIndication)) {
264 // Make sure this doesn't get stuck and burns in. Acquire wakelock until its cleared.
265 mWakeLock.setAcquired(true);
266 hideTransientIndicationDelayed(BaseKeyguardCallback.HIDE_DELAY_MS);
267 }
Adrian Roos12c1ef52014-06-04 13:54:08 +0200268 updateIndication();
269 }
270
271 /**
272 * Hides transient indication.
273 */
274 public void hideTransientIndication() {
275 if (mTransientIndication != null) {
276 mTransientIndication = null;
277 mHandler.removeMessages(MSG_HIDE_TRANSIENT);
278 updateIndication();
279 }
280 }
281
Zachary Iqbal8f4c2422017-04-20 17:56:42 -0700282 protected final void updateIndication() {
Adrian Roosc1b50322017-02-27 21:07:58 +0100283 if (TextUtils.isEmpty(mTransientIndication)) {
284 mWakeLock.setAcquired(false);
285 }
286
Adrian Roos12c1ef52014-06-04 13:54:08 +0200287 if (mVisible) {
Lucas Dupin53d50622017-05-13 15:54:14 -0700288 // Walk down a precedence-ordered list of what indication
Jeff Sharkeyb6edaa92016-07-27 15:51:31 -0600289 // should be shown based on user or device state
Adrian Roos91ba3072017-02-14 16:50:46 +0100290 if (mDozing) {
Lucas Dupin4272f442018-01-13 22:00:35 -0800291 mTextView.setTextColor(Color.WHITE);
Adrian Roos91ba3072017-02-14 16:50:46 +0100292 if (!TextUtils.isEmpty(mTransientIndication)) {
Adrian Roos12e112d2017-07-25 16:46:23 +0200293 // When dozing we ignore any text color and use white instead, because
294 // colors can be hard to read in low brightness.
Adrian Roos91ba3072017-02-14 16:50:46 +0100295 mTextView.switchIndication(mTransientIndication);
Lucas Dupin4272f442018-01-13 22:00:35 -0800296 } else if (mPowerPluggedIn) {
297 String indication = computePowerIndication();
298 mTextView.switchIndication(indication);
Adrian Roos91ba3072017-02-14 16:50:46 +0100299 } else {
Lucas Dupin4272f442018-01-13 22:00:35 -0800300 String percentage = NumberFormat.getPercentInstance()
301 .format(mBatteryLevel / 100f);
302 mTextView.switchIndication(percentage);
Adrian Roos91ba3072017-02-14 16:50:46 +0100303 }
304 return;
305 }
306
Zachary Iqbal8f4c2422017-04-20 17:56:42 -0700307 KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
Jorim Jaggifabc7432017-05-15 02:40:05 +0200308 int userId = KeyguardUpdateMonitor.getCurrentUser();
Zachary Iqbaldc05aa02017-05-17 18:52:49 -0700309 String trustGrantedIndication = getTrustGrantedIndication();
310 String trustManagedIndication = getTrustManagedIndication();
Zachary Iqbal8f4c2422017-04-20 17:56:42 -0700311 if (!mUserManager.isUserUnlocked(userId)) {
Jeff Sharkeyb6edaa92016-07-27 15:51:31 -0600312 mTextView.switchIndication(com.android.internal.R.string.lockscreen_storage_locked);
Lucas Dupin53d50622017-05-13 15:54:14 -0700313 mTextView.setTextColor(mInitialTextColor);
Jeff Sharkeyb6edaa92016-07-27 15:51:31 -0600314 } else if (!TextUtils.isEmpty(mTransientIndication)) {
315 mTextView.switchIndication(mTransientIndication);
316 mTextView.setTextColor(mTransientTextColor);
Zachary Iqbaldc05aa02017-05-17 18:52:49 -0700317 } else if (!TextUtils.isEmpty(trustGrantedIndication)
Zachary Iqbal8f4c2422017-04-20 17:56:42 -0700318 && updateMonitor.getUserHasTrust(userId)) {
Zachary Iqbaldc05aa02017-05-17 18:52:49 -0700319 mTextView.switchIndication(trustGrantedIndication);
Lucas Dupin53d50622017-05-13 15:54:14 -0700320 mTextView.setTextColor(mInitialTextColor);
Jeff Sharkeyb6edaa92016-07-27 15:51:31 -0600321 } else if (mPowerPluggedIn) {
322 String indication = computePowerIndication();
323 if (DEBUG_CHARGING_SPEED) {
324 indication += ", " + (mChargingWattage / 1000) + " mW";
325 }
326 mTextView.switchIndication(indication);
Lucas Dupin53d50622017-05-13 15:54:14 -0700327 mTextView.setTextColor(mInitialTextColor);
Zachary Iqbaldc05aa02017-05-17 18:52:49 -0700328 } else if (!TextUtils.isEmpty(trustManagedIndication)
329 && updateMonitor.getUserTrustIsManaged(userId)
330 && !updateMonitor.getUserHasTrust(userId)) {
331 mTextView.switchIndication(trustManagedIndication);
Lucas Dupin53d50622017-05-13 15:54:14 -0700332 mTextView.setTextColor(mInitialTextColor);
Jeff Sharkeyb6edaa92016-07-27 15:51:31 -0600333 } else {
334 mTextView.switchIndication(mRestingIndication);
Lucas Dupin53d50622017-05-13 15:54:14 -0700335 mTextView.setTextColor(mInitialTextColor);
Adrian Roos7b043112015-07-10 13:00:33 -0700336 }
Adrian Roos12c1ef52014-06-04 13:54:08 +0200337 }
Adrian Roos12c1ef52014-06-04 13:54:08 +0200338 }
339
340 private String computePowerIndication() {
341 if (mPowerCharged) {
342 return mContext.getResources().getString(R.string.keyguard_charged);
343 }
344
345 // Try fetching charging time from battery stats.
Adrian Roos7e39e592015-09-23 17:03:47 -0700346 long chargingTimeRemaining = 0;
Adrian Roos12c1ef52014-06-04 13:54:08 +0200347 try {
Adrian Roos7e39e592015-09-23 17:03:47 -0700348 chargingTimeRemaining = mBatteryInfo.computeChargeTimeRemaining();
349
Adrian Roos12c1ef52014-06-04 13:54:08 +0200350 } catch (RemoteException e) {
351 Log.e(TAG, "Error calling IBatteryStats: ", e);
352 }
Adrian Roos7e39e592015-09-23 17:03:47 -0700353 final boolean hasChargingTime = chargingTimeRemaining > 0;
Adrian Roos12c1ef52014-06-04 13:54:08 +0200354
Adrian Roos7b043112015-07-10 13:00:33 -0700355 int chargingId;
356 switch (mChargingSpeed) {
357 case KeyguardUpdateMonitor.BatteryStatus.CHARGING_FAST:
Adrian Roos7e39e592015-09-23 17:03:47 -0700358 chargingId = hasChargingTime
Adrian Roosf142cac2015-09-25 15:15:17 -0700359 ? R.string.keyguard_indication_charging_time_fast
Adrian Roos7e39e592015-09-23 17:03:47 -0700360 : R.string.keyguard_plugged_in_charging_fast;
Adrian Roos7b043112015-07-10 13:00:33 -0700361 break;
362 case KeyguardUpdateMonitor.BatteryStatus.CHARGING_SLOWLY:
Adrian Roos7e39e592015-09-23 17:03:47 -0700363 chargingId = hasChargingTime
Adrian Roosf142cac2015-09-25 15:15:17 -0700364 ? R.string.keyguard_indication_charging_time_slowly
Adrian Roos7e39e592015-09-23 17:03:47 -0700365 : R.string.keyguard_plugged_in_charging_slowly;
Adrian Roos7b043112015-07-10 13:00:33 -0700366 break;
367 default:
Adrian Roos7e39e592015-09-23 17:03:47 -0700368 chargingId = hasChargingTime
369 ? R.string.keyguard_indication_charging_time
370 : R.string.keyguard_plugged_in;
Adrian Roos7b043112015-07-10 13:00:33 -0700371 break;
372 }
Adrian Roos7e39e592015-09-23 17:03:47 -0700373
374 if (hasChargingTime) {
375 String chargingTimeFormatted = Formatter.formatShortElapsedTimeRoundingUpToMinutes(
376 mContext, chargingTimeRemaining);
377 return mContext.getResources().getString(chargingId, chargingTimeFormatted);
378 } else {
379 return mContext.getResources().getString(chargingId);
380 }
Adrian Roos12c1ef52014-06-04 13:54:08 +0200381 }
382
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800383 public void setStatusBarKeyguardViewManager(
384 StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
385 mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
386 }
387
Adrian Roosaf45b602017-03-14 13:10:25 -0700388 private final BroadcastReceiver mTickReceiver = new BroadcastReceiver() {
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800389 @Override
390 public void onReceive(Context context, Intent intent) {
391 mHandler.post(() -> {
392 if (mVisible) {
393 updateIndication();
394 }
395 });
396 }
397 };
398
399 private final Handler mHandler = new Handler() {
400 @Override
401 public void handleMessage(Message msg) {
Adrian Roosc1b50322017-02-27 21:07:58 +0100402 if (msg.what == MSG_HIDE_TRANSIENT) {
403 hideTransientIndication();
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800404 } else if (msg.what == MSG_CLEAR_FP_MSG) {
405 mLockIcon.setTransientFpError(false);
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800406 }
407 }
408 };
409
Adrian Roos91ba3072017-02-14 16:50:46 +0100410 public void setDozing(boolean dozing) {
Jorim Jaggifabc7432017-05-15 02:40:05 +0200411 if (mDozing == dozing) {
412 return;
413 }
Adrian Roos91ba3072017-02-14 16:50:46 +0100414 mDozing = dozing;
415 updateIndication();
416 updateDisclosure();
417 }
418
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800419 protected class BaseKeyguardCallback extends KeyguardUpdateMonitorCallback {
Adrian Roos56021892017-02-27 20:25:09 +0100420 public static final int HIDE_DELAY_MS = 5000;
Zachary Iqbalf50284c2017-01-22 18:54:46 -0800421 private int mLastSuccessiveErrorMessage = -1;
Selim Cinek3e451942016-07-14 18:07:53 -0700422
Adrian Roos12c1ef52014-06-04 13:54:08 +0200423 @Override
424 public void onRefreshBatteryInfo(KeyguardUpdateMonitor.BatteryStatus status) {
Adrian Roosad3bc7f2014-10-30 18:29:38 +0100425 boolean isChargingOrFull = status.status == BatteryManager.BATTERY_STATUS_CHARGING
Adrian Roos12c1ef52014-06-04 13:54:08 +0200426 || status.status == BatteryManager.BATTERY_STATUS_FULL;
Adrian Roos56021892017-02-27 20:25:09 +0100427 boolean wasPluggedIn = mPowerPluggedIn;
Adrian Roosad3bc7f2014-10-30 18:29:38 +0100428 mPowerPluggedIn = status.isPluggedIn() && isChargingOrFull;
Adrian Roos12c1ef52014-06-04 13:54:08 +0200429 mPowerCharged = status.isCharged();
Adrian Roos0c859ae2015-11-23 16:47:50 -0800430 mChargingWattage = status.maxChargingWattage;
Adrian Roos7b043112015-07-10 13:00:33 -0700431 mChargingSpeed = status.getChargingSpeed(mSlowThreshold, mFastThreshold);
Lucas Dupin4272f442018-01-13 22:00:35 -0800432 mBatteryLevel = status.level;
Adrian Roos12c1ef52014-06-04 13:54:08 +0200433 updateIndication();
Adrian Roosc1b50322017-02-27 21:07:58 +0100434 if (mDozing) {
435 if (!wasPluggedIn && mPowerPluggedIn) {
436 showTransientIndication(computePowerIndication());
437 hideTransientIndicationDelayed(HIDE_DELAY_MS);
438 } else if (wasPluggedIn && !mPowerPluggedIn) {
439 hideTransientIndication();
440 }
Adrian Roos56021892017-02-27 20:25:09 +0100441 }
Adrian Roos12c1ef52014-06-04 13:54:08 +0200442 }
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700443
444 @Override
Bartosz Fabianowski5f045002016-12-01 10:36:18 +0100445 public void onKeyguardVisibilityChanged(boolean showing) {
446 if (showing) {
447 updateDisclosure();
448 }
449 }
450
451 @Override
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700452 public void onFingerprintHelp(int msgId, String helpString) {
453 KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
454 if (!updateMonitor.isUnlockingWithFingerprintAllowed()) {
455 return;
456 }
Jason Monk58be7a62017-02-01 20:17:51 -0500457 int errorColor = Utils.getColorError(mContext);
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700458 if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
459 mStatusBarKeyguardViewManager.showBouncerMessage(helpString, errorColor);
Kevin Chyn4c4001c2017-08-25 14:23:36 -0700460 } else if (updateMonitor.isScreenOn()) {
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700461 mLockIcon.setTransientFpError(true);
462 showTransientIndication(helpString, errorColor);
Kevin Chyn4c4001c2017-08-25 14:23:36 -0700463 hideTransientIndicationDelayed(TRANSIENT_FP_ERROR_TIMEOUT);
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700464 mHandler.removeMessages(MSG_CLEAR_FP_MSG);
465 mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CLEAR_FP_MSG),
466 TRANSIENT_FP_ERROR_TIMEOUT);
467 }
Selim Cinek3e451942016-07-14 18:07:53 -0700468 // Help messages indicate that there was actually a try since the last error, so those
469 // are not two successive error messages anymore.
470 mLastSuccessiveErrorMessage = -1;
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700471 }
472
473 @Override
474 public void onFingerprintError(int msgId, String errString) {
475 KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
Kevin Chyn4c4001c2017-08-25 14:23:36 -0700476 if ((!updateMonitor.isUnlockingWithFingerprintAllowed()
477 && msgId != FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT)
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700478 || msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
479 return;
480 }
Jason Monk58be7a62017-02-01 20:17:51 -0500481 int errorColor = Utils.getColorError(mContext);
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700482 if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
Selim Cinek3e451942016-07-14 18:07:53 -0700483 // When swiping up right after receiving a fingerprint error, the bouncer calls
484 // authenticate leading to the same message being shown again on the bouncer.
485 // We want to avoid this, as it may confuse the user when the message is too
486 // generic.
487 if (mLastSuccessiveErrorMessage != msgId) {
488 mStatusBarKeyguardViewManager.showBouncerMessage(errString, errorColor);
489 }
Kevin Chyn4c4001c2017-08-25 14:23:36 -0700490 } else if (updateMonitor.isScreenOn()) {
Selim Cinek3e451942016-07-14 18:07:53 -0700491 showTransientIndication(errString, errorColor);
492 // We want to keep this message around in case the screen was off
Adrian Roos56021892017-02-27 20:25:09 +0100493 hideTransientIndicationDelayed(HIDE_DELAY_MS);
Selim Cinek3e451942016-07-14 18:07:53 -0700494 } else {
495 mMessageToShowOnScreenOn = errString;
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700496 }
Selim Cinek3e451942016-07-14 18:07:53 -0700497 mLastSuccessiveErrorMessage = msgId;
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700498 }
499
500 @Override
Lucas Dupinef886542018-01-03 16:03:07 -0800501 public void onTrustAgentErrorMessage(CharSequence message) {
502 int errorColor = Utils.getColorError(mContext);
503 showTransientIndication(message, errorColor);
504 }
505
506 @Override
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700507 public void onScreenTurnedOn() {
508 if (mMessageToShowOnScreenOn != null) {
Jason Monk58be7a62017-02-01 20:17:51 -0500509 int errorColor = Utils.getColorError(mContext);
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700510 showTransientIndication(mMessageToShowOnScreenOn, errorColor);
511 // We want to keep this message around in case the screen was off
Adrian Roos56021892017-02-27 20:25:09 +0100512 hideTransientIndicationDelayed(HIDE_DELAY_MS);
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700513 mMessageToShowOnScreenOn = null;
514 }
515 }
516
517 @Override
518 public void onFingerprintRunningStateChanged(boolean running) {
519 if (running) {
520 mMessageToShowOnScreenOn = null;
521 }
522 }
Selim Cinek3e451942016-07-14 18:07:53 -0700523
524 @Override
525 public void onFingerprintAuthenticated(int userId) {
526 super.onFingerprintAuthenticated(userId);
527 mLastSuccessiveErrorMessage = -1;
528 }
529
530 @Override
531 public void onFingerprintAuthFailed() {
532 super.onFingerprintAuthFailed();
533 mLastSuccessiveErrorMessage = -1;
534 }
Jorim Jaggidadafd42016-09-30 07:20:25 -0700535
536 @Override
537 public void onUserUnlocked() {
538 if (mVisible) {
539 updateIndication();
540 }
541 }
Adrian Roos12c1ef52014-06-04 13:54:08 +0200542 };
Adrian Roos12c1ef52014-06-04 13:54:08 +0200543}