WifiTile.java revision b98f747c714ff8252471ca0a3295c2cb9ccb4f3a
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.Context; 20import android.content.Intent; 21import android.content.res.Resources; 22import android.provider.Settings; 23import android.util.Log; 24import android.view.LayoutInflater; 25import android.view.View; 26import android.view.View.OnClickListener; 27import android.view.ViewGroup; 28import android.widget.ImageView; 29import android.widget.LinearLayout; 30import android.widget.TextView; 31 32import com.android.systemui.R; 33import com.android.systemui.qs.QSTile; 34import com.android.systemui.qs.QSTileView; 35import com.android.systemui.qs.SignalTileView; 36import com.android.systemui.statusbar.policy.NetworkController; 37import com.android.systemui.statusbar.policy.NetworkController.AccessPoint; 38import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback; 39 40/** Quick settings tile: Wifi **/ 41public class WifiTile extends QSTile<QSTile.SignalState> { 42 private static final Intent WIFI_SETTINGS = new Intent(Settings.ACTION_WIFI_SETTINGS); 43 private static final int MAX_ITEMS = 4; // TODO temporary visual restriction 44 45 private final NetworkController mController; 46 private final WifiDetailAdapter mDetailAdapter; 47 48 public WifiTile(Host host) { 49 super(host); 50 mController = host.getNetworkController(); 51 mDetailAdapter = new WifiDetailAdapter(); 52 } 53 54 @Override 55 public boolean supportsDualTargets() { 56 return true; 57 } 58 59 @Override 60 protected SignalState newTileState() { 61 return new SignalState(); 62 } 63 64 @Override 65 public void setListening(boolean listening) { 66 if (listening) { 67 mController.addNetworkSignalChangedCallback(mCallback); 68 mController.addAccessPointCallback(mDetailAdapter); 69 mController.scanForAccessPoints(); 70 } else { 71 mController.removeNetworkSignalChangedCallback(mCallback); 72 mController.removeAccessPointCallback(mDetailAdapter); 73 } 74 } 75 76 @Override 77 public DetailAdapter getDetailAdapter() { 78 return mDetailAdapter; 79 } 80 81 @Override 82 public QSTileView createTileView(Context context) { 83 return new SignalTileView(context); 84 } 85 86 @Override 87 protected void handleClick() { 88 mController.setWifiEnabled(!mState.enabled); 89 } 90 91 @Override 92 protected void handleSecondaryClick() { 93 showDetail(true); 94 } 95 96 @Override 97 protected void handleUpdateState(SignalState state, Object arg) { 98 state.visible = true; 99 if (DEBUG) Log.d(TAG, "handleUpdateState arg=" + arg); 100 if (arg == null) return; 101 CallbackInfo cb = (CallbackInfo) arg; 102 103 boolean wifiConnected = cb.enabled && (cb.wifiSignalIconId > 0) && (cb.enabledDesc != null); 104 boolean wifiNotConnected = (cb.wifiSignalIconId > 0) && (cb.enabledDesc == null); 105 boolean enabledChanging = state.enabled != cb.enabled; 106 if (enabledChanging) { 107 mDetailAdapter.postUpdateItems(); 108 fireToggleStateChanged(cb.enabled); 109 } 110 state.enabled = cb.enabled; 111 state.connected = wifiConnected; 112 state.activityIn = cb.enabled && cb.activityIn; 113 state.activityOut = cb.enabled && cb.activityOut; 114 state.filter = true; 115 final String signalContentDescription; 116 final Resources r = mContext.getResources(); 117 if (wifiConnected) { 118 state.iconId = cb.wifiSignalIconId; 119 state.label = removeDoubleQuotes(cb.enabledDesc); 120 signalContentDescription = cb.wifiSignalContentDescription; 121 } else if (wifiNotConnected) { 122 state.iconId = R.drawable.ic_qs_wifi_0; 123 state.label = r.getString(R.string.quick_settings_wifi_label); 124 signalContentDescription = r.getString(R.string.accessibility_no_wifi); 125 } else { 126 state.iconId = R.drawable.ic_qs_wifi_no_network; 127 state.label = r.getString(R.string.quick_settings_wifi_label); 128 signalContentDescription = r.getString(R.string.accessibility_wifi_off); 129 } 130 state.contentDescription = mContext.getString( 131 R.string.accessibility_quick_settings_wifi, 132 signalContentDescription, 133 state.connected ? state.label : ""); 134 } 135 136 private static String removeDoubleQuotes(String string) { 137 if (string == null) return null; 138 final int length = string.length(); 139 if ((length > 1) && (string.charAt(0) == '"') && (string.charAt(length - 1) == '"')) { 140 return string.substring(1, length - 1); 141 } 142 return string; 143 } 144 145 private static final class CallbackInfo { 146 boolean enabled; 147 int wifiSignalIconId; 148 String enabledDesc; 149 boolean activityIn; 150 boolean activityOut; 151 String wifiSignalContentDescription; 152 153 @Override 154 public String toString() { 155 return new StringBuilder("CallbackInfo[") 156 .append("enabled=").append(enabled) 157 .append(",wifiSignalIconId=").append(wifiSignalIconId) 158 .append(",enabledDesc=").append(enabledDesc) 159 .append(",activityIn=").append(activityIn) 160 .append(",activityOut=").append(activityOut) 161 .append(",wifiSignalContentDescription=").append(wifiSignalContentDescription) 162 .append(']').toString(); 163 } 164 } 165 166 private final NetworkSignalChangedCallback mCallback = new NetworkSignalChangedCallback() { 167 @Override 168 public void onWifiSignalChanged(boolean enabled, int wifiSignalIconId, 169 boolean activityIn, boolean activityOut, 170 String wifiSignalContentDescriptionId, String description) { 171 if (DEBUG) Log.d(TAG, "onWifiSignalChanged enabled=" + enabled); 172 final CallbackInfo info = new CallbackInfo(); 173 info.enabled = enabled; 174 info.wifiSignalIconId = wifiSignalIconId; 175 info.enabledDesc = description; 176 info.activityIn = activityIn; 177 info.activityOut = activityOut; 178 info.wifiSignalContentDescription = wifiSignalContentDescriptionId; 179 refreshState(info); 180 } 181 182 @Override 183 public void onMobileDataSignalChanged(boolean enabled, 184 int mobileSignalIconId, 185 String mobileSignalContentDescriptionId, int dataTypeIconId, 186 boolean activityIn, boolean activityOut, 187 String dataTypeContentDescriptionId, String description, boolean noSim) { 188 // noop 189 } 190 191 @Override 192 public void onAirplaneModeChanged(boolean enabled) { 193 // noop 194 } 195 196 @Override 197 public void onMobileDataEnabled(boolean enabled) { 198 // noop 199 } 200 }; 201 202 private final class WifiDetailAdapter implements DetailAdapter, 203 NetworkController.AccessPointCallback { 204 205 private LinearLayout mItems; 206 private AccessPoint[] mAccessPoints; 207 208 @Override 209 public int getTitle() { 210 return R.string.quick_settings_wifi_label; 211 } 212 213 public Intent getSettingsIntent() { 214 return WIFI_SETTINGS; 215 } 216 217 @Override 218 public Boolean getToggleState() { 219 return mState.enabled; 220 } 221 222 @Override 223 public void setToggleState(boolean state) { 224 if (DEBUG) Log.d(TAG, "setToggleState " + state); 225 mController.setWifiEnabled(state); 226 showDetail(false); 227 } 228 229 @Override 230 public View createDetailView(Context context, View convertView, ViewGroup parent) { 231 if (convertView != null) return convertView; 232 mItems = new LinearLayout(context); 233 mItems.setOrientation(LinearLayout.VERTICAL); 234 updateItems(); 235 return mItems; 236 } 237 238 @Override 239 public void onAccessPointsChanged(final AccessPoint[] accessPoints) { 240 mUiHandler.post(new Runnable() { 241 @Override 242 public void run() { 243 mAccessPoints = accessPoints; 244 updateItems(); 245 } 246 }); 247 } 248 249 public void postUpdateItems() { 250 mUiHandler.post(new Runnable() { 251 @Override 252 public void run() { 253 updateItems(); 254 } 255 }); 256 } 257 258 private void updateItems() { 259 if (mItems == null) return; 260 mItems.removeAllViews(); 261 if (mAccessPoints == null || mAccessPoints.length == 0 || !mState.enabled) return; 262 for (int i = 0; i < mAccessPoints.length; i++) { 263 final AccessPoint ap = mAccessPoints[i]; 264 if (ap == null) continue; 265 final View item = LayoutInflater.from(mContext).inflate(R.layout.qs_detail_item, 266 mItems, false); 267 final ImageView iv = (ImageView) item.findViewById(android.R.id.icon); 268 iv.setImageResource(ap.iconId); 269 final TextView title = (TextView) item.findViewById(android.R.id.title); 270 title.setText(ap.ssid); 271 final TextView summary = (TextView) item.findViewById(android.R.id.summary); 272 if (ap.isConnected) { 273 item.setMinimumHeight(mContext.getResources() 274 .getDimensionPixelSize(R.dimen.qs_detail_item_height_twoline)); 275 summary.setText(R.string.quick_settings_connected); 276 } else { 277 summary.setVisibility(View.GONE); 278 } 279 item.setOnClickListener(new OnClickListener() { 280 @Override 281 public void onClick(View v) { 282 if (!ap.isConnected) { 283 mController.connect(ap); 284 } 285 showDetail(false); 286 } 287 }); 288 mItems.addView(item); 289 if (mItems.getChildCount() == MAX_ITEMS) break; 290 } 291 } 292 }; 293} 294