Home | History | Annotate | Download | only in wifi
      1 /*
      2  * Copyright (C) 2018 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.settings.wifi;
     18 
     19 import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
     20 import static android.provider.SettingsSlicesContract.KEY_WIFI;
     21 
     22 import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
     23 
     24 import android.annotation.ColorInt;
     25 import android.app.PendingIntent;
     26 import android.content.ContentResolver;
     27 import android.content.Context;
     28 import android.content.Intent;
     29 import android.content.IntentFilter;
     30 import android.net.Uri;
     31 import android.net.wifi.WifiInfo;
     32 import android.net.wifi.WifiManager;
     33 import android.net.wifi.WifiSsid;
     34 import android.provider.SettingsSlicesContract;
     35 
     36 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
     37 import com.android.settings.R;
     38 import com.android.settings.SubSettings;
     39 import com.android.settings.Utils;
     40 import com.android.settings.search.DatabaseIndexingUtils;
     41 import com.android.settings.slices.SliceBroadcastReceiver;
     42 import com.android.settings.slices.SliceBuilderUtils;
     43 
     44 import androidx.slice.Slice;
     45 import androidx.slice.builders.ListBuilder;
     46 import androidx.slice.builders.SliceAction;
     47 
     48 import android.support.v4.graphics.drawable.IconCompat;
     49 import android.text.TextUtils;
     50 
     51 /**
     52  * Utility class to build a Wifi Slice, and handle all associated actions.
     53  */
     54 public class WifiSliceBuilder {
     55 
     56     /**
     57      * Backing Uri for the Wifi Slice.
     58      */
     59     public static final Uri WIFI_URI = new Uri.Builder()
     60             .scheme(ContentResolver.SCHEME_CONTENT)
     61             .authority(SettingsSlicesContract.AUTHORITY)
     62             .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
     63             .appendPath(KEY_WIFI)
     64             .build();
     65 
     66     /**
     67      * Action notifying a change on the Wifi Slice.
     68      */
     69     public static final String ACTION_WIFI_SLICE_CHANGED =
     70             "com.android.settings.wifi.action.WIFI_CHANGED";
     71 
     72     public static final IntentFilter INTENT_FILTER = new IntentFilter();
     73 
     74     static {
     75         INTENT_FILTER.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
     76         INTENT_FILTER.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
     77     }
     78 
     79     private WifiSliceBuilder() {
     80     }
     81 
     82     /**
     83      * Return a Wifi Slice bound to {@link #WIFI_URI}.
     84      * <p>
     85      * Note that you should register a listener for {@link #INTENT_FILTER} to get changes for Wifi.
     86      */
     87     public static Slice getSlice(Context context) {
     88         final boolean isWifiEnabled = isWifiEnabled(context);
     89         final IconCompat icon = IconCompat.createWithResource(context,
     90                 R.drawable.ic_settings_wireless);
     91         final String title = context.getString(R.string.wifi_settings);
     92         final CharSequence summary = getSummary(context);
     93         @ColorInt final int color = Utils.getColorAccent(context);
     94         final PendingIntent toggleAction = getBroadcastIntent(context);
     95         final PendingIntent primaryAction = getPrimaryAction(context);
     96         final SliceAction primarySliceAction = new SliceAction(primaryAction, icon, title);
     97         final SliceAction toggleSliceAction = new SliceAction(toggleAction, null /* actionTitle */,
     98                 isWifiEnabled);
     99 
    100         return new ListBuilder(context, WIFI_URI, ListBuilder.INFINITY)
    101                 .setAccentColor(color)
    102                 .addRow(b -> b
    103                         .setTitle(title)
    104                         .setSubtitle(summary)
    105                         .addEndItem(toggleSliceAction)
    106                         .setPrimaryAction(primarySliceAction))
    107                 .build();
    108     }
    109 
    110     /**
    111      * Update the current wifi status to the boolean value keyed by
    112      * {@link android.app.slice.Slice#EXTRA_TOGGLE_STATE} on {@param intent}.
    113      */
    114     public static void handleUriChange(Context context, Intent intent) {
    115         final WifiManager wifiManager = context.getSystemService(WifiManager.class);
    116         final boolean newState = intent.getBooleanExtra(EXTRA_TOGGLE_STATE,
    117                 wifiManager.isWifiEnabled());
    118         wifiManager.setWifiEnabled(newState);
    119         // Do not notifyChange on Uri. The service takes longer to update the current value than it
    120         // does for the Slice to check the current value again. Let {@link SliceBroadcastRelay}
    121         // handle it.
    122     }
    123 
    124     public static Intent getIntent(Context context) {
    125         final String screenTitle = context.getText(R.string.wifi_settings).toString();
    126         final Uri contentUri = new Uri.Builder().appendPath(KEY_WIFI).build();
    127         final Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(context,
    128                 WifiSettings.class.getName(), KEY_WIFI, screenTitle,
    129                 MetricsEvent.DIALOG_WIFI_AP_EDIT)
    130                 .setClassName(context.getPackageName(), SubSettings.class.getName())
    131                 .setData(contentUri);
    132 
    133         return intent;
    134     }
    135 
    136     private static boolean isWifiEnabled(Context context) {
    137         final WifiManager wifiManager = context.getSystemService(WifiManager.class);
    138 
    139         switch (wifiManager.getWifiState()) {
    140             case WifiManager.WIFI_STATE_ENABLED:
    141             case WifiManager.WIFI_STATE_ENABLING:
    142                 return true;
    143             case WifiManager.WIFI_STATE_DISABLED:
    144             case WifiManager.WIFI_STATE_DISABLING:
    145             case WifiManager.WIFI_STATE_UNKNOWN:
    146             default:
    147                 return false;
    148         }
    149     }
    150 
    151     private static CharSequence getSummary(Context context) {
    152         final WifiManager wifiManager = context.getSystemService(WifiManager.class);
    153 
    154         switch (wifiManager.getWifiState()) {
    155             case WifiManager.WIFI_STATE_ENABLED:
    156                 final String ssid = WifiInfo.removeDoubleQuotes(wifiManager.getConnectionInfo()
    157                         .getSSID());
    158                 if (TextUtils.equals(ssid, WifiSsid.NONE)) {
    159                     return context.getText(R.string.disconnected);
    160                 }
    161                 return ssid;
    162             case WifiManager.WIFI_STATE_ENABLING:
    163                 return context.getText(R.string.disconnected);
    164             case WifiManager.WIFI_STATE_DISABLED:
    165             case WifiManager.WIFI_STATE_DISABLING:
    166                 return context.getText(R.string.switch_off_text);
    167             case WifiManager.WIFI_STATE_UNKNOWN:
    168             default:
    169                 return "";
    170         }
    171     }
    172 
    173     private static PendingIntent getPrimaryAction(Context context) {
    174         final Intent intent = getIntent(context);
    175         return PendingIntent.getActivity(context, 0 /* requestCode */,
    176                 intent, 0 /* flags */);
    177     }
    178 
    179     private static PendingIntent getBroadcastIntent(Context context) {
    180         final Intent intent = new Intent(ACTION_WIFI_SLICE_CHANGED);
    181         intent.setClass(context, SliceBroadcastReceiver.class);
    182         return PendingIntent.getBroadcast(context, 0 /* requestCode */, intent,
    183                 PendingIntent.FLAG_CANCEL_CURRENT);
    184     }
    185 }
    186