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