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