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