Home | History | Annotate | Download | only in phone
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.systemui.statusbar.phone;
     18 
     19 import com.android.internal.view.RotationPolicy;
     20 import com.android.systemui.R;
     21 
     22 import com.android.systemui.statusbar.phone.QuickSettingsModel.BluetoothState;
     23 import com.android.systemui.statusbar.phone.QuickSettingsModel.RSSIState;
     24 import com.android.systemui.statusbar.phone.QuickSettingsModel.State;
     25 import com.android.systemui.statusbar.phone.QuickSettingsModel.UserState;
     26 import com.android.systemui.statusbar.phone.QuickSettingsModel.WifiState;
     27 import com.android.systemui.statusbar.policy.BatteryController;
     28 import com.android.systemui.statusbar.policy.BluetoothController;
     29 import com.android.systemui.statusbar.policy.LocationController;
     30 import com.android.systemui.statusbar.policy.NetworkController;
     31 
     32 import android.app.ActivityManagerNative;
     33 import android.app.AlertDialog;
     34 import android.app.Dialog;
     35 import android.app.PendingIntent;
     36 import android.bluetooth.BluetoothAdapter;
     37 import android.content.BroadcastReceiver;
     38 import android.content.ComponentName;
     39 import android.content.Context;
     40 import android.content.DialogInterface;
     41 import android.content.DialogInterface.OnClickListener;
     42 import android.content.Intent;
     43 import android.content.IntentFilter;
     44 import android.content.pm.PackageManager.NameNotFoundException;
     45 import android.content.pm.UserInfo;
     46 import android.content.res.Resources;
     47 import android.database.Cursor;
     48 import android.graphics.Bitmap;
     49 import android.graphics.drawable.BitmapDrawable;
     50 import android.graphics.drawable.Drawable;
     51 import android.graphics.drawable.LevelListDrawable;
     52 import android.hardware.display.DisplayManager;
     53 import android.hardware.display.WifiDisplayStatus;
     54 import android.net.wifi.WifiManager;
     55 import android.os.AsyncTask;
     56 import android.os.Handler;
     57 import android.os.RemoteException;
     58 import android.os.UserHandle;
     59 import android.os.UserManager;
     60 import android.provider.ContactsContract;
     61 import android.provider.ContactsContract.CommonDataKinds.Phone;
     62 import android.provider.ContactsContract.Profile;
     63 import android.provider.Settings;
     64 import android.util.Log;
     65 import android.util.Pair;
     66 import android.view.LayoutInflater;
     67 import android.view.View;
     68 import android.view.ViewGroup;
     69 import android.view.WindowManager;
     70 import android.view.WindowManagerGlobal;
     71 import android.widget.ImageView;
     72 import android.widget.TextView;
     73 
     74 import java.util.ArrayList;
     75 
     76 
     77 /**
     78  *
     79  */
     80 class QuickSettings {
     81     static final boolean DEBUG_GONE_TILES = false;
     82     private static final String TAG = "QuickSettings";
     83     public static final boolean SHOW_IME_TILE = false;
     84 
     85     public static final boolean LONG_PRESS_TOGGLES = true;
     86 
     87     private Context mContext;
     88     private PanelBar mBar;
     89     private QuickSettingsModel mModel;
     90     private ViewGroup mContainerView;
     91 
     92     private DisplayManager mDisplayManager;
     93     private WifiDisplayStatus mWifiDisplayStatus;
     94     private PhoneStatusBar mStatusBarService;
     95     private BluetoothState mBluetoothState;
     96     private BluetoothAdapter mBluetoothAdapter;
     97     private WifiManager mWifiManager;
     98 
     99     private BluetoothController mBluetoothController;
    100 
    101     private AsyncTask<Void, Void, Pair<String, Drawable>> mUserInfoTask;
    102 
    103     private LevelListDrawable mBatteryLevels;
    104     private LevelListDrawable mChargingBatteryLevels;
    105 
    106     boolean mTilesSetUp = false;
    107     boolean mUseDefaultAvatar = false;
    108 
    109     private Handler mHandler;
    110 
    111     // 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 
    116     private final RotationPolicy.RotationPolicyListener mRotationPolicyListener =
    117             new RotationPolicy.RotationPolicyListener() {
    118         @Override
    119         public void onChange() {
    120             mModel.onRotationLockChanged();
    121         }
    122     };
    123 
    124     public QuickSettings(Context context, QuickSettingsContainerView container) {
    125         mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
    126         mContext = context;
    127         mContainerView = container;
    128         mModel = new QuickSettingsModel(context);
    129         mWifiDisplayStatus = new WifiDisplayStatus();
    130         mBluetoothState = new QuickSettingsModel.BluetoothState();
    131         mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
    132         mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    133 
    134         mHandler = new Handler();
    135 
    136         Resources r = mContext.getResources();
    137         mBatteryLevels = (LevelListDrawable) r.getDrawable(R.drawable.qs_sys_battery);
    138         mChargingBatteryLevels =
    139                 (LevelListDrawable) r.getDrawable(R.drawable.qs_sys_battery_charging);
    140 
    141         IntentFilter filter = new IntentFilter();
    142         filter.addAction(DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED);
    143         filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
    144         filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
    145         filter.addAction(Intent.ACTION_USER_SWITCHED);
    146         filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
    147         mContext.registerReceiver(mReceiver, filter);
    148 
    149         IntentFilter profileFilter = new IntentFilter();
    150         profileFilter.addAction(ContactsContract.Intents.ACTION_PROFILE_CHANGED);
    151         profileFilter.addAction(Intent.ACTION_USER_INFO_CHANGED);
    152         mContext.registerReceiverAsUser(mProfileReceiver, UserHandle.ALL, profileFilter,
    153                 null, null);
    154     }
    155 
    156     void setBar(PanelBar bar) {
    157         mBar = bar;
    158     }
    159 
    160     public void setService(PhoneStatusBar phoneStatusBar) {
    161         mStatusBarService = phoneStatusBar;
    162     }
    163 
    164     public PhoneStatusBar getService() {
    165         return mStatusBarService;
    166     }
    167 
    168     public void setImeWindowStatus(boolean visible) {
    169         mModel.onImeWindowStatusChanged(visible);
    170     }
    171 
    172     void setup(NetworkController networkController, BluetoothController bluetoothController,
    173             BatteryController batteryController, LocationController locationController) {
    174         mBluetoothController = bluetoothController;
    175 
    176         setupQuickSettings();
    177         updateWifiDisplayStatus();
    178         updateResources();
    179 
    180         networkController.addNetworkSignalChangedCallback(mModel);
    181         bluetoothController.addStateChangedCallback(mModel);
    182         batteryController.addStateChangedCallback(mModel);
    183         locationController.addStateChangedCallback(mModel);
    184         RotationPolicy.registerRotationPolicyListener(mContext, mRotationPolicyListener,
    185                 UserHandle.USER_ALL);
    186     }
    187 
    188     private void queryForUserInformation() {
    189         Context currentUserContext = null;
    190         UserInfo userInfo = null;
    191         try {
    192             userInfo = ActivityManagerNative.getDefault().getCurrentUser();
    193             currentUserContext = mContext.createPackageContextAsUser("android", 0,
    194                     new UserHandle(userInfo.id));
    195         } catch (NameNotFoundException e) {
    196             Log.e(TAG, "Couldn't create user context", e);
    197             throw new RuntimeException(e);
    198         } catch (RemoteException e) {
    199             Log.e(TAG, "Couldn't get user info", e);
    200         }
    201         final int userId = userInfo.id;
    202         final String userName = userInfo.name;
    203 
    204         final Context context = currentUserContext;
    205         mUserInfoTask = new AsyncTask<Void, Void, Pair<String, Drawable>>() {
    206             @Override
    207             protected Pair<String, Drawable> doInBackground(Void... params) {
    208                 final UserManager um = UserManager.get(mContext);
    209 
    210                 // Fall back to the UserManager nickname if we can't read the name from the local
    211                 // profile below.
    212                 String name = userName;
    213                 Drawable avatar = null;
    214                 Bitmap rawAvatar = um.getUserIcon(userId);
    215                 if (rawAvatar != null) {
    216                     avatar = new BitmapDrawable(mContext.getResources(), rawAvatar);
    217                 } else {
    218                     avatar = mContext.getResources().getDrawable(R.drawable.ic_qs_default_user);
    219                     mUseDefaultAvatar = true;
    220                 }
    221 
    222                 // If it's a single-user device, get the profile name, since the nickname is not
    223                 // usually valid
    224                 if (um.getUsers().size() <= 1) {
    225                     // Try and read the display name from the local profile
    226                     final Cursor cursor = context.getContentResolver().query(
    227                             Profile.CONTENT_URI, new String[] {Phone._ID, Phone.DISPLAY_NAME},
    228                             null, null, null);
    229                     if (cursor != null) {
    230                         try {
    231                             if (cursor.moveToFirst()) {
    232                                 name = cursor.getString(cursor.getColumnIndex(Phone.DISPLAY_NAME));
    233                             }
    234                         } finally {
    235                             cursor.close();
    236                         }
    237                     }
    238                 }
    239                 return new Pair<String, Drawable>(name, avatar);
    240             }
    241 
    242             @Override
    243             protected void onPostExecute(Pair<String, Drawable> result) {
    244                 super.onPostExecute(result);
    245                 mModel.setUserTileInfo(result.first, result.second);
    246                 mUserInfoTask = null;
    247             }
    248         };
    249         mUserInfoTask.execute();
    250     }
    251 
    252     private void setupQuickSettings() {
    253         // Setup the tiles that we are going to be showing (including the temporary ones)
    254         LayoutInflater inflater = LayoutInflater.from(mContext);
    255 
    256         addUserTiles(mContainerView, inflater);
    257         addSystemTiles(mContainerView, inflater);
    258         addTemporaryTiles(mContainerView, inflater);
    259 
    260         queryForUserInformation();
    261         mTilesSetUp = true;
    262     }
    263 
    264     private void startSettingsActivity(String action) {
    265         Intent intent = new Intent(action);
    266         startSettingsActivity(intent);
    267     }
    268 
    269     private void startSettingsActivity(Intent intent) {
    270         startSettingsActivity(intent, true);
    271     }
    272 
    273     private void collapsePanels() {
    274         getService().animateCollapsePanels();
    275     }
    276 
    277     private void startSettingsActivity(Intent intent, boolean onlyProvisioned) {
    278         if (onlyProvisioned && !getService().isDeviceProvisioned()) return;
    279         try {
    280             // Dismiss the lock screen when Settings starts.
    281             ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
    282         } catch (RemoteException e) {
    283         }
    284         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
    285         mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
    286         collapsePanels();
    287     }
    288 
    289     private void addUserTiles(ViewGroup parent, LayoutInflater inflater) {
    290         QuickSettingsTileView userTile = (QuickSettingsTileView)
    291                 inflater.inflate(R.layout.quick_settings_tile, parent, false);
    292         userTile.setContent(R.layout.quick_settings_tile_user, inflater);
    293         userTile.setOnClickListener(new View.OnClickListener() {
    294             @Override
    295             public void onClick(View v) {
    296                 collapsePanels();
    297                 final UserManager um = UserManager.get(mContext);
    298                 if (um.getUsers(true).size() > 1) {
    299                     try {
    300                         WindowManagerGlobal.getWindowManagerService().lockNow(null);
    301                     } catch (RemoteException e) {
    302                         Log.e(TAG, "Couldn't show user switcher", e);
    303                     }
    304                 } else {
    305                     Intent intent = ContactsContract.QuickContact.composeQuickContactsIntent(
    306                             mContext, v, ContactsContract.Profile.CONTENT_URI,
    307                             ContactsContract.QuickContact.MODE_LARGE, null);
    308                     mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
    309                 }
    310             }
    311         });
    312         mModel.addUserTile(userTile, new QuickSettingsModel.RefreshCallback() {
    313             @Override
    314             public void refreshView(QuickSettingsTileView view, State state) {
    315                 UserState us = (UserState) state;
    316                 ImageView iv = (ImageView) view.findViewById(R.id.user_imageview);
    317                 TextView tv = (TextView) view.findViewById(R.id.user_textview);
    318                 tv.setText(state.label);
    319                 iv.setImageDrawable(us.avatar);
    320                 view.setContentDescription(mContext.getString(
    321                         R.string.accessibility_quick_settings_user, state.label));
    322             }
    323         });
    324         parent.addView(userTile);
    325         mDynamicSpannedTiles.add(userTile);
    326 
    327         // Brightness
    328         final QuickSettingsBasicTile brightnessTile
    329                 = new QuickSettingsBasicTile(mContext);
    330         brightnessTile.setImageResource(R.drawable.ic_qs_brightness_auto_off);
    331         brightnessTile.setOnClickListener(new View.OnClickListener() {
    332             @Override
    333             public void onClick(View v) {
    334                 collapsePanels();
    335                 showBrightnessDialog();
    336             }
    337         });
    338         mModel.addBrightnessTile(brightnessTile,
    339                 new QuickSettingsModel.BasicRefreshCallback(brightnessTile));
    340         parent.addView(brightnessTile);
    341         mDynamicSpannedTiles.add(brightnessTile);
    342 
    343         // Time tile
    344         /*
    345         QuickSettingsTileView timeTile = (QuickSettingsTileView)
    346                 inflater.inflate(R.layout.quick_settings_tile, parent, false);
    347         timeTile.setContent(R.layout.quick_settings_tile_time, inflater);
    348         timeTile.setOnClickListener(new View.OnClickListener() {
    349             @Override
    350             public void onClick(View v) {
    351                 // Quick. Clock. Quick. Clock. Quick. Clock.
    352                 startSettingsActivity(Intent.ACTION_QUICK_CLOCK);
    353             }
    354         });
    355         mModel.addTimeTile(timeTile, new QuickSettingsModel.RefreshCallback() {
    356             @Override
    357             public void refreshView(QuickSettingsTileView view, State alarmState) {}
    358         });
    359         parent.addView(timeTile);
    360         mDynamicSpannedTiles.add(timeTile);
    361         */
    362 
    363         // Settings tile
    364         final QuickSettingsBasicTile settingsTile = new QuickSettingsBasicTile(mContext);
    365         settingsTile.setImageResource(R.drawable.ic_qs_settings);
    366         settingsTile.setOnClickListener(new View.OnClickListener() {
    367             @Override
    368             public void onClick(View v) {
    369                 startSettingsActivity(android.provider.Settings.ACTION_SETTINGS);
    370             }
    371         });
    372         mModel.addSettingsTile(settingsTile,
    373                 new QuickSettingsModel.BasicRefreshCallback(settingsTile));
    374         parent.addView(settingsTile);
    375         mDynamicSpannedTiles.add(settingsTile);
    376     }
    377 
    378     private void addSystemTiles(ViewGroup parent, LayoutInflater inflater) {
    379         // Wi-fi
    380         final QuickSettingsBasicTile wifiTile
    381                 = new QuickSettingsBasicTile(mContext);
    382         wifiTile.setOnClickListener(new View.OnClickListener() {
    383             @Override
    384             public void onClick(View v) {
    385                 startSettingsActivity(android.provider.Settings.ACTION_WIFI_SETTINGS);
    386             }
    387         });
    388         if (LONG_PRESS_TOGGLES) {
    389             wifiTile.setOnLongClickListener(new View.OnLongClickListener() {
    390                 @Override
    391                 public boolean onLongClick(View v) {
    392                     final boolean enable =
    393                             (mWifiManager.getWifiState() != WifiManager.WIFI_STATE_ENABLED);
    394                     new AsyncTask<Void, Void, Void>() {
    395                         @Override
    396                         protected Void doInBackground(Void... args) {
    397                             // Disable tethering if enabling Wifi
    398                             final int wifiApState = mWifiManager.getWifiApState();
    399                             if (enable && ((wifiApState == WifiManager.WIFI_AP_STATE_ENABLING) ||
    400                                            (wifiApState == WifiManager.WIFI_AP_STATE_ENABLED))) {
    401                                 mWifiManager.setWifiApEnabled(null, false);
    402                             }
    403 
    404                             mWifiManager.setWifiEnabled(enable);
    405                             return null;
    406                         }
    407                     }.execute();
    408                     wifiTile.setPressed(false);
    409                     return true;
    410                 }} );
    411         }
    412         mModel.addWifiTile(wifiTile, new QuickSettingsModel.RefreshCallback() {
    413             @Override
    414             public void refreshView(QuickSettingsTileView unused, State state) {
    415                 WifiState wifiState = (WifiState) state;
    416                 wifiTile.setImageResource(wifiState.iconId);
    417                 wifiTile.setText(wifiState.label);
    418                 wifiTile.setContentDescription(mContext.getString(
    419                         R.string.accessibility_quick_settings_wifi,
    420                         wifiState.signalContentDescription,
    421                         (wifiState.connected) ? wifiState.label : ""));
    422             }
    423         });
    424         parent.addView(wifiTile);
    425 
    426         if (mModel.deviceHasMobileData()) {
    427             // RSSI
    428             QuickSettingsTileView rssiTile = (QuickSettingsTileView)
    429                     inflater.inflate(R.layout.quick_settings_tile, parent, false);
    430             rssiTile.setContent(R.layout.quick_settings_tile_rssi, inflater);
    431             rssiTile.setOnClickListener(new View.OnClickListener() {
    432                 @Override
    433                 public void onClick(View v) {
    434                     Intent intent = new Intent();
    435                     intent.setComponent(new ComponentName(
    436                             "com.android.settings",
    437                             "com.android.settings.Settings$DataUsageSummaryActivity"));
    438                     startSettingsActivity(intent);
    439                 }
    440             });
    441             mModel.addRSSITile(rssiTile, new QuickSettingsModel.RefreshCallback() {
    442                 @Override
    443                 public void refreshView(QuickSettingsTileView view, State state) {
    444                     RSSIState rssiState = (RSSIState) state;
    445                     ImageView iv = (ImageView) view.findViewById(R.id.rssi_image);
    446                     ImageView iov = (ImageView) view.findViewById(R.id.rssi_overlay_image);
    447                     TextView tv = (TextView) view.findViewById(R.id.rssi_textview);
    448                     // Force refresh
    449                     iv.setImageDrawable(null);
    450                     iv.setImageResource(rssiState.signalIconId);
    451 
    452                     if (rssiState.dataTypeIconId > 0) {
    453                         iov.setImageResource(rssiState.dataTypeIconId);
    454                     } else {
    455                         iov.setImageDrawable(null);
    456                     }
    457                     tv.setText(state.label);
    458                     view.setContentDescription(mContext.getResources().getString(
    459                             R.string.accessibility_quick_settings_mobile,
    460                             rssiState.signalContentDescription, rssiState.dataContentDescription,
    461                             state.label));
    462                 }
    463             });
    464             parent.addView(rssiTile);
    465         }
    466 
    467         // Rotation Lock
    468         if (mContext.getResources().getBoolean(R.bool.quick_settings_show_rotation_lock)
    469                 || DEBUG_GONE_TILES) {
    470             final QuickSettingsBasicTile rotationLockTile
    471                     = new QuickSettingsBasicTile(mContext);
    472             rotationLockTile.setOnClickListener(new View.OnClickListener() {
    473                 @Override
    474                 public void onClick(View v) {
    475                     boolean locked = RotationPolicy.isRotationLocked(mContext);
    476                     RotationPolicy.setRotationLock(mContext, !locked);
    477                 }
    478             });
    479             mModel.addRotationLockTile(rotationLockTile,
    480                     new QuickSettingsModel.BasicRefreshCallback(rotationLockTile));
    481             parent.addView(rotationLockTile);
    482         }
    483 
    484         // Battery
    485         final QuickSettingsBasicTile batteryTile = new QuickSettingsBasicTile(mContext);
    486         batteryTile.setOnClickListener(new View.OnClickListener() {
    487             @Override
    488             public void onClick(View v) {
    489                 startSettingsActivity(Intent.ACTION_POWER_USAGE_SUMMARY);
    490             }
    491         });
    492         mModel.addBatteryTile(batteryTile, new QuickSettingsModel.RefreshCallback() {
    493             @Override
    494             public void refreshView(QuickSettingsTileView unused, State state) {
    495                 QuickSettingsModel.BatteryState batteryState =
    496                         (QuickSettingsModel.BatteryState) state;
    497                 Drawable d = batteryState.pluggedIn
    498                         ? mChargingBatteryLevels
    499                         : mBatteryLevels;
    500                 String t;
    501                 if (batteryState.batteryLevel == 100) {
    502                     t = mContext.getString(R.string.quick_settings_battery_charged_label);
    503                 } else {
    504                     t = batteryState.pluggedIn
    505                         ? mContext.getString(R.string.quick_settings_battery_charging_label,
    506                                 batteryState.batteryLevel)
    507                         : mContext.getString(R.string.status_bar_settings_battery_meter_format,
    508                                 batteryState.batteryLevel);
    509                 }
    510                 batteryTile.setImageDrawable(d);
    511                 batteryTile.getImageView().setImageLevel(batteryState.batteryLevel);
    512                 batteryTile.setText(t);
    513                 batteryTile.setContentDescription(
    514                         mContext.getString(R.string.accessibility_quick_settings_battery, t));
    515             }
    516         });
    517         parent.addView(batteryTile);
    518 
    519         // Airplane Mode
    520         final QuickSettingsBasicTile airplaneTile
    521                 = new QuickSettingsBasicTile(mContext);
    522         mModel.addAirplaneModeTile(airplaneTile, new QuickSettingsModel.RefreshCallback() {
    523             @Override
    524             public void refreshView(QuickSettingsTileView unused, State state) {
    525                 airplaneTile.setImageResource(state.iconId);
    526 
    527                 String airplaneState = mContext.getString(
    528                         (state.enabled) ? R.string.accessibility_desc_on
    529                                 : R.string.accessibility_desc_off);
    530                 airplaneTile.setContentDescription(
    531                         mContext.getString(R.string.accessibility_quick_settings_airplane, airplaneState));
    532                 airplaneTile.setText(state.label);
    533             }
    534         });
    535         parent.addView(airplaneTile);
    536 
    537         // Bluetooth
    538         if (mModel.deviceSupportsBluetooth()
    539                 || DEBUG_GONE_TILES) {
    540             final QuickSettingsBasicTile bluetoothTile
    541                     = new QuickSettingsBasicTile(mContext);
    542             bluetoothTile.setOnClickListener(new View.OnClickListener() {
    543                 @Override
    544                 public void onClick(View v) {
    545                     startSettingsActivity(android.provider.Settings.ACTION_BLUETOOTH_SETTINGS);
    546                 }
    547             });
    548             if (LONG_PRESS_TOGGLES) {
    549                 bluetoothTile.setOnLongClickListener(new View.OnLongClickListener() {
    550                     @Override
    551                     public boolean onLongClick(View v) {
    552                         if (mBluetoothAdapter.isEnabled()) {
    553                             mBluetoothAdapter.disable();
    554                         } else {
    555                             mBluetoothAdapter.enable();
    556                         }
    557                         bluetoothTile.setPressed(false);
    558                         return true;
    559                     }});
    560             }
    561             mModel.addBluetoothTile(bluetoothTile, new QuickSettingsModel.RefreshCallback() {
    562                 @Override
    563                 public void refreshView(QuickSettingsTileView unused, State state) {
    564                     BluetoothState bluetoothState = (BluetoothState) state;
    565                     bluetoothTile.setImageResource(state.iconId);
    566 
    567                     /*
    568                     Resources r = mContext.getResources();
    569                     //TODO: Show connected bluetooth device label
    570                     Set<BluetoothDevice> btDevices =
    571                             mBluetoothController.getBondedBluetoothDevices();
    572                     if (btDevices.size() == 1) {
    573                         // Show the name of the bluetooth device you are connected to
    574                         label = btDevices.iterator().next().getName();
    575                     } else if (btDevices.size() > 1) {
    576                         // Show a generic label about the number of bluetooth devices
    577                         label = r.getString(R.string.quick_settings_bluetooth_multiple_devices_label,
    578                                 btDevices.size());
    579                     }
    580                     */
    581                     bluetoothTile.setContentDescription(mContext.getString(
    582                             R.string.accessibility_quick_settings_bluetooth,
    583                             bluetoothState.stateContentDescription));
    584                     bluetoothTile.setText(state.label);
    585                 }
    586             });
    587             parent.addView(bluetoothTile);
    588         }
    589 
    590     }
    591 
    592     private void addTemporaryTiles(final ViewGroup parent, final LayoutInflater inflater) {
    593         // Alarm tile
    594         final QuickSettingsBasicTile alarmTile
    595                 = new QuickSettingsBasicTile(mContext);
    596         alarmTile.setImageResource(R.drawable.ic_qs_alarm_on);
    597         alarmTile.setOnClickListener(new View.OnClickListener() {
    598             @Override
    599             public void onClick(View v) {
    600                 // TODO: Jump into the alarm application
    601                 Intent intent = new Intent();
    602                 intent.setComponent(new ComponentName(
    603                         "com.google.android.deskclock",
    604                         "com.android.deskclock.AlarmClock"));
    605                 startSettingsActivity(intent);
    606             }
    607         });
    608         mModel.addAlarmTile(alarmTile, new QuickSettingsModel.RefreshCallback() {
    609             @Override
    610             public void refreshView(QuickSettingsTileView unused, State alarmState) {
    611                 alarmTile.setText(alarmState.label);
    612                 alarmTile.setVisibility(alarmState.enabled ? View.VISIBLE : View.GONE);
    613                 alarmTile.setContentDescription(mContext.getString(
    614                         R.string.accessibility_quick_settings_alarm, alarmState.label));
    615             }
    616         });
    617         parent.addView(alarmTile);
    618 
    619         // Location
    620         final QuickSettingsBasicTile locationTile
    621                 = new QuickSettingsBasicTile(mContext);
    622         locationTile.setImageResource(R.drawable.ic_qs_location);
    623         locationTile.setTextResource(R.string.quick_settings_location_label);
    624         locationTile.setOnClickListener(new View.OnClickListener() {
    625             @Override
    626             public void onClick(View v) {
    627                 startSettingsActivity(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
    628             }
    629         });
    630         mModel.addLocationTile(locationTile,
    631                 new QuickSettingsModel.BasicRefreshCallback(locationTile)
    632                         .setShowWhenEnabled(true));
    633         parent.addView(locationTile);
    634 
    635         // Wifi Display
    636         QuickSettingsBasicTile wifiDisplayTile
    637                 = new QuickSettingsBasicTile(mContext);
    638         wifiDisplayTile.setImageResource(R.drawable.ic_qs_remote_display);
    639         wifiDisplayTile.setOnClickListener(new View.OnClickListener() {
    640             @Override
    641             public void onClick(View v) {
    642                 startSettingsActivity(android.provider.Settings.ACTION_WIFI_DISPLAY_SETTINGS);
    643             }
    644         });
    645         mModel.addWifiDisplayTile(wifiDisplayTile,
    646                 new QuickSettingsModel.BasicRefreshCallback(wifiDisplayTile)
    647                         .setShowWhenEnabled(true));
    648         parent.addView(wifiDisplayTile);
    649 
    650         if (SHOW_IME_TILE || DEBUG_GONE_TILES) {
    651             // IME
    652             final QuickSettingsBasicTile imeTile
    653                     = new QuickSettingsBasicTile(mContext);
    654             imeTile.setImageResource(R.drawable.ic_qs_ime);
    655             imeTile.setOnClickListener(new View.OnClickListener() {
    656                 @Override
    657                 public void onClick(View v) {
    658                     try {
    659                         collapsePanels();
    660                         Intent intent = new Intent(Settings.ACTION_SHOW_INPUT_METHOD_PICKER);
    661                         PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
    662                         pendingIntent.send();
    663                     } catch (Exception e) {}
    664                 }
    665             });
    666             mModel.addImeTile(imeTile,
    667                     new QuickSettingsModel.BasicRefreshCallback(imeTile)
    668                             .setShowWhenEnabled(true));
    669             parent.addView(imeTile);
    670         }
    671 
    672         // Bug reports
    673         final QuickSettingsBasicTile bugreportTile
    674                 = new QuickSettingsBasicTile(mContext);
    675         bugreportTile.setImageResource(com.android.internal.R.drawable.stat_sys_adb);
    676         bugreportTile.setTextResource(com.android.internal.R.string.bugreport_title);
    677         bugreportTile.setOnClickListener(new View.OnClickListener() {
    678             @Override
    679             public void onClick(View v) {
    680                 collapsePanels();
    681                 showBugreportDialog();
    682             }
    683         });
    684         mModel.addBugreportTile(bugreportTile, new QuickSettingsModel.RefreshCallback() {
    685             @Override
    686             public void refreshView(QuickSettingsTileView view, State state) {
    687                 view.setVisibility(state.enabled ? View.VISIBLE : View.GONE);
    688             }
    689         });
    690         parent.addView(bugreportTile);
    691         /*
    692         QuickSettingsTileView mediaTile = (QuickSettingsTileView)
    693                 inflater.inflate(R.layout.quick_settings_tile, parent, false);
    694         mediaTile.setContent(R.layout.quick_settings_tile_media, inflater);
    695         parent.addView(mediaTile);
    696         QuickSettingsTileView imeTile = (QuickSettingsTileView)
    697                 inflater.inflate(R.layout.quick_settings_tile, parent, false);
    698         imeTile.setContent(R.layout.quick_settings_tile_ime, inflater);
    699         imeTile.setOnClickListener(new View.OnClickListener() {
    700             @Override
    701             public void onClick(View v) {
    702                 parent.removeViewAt(0);
    703             }
    704         });
    705         parent.addView(imeTile);
    706         */
    707     }
    708 
    709     void updateResources() {
    710         Resources r = mContext.getResources();
    711 
    712         // Update the model
    713         mModel.updateResources();
    714 
    715         // Update the User, Time, and Settings tiles spans, and reset everything else
    716         int span = r.getInteger(R.integer.quick_settings_user_time_settings_tile_span);
    717         for (QuickSettingsTileView v : mDynamicSpannedTiles) {
    718             v.setColumnSpan(span);
    719         }
    720         ((QuickSettingsContainerView)mContainerView).updateResources();
    721         mContainerView.requestLayout();
    722     }
    723 
    724 
    725     private void showBrightnessDialog() {
    726         Intent intent = new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG);
    727         mContext.sendBroadcast(intent);
    728     }
    729 
    730     private void showBugreportDialog() {
    731         final AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
    732         builder.setPositiveButton(com.android.internal.R.string.report, new OnClickListener() {
    733             @Override
    734             public void onClick(DialogInterface dialog, int which) {
    735                 if (which == DialogInterface.BUTTON_POSITIVE) {
    736                     // Add a little delay before executing, to give the
    737                     // dialog a chance to go away before it takes a
    738                     // screenshot.
    739                     mHandler.postDelayed(new Runnable() {
    740                         @Override public void run() {
    741                             try {
    742                                 ActivityManagerNative.getDefault()
    743                                         .requestBugReport();
    744                             } catch (RemoteException e) {
    745                             }
    746                         }
    747                     }, 500);
    748                 }
    749             }
    750         });
    751         builder.setMessage(com.android.internal.R.string.bugreport_message);
    752         builder.setTitle(com.android.internal.R.string.bugreport_title);
    753         builder.setCancelable(true);
    754         final Dialog dialog = builder.create();
    755         dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
    756         try {
    757             WindowManagerGlobal.getWindowManagerService().dismissKeyguard();
    758         } catch (RemoteException e) {
    759         }
    760         dialog.show();
    761     }
    762 
    763     private void updateWifiDisplayStatus() {
    764         mWifiDisplayStatus = mDisplayManager.getWifiDisplayStatus();
    765         applyWifiDisplayStatus();
    766     }
    767 
    768     private void applyWifiDisplayStatus() {
    769         mModel.onWifiDisplayStateChanged(mWifiDisplayStatus);
    770     }
    771 
    772     private void applyBluetoothStatus() {
    773         mModel.onBluetoothStateChange(mBluetoothState);
    774     }
    775 
    776     void reloadUserInfo() {
    777         if (mUserInfoTask != null) {
    778             mUserInfoTask.cancel(false);
    779             mUserInfoTask = null;
    780         }
    781         if (mTilesSetUp) {
    782             queryForUserInformation();
    783         }
    784     }
    785 
    786     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
    787         @Override
    788         public void onReceive(Context context, Intent intent) {
    789             final String action = intent.getAction();
    790             if (DisplayManager.ACTION_WIFI_DISPLAY_STATUS_CHANGED.equals(action)) {
    791                 WifiDisplayStatus status = (WifiDisplayStatus)intent.getParcelableExtra(
    792                         DisplayManager.EXTRA_WIFI_DISPLAY_STATUS);
    793                 mWifiDisplayStatus = status;
    794                 applyWifiDisplayStatus();
    795             } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
    796                 int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE,
    797                         BluetoothAdapter.ERROR);
    798                 mBluetoothState.enabled = (state == BluetoothAdapter.STATE_ON);
    799                 applyBluetoothStatus();
    800             } else if (BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
    801                 int status = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
    802                         BluetoothAdapter.STATE_DISCONNECTED);
    803                 mBluetoothState.connected = (status == BluetoothAdapter.STATE_CONNECTED);
    804                 applyBluetoothStatus();
    805             } else if (Intent.ACTION_USER_SWITCHED.equals(action)) {
    806                 reloadUserInfo();
    807             } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
    808                 if (mUseDefaultAvatar) {
    809                     queryForUserInformation();
    810                 }
    811             }
    812         }
    813     };
    814 
    815     private final BroadcastReceiver mProfileReceiver = new BroadcastReceiver() {
    816         @Override
    817         public void onReceive(Context context, Intent intent) {
    818             final String action = intent.getAction();
    819             if (ContactsContract.Intents.ACTION_PROFILE_CHANGED.equals(action) ||
    820                     Intent.ACTION_USER_INFO_CHANGED.equals(action)) {
    821                 try {
    822                     final int currentUser = ActivityManagerNative.getDefault().getCurrentUser().id;
    823                     final int changedUser =
    824                             intent.getIntExtra(Intent.EXTRA_USER_HANDLE, getSendingUserId());
    825                     if (changedUser == currentUser) {
    826                         reloadUserInfo();
    827                     }
    828                 } catch (RemoteException e) {
    829                     Log.e(TAG, "Couldn't get current user id for profile change", e);
    830                 }
    831             }
    832 
    833         }
    834     };
    835 }
    836