/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings.wifi.tether; import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED; import static android.net.wifi.WifiManager.WIFI_AP_STATE_CHANGED_ACTION; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; import android.os.Bundle; import android.os.UserManager; import android.support.annotation.VisibleForTesting; import android.util.Log; import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.dashboard.RestrictedDashboardFragment; import com.android.settings.widget.SwitchBar; import com.android.settings.widget.SwitchBarController; import com.android.settingslib.core.AbstractPreferenceController; import java.util.ArrayList; import java.util.List; public class WifiTetherSettings extends RestrictedDashboardFragment implements WifiTetherBasePreferenceController.OnTetherConfigUpdateListener { private static final IntentFilter TETHER_STATE_CHANGE_FILTER; private WifiTetherSwitchBarController mSwitchBarController; private WifiTetherSSIDPreferenceController mSSIDPreferenceController; private WifiTetherPasswordPreferenceController mPasswordPreferenceController; private WifiTetherApBandPreferenceController mApBandPreferenceController; private WifiManager mWifiManager; private boolean mRestartWifiApAfterConfigChange; @VisibleForTesting TetherChangeReceiver mTetherChangeReceiver; static { TETHER_STATE_CHANGE_FILTER = new IntentFilter(ACTION_TETHER_STATE_CHANGED); TETHER_STATE_CHANGE_FILTER.addAction(WIFI_AP_STATE_CHANGED_ACTION); } public WifiTetherSettings() { super(UserManager.DISALLOW_CONFIG_TETHERING); } @Override public int getMetricsCategory() { return MetricsProto.MetricsEvent.WIFI_TETHER_SETTINGS; } @Override protected String getLogTag() { return "WifiTetherSettings"; } @Override public void onAttach(Context context) { super.onAttach(context); mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); mTetherChangeReceiver = new TetherChangeReceiver(); } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); // Assume we are in a SettingsActivity. This is only safe because we currently use // SettingsActivity as base for all preference fragments. final SettingsActivity activity = (SettingsActivity) getActivity(); final SwitchBar switchBar = activity.getSwitchBar(); mSwitchBarController = new WifiTetherSwitchBarController(activity, new SwitchBarController(switchBar)); getLifecycle().addObserver(mSwitchBarController); switchBar.show(); } @Override public void onStart() { super.onStart(); final Context context = getContext(); if (context != null) { context.registerReceiver(mTetherChangeReceiver, TETHER_STATE_CHANGE_FILTER); } } @Override public void onStop() { super.onStop(); final Context context = getContext(); if (context != null) { context.unregisterReceiver(mTetherChangeReceiver); } } @Override protected int getPreferenceScreenResId() { return R.xml.wifi_tether_settings; } @Override protected List getPreferenceControllers(Context context) { final List controllers = new ArrayList<>(); mSSIDPreferenceController = new WifiTetherSSIDPreferenceController(context, this); mPasswordPreferenceController = new WifiTetherPasswordPreferenceController(context, this); mApBandPreferenceController = new WifiTetherApBandPreferenceController(context, this); controllers.add(mSSIDPreferenceController); controllers.add(mPasswordPreferenceController); controllers.add(mApBandPreferenceController); return controllers; } @Override public void onTetherConfigUpdated() { final WifiConfiguration config = buildNewConfig(); /** * if soft AP is stopped, bring up * else restart with new config * TODO: update config on a running access point when framework support is added */ if (mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED) { Log.d("TetheringSettings", "Wifi AP config changed while enabled, stop and restart"); mRestartWifiApAfterConfigChange = true; mSwitchBarController.stopTether(); } mWifiManager.setWifiApConfiguration(config); } private WifiConfiguration buildNewConfig() { final WifiConfiguration config = new WifiConfiguration(); config.SSID = mSSIDPreferenceController.getSSID(); config.preSharedKey = mPasswordPreferenceController.getPassword(); config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA2_PSK); config.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); config.apBand = mApBandPreferenceController.getBandIndex(); return config; } @VisibleForTesting class TetherChangeReceiver extends BroadcastReceiver { private static final String TAG = "TetherChangeReceiver"; @Override public void onReceive(Context content, Intent intent) { String action = intent.getAction(); if (action.equals(ACTION_TETHER_STATE_CHANGED)) { if (mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_DISABLED && mRestartWifiApAfterConfigChange) { mRestartWifiApAfterConfigChange = false; Log.d(TAG, "Restarting WifiAp due to prior config change."); mSwitchBarController.startTether(); } } else if (action.equals(WIFI_AP_STATE_CHANGED_ACTION)) { int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE, 0); if (state == WifiManager.WIFI_AP_STATE_DISABLED && mRestartWifiApAfterConfigChange) { mRestartWifiApAfterConfigChange = false; Log.d(TAG, "Restarting WifiAp due to prior config change."); mSwitchBarController.startTether(); } } } } }