• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.ACTION_TETHER_STATE_CHANGED;
20 import static android.net.wifi.WifiManager.WIFI_AP_STATE_CHANGED_ACTION;
21 
22 import android.content.BroadcastReceiver;
23 import android.content.Context;
24 import android.content.Intent;
25 import android.content.IntentFilter;
26 import android.net.wifi.WifiConfiguration;
27 import android.net.wifi.WifiManager;
28 import android.os.Bundle;
29 import android.os.UserManager;
30 import android.support.annotation.VisibleForTesting;
31 import android.util.Log;
32 
33 import com.android.internal.logging.nano.MetricsProto;
34 import com.android.settings.R;
35 import com.android.settings.SettingsActivity;
36 import com.android.settings.dashboard.RestrictedDashboardFragment;
37 import com.android.settings.widget.SwitchBar;
38 import com.android.settings.widget.SwitchBarController;
39 import com.android.settingslib.core.AbstractPreferenceController;
40 
41 import java.util.ArrayList;
42 import java.util.List;
43 
44 public class WifiTetherSettings extends RestrictedDashboardFragment
45         implements WifiTetherBasePreferenceController.OnTetherConfigUpdateListener {
46 
47     private static final String TAG = "WifiTetherSettings";
48     private static final IntentFilter TETHER_STATE_CHANGE_FILTER;
49     private static final String KEY_WIFI_TETHER_AUTO_OFF = "wifi_tether_auto_turn_off";
50 
51     private WifiTetherSwitchBarController mSwitchBarController;
52     private WifiTetherSSIDPreferenceController mSSIDPreferenceController;
53     private WifiTetherPasswordPreferenceController mPasswordPreferenceController;
54     private WifiTetherApBandPreferenceController mApBandPreferenceController;
55     private WifiTetherSecurityPreferenceController mSecurityPreferenceController;
56 
57     private WifiManager mWifiManager;
58     private boolean mRestartWifiApAfterConfigChange;
59 
60     @VisibleForTesting
61     TetherChangeReceiver mTetherChangeReceiver;
62 
63     static {
64         TETHER_STATE_CHANGE_FILTER = new IntentFilter(ACTION_TETHER_STATE_CHANGED);
65         TETHER_STATE_CHANGE_FILTER.addAction(WIFI_AP_STATE_CHANGED_ACTION);
66     }
67 
WifiTetherSettings()68     public WifiTetherSettings() {
69         super(UserManager.DISALLOW_CONFIG_TETHERING);
70     }
71 
72     @Override
getMetricsCategory()73     public int getMetricsCategory() {
74         return MetricsProto.MetricsEvent.WIFI_TETHER_SETTINGS;
75     }
76 
77     @Override
getLogTag()78     protected String getLogTag() {
79         return "WifiTetherSettings";
80     }
81 
82     @Override
onAttach(Context context)83     public void onAttach(Context context) {
84         super.onAttach(context);
85         mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
86         mTetherChangeReceiver = new TetherChangeReceiver();
87     }
88 
89     @Override
onActivityCreated(Bundle savedInstanceState)90     public void onActivityCreated(Bundle savedInstanceState) {
91         super.onActivityCreated(savedInstanceState);
92         // Assume we are in a SettingsActivity. This is only safe because we currently use
93         // SettingsActivity as base for all preference fragments.
94         final SettingsActivity activity = (SettingsActivity) getActivity();
95         final SwitchBar switchBar = activity.getSwitchBar();
96         mSwitchBarController = new WifiTetherSwitchBarController(activity,
97                 new SwitchBarController(switchBar));
98         getLifecycle().addObserver(mSwitchBarController);
99         switchBar.show();
100     }
101 
102     @Override
onStart()103     public void onStart() {
104         super.onStart();
105         final Context context = getContext();
106         if (context != null) {
107             context.registerReceiver(mTetherChangeReceiver, TETHER_STATE_CHANGE_FILTER);
108         }
109     }
110 
111     @Override
onStop()112     public void onStop() {
113         super.onStop();
114         final Context context = getContext();
115         if (context != null) {
116             context.unregisterReceiver(mTetherChangeReceiver);
117         }
118     }
119 
120 
121     @Override
getPreferenceScreenResId()122     protected int getPreferenceScreenResId() {
123         return R.xml.wifi_tether_settings;
124     }
125 
126     @Override
createPreferenceControllers(Context context)127     protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
128         final List<AbstractPreferenceController> controllers = new ArrayList<>();
129         mSSIDPreferenceController = new WifiTetherSSIDPreferenceController(context, this);
130         mSecurityPreferenceController = new WifiTetherSecurityPreferenceController(context, this);
131         mPasswordPreferenceController = new WifiTetherPasswordPreferenceController(context, this);
132         mApBandPreferenceController = new WifiTetherApBandPreferenceController(context, this);
133 
134         controllers.add(mSSIDPreferenceController);
135         controllers.add(mSecurityPreferenceController);
136         controllers.add(mPasswordPreferenceController);
137         controllers.add(mApBandPreferenceController);
138         controllers.add(
139                 new WifiTetherAutoOffPreferenceController(context, KEY_WIFI_TETHER_AUTO_OFF));
140         return controllers;
141     }
142 
143     @Override
onTetherConfigUpdated()144     public void onTetherConfigUpdated() {
145         final WifiConfiguration config = buildNewConfig();
146         mPasswordPreferenceController.updateVisibility(config.getAuthType());
147 
148         /**
149          * if soft AP is stopped, bring up
150          * else restart with new config
151          * TODO: update config on a running access point when framework support is added
152          */
153         if (mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED) {
154             Log.d("TetheringSettings",
155                     "Wifi AP config changed while enabled, stop and restart");
156             mRestartWifiApAfterConfigChange = true;
157             mSwitchBarController.stopTether();
158         }
159         mWifiManager.setWifiApConfiguration(config);
160     }
161 
buildNewConfig()162     private WifiConfiguration buildNewConfig() {
163         final WifiConfiguration config = new WifiConfiguration();
164         final int securityType = mSecurityPreferenceController.getSecurityType();
165 
166         config.SSID = mSSIDPreferenceController.getSSID();
167         config.allowedKeyManagement.set(securityType);
168         config.preSharedKey = mPasswordPreferenceController.getPasswordValidated(securityType);
169         config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
170         config.apBand = mApBandPreferenceController.getBandIndex();
171         return config;
172     }
173 
startTether()174     private void startTether() {
175         mRestartWifiApAfterConfigChange = false;
176         mSwitchBarController.startTether();
177     }
178 
updateDisplayWithNewConfig()179     private void updateDisplayWithNewConfig() {
180         use(WifiTetherSSIDPreferenceController.class)
181                 .updateDisplay();
182         use(WifiTetherSecurityPreferenceController.class)
183                 .updateDisplay();
184         use(WifiTetherPasswordPreferenceController.class)
185                 .updateDisplay();
186         use(WifiTetherApBandPreferenceController.class)
187                 .updateDisplay();
188     }
189 
190     @VisibleForTesting
191     class TetherChangeReceiver extends BroadcastReceiver {
192         @Override
onReceive(Context content, Intent intent)193         public void onReceive(Context content, Intent intent) {
194             String action = intent.getAction();
195             Log.d(TAG, "updating display config due to receiving broadcast action " + action);
196             updateDisplayWithNewConfig();
197             if (action.equals(ACTION_TETHER_STATE_CHANGED)) {
198                 if (mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_DISABLED
199                         && mRestartWifiApAfterConfigChange) {
200                     startTether();
201                 }
202             } else if (action.equals(WIFI_AP_STATE_CHANGED_ACTION)) {
203                 int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE, 0);
204                 if (state == WifiManager.WIFI_AP_STATE_DISABLED
205                         && mRestartWifiApAfterConfigChange) {
206                     startTether();
207                 }
208             }
209         }
210     }
211 }
212