blob: 960e4cf47001e6c9bc76711c2523f2c34d66e41d [file] [log] [blame]
Christian Robertson2e347422011-08-11 14:01:04 -07001/*
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
17package com.android.systemui.statusbar;
18
Anthony Chen55e8e1e2016-01-08 10:31:46 -080019import android.annotation.DrawableRes;
Christian Robertson2e347422011-08-11 14:01:04 -070020import android.content.Context;
Jorim Jaggidd0107a2015-01-21 22:23:48 +010021import android.content.res.ColorStateList;
Anthony Chen55e8e1e2016-01-08 10:31:46 -080022import android.content.res.Resources;
Jorim Jaggidd0107a2015-01-21 22:23:48 +010023import android.graphics.Color;
Jorim Jaggi86905582016-02-09 21:36:09 -080024import android.graphics.Rect;
Andrew Flynna478d702015-04-14 23:33:45 -040025import android.graphics.drawable.Animatable;
Jorim Jaggi035a82d2016-02-29 08:42:25 +010026import android.graphics.drawable.AnimatedVectorDrawable;
Andrew Flynna478d702015-04-14 23:33:45 -040027import android.graphics.drawable.Drawable;
Jason Monkb5746272014-11-12 16:50:31 -050028import android.telephony.SubscriptionInfo;
Jason Monk5e745172015-06-02 19:14:44 -040029import android.util.ArraySet;
Christian Robertson2e347422011-08-11 14:01:04 -070030import android.util.AttributeSet;
John Spurlockcd686b52013-06-05 10:13:46 -040031import android.util.Log;
Anthony Chen55e8e1e2016-01-08 10:31:46 -080032import android.util.TypedValue;
Jason Monkb5746272014-11-12 16:50:31 -050033import android.view.LayoutInflater;
Christian Robertson2e347422011-08-11 14:01:04 -070034import android.view.View;
35import android.view.ViewGroup;
John Spurlock2f7dfa72012-05-16 20:20:59 -040036import android.view.accessibility.AccessibilityEvent;
Christian Robertson2e347422011-08-11 14:01:04 -070037import android.widget.ImageView;
38import android.widget.LinearLayout;
Christian Robertson2e347422011-08-11 14:01:04 -070039
Christian Robertson2e347422011-08-11 14:01:04 -070040import com.android.systemui.R;
Jason Monk3b230072015-05-29 11:11:29 -040041import com.android.systemui.statusbar.phone.StatusBarIconController;
Jason Monk07b75fe2015-05-14 16:47:03 -040042import com.android.systemui.statusbar.policy.NetworkController.IconState;
John Spurlockaf8d6c42014-05-07 17:49:08 -040043import com.android.systemui.statusbar.policy.NetworkControllerImpl;
Jason Monk3128f122014-09-03 13:18:57 -040044import com.android.systemui.statusbar.policy.SecurityController;
Jason Monk5e745172015-06-02 19:14:44 -040045import com.android.systemui.tuner.TunerService;
46import com.android.systemui.tuner.TunerService.Tunable;
Christian Robertson2e347422011-08-11 14:01:04 -070047
Jason Monkb5746272014-11-12 16:50:31 -050048import java.util.ArrayList;
49import java.util.List;
50
Daniel Sandler5ccff812011-09-13 15:17:58 -040051// Intimately tied to the design of res/layout/signal_cluster_view.xml
Christian Robertson2e347422011-08-11 14:01:04 -070052public class SignalClusterView
John Spurlock2f7dfa72012-05-16 20:20:59 -040053 extends LinearLayout
Jason Monk07b75fe2015-05-14 16:47:03 -040054 implements NetworkControllerImpl.SignalCallback,
Jason Monk5e745172015-06-02 19:14:44 -040055 SecurityController.SecurityControllerCallback, Tunable {
Christian Robertson2e347422011-08-11 14:01:04 -070056
Daniel Sandler28f89d42011-08-15 14:04:15 -040057 static final String TAG = "SignalClusterView";
John Spurlockb3eb8912014-07-30 11:03:03 -040058 static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
John Spurlock2f7dfa72012-05-16 20:20:59 -040059
Jason Monk3b230072015-05-29 11:11:29 -040060 private static final String SLOT_AIRPLANE = "airplane";
61 private static final String SLOT_MOBILE = "mobile";
62 private static final String SLOT_WIFI = "wifi";
63 private static final String SLOT_ETHERNET = "ethernet";
64
John Spurlockaf8d6c42014-05-07 17:49:08 -040065 NetworkControllerImpl mNC;
Jason Monk3128f122014-09-03 13:18:57 -040066 SecurityController mSC;
Christian Robertson2e347422011-08-11 14:01:04 -070067
Jason Monkb5746272014-11-12 16:50:31 -050068 private boolean mNoSimsVisible = false;
Jason Monk3128f122014-09-03 13:18:57 -040069 private boolean mVpnVisible = false;
Lorenzo Colittid46bb582015-04-27 20:32:01 +090070 private boolean mEthernetVisible = false;
71 private int mEthernetIconId = 0;
Jorim Jaggi06302c22015-05-20 17:05:23 -070072 private int mLastEthernetIconId = -1;
Daniel Sandler28f89d42011-08-15 14:04:15 -040073 private boolean mWifiVisible = false;
John Spurlockfcc901c2013-09-04 10:36:27 -040074 private int mWifiStrengthId = 0;
Jorim Jaggi06302c22015-05-20 17:05:23 -070075 private int mLastWifiStrengthId = -1;
Daniel Sandler5ccff812011-09-13 15:17:58 -040076 private boolean mIsAirplaneMode = false;
Andrew Flynn061d43c2012-05-04 10:57:58 -070077 private int mAirplaneIconId = 0;
Jorim Jaggi06302c22015-05-20 17:05:23 -070078 private int mLastAirplaneIconId = -1;
Jason Monk07b75fe2015-05-14 16:47:03 -040079 private String mAirplaneContentDescription;
Jason Monkb5746272014-11-12 16:50:31 -050080 private String mWifiDescription;
Lorenzo Colittid46bb582015-04-27 20:32:01 +090081 private String mEthernetDescription;
Jason Monkb5746272014-11-12 16:50:31 -050082 private ArrayList<PhoneState> mPhoneStates = new ArrayList<PhoneState>();
Jorim Jaggidd0107a2015-01-21 22:23:48 +010083 private int mIconTint = Color.WHITE;
Jorim Jaggi5443cc52015-03-20 14:39:24 -070084 private float mDarkIntensity;
Jorim Jaggi86905582016-02-09 21:36:09 -080085 private final Rect mTintArea = new Rect();
Daniel Sandler28f89d42011-08-15 14:04:15 -040086
Lorenzo Colittid46bb582015-04-27 20:32:01 +090087 ViewGroup mEthernetGroup, mWifiGroup;
Adrian Roos1b5eb972015-06-11 18:22:52 -070088 View mNoSimsCombo;
Lorenzo Colittid46bb582015-04-27 20:32:01 +090089 ImageView mVpn, mEthernet, mWifi, mAirplane, mNoSims, mEthernetDark, mWifiDark, mNoSimsDark;
Jorim Jaggi5172dc22014-09-02 14:59:06 +020090 View mWifiAirplaneSpacer;
Jorim Jaggic737b9b2014-09-08 23:57:20 +020091 View mWifiSignalSpacer;
Jason Monkb5746272014-11-12 16:50:31 -050092 LinearLayout mMobileSignalGroup;
Jorim Jaggic737b9b2014-09-08 23:57:20 +020093
Anthony Chene87032c2016-02-09 07:42:25 -080094 private final int mMobileSignalGroupEndPadding;
95 private final int mMobileDataIconStartPadding;
Anthony Chen55e8e1e2016-01-08 10:31:46 -080096 private final int mWideTypeIconStartPadding;
97 private final int mSecondaryTelephonyPadding;
98 private final int mEndPadding;
99 private final int mEndPaddingNothingVisible;
100 private final float mIconScaleFactor;
Christian Robertson2e347422011-08-11 14:01:04 -0700101
Jason Monk3b230072015-05-29 11:11:29 -0400102 private boolean mBlockAirplane;
103 private boolean mBlockMobile;
104 private boolean mBlockWifi;
105 private boolean mBlockEthernet;
106
Christian Robertson2e347422011-08-11 14:01:04 -0700107 public SignalClusterView(Context context) {
108 this(context, null);
109 }
110
111 public SignalClusterView(Context context, AttributeSet attrs) {
112 this(context, attrs, 0);
113 }
114
115 public SignalClusterView(Context context, AttributeSet attrs, int defStyle) {
116 super(context, attrs, defStyle);
Anthony Chen55e8e1e2016-01-08 10:31:46 -0800117
118 Resources res = getResources();
Anthony Chene87032c2016-02-09 07:42:25 -0800119 mMobileSignalGroupEndPadding =
120 res.getDimensionPixelSize(R.dimen.mobile_signal_group_end_padding);
121 mMobileDataIconStartPadding =
122 res.getDimensionPixelSize(R.dimen.mobile_data_icon_start_padding);
Anthony Chen55e8e1e2016-01-08 10:31:46 -0800123 mWideTypeIconStartPadding = res.getDimensionPixelSize(R.dimen.wide_type_icon_start_padding);
124 mSecondaryTelephonyPadding = res.getDimensionPixelSize(R.dimen.secondary_telephony_padding);
125 mEndPadding = res.getDimensionPixelSize(R.dimen.signal_cluster_battery_padding);
126 mEndPaddingNothingVisible = res.getDimensionPixelSize(
127 R.dimen.no_signal_cluster_battery_padding);
128
129 TypedValue typedValue = new TypedValue();
130 res.getValue(R.dimen.status_bar_icon_scale_factor, typedValue, true);
131 mIconScaleFactor = typedValue.getFloat();
Jason Monk3b230072015-05-29 11:11:29 -0400132 }
133
Jason Monk5e745172015-06-02 19:14:44 -0400134 @Override
135 public void onTuningChanged(String key, String newValue) {
136 if (!StatusBarIconController.ICON_BLACKLIST.equals(key)) {
137 return;
138 }
139 ArraySet<String> blockList = StatusBarIconController.getIconBlacklist(newValue);
Jason Monkf3d17152015-06-15 15:02:56 -0400140 boolean blockAirplane = blockList.contains(SLOT_AIRPLANE);
141 boolean blockMobile = blockList.contains(SLOT_MOBILE);
142 boolean blockWifi = blockList.contains(SLOT_WIFI);
143 boolean blockEthernet = blockList.contains(SLOT_ETHERNET);
Jason Monk5e745172015-06-02 19:14:44 -0400144
Jason Monkf3d17152015-06-15 15:02:56 -0400145 if (blockAirplane != mBlockAirplane || blockMobile != mBlockMobile
146 || blockEthernet != mBlockEthernet || blockWifi != mBlockWifi) {
147 mBlockAirplane = blockAirplane;
148 mBlockMobile = blockMobile;
149 mBlockEthernet = blockEthernet;
150 mBlockWifi = blockWifi;
151 // Re-register to get new callbacks.
152 mNC.removeSignalCallback(this);
153 mNC.addSignalCallback(this);
154 }
Christian Robertson2e347422011-08-11 14:01:04 -0700155 }
156
John Spurlockaf8d6c42014-05-07 17:49:08 -0400157 public void setNetworkController(NetworkControllerImpl nc) {
John Spurlockcd686b52013-06-05 10:13:46 -0400158 if (DEBUG) Log.d(TAG, "NetworkController=" + nc);
Christian Robertson2e347422011-08-11 14:01:04 -0700159 mNC = nc;
160 }
161
Jason Monk3128f122014-09-03 13:18:57 -0400162 public void setSecurityController(SecurityController sc) {
163 if (DEBUG) Log.d(TAG, "SecurityController=" + sc);
164 mSC = sc;
165 mSC.addCallback(this);
166 mVpnVisible = mSC.isVpnEnabled();
167 }
168
Christian Robertson2e347422011-08-11 14:01:04 -0700169 @Override
Jorim Jaggic737b9b2014-09-08 23:57:20 +0200170 protected void onFinishInflate() {
171 super.onFinishInflate();
Christian Robertson2e347422011-08-11 14:01:04 -0700172
Jason Monk3128f122014-09-03 13:18:57 -0400173 mVpn = (ImageView) findViewById(R.id.vpn);
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900174 mEthernetGroup = (ViewGroup) findViewById(R.id.ethernet_combo);
175 mEthernet = (ImageView) findViewById(R.id.ethernet);
176 mEthernetDark = (ImageView) findViewById(R.id.ethernet_dark);
Christian Robertson2e347422011-08-11 14:01:04 -0700177 mWifiGroup = (ViewGroup) findViewById(R.id.wifi_combo);
178 mWifi = (ImageView) findViewById(R.id.wifi_signal);
Jorim Jaggi5443cc52015-03-20 14:39:24 -0700179 mWifiDark = (ImageView) findViewById(R.id.wifi_signal_dark);
Andrew Flynn061d43c2012-05-04 10:57:58 -0700180 mAirplane = (ImageView) findViewById(R.id.airplane);
Jason Monkb5746272014-11-12 16:50:31 -0500181 mNoSims = (ImageView) findViewById(R.id.no_sims);
Jorim Jaggi5443cc52015-03-20 14:39:24 -0700182 mNoSimsDark = (ImageView) findViewById(R.id.no_sims_dark);
Adrian Roos1b5eb972015-06-11 18:22:52 -0700183 mNoSimsCombo = findViewById(R.id.no_sims_combo);
Jorim Jaggi5172dc22014-09-02 14:59:06 +0200184 mWifiAirplaneSpacer = findViewById(R.id.wifi_airplane_spacer);
Jorim Jaggic737b9b2014-09-08 23:57:20 +0200185 mWifiSignalSpacer = findViewById(R.id.wifi_signal_spacer);
Jason Monkb5746272014-11-12 16:50:31 -0500186 mMobileSignalGroup = (LinearLayout) findViewById(R.id.mobile_signal_group);
Anthony Chen55e8e1e2016-01-08 10:31:46 -0800187
188 maybeScaleVpnAndNoSimsIcons();
189 }
190
191 /**
192 * Extracts the icon off of the VPN and no sims views and maybe scale them by
193 * {@link #mIconScaleFactor}. Note that the other icons are not scaled here because they are
194 * dynamic. As such, they need to be scaled each time the icon changes in {@link #apply()}.
195 */
196 private void maybeScaleVpnAndNoSimsIcons() {
197 if (mIconScaleFactor == 1.f) {
198 return;
199 }
200
201 mVpn.setImageDrawable(new ScalingDrawableWrapper(mVpn.getDrawable(), mIconScaleFactor));
202
203 mNoSims.setImageDrawable(
204 new ScalingDrawableWrapper(mNoSims.getDrawable(), mIconScaleFactor));
205 mNoSimsDark.setImageDrawable(
206 new ScalingDrawableWrapper(mNoSimsDark.getDrawable(), mIconScaleFactor));
207 }
208
209 @Override
210 protected void onAttachedToWindow() {
211 super.onAttachedToWindow();
212
Jason Monkb5746272014-11-12 16:50:31 -0500213 for (PhoneState state : mPhoneStates) {
214 mMobileSignalGroup.addView(state.mMobileGroup);
215 }
Anthony Chene87032c2016-02-09 07:42:25 -0800216
217 int endPadding = mMobileSignalGroup.getChildCount() > 0 ? mMobileSignalGroupEndPadding : 0;
218 mMobileSignalGroup.setPaddingRelative(0, 0, endPadding, 0);
219
Jason Monk5e745172015-06-02 19:14:44 -0400220 TunerService.get(mContext).addTunable(this, StatusBarIconController.ICON_BLACKLIST);
Daniel Sandler28f89d42011-08-15 14:04:15 -0400221
222 apply();
Jorim Jaggidd0107a2015-01-21 22:23:48 +0100223 applyIconTint();
Christian Robertson2e347422011-08-11 14:01:04 -0700224 }
225
226 @Override
227 protected void onDetachedFromWindow() {
Jason Monkb5746272014-11-12 16:50:31 -0500228 mMobileSignalGroup.removeAllViews();
Jason Monk5e745172015-06-02 19:14:44 -0400229 TunerService.get(mContext).removeTunable(this);
Jason Monk46dbfb42016-02-25 14:59:20 -0500230 mSC.removeCallback(this);
231 mNC.removeSignalCallback(this);
Daniel Sandler28f89d42011-08-15 14:04:15 -0400232
Christian Robertson2e347422011-08-11 14:01:04 -0700233 super.onDetachedFromWindow();
234 }
235
Jason Monk3128f122014-09-03 13:18:57 -0400236 // From SecurityController.
237 @Override
238 public void onStateChanged() {
239 post(new Runnable() {
240 @Override
241 public void run() {
242 mVpnVisible = mSC.isVpnEnabled();
243 apply();
244 }
245 });
246 }
247
Andrew Flynn061d43c2012-05-04 10:57:58 -0700248 @Override
Jason Monk07b75fe2015-05-14 16:47:03 -0400249 public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
250 boolean activityIn, boolean activityOut, String description) {
Jason Monk3b230072015-05-29 11:11:29 -0400251 mWifiVisible = statusIcon.visible && !mBlockWifi;
Jason Monk07b75fe2015-05-14 16:47:03 -0400252 mWifiStrengthId = statusIcon.icon;
253 mWifiDescription = statusIcon.contentDescription;
Christian Robertson2e347422011-08-11 14:01:04 -0700254
Daniel Sandler28f89d42011-08-15 14:04:15 -0400255 apply();
Christian Robertson2e347422011-08-11 14:01:04 -0700256 }
257
Andrew Flynn061d43c2012-05-04 10:57:58 -0700258 @Override
Andrew Flynn2fdbe122015-06-01 16:34:21 -0400259 public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
260 int qsType, boolean activityIn, boolean activityOut, String typeContentDescription,
261 String description, boolean isWide, int subId) {
Jason Monk8fcab352015-06-29 10:57:00 -0400262 PhoneState state = getState(subId);
263 if (state == null) {
264 return;
265 }
Jason Monk3b230072015-05-29 11:11:29 -0400266 state.mMobileVisible = statusIcon.visible && !mBlockMobile;
Jason Monk07b75fe2015-05-14 16:47:03 -0400267 state.mMobileStrengthId = statusIcon.icon;
Jason Monk07b75fe2015-05-14 16:47:03 -0400268 state.mMobileTypeId = statusType;
269 state.mMobileDescription = statusIcon.contentDescription;
Jason Monkb5746272014-11-12 16:50:31 -0500270 state.mMobileTypeDescription = typeContentDescription;
Jason Monk07b75fe2015-05-14 16:47:03 -0400271 state.mIsMobileTypeIconWide = statusType != 0 && isWide;
Christian Robertson2e347422011-08-11 14:01:04 -0700272
Daniel Sandler28f89d42011-08-15 14:04:15 -0400273 apply();
274 }
275
Andrew Flynn061d43c2012-05-04 10:57:58 -0700276 @Override
Jason Monk07b75fe2015-05-14 16:47:03 -0400277 public void setEthernetIndicators(IconState state) {
Jason Monk3b230072015-05-29 11:11:29 -0400278 mEthernetVisible = state.visible && !mBlockEthernet;
Jason Monk07b75fe2015-05-14 16:47:03 -0400279 mEthernetIconId = state.icon;
280 mEthernetDescription = state.contentDescription;
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900281
282 apply();
283 }
284
285 @Override
Jason Monkb5746272014-11-12 16:50:31 -0500286 public void setNoSims(boolean show) {
Jason Monk3b230072015-05-29 11:11:29 -0400287 mNoSimsVisible = show && !mBlockMobile;
Jason Monk64f4f982015-10-08 10:09:21 -0400288 apply();
Jason Monkb5746272014-11-12 16:50:31 -0500289 }
290
291 @Override
292 public void setSubs(List<SubscriptionInfo> subs) {
Jason Monkf535cf02015-06-17 12:52:43 -0400293 if (hasCorrectSubs(subs)) {
294 return;
295 }
Jason Monkb5746272014-11-12 16:50:31 -0500296 // Clear out all old subIds.
297 mPhoneStates.clear();
298 if (mMobileSignalGroup != null) {
299 mMobileSignalGroup.removeAllViews();
300 }
301 final int n = subs.size();
302 for (int i = 0; i < n; i++) {
303 inflatePhoneState(subs.get(i).getSubscriptionId());
304 }
Jorim Jaggidd0107a2015-01-21 22:23:48 +0100305 if (isAttachedToWindow()) {
306 applyIconTint();
307 }
Jason Monkb5746272014-11-12 16:50:31 -0500308 }
309
Jason Monkf535cf02015-06-17 12:52:43 -0400310 private boolean hasCorrectSubs(List<SubscriptionInfo> subs) {
311 final int N = subs.size();
312 if (N != mPhoneStates.size()) {
313 return false;
314 }
315 for (int i = 0; i < N; i++) {
316 if (mPhoneStates.get(i).mSubId != subs.get(i).getSubscriptionId()) {
317 return false;
318 }
319 }
320 return true;
321 }
322
Jason Monk8fcab352015-06-29 10:57:00 -0400323 private PhoneState getState(int subId) {
Jason Monkb5746272014-11-12 16:50:31 -0500324 for (PhoneState state : mPhoneStates) {
325 if (state.mSubId == subId) {
326 return state;
327 }
328 }
Jason Monk8fcab352015-06-29 10:57:00 -0400329 Log.e(TAG, "Unexpected subscription " + subId);
330 return null;
Jason Monkb5746272014-11-12 16:50:31 -0500331 }
332
333 private PhoneState inflatePhoneState(int subId) {
334 PhoneState state = new PhoneState(subId, mContext);
335 if (mMobileSignalGroup != null) {
336 mMobileSignalGroup.addView(state.mMobileGroup);
337 }
338 mPhoneStates.add(state);
339 return state;
340 }
341
342 @Override
Jason Monk07b75fe2015-05-14 16:47:03 -0400343 public void setIsAirplaneMode(IconState icon) {
Jason Monk3b230072015-05-29 11:11:29 -0400344 mIsAirplaneMode = icon.visible && !mBlockAirplane;
Jason Monk07b75fe2015-05-14 16:47:03 -0400345 mAirplaneIconId = icon.icon;
346 mAirplaneContentDescription = icon.contentDescription;
Andrew Flynn061d43c2012-05-04 10:57:58 -0700347
348 apply();
Daniel Sandler5ccff812011-09-13 15:17:58 -0400349 }
350
John Spurlock2f7dfa72012-05-16 20:20:59 -0400351 @Override
Jason Monk07b75fe2015-05-14 16:47:03 -0400352 public void setMobileDataEnabled(boolean enabled) {
353 // Don't care.
354 }
355
356 @Override
Alan Viverettea54956a2015-01-07 16:05:02 -0800357 public boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
John Spurlock2f7dfa72012-05-16 20:20:59 -0400358 // Standard group layout onPopulateAccessibilityEvent() implementations
359 // ignore content description, so populate manually
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900360 if (mEthernetVisible && mEthernetGroup != null &&
361 mEthernetGroup.getContentDescription() != null)
362 event.getText().add(mEthernetGroup.getContentDescription());
Daniel Sandler24e028e2013-08-13 20:18:01 -0700363 if (mWifiVisible && mWifiGroup != null && mWifiGroup.getContentDescription() != null)
John Spurlock2f7dfa72012-05-16 20:20:59 -0400364 event.getText().add(mWifiGroup.getContentDescription());
Jason Monkb5746272014-11-12 16:50:31 -0500365 for (PhoneState state : mPhoneStates) {
366 state.populateAccessibilityEvent(event);
367 }
Alan Viverettea54956a2015-01-07 16:05:02 -0800368 return super.dispatchPopulateAccessibilityEventInternal(event);
John Spurlock2f7dfa72012-05-16 20:20:59 -0400369 }
370
Fabrice Di Meglio46626112013-05-07 11:32:51 -0700371 @Override
372 public void onRtlPropertiesChanged(int layoutDirection) {
373 super.onRtlPropertiesChanged(layoutDirection);
374
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900375 if (mEthernet != null) {
376 mEthernet.setImageDrawable(null);
Jorim Jaggi06302c22015-05-20 17:05:23 -0700377 mEthernetDark.setImageDrawable(null);
378 mLastEthernetIconId = -1;
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900379 }
380
Fabrice Di Meglio46626112013-05-07 11:32:51 -0700381 if (mWifi != null) {
382 mWifi.setImageDrawable(null);
Jorim Jaggi06302c22015-05-20 17:05:23 -0700383 mWifiDark.setImageDrawable(null);
384 mLastWifiStrengthId = -1;
Fabrice Di Meglio46626112013-05-07 11:32:51 -0700385 }
Fabrice Di Meglio46626112013-05-07 11:32:51 -0700386
Jason Monkb5746272014-11-12 16:50:31 -0500387 for (PhoneState state : mPhoneStates) {
388 if (state.mMobile != null) {
Jorim Jaggi3c988192016-01-19 16:32:17 -0800389 state.maybeStopAnimatableDrawable(state.mMobile);
Jason Monkb5746272014-11-12 16:50:31 -0500390 state.mMobile.setImageDrawable(null);
Jorim Jaggi3c988192016-01-19 16:32:17 -0800391 state.mLastMobileStrengthId = -1;
Jason Monkb5746272014-11-12 16:50:31 -0500392 }
393 if (state.mMobileType != null) {
394 state.mMobileType.setImageDrawable(null);
Jorim Jaggi3c988192016-01-19 16:32:17 -0800395 state.mLastMobileTypeId = -1;
Jason Monkb5746272014-11-12 16:50:31 -0500396 }
Fabrice Di Meglio46626112013-05-07 11:32:51 -0700397 }
398
Jorim Jaggi06302c22015-05-20 17:05:23 -0700399 if (mAirplane != null) {
Fabrice Di Meglio46626112013-05-07 11:32:51 -0700400 mAirplane.setImageDrawable(null);
Jorim Jaggi06302c22015-05-20 17:05:23 -0700401 mLastAirplaneIconId = -1;
Fabrice Di Meglio46626112013-05-07 11:32:51 -0700402 }
403
404 apply();
405 }
406
Jorim Jaggi0d266892014-07-28 14:49:13 +0200407 @Override
408 public boolean hasOverlappingRendering() {
409 return false;
410 }
411
Daniel Sandler28f89d42011-08-15 14:04:15 -0400412 // Run after each indicator change.
413 private void apply() {
414 if (mWifiGroup == null) return;
415
Jason Monk3128f122014-09-03 13:18:57 -0400416 mVpn.setVisibility(mVpnVisible ? View.VISIBLE : View.GONE);
417 if (DEBUG) Log.d(TAG, String.format("vpn: %s", mVpnVisible ? "VISIBLE" : "GONE"));
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900418
419 if (mEthernetVisible) {
Jorim Jaggi06302c22015-05-20 17:05:23 -0700420 if (mLastEthernetIconId != mEthernetIconId) {
Anthony Chen55e8e1e2016-01-08 10:31:46 -0800421 setIconForView(mEthernet, mEthernetIconId);
422 setIconForView(mEthernetDark, mEthernetIconId);
Jorim Jaggi06302c22015-05-20 17:05:23 -0700423 mLastEthernetIconId = mEthernetIconId;
424 }
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900425 mEthernetGroup.setContentDescription(mEthernetDescription);
426 mEthernetGroup.setVisibility(View.VISIBLE);
427 } else {
428 mEthernetGroup.setVisibility(View.GONE);
429 }
430
431 if (DEBUG) Log.d(TAG,
432 String.format("ethernet: %s",
433 (mEthernetVisible ? "VISIBLE" : "GONE")));
434
Daniel Sandler28f89d42011-08-15 14:04:15 -0400435 if (mWifiVisible) {
Jorim Jaggi06302c22015-05-20 17:05:23 -0700436 if (mWifiStrengthId != mLastWifiStrengthId) {
Anthony Chen55e8e1e2016-01-08 10:31:46 -0800437 setIconForView(mWifi, mWifiStrengthId);
438 setIconForView(mWifiDark, mWifiStrengthId);
Jorim Jaggi06302c22015-05-20 17:05:23 -0700439 mLastWifiStrengthId = mWifiStrengthId;
440 }
Daniel Sandlerbcf6ef0b2011-09-30 11:43:36 -0400441 mWifiGroup.setContentDescription(mWifiDescription);
Fabrice Di Megliocda096e2012-12-26 17:11:13 -0800442 mWifiGroup.setVisibility(View.VISIBLE);
Daniel Sandler28f89d42011-08-15 14:04:15 -0400443 } else {
444 mWifiGroup.setVisibility(View.GONE);
445 }
446
John Spurlockcd686b52013-06-05 10:13:46 -0400447 if (DEBUG) Log.d(TAG,
John Spurlockfcc901c2013-09-04 10:36:27 -0400448 String.format("wifi: %s sig=%d",
Daniel Sandler28f89d42011-08-15 14:04:15 -0400449 (mWifiVisible ? "VISIBLE" : "GONE"),
John Spurlockfcc901c2013-09-04 10:36:27 -0400450 mWifiStrengthId));
Daniel Sandler28f89d42011-08-15 14:04:15 -0400451
Jason Monkb5746272014-11-12 16:50:31 -0500452 boolean anyMobileVisible = false;
Dan Sandlere912c9c2014-12-08 15:00:09 -0500453 int firstMobileTypeId = 0;
Jason Monkb5746272014-11-12 16:50:31 -0500454 for (PhoneState state : mPhoneStates) {
455 if (state.apply(anyMobileVisible)) {
Dan Sandlere912c9c2014-12-08 15:00:09 -0500456 if (!anyMobileVisible) {
457 firstMobileTypeId = state.mMobileTypeId;
458 anyMobileVisible = true;
459 }
Jason Monkb5746272014-11-12 16:50:31 -0500460 }
Christian Robertson2e347422011-08-11 14:01:04 -0700461 }
Daniel Sandler28f89d42011-08-15 14:04:15 -0400462
Andrew Flynn061d43c2012-05-04 10:57:58 -0700463 if (mIsAirplaneMode) {
Jorim Jaggi06302c22015-05-20 17:05:23 -0700464 if (mLastAirplaneIconId != mAirplaneIconId) {
Anthony Chen55e8e1e2016-01-08 10:31:46 -0800465 setIconForView(mAirplane, mAirplaneIconId);
Jorim Jaggi06302c22015-05-20 17:05:23 -0700466 mLastAirplaneIconId = mAirplaneIconId;
467 }
Jason Monk07b75fe2015-05-14 16:47:03 -0400468 mAirplane.setContentDescription(mAirplaneContentDescription);
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700469 mAirplane.setVisibility(View.VISIBLE);
Andrew Flynn061d43c2012-05-04 10:57:58 -0700470 } else {
471 mAirplane.setVisibility(View.GONE);
472 }
473
Jorim Jaggi5172dc22014-09-02 14:59:06 +0200474 if (mIsAirplaneMode && mWifiVisible) {
475 mWifiAirplaneSpacer.setVisibility(View.VISIBLE);
Daniel Sandler5ccff812011-09-13 15:17:58 -0400476 } else {
Jorim Jaggi5172dc22014-09-02 14:59:06 +0200477 mWifiAirplaneSpacer.setVisibility(View.GONE);
Daniel Sandler5ccff812011-09-13 15:17:58 -0400478 }
479
Dan Sandlere912c9c2014-12-08 15:00:09 -0500480 if (((anyMobileVisible && firstMobileTypeId != 0) || mNoSimsVisible) && mWifiVisible) {
Jorim Jaggic737b9b2014-09-08 23:57:20 +0200481 mWifiSignalSpacer.setVisibility(View.VISIBLE);
482 } else {
483 mWifiSignalSpacer.setVisibility(View.GONE);
484 }
485
Adrian Roos1b5eb972015-06-11 18:22:52 -0700486 mNoSimsCombo.setVisibility(mNoSimsVisible ? View.VISIBLE : View.GONE);
Jorim Jaggic737b9b2014-09-08 23:57:20 +0200487
Jason Monkb5746272014-11-12 16:50:31 -0500488 boolean anythingVisible = mNoSimsVisible || mWifiVisible || mIsAirplaneMode
Lorenzo Colittid46bb582015-04-27 20:32:01 +0900489 || anyMobileVisible || mVpnVisible || mEthernetVisible;
Jorim Jaggi6d035f12014-10-17 18:43:43 +0200490 setPaddingRelative(0, 0, anythingVisible ? mEndPadding : mEndPaddingNothingVisible, 0);
Christian Robertson2e347422011-08-11 14:01:04 -0700491 }
Jason Monkb5746272014-11-12 16:50:31 -0500492
Anthony Chen55e8e1e2016-01-08 10:31:46 -0800493 /**
494 * Sets the given drawable id on the view. This method will also scale the icon by
495 * {@link #mIconScaleFactor} if appropriate.
496 */
497 private void setIconForView(ImageView imageView, @DrawableRes int iconId) {
498 // Using the imageView's context to retrieve the Drawable so that theme is preserved.
499 Drawable icon = imageView.getContext().getDrawable(iconId);
500
501 if (mIconScaleFactor == 1.f) {
502 imageView.setImageDrawable(icon);
503 } else {
504 imageView.setImageDrawable(new ScalingDrawableWrapper(icon, mIconScaleFactor));
505 }
506 }
507
Jorim Jaggi86905582016-02-09 21:36:09 -0800508 public void setIconTint(int tint, float darkIntensity, Rect tintArea) {
509 boolean changed = tint != mIconTint || darkIntensity != mDarkIntensity
510 || !mTintArea.equals(tintArea);
Jorim Jaggidd0107a2015-01-21 22:23:48 +0100511 mIconTint = tint;
Jorim Jaggi5443cc52015-03-20 14:39:24 -0700512 mDarkIntensity = darkIntensity;
Jorim Jaggi86905582016-02-09 21:36:09 -0800513 mTintArea.set(tintArea);
Jorim Jaggidd0107a2015-01-21 22:23:48 +0100514 if (changed && isAttachedToWindow()) {
515 applyIconTint();
516 }
517 }
518
519 private void applyIconTint() {
Jorim Jaggi86905582016-02-09 21:36:09 -0800520 setTint(mVpn, StatusBarIconController.getTint(mTintArea, mVpn, mIconTint));
521 setTint(mAirplane, StatusBarIconController.getTint(mTintArea, mAirplane, mIconTint));
522 applyDarkIntensity(
523 StatusBarIconController.getDarkIntensity(mTintArea, mNoSims, mDarkIntensity),
524 mNoSims, mNoSimsDark);
525 applyDarkIntensity(
526 StatusBarIconController.getDarkIntensity(mTintArea, mWifi, mDarkIntensity),
527 mWifi, mWifiDark);
528 applyDarkIntensity(
529 StatusBarIconController.getDarkIntensity(mTintArea, mEthernet, mDarkIntensity),
530 mEthernet, mEthernetDark);
Jorim Jaggidd0107a2015-01-21 22:23:48 +0100531 for (int i = 0; i < mPhoneStates.size(); i++) {
Jorim Jaggi86905582016-02-09 21:36:09 -0800532 mPhoneStates.get(i).setIconTint(mIconTint, mDarkIntensity, mTintArea);
Jorim Jaggidd0107a2015-01-21 22:23:48 +0100533 }
534 }
535
Jorim Jaggi5443cc52015-03-20 14:39:24 -0700536 private void applyDarkIntensity(float darkIntensity, View lightIcon, View darkIcon) {
537 lightIcon.setAlpha(1 - darkIntensity);
538 darkIcon.setAlpha(darkIntensity);
539 }
540
Jorim Jaggidd0107a2015-01-21 22:23:48 +0100541 private void setTint(ImageView v, int tint) {
Jorim Jaggidd0107a2015-01-21 22:23:48 +0100542 v.setImageTintList(ColorStateList.valueOf(tint));
543 }
544
Jason Monkb5746272014-11-12 16:50:31 -0500545 private class PhoneState {
546 private final int mSubId;
547 private boolean mMobileVisible = false;
Andrew Flynn2fdbe122015-06-01 16:34:21 -0400548 private int mMobileStrengthId = 0, mMobileTypeId = 0;
Jorim Jaggi3c988192016-01-19 16:32:17 -0800549 private int mLastMobileStrengthId = -1;
550 private int mLastMobileTypeId = -1;
Jason Monkb5746272014-11-12 16:50:31 -0500551 private boolean mIsMobileTypeIconWide;
552 private String mMobileDescription, mMobileTypeDescription;
553
554 private ViewGroup mMobileGroup;
Jorim Jaggi5443cc52015-03-20 14:39:24 -0700555 private ImageView mMobile, mMobileDark, mMobileType;
Jason Monkb5746272014-11-12 16:50:31 -0500556
557 public PhoneState(int subId, Context context) {
558 ViewGroup root = (ViewGroup) LayoutInflater.from(context)
559 .inflate(R.layout.mobile_signal_group, null);
560 setViews(root);
561 mSubId = subId;
562 }
563
564 public void setViews(ViewGroup root) {
565 mMobileGroup = root;
566 mMobile = (ImageView) root.findViewById(R.id.mobile_signal);
Jorim Jaggi5443cc52015-03-20 14:39:24 -0700567 mMobileDark = (ImageView) root.findViewById(R.id.mobile_signal_dark);
Jason Monkb5746272014-11-12 16:50:31 -0500568 mMobileType = (ImageView) root.findViewById(R.id.mobile_type);
569 }
570
571 public boolean apply(boolean isSecondaryIcon) {
572 if (mMobileVisible && !mIsAirplaneMode) {
Jorim Jaggi3c988192016-01-19 16:32:17 -0800573 if (mLastMobileStrengthId != mMobileStrengthId) {
574 updateAnimatableIcon(mMobile, mMobileStrengthId);
575 updateAnimatableIcon(mMobileDark, mMobileStrengthId);
576 mLastMobileStrengthId = mMobileStrengthId;
Andrew Flynna478d702015-04-14 23:33:45 -0400577 }
578
Jorim Jaggi3c988192016-01-19 16:32:17 -0800579 if (mLastMobileTypeId != mMobileTypeId) {
580 mMobileType.setImageResource(mMobileTypeId);
581 mLastMobileTypeId = mMobileTypeId;
Andrew Flynna478d702015-04-14 23:33:45 -0400582 }
Jason Monkb5746272014-11-12 16:50:31 -0500583 mMobileGroup.setContentDescription(mMobileTypeDescription
584 + " " + mMobileDescription);
585 mMobileGroup.setVisibility(View.VISIBLE);
586 } else {
587 mMobileGroup.setVisibility(View.GONE);
588 }
589
590 // When this isn't next to wifi, give it some extra padding between the signals.
591 mMobileGroup.setPaddingRelative(isSecondaryIcon ? mSecondaryTelephonyPadding : 0,
592 0, 0, 0);
Anthony Chene87032c2016-02-09 07:42:25 -0800593 mMobile.setPaddingRelative(
594 mIsMobileTypeIconWide ? mWideTypeIconStartPadding : mMobileDataIconStartPadding,
Jason Monkb5746272014-11-12 16:50:31 -0500595 0, 0, 0);
Anthony Chene87032c2016-02-09 07:42:25 -0800596 mMobileDark.setPaddingRelative(
597 mIsMobileTypeIconWide ? mWideTypeIconStartPadding : mMobileDataIconStartPadding,
Jorim Jaggi5443cc52015-03-20 14:39:24 -0700598 0, 0, 0);
Jason Monkb5746272014-11-12 16:50:31 -0500599
Andrew Flynn2fdbe122015-06-01 16:34:21 -0400600 if (DEBUG) Log.d(TAG, String.format("mobile: %s sig=%d typ=%d",
601 (mMobileVisible ? "VISIBLE" : "GONE"), mMobileStrengthId, mMobileTypeId));
Jason Monkb5746272014-11-12 16:50:31 -0500602
603 mMobileType.setVisibility(mMobileTypeId != 0 ? View.VISIBLE : View.GONE);
604
605 return mMobileVisible;
606 }
607
Jorim Jaggi3c988192016-01-19 16:32:17 -0800608 private void updateAnimatableIcon(ImageView view, int resId) {
609 maybeStopAnimatableDrawable(view);
Anthony Chene87032c2016-02-09 07:42:25 -0800610 setIconForView(view, resId);
Jorim Jaggi3c988192016-01-19 16:32:17 -0800611 maybeStartAnimatableDrawable(view);
612 }
613
614 private void maybeStopAnimatableDrawable(ImageView view) {
615 Drawable drawable = view.getDrawable();
Anthony Chene87032c2016-02-09 07:42:25 -0800616
617 // Check if the icon has been scaled. If it has retrieve the actual drawable out of the
618 // wrapper.
619 if (drawable instanceof ScalingDrawableWrapper) {
620 drawable = ((ScalingDrawableWrapper) drawable).getDrawable();
621 }
622
Jorim Jaggi3c988192016-01-19 16:32:17 -0800623 if (drawable instanceof Animatable) {
624 Animatable ad = (Animatable) drawable;
625 if (ad.isRunning()) {
626 ad.stop();
627 }
628 }
629 }
630
631 private void maybeStartAnimatableDrawable(ImageView view) {
632 Drawable drawable = view.getDrawable();
Anthony Chene87032c2016-02-09 07:42:25 -0800633
634 // Check if the icon has been scaled. If it has retrieve the actual drawable out of the
635 // wrapper.
636 if (drawable instanceof ScalingDrawableWrapper) {
637 drawable = ((ScalingDrawableWrapper) drawable).getDrawable();
638 }
639
Jorim Jaggi3c988192016-01-19 16:32:17 -0800640 if (drawable instanceof Animatable) {
641 Animatable ad = (Animatable) drawable;
Jorim Jaggi035a82d2016-02-29 08:42:25 +0100642 if (ad instanceof AnimatedVectorDrawable) {
643 ((AnimatedVectorDrawable) ad).forceAnimationOnUI();
644 }
Jorim Jaggi3c988192016-01-19 16:32:17 -0800645 if (!ad.isRunning()) {
646 ad.start();
647 }
648 }
649 }
650
Jason Monkb5746272014-11-12 16:50:31 -0500651 public void populateAccessibilityEvent(AccessibilityEvent event) {
652 if (mMobileVisible && mMobileGroup != null
653 && mMobileGroup.getContentDescription() != null) {
654 event.getText().add(mMobileGroup.getContentDescription());
655 }
656 }
Jorim Jaggidd0107a2015-01-21 22:23:48 +0100657
Jorim Jaggi86905582016-02-09 21:36:09 -0800658 public void setIconTint(int tint, float darkIntensity, Rect tintArea) {
659 applyDarkIntensity(
660 StatusBarIconController.getDarkIntensity(tintArea, mMobile, darkIntensity),
661 mMobile, mMobileDark);
662 setTint(mMobileType, StatusBarIconController.getTint(tintArea, mMobileType, tint));
Jorim Jaggidd0107a2015-01-21 22:23:48 +0100663 }
Jason Monkb5746272014-11-12 16:50:31 -0500664 }
Christian Robertson2e347422011-08-11 14:01:04 -0700665}
666