blob: f981eeb8912045f956dbd2e9b2625967b9442f4e [file] [log] [blame]
Winson Chungd63c59782012-09-05 17:34:41 -07001/*
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
Adam Powell6f2a3d22012-10-05 22:32:04 -070019import com.android.internal.view.RotationPolicy;
20import com.android.internal.widget.LockPatternUtils;
21import com.android.systemui.R;
22import com.android.systemui.statusbar.phone.QuickSettingsModel.RSSIState;
23import com.android.systemui.statusbar.phone.QuickSettingsModel.State;
24import com.android.systemui.statusbar.phone.QuickSettingsModel.UserState;
25import com.android.systemui.statusbar.policy.BatteryController;
26import com.android.systemui.statusbar.policy.BluetoothController;
27import com.android.systemui.statusbar.policy.BrightnessController;
28import com.android.systemui.statusbar.policy.LocationController;
29import com.android.systemui.statusbar.policy.NetworkController;
30import com.android.systemui.statusbar.policy.ToggleSlider;
31
Daniel Sandler3ffdcc72012-09-23 14:31:48 -040032import android.app.ActivityManagerNative;
Daniel Sandlerc19d4482012-09-19 16:26:39 -040033import android.app.AlertDialog;
Jeff Brown508257b2012-09-08 23:15:12 -070034import android.app.Dialog;
Winson Chung43229d72012-09-12 18:04:18 -070035import android.app.PendingIntent;
Chris Wrenb2a7d272012-10-03 10:16:51 -040036import android.bluetooth.BluetoothAdapter;
Jeff Brown508257b2012-09-08 23:15:12 -070037import android.content.BroadcastReceiver;
Winson Chunge641b6a2012-09-10 17:30:27 -070038import android.content.ComponentName;
Winson Chungd63c59782012-09-05 17:34:41 -070039import android.content.Context;
40import android.content.CursorLoader;
Winson Chung1679b362012-09-10 20:08:01 -070041import android.content.DialogInterface;
Daniel Sandlerc19d4482012-09-19 16:26:39 -040042import android.content.DialogInterface.OnClickListener;
Winson Chungd63c59782012-09-05 17:34:41 -070043import android.content.Intent;
Jeff Brown508257b2012-09-08 23:15:12 -070044import android.content.IntentFilter;
Adam Powell6f2a3d22012-10-05 22:32:04 -070045import android.content.pm.PackageManager.NameNotFoundException;
46import android.content.pm.UserInfo;
Winson Chungd63c59782012-09-05 17:34:41 -070047import android.content.res.Resources;
48import android.database.Cursor;
Adam Powell6f2a3d22012-10-05 22:32:04 -070049import android.graphics.Bitmap;
Winson Chungefba3232012-09-27 16:56:42 -070050import android.graphics.drawable.BitmapDrawable;
Winson Chungeaa5ab02012-09-13 16:36:41 -070051import android.graphics.drawable.Drawable;
52import android.graphics.drawable.LevelListDrawable;
Jeff Brown508257b2012-09-08 23:15:12 -070053import android.hardware.display.DisplayManager;
Jeff Brown508257b2012-09-08 23:15:12 -070054import android.hardware.display.WifiDisplayStatus;
Adam Powell6f2a3d22012-10-05 22:32:04 -070055import android.os.AsyncTask;
Winson Chung3ed6f942012-09-20 16:07:11 -070056import android.os.Handler;
Daniel Sandler3ffdcc72012-09-23 14:31:48 -040057import android.os.RemoteException;
Winson Chung34563e22012-09-21 17:19:49 -070058import android.os.UserHandle;
Winson Chungefba3232012-09-27 16:56:42 -070059import android.os.UserManager;
Winson Chungd63c59782012-09-05 17:34:41 -070060import android.provider.ContactsContract;
Adam Powell6f2a3d22012-10-05 22:32:04 -070061import android.provider.ContactsContract.CommonDataKinds.Phone;
62import android.provider.ContactsContract.Profile;
Winson Chung43229d72012-09-12 18:04:18 -070063import android.provider.Settings;
Adam Powell6f2a3d22012-10-05 22:32:04 -070064import android.util.Log;
65import android.util.Pair;
Winson Chungd63c59782012-09-05 17:34:41 -070066import android.view.LayoutInflater;
67import android.view.View;
68import android.view.ViewGroup;
Winson Chung1679b362012-09-10 20:08:01 -070069import android.view.Window;
Jeff Brown508257b2012-09-08 23:15:12 -070070import android.view.WindowManager;
Adam Powell6f2a3d22012-10-05 22:32:04 -070071import android.view.WindowManagerGlobal;
Winson Chungeaa5ab02012-09-13 16:36:41 -070072import android.widget.ImageView;
Winson Chungd63c59782012-09-05 17:34:41 -070073import android.widget.TextView;
74
Winson Chunge641b6a2012-09-10 17:30:27 -070075import java.util.ArrayList;
Winson Chungd63c59782012-09-05 17:34:41 -070076
Winson Chungd63c59782012-09-05 17:34:41 -070077
78/**
79 *
80 */
81class QuickSettings {
Adam Powell6f2a3d22012-10-05 22:32:04 -070082 private static final String TAG = "QuickSettings";
Daniel Sandlerdd68da82012-10-01 10:19:09 -040083 public static final boolean SHOW_IME_TILE = false;
Winson Chungd63c59782012-09-05 17:34:41 -070084
85 private Context mContext;
86 private PanelBar mBar;
87 private QuickSettingsModel mModel;
88 private QuickSettingsContainerView mContainerView;
89
Jeff Brown508257b2012-09-08 23:15:12 -070090 private DisplayManager mDisplayManager;
91 private WifiDisplayStatus mWifiDisplayStatus;
Daniel Sandler3ffdcc72012-09-23 14:31:48 -040092 private PhoneStatusBar mStatusBarService;
Chris Wrenb2a7d272012-10-03 10:16:51 -040093 private QuickSettingsModel.BluetoothState mBluetoothState;
Jeff Brown89d55462012-09-19 11:33:42 -070094
Winson Chung1679b362012-09-10 20:08:01 -070095 private BrightnessController mBrightnessController;
Winson Chung5f623012012-09-14 14:58:43 -070096 private BluetoothController mBluetoothController;
Winson Chung3ed6f942012-09-20 16:07:11 -070097
Winson Chung1679b362012-09-10 20:08:01 -070098 private Dialog mBrightnessDialog;
Winson Chung3ed6f942012-09-20 16:07:11 -070099 private int mBrightnessDialogShortTimeout;
100 private int mBrightnessDialogLongTimeout;
Jeff Brown508257b2012-09-08 23:15:12 -0700101
Adam Powell6f2a3d22012-10-05 22:32:04 -0700102 private AsyncTask<Void, Void, Pair<String, BitmapDrawable>> mUserInfoTask;
Winson Chungd63c59782012-09-05 17:34:41 -0700103
Winson Chungeaa5ab02012-09-13 16:36:41 -0700104 private LevelListDrawable mBatteryLevels;
105 private LevelListDrawable mChargingBatteryLevels;
106
Adam Powell6f2a3d22012-10-05 22:32:04 -0700107 boolean mTilesSetUp = false;
108
Winson Chung3ed6f942012-09-20 16:07:11 -0700109 private Handler mHandler;
110
Winson Chungd63c59782012-09-05 17:34:41 -0700111 // The set of QuickSettingsTiles that have dynamic spans (and need to be updated on
112 // configuration change)
113 private final ArrayList<QuickSettingsTileView> mDynamicSpannedTiles =
114 new ArrayList<QuickSettingsTileView>();
115
Winson Chungd4726d02012-09-14 12:27:29 -0700116 private final RotationPolicy.RotationPolicyListener mRotationPolicyListener =
117 new RotationPolicy.RotationPolicyListener() {
118 @Override
119 public void onChange() {
120 mModel.onRotationLockChanged();
121 }
122 };
123
Winson Chungd63c59782012-09-05 17:34:41 -0700124 public QuickSettings(Context context, QuickSettingsContainerView container) {
Jeff Brown508257b2012-09-08 23:15:12 -0700125 mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
Winson Chungd63c59782012-09-05 17:34:41 -0700126 mContext = context;
Winson Chungd63c59782012-09-05 17:34:41 -0700127 mContainerView = container;
Jeff Brown508257b2012-09-08 23:15:12 -0700128 mModel = new QuickSettingsModel(context);
129 mWifiDisplayStatus = new WifiDisplayStatus();
Chris Wrenb2a7d272012-10-03 10:16:51 -0400130 mBluetoothState = new QuickSettingsModel.BluetoothState();
Winson Chung3ed6f942012-09-20 16:07:11 -0700131 mHandler = new Handler();
Jeff Brown508257b2012-09-08 23:15:12 -0700132
Winson Chungeaa5ab02012-09-13 16:36:41 -0700133 Resources r = mContext.getResources();
134 mBatteryLevels = (LevelListDrawable) r.getDrawable(R.drawable.qs_sys_battery);
135 mChargingBatteryLevels =
136 (LevelListDrawable) r.getDrawable(R.drawable.qs_sys_battery_charging);
Winson Chung3ed6f942012-09-20 16:07:11 -0700137 mBrightnessDialogLongTimeout =
138 r.getInteger(R.integer.quick_settings_brightness_dialog_long_timeout);
139 mBrightnessDialogShortTimeout =
140 r.getInteger(R.integer.quick_settings_brightness_dialog_short_timeout);
Winson Chungeaa5ab02012-09-13 16:36:41 -0700141
Jeff Brown508257b2012-09-08 23:15:12 -0700142 IntentFilter filter = new IntentFilter();
143 filter.addAction(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED);
Chris Wrenb2a7d272012-10-03 10:16:51 -0400144 filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
Adam Powell6f2a3d22012-10-05 22:32:04 -0700145 filter.addAction(Intent.ACTION_USER_SWITCHED);
Jeff Brown508257b2012-09-08 23:15:12 -0700146 mContext.registerReceiver(mReceiver, filter);
Adam Powell6f2a3d22012-10-05 22:32:04 -0700147
148 IntentFilter profileFilter = new IntentFilter();
149 profileFilter.addAction(ContactsContract.Intents.ACTION_PROFILE_CHANGED);
150 profileFilter.addAction(Intent.ACTION_USER_INFO_CHANGED);
151 mContext.registerReceiverAsUser(mProfileReceiver, UserHandle.ALL, profileFilter,
152 null, null);
Winson Chungd63c59782012-09-05 17:34:41 -0700153 }
154
155 void setBar(PanelBar bar) {
156 mBar = bar;
157 }
158
Daniel Sandler3ffdcc72012-09-23 14:31:48 -0400159 public void setService(PhoneStatusBar phoneStatusBar) {
160 mStatusBarService = phoneStatusBar;
161 }
162
163 public PhoneStatusBar getService() {
164 return mStatusBarService;
165 }
166
Winson Chung43229d72012-09-12 18:04:18 -0700167 public void setImeWindowStatus(boolean visible) {
168 mModel.onImeWindowStatusChanged(visible);
169 }
170
Winson Chungd63c59782012-09-05 17:34:41 -0700171 void setup(NetworkController networkController, BluetoothController bluetoothController,
172 BatteryController batteryController, LocationController locationController) {
Winson Chung5f623012012-09-14 14:58:43 -0700173 mBluetoothController = bluetoothController;
174
175 setupQuickSettings();
176 updateWifiDisplayStatus();
177 updateResources();
178
Winson Chungd63c59782012-09-05 17:34:41 -0700179 networkController.addNetworkSignalChangedCallback(mModel);
180 bluetoothController.addStateChangedCallback(mModel);
181 batteryController.addStateChangedCallback(mModel);
182 locationController.addStateChangedCallback(mModel);
Christopher Tate5e08af02012-09-21 17:17:22 -0700183 RotationPolicy.registerRotationPolicyListener(mContext, mRotationPolicyListener,
184 UserHandle.USER_ALL);
Winson Chungd63c59782012-09-05 17:34:41 -0700185 }
186
187 private void queryForUserInformation() {
Adam Powell6f2a3d22012-10-05 22:32:04 -0700188 Context currentUserContext = null;
189 UserInfo userInfo = null;
190 try {
191 userInfo = ActivityManagerNative.getDefault().getCurrentUser();
192 currentUserContext = mContext.createPackageContextAsUser("android", 0,
193 new UserHandle(userInfo.id));
194 } catch (NameNotFoundException e) {
195 Log.e(TAG, "Couldn't create user context", e);
196 throw new RuntimeException(e);
197 } catch (RemoteException e) {
198 Log.e(TAG, "Couldn't get user info", e);
199 }
200 final int userId = userInfo.id;
Winson Chungefba3232012-09-27 16:56:42 -0700201
Adam Powell6f2a3d22012-10-05 22:32:04 -0700202 final Context context = currentUserContext;
203 mUserInfoTask = new AsyncTask<Void, Void, Pair<String, BitmapDrawable>>() {
204 @Override
205 protected Pair<String, BitmapDrawable> doInBackground(Void... params) {
206 Cursor cursor = context.getContentResolver().query(
207 Profile.CONTENT_URI, new String[] {Phone._ID, Phone.DISPLAY_NAME},
208 null, null, null);
Winson Chungd63c59782012-09-05 17:34:41 -0700209
Adam Powell6f2a3d22012-10-05 22:32:04 -0700210 String name = null;
211 try {
212 if (cursor.moveToFirst()) {
213 name = cursor.getString(cursor.getColumnIndex(Phone.DISPLAY_NAME));
Winson Chungd63c59782012-09-05 17:34:41 -0700214 }
Adam Powell6f2a3d22012-10-05 22:32:04 -0700215 } finally {
216 cursor.close();
217 }
218 final UserManager userManager =
219 (UserManager) mContext.getSystemService(Context.USER_SERVICE);
220 final BitmapDrawable icon = new BitmapDrawable(mContext.getResources(),
221 userManager.getUserIcon(userId));
222 return new Pair<String, BitmapDrawable>(name, icon);
223 }
224
225 @Override
226 protected void onPostExecute(Pair<String, BitmapDrawable> result) {
227 super.onPostExecute(result);
228 mModel.setUserTileInfo(result.first, result.second);
229 mUserInfoTask = null;
230 }
231 };
232 mUserInfoTask.execute();
Winson Chungd63c59782012-09-05 17:34:41 -0700233 }
234
235 private void setupQuickSettings() {
236 // Setup the tiles that we are going to be showing (including the temporary ones)
237 LayoutInflater inflater = LayoutInflater.from(mContext);
238
239 addUserTiles(mContainerView, inflater);
240 addSystemTiles(mContainerView, inflater);
241 addTemporaryTiles(mContainerView, inflater);
242
243 queryForUserInformation();
Adam Powell6f2a3d22012-10-05 22:32:04 -0700244 mTilesSetUp = true;
Winson Chungd63c59782012-09-05 17:34:41 -0700245 }
246
Winson Chunge641b6a2012-09-10 17:30:27 -0700247 private void startSettingsActivity(String action) {
248 Intent intent = new Intent(action);
249 startSettingsActivity(intent);
250 }
Daniel Sandler3ffdcc72012-09-23 14:31:48 -0400251
Winson Chunge641b6a2012-09-10 17:30:27 -0700252 private void startSettingsActivity(Intent intent) {
Daniel Sandler3ffdcc72012-09-23 14:31:48 -0400253 startSettingsActivity(intent, true);
254 }
255
256 private void startSettingsActivity(Intent intent, boolean onlyProvisioned) {
257 if (onlyProvisioned && !getService().isDeviceProvisioned()) return;
258 try {
259 // Dismiss the lock screen when Settings starts.
260 ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
261 } catch (RemoteException e) {
262 }
Winson Chung6072b002012-09-11 17:10:10 -0700263 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
Michael Jurka09885242012-09-24 14:42:01 -0700264 mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
Daniel Sandler11cf1782012-09-27 14:03:08 -0400265 getService().animateCollapsePanels();
Winson Chunge641b6a2012-09-10 17:30:27 -0700266 }
267
Winson Chungd63c59782012-09-05 17:34:41 -0700268 private void addUserTiles(ViewGroup parent, LayoutInflater inflater) {
269 QuickSettingsTileView userTile = (QuickSettingsTileView)
270 inflater.inflate(R.layout.quick_settings_tile, parent, false);
271 userTile.setContent(R.layout.quick_settings_tile_user, inflater);
Winson Chung3ed6f942012-09-20 16:07:11 -0700272 userTile.setOnClickListener(new View.OnClickListener() {
273 @Override
274 public void onClick(View v) {
275 mBar.collapseAllPanels(true);
Adam Powell6f2a3d22012-10-05 22:32:04 -0700276 final UserManager um =
277 (UserManager) mContext.getSystemService(Context.USER_SERVICE);
278 if (um.getUsers().size() > 1) {
279 try {
280 WindowManagerGlobal.getWindowManagerService().lockNow(
281 LockPatternUtils.USER_SWITCH_LOCK_OPTIONS);
282 } catch (RemoteException e) {
283 Log.e(TAG, "Couldn't show user switcher", e);
284 }
285 } else {
286 Intent intent = ContactsContract.QuickContact.composeQuickContactsIntent(
287 mContext, v, ContactsContract.Profile.CONTENT_URI,
288 ContactsContract.QuickContact.MODE_LARGE, null);
289 mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
290 }
Winson Chung3ed6f942012-09-20 16:07:11 -0700291 }
292 });
Winson Chungd63c59782012-09-05 17:34:41 -0700293 mModel.addUserTile(userTile, new QuickSettingsModel.RefreshCallback() {
294 @Override
295 public void refreshView(QuickSettingsTileView view, State state) {
Winson Chungeaa5ab02012-09-13 16:36:41 -0700296 UserState us = (UserState) state;
Winson Chungefba3232012-09-27 16:56:42 -0700297 ImageView iv = (ImageView) view.findViewById(R.id.user_imageview);
Winson Chungd63c59782012-09-05 17:34:41 -0700298 TextView tv = (TextView) view.findViewById(R.id.user_textview);
299 tv.setText(state.label);
Winson Chungeaa5ab02012-09-13 16:36:41 -0700300 if (us.avatar != null) {
Winson Chungefba3232012-09-27 16:56:42 -0700301 iv.setImageDrawable(us.avatar);
Winson Chungeaa5ab02012-09-13 16:36:41 -0700302 }
Winson Chungd63c59782012-09-05 17:34:41 -0700303 }
304 });
305 parent.addView(userTile);
306 mDynamicSpannedTiles.add(userTile);
307
308 // Time tile
309 QuickSettingsTileView timeTile = (QuickSettingsTileView)
310 inflater.inflate(R.layout.quick_settings_tile, parent, false);
311 timeTile.setContent(R.layout.quick_settings_tile_time, inflater);
Winson Chunge641b6a2012-09-10 17:30:27 -0700312 timeTile.setOnClickListener(new View.OnClickListener() {
313 @Override
314 public void onClick(View v) {
Daniel Sandler2e7d25b2012-10-01 16:43:26 -0400315 // Quick. Clock. Quick. Clock. Quick. Clock.
316 startSettingsActivity(Intent.ACTION_QUICK_CLOCK);
Winson Chunge641b6a2012-09-10 17:30:27 -0700317 }
318 });
319 mModel.addTimeTile(timeTile, new QuickSettingsModel.RefreshCallback() {
320 @Override
Winson Chungc86b23b2012-09-24 11:24:28 -0700321 public void refreshView(QuickSettingsTileView view, State alarmState) {}
Winson Chunge641b6a2012-09-10 17:30:27 -0700322 });
Winson Chungd63c59782012-09-05 17:34:41 -0700323 parent.addView(timeTile);
324 mDynamicSpannedTiles.add(timeTile);
325
326 // Settings tile
327 QuickSettingsTileView settingsTile = (QuickSettingsTileView)
328 inflater.inflate(R.layout.quick_settings_tile, parent, false);
329 settingsTile.setContent(R.layout.quick_settings_tile_settings, inflater);
330 settingsTile.setOnClickListener(new View.OnClickListener() {
331 @Override
332 public void onClick(View v) {
Winson Chunge641b6a2012-09-10 17:30:27 -0700333 startSettingsActivity(android.provider.Settings.ACTION_SETTINGS);
Winson Chungd63c59782012-09-05 17:34:41 -0700334 }
335 });
Winson Chungefba3232012-09-27 16:56:42 -0700336 mModel.addSettingsTile(settingsTile, new QuickSettingsModel.RefreshCallback() {
337 @Override
338 public void refreshView(QuickSettingsTileView view, State state) {
339 TextView tv = (TextView) view.findViewById(R.id.settings_tileview);
340 tv.setText(state.label);
341 }
342 });
Winson Chungd63c59782012-09-05 17:34:41 -0700343 parent.addView(settingsTile);
344 mDynamicSpannedTiles.add(settingsTile);
345 }
346
347 private void addSystemTiles(ViewGroup parent, LayoutInflater inflater) {
348 // Wi-fi
349 QuickSettingsTileView wifiTile = (QuickSettingsTileView)
350 inflater.inflate(R.layout.quick_settings_tile, parent, false);
351 wifiTile.setContent(R.layout.quick_settings_tile_wifi, inflater);
352 wifiTile.setOnClickListener(new View.OnClickListener() {
353 @Override
354 public void onClick(View v) {
Winson Chunge641b6a2012-09-10 17:30:27 -0700355 startSettingsActivity(android.provider.Settings.ACTION_WIFI_SETTINGS);
Winson Chungd63c59782012-09-05 17:34:41 -0700356 }
357 });
358 mModel.addWifiTile(wifiTile, new QuickSettingsModel.RefreshCallback() {
359 @Override
360 public void refreshView(QuickSettingsTileView view, State state) {
361 TextView tv = (TextView) view.findViewById(R.id.wifi_textview);
Winson Chung5f623012012-09-14 14:58:43 -0700362 tv.setCompoundDrawablesWithIntrinsicBounds(0, state.iconId, 0, 0);
Winson Chungd63c59782012-09-05 17:34:41 -0700363 tv.setText(state.label);
364 }
365 });
366 parent.addView(wifiTile);
367
Winson Chung43229d72012-09-12 18:04:18 -0700368 if (mModel.deviceSupportsTelephony()) {
369 // RSSI
370 QuickSettingsTileView rssiTile = (QuickSettingsTileView)
371 inflater.inflate(R.layout.quick_settings_tile, parent, false);
372 rssiTile.setContent(R.layout.quick_settings_tile_rssi, inflater);
373 rssiTile.setOnClickListener(new View.OnClickListener() {
374 @Override
375 public void onClick(View v) {
376 Intent intent = new Intent();
377 intent.setComponent(new ComponentName(
378 "com.android.settings",
379 "com.android.settings.Settings$DataUsageSummaryActivity"));
380 startSettingsActivity(intent);
381 }
382 });
383 mModel.addRSSITile(rssiTile, new QuickSettingsModel.RefreshCallback() {
384 @Override
385 public void refreshView(QuickSettingsTileView view, State state) {
Winson Chung4f49d942012-09-14 14:01:40 -0700386 RSSIState rssiState = (RSSIState) state;
387 ImageView iv = (ImageView) view.findViewById(R.id.rssi_image);
388 ImageView iov = (ImageView) view.findViewById(R.id.rssi_overlay_image);
Winson Chung43229d72012-09-12 18:04:18 -0700389 TextView tv = (TextView) view.findViewById(R.id.rssi_textview);
Winson Chung4f49d942012-09-14 14:01:40 -0700390 iv.setImageResource(rssiState.signalIconId);
391 if (rssiState.dataTypeIconId > 0) {
392 iov.setImageResource(rssiState.dataTypeIconId);
393 } else {
394 iov.setImageDrawable(null);
395 }
Winson Chung43229d72012-09-12 18:04:18 -0700396 tv.setText(state.label);
397 }
398 });
399 parent.addView(rssiTile);
400 }
Winson Chungd63c59782012-09-05 17:34:41 -0700401
Winson Chungd4726d02012-09-14 12:27:29 -0700402 // Rotation Lock
403 if (mContext.getResources().getBoolean(R.bool.quick_settings_show_rotation_lock)) {
404 QuickSettingsTileView rotationLockTile = (QuickSettingsTileView)
405 inflater.inflate(R.layout.quick_settings_tile, parent, false);
406 rotationLockTile.setContent(R.layout.quick_settings_tile_rotation_lock, inflater);
407 rotationLockTile.setOnClickListener(new View.OnClickListener() {
408 @Override
409 public void onClick(View v) {
410 boolean locked = RotationPolicy.isRotationLocked(mContext);
411 RotationPolicy.setRotationLock(mContext, !locked);
412 }
413 });
414 mModel.addRotationLockTile(rotationLockTile, new QuickSettingsModel.RefreshCallback() {
415 @Override
416 public void refreshView(QuickSettingsTileView view, State state) {
417 TextView tv = (TextView) view.findViewById(R.id.rotation_lock_textview);
Winson Chung5f623012012-09-14 14:58:43 -0700418 tv.setCompoundDrawablesWithIntrinsicBounds(0, state.iconId, 0, 0);
Winson Chungd4726d02012-09-14 12:27:29 -0700419 tv.setText(state.label);
420 }
421 });
422 parent.addView(rotationLockTile);
423 }
424
Winson Chungd63c59782012-09-05 17:34:41 -0700425 // Battery
426 QuickSettingsTileView batteryTile = (QuickSettingsTileView)
427 inflater.inflate(R.layout.quick_settings_tile, parent, false);
428 batteryTile.setContent(R.layout.quick_settings_tile_battery, inflater);
429 batteryTile.setOnClickListener(new View.OnClickListener() {
430 @Override
431 public void onClick(View v) {
Winson Chunge641b6a2012-09-10 17:30:27 -0700432 startSettingsActivity(Intent.ACTION_POWER_USAGE_SUMMARY);
Winson Chungd63c59782012-09-05 17:34:41 -0700433 }
434 });
435 mModel.addBatteryTile(batteryTile, new QuickSettingsModel.RefreshCallback() {
436 @Override
437 public void refreshView(QuickSettingsTileView view, State state) {
438 QuickSettingsModel.BatteryState batteryState =
439 (QuickSettingsModel.BatteryState) state;
440 TextView tv = (TextView) view.findViewById(R.id.battery_textview);
Winson Chungeaa5ab02012-09-13 16:36:41 -0700441 ImageView iv = (ImageView) view.findViewById(R.id.battery_image);
442 Drawable d = batteryState.pluggedIn
443 ? mChargingBatteryLevels
444 : mBatteryLevels;
445 String t;
446 if (batteryState.batteryLevel == 100) {
447 t = mContext.getString(R.string.quick_settings_battery_charged_label);
448 } else {
449 t = batteryState.pluggedIn
450 ? mContext.getString(R.string.quick_settings_battery_charging_label,
451 batteryState.batteryLevel)
452 : mContext.getString(R.string.status_bar_settings_battery_meter_format,
453 batteryState.batteryLevel);
454 }
455 iv.setImageDrawable(d);
456 iv.setImageLevel(batteryState.batteryLevel);
457 tv.setText(t);
Winson Chungd63c59782012-09-05 17:34:41 -0700458 }
459 });
460 parent.addView(batteryTile);
461
462 // Airplane Mode
463 QuickSettingsTileView airplaneTile = (QuickSettingsTileView)
464 inflater.inflate(R.layout.quick_settings_tile, parent, false);
465 airplaneTile.setContent(R.layout.quick_settings_tile_airplane, inflater);
466 mModel.addAirplaneModeTile(airplaneTile, new QuickSettingsModel.RefreshCallback() {
467 @Override
468 public void refreshView(QuickSettingsTileView view, State state) {
469 TextView tv = (TextView) view.findViewById(R.id.airplane_mode_textview);
Winson Chung5f623012012-09-14 14:58:43 -0700470 tv.setCompoundDrawablesWithIntrinsicBounds(0, state.iconId, 0, 0);
Winson Chungefba3232012-09-27 16:56:42 -0700471 tv.setText(state.label);
Winson Chungd63c59782012-09-05 17:34:41 -0700472 }
473 });
474 parent.addView(airplaneTile);
475
476 // Bluetooth
Winson Chung6072b002012-09-11 17:10:10 -0700477 if (mModel.deviceSupportsBluetooth()) {
478 QuickSettingsTileView bluetoothTile = (QuickSettingsTileView)
479 inflater.inflate(R.layout.quick_settings_tile, parent, false);
480 bluetoothTile.setContent(R.layout.quick_settings_tile_bluetooth, inflater);
481 bluetoothTile.setOnClickListener(new View.OnClickListener() {
482 @Override
483 public void onClick(View v) {
484 startSettingsActivity(android.provider.Settings.ACTION_BLUETOOTH_SETTINGS);
485 }
486 });
487 mModel.addBluetoothTile(bluetoothTile, new QuickSettingsModel.RefreshCallback() {
488 @Override
489 public void refreshView(QuickSettingsTileView view, State state) {
490 TextView tv = (TextView) view.findViewById(R.id.bluetooth_textview);
Winson Chung5f623012012-09-14 14:58:43 -0700491 tv.setCompoundDrawablesWithIntrinsicBounds(0, state.iconId, 0, 0);
492
493 Resources r = mContext.getResources();
Winson Chung34563e22012-09-21 17:19:49 -0700494 String label = state.label;
Winson Chung5f623012012-09-14 14:58:43 -0700495 /*
496 //TODO: Show connected bluetooth device label
497 Set<BluetoothDevice> btDevices =
498 mBluetoothController.getBondedBluetoothDevices();
499 if (btDevices.size() == 1) {
500 // Show the name of the bluetooth device you are connected to
501 label = btDevices.iterator().next().getName();
502 } else if (btDevices.size() > 1) {
503 // Show a generic label about the number of bluetooth devices
504 label = r.getString(R.string.quick_settings_bluetooth_multiple_devices_label,
505 btDevices.size());
506 }
507 */
Winson Chung5f623012012-09-14 14:58:43 -0700508 tv.setText(label);
Winson Chung6072b002012-09-11 17:10:10 -0700509 }
510 });
511 parent.addView(bluetoothTile);
512 }
Winson Chungd63c59782012-09-05 17:34:41 -0700513
514 // Brightness
515 QuickSettingsTileView brightnessTile = (QuickSettingsTileView)
516 inflater.inflate(R.layout.quick_settings_tile, parent, false);
517 brightnessTile.setContent(R.layout.quick_settings_tile_brightness, inflater);
518 brightnessTile.setOnClickListener(new View.OnClickListener() {
519 @Override
520 public void onClick(View v) {
Winson Chung1679b362012-09-10 20:08:01 -0700521 mBar.collapseAllPanels(true);
522 showBrightnessDialog();
Winson Chungd63c59782012-09-05 17:34:41 -0700523 }
524 });
Winson Chung5f623012012-09-14 14:58:43 -0700525 mModel.addBrightnessTile(brightnessTile, new QuickSettingsModel.RefreshCallback() {
526 @Override
527 public void refreshView(QuickSettingsTileView view, State state) {
528 TextView tv = (TextView) view.findViewById(R.id.brightness_textview);
529 tv.setCompoundDrawablesWithIntrinsicBounds(0, state.iconId, 0, 0);
Winson Chungefba3232012-09-27 16:56:42 -0700530 tv.setText(state.label);
Winson Chung3ed6f942012-09-20 16:07:11 -0700531 dismissBrightnessDialog(mBrightnessDialogShortTimeout);
Winson Chung5f623012012-09-14 14:58:43 -0700532 }
533 });
Winson Chungd63c59782012-09-05 17:34:41 -0700534 parent.addView(brightnessTile);
535 }
536
537 private void addTemporaryTiles(final ViewGroup parent, final LayoutInflater inflater) {
Winson Chungc86b23b2012-09-24 11:24:28 -0700538 // Alarm tile
539 QuickSettingsTileView alarmTile = (QuickSettingsTileView)
540 inflater.inflate(R.layout.quick_settings_tile, parent, false);
541 alarmTile.setContent(R.layout.quick_settings_tile_alarm, inflater);
542 alarmTile.setOnClickListener(new View.OnClickListener() {
543 @Override
544 public void onClick(View v) {
545 // TODO: Jump into the alarm application
546 Intent intent = new Intent();
547 intent.setComponent(new ComponentName(
548 "com.google.android.deskclock",
549 "com.android.deskclock.AlarmClock"));
550 startSettingsActivity(intent);
551 }
552 });
553 mModel.addAlarmTile(alarmTile, new QuickSettingsModel.RefreshCallback() {
554 @Override
555 public void refreshView(QuickSettingsTileView view, State alarmState) {
556 TextView tv = (TextView) view.findViewById(R.id.alarm_textview);
557 tv.setText(alarmState.label);
558 view.setVisibility(alarmState.enabled ? View.VISIBLE : View.GONE);
559 }
560 });
561 parent.addView(alarmTile);
562
Winson Chungd63c59782012-09-05 17:34:41 -0700563 // Location
564 QuickSettingsTileView locationTile = (QuickSettingsTileView)
565 inflater.inflate(R.layout.quick_settings_tile, parent, false);
566 locationTile.setContent(R.layout.quick_settings_tile_location, inflater);
567 locationTile.setOnClickListener(new View.OnClickListener() {
568 @Override
569 public void onClick(View v) {
Winson Chunge641b6a2012-09-10 17:30:27 -0700570 startSettingsActivity(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
Winson Chungd63c59782012-09-05 17:34:41 -0700571 }
572 });
573 mModel.addLocationTile(locationTile, new QuickSettingsModel.RefreshCallback() {
574 @Override
575 public void refreshView(QuickSettingsTileView view, State state) {
576 TextView tv = (TextView) view.findViewById(R.id.location_textview);
577 tv.setText(state.label);
Winson Chunge641b6a2012-09-10 17:30:27 -0700578 view.setVisibility(state.enabled ? View.VISIBLE : View.GONE);
Winson Chungd63c59782012-09-05 17:34:41 -0700579 }
580 });
581 parent.addView(locationTile);
582
Jeff Brown508257b2012-09-08 23:15:12 -0700583 // Wifi Display
584 QuickSettingsTileView wifiDisplayTile = (QuickSettingsTileView)
585 inflater.inflate(R.layout.quick_settings_tile, parent, false);
586 wifiDisplayTile.setContent(R.layout.quick_settings_tile_wifi_display, inflater);
587 wifiDisplayTile.setOnClickListener(new View.OnClickListener() {
588 @Override
589 public void onClick(View v) {
Jeff Brown89d55462012-09-19 11:33:42 -0700590 startSettingsActivity(android.provider.Settings.ACTION_WIFI_DISPLAY_SETTINGS);
Jeff Brown508257b2012-09-08 23:15:12 -0700591 }
592 });
593 mModel.addWifiDisplayTile(wifiDisplayTile, new QuickSettingsModel.RefreshCallback() {
594 @Override
595 public void refreshView(QuickSettingsTileView view, State state) {
596 TextView tv = (TextView) view.findViewById(R.id.wifi_display_textview);
597 tv.setText(state.label);
John Spurlock01e2f4f2012-10-05 17:33:31 -0400598 tv.setCompoundDrawablesWithIntrinsicBounds(0, state.iconId, 0, 0);
Winson Chunge641b6a2012-09-10 17:30:27 -0700599 view.setVisibility(state.enabled ? View.VISIBLE : View.GONE);
Jeff Brown508257b2012-09-08 23:15:12 -0700600 }
601 });
602 parent.addView(wifiDisplayTile);
603
Daniel Sandlerdd68da82012-10-01 10:19:09 -0400604 if (SHOW_IME_TILE) {
605 // IME
606 QuickSettingsTileView imeTile = (QuickSettingsTileView)
607 inflater.inflate(R.layout.quick_settings_tile, parent, false);
608 imeTile.setContent(R.layout.quick_settings_tile_ime, inflater);
609 imeTile.setOnClickListener(new View.OnClickListener() {
610 @Override
611 public void onClick(View v) {
612 try {
613 mBar.collapseAllPanels(true);
614 Intent intent = new Intent(Settings.ACTION_SHOW_INPUT_METHOD_PICKER);
615 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
616 pendingIntent.send();
617 } catch (Exception e) {}
Winson Chung2a4057d2012-09-12 18:30:06 -0700618 }
Daniel Sandlerdd68da82012-10-01 10:19:09 -0400619 });
620 mModel.addImeTile(imeTile, new QuickSettingsModel.RefreshCallback() {
621 @Override
622 public void refreshView(QuickSettingsTileView view, State state) {
623 TextView tv = (TextView) view.findViewById(R.id.ime_textview);
624 if (state.label != null) {
625 tv.setText(state.label);
626 }
627 view.setVisibility(state.enabled ? View.VISIBLE : View.GONE);
628 }
629 });
630 parent.addView(imeTile);
631 }
Winson Chung43229d72012-09-12 18:04:18 -0700632
Daniel Sandlerc19d4482012-09-19 16:26:39 -0400633 // Bug reports
634 QuickSettingsTileView bugreportTile = (QuickSettingsTileView)
635 inflater.inflate(R.layout.quick_settings_tile, parent, false);
636 bugreportTile.setContent(R.layout.quick_settings_tile_bugreport, inflater);
637 bugreportTile.setOnClickListener(new View.OnClickListener() {
638 @Override
639 public void onClick(View v) {
640 mBar.collapseAllPanels(true);
641 showBugreportDialog();
642 }
643 });
644 mModel.addBugreportTile(bugreportTile, new QuickSettingsModel.RefreshCallback() {
645 @Override
646 public void refreshView(QuickSettingsTileView view, State state) {
647 view.setVisibility(state.enabled ? View.VISIBLE : View.GONE);
648 }
649 });
650 parent.addView(bugreportTile);
Winson Chungd63c59782012-09-05 17:34:41 -0700651 /*
652 QuickSettingsTileView mediaTile = (QuickSettingsTileView)
653 inflater.inflate(R.layout.quick_settings_tile, parent, false);
654 mediaTile.setContent(R.layout.quick_settings_tile_media, inflater);
655 parent.addView(mediaTile);
656 QuickSettingsTileView imeTile = (QuickSettingsTileView)
657 inflater.inflate(R.layout.quick_settings_tile, parent, false);
658 imeTile.setContent(R.layout.quick_settings_tile_ime, inflater);
659 imeTile.setOnClickListener(new View.OnClickListener() {
660 @Override
661 public void onClick(View v) {
662 parent.removeViewAt(0);
663 }
664 });
665 parent.addView(imeTile);
666 */
667 }
668
669 void updateResources() {
670 Resources r = mContext.getResources();
671
Winson Chungefba3232012-09-27 16:56:42 -0700672 // Update the model
673 mModel.updateResources();
674
Winson Chungd63c59782012-09-05 17:34:41 -0700675 // Update the User, Time, and Settings tiles spans, and reset everything else
676 int span = r.getInteger(R.integer.quick_settings_user_time_settings_tile_span);
677 for (QuickSettingsTileView v : mDynamicSpannedTiles) {
678 v.setColumnSpan(span);
679 }
680 mContainerView.requestLayout();
Winson Chung3ed6f942012-09-20 16:07:11 -0700681
682 // Reset the dialog
683 boolean isBrightnessDialogVisible = false;
684 if (mBrightnessDialog != null) {
685 removeAllBrightnessDialogCallbacks();
686
687 isBrightnessDialogVisible = mBrightnessDialog.isShowing();
688 mBrightnessDialog.dismiss();
689 }
690 mBrightnessDialog = null;
691 if (isBrightnessDialogVisible) {
692 showBrightnessDialog();
693 }
Winson Chungd63c59782012-09-05 17:34:41 -0700694 }
Winson Chung1679b362012-09-10 20:08:01 -0700695
Winson Chung3ed6f942012-09-20 16:07:11 -0700696 private void removeAllBrightnessDialogCallbacks() {
697 mHandler.removeCallbacks(mDismissBrightnessDialogRunnable);
698 }
699
700 private Runnable mDismissBrightnessDialogRunnable = new Runnable() {
701 public void run() {
702 if (mBrightnessDialog != null && mBrightnessDialog.isShowing()) {
703 mBrightnessDialog.dismiss();
704 }
705 removeAllBrightnessDialogCallbacks();
706 };
707 };
708
Winson Chung1679b362012-09-10 20:08:01 -0700709 private void showBrightnessDialog() {
710 if (mBrightnessDialog == null) {
711 mBrightnessDialog = new Dialog(mContext);
712 mBrightnessDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
713 mBrightnessDialog.setContentView(R.layout.quick_settings_brightness_dialog);
714 mBrightnessDialog.setCanceledOnTouchOutside(true);
715
716 mBrightnessController = new BrightnessController(mContext,
717 (ToggleSlider) mBrightnessDialog.findViewById(R.id.brightness_slider));
Winson Chung5f623012012-09-14 14:58:43 -0700718 mBrightnessController.addStateChangedCallback(mModel);
Winson Chung1679b362012-09-10 20:08:01 -0700719 mBrightnessDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
720 @Override
721 public void onDismiss(DialogInterface dialog) {
722 mBrightnessController = null;
723 }
724 });
725
726 mBrightnessDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
727 mBrightnessDialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
728 }
729 if (!mBrightnessDialog.isShowing()) {
730 mBrightnessDialog.show();
Winson Chung3ed6f942012-09-20 16:07:11 -0700731 dismissBrightnessDialog(mBrightnessDialogLongTimeout);
732 }
733 }
734
735 private void dismissBrightnessDialog(int timeout) {
Winson Chungf4b5ab12012-09-24 16:47:46 -0700736 removeAllBrightnessDialogCallbacks();
Winson Chung3ed6f942012-09-20 16:07:11 -0700737 if (mBrightnessDialog != null) {
738 mHandler.postDelayed(mDismissBrightnessDialogRunnable, timeout);
Winson Chung1679b362012-09-10 20:08:01 -0700739 }
740 }
Jeff Brown508257b2012-09-08 23:15:12 -0700741
Daniel Sandlerc19d4482012-09-19 16:26:39 -0400742 private void showBugreportDialog() {
743 final AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
744 builder.setPositiveButton(com.android.internal.R.string.report, new OnClickListener() {
745 @Override
746 public void onClick(DialogInterface dialog, int which) {
747 if (which == DialogInterface.BUTTON_POSITIVE) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700748 // Add a little delay before executing, to give the
749 // dialog a chance to go away before it takes a
750 // screenshot.
751 mHandler.postDelayed(new Runnable() {
752 @Override public void run() {
753 try {
754 ActivityManagerNative.getDefault()
755 .requestBugReport();
756 } catch (RemoteException e) {
757 }
758 }
759 }, 500);
Daniel Sandlerc19d4482012-09-19 16:26:39 -0400760 }
761 }
762 });
763 builder.setMessage(com.android.internal.R.string.bugreport_message);
764 builder.setTitle(com.android.internal.R.string.bugreport_title);
765 builder.setCancelable(true);
766 final Dialog dialog = builder.create();
767 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
768 dialog.show();
769 }
770
Jeff Brown508257b2012-09-08 23:15:12 -0700771 private void updateWifiDisplayStatus() {
Jeff Brown89d55462012-09-19 11:33:42 -0700772 mWifiDisplayStatus = mDisplayManager.getWifiDisplayStatus();
773 applyWifiDisplayStatus();
Jeff Brown508257b2012-09-08 23:15:12 -0700774 }
775
Jeff Brown89d55462012-09-19 11:33:42 -0700776 private void applyWifiDisplayStatus() {
777 mModel.onWifiDisplayStateChanged(mWifiDisplayStatus);
Jeff Brown508257b2012-09-08 23:15:12 -0700778 }
779
Chris Wrenb2a7d272012-10-03 10:16:51 -0400780 private void applyBluetoothStatus() {
781 mModel.onBluetoothStateChange(mBluetoothState);
782 }
783
Adam Powell6f2a3d22012-10-05 22:32:04 -0700784 void reloadUserInfo() {
785 if (mUserInfoTask != null) {
786 mUserInfoTask.cancel(false);
787 mUserInfoTask = null;
788 }
789 if (mTilesSetUp) {
790 queryForUserInformation();
791 }
792 }
793
Jeff Brown508257b2012-09-08 23:15:12 -0700794 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
795 @Override
796 public void onReceive(Context context, Intent intent) {
Adam Powell6f2a3d22012-10-05 22:32:04 -0700797 final String action = intent.getAction();
798 if (DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED.equals(action)) {
Jeff Brown508257b2012-09-08 23:15:12 -0700799 WifiDisplayStatus status = (WifiDisplayStatus)intent.getParcelableExtra(
800 DisplayManager.EXTRA_WIFI_DISPLAY_STATUS);
Jeff Brown89d55462012-09-19 11:33:42 -0700801 mWifiDisplayStatus = status;
802 applyWifiDisplayStatus();
Adam Powell6f2a3d22012-10-05 22:32:04 -0700803 } else if (BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
Chris Wrenb2a7d272012-10-03 10:16:51 -0400804 int status = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
805 BluetoothAdapter.STATE_DISCONNECTED);
806 mBluetoothState.connected = (status == BluetoothAdapter.STATE_CONNECTED);
807 applyBluetoothStatus();
Adam Powell6f2a3d22012-10-05 22:32:04 -0700808 } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
809 reloadUserInfo();
810 }
811 }
812 };
813
814 private final BroadcastReceiver mProfileReceiver = new BroadcastReceiver() {
815 @Override
816 public void onReceive(Context context, Intent intent) {
817 final String action = intent.getAction();
818 if (ContactsContract.Intents.ACTION_PROFILE_CHANGED.equals(action) ||
819 Intent.ACTION_USER_INFO_CHANGED.equals(action)) {
820 try {
821 final int userId = ActivityManagerNative.getDefault().getCurrentUser().id;
822 if (getSendingUserId() == userId) {
823 reloadUserInfo();
824 }
825 } catch (RemoteException e) {
826 Log.e(TAG, "Couldn't get current user id for profile change", e);
827 }
Chris Wrenb2a7d272012-10-03 10:16:51 -0400828 }
Jeff Brown508257b2012-09-08 23:15:12 -0700829 }
830 };
Daniel Sandlerc19d4482012-09-19 16:26:39 -0400831}