CellularTile.java revision 3250885c9feb9b42d60058a823c57a027c0dcf58
1/* 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; 23import android.service.quicksettings.Tile; 24import android.view.LayoutInflater; 25import android.view.View; 26import android.view.ViewGroup; 27import android.widget.Button; 28 29import com.android.internal.logging.MetricsLogger; 30import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 31import com.android.settingslib.net.DataUsageController; 32import com.android.systemui.R; 33import com.android.systemui.plugins.qs.QS.DetailAdapter; 34import com.android.systemui.qs.QSIconView; 35import com.android.systemui.qs.QSTile; 36import com.android.systemui.qs.SignalTileView; 37import com.android.systemui.statusbar.policy.NetworkController; 38import com.android.systemui.statusbar.policy.NetworkController.IconState; 39import com.android.systemui.statusbar.policy.SignalCallbackAdapter; 40 41/** Quick settings tile: Cellular **/ 42public class CellularTile extends QSTile<QSTile.SignalState> { 43 static final Intent CELLULAR_SETTINGS = new Intent().setComponent(new ComponentName( 44 "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity")); 45 46 private final NetworkController mController; 47 private final DataUsageController mDataController; 48 private final CellularDetailAdapter mDetailAdapter; 49 50 private final CellSignalCallback mSignalCallback = new CellSignalCallback(); 51 52 public CellularTile(Host host) { 53 super(host); 54 mController = host.getNetworkController(); 55 mDataController = mController.getMobileDataController(); 56 mDetailAdapter = new CellularDetailAdapter(); 57 } 58 59 @Override 60 public SignalState newTileState() { 61 return new SignalState(); 62 } 63 64 @Override 65 public DetailAdapter getDetailAdapter() { 66 return mDetailAdapter; 67 } 68 69 @Override 70 public void setListening(boolean listening) { 71 if (listening) { 72 mController.addCallback(mSignalCallback); 73 } else { 74 mController.removeCallback(mSignalCallback); 75 } 76 } 77 78 @Override 79 public QSIconView createTileView(Context context) { 80 return new SignalTileView(context); 81 } 82 83 @Override 84 public Intent getLongClickIntent() { 85 return CELLULAR_SETTINGS; 86 } 87 88 @Override 89 protected void handleClick() { 90 mDataController.setMobileDataEnabled(!mDataController.isMobileDataEnabled()); 91 } 92 93 @Override 94 protected void handleSecondaryClick() { 95 MetricsLogger.action(mContext, getMetricsCategory()); 96 if (mDataController.isMobileDataSupported()) { 97 showDetail(true); 98 } else { 99 mHost.startActivityDismissingKeyguard(CELLULAR_SETTINGS); 100 } 101 } 102 103 @Override 104 public CharSequence getTileLabel() { 105 return mContext.getString(R.string.quick_settings_cellular_detail_title); 106 } 107 108 @Override 109 protected void handleUpdateState(SignalState state, Object arg) { 110 CallbackInfo cb = (CallbackInfo) arg; 111 if (cb == null) { 112 cb = mSignalCallback.mInfo; 113 } 114 115 final Resources r = mContext.getResources(); 116 final int iconId = cb.noSim ? R.drawable.ic_qs_no_sim 117 : !cb.enabled || cb.airplaneModeEnabled ? R.drawable.ic_qs_signal_disabled 118 : cb.mobileSignalIconId > 0 ? cb.mobileSignalIconId 119 : R.drawable.ic_qs_signal_no_signal; 120 if (cb.dataTypeIconId != 0) { 121 state.icon = ResourceIcon.get(cb.dataTypeIconId); 122 } else { 123 state.icon = ResourceIcon.get(iconId); 124 } 125 state.isOverlayIconWide = cb.isDataTypeIconWide; 126 state.autoMirrorDrawable = !cb.noSim; 127 state.filter = iconId != R.drawable.ic_qs_no_sim; 128 state.activityIn = cb.enabled && cb.activityIn; 129 state.activityOut = cb.enabled && cb.activityOut; 130 131 state.label = cb.enabled 132 ? removeTrailingPeriod(cb.enabledDesc) 133 : r.getString(R.string.quick_settings_rssi_emergency_only); 134 135 final String signalContentDesc = cb.enabled && (cb.mobileSignalIconId > 0) 136 ? cb.signalContentDescription 137 : r.getString(R.string.accessibility_no_signal); 138 139 if (cb.noSim) { 140 state.contentDescription = state.label; 141 } else { 142 String enabledDesc = cb.enabled ? r.getString(R.string.accessibility_cell_data_on) 143 : r.getString(R.string.accessibility_cell_data_off); 144 145 state.contentDescription = r.getString( 146 R.string.accessibility_quick_settings_mobile, 147 enabledDesc, signalContentDesc, 148 state.label); 149 state.minimalContentDescription = r.getString( 150 R.string.accessibility_quick_settings_mobile, 151 r.getString(R.string.accessibility_cell_data), signalContentDesc, 152 state.label); 153 } 154 state.contentDescription = state.contentDescription + "," + r.getString( 155 R.string.accessibility_quick_settings_open_settings, getTileLabel()); 156 state.minimalAccessibilityClassName = state.expandedAccessibilityClassName 157 = Button.class.getName(); 158 state.value = mDataController.isMobileDataSupported() 159 && mDataController.isMobileDataEnabled(); 160 state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; 161 } 162 163 @Override 164 public int getMetricsCategory() { 165 return MetricsEvent.QS_CELLULAR; 166 } 167 168 @Override 169 public boolean isAvailable() { 170 return mController.hasMobileDataFeature(); 171 } 172 173 // Remove the period from the network name 174 public static String removeTrailingPeriod(String string) { 175 if (string == null) return null; 176 final int length = string.length(); 177 if (string.endsWith(".")) { 178 return string.substring(0, length - 1); 179 } 180 return string; 181 } 182 183 private static final class CallbackInfo { 184 boolean enabled; 185 boolean wifiEnabled; 186 boolean airplaneModeEnabled; 187 int mobileSignalIconId; 188 String signalContentDescription; 189 int dataTypeIconId; 190 String dataContentDescription; 191 boolean activityIn; 192 boolean activityOut; 193 String enabledDesc; 194 boolean noSim; 195 boolean isDataTypeIconWide; 196 } 197 198 private final class CellSignalCallback extends SignalCallbackAdapter { 199 private final CallbackInfo mInfo = new CallbackInfo(); 200 @Override 201 public void setWifiIndicators(boolean enabled, IconState statusIcon, IconState qsIcon, 202 boolean activityIn, boolean activityOut, String description) { 203 mInfo.wifiEnabled = enabled; 204 refreshState(mInfo); 205 } 206 207 @Override 208 public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType, 209 int qsType, boolean activityIn, boolean activityOut, String typeContentDescription, 210 String description, boolean isWide, int subId) { 211 if (qsIcon == null) { 212 // Not data sim, don't display. 213 return; 214 } 215 mInfo.enabled = qsIcon.visible; 216 mInfo.mobileSignalIconId = qsIcon.icon; 217 mInfo.signalContentDescription = qsIcon.contentDescription; 218 mInfo.dataTypeIconId = qsType; 219 mInfo.dataContentDescription = typeContentDescription; 220 mInfo.activityIn = activityIn; 221 mInfo.activityOut = activityOut; 222 mInfo.enabledDesc = description; 223 mInfo.isDataTypeIconWide = qsType != 0 && isWide; 224 refreshState(mInfo); 225 } 226 227 @Override 228 public void setNoSims(boolean show) { 229 mInfo.noSim = show; 230 if (mInfo.noSim) { 231 // Make sure signal gets cleared out when no sims. 232 mInfo.mobileSignalIconId = 0; 233 mInfo.dataTypeIconId = 0; 234 // Show a No SIMs description to avoid emergency calls message. 235 mInfo.enabled = true; 236 mInfo.enabledDesc = mContext.getString( 237 R.string.keyguard_missing_sim_message_short); 238 mInfo.signalContentDescription = mInfo.enabledDesc; 239 } 240 refreshState(mInfo); 241 } 242 243 @Override 244 public void setIsAirplaneMode(IconState icon) { 245 mInfo.airplaneModeEnabled = icon.visible; 246 refreshState(mInfo); 247 } 248 249 @Override 250 public void setMobileDataEnabled(boolean enabled) { 251 mDetailAdapter.setMobileDataEnabled(enabled); 252 } 253 }; 254 255 private final class CellularDetailAdapter implements DetailAdapter { 256 257 @Override 258 public CharSequence getTitle() { 259 return mContext.getString(R.string.quick_settings_cellular_detail_title); 260 } 261 262 @Override 263 public Boolean getToggleState() { 264 return mDataController.isMobileDataSupported() 265 ? mDataController.isMobileDataEnabled() 266 : null; 267 } 268 269 @Override 270 public Intent getSettingsIntent() { 271 return CELLULAR_SETTINGS; 272 } 273 274 @Override 275 public void setToggleState(boolean state) { 276 MetricsLogger.action(mContext, MetricsEvent.QS_CELLULAR_TOGGLE, state); 277 mDataController.setMobileDataEnabled(state); 278 } 279 280 @Override 281 public int getMetricsCategory() { 282 return MetricsEvent.QS_DATAUSAGEDETAIL; 283 } 284 285 @Override 286 public View createDetailView(Context context, View convertView, ViewGroup parent) { 287 final DataUsageDetailView v = (DataUsageDetailView) (convertView != null 288 ? convertView 289 : LayoutInflater.from(mContext).inflate(R.layout.data_usage, parent, false)); 290 final DataUsageController.DataUsageInfo info = mDataController.getDataUsageInfo(); 291 if (info == null) return v; 292 v.bind(info); 293 return v; 294 } 295 296 public void setMobileDataEnabled(boolean enabled) { 297 fireToggleStateChanged(enabled); 298 } 299 } 300} 301