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