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 static com.android.systemui.statusbar.StatusBarIconView.STATE_DOT;
20 import static com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN;
21 import static com.android.systemui.statusbar.StatusBarIconView.STATE_ICON;
22 import static com.android.systemui.statusbar.policy.DarkIconDispatcher.getTint;
23 import static com.android.systemui.statusbar.policy.DarkIconDispatcher.isInArea;
24 
25 import android.content.Context;
26 import android.content.res.ColorStateList;
27 import android.graphics.Color;
28 import android.graphics.Rect;
29 import android.util.AttributeSet;
30 import android.util.Log;
31 import android.view.Gravity;
32 import android.view.LayoutInflater;
33 import android.view.View;
34 import android.widget.FrameLayout;
35 import android.widget.ImageView;
36 
37 import android.widget.LinearLayout;
38 import com.android.internal.annotations.VisibleForTesting;
39 import com.android.keyguard.AlphaOptimizedLinearLayout;
40 import com.android.settingslib.graph.SignalDrawable;
41 import com.android.systemui.R;
42 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
43 import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
44 
45 public class StatusBarMobileView extends FrameLayout implements DarkReceiver,
46         StatusIconDisplayable {
47     private static final String TAG = "StatusBarMobileView";
48 
49     /// Used to show etc dots
50     private StatusBarIconView mDotView;
51     /// The main icon view
52     private LinearLayout mMobileGroup;
53     private String mSlot;
54     private MobileIconState mState;
55     private SignalDrawable mMobileDrawable;
56     private View mInoutContainer;
57     private ImageView mIn;
58     private ImageView mOut;
59     private ImageView mMobile, mMobileType, mMobileRoaming;
60     private View mMobileRoamingSpace;
61     private int mVisibleState = -1;
62 
fromContext(Context context, String slot)63     public static StatusBarMobileView fromContext(Context context, String slot) {
64         LayoutInflater inflater = LayoutInflater.from(context);
65         StatusBarMobileView v = (StatusBarMobileView)
66                 inflater.inflate(R.layout.status_bar_mobile_signal_group, null);
67 
68         v.setSlot(slot);
69         v.init();
70         v.setVisibleState(STATE_ICON);
71         return v;
72     }
73 
StatusBarMobileView(Context context)74     public StatusBarMobileView(Context context) {
75         super(context);
76     }
77 
StatusBarMobileView(Context context, AttributeSet attrs)78     public StatusBarMobileView(Context context, AttributeSet attrs) {
79         super(context, attrs);
80     }
81 
StatusBarMobileView(Context context, AttributeSet attrs, int defStyleAttr)82     public StatusBarMobileView(Context context, AttributeSet attrs, int defStyleAttr) {
83         super(context, attrs, defStyleAttr);
84     }
85 
StatusBarMobileView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)86     public StatusBarMobileView(Context context, AttributeSet attrs, int defStyleAttr,
87             int defStyleRes) {
88         super(context, attrs, defStyleAttr, defStyleRes);
89     }
90 
91     @Override
getDrawingRect(Rect outRect)92     public void getDrawingRect(Rect outRect) {
93         super.getDrawingRect(outRect);
94         float translationX = getTranslationX();
95         float translationY = getTranslationY();
96         outRect.left += translationX;
97         outRect.right += translationX;
98         outRect.top += translationY;
99         outRect.bottom += translationY;
100     }
101 
init()102     private void init() {
103         mMobileGroup = findViewById(R.id.mobile_group);
104         mMobile = findViewById(R.id.mobile_signal);
105         mMobileType = findViewById(R.id.mobile_type);
106         mMobileRoaming = findViewById(R.id.mobile_roaming);
107         mMobileRoamingSpace = findViewById(R.id.mobile_roaming_space);
108         mIn = findViewById(R.id.mobile_in);
109         mOut = findViewById(R.id.mobile_out);
110         mInoutContainer = findViewById(R.id.inout_container);
111 
112         mMobileDrawable = new SignalDrawable(getContext());
113         mMobile.setImageDrawable(mMobileDrawable);
114 
115         initDotView();
116     }
117 
initDotView()118     private void initDotView() {
119         mDotView = new StatusBarIconView(mContext, mSlot, null);
120         mDotView.setVisibleState(STATE_DOT);
121 
122         int width = mContext.getResources().getDimensionPixelSize(R.dimen.status_bar_icon_size);
123         LayoutParams lp = new LayoutParams(width, width);
124         lp.gravity = Gravity.CENTER_VERTICAL | Gravity.START;
125         addView(mDotView, lp);
126     }
127 
applyMobileState(MobileIconState state)128     public void applyMobileState(MobileIconState state) {
129         if (state == null) {
130             setVisibility(View.GONE);
131             mState = null;
132             return;
133         }
134 
135         if (mState == null) {
136             mState = state.copy();
137             initViewState();
138             return;
139         }
140 
141         if (!mState.equals(state)) {
142             updateState(state.copy());
143         }
144     }
145 
initViewState()146     private void initViewState() {
147         setContentDescription(mState.contentDescription);
148         if (!mState.visible) {
149             mMobileGroup.setVisibility(View.GONE);
150         } else {
151             mMobileGroup.setVisibility(View.VISIBLE);
152         }
153         mMobileDrawable.setLevel(mState.strengthId);
154         if (mState.typeId > 0) {
155             mMobileType.setContentDescription(mState.typeContentDescription);
156             mMobileType.setImageResource(mState.typeId);
157             mMobileType.setVisibility(View.VISIBLE);
158         } else {
159             mMobileType.setVisibility(View.GONE);
160         }
161 
162         mMobileRoaming.setVisibility(mState.roaming ? View.VISIBLE : View.GONE);
163         mMobileRoamingSpace.setVisibility(mState.roaming ? View.VISIBLE : View.GONE);
164         mIn.setVisibility(mState.activityIn ? View.VISIBLE : View.GONE);
165         mOut.setVisibility(mState.activityIn ? View.VISIBLE : View.GONE);
166         mInoutContainer.setVisibility((mState.activityIn || mState.activityOut)
167                 ? View.VISIBLE : View.GONE);
168     }
169 
updateState(MobileIconState state)170     private void updateState(MobileIconState state) {
171         setContentDescription(state.contentDescription);
172         if (mState.visible != state.visible) {
173             mMobileGroup.setVisibility(state.visible ? View.VISIBLE : View.GONE);
174         }
175         if (mState.strengthId != state.strengthId) {
176             mMobileDrawable.setLevel(state.strengthId);
177         }
178         if (mState.typeId != state.typeId) {
179             if (state.typeId != 0) {
180                 mMobileType.setContentDescription(state.typeContentDescription);
181                 mMobileType.setImageResource(state.typeId);
182                 mMobileType.setVisibility(View.VISIBLE);
183             } else {
184                 mMobileType.setVisibility(View.GONE);
185             }
186         }
187 
188         mMobileRoaming.setVisibility(state.roaming ? View.VISIBLE : View.GONE);
189         mMobileRoamingSpace.setVisibility(state.roaming ? View.VISIBLE : View.GONE);
190         mIn.setVisibility(state.activityIn ? View.VISIBLE : View.GONE);
191         mOut.setVisibility(state.activityIn ? View.VISIBLE : View.GONE);
192         mInoutContainer.setVisibility((state.activityIn || state.activityOut)
193                 ? View.VISIBLE : View.GONE);
194 
195         mState = state;
196     }
197 
198     @Override
onDarkChanged(Rect area, float darkIntensity, int tint)199     public void onDarkChanged(Rect area, float darkIntensity, int tint) {
200         if (!isInArea(area, this)) {
201             return;
202         }
203         mMobileDrawable.setDarkIntensity(darkIntensity);
204         ColorStateList color = ColorStateList.valueOf(getTint(area, this, tint));
205         mIn.setImageTintList(color);
206         mOut.setImageTintList(color);
207         mMobileType.setImageTintList(color);
208         mMobileRoaming.setImageTintList(color);
209         mDotView.setDecorColor(tint);
210         mDotView.setIconColor(tint, false);
211     }
212 
213     @Override
getSlot()214     public String getSlot() {
215         return mSlot;
216     }
217 
setSlot(String slot)218     public void setSlot(String slot) {
219         mSlot = slot;
220     }
221 
222     @Override
setStaticDrawableColor(int color)223     public void setStaticDrawableColor(int color) {
224         ColorStateList list = ColorStateList.valueOf(color);
225         float intensity = color == Color.WHITE ? 0 : 1;
226         mMobileDrawable.setDarkIntensity(intensity);
227 
228         mIn.setImageTintList(list);
229         mOut.setImageTintList(list);
230         mMobileType.setImageTintList(list);
231         mMobileRoaming.setImageTintList(list);
232         mDotView.setDecorColor(color);
233     }
234 
235     @Override
setDecorColor(int color)236     public void setDecorColor(int color) {
237         mDotView.setDecorColor(color);
238     }
239 
240     @Override
isIconVisible()241     public boolean isIconVisible() {
242         return mState.visible;
243     }
244 
245     @Override
setVisibleState(int state)246     public void setVisibleState(int state) {
247         if (state == mVisibleState) {
248             return;
249         }
250 
251         mVisibleState = state;
252         switch (state) {
253             case STATE_ICON:
254                 mMobileGroup.setVisibility(View.VISIBLE);
255                 mDotView.setVisibility(View.GONE);
256                 break;
257             case STATE_DOT:
258                 mMobileGroup.setVisibility(View.INVISIBLE);
259                 mDotView.setVisibility(View.VISIBLE);
260                 break;
261             case STATE_HIDDEN:
262             default:
263                 mMobileGroup.setVisibility(View.INVISIBLE);
264                 mDotView.setVisibility(View.INVISIBLE);
265                 break;
266         }
267     }
268 
269     @Override
getVisibleState()270     public int getVisibleState() {
271         return mVisibleState;
272     }
273 
274     @VisibleForTesting
getState()275     public MobileIconState getState() {
276         return mState;
277     }
278 
279     @Override
toString()280     public String toString() {
281         return "StatusBarMobileView(slot=" + mSlot + " state=" + mState + ")";
282     }
283 }
284