Home | History | Annotate | Download | only in tether
      1 /*
      2  * Copyright (C) 2017 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.tether;
     18 
     19 import static android.net.ConnectivityManager.TETHERING_WIFI;
     20 
     21 import android.content.BroadcastReceiver;
     22 import android.content.Context;
     23 import android.content.Intent;
     24 import android.content.IntentFilter;
     25 import android.net.ConnectivityManager;
     26 import android.net.wifi.WifiManager;
     27 import android.os.Handler;
     28 import android.os.Looper;
     29 import android.provider.Settings;
     30 import android.support.annotation.VisibleForTesting;
     31 
     32 import com.android.settings.datausage.DataSaverBackend;
     33 import com.android.settings.widget.SwitchWidgetController;
     34 import com.android.settingslib.core.lifecycle.LifecycleObserver;
     35 import com.android.settingslib.core.lifecycle.events.OnStart;
     36 import com.android.settingslib.core.lifecycle.events.OnStop;
     37 
     38 public class WifiTetherSwitchBarController implements SwitchWidgetController.OnSwitchChangeListener,
     39         LifecycleObserver, OnStart, OnStop, DataSaverBackend.Listener {
     40 
     41     private static final IntentFilter WIFI_INTENT_FILTER;
     42 
     43     private final Context mContext;
     44     private final SwitchWidgetController mSwitchBar;
     45     private final ConnectivityManager mConnectivityManager;
     46     private final WifiManager mWifiManager;
     47 
     48     @VisibleForTesting
     49     final DataSaverBackend mDataSaverBackend;
     50     @VisibleForTesting
     51     final ConnectivityManager.OnStartTetheringCallback mOnStartTetheringCallback =
     52             new ConnectivityManager.OnStartTetheringCallback() {
     53                 @Override
     54                 public void onTetheringFailed() {
     55                     super.onTetheringFailed();
     56                     mSwitchBar.setChecked(false);
     57                     updateWifiSwitch();
     58                 }
     59             };
     60 
     61     static {
     62         WIFI_INTENT_FILTER = new IntentFilter(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
     63         WIFI_INTENT_FILTER.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
     64     }
     65 
     66     WifiTetherSwitchBarController(Context context, SwitchWidgetController switchBar) {
     67         mContext = context;
     68         mSwitchBar = switchBar;
     69         mDataSaverBackend = new DataSaverBackend(context);
     70         mConnectivityManager =
     71                 (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
     72         mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
     73         mSwitchBar.setChecked(mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED);
     74         mSwitchBar.setListener(this);
     75         updateWifiSwitch();
     76     }
     77 
     78     @Override
     79     public void onStart() {
     80         mDataSaverBackend.addListener(this);
     81         mSwitchBar.startListening();
     82         mContext.registerReceiver(mReceiver, WIFI_INTENT_FILTER);
     83     }
     84 
     85     @Override
     86     public void onStop() {
     87         mDataSaverBackend.remListener(this);
     88         mSwitchBar.stopListening();
     89         mContext.unregisterReceiver(mReceiver);
     90     }
     91 
     92     @Override
     93     public boolean onSwitchToggled(boolean isChecked) {
     94         if (!isChecked) {
     95             stopTether();
     96         } else if (!mWifiManager.isWifiApEnabled()) {
     97             startTether();
     98         }
     99         return true;
    100     }
    101 
    102     void stopTether() {
    103         mSwitchBar.setEnabled(false);
    104         mConnectivityManager.stopTethering(TETHERING_WIFI);
    105     }
    106 
    107     void startTether() {
    108         mSwitchBar.setEnabled(false);
    109         mConnectivityManager.startTethering(TETHERING_WIFI, true /* showProvisioningUi */,
    110                 mOnStartTetheringCallback, new Handler(Looper.getMainLooper()));
    111     }
    112 
    113     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
    114         @Override
    115         public void onReceive(Context context, Intent intent) {
    116             String action = intent.getAction();
    117             if (WifiManager.WIFI_AP_STATE_CHANGED_ACTION.equals(action)) {
    118                 final int state = intent.getIntExtra(
    119                         WifiManager.EXTRA_WIFI_AP_STATE, WifiManager.WIFI_AP_STATE_FAILED);
    120                 handleWifiApStateChanged(state);
    121             } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
    122                 updateWifiSwitch();
    123             }
    124         }
    125     };
    126 
    127     private void handleWifiApStateChanged(int state) {
    128         switch (state) {
    129             case WifiManager.WIFI_AP_STATE_ENABLING:
    130                 mSwitchBar.setEnabled(false);
    131                 break;
    132             case WifiManager.WIFI_AP_STATE_ENABLED:
    133                 if (!mSwitchBar.isChecked()) {
    134                     mSwitchBar.setChecked(true);
    135                 }
    136                 updateWifiSwitch();
    137                 break;
    138             case WifiManager.WIFI_AP_STATE_DISABLING:
    139                 if (mSwitchBar.isChecked()) {
    140                     mSwitchBar.setChecked(false);
    141                 }
    142                 mSwitchBar.setEnabled(false);
    143                 break;
    144             case WifiManager.WIFI_AP_STATE_DISABLED:
    145                 mSwitchBar.setChecked(false);
    146                 updateWifiSwitch();
    147                 break;
    148             default:
    149                 mSwitchBar.setChecked(false);
    150                 updateWifiSwitch();
    151                 break;
    152         }
    153     }
    154 
    155     private void updateWifiSwitch() {
    156         boolean isAirplaneMode = Settings.Global.getInt(mContext.getContentResolver(),
    157                 Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
    158         if (!isAirplaneMode) {
    159             mSwitchBar.setEnabled(!mDataSaverBackend.isDataSaverEnabled());
    160         } else {
    161             mSwitchBar.setEnabled(false);
    162         }
    163     }
    164 
    165     @Override
    166     public void onDataSaverChanged(boolean isDataSaving) {
    167         updateWifiSwitch();
    168     }
    169 
    170     @Override
    171     public void onWhitelistStatusChanged(int uid, boolean isWhitelisted) {
    172         // we don't care, since we just want to read the value
    173     }
    174 
    175     @Override
    176     public void onBlacklistStatusChanged(int uid, boolean isBlacklisted) {
    177         // we don't care, since we just want to read the value
    178     }
    179 }
    180