blob: 7f95379d1d917d74e1f26a84a1660361b0e55bff [file] [log] [blame]
Tony Mantler98608e42016-01-22 14:58:48 -08001/*
2 * Copyright (C) 2016 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 */
Tony Mantler98608e42016-01-22 14:58:48 -080016package com.android.settingslib.wifi;
17
18import android.content.Context;
19import android.content.pm.PackageManager;
Stephen Chen2c096592017-01-18 15:25:31 -080020import android.content.res.Resources;
21import android.content.res.TypedArray;
Tony Mantler98608e42016-01-22 14:58:48 -080022import android.graphics.drawable.Drawable;
23import android.graphics.drawable.StateListDrawable;
Stephen Chened8f5292017-01-30 16:31:23 -080024import android.net.NetworkBadging;
Tony Mantler98608e42016-01-22 14:58:48 -080025import android.net.wifi.WifiConfiguration;
26import android.os.Looper;
27import android.os.UserHandle;
28import android.support.v7.preference.Preference;
29import android.support.v7.preference.PreferenceViewHolder;
30import android.text.TextUtils;
31import android.util.AttributeSet;
32import android.util.SparseArray;
Stephen Chen2c096592017-01-18 15:25:31 -080033import android.widget.ImageView;
Tony Mantler98608e42016-01-22 14:58:48 -080034import android.widget.TextView;
Sundeep Ghumanbf339f52017-01-23 15:41:43 -080035
Tony Mantler98608e42016-01-22 14:58:48 -080036import com.android.settingslib.R;
Sundeep Ghumanbf339f52017-01-23 15:41:43 -080037import com.android.settingslib.TronUtils;
Sundeep Ghumanf84e0572017-01-10 13:43:03 -080038import com.android.settingslib.Utils;
Tony Mantler98608e42016-01-22 14:58:48 -080039
40public class AccessPointPreference extends Preference {
41
42 private static final int[] STATE_SECURED = {
43 R.attr.state_encrypted
44 };
Tony Mantler98608e42016-01-22 14:58:48 -080045
Stephen Chenaed318e2017-03-31 16:58:38 -070046 private static final int[] STATE_METERED = {
47 R.attr.state_metered
48 };
49
Stephen Chen2c096592017-01-18 15:25:31 -080050 private static final int[] wifi_friction_attributes = { R.attr.wifi_friction };
Tony Mantler98608e42016-01-22 14:58:48 -080051
Stephen Chen2c096592017-01-18 15:25:31 -080052 private final StateListDrawable mFrictionSld;
Tony Mantler98608e42016-01-22 14:58:48 -080053 private final int mBadgePadding;
54 private final UserBadgeCache mBadgeCache;
Tony Mantler98608e42016-01-22 14:58:48 -080055 private TextView mTitleView;
Salvador Martinez45a15942016-08-11 17:14:11 -070056
Tony Mantler98608e42016-01-22 14:58:48 -080057 private boolean mForSavedNetworks = false;
58 private AccessPoint mAccessPoint;
59 private Drawable mBadge;
60 private int mLevel;
61 private CharSequence mContentDescription;
Salvador Martinez45a15942016-08-11 17:14:11 -070062 private int mDefaultIconResId;
Sundeep Ghuman699deaf2017-02-13 15:32:13 -080063 private int mWifiBadge = NetworkBadging.BADGING_NONE;
Tony Mantler98608e42016-01-22 14:58:48 -080064
65 static final int[] WIFI_CONNECTION_STRENGTH = {
66 R.string.accessibility_wifi_one_bar,
67 R.string.accessibility_wifi_two_bars,
68 R.string.accessibility_wifi_three_bars,
69 R.string.accessibility_wifi_signal_full
70 };
71
72 // Used for dummy pref.
73 public AccessPointPreference(Context context, AttributeSet attrs) {
74 super(context, attrs);
Stephen Chen2c096592017-01-18 15:25:31 -080075 mFrictionSld = null;
Tony Mantler98608e42016-01-22 14:58:48 -080076 mBadgePadding = 0;
77 mBadgeCache = null;
78 }
79
80 public AccessPointPreference(AccessPoint accessPoint, Context context, UserBadgeCache cache,
81 boolean forSavedNetworks) {
82 super(context);
Stephen Chen2c096592017-01-18 15:25:31 -080083 setWidgetLayoutResource(R.layout.access_point_friction_widget);
Tony Mantler98608e42016-01-22 14:58:48 -080084 mBadgeCache = cache;
85 mAccessPoint = accessPoint;
86 mForSavedNetworks = forSavedNetworks;
87 mAccessPoint.setTag(this);
88 mLevel = -1;
89
Stephen Chen2c096592017-01-18 15:25:31 -080090 TypedArray frictionSld;
91 try {
92 frictionSld = context.getTheme().obtainStyledAttributes(wifi_friction_attributes);
93 } catch (Resources.NotFoundException e) {
94 // Fallback for platforms that do not need friction icon resources.
95 frictionSld = null;
96 }
97 mFrictionSld = frictionSld != null ? (StateListDrawable) frictionSld.getDrawable(0) : null;
98
Tony Mantler98608e42016-01-22 14:58:48 -080099 // Distance from the end of the title at which this AP's user badge should sit.
100 mBadgePadding = context.getResources()
101 .getDimensionPixelSize(R.dimen.wifi_preference_badge_padding);
102 refresh();
103 }
104
Salvador Martinez45a15942016-08-11 17:14:11 -0700105 public AccessPointPreference(AccessPoint accessPoint, Context context, UserBadgeCache cache,
106 int iconResId, boolean forSavedNetworks) {
107 super(context);
Stephen Chen2c096592017-01-18 15:25:31 -0800108 setWidgetLayoutResource(R.layout.access_point_friction_widget);
Salvador Martinez45a15942016-08-11 17:14:11 -0700109 mBadgeCache = cache;
110 mAccessPoint = accessPoint;
111 mForSavedNetworks = forSavedNetworks;
112 mAccessPoint.setTag(this);
113 mLevel = -1;
114 mDefaultIconResId = iconResId;
115
Stephen Chen2c096592017-01-18 15:25:31 -0800116 TypedArray frictionSld;
117 try {
118 frictionSld = context.getTheme().obtainStyledAttributes(wifi_friction_attributes);
119 } catch (Resources.NotFoundException e) {
120 // Fallback for platforms that do not need friction icon resources.
121 frictionSld = null;
122 }
123 mFrictionSld = frictionSld != null ? (StateListDrawable) frictionSld.getDrawable(0) : null;
124
Salvador Martinez45a15942016-08-11 17:14:11 -0700125 // Distance from the end of the title at which this AP's user badge should sit.
126 mBadgePadding = context.getResources()
127 .getDimensionPixelSize(R.dimen.wifi_preference_badge_padding);
128 }
129
Tony Mantler98608e42016-01-22 14:58:48 -0800130 public AccessPoint getAccessPoint() {
131 return mAccessPoint;
132 }
133
134 @Override
135 public void onBindViewHolder(final PreferenceViewHolder view) {
136 super.onBindViewHolder(view);
137 if (mAccessPoint == null) {
138 // Used for dummy pref.
139 return;
140 }
141 Drawable drawable = getIcon();
142 if (drawable != null) {
143 drawable.setLevel(mLevel);
144 }
145
146 mTitleView = (TextView) view.findViewById(com.android.internal.R.id.title);
147 if (mTitleView != null) {
148 // Attach to the end of the title view
149 mTitleView.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null, mBadge, null);
150 mTitleView.setCompoundDrawablePadding(mBadgePadding);
151 }
152 view.itemView.setContentDescription(mContentDescription);
Stephen Chen2c096592017-01-18 15:25:31 -0800153
Sundeep Ghuman4d8781e2017-03-15 16:03:55 -0700154 ImageView frictionImageView = (ImageView) view.findViewById(R.id.friction_icon);
155 bindFrictionImage(frictionImageView);
Tony Mantler98608e42016-01-22 14:58:48 -0800156 }
157
158 protected void updateIcon(int level, Context context) {
159 if (level == -1) {
Salvador Martinez45a15942016-08-11 17:14:11 -0700160 safeSetDefaultIcon();
Stephen Chened8f5292017-01-30 16:31:23 -0800161 return;
162 }
163 TronUtils.logWifiSettingsBadge(context, mWifiBadge);
164 Drawable drawable = NetworkBadging.getWifiIcon(level, mWifiBadge, getContext().getTheme());
165 if (!mForSavedNetworks && drawable != null) {
Sundeep Ghuman6962c0c2017-05-08 14:27:06 -0700166 drawable.setTint(Utils.getColorAttr(context, android.R.attr.colorControlNormal));
Stephen Chened8f5292017-01-30 16:31:23 -0800167 setIcon(drawable);
Tony Mantler98608e42016-01-22 14:58:48 -0800168 } else {
Stephen Chened8f5292017-01-30 16:31:23 -0800169 safeSetDefaultIcon();
Tony Mantler98608e42016-01-22 14:58:48 -0800170 }
171 }
172
Stephen Chen2c096592017-01-18 15:25:31 -0800173 /**
174 * Binds the friction icon drawable using a StateListDrawable.
175 *
176 * <p>Friction icons will be rebound when notifyChange() is called, and therefore
177 * do not need to be managed in refresh()</p>.
178 */
179 private void bindFrictionImage(ImageView frictionImageView) {
180 if (frictionImageView == null || mFrictionSld == null) {
181 return;
182 }
183 if (mAccessPoint.getSecurity() != AccessPoint.SECURITY_NONE) {
Sundeep Ghuman4d8781e2017-03-15 16:03:55 -0700184 mFrictionSld.setState(STATE_SECURED);
Stephen Chen21f68682017-04-04 13:23:31 -0700185 } else if (mAccessPoint.isMetered()) {
Stephen Chenaed318e2017-03-31 16:58:38 -0700186 mFrictionSld.setState(STATE_METERED);
Stephen Chen2c096592017-01-18 15:25:31 -0800187 }
188 Drawable drawable = mFrictionSld.getCurrent();
189 frictionImageView.setImageDrawable(drawable);
190 }
191
Salvador Martinez45a15942016-08-11 17:14:11 -0700192 private void safeSetDefaultIcon() {
193 if (mDefaultIconResId != 0) {
194 setIcon(mDefaultIconResId);
195 } else {
196 setIcon(null);
197 }
198 }
199
Tony Mantler98608e42016-01-22 14:58:48 -0800200 protected void updateBadge(Context context) {
201 WifiConfiguration config = mAccessPoint.getConfig();
202 if (config != null) {
203 // Fetch badge (may be null)
204 // Get the badge using a cache since the PM will ask the UserManager for the list
205 // of profiles every time otherwise.
206 mBadge = mBadgeCache.getUserBadge(config.creatorUid);
207 }
208 }
209
210 /**
211 * Updates the title and summary; may indirectly call notifyChanged().
212 */
213 public void refresh() {
214 if (mForSavedNetworks) {
215 setTitle(mAccessPoint.getConfigName());
216 } else {
217 setTitle(mAccessPoint.getSsid());
218 }
219
220 final Context context = getContext();
Sundeep Ghumanaaa8a1b2017-03-13 14:40:56 -0700221 int level = mAccessPoint.getLevel();
Sundeep Ghumanf84e0572017-01-10 13:43:03 -0800222 int wifiBadge = mAccessPoint.getBadge();
223 if (level != mLevel || wifiBadge != mWifiBadge) {
Tony Mantler98608e42016-01-22 14:58:48 -0800224 mLevel = level;
Sundeep Ghumanf84e0572017-01-10 13:43:03 -0800225 mWifiBadge = wifiBadge;
Tony Mantler98608e42016-01-22 14:58:48 -0800226 updateIcon(mLevel, context);
Julia Reynolds8897a502016-06-14 17:28:47 +0000227 notifyChanged();
Tony Mantler98608e42016-01-22 14:58:48 -0800228 }
Sundeep Ghumanf84e0572017-01-10 13:43:03 -0800229
Tony Mantler98608e42016-01-22 14:58:48 -0800230 updateBadge(context);
231
232 setSummary(mForSavedNetworks ? mAccessPoint.getSavedNetworkSummary()
233 : mAccessPoint.getSettingsSummary());
234
Julia Reynolds8897a502016-06-14 17:28:47 +0000235 mContentDescription = getTitle();
Tony Mantler98608e42016-01-22 14:58:48 -0800236 if (getSummary() != null) {
Julia Reynolds8897a502016-06-14 17:28:47 +0000237 mContentDescription = TextUtils.concat(mContentDescription, ",", getSummary());
Tony Mantler98608e42016-01-22 14:58:48 -0800238 }
239 if (level >= 0 && level < WIFI_CONNECTION_STRENGTH.length) {
Julia Reynolds8897a502016-06-14 17:28:47 +0000240 mContentDescription = TextUtils.concat(mContentDescription, ",",
Tony Mantler98608e42016-01-22 14:58:48 -0800241 getContext().getString(WIFI_CONNECTION_STRENGTH[level]));
242 }
Tony Mantler98608e42016-01-22 14:58:48 -0800243 }
244
245 @Override
246 protected void notifyChanged() {
247 if (Looper.getMainLooper() != Looper.myLooper()) {
248 // Let our BG thread callbacks call setTitle/setSummary.
249 postNotifyChanged();
250 } else {
251 super.notifyChanged();
252 }
253 }
254
255 public void onLevelChanged() {
256 postNotifyChanged();
257 }
258
259 private void postNotifyChanged() {
260 if (mTitleView != null) {
261 mTitleView.post(mNotifyChanged);
262 } // Otherwise we haven't been bound yet, and don't need to update.
263 }
264
265 private final Runnable mNotifyChanged = new Runnable() {
266 @Override
267 public void run() {
268 notifyChanged();
269 }
270 };
271
272 public static class UserBadgeCache {
273 private final SparseArray<Drawable> mBadges = new SparseArray<>();
274 private final PackageManager mPm;
275
276 public UserBadgeCache(PackageManager pm) {
277 mPm = pm;
278 }
279
280 private Drawable getUserBadge(int userId) {
281 int index = mBadges.indexOfKey(userId);
282 if (index < 0) {
283 Drawable badge = mPm.getUserBadgeForDensity(new UserHandle(userId), 0 /* dpi */);
284 mBadges.put(userId, badge);
285 return badge;
286 }
287 return mBadges.valueAt(index);
288 }
289 }
290}