Home | History | Annotate | Download | only in phone
      1 /*
      2  * Copyright (C) 2014 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 android.content.Context;
     20 import android.content.Intent;
     21 import android.content.res.Resources;
     22 import android.os.HandlerThread;
     23 import android.os.Looper;
     24 import android.os.Process;
     25 import android.util.Log;
     26 
     27 import com.android.systemui.R;
     28 import com.android.systemui.qs.QSTile;
     29 import com.android.systemui.qs.tiles.AirplaneModeTile;
     30 import com.android.systemui.qs.tiles.BluetoothTile;
     31 import com.android.systemui.qs.tiles.CastTile;
     32 import com.android.systemui.qs.tiles.CellularTile;
     33 import com.android.systemui.qs.tiles.ColorInversionTile;
     34 import com.android.systemui.qs.tiles.DndTile;
     35 import com.android.systemui.qs.tiles.FlashlightTile;
     36 import com.android.systemui.qs.tiles.HotspotTile;
     37 import com.android.systemui.qs.tiles.IntentTile;
     38 import com.android.systemui.qs.tiles.LocationTile;
     39 import com.android.systemui.qs.tiles.RotationLockTile;
     40 import com.android.systemui.qs.tiles.WifiTile;
     41 import com.android.systemui.statusbar.policy.BluetoothController;
     42 import com.android.systemui.statusbar.policy.CastController;
     43 import com.android.systemui.statusbar.policy.FlashlightController;
     44 import com.android.systemui.statusbar.policy.HotspotController;
     45 import com.android.systemui.statusbar.policy.KeyguardMonitor;
     46 import com.android.systemui.statusbar.policy.LocationController;
     47 import com.android.systemui.statusbar.policy.NetworkController;
     48 import com.android.systemui.statusbar.policy.RotationLockController;
     49 import com.android.systemui.statusbar.policy.SecurityController;
     50 import com.android.systemui.statusbar.policy.UserSwitcherController;
     51 import com.android.systemui.statusbar.policy.ZenModeController;
     52 import com.android.systemui.tuner.TunerService;
     53 import com.android.systemui.tuner.TunerService.Tunable;
     54 
     55 import java.util.ArrayList;
     56 import java.util.Arrays;
     57 import java.util.Collection;
     58 import java.util.LinkedHashMap;
     59 import java.util.List;
     60 import java.util.Map;
     61 
     62 /** Platform implementation of the quick settings tile host **/
     63 public class QSTileHost implements QSTile.Host, Tunable {
     64     private static final String TAG = "QSTileHost";
     65     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     66 
     67     protected static final String TILES_SETTING = "sysui_qs_tiles";
     68 
     69     private final Context mContext;
     70     private final PhoneStatusBar mStatusBar;
     71     private final LinkedHashMap<String, QSTile<?>> mTiles = new LinkedHashMap<>();
     72     protected final ArrayList<String> mTileSpecs = new ArrayList<>();
     73     private final BluetoothController mBluetooth;
     74     private final LocationController mLocation;
     75     private final RotationLockController mRotation;
     76     private final NetworkController mNetwork;
     77     private final ZenModeController mZen;
     78     private final HotspotController mHotspot;
     79     private final CastController mCast;
     80     private final Looper mLooper;
     81     private final FlashlightController mFlashlight;
     82     private final UserSwitcherController mUserSwitcherController;
     83     private final KeyguardMonitor mKeyguard;
     84     private final SecurityController mSecurity;
     85 
     86     private Callback mCallback;
     87 
     88     public QSTileHost(Context context, PhoneStatusBar statusBar,
     89             BluetoothController bluetooth, LocationController location,
     90             RotationLockController rotation, NetworkController network,
     91             ZenModeController zen, HotspotController hotspot,
     92             CastController cast, FlashlightController flashlight,
     93             UserSwitcherController userSwitcher, KeyguardMonitor keyguard,
     94             SecurityController security) {
     95         mContext = context;
     96         mStatusBar = statusBar;
     97         mBluetooth = bluetooth;
     98         mLocation = location;
     99         mRotation = rotation;
    100         mNetwork = network;
    101         mZen = zen;
    102         mHotspot = hotspot;
    103         mCast = cast;
    104         mFlashlight = flashlight;
    105         mUserSwitcherController = userSwitcher;
    106         mKeyguard = keyguard;
    107         mSecurity = security;
    108 
    109         final HandlerThread ht = new HandlerThread(QSTileHost.class.getSimpleName(),
    110                 Process.THREAD_PRIORITY_BACKGROUND);
    111         ht.start();
    112         mLooper = ht.getLooper();
    113 
    114         TunerService.get(mContext).addTunable(this, TILES_SETTING);
    115     }
    116 
    117     public void destroy() {
    118         TunerService.get(mContext).removeTunable(this);
    119     }
    120 
    121     @Override
    122     public void setCallback(Callback callback) {
    123         mCallback = callback;
    124     }
    125 
    126     @Override
    127     public Collection<QSTile<?>> getTiles() {
    128         return mTiles.values();
    129     }
    130 
    131     @Override
    132     public void startActivityDismissingKeyguard(final Intent intent) {
    133         mStatusBar.postStartActivityDismissingKeyguard(intent, 0);
    134     }
    135 
    136     @Override
    137     public void warn(String message, Throwable t) {
    138         // already logged
    139     }
    140 
    141     @Override
    142     public void collapsePanels() {
    143         mStatusBar.postAnimateCollapsePanels();
    144     }
    145 
    146     @Override
    147     public Looper getLooper() {
    148         return mLooper;
    149     }
    150 
    151     @Override
    152     public Context getContext() {
    153         return mContext;
    154     }
    155 
    156     @Override
    157     public BluetoothController getBluetoothController() {
    158         return mBluetooth;
    159     }
    160 
    161     @Override
    162     public LocationController getLocationController() {
    163         return mLocation;
    164     }
    165 
    166     @Override
    167     public RotationLockController getRotationLockController() {
    168         return mRotation;
    169     }
    170 
    171     @Override
    172     public NetworkController getNetworkController() {
    173         return mNetwork;
    174     }
    175 
    176     @Override
    177     public ZenModeController getZenModeController() {
    178         return mZen;
    179     }
    180 
    181     @Override
    182     public HotspotController getHotspotController() {
    183         return mHotspot;
    184     }
    185 
    186     @Override
    187     public CastController getCastController() {
    188         return mCast;
    189     }
    190 
    191     @Override
    192     public FlashlightController getFlashlightController() {
    193         return mFlashlight;
    194     }
    195 
    196     @Override
    197     public KeyguardMonitor getKeyguardMonitor() {
    198         return mKeyguard;
    199     }
    200 
    201     public UserSwitcherController getUserSwitcherController() {
    202         return mUserSwitcherController;
    203     }
    204 
    205     public SecurityController getSecurityController() {
    206         return mSecurity;
    207     }
    208 
    209     @Override
    210     public void onTuningChanged(String key, String newValue) {
    211         if (!TILES_SETTING.equals(key)) {
    212             return;
    213         }
    214         if (DEBUG) Log.d(TAG, "Recreating tiles");
    215         final List<String> tileSpecs = loadTileSpecs(newValue);
    216         if (tileSpecs.equals(mTileSpecs)) return;
    217         for (Map.Entry<String, QSTile<?>> tile : mTiles.entrySet()) {
    218             if (!tileSpecs.contains(tile.getKey())) {
    219                 if (DEBUG) Log.d(TAG, "Destroying tile: " + tile.getKey());
    220                 tile.getValue().destroy();
    221             }
    222         }
    223         final LinkedHashMap<String, QSTile<?>> newTiles = new LinkedHashMap<>();
    224         for (String tileSpec : tileSpecs) {
    225             if (mTiles.containsKey(tileSpec)) {
    226                 newTiles.put(tileSpec, mTiles.get(tileSpec));
    227             } else {
    228                 if (DEBUG) Log.d(TAG, "Creating tile: " + tileSpec);
    229                 try {
    230                     newTiles.put(tileSpec, createTile(tileSpec));
    231                 } catch (Throwable t) {
    232                     Log.w(TAG, "Error creating tile for spec: " + tileSpec, t);
    233                 }
    234             }
    235         }
    236         mTileSpecs.clear();
    237         mTileSpecs.addAll(tileSpecs);
    238         mTiles.clear();
    239         mTiles.putAll(newTiles);
    240         if (mCallback != null) {
    241             mCallback.onTilesChanged();
    242         }
    243     }
    244 
    245     protected QSTile<?> createTile(String tileSpec) {
    246         if (tileSpec.equals("wifi")) return new WifiTile(this);
    247         else if (tileSpec.equals("bt")) return new BluetoothTile(this);
    248         else if (tileSpec.equals("inversion")) return new ColorInversionTile(this);
    249         else if (tileSpec.equals("cell")) return new CellularTile(this);
    250         else if (tileSpec.equals("airplane")) return new AirplaneModeTile(this);
    251         else if (tileSpec.equals("dnd")) return new DndTile(this);
    252         else if (tileSpec.equals("rotation")) return new RotationLockTile(this);
    253         else if (tileSpec.equals("flashlight")) return new FlashlightTile(this);
    254         else if (tileSpec.equals("location")) return new LocationTile(this);
    255         else if (tileSpec.equals("cast")) return new CastTile(this);
    256         else if (tileSpec.equals("hotspot")) return new HotspotTile(this);
    257         else if (tileSpec.startsWith(IntentTile.PREFIX)) return IntentTile.create(this,tileSpec);
    258         else throw new IllegalArgumentException("Bad tile spec: " + tileSpec);
    259     }
    260 
    261     protected List<String> loadTileSpecs(String tileList) {
    262         final Resources res = mContext.getResources();
    263         final String defaultTileList = res.getString(R.string.quick_settings_tiles_default);
    264         if (tileList == null) {
    265             tileList = res.getString(R.string.quick_settings_tiles);
    266             if (DEBUG) Log.d(TAG, "Loaded tile specs from config: " + tileList);
    267         } else {
    268             if (DEBUG) Log.d(TAG, "Loaded tile specs from setting: " + tileList);
    269         }
    270         final ArrayList<String> tiles = new ArrayList<String>();
    271         boolean addedDefault = false;
    272         for (String tile : tileList.split(",")) {
    273             tile = tile.trim();
    274             if (tile.isEmpty()) continue;
    275             if (tile.equals("default")) {
    276                 if (!addedDefault) {
    277                     tiles.addAll(Arrays.asList(defaultTileList.split(",")));
    278                     addedDefault = true;
    279                 }
    280             } else {
    281                 tiles.add(tile);
    282             }
    283         }
    284         return tiles;
    285     }
    286 }
    287