QuickSettingsModel.java revision ed1395f3981193c762e436cd1db725ce70022e43
1/* 2 * Copyright (C) 2012 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.statusbar.phone; 18 19import android.bluetooth.BluetoothAdapter; 20import android.bluetooth.BluetoothAdapter.BluetoothStateChangeCallback; 21import android.content.BroadcastReceiver; 22import android.content.ContentResolver; 23import android.content.Context; 24import android.content.Intent; 25import android.content.IntentFilter; 26import android.content.pm.PackageManager; 27import android.content.res.Resources; 28import android.database.ContentObserver; 29import android.graphics.drawable.Drawable; 30import android.hardware.display.WifiDisplayStatus; 31import android.os.Handler; 32import android.provider.Settings; 33import android.text.TextUtils; 34import android.view.View; 35import android.view.inputmethod.InputMethodInfo; 36import android.view.inputmethod.InputMethodManager; 37import android.view.inputmethod.InputMethodSubtype; 38 39import com.android.systemui.R; 40import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback; 41import com.android.systemui.statusbar.policy.LocationController.LocationGpsStateChangeCallback; 42import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback; 43 44import java.util.List; 45 46 47class QuickSettingsModel implements BluetoothStateChangeCallback, 48 NetworkSignalChangedCallback, 49 BatteryStateChangeCallback, 50 LocationGpsStateChangeCallback { 51 52 /** Represents the state of a given attribute. */ 53 static class State { 54 int iconId; 55 String label; 56 boolean enabled = false; 57 } 58 static class BatteryState extends State { 59 int batteryLevel; 60 boolean pluggedIn; 61 } 62 static class UserState extends State { 63 Drawable avatar; 64 } 65 66 /** The callback to update a given tile. */ 67 interface RefreshCallback { 68 public void refreshView(QuickSettingsTileView view, State state); 69 } 70 71 /** Broadcast receive to determine if there is an alarm set. */ 72 private BroadcastReceiver mAlarmIntentReceiver = new BroadcastReceiver() { 73 @Override 74 public void onReceive(Context context, Intent intent) { 75 String action = intent.getAction(); 76 if (action.equals(Intent.ACTION_ALARM_CHANGED)) { 77 onAlarmChanged(intent); 78 onNextAlarmChanged(); 79 } 80 } 81 }; 82 83 /** ContentObserver to determine the next alarm */ 84 private class NextAlarmObserver extends ContentObserver { 85 public NextAlarmObserver(Handler handler) { 86 super(handler); 87 } 88 89 @Override public void onChange(boolean selfChange) { 90 onNextAlarmChanged(); 91 } 92 93 public void startObserving() { 94 final ContentResolver cr = mContext.getContentResolver(); 95 cr.registerContentObserver( 96 Settings.System.getUriFor(Settings.System.NEXT_ALARM_FORMATTED), false, this); 97 } 98 } 99 100 private Context mContext; 101 private Handler mHandler; 102 private NextAlarmObserver mNextAlarmObserver; 103 104 private QuickSettingsTileView mUserTile; 105 private RefreshCallback mUserCallback; 106 private UserState mUserState = new UserState(); 107 108 private QuickSettingsTileView mTimeTile; 109 private RefreshCallback mTimeAlarmCallback; 110 private State mTimeAlarmState = new State(); 111 112 private QuickSettingsTileView mAirplaneModeTile; 113 private RefreshCallback mAirplaneModeCallback; 114 private State mAirplaneModeState = new State(); 115 116 private QuickSettingsTileView mWifiTile; 117 private RefreshCallback mWifiCallback; 118 private State mWifiState = new State(); 119 120 private QuickSettingsTileView mWifiDisplayTile; 121 private RefreshCallback mWifiDisplayCallback; 122 private State mWifiDisplayState = new State(); 123 124 private QuickSettingsTileView mRSSITile; 125 private RefreshCallback mRSSICallback; 126 private State mRSSIState = new State(); 127 128 private QuickSettingsTileView mBluetoothTile; 129 private RefreshCallback mBluetoothCallback; 130 private State mBluetoothState = new State(); 131 132 private QuickSettingsTileView mBatteryTile; 133 private RefreshCallback mBatteryCallback; 134 private BatteryState mBatteryState = new BatteryState(); 135 136 private QuickSettingsTileView mLocationTile; 137 private RefreshCallback mLocationCallback; 138 private State mLocationState = new State(); 139 140 private QuickSettingsTileView mImeTile; 141 private RefreshCallback mImeCallback; 142 private State mImeState = new State(); 143 144 public QuickSettingsModel(Context context) { 145 mContext = context; 146 mHandler = new Handler(); 147 mNextAlarmObserver = new NextAlarmObserver(mHandler); 148 mNextAlarmObserver.startObserving(); 149 150 IntentFilter alarmIntentFilter = new IntentFilter(); 151 alarmIntentFilter.addAction(Intent.ACTION_ALARM_CHANGED); 152 context.registerReceiver(mAlarmIntentReceiver, alarmIntentFilter); 153 } 154 155 // User 156 void addUserTile(QuickSettingsTileView view, RefreshCallback cb) { 157 mUserTile = view; 158 mUserCallback = cb; 159 mUserCallback.refreshView(mUserTile, mUserState); 160 } 161 void setUserTileInfo(String name, Drawable avatar) { 162 mUserState.label = name; 163 mUserState.avatar = avatar; 164 mUserCallback.refreshView(mUserTile, mUserState); 165 } 166 167 // Time 168 void addTimeTile(QuickSettingsTileView view, RefreshCallback cb) { 169 mTimeTile = view; 170 mTimeAlarmCallback = cb; 171 mTimeAlarmCallback.refreshView(view, mTimeAlarmState); 172 } 173 void onAlarmChanged(Intent intent) { 174 mTimeAlarmState.enabled = intent.getBooleanExtra("alarmSet", false); 175 mTimeAlarmCallback.refreshView(mTimeTile, mTimeAlarmState); 176 } 177 void onNextAlarmChanged() { 178 mTimeAlarmState.label = Settings.System.getString(mContext.getContentResolver(), 179 Settings.System.NEXT_ALARM_FORMATTED); 180 mTimeAlarmCallback.refreshView(mTimeTile, mTimeAlarmState); 181 } 182 183 // Airplane Mode 184 void addAirplaneModeTile(QuickSettingsTileView view, RefreshCallback cb) { 185 mAirplaneModeTile = view; 186 mAirplaneModeTile.setOnClickListener(new View.OnClickListener() { 187 @Override 188 public void onClick(View v) { 189 if (mAirplaneModeState.enabled) { 190 setAirplaneModeState(false); 191 } else { 192 setAirplaneModeState(true); 193 } 194 } 195 }); 196 mAirplaneModeCallback = cb; 197 mAirplaneModeCallback.refreshView(mAirplaneModeTile, mAirplaneModeState); 198 } 199 private void setAirplaneModeState(boolean enabled) { 200 // TODO: Sets the view to be "awaiting" if not already awaiting 201 202 // Change the system setting 203 Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 204 enabled ? 1 : 0); 205 206 // Post the intent 207 Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); 208 intent.putExtra("state", enabled); 209 mContext.sendBroadcast(intent); 210 } 211 // NetworkSignalChanged callback 212 @Override 213 public void onAirplaneModeChanged(boolean enabled) { 214 // TODO: If view is in awaiting state, disable 215 Resources r = mContext.getResources(); 216 mAirplaneModeState.enabled = enabled; 217 mAirplaneModeState.iconId = (enabled ? 218 R.drawable.ic_qs_airplane_on : 219 R.drawable.ic_qs_airplane_off); 220 mAirplaneModeCallback.refreshView(mAirplaneModeTile, mAirplaneModeState); 221 } 222 223 // Wifi 224 void addWifiTile(QuickSettingsTileView view, RefreshCallback cb) { 225 mWifiTile = view; 226 mWifiCallback = cb; 227 mWifiCallback.refreshView(mWifiTile, mWifiState); 228 } 229 // NetworkSignalChanged callback 230 @Override 231 public void onWifiSignalChanged(boolean enabled, int wifiSignalIconId, String enabledDesc) { 232 // TODO: If view is in awaiting state, disable 233 Resources r = mContext.getResources(); 234 mWifiState.iconId = enabled && (wifiSignalIconId > 0) 235 ? wifiSignalIconId 236 : R.drawable.ic_qs_wifi_no_network; 237 mWifiState.label = enabled 238 ? enabledDesc 239 : r.getString(R.string.quick_settings_wifi_no_network); 240 mWifiCallback.refreshView(mWifiTile, mWifiState); 241 } 242 243 // RSSI 244 void addRSSITile(QuickSettingsTileView view, RefreshCallback cb) { 245 mRSSITile = view; 246 mRSSICallback = cb; 247 mRSSICallback.refreshView(mRSSITile, mRSSIState); 248 } 249 boolean deviceSupportsTelephony() { 250 PackageManager pm = mContext.getPackageManager(); 251 return pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY); 252 } 253 // NetworkSignalChanged callback 254 @Override 255 public void onMobileDataSignalChanged(boolean enabled, int mobileSignalIconId, 256 String enabledDesc) { 257 if (deviceSupportsTelephony()) { 258 // TODO: If view is in awaiting state, disable 259 Resources r = mContext.getResources(); 260 mRSSIState.iconId = enabled && (mobileSignalIconId > 0) 261 ? mobileSignalIconId 262 : R.drawable.ic_qs_signal_no_signal; 263 mRSSIState.label = enabled 264 ? enabledDesc 265 : r.getString(R.string.quick_settings_rssi_emergency_only); 266 mRSSICallback.refreshView(mRSSITile, mRSSIState); 267 } 268 } 269 270 // Bluetooth 271 void addBluetoothTile(QuickSettingsTileView view, RefreshCallback cb) { 272 mBluetoothTile = view; 273 mBluetoothCallback = cb; 274 275 final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 276 onBluetoothStateChange(adapter.isEnabled()); 277 } 278 boolean deviceSupportsBluetooth() { 279 return (BluetoothAdapter.getDefaultAdapter() != null); 280 } 281 // BluetoothController callback 282 @Override 283 public void onBluetoothStateChange(boolean on) { 284 // TODO: If view is in awaiting state, disable 285 Resources r = mContext.getResources(); 286 mBluetoothState.enabled = on; 287 if (on) { 288 mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_on; 289 } else { 290 mBluetoothState.iconId = R.drawable.ic_qs_bluetooth_off; 291 } 292 mBluetoothCallback.refreshView(mBluetoothTile, mBluetoothState); 293 } 294 295 // Battery 296 void addBatteryTile(QuickSettingsTileView view, RefreshCallback cb) { 297 mBatteryTile = view; 298 mBatteryCallback = cb; 299 mBatteryCallback.refreshView(mBatteryTile, mBatteryState); 300 } 301 // BatteryController callback 302 @Override 303 public void onBatteryLevelChanged(int level, boolean pluggedIn) { 304 mBatteryState.batteryLevel = level; 305 mBatteryState.pluggedIn = pluggedIn; 306 mBatteryCallback.refreshView(mBatteryTile, mBatteryState); 307 } 308 309 // Location 310 void addLocationTile(QuickSettingsTileView view, RefreshCallback cb) { 311 mLocationTile = view; 312 mLocationCallback = cb; 313 mLocationCallback.refreshView(mLocationTile, mLocationState); 314 } 315 // LocationController callback 316 @Override 317 public void onLocationGpsStateChanged(boolean inUse, String description) { 318 mLocationState.enabled = inUse; 319 mLocationState.label = description; 320 mLocationCallback.refreshView(mLocationTile, mLocationState); 321 } 322 323 // Wifi Display 324 void addWifiDisplayTile(QuickSettingsTileView view, RefreshCallback cb) { 325 mWifiDisplayTile = view; 326 mWifiDisplayCallback = cb; 327 } 328 public void onWifiDisplayStateChanged(WifiDisplayStatus status) { 329 mWifiDisplayState.enabled = status.isEnabled(); 330 if (status.getActiveDisplay() != null) { 331 mWifiDisplayState.label = status.getActiveDisplay().getDeviceName(); 332 } else { 333 mWifiDisplayState.label = mContext.getString( 334 R.string.quick_settings_wifi_display_no_connection_label); 335 } 336 mWifiDisplayCallback.refreshView(mWifiDisplayTile, mWifiDisplayState); 337 338 } 339 340 // IME 341 void addImeTile(QuickSettingsTileView view, RefreshCallback cb) { 342 mImeTile = view; 343 mImeCallback = cb; 344 mImeCallback.refreshView(mImeTile, mImeState); 345 } 346 void onImeWindowStatusChanged(boolean visible) { 347 InputMethodManager imm = 348 (InputMethodManager) mContext.getSystemService(Context.INPUT_METHOD_SERVICE); 349 List<InputMethodInfo> imis = imm.getInputMethodList(); 350 351 mImeState.enabled = visible; 352 mImeState.label = getCurrentInputMethodName(mContext, mContext.getContentResolver(), 353 imm, imis, mContext.getPackageManager()); 354 mImeCallback.refreshView(mImeTile, mImeState); 355 } 356 private static String getCurrentInputMethodName(Context context, ContentResolver resolver, 357 InputMethodManager imm, List<InputMethodInfo> imis, PackageManager pm) { 358 if (resolver == null || imis == null) return null; 359 final String currentInputMethodId = Settings.Secure.getString(resolver, 360 Settings.Secure.DEFAULT_INPUT_METHOD); 361 if (TextUtils.isEmpty(currentInputMethodId)) return null; 362 for (InputMethodInfo imi : imis) { 363 if (currentInputMethodId.equals(imi.getId())) { 364 final InputMethodSubtype subtype = imm.getCurrentInputMethodSubtype(); 365 final CharSequence summary = subtype != null 366 ? subtype.getDisplayName(context, imi.getPackageName(), 367 imi.getServiceInfo().applicationInfo) 368 : context.getString(R.string.quick_settings_ime_label); 369 return summary.toString(); 370 } 371 } 372 return null; 373 } 374 375}