• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.keyguard;
18 
19 import android.content.Context;
20 import android.os.Handler;
21 import android.os.Looper;
22 import android.os.SystemClock;
23 import android.text.TextUtils;
24 import android.util.AttributeSet;
25 import android.view.View;
26 import android.widget.TextView;
27 
28 import java.lang.ref.WeakReference;
29 
30 /***
31  * Manages a number of views inside of the given layout. See below for a list of widgets.
32  */
33 class KeyguardMessageArea extends TextView implements SecurityMessageDisplay {
34     /** Handler token posted with accessibility announcement runnables. */
35     private static final Object ANNOUNCE_TOKEN = new Object();
36 
37     /**
38      * Delay before speaking an accessibility announcement. Used to prevent
39      * lift-to-type from interrupting itself.
40      */
41     private static final long ANNOUNCEMENT_DELAY = 250;
42     private static final int DEFAULT_COLOR = -1;
43 
44     private final Handler mHandler;
45     private final int mDefaultColor;
46 
47     private CharSequence mMessage;
48     private int mNextMessageColor = DEFAULT_COLOR;
49 
50     private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
51         public void onFinishedGoingToSleep(int why) {
52             setSelected(false);
53         };
54         public void onStartedWakingUp() {
55             setSelected(true);
56         };
57     };
58 
KeyguardMessageArea(Context context)59     public KeyguardMessageArea(Context context) {
60         this(context, null);
61     }
62 
KeyguardMessageArea(Context context, AttributeSet attrs)63     public KeyguardMessageArea(Context context, AttributeSet attrs) {
64         this(context, attrs, KeyguardUpdateMonitor.getInstance(context));
65     }
66 
KeyguardMessageArea(Context context, AttributeSet attrs, KeyguardUpdateMonitor monitor)67     public KeyguardMessageArea(Context context, AttributeSet attrs, KeyguardUpdateMonitor monitor) {
68         super(context, attrs);
69         setLayerType(LAYER_TYPE_HARDWARE, null); // work around nested unclipped SaveLayer bug
70 
71         monitor.registerCallback(mInfoCallback);
72         mHandler = new Handler(Looper.myLooper());
73 
74         mDefaultColor = getCurrentTextColor();
75         update();
76     }
77 
78     @Override
setNextMessageColor(int color)79     public void setNextMessageColor(int color) {
80         mNextMessageColor = color;
81     }
82 
83     @Override
setMessage(CharSequence msg)84     public void setMessage(CharSequence msg) {
85         if (!TextUtils.isEmpty(msg)) {
86             securityMessageChanged(msg);
87         } else {
88             clearMessage();
89         }
90     }
91 
92     @Override
setMessage(int resId)93     public void setMessage(int resId) {
94         CharSequence message = null;
95         if (resId != 0) {
96             message = getContext().getResources().getText(resId);
97         }
98         setMessage(message);
99     }
100 
101     @Override
formatMessage(int resId, Object... formatArgs)102     public void formatMessage(int resId, Object... formatArgs) {
103         CharSequence message = null;
104         if (resId != 0) {
105             message = getContext().getString(resId, formatArgs);
106         }
107         setMessage(message);
108     }
109 
findSecurityMessageDisplay(View v)110     public static SecurityMessageDisplay findSecurityMessageDisplay(View v) {
111         KeyguardMessageArea messageArea = (KeyguardMessageArea) v.findViewById(
112                 R.id.keyguard_message_area);
113         if (messageArea == null) {
114             throw new RuntimeException("Can't find keyguard_message_area in " + v.getClass());
115         }
116         return messageArea;
117     }
118 
119     @Override
onFinishInflate()120     protected void onFinishInflate() {
121         boolean shouldMarquee = KeyguardUpdateMonitor.getInstance(mContext).isDeviceInteractive();
122         setSelected(shouldMarquee); // This is required to ensure marquee works
123     }
124 
securityMessageChanged(CharSequence message)125     private void securityMessageChanged(CharSequence message) {
126         mMessage = message;
127         update();
128         mHandler.removeCallbacksAndMessages(ANNOUNCE_TOKEN);
129         mHandler.postAtTime(new AnnounceRunnable(this, getText()), ANNOUNCE_TOKEN,
130                 (SystemClock.uptimeMillis() + ANNOUNCEMENT_DELAY));
131     }
132 
clearMessage()133     private void clearMessage() {
134         mMessage = null;
135         update();
136     }
137 
update()138     private void update() {
139         CharSequence status = mMessage;
140         setVisibility(TextUtils.isEmpty(status) ? INVISIBLE : VISIBLE);
141         setText(status);
142         int color = mDefaultColor;
143         if (mNextMessageColor != DEFAULT_COLOR) {
144             color = mNextMessageColor;
145             mNextMessageColor = DEFAULT_COLOR;
146         }
147         setTextColor(color);
148     }
149 
150 
151     /**
152      * Runnable used to delay accessibility announcements.
153      */
154     private static class AnnounceRunnable implements Runnable {
155         private final WeakReference<View> mHost;
156         private final CharSequence mTextToAnnounce;
157 
AnnounceRunnable(View host, CharSequence textToAnnounce)158         AnnounceRunnable(View host, CharSequence textToAnnounce) {
159             mHost = new WeakReference<View>(host);
160             mTextToAnnounce = textToAnnounce;
161         }
162 
163         @Override
run()164         public void run() {
165             final View host = mHost.get();
166             if (host != null) {
167                 host.announceForAccessibility(mTextToAnnounce);
168             }
169         }
170     }
171 }
172