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.content.res.TypedArray;
21 import android.text.TextUtils;
22 import android.util.AttributeSet;
23 import android.util.TypedValue;
24 import android.view.ViewGroup;
25 import android.widget.TextView;
26 
27 import androidx.annotation.Nullable;
28 
29 import com.android.internal.policy.SystemBarUtils;
30 import com.android.systemui.res.R;
31 
32 /***
33  * Manages a number of views inside of the given layout. See below for a list of widgets.
34  */
35 public abstract class KeyguardMessageArea extends TextView implements SecurityMessageDisplay {
36 
37     private CharSequence mMessage;
38     private boolean mIsVisible;
39     /**
40      * Container that wraps the KeyguardMessageArea - may be null if current view hierarchy doesn't
41      * contain {@link R.id.keyguard_message_area_container}.
42      */
43     @Nullable
44     private ViewGroup mContainer;
45     private int mTopMargin;
46     protected boolean mAnimate;
47     private final int mStyleResId;
48     private boolean mIsDisabled = false;
49 
KeyguardMessageArea(Context context, AttributeSet attrs)50     public KeyguardMessageArea(Context context, AttributeSet attrs) {
51         super(context, attrs);
52         setLayerType(LAYER_TYPE_HARDWARE, null); // work around nested unclipped SaveLayer bug
53         if (attrs != null) {
54             mStyleResId = attrs.getStyleAttribute();
55         } else {
56             // Set to default reference style if the component is used without setting "style" attr
57             mStyleResId = R.style.Keyguard_TextView;
58         }
59         onThemeChanged();
60     }
61 
62     @Override
onAttachedToWindow()63     protected void onAttachedToWindow() {
64         super.onAttachedToWindow();
65         mContainer = getRootView().findViewById(R.id.keyguard_message_area_container);
66     }
67 
onConfigChanged()68     void onConfigChanged() {
69         if (mContainer == null) {
70             return;
71         }
72         final int newTopMargin = SystemBarUtils.getStatusBarHeight(getContext());
73         if (mTopMargin == newTopMargin) {
74             return;
75         }
76         mTopMargin = newTopMargin;
77         ViewGroup.MarginLayoutParams lp =
78                 (ViewGroup.MarginLayoutParams) mContainer.getLayoutParams();
79         lp.topMargin = mTopMargin;
80         mContainer.setLayoutParams(lp);
81     }
82 
onThemeChanged()83     protected void onThemeChanged() {
84         update();
85     }
86 
reloadColor()87     protected void reloadColor() {
88         update();
89     }
90 
onDensityOrFontScaleChanged()91     void onDensityOrFontScaleChanged() {
92         TypedArray array = mContext.obtainStyledAttributes(getStyleResId(), new int[] {
93                 android.R.attr.textSize
94         });
95         setTextSize(TypedValue.COMPLEX_UNIT_PX, array.getDimensionPixelSize(0, 0));
96         array.recycle();
97     }
98 
getStyleResId()99     protected int getStyleResId() {
100         return mStyleResId;
101     }
102 
103     @Override
setMessage(CharSequence msg, boolean animate)104     public void setMessage(CharSequence msg, boolean animate) {
105         if (!TextUtils.isEmpty(msg)) {
106             securityMessageChanged(msg);
107         } else {
108             clearMessage();
109         }
110     }
111 
112     @Override
formatMessage(int resId, Object... formatArgs)113     public void formatMessage(int resId, Object... formatArgs) {
114         CharSequence message = null;
115         if (resId != 0) {
116             message = getContext().getString(resId, formatArgs);
117         }
118         setMessage(message, true);
119     }
120 
securityMessageChanged(CharSequence message)121     private void securityMessageChanged(CharSequence message) {
122         mMessage = message;
123         update();
124     }
125 
clearMessage()126     private void clearMessage() {
127         mMessage = null;
128         update();
129     }
130 
update()131     void update() {
132         if (mIsDisabled) {
133             setVisibility(GONE);
134             return;
135         }
136         CharSequence status = mMessage;
137         setVisibility(TextUtils.isEmpty(status) || (!mIsVisible) ? INVISIBLE : VISIBLE);
138         setText(status);
139         updateTextColor();
140     }
141 
142     /**
143      * Set whether the bouncer is fully showing
144      */
setIsVisible(boolean isVisible)145     public void setIsVisible(boolean isVisible) {
146         if (mIsVisible != isVisible) {
147             mIsVisible = isVisible;
148             update();
149         }
150     }
151 
152     /** Set the text color */
updateTextColor()153     protected abstract void updateTextColor();
154 
155     /**
156      * Mark this view with {@link android.view.View#GONE} visibility to remove this from the layout
157      * of the view. Any calls to {@link #setIsVisible(boolean)} after this will be a no-op.
158      */
disable()159     public void disable() {
160         mIsDisabled = true;
161         update();
162     }
163 
isDisabled()164     public boolean isDisabled() {
165         return mIsDisabled;
166     }
167 }
168