blob: 1ff98ddf22674c26df1161dd256d640549ebf677 [file] [log] [blame]
Jim Miller0b728242012-10-28 19:42:30 -07001/*
2 * Copyright (C) 2011 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
Jim Miller5ecd8112013-01-09 18:50:26 -080017package com.android.keyguard;
Jim Miller0b728242012-10-28 19:42:30 -070018
Lucas Dupin2e838ac2019-04-17 16:50:58 -070019import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
20
Jim Miller0b728242012-10-28 19:42:30 -070021import android.content.Context;
Jason Chang1e4a4bd2018-05-22 17:30:19 +080022import android.content.res.ColorStateList;
Lucas Dupin2e838ac2019-04-17 16:50:58 -070023import android.content.res.TypedArray;
24import android.graphics.Color;
Jim Miller0b728242012-10-28 19:42:30 -070025import android.os.Handler;
26import android.os.Looper;
Alan Viveretteb428b0f2013-02-07 12:19:15 -080027import android.os.SystemClock;
Jim Miller0b728242012-10-28 19:42:30 -070028import android.text.TextUtils;
29import android.util.AttributeSet;
Lucas Dupin32774922019-04-25 12:42:25 -070030import android.util.TypedValue;
Jim Miller0b728242012-10-28 19:42:30 -070031import android.view.View;
32import android.widget.TextView;
33
Sunny Goyal87fccf02019-08-13 17:39:10 -070034import com.android.systemui.R;
Lucas Dupin2e838ac2019-04-17 16:50:58 -070035import com.android.systemui.statusbar.policy.ConfigurationController;
36
Alan Viveretteb428b0f2013-02-07 12:19:15 -080037import java.lang.ref.WeakReference;
38
Lucas Dupin2e838ac2019-04-17 16:50:58 -070039import javax.inject.Inject;
40import javax.inject.Named;
41
Jim Miller0b728242012-10-28 19:42:30 -070042/***
43 * Manages a number of views inside of the given layout. See below for a list of widgets.
44 */
Lucas Dupin2e838ac2019-04-17 16:50:58 -070045public class KeyguardMessageArea extends TextView implements SecurityMessageDisplay,
46 ConfigurationController.ConfigurationListener {
Alan Viveretteb428b0f2013-02-07 12:19:15 -080047 /** Handler token posted with accessibility announcement runnables. */
48 private static final Object ANNOUNCE_TOKEN = new Object();
49
50 /**
51 * Delay before speaking an accessibility announcement. Used to prevent
52 * lift-to-type from interrupting itself.
53 */
54 private static final long ANNOUNCEMENT_DELAY = 250;
Selim Cinekcfafe4e2015-08-11 14:58:44 -070055 private static final int DEFAULT_COLOR = -1;
Alan Viveretteb428b0f2013-02-07 12:19:15 -080056
Adrian Roos28828b52015-05-25 18:48:14 -070057 private final Handler mHandler;
Lucas Dupin2e838ac2019-04-17 16:50:58 -070058 private final ConfigurationController mConfigurationController;
Jim Miller0b728242012-10-28 19:42:30 -070059
Lucas Dupin2e838ac2019-04-17 16:50:58 -070060 private ColorStateList mDefaultColorState;
Adrian Roos154b9ee2016-10-20 15:34:23 -070061 private CharSequence mMessage;
Jason Chang1e4a4bd2018-05-22 17:30:19 +080062 private ColorStateList mNextMessageColorState = ColorStateList.valueOf(DEFAULT_COLOR);
Lucas Dupin473f3a52019-04-30 15:33:28 -070063 private boolean mBouncerVisible;
Jim Miller187ec582013-04-15 18:27:54 -070064
Jim Miller0b728242012-10-28 19:42:30 -070065 private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
Jorim Jaggi0d210f62015-07-10 14:24:44 -070066 public void onFinishedGoingToSleep(int why) {
Jim Miller20daffd2013-10-07 14:59:53 -070067 setSelected(false);
Lucas Dupin473f3a52019-04-30 15:33:28 -070068 }
69
Jorim Jaggi0d210f62015-07-10 14:24:44 -070070 public void onStartedWakingUp() {
Jim Miller20daffd2013-10-07 14:59:53 -070071 setSelected(true);
Lucas Dupin473f3a52019-04-30 15:33:28 -070072 }
73
74 @Override
75 public void onKeyguardBouncerChanged(boolean bouncer) {
76 mBouncerVisible = bouncer;
77 update();
78 }
Jim Miller0b728242012-10-28 19:42:30 -070079 };
80
81 public KeyguardMessageArea(Context context) {
Lucas Dupin2e838ac2019-04-17 16:50:58 -070082 super(context, null);
83 throw new IllegalStateException("This constructor should never be invoked");
Jim Miller0b728242012-10-28 19:42:30 -070084 }
85
Lucas Dupin2e838ac2019-04-17 16:50:58 -070086 @Inject
87 public KeyguardMessageArea(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
88 ConfigurationController configurationController) {
89 this(context, attrs, KeyguardUpdateMonitor.getInstance(context), configurationController);
Adrian Roos154b9ee2016-10-20 15:34:23 -070090 }
91
Lucas Dupin2e838ac2019-04-17 16:50:58 -070092 public KeyguardMessageArea(Context context, AttributeSet attrs, KeyguardUpdateMonitor monitor,
93 ConfigurationController configurationController) {
Jim Miller0b728242012-10-28 19:42:30 -070094 super(context, attrs);
Chris Craik362adb82013-11-05 17:41:21 -080095 setLayerType(LAYER_TYPE_HARDWARE, null); // work around nested unclipped SaveLayer bug
Jim Miller0b728242012-10-28 19:42:30 -070096
Adrian Roos154b9ee2016-10-20 15:34:23 -070097 monitor.registerCallback(mInfoCallback);
Jim Miller0b728242012-10-28 19:42:30 -070098 mHandler = new Handler(Looper.myLooper());
Lucas Dupin2e838ac2019-04-17 16:50:58 -070099 mConfigurationController = configurationController;
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700100 onThemeChanged();
Jim Miller0b728242012-10-28 19:42:30 -0700101 }
102
Jim Miller20daffd2013-10-07 14:59:53 -0700103 @Override
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700104 protected void onAttachedToWindow() {
105 super.onAttachedToWindow();
106 mConfigurationController.addCallback(this);
Lucas Dupin12dab902019-04-19 11:10:48 -0700107 onThemeChanged();
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700108 }
109
110 @Override
111 protected void onDetachedFromWindow() {
112 super.onDetachedFromWindow();
113 mConfigurationController.removeCallback(this);
114 }
115
116 @Override
Jason Chang1e4a4bd2018-05-22 17:30:19 +0800117 public void setNextMessageColor(ColorStateList colorState) {
118 mNextMessageColorState = colorState;
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700119 }
120
121 @Override
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700122 public void onThemeChanged() {
123 TypedArray array = mContext.obtainStyledAttributes(new int[] {
124 R.attr.wallpaperTextColor
125 });
126 ColorStateList newTextColors = ColorStateList.valueOf(array.getColor(0, Color.RED));
127 array.recycle();
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700128 mDefaultColorState = newTextColors;
Lucas Dupin12dab902019-04-19 11:10:48 -0700129 update();
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700130 }
131
132 @Override
Lucas Dupin32774922019-04-25 12:42:25 -0700133 public void onDensityOrFontScaleChanged() {
134 TypedArray array = mContext.obtainStyledAttributes(R.style.Keyguard_TextView, new int[] {
135 android.R.attr.textSize
136 });
137 setTextSize(TypedValue.COMPLEX_UNIT_PX, array.getDimensionPixelSize(0, 0));
138 array.recycle();
139 }
140
141 @Override
Adrian Roosdb327e92016-10-12 16:41:28 -0700142 public void setMessage(CharSequence msg) {
143 if (!TextUtils.isEmpty(msg)) {
Adrian Roos28828b52015-05-25 18:48:14 -0700144 securityMessageChanged(msg);
145 } else {
146 clearMessage();
147 }
148 }
149
150 @Override
Adrian Roosdb327e92016-10-12 16:41:28 -0700151 public void setMessage(int resId) {
152 CharSequence message = null;
153 if (resId != 0) {
154 message = getContext().getResources().getText(resId);
Adrian Roos28828b52015-05-25 18:48:14 -0700155 }
Adrian Roosdb327e92016-10-12 16:41:28 -0700156 setMessage(message);
Adrian Roos28828b52015-05-25 18:48:14 -0700157 }
158
159 @Override
Adrian Roosdb327e92016-10-12 16:41:28 -0700160 public void formatMessage(int resId, Object... formatArgs) {
161 CharSequence message = null;
162 if (resId != 0) {
163 message = getContext().getString(resId, formatArgs);
Adrian Roos28828b52015-05-25 18:48:14 -0700164 }
Adrian Roosdb327e92016-10-12 16:41:28 -0700165 setMessage(message);
Adrian Roos28828b52015-05-25 18:48:14 -0700166 }
167
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700168 public static KeyguardMessageArea findSecurityMessageDisplay(View v) {
169 KeyguardMessageArea messageArea = v.findViewById(R.id.keyguard_message_area);
170 if (messageArea == null) {
171 messageArea = v.getRootView().findViewById(R.id.keyguard_message_area);
172 }
Adrian Roos28828b52015-05-25 18:48:14 -0700173 if (messageArea == null) {
174 throw new RuntimeException("Can't find keyguard_message_area in " + v.getClass());
175 }
176 return messageArea;
177 }
178
179 @Override
Jim Miller20daffd2013-10-07 14:59:53 -0700180 protected void onFinishInflate() {
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700181 boolean shouldMarquee = KeyguardUpdateMonitor.getInstance(mContext).isDeviceInteractive();
182 setSelected(shouldMarquee); // This is required to ensure marquee works
Jim Miller20daffd2013-10-07 14:59:53 -0700183 }
184
Adrian Roos28828b52015-05-25 18:48:14 -0700185 private void securityMessageChanged(CharSequence message) {
186 mMessage = message;
Jim Miller0b728242012-10-28 19:42:30 -0700187 update();
Alan Viveretteb428b0f2013-02-07 12:19:15 -0800188 mHandler.removeCallbacksAndMessages(ANNOUNCE_TOKEN);
189 mHandler.postAtTime(new AnnounceRunnable(this, getText()), ANNOUNCE_TOKEN,
190 (SystemClock.uptimeMillis() + ANNOUNCEMENT_DELAY));
Jim Miller0b728242012-10-28 19:42:30 -0700191 }
192
Adrian Roos28828b52015-05-25 18:48:14 -0700193 private void clearMessage() {
Adrian Roos154b9ee2016-10-20 15:34:23 -0700194 mMessage = null;
195 update();
Xiyuan Xia09eb0332015-05-13 15:29:42 -0700196 }
197
Adrian Roos28828b52015-05-25 18:48:14 -0700198 private void update() {
199 CharSequence status = mMessage;
Lucas Dupin473f3a52019-04-30 15:33:28 -0700200 setVisibility(TextUtils.isEmpty(status) || !mBouncerVisible ? INVISIBLE : VISIBLE);
Jim Miller0b728242012-10-28 19:42:30 -0700201 setText(status);
Jason Chang1e4a4bd2018-05-22 17:30:19 +0800202 ColorStateList colorState = mDefaultColorState;
203 if (mNextMessageColorState.getDefaultColor() != DEFAULT_COLOR) {
204 colorState = mNextMessageColorState;
205 mNextMessageColorState = ColorStateList.valueOf(DEFAULT_COLOR);
Selim Cinekcfafe4e2015-08-11 14:58:44 -0700206 }
Jason Chang1e4a4bd2018-05-22 17:30:19 +0800207 setTextColor(colorState);
Jim Miller0b728242012-10-28 19:42:30 -0700208 }
209
Jim Miller0b728242012-10-28 19:42:30 -0700210
Alan Viveretteb428b0f2013-02-07 12:19:15 -0800211 /**
212 * Runnable used to delay accessibility announcements.
213 */
214 private static class AnnounceRunnable implements Runnable {
215 private final WeakReference<View> mHost;
216 private final CharSequence mTextToAnnounce;
217
Adrian Roos28828b52015-05-25 18:48:14 -0700218 AnnounceRunnable(View host, CharSequence textToAnnounce) {
Alan Viveretteb428b0f2013-02-07 12:19:15 -0800219 mHost = new WeakReference<View>(host);
220 mTextToAnnounce = textToAnnounce;
221 }
222
223 @Override
224 public void run() {
225 final View host = mHost.get();
226 if (host != null) {
227 host.announceForAccessibility(mTextToAnnounce);
228 }
229 }
230 }
Jim Miller0b728242012-10-28 19:42:30 -0700231}