blob: 55b00b5c403045b9ad32652e586567d179c9a98e [file] [log] [blame]
John Spurlockaf8d6c42014-05-07 17:49:08 -04001/*
2 * Copyright (C) 2014 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.qs.tiles;
18
19import android.content.ComponentName;
20import android.content.Context;
21import android.content.Intent;
22import android.content.res.Resources;
John Spurlockb98f7472014-07-08 17:09:42 -040023import android.view.LayoutInflater;
24import android.view.View;
25import android.view.ViewGroup;
Chris Wrenf6e9228b2016-01-26 18:04:35 -050026
Chris Wren457a21c2015-05-06 17:50:34 -040027import com.android.internal.logging.MetricsLogger;
Chris Wrenf6e9228b2016-01-26 18:04:35 -050028import com.android.internal.logging.MetricsProto.MetricsEvent;
Jason Monkf668d7c2016-01-14 10:38:41 -050029import com.android.settingslib.net.DataUsageController;
John Spurlockaf8d6c42014-05-07 17:49:08 -040030import com.android.systemui.R;
Jason Monkdc35dcb2015-12-04 16:36:15 -050031import com.android.systemui.qs.QSIconView;
John Spurlockaf8d6c42014-05-07 17:49:08 -040032import com.android.systemui.qs.QSTile;
John Spurlockaf8d6c42014-05-07 17:49:08 -040033import com.android.systemui.qs.SignalTileView;
34import com.android.systemui.statusbar.policy.NetworkController;
Jason Monk07b75fe2015-05-14 16:47:03 -040035import com.android.systemui.statusbar.policy.NetworkController.IconState;
Jason Monk07b75fe2015-05-14 16:47:03 -040036import com.android.systemui.statusbar.policy.SignalCallbackAdapter;
John Spurlockaf8d6c42014-05-07 17:49:08 -040037
38/** Quick settings tile: Cellular **/
39public class CellularTile extends QSTile<QSTile.SignalState> {
Jason Monk76c67aa2016-02-19 14:49:42 -050040 static final Intent CELLULAR_SETTINGS = new Intent().setComponent(new ComponentName(
John Spurlockaf8d6c42014-05-07 17:49:08 -040041 "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity"));
42
43 private final NetworkController mController;
Jason Monkf668d7c2016-01-14 10:38:41 -050044 private final DataUsageController mDataController;
John Spurlockb98f7472014-07-08 17:09:42 -040045 private final CellularDetailAdapter mDetailAdapter;
John Spurlockaf8d6c42014-05-07 17:49:08 -040046
Jason Monk878c0932015-07-21 10:18:01 -040047 private final CellSignalCallback mSignalCallback = new CellSignalCallback();
48
John Spurlockaf8d6c42014-05-07 17:49:08 -040049 public CellularTile(Host host) {
50 super(host);
51 mController = host.getNetworkController();
Jason Monkd2263cd2014-11-10 14:22:56 -050052 mDataController = mController.getMobileDataController();
John Spurlockb98f7472014-07-08 17:09:42 -040053 mDetailAdapter = new CellularDetailAdapter();
John Spurlockaf8d6c42014-05-07 17:49:08 -040054 }
55
56 @Override
Jason Monk62b63a02016-02-02 15:15:31 -050057 public SignalState newTileState() {
John Spurlockaf8d6c42014-05-07 17:49:08 -040058 return new SignalState();
59 }
60
61 @Override
John Spurlockb98f7472014-07-08 17:09:42 -040062 public DetailAdapter getDetailAdapter() {
63 return mDetailAdapter;
64 }
65
66 @Override
John Spurlockccb6b9a2014-05-17 15:54:40 -040067 public void setListening(boolean listening) {
68 if (listening) {
Jason Monk07b75fe2015-05-14 16:47:03 -040069 mController.addSignalCallback(mSignalCallback);
John Spurlockccb6b9a2014-05-17 15:54:40 -040070 } else {
Jason Monk07b75fe2015-05-14 16:47:03 -040071 mController.removeSignalCallback(mSignalCallback);
John Spurlockccb6b9a2014-05-17 15:54:40 -040072 }
John Spurlockaf8d6c42014-05-07 17:49:08 -040073 }
74
75 @Override
Jason Monkdc35dcb2015-12-04 16:36:15 -050076 public QSIconView createTileView(Context context) {
John Spurlockaf8d6c42014-05-07 17:49:08 -040077 return new SignalTileView(context);
78 }
79
80 @Override
Jason Monk76c67aa2016-02-19 14:49:42 -050081 public Intent getLongClickIntent() {
82 return CELLULAR_SETTINGS;
83 }
84
85 @Override
John Spurlockaf8d6c42014-05-07 17:49:08 -040086 protected void handleClick() {
Chris Wren9e7283f2015-05-08 17:23:47 -040087 MetricsLogger.action(mContext, getMetricsCategory());
Jason Monkd2263cd2014-11-10 14:22:56 -050088 if (mDataController.isMobileDataSupported()) {
John Spurlockb98f7472014-07-08 17:09:42 -040089 showDetail(true);
90 } else {
Jason Monkee43cdf2015-06-19 14:20:46 -040091 mHost.startActivityDismissingKeyguard(CELLULAR_SETTINGS);
John Spurlockb98f7472014-07-08 17:09:42 -040092 }
John Spurlockaf8d6c42014-05-07 17:49:08 -040093 }
94
95 @Override
Jason Monkdeba7a42015-12-08 16:14:10 -050096 protected void handleSecondaryClick() {
97 boolean dataEnabled = mDataController.isMobileDataSupported()
98 && mDataController.isMobileDataEnabled();
Chris Wrenf6e9228b2016-01-26 18:04:35 -050099 MetricsLogger.action(mContext, MetricsEvent.QS_CELLULAR_TOGGLE, !dataEnabled);
Jason Monkdeba7a42015-12-08 16:14:10 -0500100 mDataController.setMobileDataEnabled(!dataEnabled);
101 }
102
103 @Override
Jason Monk39c98e62016-03-16 09:18:35 -0400104 public CharSequence getTileLabel() {
105 return mContext.getString(R.string.quick_settings_cellular_detail_title);
106 }
107
108 @Override
John Spurlockaf8d6c42014-05-07 17:49:08 -0400109 protected void handleUpdateState(SignalState state, Object arg) {
Jason Monk878c0932015-07-21 10:18:01 -0400110 CallbackInfo cb = (CallbackInfo) arg;
111 if (cb == null) {
112 cb = mSignalCallback.mInfo;
113 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400114
115 final Resources r = mContext.getResources();
John Spurlock2d695812014-10-30 13:25:21 -0400116 final int iconId = cb.noSim ? R.drawable.ic_qs_no_sim
John Spurlockc1d48a52014-08-01 12:12:32 -0400117 : !cb.enabled || cb.airplaneModeEnabled ? R.drawable.ic_qs_signal_disabled
118 : cb.mobileSignalIconId > 0 ? cb.mobileSignalIconId
John Spurlockaf8d6c42014-05-07 17:49:08 -0400119 : R.drawable.ic_qs_signal_no_signal;
John Spurlock2d695812014-10-30 13:25:21 -0400120 state.icon = ResourceIcon.get(iconId);
Jorim Jaggic737b9b2014-09-08 23:57:20 +0200121 state.isOverlayIconWide = cb.isDataTypeIconWide;
Selim Cinek06d3bca2014-08-26 17:29:20 +0200122 state.autoMirrorDrawable = !cb.noSim;
Jeff Davidsonccda9962015-01-26 18:23:24 -0800123 state.overlayIconId = cb.enabled && (cb.dataTypeIconId > 0) ? cb.dataTypeIconId : 0;
John Spurlock2d695812014-10-30 13:25:21 -0400124 state.filter = iconId != R.drawable.ic_qs_no_sim;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400125 state.activityIn = cb.enabled && cb.activityIn;
126 state.activityOut = cb.enabled && cb.activityOut;
127
128 state.label = cb.enabled
129 ? removeTrailingPeriod(cb.enabledDesc)
130 : r.getString(R.string.quick_settings_rssi_emergency_only);
131
132 final String signalContentDesc = cb.enabled && (cb.mobileSignalIconId > 0)
133 ? cb.signalContentDescription
134 : r.getString(R.string.accessibility_no_signal);
135 final String dataContentDesc = cb.enabled && (cb.dataTypeIconId > 0) && !cb.wifiEnabled
136 ? cb.dataContentDescription
137 : r.getString(R.string.accessibility_no_data);
138 state.contentDescription = r.getString(
139 R.string.accessibility_quick_settings_mobile,
140 signalContentDesc, dataContentDesc,
141 state.label);
142 }
143
Chris Wren457a21c2015-05-06 17:50:34 -0400144 @Override
145 public int getMetricsCategory() {
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500146 return MetricsEvent.QS_CELLULAR;
Chris Wren457a21c2015-05-06 17:50:34 -0400147 }
148
Jason Monkc3f42c12016-02-05 12:33:13 -0500149 @Override
150 public boolean isAvailable() {
151 return mController.hasMobileDataFeature();
152 }
153
John Spurlockaf8d6c42014-05-07 17:49:08 -0400154 // Remove the period from the network name
155 public static String removeTrailingPeriod(String string) {
156 if (string == null) return null;
157 final int length = string.length();
158 if (string.endsWith(".")) {
159 return string.substring(0, length - 1);
160 }
161 return string;
162 }
163
164 private static final class CallbackInfo {
165 boolean enabled;
166 boolean wifiEnabled;
John Spurlockd5cd2fd2014-07-27 11:36:33 -0400167 boolean airplaneModeEnabled;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400168 int mobileSignalIconId;
169 String signalContentDescription;
170 int dataTypeIconId;
171 String dataContentDescription;
172 boolean activityIn;
173 boolean activityOut;
174 String enabledDesc;
John Spurlock899f4392014-06-11 10:59:11 -0400175 boolean noSim;
Jorim Jaggic737b9b2014-09-08 23:57:20 +0200176 boolean isDataTypeIconWide;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400177 }
178
Jason Monk878c0932015-07-21 10:18:01 -0400179 private final class CellSignalCallback extends SignalCallbackAdapter {
Jason Monkb5746272014-11-12 16:50:31 -0500180 private final CallbackInfo mInfo = new CallbackInfo();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400181 @Override
Jason Monk07b75fe2015-05-14 16:47:03 -0400182 public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon,
183 boolean activityIn, boolean activityOut, String description) {
Jason Monkb5746272014-11-12 16:50:31 -0500184 mInfo.wifiEnabled = enabled;
Jason Monkb5746272014-11-12 16:50:31 -0500185 refreshState(mInfo);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400186 }
187
188 @Override
Andrew Flynn2fdbe122015-06-01 16:34:21 -0400189 public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
190 int qsType, boolean activityIn, boolean activityOut, String typeContentDescription,
191 String description, boolean isWide, int subId) {
Jason Monk07b75fe2015-05-14 16:47:03 -0400192 if (qsIcon == null) {
193 // Not data sim, don't display.
194 return;
195 }
196 mInfo.enabled = qsIcon.visible;
197 mInfo.mobileSignalIconId = qsIcon.icon;
198 mInfo.signalContentDescription = qsIcon.contentDescription;
199 mInfo.dataTypeIconId = qsType;
200 mInfo.dataContentDescription = typeContentDescription;
Jason Monkb5746272014-11-12 16:50:31 -0500201 mInfo.activityIn = activityIn;
202 mInfo.activityOut = activityOut;
203 mInfo.enabledDesc = description;
Jason Monk07b75fe2015-05-14 16:47:03 -0400204 mInfo.isDataTypeIconWide = qsType != 0 && isWide;
Jason Monkb5746272014-11-12 16:50:31 -0500205 refreshState(mInfo);
206 }
207
208 @Override
Jason Monk07b75fe2015-05-14 16:47:03 -0400209 public void setNoSims(boolean show) {
210 mInfo.noSim = show;
Jason Monkb5746272014-11-12 16:50:31 -0500211 if (mInfo.noSim) {
212 // Make sure signal gets cleared out when no sims.
213 mInfo.mobileSignalIconId = 0;
214 mInfo.dataTypeIconId = 0;
Jason Monkb36becf2015-01-08 11:12:39 -0500215 // Show a No SIMs description to avoid emergency calls message.
216 mInfo.enabled = true;
217 mInfo.enabledDesc = mContext.getString(
218 R.string.keyguard_missing_sim_message_short);
219 mInfo.signalContentDescription = mInfo.enabledDesc;
Jason Monkb5746272014-11-12 16:50:31 -0500220 }
221 refreshState(mInfo);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400222 }
223
224 @Override
Jason Monk07b75fe2015-05-14 16:47:03 -0400225 public void setIsAirplaneMode(IconState icon) {
226 mInfo.airplaneModeEnabled = icon.visible;
Jason Monkb5746272014-11-12 16:50:31 -0500227 refreshState(mInfo);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400228 }
John Spurlockb98f7472014-07-08 17:09:42 -0400229
Jason Monk07b75fe2015-05-14 16:47:03 -0400230 @Override
231 public void setMobileDataEnabled(boolean enabled) {
John Spurlockb98f7472014-07-08 17:09:42 -0400232 mDetailAdapter.setMobileDataEnabled(enabled);
233 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400234 };
John Spurlockb98f7472014-07-08 17:09:42 -0400235
236 private final class CellularDetailAdapter implements DetailAdapter {
John Spurlockb98f7472014-07-08 17:09:42 -0400237
238 @Override
Jason Monkc06fbb12016-01-08 14:12:18 -0500239 public CharSequence getTitle() {
240 return mContext.getString(R.string.quick_settings_cellular_detail_title);
John Spurlockb98f7472014-07-08 17:09:42 -0400241 }
242
243 @Override
244 public Boolean getToggleState() {
Jason Monkd2263cd2014-11-10 14:22:56 -0500245 return mDataController.isMobileDataSupported()
Jason Monkb5746272014-11-12 16:50:31 -0500246 ? mDataController.isMobileDataEnabled()
247 : null;
John Spurlockb98f7472014-07-08 17:09:42 -0400248 }
249
250 @Override
251 public Intent getSettingsIntent() {
252 return CELLULAR_SETTINGS;
253 }
254
255 @Override
256 public void setToggleState(boolean state) {
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500257 MetricsLogger.action(mContext, MetricsEvent.QS_CELLULAR_TOGGLE, state);
Jason Monkd2263cd2014-11-10 14:22:56 -0500258 mDataController.setMobileDataEnabled(state);
John Spurlockb98f7472014-07-08 17:09:42 -0400259 }
260
261 @Override
Chris Wren457a21c2015-05-06 17:50:34 -0400262 public int getMetricsCategory() {
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500263 return MetricsEvent.QS_DATAUSAGEDETAIL;
Chris Wren457a21c2015-05-06 17:50:34 -0400264 }
265
266 @Override
John Spurlockb98f7472014-07-08 17:09:42 -0400267 public View createDetailView(Context context, View convertView, ViewGroup parent) {
Jorim Jaggie17c4b42014-08-26 17:27:31 +0200268 final DataUsageDetailView v = (DataUsageDetailView) (convertView != null
269 ? convertView
270 : LayoutInflater.from(mContext).inflate(R.layout.data_usage, parent, false));
Jason Monkf668d7c2016-01-14 10:38:41 -0500271 final DataUsageController.DataUsageInfo info = mDataController.getDataUsageInfo();
John Spurlockb98f7472014-07-08 17:09:42 -0400272 if (info == null) return v;
Jorim Jaggie17c4b42014-08-26 17:27:31 +0200273 v.bind(info);
John Spurlockb98f7472014-07-08 17:09:42 -0400274 return v;
275 }
276
277 public void setMobileDataEnabled(boolean enabled) {
278 fireToggleStateChanged(enabled);
279 }
John Spurlockb98f7472014-07-08 17:09:42 -0400280 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400281}