blob: 689d161c2ee86885219f7803e900e0950185aeb3 [file] [log] [blame]
Evan Lairde1d13c92018-03-20 16:58:01 -04001/*
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
17package com.android.systemui.statusbar;
18
Beverly1be62f42018-12-19 17:17:48 -050019import static com.android.systemui.plugins.DarkIconDispatcher.getTint;
20import static com.android.systemui.plugins.DarkIconDispatcher.isInArea;
Evan Laird97ae20c2018-05-10 13:13:27 -040021import static com.android.systemui.statusbar.StatusBarIconView.STATE_DOT;
22import static com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN;
23import static com.android.systemui.statusbar.StatusBarIconView.STATE_ICON;
Evan Lairde1d13c92018-03-20 16:58:01 -040024
25import android.content.Context;
26import android.content.res.ColorStateList;
27import android.graphics.Color;
28import android.graphics.Rect;
29import android.util.AttributeSet;
Evan Laird97ae20c2018-05-10 13:13:27 -040030import android.view.Gravity;
Evan Lairde1d13c92018-03-20 16:58:01 -040031import android.view.LayoutInflater;
32import android.view.View;
Evan Laird97ae20c2018-05-10 13:13:27 -040033import android.widget.FrameLayout;
Evan Lairde1d13c92018-03-20 16:58:01 -040034import android.widget.ImageView;
Evan Laird97ae20c2018-05-10 13:13:27 -040035import android.widget.LinearLayout;
Gus Prevasab336792018-11-14 13:52:20 -050036
Evan Lairde1d13c92018-03-20 16:58:01 -040037import com.android.internal.annotations.VisibleForTesting;
Evan Lairde1d13c92018-03-20 16:58:01 -040038import com.android.settingslib.graph.SignalDrawable;
Fabian Kozynskif86df992019-04-22 14:23:47 -040039import com.android.systemui.DualToneHandler;
Evan Lairde1d13c92018-03-20 16:58:01 -040040import com.android.systemui.R;
Beverly1be62f42018-12-19 17:17:48 -050041import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
Evan Lairde1d13c92018-03-20 16:58:01 -040042import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
Evan Lairde1d13c92018-03-20 16:58:01 -040043
Evan Laird97ae20c2018-05-10 13:13:27 -040044public class StatusBarMobileView extends FrameLayout implements DarkReceiver,
Evan Lairde1d13c92018-03-20 16:58:01 -040045 StatusIconDisplayable {
46 private static final String TAG = "StatusBarMobileView";
47
Evan Laird97ae20c2018-05-10 13:13:27 -040048 /// Used to show etc dots
49 private StatusBarIconView mDotView;
50 /// The main icon view
51 private LinearLayout mMobileGroup;
Evan Lairde1d13c92018-03-20 16:58:01 -040052 private String mSlot;
53 private MobileIconState mState;
54 private SignalDrawable mMobileDrawable;
55 private View mInoutContainer;
56 private ImageView mIn;
57 private ImageView mOut;
58 private ImageView mMobile, mMobileType, mMobileRoaming;
59 private View mMobileRoamingSpace;
Evan Laird97ae20c2018-05-10 13:13:27 -040060 private int mVisibleState = -1;
Fabian Kozynskif86df992019-04-22 14:23:47 -040061 private DualToneHandler mDualToneHandler;
Evan Lairde1d13c92018-03-20 16:58:01 -040062
Evan Laird97ae20c2018-05-10 13:13:27 -040063 public static StatusBarMobileView fromContext(Context context, String slot) {
Evan Lairde1d13c92018-03-20 16:58:01 -040064 LayoutInflater inflater = LayoutInflater.from(context);
Evan Laird97ae20c2018-05-10 13:13:27 -040065 StatusBarMobileView v = (StatusBarMobileView)
Evan Lairde1d13c92018-03-20 16:58:01 -040066 inflater.inflate(R.layout.status_bar_mobile_signal_group, null);
Evan Laird97ae20c2018-05-10 13:13:27 -040067
68 v.setSlot(slot);
69 v.init();
70 v.setVisibleState(STATE_ICON);
71 return v;
Evan Lairde1d13c92018-03-20 16:58:01 -040072 }
73
74 public StatusBarMobileView(Context context) {
75 super(context);
76 }
77
78 public StatusBarMobileView(Context context, AttributeSet attrs) {
79 super(context, attrs);
80 }
81
82 public StatusBarMobileView(Context context, AttributeSet attrs, int defStyleAttr) {
83 super(context, attrs, defStyleAttr);
84 }
85
86 public StatusBarMobileView(Context context, AttributeSet attrs, int defStyleAttr,
87 int defStyleRes) {
88 super(context, attrs, defStyleAttr, defStyleRes);
89 }
90
Evan Lairdc1397272018-05-21 20:12:34 -040091 @Override
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
Evan Lairde1d13c92018-03-20 16:58:01 -0400102 private void init() {
Fabian Kozynskif86df992019-04-22 14:23:47 -0400103 mDualToneHandler = new DualToneHandler(getContext());
Evan Laird97ae20c2018-05-10 13:13:27 -0400104 mMobileGroup = findViewById(R.id.mobile_group);
Evan Lairde1d13c92018-03-20 16:58:01 -0400105 mMobile = findViewById(R.id.mobile_signal);
106 mMobileType = findViewById(R.id.mobile_type);
107 mMobileRoaming = findViewById(R.id.mobile_roaming);
108 mMobileRoamingSpace = findViewById(R.id.mobile_roaming_space);
109 mIn = findViewById(R.id.mobile_in);
110 mOut = findViewById(R.id.mobile_out);
111 mInoutContainer = findViewById(R.id.inout_container);
112
113 mMobileDrawable = new SignalDrawable(getContext());
114 mMobile.setImageDrawable(mMobileDrawable);
Evan Laird97ae20c2018-05-10 13:13:27 -0400115
116 initDotView();
117 }
118
119 private void initDotView() {
120 mDotView = new StatusBarIconView(mContext, mSlot, null);
121 mDotView.setVisibleState(STATE_DOT);
122
123 int width = mContext.getResources().getDimensionPixelSize(R.dimen.status_bar_icon_size);
124 LayoutParams lp = new LayoutParams(width, width);
125 lp.gravity = Gravity.CENTER_VERTICAL | Gravity.START;
126 addView(mDotView, lp);
Evan Lairde1d13c92018-03-20 16:58:01 -0400127 }
128
129 public void applyMobileState(MobileIconState state) {
Evan Lairdf303d952018-06-21 14:07:10 -0400130 boolean requestLayout = false;
Evan Lairde1d13c92018-03-20 16:58:01 -0400131 if (state == null) {
Evan Lairdf303d952018-06-21 14:07:10 -0400132 requestLayout = getVisibility() != View.GONE;
Evan Lairde1d13c92018-03-20 16:58:01 -0400133 setVisibility(View.GONE);
134 mState = null;
Evan Lairdf303d952018-06-21 14:07:10 -0400135 } else if (mState == null) {
136 requestLayout = true;
Evan Laird56fb9f82018-04-24 21:11:15 -0400137 mState = state.copy();
Evan Lairde1d13c92018-03-20 16:58:01 -0400138 initViewState();
Evan Lairdf303d952018-06-21 14:07:10 -0400139 } else if (!mState.equals(state)) {
140 requestLayout = updateState(state.copy());
Evan Lairde1d13c92018-03-20 16:58:01 -0400141 }
142
Evan Lairdf303d952018-06-21 14:07:10 -0400143 if (requestLayout) {
144 requestLayout();
Evan Lairde1d13c92018-03-20 16:58:01 -0400145 }
146 }
147
148 private void initViewState() {
149 setContentDescription(mState.contentDescription);
150 if (!mState.visible) {
Evan Laird97ae20c2018-05-10 13:13:27 -0400151 mMobileGroup.setVisibility(View.GONE);
Evan Lairde1d13c92018-03-20 16:58:01 -0400152 } else {
Evan Laird97ae20c2018-05-10 13:13:27 -0400153 mMobileGroup.setVisibility(View.VISIBLE);
Evan Lairde1d13c92018-03-20 16:58:01 -0400154 }
155 mMobileDrawable.setLevel(mState.strengthId);
156 if (mState.typeId > 0) {
157 mMobileType.setContentDescription(mState.typeContentDescription);
158 mMobileType.setImageResource(mState.typeId);
159 mMobileType.setVisibility(View.VISIBLE);
160 } else {
161 mMobileType.setVisibility(View.GONE);
162 }
163
164 mMobileRoaming.setVisibility(mState.roaming ? View.VISIBLE : View.GONE);
165 mMobileRoamingSpace.setVisibility(mState.roaming ? View.VISIBLE : View.GONE);
166 mIn.setVisibility(mState.activityIn ? View.VISIBLE : View.GONE);
Evan Lairdf303d952018-06-21 14:07:10 -0400167 mOut.setVisibility(mState.activityOut ? View.VISIBLE : View.GONE);
Evan Lairde1d13c92018-03-20 16:58:01 -0400168 mInoutContainer.setVisibility((mState.activityIn || mState.activityOut)
169 ? View.VISIBLE : View.GONE);
170 }
171
Evan Lairdf303d952018-06-21 14:07:10 -0400172 private boolean updateState(MobileIconState state) {
173 boolean needsLayout = false;
174
Evan Lairde1d13c92018-03-20 16:58:01 -0400175 setContentDescription(state.contentDescription);
176 if (mState.visible != state.visible) {
Evan Laird97ae20c2018-05-10 13:13:27 -0400177 mMobileGroup.setVisibility(state.visible ? View.VISIBLE : View.GONE);
Evan Lairdf303d952018-06-21 14:07:10 -0400178 needsLayout = true;
Evan Lairde1d13c92018-03-20 16:58:01 -0400179 }
180 if (mState.strengthId != state.strengthId) {
181 mMobileDrawable.setLevel(state.strengthId);
182 }
Evan Laird6dedbe62018-04-05 16:22:36 -0400183 if (mState.typeId != state.typeId) {
Evan Lairdf303d952018-06-21 14:07:10 -0400184 needsLayout |= state.typeId == 0 || mState.typeId == 0;
Evan Laird6dedbe62018-04-05 16:22:36 -0400185 if (state.typeId != 0) {
186 mMobileType.setContentDescription(state.typeContentDescription);
187 mMobileType.setImageResource(state.typeId);
188 mMobileType.setVisibility(View.VISIBLE);
189 } else {
190 mMobileType.setVisibility(View.GONE);
191 }
Evan Lairde1d13c92018-03-20 16:58:01 -0400192 }
193
194 mMobileRoaming.setVisibility(state.roaming ? View.VISIBLE : View.GONE);
195 mMobileRoamingSpace.setVisibility(state.roaming ? View.VISIBLE : View.GONE);
196 mIn.setVisibility(state.activityIn ? View.VISIBLE : View.GONE);
Evan Lairdf303d952018-06-21 14:07:10 -0400197 mOut.setVisibility(state.activityOut ? View.VISIBLE : View.GONE);
Evan Lairde1d13c92018-03-20 16:58:01 -0400198 mInoutContainer.setVisibility((state.activityIn || state.activityOut)
199 ? View.VISIBLE : View.GONE);
200
Evan Lairdf303d952018-06-21 14:07:10 -0400201 needsLayout |= state.roaming != mState.roaming
202 || state.activityIn != mState.activityIn
203 || state.activityOut != mState.activityOut;
204
Evan Lairde1d13c92018-03-20 16:58:01 -0400205 mState = state;
Evan Lairdf303d952018-06-21 14:07:10 -0400206 return needsLayout;
Evan Lairde1d13c92018-03-20 16:58:01 -0400207 }
208
209 @Override
210 public void onDarkChanged(Rect area, float darkIntensity, int tint) {
Evan Lairddbeefe32018-04-03 16:52:41 -0400211 if (!isInArea(area, this)) {
212 return;
213 }
Amin Shaikh0ad7e512019-04-29 07:36:34 -0400214 mMobileDrawable.setTintList(
Fabian Kozynski8957ede2019-05-22 12:16:10 -0400215 ColorStateList.valueOf(mDualToneHandler.getSingleColor(darkIntensity)));
Evan Lairde1d13c92018-03-20 16:58:01 -0400216 ColorStateList color = ColorStateList.valueOf(getTint(area, this, tint));
217 mIn.setImageTintList(color);
218 mOut.setImageTintList(color);
219 mMobileType.setImageTintList(color);
220 mMobileRoaming.setImageTintList(color);
Evan Laird97ae20c2018-05-10 13:13:27 -0400221 mDotView.setDecorColor(tint);
222 mDotView.setIconColor(tint, false);
Evan Lairde1d13c92018-03-20 16:58:01 -0400223 }
224
225 @Override
226 public String getSlot() {
227 return mSlot;
228 }
229
230 public void setSlot(String slot) {
231 mSlot = slot;
232 }
233
234 @Override
235 public void setStaticDrawableColor(int color) {
236 ColorStateList list = ColorStateList.valueOf(color);
237 float intensity = color == Color.WHITE ? 0 : 1;
Fabian Kozynskif86df992019-04-22 14:23:47 -0400238 // We want the ability to change the theme from the one set by SignalDrawable in certain
239 // surfaces. In this way, we can pass a theme to the view.
Amin Shaikh0ad7e512019-04-29 07:36:34 -0400240 mMobileDrawable.setTintList(
Fabian Kozynski8957ede2019-05-22 12:16:10 -0400241 ColorStateList.valueOf(mDualToneHandler.getSingleColor(intensity)));
Evan Lairde1d13c92018-03-20 16:58:01 -0400242 mIn.setImageTintList(list);
243 mOut.setImageTintList(list);
244 mMobileType.setImageTintList(list);
245 mMobileRoaming.setImageTintList(list);
Evan Laird97ae20c2018-05-10 13:13:27 -0400246 mDotView.setDecorColor(color);
Evan Lairde1d13c92018-03-20 16:58:01 -0400247 }
248
249 @Override
Evan Laird20b87bf2018-04-12 09:54:11 -0400250 public void setDecorColor(int color) {
Evan Laird97ae20c2018-05-10 13:13:27 -0400251 mDotView.setDecorColor(color);
Evan Laird20b87bf2018-04-12 09:54:11 -0400252 }
253
254 @Override
Evan Lairde1d13c92018-03-20 16:58:01 -0400255 public boolean isIconVisible() {
256 return mState.visible;
257 }
258
Evan Laird20b87bf2018-04-12 09:54:11 -0400259 @Override
Evan Laird620ea2c2018-06-21 11:18:19 -0400260 public void setVisibleState(int state, boolean animate) {
Evan Laird97ae20c2018-05-10 13:13:27 -0400261 if (state == mVisibleState) {
262 return;
263 }
264
265 mVisibleState = state;
266 switch (state) {
267 case STATE_ICON:
268 mMobileGroup.setVisibility(View.VISIBLE);
269 mDotView.setVisibility(View.GONE);
270 break;
271 case STATE_DOT:
272 mMobileGroup.setVisibility(View.INVISIBLE);
273 mDotView.setVisibility(View.VISIBLE);
274 break;
275 case STATE_HIDDEN:
276 default:
Evan Laird78047782018-06-04 17:54:42 -0400277 mMobileGroup.setVisibility(View.INVISIBLE);
278 mDotView.setVisibility(View.INVISIBLE);
Evan Laird97ae20c2018-05-10 13:13:27 -0400279 break;
280 }
Evan Laird20b87bf2018-04-12 09:54:11 -0400281 }
282
Evan Laird150701d42018-05-04 16:14:00 -0400283 @Override
284 public int getVisibleState() {
Evan Laird97ae20c2018-05-10 13:13:27 -0400285 return mVisibleState;
Evan Laird150701d42018-05-04 16:14:00 -0400286 }
287
Evan Lairde1d13c92018-03-20 16:58:01 -0400288 @VisibleForTesting
289 public MobileIconState getState() {
290 return mState;
291 }
292
293 @Override
294 public String toString() {
295 return "StatusBarMobileView(slot=" + mSlot + " state=" + mState + ")";
296 }
297}