blob: 4d7ff5e4e38bea843d70fed5bddeaf615ce9d523 [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
John Spurlock43670872013-09-05 16:50:21 -040019import android.animation.ValueAnimator;
Daniel Sandler3ffdcc72012-09-23 14:31:48 -040020import android.app.ActivityManagerNative;
Daniel Sandlerc19d4482012-09-19 16:26:39 -040021import android.app.AlertDialog;
Jeff Brown508257b2012-09-08 23:15:12 -070022import android.app.Dialog;
Winson Chung43229d72012-09-12 18:04:18 -070023import android.app.PendingIntent;
Geoffrey Borggaard348fc482013-08-08 14:32:39 -040024import android.app.admin.DevicePolicyManager;
Chris Wrenb2a7d272012-10-03 10:16:51 -040025import android.bluetooth.BluetoothAdapter;
Jeff Brown508257b2012-09-08 23:15:12 -070026import android.content.BroadcastReceiver;
Winson Chunge641b6a2012-09-10 17:30:27 -070027import android.content.ComponentName;
Alan Viveretteda0cc3e2013-09-26 13:11:54 -070028import android.content.ContentResolver;
Winson Chungd63c59782012-09-05 17:34:41 -070029import android.content.Context;
Winson Chung1679b362012-09-10 20:08:01 -070030import android.content.DialogInterface;
Daniel Sandlerc19d4482012-09-19 16:26:39 -040031import android.content.DialogInterface.OnClickListener;
Winson Chungd63c59782012-09-05 17:34:41 -070032import android.content.Intent;
Jeff Brown508257b2012-09-08 23:15:12 -070033import android.content.IntentFilter;
Adam Powell6f2a3d22012-10-05 22:32:04 -070034import android.content.pm.PackageManager.NameNotFoundException;
35import android.content.pm.UserInfo;
Winson Chungd63c59782012-09-05 17:34:41 -070036import android.content.res.Resources;
37import android.database.Cursor;
Adam Powell6f2a3d22012-10-05 22:32:04 -070038import android.graphics.Bitmap;
Winson Chungefba3232012-09-27 16:56:42 -070039import android.graphics.drawable.BitmapDrawable;
Winson Chungeaa5ab02012-09-13 16:36:41 -070040import android.graphics.drawable.Drawable;
Jeff Brown508257b2012-09-08 23:15:12 -070041import android.hardware.display.DisplayManager;
Jeff Brown0abd3a62013-11-09 17:48:23 -080042import android.media.MediaRouter;
Daniel Sandlerab510022012-10-22 22:13:35 -040043import android.net.wifi.WifiManager;
Adam Powell6f2a3d22012-10-05 22:32:04 -070044import android.os.AsyncTask;
Winson Chung3ed6f942012-09-20 16:07:11 -070045import android.os.Handler;
Daniel Sandler3ffdcc72012-09-23 14:31:48 -040046import android.os.RemoteException;
Winson Chung34563e22012-09-21 17:19:49 -070047import android.os.UserHandle;
Winson Chungefba3232012-09-27 16:56:42 -070048import android.os.UserManager;
Satoshi Kataokac44f7a22013-05-22 08:54:56 +090049import android.provider.AlarmClock;
Winson Chungd63c59782012-09-05 17:34:41 -070050import android.provider.ContactsContract;
Adam Powell6f2a3d22012-10-05 22:32:04 -070051import android.provider.ContactsContract.CommonDataKinds.Phone;
52import android.provider.ContactsContract.Profile;
Winson Chung43229d72012-09-12 18:04:18 -070053import android.provider.Settings;
Geoffrey Borggaard348fc482013-08-08 14:32:39 -040054import android.security.KeyChain;
Adam Powell6f2a3d22012-10-05 22:32:04 -070055import android.util.Log;
56import android.util.Pair;
Winson Chungd63c59782012-09-05 17:34:41 -070057import android.view.LayoutInflater;
58import android.view.View;
59import android.view.ViewGroup;
Jeff Brown508257b2012-09-08 23:15:12 -070060import android.view.WindowManager;
Adam Powell6f2a3d22012-10-05 22:32:04 -070061import android.view.WindowManagerGlobal;
Winson Chungeaa5ab02012-09-13 16:36:41 -070062import android.widget.ImageView;
Winson Chungd63c59782012-09-05 17:34:41 -070063import android.widget.TextView;
64
Jeff Brown0abd3a62013-11-09 17:48:23 -080065import com.android.internal.app.MediaRouteDialogPresenter;
John Spurlockde84f0e2013-06-12 12:41:00 -040066import com.android.systemui.R;
John Spurlock43670872013-09-05 16:50:21 -040067import com.android.systemui.statusbar.phone.QuickSettingsModel.ActivityState;
John Spurlockde84f0e2013-06-12 12:41:00 -040068import com.android.systemui.statusbar.phone.QuickSettingsModel.BluetoothState;
69import com.android.systemui.statusbar.phone.QuickSettingsModel.RSSIState;
70import com.android.systemui.statusbar.phone.QuickSettingsModel.State;
71import com.android.systemui.statusbar.phone.QuickSettingsModel.UserState;
72import com.android.systemui.statusbar.phone.QuickSettingsModel.WifiState;
73import com.android.systemui.statusbar.policy.BatteryController;
74import com.android.systemui.statusbar.policy.BluetoothController;
75import com.android.systemui.statusbar.policy.LocationController;
76import com.android.systemui.statusbar.policy.NetworkController;
77import com.android.systemui.statusbar.policy.RotationLockController;
78
Winson Chunge641b6a2012-09-10 17:30:27 -070079import java.util.ArrayList;
Winson Chungd63c59782012-09-05 17:34:41 -070080
Winson Chungd63c59782012-09-05 17:34:41 -070081/**
82 *
83 */
84class QuickSettings {
Daniel Sandlerb5538e62013-04-12 15:16:53 -040085 static final boolean DEBUG_GONE_TILES = false;
Adam Powell6f2a3d22012-10-05 22:32:04 -070086 private static final String TAG = "QuickSettings";
Daniel Sandlerdd68da82012-10-01 10:19:09 -040087 public static final boolean SHOW_IME_TILE = false;
Alan Viveretteda0cc3e2013-09-26 13:11:54 -070088 public static final boolean SHOW_ACCESSIBILITY_TILES = true;
Winson Chungd63c59782012-09-05 17:34:41 -070089
Daniel Sandlerab510022012-10-22 22:13:35 -040090 public static final boolean LONG_PRESS_TOGGLES = true;
91
Winson Chungd63c59782012-09-05 17:34:41 -070092 private Context mContext;
93 private PanelBar mBar;
94 private QuickSettingsModel mModel;
Daniel Sandler101784e2012-10-15 13:39:38 -040095 private ViewGroup mContainerView;
Winson Chungd63c59782012-09-05 17:34:41 -070096
Geoffrey Borggaard348fc482013-08-08 14:32:39 -040097 private DevicePolicyManager mDevicePolicyManager;
Daniel Sandler3ffdcc72012-09-23 14:31:48 -040098 private PhoneStatusBar mStatusBarService;
Casey Burkhardtbac221f2012-10-03 18:13:58 -070099 private BluetoothState mBluetoothState;
Daniel Sandlerab510022012-10-22 22:13:35 -0400100 private BluetoothAdapter mBluetoothAdapter;
101 private WifiManager mWifiManager;
Jeff Brown89d55462012-09-19 11:33:42 -0700102
Winson Chung5f623012012-09-14 14:58:43 -0700103 private BluetoothController mBluetoothController;
Svetoslav79578b22013-04-29 16:55:57 -0700104 private RotationLockController mRotationLockController;
David Christie03ed0122013-07-30 18:11:23 -0700105 private LocationController mLocationController;
Winson Chung3ed6f942012-09-20 16:07:11 -0700106
Winson Chung7a6355b2012-10-08 18:19:09 -0700107 private AsyncTask<Void, Void, Pair<String, Drawable>> mUserInfoTask;
Geoffrey Borggaard348fc482013-08-08 14:32:39 -0400108 private AsyncTask<Void, Void, Pair<Boolean, Boolean>> mQueryCertTask;
Winson Chungd63c59782012-09-05 17:34:41 -0700109
Adam Powell6f2a3d22012-10-05 22:32:04 -0700110 boolean mTilesSetUp = false;
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700111 boolean mUseDefaultAvatar = false;
Adam Powell6f2a3d22012-10-05 22:32:04 -0700112
Winson Chung3ed6f942012-09-20 16:07:11 -0700113 private Handler mHandler;
114
Winson Chungd63c59782012-09-05 17:34:41 -0700115 // The set of QuickSettingsTiles that have dynamic spans (and need to be updated on
116 // configuration change)
117 private final ArrayList<QuickSettingsTileView> mDynamicSpannedTiles =
118 new ArrayList<QuickSettingsTileView>();
119
120 public QuickSettings(Context context, QuickSettingsContainerView container) {
Geoffrey Borggaard348fc482013-08-08 14:32:39 -0400121 mDevicePolicyManager
122 = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
Winson Chungd63c59782012-09-05 17:34:41 -0700123 mContext = context;
Winson Chungd63c59782012-09-05 17:34:41 -0700124 mContainerView = container;
Jeff Brown508257b2012-09-08 23:15:12 -0700125 mModel = new QuickSettingsModel(context);
Chris Wrenb2a7d272012-10-03 10:16:51 -0400126 mBluetoothState = new QuickSettingsModel.BluetoothState();
Daniel Sandlerab510022012-10-22 22:13:35 -0400127 mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
128 mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
129
Winson Chung3ed6f942012-09-20 16:07:11 -0700130 mHandler = new Handler();
Jeff Brown508257b2012-09-08 23:15:12 -0700131
132 IntentFilter filter = new IntentFilter();
133 filter.addAction(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED);
Chris Wrenb2a7d272012-10-03 10:16:51 -0400134 filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
Daniel Sandlerebaefec2012-10-17 11:37:42 -0400135 filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
Adam Powell6f2a3d22012-10-05 22:32:04 -0700136 filter.addAction(Intent.ACTION_USER_SWITCHED);
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700137 filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
Geoffrey Borggaard348fc482013-08-08 14:32:39 -0400138 filter.addAction(KeyChain.ACTION_STORAGE_CHANGED);
Jeff Brown508257b2012-09-08 23:15:12 -0700139 mContext.registerReceiver(mReceiver, filter);
Adam Powell6f2a3d22012-10-05 22:32:04 -0700140
141 IntentFilter profileFilter = new IntentFilter();
142 profileFilter.addAction(ContactsContract.Intents.ACTION_PROFILE_CHANGED);
143 profileFilter.addAction(Intent.ACTION_USER_INFO_CHANGED);
144 mContext.registerReceiverAsUser(mProfileReceiver, UserHandle.ALL, profileFilter,
145 null, null);
Winson Chungd63c59782012-09-05 17:34:41 -0700146 }
147
148 void setBar(PanelBar bar) {
149 mBar = bar;
150 }
151
Daniel Sandler3ffdcc72012-09-23 14:31:48 -0400152 public void setService(PhoneStatusBar phoneStatusBar) {
153 mStatusBarService = phoneStatusBar;
154 }
155
156 public PhoneStatusBar getService() {
157 return mStatusBarService;
158 }
159
Winson Chung43229d72012-09-12 18:04:18 -0700160 public void setImeWindowStatus(boolean visible) {
161 mModel.onImeWindowStatusChanged(visible);
162 }
163
Winson Chungd63c59782012-09-05 17:34:41 -0700164 void setup(NetworkController networkController, BluetoothController bluetoothController,
Svetoslav79578b22013-04-29 16:55:57 -0700165 BatteryController batteryController, LocationController locationController,
166 RotationLockController rotationLockController) {
Winson Chung5f623012012-09-14 14:58:43 -0700167 mBluetoothController = bluetoothController;
Svetoslav79578b22013-04-29 16:55:57 -0700168 mRotationLockController = rotationLockController;
David Christie03ed0122013-07-30 18:11:23 -0700169 mLocationController = locationController;
Winson Chung5f623012012-09-14 14:58:43 -0700170
171 setupQuickSettings();
Winson Chung5f623012012-09-14 14:58:43 -0700172 updateResources();
David Christie03ed0122013-07-30 18:11:23 -0700173 applyLocationEnabledStatus();
Winson Chung5f623012012-09-14 14:58:43 -0700174
Winson Chungd63c59782012-09-05 17:34:41 -0700175 networkController.addNetworkSignalChangedCallback(mModel);
176 bluetoothController.addStateChangedCallback(mModel);
177 batteryController.addStateChangedCallback(mModel);
David Christie03ed0122013-07-30 18:11:23 -0700178 locationController.addSettingsChangedCallback(mModel);
John Spurlock8ab172e2013-12-19 16:39:23 -0500179 if (rotationLockController != null) {
180 rotationLockController.addRotationLockControllerCallback(mModel);
181 }
Winson Chungd63c59782012-09-05 17:34:41 -0700182 }
183
Geoffrey Borggaard348fc482013-08-08 14:32:39 -0400184 private void queryForSslCaCerts() {
185 mQueryCertTask = new AsyncTask<Void, Void, Pair<Boolean, Boolean>>() {
186 @Override
187 protected Pair<Boolean, Boolean> doInBackground(Void... params) {
Maggie Benthall0469f412013-09-05 15:30:26 -0400188 boolean hasCert = DevicePolicyManager.hasAnyCaCertsInstalled();
Geoffrey Borggaard348fc482013-08-08 14:32:39 -0400189 boolean isManaged = mDevicePolicyManager.getDeviceOwner() != null;
190
191 return Pair.create(hasCert, isManaged);
192 }
193 @Override
194 protected void onPostExecute(Pair<Boolean, Boolean> result) {
195 super.onPostExecute(result);
196 boolean hasCert = result.first;
197 boolean isManaged = result.second;
198 mModel.setSslCaCertWarningTileInfo(hasCert, isManaged);
199 }
200 };
201 mQueryCertTask.execute();
202 }
203
Winson Chungd63c59782012-09-05 17:34:41 -0700204 private void queryForUserInformation() {
Adam Powell6f2a3d22012-10-05 22:32:04 -0700205 Context currentUserContext = null;
206 UserInfo userInfo = null;
207 try {
208 userInfo = ActivityManagerNative.getDefault().getCurrentUser();
209 currentUserContext = mContext.createPackageContextAsUser("android", 0,
210 new UserHandle(userInfo.id));
211 } catch (NameNotFoundException e) {
212 Log.e(TAG, "Couldn't create user context", e);
213 throw new RuntimeException(e);
214 } catch (RemoteException e) {
215 Log.e(TAG, "Couldn't get user info", e);
216 }
217 final int userId = userInfo.id;
Amith Yamasani7277d5d2012-10-30 14:32:45 -0700218 final String userName = userInfo.name;
Winson Chungefba3232012-09-27 16:56:42 -0700219
Adam Powell6f2a3d22012-10-05 22:32:04 -0700220 final Context context = currentUserContext;
Winson Chung7a6355b2012-10-08 18:19:09 -0700221 mUserInfoTask = new AsyncTask<Void, Void, Pair<String, Drawable>>() {
Adam Powell6f2a3d22012-10-05 22:32:04 -0700222 @Override
Winson Chung7a6355b2012-10-08 18:19:09 -0700223 protected Pair<String, Drawable> doInBackground(Void... params) {
Amith Yamasani27db4682013-03-30 17:07:47 -0700224 final UserManager um = UserManager.get(mContext);
Winson Chungd63c59782012-09-05 17:34:41 -0700225
Winson Chung7a6355b2012-10-08 18:19:09 -0700226 // Fall back to the UserManager nickname if we can't read the name from the local
227 // profile below.
Amith Yamasani7277d5d2012-10-30 14:32:45 -0700228 String name = userName;
Winson Chung7a6355b2012-10-08 18:19:09 -0700229 Drawable avatar = null;
230 Bitmap rawAvatar = um.getUserIcon(userId);
231 if (rawAvatar != null) {
232 avatar = new BitmapDrawable(mContext.getResources(), rawAvatar);
233 } else {
234 avatar = mContext.getResources().getDrawable(R.drawable.ic_qs_default_user);
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700235 mUseDefaultAvatar = true;
Adam Powelldb43f472012-10-07 15:40:00 -0700236 }
237
Amith Yamasani7277d5d2012-10-30 14:32:45 -0700238 // If it's a single-user device, get the profile name, since the nickname is not
239 // usually valid
240 if (um.getUsers().size() <= 1) {
241 // Try and read the display name from the local profile
242 final Cursor cursor = context.getContentResolver().query(
243 Profile.CONTENT_URI, new String[] {Phone._ID, Phone.DISPLAY_NAME},
244 null, null, null);
245 if (cursor != null) {
246 try {
247 if (cursor.moveToFirst()) {
248 name = cursor.getString(cursor.getColumnIndex(Phone.DISPLAY_NAME));
249 }
250 } finally {
251 cursor.close();
Winson Chung7a6355b2012-10-08 18:19:09 -0700252 }
Winson Chungd63c59782012-09-05 17:34:41 -0700253 }
Adam Powell6f2a3d22012-10-05 22:32:04 -0700254 }
Winson Chung7a6355b2012-10-08 18:19:09 -0700255 return new Pair<String, Drawable>(name, avatar);
Adam Powell6f2a3d22012-10-05 22:32:04 -0700256 }
257
258 @Override
Winson Chung7a6355b2012-10-08 18:19:09 -0700259 protected void onPostExecute(Pair<String, Drawable> result) {
Adam Powell6f2a3d22012-10-05 22:32:04 -0700260 super.onPostExecute(result);
261 mModel.setUserTileInfo(result.first, result.second);
262 mUserInfoTask = null;
263 }
264 };
265 mUserInfoTask.execute();
Winson Chungd63c59782012-09-05 17:34:41 -0700266 }
267
268 private void setupQuickSettings() {
269 // Setup the tiles that we are going to be showing (including the temporary ones)
270 LayoutInflater inflater = LayoutInflater.from(mContext);
271
272 addUserTiles(mContainerView, inflater);
273 addSystemTiles(mContainerView, inflater);
274 addTemporaryTiles(mContainerView, inflater);
275
276 queryForUserInformation();
Geoffrey Borggaard348fc482013-08-08 14:32:39 -0400277 queryForSslCaCerts();
Adam Powell6f2a3d22012-10-05 22:32:04 -0700278 mTilesSetUp = true;
Winson Chungd63c59782012-09-05 17:34:41 -0700279 }
280
Winson Chunge641b6a2012-09-10 17:30:27 -0700281 private void startSettingsActivity(String action) {
282 Intent intent = new Intent(action);
283 startSettingsActivity(intent);
284 }
Daniel Sandler3ffdcc72012-09-23 14:31:48 -0400285
Winson Chunge641b6a2012-09-10 17:30:27 -0700286 private void startSettingsActivity(Intent intent) {
Daniel Sandler3ffdcc72012-09-23 14:31:48 -0400287 startSettingsActivity(intent, true);
288 }
289
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400290 private void collapsePanels() {
291 getService().animateCollapsePanels();
292 }
293
Daniel Sandler3ffdcc72012-09-23 14:31:48 -0400294 private void startSettingsActivity(Intent intent, boolean onlyProvisioned) {
295 if (onlyProvisioned && !getService().isDeviceProvisioned()) return;
296 try {
297 // Dismiss the lock screen when Settings starts.
298 ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
299 } catch (RemoteException e) {
300 }
Winson Chung6072b002012-09-11 17:10:10 -0700301 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
Michael Jurka09885242012-09-24 14:42:01 -0700302 mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400303 collapsePanels();
Winson Chunge641b6a2012-09-10 17:30:27 -0700304 }
305
Winson Chungd63c59782012-09-05 17:34:41 -0700306 private void addUserTiles(ViewGroup parent, LayoutInflater inflater) {
307 QuickSettingsTileView userTile = (QuickSettingsTileView)
308 inflater.inflate(R.layout.quick_settings_tile, parent, false);
309 userTile.setContent(R.layout.quick_settings_tile_user, inflater);
Winson Chung3ed6f942012-09-20 16:07:11 -0700310 userTile.setOnClickListener(new View.OnClickListener() {
311 @Override
312 public void onClick(View v) {
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400313 collapsePanels();
Amith Yamasani27db4682013-03-30 17:07:47 -0700314 final UserManager um = UserManager.get(mContext);
Winson Chungada86cb2012-10-11 12:48:36 -0700315 if (um.getUsers(true).size() > 1) {
Jim Miller8a26b432013-10-30 15:23:46 -0700316 // Since keyguard and systemui were merged into the same process to save
317 // memory, they share the same Looper and graphics context. As a result,
318 // there's no way to allow concurrent animation while keyguard inflates.
319 // The workaround is to add a slight delay to allow the animation to finish.
320 mHandler.postDelayed(new Runnable() {
321 public void run() {
322 try {
323 WindowManagerGlobal.getWindowManagerService().lockNow(null);
324 } catch (RemoteException e) {
325 Log.e(TAG, "Couldn't show user switcher", e);
326 }
327 }
328 }, 400); // TODO: ideally this would be tied to the collapse of the panel
Adam Powell6f2a3d22012-10-05 22:32:04 -0700329 } else {
330 Intent intent = ContactsContract.QuickContact.composeQuickContactsIntent(
331 mContext, v, ContactsContract.Profile.CONTENT_URI,
332 ContactsContract.QuickContact.MODE_LARGE, null);
333 mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
334 }
Winson Chung3ed6f942012-09-20 16:07:11 -0700335 }
336 });
Winson Chungd63c59782012-09-05 17:34:41 -0700337 mModel.addUserTile(userTile, new QuickSettingsModel.RefreshCallback() {
338 @Override
339 public void refreshView(QuickSettingsTileView view, State state) {
Winson Chungeaa5ab02012-09-13 16:36:41 -0700340 UserState us = (UserState) state;
Winson Chungefba3232012-09-27 16:56:42 -0700341 ImageView iv = (ImageView) view.findViewById(R.id.user_imageview);
Winson Chungd63c59782012-09-05 17:34:41 -0700342 TextView tv = (TextView) view.findViewById(R.id.user_textview);
343 tv.setText(state.label);
Winson Chung7a6355b2012-10-08 18:19:09 -0700344 iv.setImageDrawable(us.avatar);
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700345 view.setContentDescription(mContext.getString(
346 R.string.accessibility_quick_settings_user, state.label));
Winson Chungd63c59782012-09-05 17:34:41 -0700347 }
348 });
349 parent.addView(userTile);
350 mDynamicSpannedTiles.add(userTile);
351
Daniel Sandler3679bf52012-10-16 21:30:28 -0400352 // Brightness
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400353 final QuickSettingsBasicTile brightnessTile
354 = new QuickSettingsBasicTile(mContext);
355 brightnessTile.setImageResource(R.drawable.ic_qs_brightness_auto_off);
Daniel Sandler3679bf52012-10-16 21:30:28 -0400356 brightnessTile.setOnClickListener(new View.OnClickListener() {
357 @Override
358 public void onClick(View v) {
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400359 collapsePanels();
Daniel Sandler3679bf52012-10-16 21:30:28 -0400360 showBrightnessDialog();
361 }
362 });
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400363 mModel.addBrightnessTile(brightnessTile,
364 new QuickSettingsModel.BasicRefreshCallback(brightnessTile));
Daniel Sandler3679bf52012-10-16 21:30:28 -0400365 parent.addView(brightnessTile);
366 mDynamicSpannedTiles.add(brightnessTile);
367
Winson Chungd63c59782012-09-05 17:34:41 -0700368 // Settings tile
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400369 final QuickSettingsBasicTile settingsTile = new QuickSettingsBasicTile(mContext);
370 settingsTile.setImageResource(R.drawable.ic_qs_settings);
Winson Chungd63c59782012-09-05 17:34:41 -0700371 settingsTile.setOnClickListener(new View.OnClickListener() {
372 @Override
373 public void onClick(View v) {
Winson Chunge641b6a2012-09-10 17:30:27 -0700374 startSettingsActivity(android.provider.Settings.ACTION_SETTINGS);
Winson Chungd63c59782012-09-05 17:34:41 -0700375 }
376 });
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400377 mModel.addSettingsTile(settingsTile,
378 new QuickSettingsModel.BasicRefreshCallback(settingsTile));
Winson Chungd63c59782012-09-05 17:34:41 -0700379 parent.addView(settingsTile);
380 mDynamicSpannedTiles.add(settingsTile);
Alan Viveretteda0cc3e2013-09-26 13:11:54 -0700381
382 if (SHOW_ACCESSIBILITY_TILES) {
383 // Color inversion tile
384 final SystemSettingTile inversionTile = new SystemSettingTile(mContext);
385 inversionTile.setUri(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED,
386 SystemSettingTile.TYPE_SECURE);
387 inversionTile.setFragment("Settings$AccessibilityInversionSettingsActivity");
388 mModel.addInversionTile(inversionTile, inversionTile.getRefreshCallback());
389 parent.addView(inversionTile);
390 mDynamicSpannedTiles.add(inversionTile);
391
392 // Contrast enhancement tile
393 final SystemSettingTile contrastTile = new SystemSettingTile(mContext);
394 contrastTile.setUri(Settings.Secure.ACCESSIBILITY_DISPLAY_CONTRAST_ENABLED,
395 SystemSettingTile.TYPE_SECURE);
396 contrastTile.setFragment("Settings$AccessibilityContrastSettingsActivity");
397 mModel.addContrastTile(contrastTile, contrastTile.getRefreshCallback());
398 parent.addView(contrastTile);
399 mDynamicSpannedTiles.add(contrastTile);
400
401 // Color space adjustment tile
402 final SystemSettingTile colorSpaceTile = new SystemSettingTile(mContext);
403 colorSpaceTile.setUri(Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
404 SystemSettingTile.TYPE_SECURE);
405 colorSpaceTile.setFragment("Settings$AccessibilityDaltonizerSettingsActivity");
406 mModel.addColorSpaceTile(colorSpaceTile, colorSpaceTile.getRefreshCallback());
407 parent.addView(colorSpaceTile);
408 mDynamicSpannedTiles.add(colorSpaceTile);
409 }
Winson Chungd63c59782012-09-05 17:34:41 -0700410 }
411
412 private void addSystemTiles(ViewGroup parent, LayoutInflater inflater) {
413 // Wi-fi
John Spurlock43670872013-09-05 16:50:21 -0400414 final QuickSettingsTileView wifiTile = (QuickSettingsTileView)
415 inflater.inflate(R.layout.quick_settings_tile, parent, false);
416 wifiTile.setContent(R.layout.quick_settings_tile_wifi, inflater);
Winson Chungd63c59782012-09-05 17:34:41 -0700417 wifiTile.setOnClickListener(new View.OnClickListener() {
418 @Override
419 public void onClick(View v) {
Winson Chunge641b6a2012-09-10 17:30:27 -0700420 startSettingsActivity(android.provider.Settings.ACTION_WIFI_SETTINGS);
Winson Chungd63c59782012-09-05 17:34:41 -0700421 }
422 });
Daniel Sandlerab510022012-10-22 22:13:35 -0400423 if (LONG_PRESS_TOGGLES) {
424 wifiTile.setOnLongClickListener(new View.OnLongClickListener() {
425 @Override
426 public boolean onLongClick(View v) {
427 final boolean enable =
428 (mWifiManager.getWifiState() != WifiManager.WIFI_STATE_ENABLED);
429 new AsyncTask<Void, Void, Void>() {
430 @Override
431 protected Void doInBackground(Void... args) {
432 // Disable tethering if enabling Wifi
433 final int wifiApState = mWifiManager.getWifiApState();
434 if (enable && ((wifiApState == WifiManager.WIFI_AP_STATE_ENABLING) ||
435 (wifiApState == WifiManager.WIFI_AP_STATE_ENABLED))) {
436 mWifiManager.setWifiApEnabled(null, false);
437 }
438
439 mWifiManager.setWifiEnabled(enable);
440 return null;
441 }
442 }.execute();
443 wifiTile.setPressed(false);
444 return true;
445 }} );
446 }
John Spurlock43670872013-09-05 16:50:21 -0400447 mModel.addWifiTile(wifiTile, new NetworkActivityCallback() {
Winson Chungd63c59782012-09-05 17:34:41 -0700448 @Override
John Spurlock43670872013-09-05 16:50:21 -0400449 public void refreshView(QuickSettingsTileView view, State state) {
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700450 WifiState wifiState = (WifiState) state;
John Spurlock43670872013-09-05 16:50:21 -0400451 ImageView iv = (ImageView) view.findViewById(R.id.image);
452 iv.setImageResource(wifiState.iconId);
453 setActivity(view, wifiState);
454 TextView tv = (TextView) view.findViewById(R.id.text);
455 tv.setText(wifiState.label);
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400456 wifiTile.setContentDescription(mContext.getString(
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700457 R.string.accessibility_quick_settings_wifi,
458 wifiState.signalContentDescription,
459 (wifiState.connected) ? wifiState.label : ""));
Winson Chungd63c59782012-09-05 17:34:41 -0700460 }
461 });
462 parent.addView(wifiTile);
463
Daniel Sandler50528052012-11-07 23:39:41 -0500464 if (mModel.deviceHasMobileData()) {
Winson Chung43229d72012-09-12 18:04:18 -0700465 // RSSI
466 QuickSettingsTileView rssiTile = (QuickSettingsTileView)
467 inflater.inflate(R.layout.quick_settings_tile, parent, false);
468 rssiTile.setContent(R.layout.quick_settings_tile_rssi, inflater);
469 rssiTile.setOnClickListener(new View.OnClickListener() {
470 @Override
471 public void onClick(View v) {
472 Intent intent = new Intent();
473 intent.setComponent(new ComponentName(
474 "com.android.settings",
475 "com.android.settings.Settings$DataUsageSummaryActivity"));
476 startSettingsActivity(intent);
477 }
478 });
John Spurlock43670872013-09-05 16:50:21 -0400479 mModel.addRSSITile(rssiTile, new NetworkActivityCallback() {
Winson Chung43229d72012-09-12 18:04:18 -0700480 @Override
481 public void refreshView(QuickSettingsTileView view, State state) {
Winson Chung4f49d942012-09-14 14:01:40 -0700482 RSSIState rssiState = (RSSIState) state;
483 ImageView iv = (ImageView) view.findViewById(R.id.rssi_image);
484 ImageView iov = (ImageView) view.findViewById(R.id.rssi_overlay_image);
Winson Chung43229d72012-09-12 18:04:18 -0700485 TextView tv = (TextView) view.findViewById(R.id.rssi_textview);
Fabrice Di Meglio16b9f072013-01-11 15:06:31 -0800486 // Force refresh
487 iv.setImageDrawable(null);
Winson Chung4f49d942012-09-14 14:01:40 -0700488 iv.setImageResource(rssiState.signalIconId);
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700489
Winson Chung4f49d942012-09-14 14:01:40 -0700490 if (rssiState.dataTypeIconId > 0) {
491 iov.setImageResource(rssiState.dataTypeIconId);
492 } else {
493 iov.setImageDrawable(null);
494 }
John Spurlock43670872013-09-05 16:50:21 -0400495 setActivity(view, rssiState);
496
Winson Chung43229d72012-09-12 18:04:18 -0700497 tv.setText(state.label);
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700498 view.setContentDescription(mContext.getResources().getString(
499 R.string.accessibility_quick_settings_mobile,
500 rssiState.signalContentDescription, rssiState.dataContentDescription,
501 state.label));
Winson Chung43229d72012-09-12 18:04:18 -0700502 }
503 });
504 parent.addView(rssiTile);
505 }
Winson Chungd63c59782012-09-05 17:34:41 -0700506
Winson Chungd4726d02012-09-14 12:27:29 -0700507 // Rotation Lock
John Spurlock8ab172e2013-12-19 16:39:23 -0500508 if (mRotationLockController != null) {
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400509 final QuickSettingsBasicTile rotationLockTile
510 = new QuickSettingsBasicTile(mContext);
Winson Chungd4726d02012-09-14 12:27:29 -0700511 rotationLockTile.setOnClickListener(new View.OnClickListener() {
512 @Override
Svetoslav79578b22013-04-29 16:55:57 -0700513 public void onClick(View view) {
514 final boolean locked = mRotationLockController.isRotationLocked();
515 mRotationLockController.setRotationLocked(!locked);
Winson Chungd4726d02012-09-14 12:27:29 -0700516 }
517 });
Svetoslav79578b22013-04-29 16:55:57 -0700518 mModel.addRotationLockTile(rotationLockTile, mRotationLockController,
519 new QuickSettingsModel.RefreshCallback() {
520 @Override
521 public void refreshView(QuickSettingsTileView view, State state) {
522 QuickSettingsModel.RotationLockState rotationLockState =
523 (QuickSettingsModel.RotationLockState) state;
524 view.setVisibility(rotationLockState.visible
525 ? View.VISIBLE : View.GONE);
526 if (state.iconId != 0) {
527 // needed to flush any cached IDs
528 rotationLockTile.setImageDrawable(null);
529 rotationLockTile.setImageResource(state.iconId);
530 }
531 if (state.label != null) {
532 rotationLockTile.setText(state.label);
533 }
534 }
535 });
Winson Chungd4726d02012-09-14 12:27:29 -0700536 parent.addView(rotationLockTile);
537 }
538
Winson Chungd63c59782012-09-05 17:34:41 -0700539 // Battery
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400540 final QuickSettingsTileView batteryTile = (QuickSettingsTileView)
541 inflater.inflate(R.layout.quick_settings_tile, parent, false);
542 batteryTile.setContent(R.layout.quick_settings_tile_battery, inflater);
Winson Chungd63c59782012-09-05 17:34:41 -0700543 batteryTile.setOnClickListener(new View.OnClickListener() {
544 @Override
545 public void onClick(View v) {
Winson Chunge641b6a2012-09-10 17:30:27 -0700546 startSettingsActivity(Intent.ACTION_POWER_USAGE_SUMMARY);
Winson Chungd63c59782012-09-05 17:34:41 -0700547 }
548 });
549 mModel.addBatteryTile(batteryTile, new QuickSettingsModel.RefreshCallback() {
550 @Override
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400551 public void refreshView(QuickSettingsTileView unused, State state) {
Winson Chungd63c59782012-09-05 17:34:41 -0700552 QuickSettingsModel.BatteryState batteryState =
553 (QuickSettingsModel.BatteryState) state;
Winson Chungeaa5ab02012-09-13 16:36:41 -0700554 String t;
555 if (batteryState.batteryLevel == 100) {
556 t = mContext.getString(R.string.quick_settings_battery_charged_label);
557 } else {
558 t = batteryState.pluggedIn
559 ? mContext.getString(R.string.quick_settings_battery_charging_label,
560 batteryState.batteryLevel)
561 : mContext.getString(R.string.status_bar_settings_battery_meter_format,
562 batteryState.batteryLevel);
563 }
Daniel Sandlerdfaf3bd2013-04-12 01:39:02 -0400564 ((TextView)batteryTile.findViewById(R.id.text)).setText(t);
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400565 batteryTile.setContentDescription(
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700566 mContext.getString(R.string.accessibility_quick_settings_battery, t));
Winson Chungd63c59782012-09-05 17:34:41 -0700567 }
568 });
569 parent.addView(batteryTile);
570
571 // Airplane Mode
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400572 final QuickSettingsBasicTile airplaneTile
573 = new QuickSettingsBasicTile(mContext);
Winson Chungd63c59782012-09-05 17:34:41 -0700574 mModel.addAirplaneModeTile(airplaneTile, new QuickSettingsModel.RefreshCallback() {
575 @Override
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400576 public void refreshView(QuickSettingsTileView unused, State state) {
577 airplaneTile.setImageResource(state.iconId);
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700578
579 String airplaneState = mContext.getString(
580 (state.enabled) ? R.string.accessibility_desc_on
581 : R.string.accessibility_desc_off);
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400582 airplaneTile.setContentDescription(
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700583 mContext.getString(R.string.accessibility_quick_settings_airplane, airplaneState));
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400584 airplaneTile.setText(state.label);
Winson Chungd63c59782012-09-05 17:34:41 -0700585 }
586 });
587 parent.addView(airplaneTile);
588
589 // Bluetooth
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400590 if (mModel.deviceSupportsBluetooth()
591 || DEBUG_GONE_TILES) {
592 final QuickSettingsBasicTile bluetoothTile
593 = new QuickSettingsBasicTile(mContext);
Winson Chung6072b002012-09-11 17:10:10 -0700594 bluetoothTile.setOnClickListener(new View.OnClickListener() {
595 @Override
596 public void onClick(View v) {
597 startSettingsActivity(android.provider.Settings.ACTION_BLUETOOTH_SETTINGS);
598 }
599 });
Daniel Sandlerab510022012-10-22 22:13:35 -0400600 if (LONG_PRESS_TOGGLES) {
601 bluetoothTile.setOnLongClickListener(new View.OnLongClickListener() {
602 @Override
603 public boolean onLongClick(View v) {
604 if (mBluetoothAdapter.isEnabled()) {
605 mBluetoothAdapter.disable();
606 } else {
607 mBluetoothAdapter.enable();
608 }
609 bluetoothTile.setPressed(false);
610 return true;
611 }});
612 }
Winson Chung6072b002012-09-11 17:10:10 -0700613 mModel.addBluetoothTile(bluetoothTile, new QuickSettingsModel.RefreshCallback() {
614 @Override
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400615 public void refreshView(QuickSettingsTileView unused, State state) {
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700616 BluetoothState bluetoothState = (BluetoothState) state;
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400617 bluetoothTile.setImageResource(state.iconId);
Winson Chung5f623012012-09-14 14:58:43 -0700618
Winson Chung5f623012012-09-14 14:58:43 -0700619 /*
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400620 Resources r = mContext.getResources();
Winson Chung5f623012012-09-14 14:58:43 -0700621 //TODO: Show connected bluetooth device label
622 Set<BluetoothDevice> btDevices =
623 mBluetoothController.getBondedBluetoothDevices();
624 if (btDevices.size() == 1) {
625 // Show the name of the bluetooth device you are connected to
626 label = btDevices.iterator().next().getName();
627 } else if (btDevices.size() > 1) {
628 // Show a generic label about the number of bluetooth devices
629 label = r.getString(R.string.quick_settings_bluetooth_multiple_devices_label,
630 btDevices.size());
631 }
632 */
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400633 bluetoothTile.setContentDescription(mContext.getString(
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700634 R.string.accessibility_quick_settings_bluetooth,
635 bluetoothState.stateContentDescription));
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400636 bluetoothTile.setText(state.label);
Winson Chung6072b002012-09-11 17:10:10 -0700637 }
638 });
639 parent.addView(bluetoothTile);
640 }
Winson Chungd63c59782012-09-05 17:34:41 -0700641
David Christie03ed0122013-07-30 18:11:23 -0700642 // Location
643 final QuickSettingsBasicTile locationTile
644 = new QuickSettingsBasicTile(mContext);
645 locationTile.setImageResource(R.drawable.ic_qs_location_on);
646 locationTile.setTextResource(R.string.quick_settings_location_label);
647 locationTile.setOnClickListener(new View.OnClickListener() {
648 @Override
649 public void onClick(View v) {
650 startSettingsActivity(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
651 }
652 });
653 if (LONG_PRESS_TOGGLES) {
654 locationTile.setOnLongClickListener(new View.OnLongClickListener() {
655 @Override
656 public boolean onLongClick(View v) {
657 boolean newLocationEnabledState = !mLocationController.isLocationEnabled();
David Christieb12ba932013-09-03 17:15:28 -0700658 if (mLocationController.setLocationEnabled(newLocationEnabledState)
659 && newLocationEnabledState) {
660 // If we've successfully switched from location off to on, close the
661 // notifications tray to show the network location provider consent dialog.
David Christie03ed0122013-07-30 18:11:23 -0700662 Intent closeDialog = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
663 mContext.sendBroadcast(closeDialog);
664 }
665 return true; // Consume click
666 }} );
667 }
Victoria Lease3ac54a32013-10-14 14:54:10 -0700668 mModel.addLocationTile(locationTile, new QuickSettingsModel.RefreshCallback() {
669 @Override
670 public void refreshView(QuickSettingsTileView unused, State state) {
671 locationTile.setImageResource(state.iconId);
672 String locationState = mContext.getString(
673 (state.enabled) ? R.string.accessibility_desc_on
674 : R.string.accessibility_desc_off);
675 locationTile.setContentDescription(mContext.getString(
676 R.string.accessibility_quick_settings_location,
677 locationState));
678 locationTile.setText(state.label);
679 }
680 });
David Christie03ed0122013-07-30 18:11:23 -0700681 parent.addView(locationTile);
Winson Chungd63c59782012-09-05 17:34:41 -0700682 }
683
684 private void addTemporaryTiles(final ViewGroup parent, final LayoutInflater inflater) {
Winson Chungc86b23b2012-09-24 11:24:28 -0700685 // Alarm tile
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400686 final QuickSettingsBasicTile alarmTile
687 = new QuickSettingsBasicTile(mContext);
688 alarmTile.setImageResource(R.drawable.ic_qs_alarm_on);
Winson Chungc86b23b2012-09-24 11:24:28 -0700689 alarmTile.setOnClickListener(new View.OnClickListener() {
690 @Override
691 public void onClick(View v) {
Daniel Sandler0e9925a2013-09-13 14:49:39 -0400692 startSettingsActivity(AlarmClock.ACTION_SHOW_ALARMS);
Winson Chungc86b23b2012-09-24 11:24:28 -0700693 }
694 });
695 mModel.addAlarmTile(alarmTile, new QuickSettingsModel.RefreshCallback() {
696 @Override
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400697 public void refreshView(QuickSettingsTileView unused, State alarmState) {
698 alarmTile.setText(alarmState.label);
699 alarmTile.setVisibility(alarmState.enabled ? View.VISIBLE : View.GONE);
700 alarmTile.setContentDescription(mContext.getString(
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700701 R.string.accessibility_quick_settings_alarm, alarmState.label));
Winson Chungc86b23b2012-09-24 11:24:28 -0700702 }
703 });
704 parent.addView(alarmTile);
705
Jeff Brown635e9152013-11-07 00:38:14 -0800706 // Remote Display
707 QuickSettingsBasicTile remoteDisplayTile
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400708 = new QuickSettingsBasicTile(mContext);
Jeff Brown635e9152013-11-07 00:38:14 -0800709 remoteDisplayTile.setOnClickListener(new View.OnClickListener() {
Jeff Brown508257b2012-09-08 23:15:12 -0700710 @Override
711 public void onClick(View v) {
Jeff Brown0abd3a62013-11-09 17:48:23 -0800712 collapsePanels();
713
714 final Dialog[] dialog = new Dialog[1];
715 dialog[0] = MediaRouteDialogPresenter.createDialog(mContext,
716 MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY,
717 new View.OnClickListener() {
718 @Override
719 public void onClick(View v) {
720 dialog[0].dismiss();
721 startSettingsActivity(
722 android.provider.Settings.ACTION_WIFI_DISPLAY_SETTINGS);
723 }
724 });
725 dialog[0].getWindow().setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
726 dialog[0].show();
Jeff Brown508257b2012-09-08 23:15:12 -0700727 }
728 });
Jeff Brown635e9152013-11-07 00:38:14 -0800729 mModel.addRemoteDisplayTile(remoteDisplayTile,
730 new QuickSettingsModel.BasicRefreshCallback(remoteDisplayTile)
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400731 .setShowWhenEnabled(true));
Jeff Brown635e9152013-11-07 00:38:14 -0800732 parent.addView(remoteDisplayTile);
Jeff Brown508257b2012-09-08 23:15:12 -0700733
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400734 if (SHOW_IME_TILE || DEBUG_GONE_TILES) {
Daniel Sandlerdd68da82012-10-01 10:19:09 -0400735 // IME
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400736 final QuickSettingsBasicTile imeTile
737 = new QuickSettingsBasicTile(mContext);
738 imeTile.setImageResource(R.drawable.ic_qs_ime);
Daniel Sandlerdd68da82012-10-01 10:19:09 -0400739 imeTile.setOnClickListener(new View.OnClickListener() {
740 @Override
741 public void onClick(View v) {
742 try {
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400743 collapsePanels();
Daniel Sandlerdd68da82012-10-01 10:19:09 -0400744 Intent intent = new Intent(Settings.ACTION_SHOW_INPUT_METHOD_PICKER);
745 PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
746 pendingIntent.send();
747 } catch (Exception e) {}
Winson Chung2a4057d2012-09-12 18:30:06 -0700748 }
Daniel Sandlerdd68da82012-10-01 10:19:09 -0400749 });
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400750 mModel.addImeTile(imeTile,
751 new QuickSettingsModel.BasicRefreshCallback(imeTile)
752 .setShowWhenEnabled(true));
Daniel Sandlerdd68da82012-10-01 10:19:09 -0400753 parent.addView(imeTile);
754 }
Winson Chung43229d72012-09-12 18:04:18 -0700755
Daniel Sandlerc19d4482012-09-19 16:26:39 -0400756 // Bug reports
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400757 final QuickSettingsBasicTile bugreportTile
758 = new QuickSettingsBasicTile(mContext);
759 bugreportTile.setImageResource(com.android.internal.R.drawable.stat_sys_adb);
760 bugreportTile.setTextResource(com.android.internal.R.string.bugreport_title);
Daniel Sandlerc19d4482012-09-19 16:26:39 -0400761 bugreportTile.setOnClickListener(new View.OnClickListener() {
762 @Override
763 public void onClick(View v) {
Daniel Sandlerb5538e62013-04-12 15:16:53 -0400764 collapsePanels();
Daniel Sandlerc19d4482012-09-19 16:26:39 -0400765 showBugreportDialog();
766 }
767 });
768 mModel.addBugreportTile(bugreportTile, new QuickSettingsModel.RefreshCallback() {
769 @Override
770 public void refreshView(QuickSettingsTileView view, State state) {
771 view.setVisibility(state.enabled ? View.VISIBLE : View.GONE);
772 }
773 });
774 parent.addView(bugreportTile);
Winson Chungd63c59782012-09-05 17:34:41 -0700775 /*
776 QuickSettingsTileView mediaTile = (QuickSettingsTileView)
777 inflater.inflate(R.layout.quick_settings_tile, parent, false);
778 mediaTile.setContent(R.layout.quick_settings_tile_media, inflater);
779 parent.addView(mediaTile);
780 QuickSettingsTileView imeTile = (QuickSettingsTileView)
781 inflater.inflate(R.layout.quick_settings_tile, parent, false);
782 imeTile.setContent(R.layout.quick_settings_tile_ime, inflater);
783 imeTile.setOnClickListener(new View.OnClickListener() {
784 @Override
785 public void onClick(View v) {
786 parent.removeViewAt(0);
787 }
788 });
789 parent.addView(imeTile);
790 */
Geoffrey Borggaard348fc482013-08-08 14:32:39 -0400791
792 // SSL CA Cert Warning.
Maggie Benthall68881e42013-09-17 19:23:59 -0400793 final QuickSettingsBasicTile sslCaCertWarningTile =
794 new QuickSettingsBasicTile(mContext, null, R.layout.quick_settings_tile_monitoring);
Geoffrey Borggaard348fc482013-08-08 14:32:39 -0400795 sslCaCertWarningTile.setOnClickListener(new View.OnClickListener() {
796 @Override
797 public void onClick(View v) {
798 collapsePanels();
Maggie Benthall0469f412013-09-05 15:30:26 -0400799 startSettingsActivity(Settings.ACTION_MONITORING_CERT_INFO);
Geoffrey Borggaard348fc482013-08-08 14:32:39 -0400800 }
801 });
802
803 sslCaCertWarningTile.setImageResource(
804 com.android.internal.R.drawable.indicator_input_error);
805 sslCaCertWarningTile.setTextResource(R.string.ssl_ca_cert_warning);
806
807 mModel.addSslCaCertWarningTile(sslCaCertWarningTile,
808 new QuickSettingsModel.BasicRefreshCallback(sslCaCertWarningTile)
809 .setShowWhenEnabled(true));
810 parent.addView(sslCaCertWarningTile);
Winson Chungd63c59782012-09-05 17:34:41 -0700811 }
812
813 void updateResources() {
814 Resources r = mContext.getResources();
815
Winson Chungefba3232012-09-27 16:56:42 -0700816 // Update the model
817 mModel.updateResources();
818
Winson Chungd63c59782012-09-05 17:34:41 -0700819 // Update the User, Time, and Settings tiles spans, and reset everything else
820 int span = r.getInteger(R.integer.quick_settings_user_time_settings_tile_span);
821 for (QuickSettingsTileView v : mDynamicSpannedTiles) {
822 v.setColumnSpan(span);
823 }
Daniel Sandler101784e2012-10-15 13:39:38 -0400824 ((QuickSettingsContainerView)mContainerView).updateResources();
Winson Chungd63c59782012-09-05 17:34:41 -0700825 mContainerView.requestLayout();
826 }
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700827
Winson Chung3ed6f942012-09-20 16:07:11 -0700828
Winson Chung1679b362012-09-10 20:08:01 -0700829 private void showBrightnessDialog() {
Michael Wright0087a142013-02-05 16:29:39 -0800830 Intent intent = new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG);
831 mContext.sendBroadcast(intent);
Winson Chung1679b362012-09-10 20:08:01 -0700832 }
Jeff Brown508257b2012-09-08 23:15:12 -0700833
Daniel Sandlerc19d4482012-09-19 16:26:39 -0400834 private void showBugreportDialog() {
835 final AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
836 builder.setPositiveButton(com.android.internal.R.string.report, new OnClickListener() {
837 @Override
838 public void onClick(DialogInterface dialog, int which) {
839 if (which == DialogInterface.BUTTON_POSITIVE) {
Dianne Hackbornd4ac8d72012-09-27 23:20:10 -0700840 // Add a little delay before executing, to give the
841 // dialog a chance to go away before it takes a
842 // screenshot.
843 mHandler.postDelayed(new Runnable() {
844 @Override public void run() {
845 try {
846 ActivityManagerNative.getDefault()
847 .requestBugReport();
848 } catch (RemoteException e) {
849 }
850 }
851 }, 500);
Daniel Sandlerc19d4482012-09-19 16:26:39 -0400852 }
853 }
854 });
855 builder.setMessage(com.android.internal.R.string.bugreport_message);
856 builder.setTitle(com.android.internal.R.string.bugreport_title);
857 builder.setCancelable(true);
858 final Dialog dialog = builder.create();
859 dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
Daniel Sandlerb64c3dd2012-10-09 00:37:53 -0400860 try {
861 WindowManagerGlobal.getWindowManagerService().dismissKeyguard();
862 } catch (RemoteException e) {
863 }
Daniel Sandlerc19d4482012-09-19 16:26:39 -0400864 dialog.show();
865 }
866
Chris Wrenb2a7d272012-10-03 10:16:51 -0400867 private void applyBluetoothStatus() {
868 mModel.onBluetoothStateChange(mBluetoothState);
869 }
870
David Christie03ed0122013-07-30 18:11:23 -0700871 private void applyLocationEnabledStatus() {
872 mModel.onLocationSettingsChanged(mLocationController.isLocationEnabled());
873 }
874
Adam Powell6f2a3d22012-10-05 22:32:04 -0700875 void reloadUserInfo() {
876 if (mUserInfoTask != null) {
877 mUserInfoTask.cancel(false);
878 mUserInfoTask = null;
879 }
880 if (mTilesSetUp) {
881 queryForUserInformation();
Geoffrey Borggaard348fc482013-08-08 14:32:39 -0400882 queryForSslCaCerts();
Adam Powell6f2a3d22012-10-05 22:32:04 -0700883 }
884 }
885
Jeff Brown508257b2012-09-08 23:15:12 -0700886 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
887 @Override
888 public void onReceive(Context context, Intent intent) {
Adam Powell6f2a3d22012-10-05 22:32:04 -0700889 final String action = intent.getAction();
Jeff Brown635e9152013-11-07 00:38:14 -0800890 if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
Daniel Sandlerebaefec2012-10-17 11:37:42 -0400891 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
892 BluetoothAdapter.ERROR);
893 mBluetoothState.enabled = (state == BluetoothAdapter.STATE_ON);
894 applyBluetoothStatus();
Adam Powell6f2a3d22012-10-05 22:32:04 -0700895 } else if (BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
Chris Wrenb2a7d272012-10-03 10:16:51 -0400896 int status = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
897 BluetoothAdapter.STATE_DISCONNECTED);
898 mBluetoothState.connected = (status == BluetoothAdapter.STATE_CONNECTED);
899 applyBluetoothStatus();
Adam Powell6f2a3d22012-10-05 22:32:04 -0700900 } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
901 reloadUserInfo();
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700902 } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
903 if (mUseDefaultAvatar) {
904 queryForUserInformation();
905 }
Geoffrey Borggaard348fc482013-08-08 14:32:39 -0400906 } else if (KeyChain.ACTION_STORAGE_CHANGED.equals(action)) {
907 queryForSslCaCerts();
Adam Powell6f2a3d22012-10-05 22:32:04 -0700908 }
909 }
910 };
911
912 private final BroadcastReceiver mProfileReceiver = new BroadcastReceiver() {
913 @Override
914 public void onReceive(Context context, Intent intent) {
915 final String action = intent.getAction();
916 if (ContactsContract.Intents.ACTION_PROFILE_CHANGED.equals(action) ||
917 Intent.ACTION_USER_INFO_CHANGED.equals(action)) {
918 try {
Amith Yamasani6fc1d4e2013-05-08 16:43:58 -0700919 final int currentUser = ActivityManagerNative.getDefault().getCurrentUser().id;
920 final int changedUser =
921 intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId());
922 if (changedUser == currentUser) {
Adam Powell6f2a3d22012-10-05 22:32:04 -0700923 reloadUserInfo();
924 }
925 } catch (RemoteException e) {
926 Log.e(TAG, "Couldn't get current user id for profile change", e);
927 }
Chris Wrenb2a7d272012-10-03 10:16:51 -0400928 }
Casey Burkhardtbac221f2012-10-03 18:13:58 -0700929
Jeff Brown508257b2012-09-08 23:15:12 -0700930 }
931 };
John Spurlock43670872013-09-05 16:50:21 -0400932
933 private abstract static class NetworkActivityCallback
934 implements QuickSettingsModel.RefreshCallback {
935 private final long mDefaultDuration = new ValueAnimator().getDuration();
936 private final long mShortDuration = mDefaultDuration / 3;
937
938 public void setActivity(View view, ActivityState state) {
939 setVisibility(view.findViewById(R.id.activity_in), state.activityIn);
940 setVisibility(view.findViewById(R.id.activity_out), state.activityOut);
941 }
942
943 private void setVisibility(View view, boolean visible) {
944 final float newAlpha = visible ? 1 : 0;
945 if (view.getAlpha() != newAlpha) {
946 view.animate()
947 .setDuration(visible ? mShortDuration : mDefaultDuration)
948 .alpha(newAlpha)
949 .start();
950 }
951 }
952 }
Alan Viveretteda0cc3e2013-09-26 13:11:54 -0700953
954 /**
955 * Quick Setting tile that represents a secure setting. This type of tile
956 * can toggle a URI within Settings.Secure on click and launch a Settings
957 * fragment on long-click.
958 */
959 public class SystemSettingTile extends QuickSettingsBasicTile {
960 private static final int TYPE_GLOBAL = 0;
961 private static final int TYPE_SECURE = 1;
962 private static final int TYPE_SYSTEM = 2;
963
964 private final QuickSettingsModel.BasicRefreshCallback mRefreshCallback;
965
966 private String mFragment;
967 private String mName;
968 private int mType;
969
970 public SystemSettingTile(Context context) {
971 super(context);
972
973 mRefreshCallback = new QuickSettingsModel.BasicRefreshCallback(this);
974 mRefreshCallback.setShowWhenEnabled(true);
975 }
976
977 @Override
978 public boolean performLongClick() {
979 if (mFragment != null) {
980 collapsePanels();
981
982 final Intent intent = new Intent();
983 intent.setComponent(new ComponentName(
984 "com.android.settings", "com.android.settings." + mFragment));
985 startSettingsActivity(intent);
986 return true;
987 }
988 return false;
989 }
990
991 @Override
992 public boolean performClick() {
993 if (mName != null) {
994 collapsePanels();
995
996 final ContentResolver cr = mContext.getContentResolver();
997 switch (mType) {
998 case TYPE_GLOBAL: {
999 final boolean enable = Settings.Global.getInt(cr, mName, 0) == 0;
1000 Settings.Global.putInt(cr, mName, enable ? 1 : 0);
1001 } break;
1002 case TYPE_SECURE: {
1003 final boolean enable = Settings.Secure.getIntForUser(
1004 cr, mName, 0, UserHandle.USER_CURRENT) == 0;
1005 Settings.Secure.putIntForUser(
1006 cr, mName, enable ? 1 : 0, UserHandle.USER_CURRENT);
1007 } break;
1008 case TYPE_SYSTEM: {
1009 final boolean enable = Settings.System.getIntForUser(
1010 cr, mName, 0, UserHandle.USER_CURRENT) == 0;
1011 Settings.System.putIntForUser(
1012 cr, mName, enable ? 1 : 0, UserHandle.USER_CURRENT);
1013 } break;
1014 }
1015 return true;
1016 }
1017 return false;
1018 }
1019
1020 /**
1021 * Specifies the fragment within the com.android.settings package to
1022 * launch when this tile is long-clicked.
1023 *
1024 * @param fragment a fragment name within the com.android.settings
1025 * package
1026 */
1027 public void setFragment(String fragment) {
1028 mFragment = fragment;
1029 setLongClickable(fragment != null);
1030 }
1031
1032 /**
1033 * Specifies the setting name and type to toggle when this tile is
1034 * clicked.
1035 *
1036 * @param name a setting name
1037 * @param type the type of setting, one of:
1038 * <ul>
1039 * <li>{@link #TYPE_GLOBAL}
1040 * <li>{@link #TYPE_SECURE}
1041 * <li>{@link #TYPE_SYSTEM}
1042 * </ul>
1043 */
1044 public void setUri(String name, int type) {
1045 mName = name;
1046 mType = type;
1047 setClickable(mName != null);
1048 }
1049
1050 /**
1051 * @return the refresh callback for this tile
1052 */
1053 public QuickSettingsModel.BasicRefreshCallback getRefreshCallback() {
1054 return mRefreshCallback;
1055 }
1056 }
Daniel Sandlerc19d4482012-09-19 16:26:39 -04001057}