Home | History | Annotate | Download | only in tiles
      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.qs.tiles;
     18 
     19 import android.content.Context;
     20 import android.content.Intent;
     21 import android.content.res.Resources;
     22 import android.provider.Settings;
     23 import android.util.Log;
     24 import android.view.View;
     25 import android.view.ViewGroup;
     26 
     27 import com.android.systemui.R;
     28 import com.android.systemui.qs.QSDetailItems;
     29 import com.android.systemui.qs.QSDetailItems.Item;
     30 import com.android.systemui.qs.QSTile;
     31 import com.android.systemui.qs.QSTileView;
     32 import com.android.systemui.qs.SignalTileView;
     33 import com.android.systemui.statusbar.phone.QSTileHost;
     34 import com.android.systemui.statusbar.policy.NetworkController;
     35 import com.android.systemui.statusbar.policy.NetworkController.AccessPointController;
     36 import com.android.systemui.statusbar.policy.NetworkController.AccessPointController.AccessPoint;
     37 import com.android.systemui.statusbar.policy.NetworkController.NetworkSignalChangedCallback;
     38 
     39 /** Quick settings tile: Wifi **/
     40 public class WifiTile extends QSTile<QSTile.SignalState> {
     41     private static final Intent WIFI_SETTINGS = new Intent(Settings.ACTION_WIFI_SETTINGS);
     42 
     43     private final NetworkController mController;
     44     private final AccessPointController mWifiController;
     45     private final WifiDetailAdapter mDetailAdapter;
     46     private final QSTile.SignalState mStateBeforeClick = newTileState();
     47 
     48     public WifiTile(Host host) {
     49         super(host);
     50         mController = host.getNetworkController();
     51         mWifiController = mController.getAccessPointController();
     52         mDetailAdapter = new WifiDetailAdapter();
     53     }
     54 
     55     @Override
     56     public boolean supportsDualTargets() {
     57         return true;
     58     }
     59 
     60     @Override
     61     protected SignalState newTileState() {
     62         return new SignalState();
     63     }
     64 
     65     @Override
     66     public void setListening(boolean listening) {
     67         if (listening) {
     68             mController.addNetworkSignalChangedCallback(mCallback);
     69             mWifiController.addAccessPointCallback(mDetailAdapter);
     70         } else {
     71             mController.removeNetworkSignalChangedCallback(mCallback);
     72             mWifiController.removeAccessPointCallback(mDetailAdapter);
     73         }
     74     }
     75 
     76     @Override
     77     public DetailAdapter getDetailAdapter() {
     78         return mDetailAdapter;
     79     }
     80 
     81     @Override
     82     public QSTileView createTileView(Context context) {
     83         return new SignalTileView(context);
     84     }
     85 
     86     @Override
     87     protected void handleClick() {
     88         mState.copyTo(mStateBeforeClick);
     89         mController.setWifiEnabled(!mState.enabled);
     90     }
     91 
     92     @Override
     93     protected void handleSecondaryClick() {
     94         if (!mWifiController.canConfigWifi()) {
     95             mHost.startSettingsActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
     96             return;
     97         }
     98         if (!mState.enabled) {
     99             mController.setWifiEnabled(true);
    100             mState.enabled = true;
    101         }
    102         showDetail(true);
    103     }
    104 
    105     @Override
    106     protected void handleUpdateState(SignalState state, Object arg) {
    107         state.visible = true;
    108         if (DEBUG) Log.d(TAG, "handleUpdateState arg=" + arg);
    109         if (arg == null) return;
    110         CallbackInfo cb = (CallbackInfo) arg;
    111 
    112         boolean wifiConnected = cb.enabled && (cb.wifiSignalIconId > 0) && (cb.enabledDesc != null);
    113         boolean wifiNotConnected = (cb.wifiSignalIconId > 0) && (cb.enabledDesc == null);
    114         boolean enabledChanging = state.enabled != cb.enabled;
    115         if (enabledChanging) {
    116             mDetailAdapter.setItemsVisible(cb.enabled);
    117             fireToggleStateChanged(cb.enabled);
    118         }
    119         state.enabled = cb.enabled;
    120         state.connected = wifiConnected;
    121         state.activityIn = cb.enabled && cb.activityIn;
    122         state.activityOut = cb.enabled && cb.activityOut;
    123         state.filter = true;
    124         final String signalContentDescription;
    125         final Resources r = mContext.getResources();
    126         if (!state.enabled) {
    127             state.icon = ResourceIcon.get(R.drawable.ic_qs_wifi_disabled);
    128             state.label = r.getString(R.string.quick_settings_wifi_label);
    129             signalContentDescription = r.getString(R.string.accessibility_wifi_off);
    130         } else if (wifiConnected) {
    131             state.icon = ResourceIcon.get(cb.wifiSignalIconId);
    132             state.label = removeDoubleQuotes(cb.enabledDesc);
    133             signalContentDescription = cb.wifiSignalContentDescription;
    134         } else if (wifiNotConnected) {
    135             state.icon = ResourceIcon.get(R.drawable.ic_qs_wifi_0);
    136             state.label = r.getString(R.string.quick_settings_wifi_label);
    137             signalContentDescription = r.getString(R.string.accessibility_no_wifi);
    138         } else {
    139             state.icon = ResourceIcon.get(R.drawable.ic_qs_wifi_no_network);
    140             state.label = r.getString(R.string.quick_settings_wifi_label);
    141             signalContentDescription = r.getString(R.string.accessibility_wifi_off);
    142         }
    143         state.contentDescription = mContext.getString(
    144                 R.string.accessibility_quick_settings_wifi,
    145                 signalContentDescription);
    146         String wifiName = state.label;
    147         if (state.connected) {
    148             wifiName = r.getString(R.string.accessibility_wifi_name, state.label);
    149         }
    150         state.dualLabelContentDescription = wifiName;
    151     }
    152 
    153     @Override
    154     protected boolean shouldAnnouncementBeDelayed() {
    155         return mStateBeforeClick.enabled == mState.enabled;
    156     }
    157 
    158     @Override
    159     protected String composeChangeAnnouncement() {
    160         if (mState.enabled) {
    161             return mContext.getString(R.string.accessibility_quick_settings_wifi_changed_on);
    162         } else {
    163             return mContext.getString(R.string.accessibility_quick_settings_wifi_changed_off);
    164         }
    165     }
    166 
    167     private static String removeDoubleQuotes(String string) {
    168         if (string == null) return null;
    169         final int length = string.length();
    170         if ((length > 1) && (string.charAt(0) == '"') && (string.charAt(length - 1) == '"')) {
    171             return string.substring(1, length - 1);
    172         }
    173         return string;
    174     }
    175 
    176     private static final class CallbackInfo {
    177         boolean enabled;
    178         boolean connected;
    179         int wifiSignalIconId;
    180         String enabledDesc;
    181         boolean activityIn;
    182         boolean activityOut;
    183         String wifiSignalContentDescription;
    184 
    185         @Override
    186         public String toString() {
    187             return new StringBuilder("CallbackInfo[")
    188                 .append("enabled=").append(enabled)
    189                 .append(",connected=").append(connected)
    190                 .append(",wifiSignalIconId=").append(wifiSignalIconId)
    191                 .append(",enabledDesc=").append(enabledDesc)
    192                 .append(",activityIn=").append(activityIn)
    193                 .append(",activityOut=").append(activityOut)
    194                 .append(",wifiSignalContentDescription=").append(wifiSignalContentDescription)
    195                 .append(']').toString();
    196         }
    197     }
    198 
    199     private final NetworkSignalChangedCallback mCallback = new NetworkSignalChangedCallback() {
    200         @Override
    201         public void onWifiSignalChanged(boolean enabled, boolean connected, int wifiSignalIconId,
    202                 boolean activityIn, boolean activityOut,
    203                 String wifiSignalContentDescriptionId, String description) {
    204             if (DEBUG) Log.d(TAG, "onWifiSignalChanged enabled=" + enabled);
    205             final CallbackInfo info = new CallbackInfo();
    206             info.enabled = enabled;
    207             info.connected = connected;
    208             info.wifiSignalIconId = wifiSignalIconId;
    209             info.enabledDesc = description;
    210             info.activityIn = activityIn;
    211             info.activityOut = activityOut;
    212             info.wifiSignalContentDescription = wifiSignalContentDescriptionId;
    213             refreshState(info);
    214         }
    215 
    216         @Override
    217         public void onMobileDataSignalChanged(boolean enabled,
    218                 int mobileSignalIconId,
    219                 String mobileSignalContentDescriptionId, int dataTypeIconId,
    220                 boolean activityIn, boolean activityOut,
    221                 String dataTypeContentDescriptionId, String description,
    222                 boolean isDataTypeIconWide) {
    223             // noop
    224         }
    225 
    226         public void onNoSimVisibleChanged(boolean noSims) {
    227             // noop
    228         }
    229 
    230         @Override
    231         public void onAirplaneModeChanged(boolean enabled) {
    232             // noop
    233         }
    234 
    235         @Override
    236         public void onMobileDataEnabled(boolean enabled) {
    237             // noop
    238         }
    239     };
    240 
    241     private final class WifiDetailAdapter implements DetailAdapter,
    242             NetworkController.AccessPointController.AccessPointCallback, QSDetailItems.Callback {
    243 
    244         private QSDetailItems mItems;
    245         private AccessPoint[] mAccessPoints;
    246 
    247         @Override
    248         public int getTitle() {
    249             return R.string.quick_settings_wifi_label;
    250         }
    251 
    252         public Intent getSettingsIntent() {
    253             return WIFI_SETTINGS;
    254         }
    255 
    256         @Override
    257         public Boolean getToggleState() {
    258             return mState.enabled;
    259         }
    260 
    261         @Override
    262         public void setToggleState(boolean state) {
    263             if (DEBUG) Log.d(TAG, "setToggleState " + state);
    264             mController.setWifiEnabled(state);
    265             showDetail(false);
    266         }
    267 
    268         @Override
    269         public View createDetailView(Context context, View convertView, ViewGroup parent) {
    270             if (DEBUG) Log.d(TAG, "createDetailView convertView=" + (convertView != null));
    271             mAccessPoints = null;
    272             mWifiController.scanForAccessPoints();
    273             fireScanStateChanged(true);
    274             mItems = QSDetailItems.convertOrInflate(context, convertView, parent);
    275             mItems.setTagSuffix("Wifi");
    276             mItems.setCallback(this);
    277             mItems.setEmptyState(R.drawable.ic_qs_wifi_detail_empty,
    278                     R.string.quick_settings_wifi_detail_empty_text);
    279             updateItems();
    280             setItemsVisible(mState.enabled);
    281             return mItems;
    282         }
    283 
    284         @Override
    285         public void onAccessPointsChanged(final AccessPoint[] accessPoints) {
    286             mAccessPoints = accessPoints;
    287             updateItems();
    288             if (accessPoints != null && accessPoints.length > 0) {
    289                 fireScanStateChanged(false);
    290             }
    291         }
    292 
    293         @Override
    294         public void onSettingsActivityTriggered(Intent settingsIntent) {
    295             mHost.startSettingsActivity(settingsIntent);
    296         }
    297 
    298         @Override
    299         public void onDetailItemClick(Item item) {
    300             if (item == null || item.tag == null) return;
    301             final AccessPoint ap = (AccessPoint) item.tag;
    302             if (!ap.isConnected) {
    303                 if (mWifiController.connect(ap)) {
    304                     mHost.collapsePanels();
    305                 }
    306             }
    307             showDetail(false);
    308         }
    309 
    310         @Override
    311         public void onDetailItemDisconnect(Item item) {
    312             // noop
    313         }
    314 
    315         public void setItemsVisible(boolean visible) {
    316             if (mItems == null) return;
    317             mItems.setItemsVisible(visible);
    318         }
    319 
    320         private void updateItems() {
    321             if (mItems == null) return;
    322             Item[] items = null;
    323             if (mAccessPoints != null) {
    324                 items = new Item[mAccessPoints.length];
    325                 for (int i = 0; i < mAccessPoints.length; i++) {
    326                     final AccessPoint ap = mAccessPoints[i];
    327                     final Item item = new Item();
    328                     item.tag = ap;
    329                     item.icon = ap.iconId;
    330                     item.line1 = ap.ssid;
    331                     if (ap.isConnected) {
    332                         item.line2 = mContext.getString(ap.isConfigured ?
    333                                 R.string.quick_settings_connected :
    334                                 R.string.quick_settings_connected_via_wfa);
    335                     } else if (ap.networkId >= 0) {
    336                         // TODO: Set line 2 to wifi saved string here.
    337                     }
    338                     item.overlay = ap.hasSecurity
    339                             ? mContext.getDrawable(R.drawable.qs_ic_wifi_lock)
    340                             : null;
    341                     items[i] = item;
    342                 }
    343             }
    344             mItems.setItems(items);
    345         }
    346     };
    347 }
    348