1 /*
2  * Copyright (C) 2018 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.systemui.statusbar;
18 
19 import android.content.Context;
20 import android.graphics.Rect;
21 import android.os.Bundle;
22 import android.os.Parcelable;
23 import android.util.AttributeSet;
24 import android.view.View;
25 import android.widget.TextView;
26 
27 import com.android.internal.annotations.VisibleForTesting;
28 import com.android.keyguard.AlphaOptimizedLinearLayout;
29 import com.android.systemui.R;
30 import com.android.systemui.plugins.DarkIconDispatcher;
31 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
32 import com.android.systemui.statusbar.notification.collection.NotificationEntry.OnSensitivityChangedListener;
33 
34 import java.util.ArrayList;
35 
36 
37 /**
38  * The view in the statusBar that contains part of the heads-up information
39  */
40 public class HeadsUpStatusBarView extends AlphaOptimizedLinearLayout {
41     private static final String HEADS_UP_STATUS_BAR_VIEW_SUPER_PARCELABLE =
42             "heads_up_status_bar_view_super_parcelable";
43     private static final String VISIBILITY = "visibility";
44     private static final String ALPHA = "alpha";
45     private final Rect mLayoutedIconRect = new Rect();
46     private final int[] mTmpPosition = new int[2];
47     private final Rect mIconDrawingRect = new Rect();
48     private View mIconPlaceholder;
49     private TextView mTextView;
50     private NotificationEntry mShowingEntry;
51     private Runnable mOnDrawingRectChangedListener;
52 
HeadsUpStatusBarView(Context context)53     public HeadsUpStatusBarView(Context context) {
54         this(context, null);
55     }
56 
HeadsUpStatusBarView(Context context, AttributeSet attrs)57     public HeadsUpStatusBarView(Context context, AttributeSet attrs) {
58         this(context, attrs, 0);
59     }
60 
HeadsUpStatusBarView(Context context, AttributeSet attrs, int defStyleAttr)61     public HeadsUpStatusBarView(Context context, AttributeSet attrs, int defStyleAttr) {
62         this(context, attrs, defStyleAttr, 0);
63     }
64 
HeadsUpStatusBarView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)65     public HeadsUpStatusBarView(Context context, AttributeSet attrs, int defStyleAttr,
66             int defStyleRes) {
67         super(context, attrs, defStyleAttr, defStyleRes);
68     }
69 
70     @Override
onSaveInstanceState()71     public Bundle onSaveInstanceState() {
72         Bundle bundle = new Bundle();
73         bundle.putParcelable(HEADS_UP_STATUS_BAR_VIEW_SUPER_PARCELABLE,
74                 super.onSaveInstanceState());
75         bundle.putInt(VISIBILITY, getVisibility());
76         bundle.putFloat(ALPHA, getAlpha());
77 
78         return bundle;
79     }
80 
81     @Override
onRestoreInstanceState(Parcelable state)82     public void onRestoreInstanceState(Parcelable state) {
83         if (!(state instanceof Bundle)) {
84             super.onRestoreInstanceState(state);
85             return;
86         }
87 
88         Bundle bundle = (Bundle) state;
89         Parcelable superState = bundle.getParcelable(HEADS_UP_STATUS_BAR_VIEW_SUPER_PARCELABLE);
90         super.onRestoreInstanceState(superState);
91         if (bundle.containsKey(VISIBILITY)) {
92             setVisibility(bundle.getInt(VISIBILITY));
93         }
94         if (bundle.containsKey(ALPHA)) {
95             setAlpha(bundle.getFloat(ALPHA));
96         }
97     }
98 
99     @VisibleForTesting
HeadsUpStatusBarView(Context context, View iconPlaceholder, TextView textView)100     public HeadsUpStatusBarView(Context context, View iconPlaceholder, TextView textView) {
101         this(context);
102         mIconPlaceholder = iconPlaceholder;
103         mTextView = textView;
104     }
105 
106     @Override
onFinishInflate()107     protected void onFinishInflate() {
108         super.onFinishInflate();
109         mIconPlaceholder = findViewById(R.id.icon_placeholder);
110         mTextView = findViewById(R.id.text);
111     }
112 
setEntry(NotificationEntry entry)113     public void setEntry(NotificationEntry entry) {
114         if (mShowingEntry != null) {
115             mShowingEntry.removeOnSensitivityChangedListener(mOnSensitivityChangedListener);
116         }
117         mShowingEntry = entry;
118 
119         if (mShowingEntry != null) {
120             CharSequence text = entry.headsUpStatusBarText;
121             if (entry.isSensitive()) {
122                 text = entry.headsUpStatusBarTextPublic;
123             }
124             mTextView.setText(text);
125             mShowingEntry.addOnSensitivityChangedListener(mOnSensitivityChangedListener);
126         }
127     }
128 
129     private final OnSensitivityChangedListener mOnSensitivityChangedListener = entry -> {
130         if (entry != mShowingEntry) {
131             throw new IllegalStateException("Got a sensitivity change for " + entry
132                     + " but mShowingEntry is " + mShowingEntry);
133         }
134         // Update the text
135         setEntry(entry);
136     };
137 
138     @Override
onLayout(boolean changed, int l, int t, int r, int b)139     protected void onLayout(boolean changed, int l, int t, int r, int b) {
140         super.onLayout(changed, l, t, r, b);
141         mIconPlaceholder.getLocationOnScreen(mTmpPosition);
142         int left = mTmpPosition[0];
143         int top = mTmpPosition[1];
144         int right = left + mIconPlaceholder.getWidth();
145         int bottom = top + mIconPlaceholder.getHeight();
146         mLayoutedIconRect.set(left, top, right, bottom);
147         updateDrawingRect();
148     }
149 
updateDrawingRect()150     private void updateDrawingRect() {
151         float oldLeft = mIconDrawingRect.left;
152         mIconDrawingRect.set(mLayoutedIconRect);
153         if (oldLeft != mIconDrawingRect.left && mOnDrawingRectChangedListener != null) {
154             mOnDrawingRectChangedListener.run();
155         }
156     }
157 
getShowingEntry()158     public NotificationEntry getShowingEntry() {
159         return mShowingEntry;
160     }
161 
getIconDrawingRect()162     public Rect getIconDrawingRect() {
163         return mIconDrawingRect;
164     }
165 
onDarkChanged(ArrayList<Rect> areas, float darkIntensity, int tint)166     public void onDarkChanged(ArrayList<Rect> areas, float darkIntensity, int tint) {
167         mTextView.setTextColor(DarkIconDispatcher.getTint(areas, this, tint));
168     }
169 
setOnDrawingRectChangedListener(Runnable onDrawingRectChangedListener)170     public void setOnDrawingRectChangedListener(Runnable onDrawingRectChangedListener) {
171         mOnDrawingRectChangedListener = onDrawingRectChangedListener;
172     }
173 }
174