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