Refactor hotspot into a full page
- Deprecated WifiAPEnabler, and copied most of its logic into various controllers and WifiTetherSettings. - Added tests Fix: 37253404 Fix: 36181835 Test: make RunSettingsRoboTests Change-Id: Iad994d61b694ad7f1113d045a3e7500eeaec178b
This commit is contained in:
@@ -32,6 +32,10 @@ import com.android.settings.datausage.DataSaverBackend;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @deprecated in favor of WifiTetherPreferenceController and WifiTetherSettings
|
||||
*/
|
||||
@Deprecated
|
||||
public class WifiApEnabler {
|
||||
private final Context mContext;
|
||||
private final SwitchPreference mSwitch;
|
||||
|
@@ -110,7 +110,6 @@ public class WifiConfigController implements TextWatcher,
|
||||
public static final int WIFI_PEAP_PHASE2_AKA = 4;
|
||||
public static final int WIFI_PEAP_PHASE2_AKA_PRIME = 5;
|
||||
|
||||
private static final int SSID_ASCII_MAX_LENGTH = 32;
|
||||
|
||||
/* Phase2 methods supported by PEAP are limited */
|
||||
private final ArrayAdapter<String> mPhase2PeapAdapter;
|
||||
@@ -463,7 +462,7 @@ public class WifiConfigController implements TextWatcher,
|
||||
|
||||
if (mSsidView != null) {
|
||||
final String ssid = mSsidView.getText().toString();
|
||||
if (ssid.length() > SSID_ASCII_MAX_LENGTH) {
|
||||
if (WifiUtils.isSSIDTooLong(ssid)) {
|
||||
mView.findViewById(R.id.ssid_too_long_warning).setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
50
src/com/android/settings/wifi/WifiUtils.java
Normal file
50
src/com/android/settings/wifi/WifiUtils.java
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
public class WifiUtils {
|
||||
|
||||
private static final int SSID_ASCII_MIN_LENGTH = 1;
|
||||
private static final int SSID_ASCII_MAX_LENGTH = 32;
|
||||
private static final int PASSWORD_MIN_LENGTH = 8;
|
||||
private static final int PASSWORD_MAX_LENGTH = 63;
|
||||
|
||||
|
||||
public static boolean isSSIDTooLong(String ssid) {
|
||||
if (TextUtils.isEmpty(ssid)) {
|
||||
return false;
|
||||
}
|
||||
return ssid.length() > SSID_ASCII_MAX_LENGTH;
|
||||
}
|
||||
|
||||
public static boolean isSSIDTooShort(String ssid) {
|
||||
if (TextUtils.isEmpty(ssid)) {
|
||||
return true;
|
||||
}
|
||||
return ssid.length() < SSID_ASCII_MIN_LENGTH;
|
||||
}
|
||||
|
||||
public static boolean isPasswordValid(String password) {
|
||||
if (TextUtils.isEmpty(password)) {
|
||||
return false;
|
||||
}
|
||||
final int length = password.length();
|
||||
return length >= PASSWORD_MIN_LENGTH && length <= PASSWORD_MAX_LENGTH;
|
||||
}
|
||||
}
|
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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 android.net.ConnectivityManager;
|
||||
|
||||
class NoOpOnStartTetheringCallback extends ConnectivityManager.OnStartTetheringCallback {
|
||||
|
||||
}
|
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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 android.content.Context;
|
||||
import android.net.wifi.WifiConfiguration;
|
||||
import android.support.v7.preference.ListPreference;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
|
||||
import static android.net.wifi.WifiConfiguration.AP_BAND_2GHZ;
|
||||
import static android.net.wifi.WifiConfiguration.AP_BAND_5GHZ;
|
||||
|
||||
public class WifiTetherApBandPreferenceController extends WifiTetherBasePreferenceController {
|
||||
|
||||
private static final String PREF_KEY = "wifi_tether_network_ap_band";
|
||||
private static final String[] BAND_VALUES =
|
||||
{String.valueOf(AP_BAND_2GHZ), String.valueOf(AP_BAND_5GHZ)};
|
||||
|
||||
private final String[] mBandEntries;
|
||||
private int mBandIndex;
|
||||
|
||||
public WifiTetherApBandPreferenceController(Context context,
|
||||
OnTetherConfigUpdateListener listener) {
|
||||
super(context, listener);
|
||||
mBandEntries = mContext.getResources().getStringArray(R.array.wifi_ap_band_config_full);
|
||||
final WifiConfiguration config = mWifiManager.getWifiApConfiguration();
|
||||
if (config != null) {
|
||||
mBandIndex = config.apBand;
|
||||
} else {
|
||||
mBandIndex = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
ListPreference preference = (ListPreference) mPreference;
|
||||
if (!is5GhzBandSupported()) {
|
||||
preference.setEnabled(false);
|
||||
preference.setSummary(R.string.wifi_ap_choose_2G);
|
||||
} else {
|
||||
preference.setEntries(mBandEntries);
|
||||
preference.setEntryValues(BAND_VALUES);
|
||||
preference.setSummary(mBandEntries[mBandIndex]);
|
||||
preference.setValue(String.valueOf(mBandIndex));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return PREF_KEY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
mBandIndex = Integer.parseInt((String) newValue);
|
||||
preference.setSummary(mBandEntries[mBandIndex]);
|
||||
mListener.onTetherConfigUpdated();
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean is5GhzBandSupported() {
|
||||
if (mBandIndex > 0) {
|
||||
return true;
|
||||
}
|
||||
return mWifiManager.is5GHzBandSupported();
|
||||
}
|
||||
|
||||
public int getBandIndex() {
|
||||
return mBandIndex;
|
||||
}
|
||||
}
|
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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 android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.core.PreferenceController;
|
||||
|
||||
public abstract class WifiTetherBasePreferenceController extends PreferenceController
|
||||
implements Preference.OnPreferenceChangeListener {
|
||||
|
||||
public interface OnTetherConfigUpdateListener {
|
||||
void onTetherConfigUpdated();
|
||||
}
|
||||
|
||||
protected final WifiManager mWifiManager;
|
||||
protected final String[] mWifiRegexs;
|
||||
protected final ConnectivityManager mCm;
|
||||
protected final OnTetherConfigUpdateListener mListener;
|
||||
|
||||
protected Preference mPreference;
|
||||
|
||||
public WifiTetherBasePreferenceController(Context context,
|
||||
OnTetherConfigUpdateListener listener) {
|
||||
super(context);
|
||||
mListener = listener;
|
||||
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
|
||||
mCm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
mWifiRegexs = mCm.getTetherableWifiRegexs();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return mWifiManager != null && mWifiRegexs != null && mWifiRegexs.length > 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
mPreference = screen.findPreference(getPreferenceKey());
|
||||
}
|
||||
}
|
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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 android.content.Context;
|
||||
import android.net.wifi.WifiConfiguration;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.widget.ValidatedEditTextPreference;
|
||||
import com.android.settings.wifi.WifiUtils;
|
||||
|
||||
public class WifiTetherPasswordPreferenceController extends WifiTetherBasePreferenceController
|
||||
implements ValidatedEditTextPreference.Validator {
|
||||
|
||||
private static final String PREF_KEY = "wifi_tether_network_password";
|
||||
|
||||
private String mPassword;
|
||||
|
||||
public WifiTetherPasswordPreferenceController(Context context,
|
||||
OnTetherConfigUpdateListener listener) {
|
||||
super(context, listener);
|
||||
final WifiConfiguration config = mWifiManager.getWifiApConfiguration();
|
||||
if (config != null) {
|
||||
mPassword = config.preSharedKey;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return PREF_KEY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
((ValidatedEditTextPreference) mPreference).setText(mPassword);
|
||||
((ValidatedEditTextPreference) mPreference).setIsPassword(true);
|
||||
((ValidatedEditTextPreference) mPreference).setValidator(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
mPassword = (String) newValue;
|
||||
((ValidatedEditTextPreference) mPreference).setText(mPassword);
|
||||
mListener.onTetherConfigUpdated();
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return mPassword;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTextValid(String value) {
|
||||
return WifiUtils.isPasswordValid(value);
|
||||
}
|
||||
}
|
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* 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 android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.wifi.WifiConfiguration;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.provider.Settings;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.text.BidiFormatter;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.core.PreferenceController;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnPause;
|
||||
import com.android.settingslib.core.lifecycle.events.OnResume;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class WifiTetherPreferenceController extends PreferenceController
|
||||
implements LifecycleObserver, OnResume, OnPause {
|
||||
|
||||
public static final IntentFilter WIFI_TETHER_INTENT_FILTER;
|
||||
private static final String WIFI_TETHER_SETTINGS = "wifi_tether";
|
||||
|
||||
private final ConnectivityManager mConnectivityManager;
|
||||
private final String[] mWifiRegexs;
|
||||
private final WifiManager mWifiManager;
|
||||
private Preference mPreference;
|
||||
|
||||
static {
|
||||
WIFI_TETHER_INTENT_FILTER = new IntentFilter(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
|
||||
WIFI_TETHER_INTENT_FILTER.addAction(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
|
||||
WIFI_TETHER_INTENT_FILTER.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
|
||||
}
|
||||
|
||||
public WifiTetherPreferenceController(Context context, Lifecycle lifecycle) {
|
||||
super(context);
|
||||
mConnectivityManager =
|
||||
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
|
||||
|
||||
mWifiRegexs = mConnectivityManager.getTetherableWifiRegexs();
|
||||
|
||||
if (lifecycle != null) {
|
||||
lifecycle.addObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return mWifiRegexs != null
|
||||
&& mWifiRegexs.length != 0
|
||||
&& WifiTetherSettings.isTetherSettingPageEnabled()
|
||||
&& !Utils.isMonkeyRunning();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
mPreference = screen.findPreference(WIFI_TETHER_SETTINGS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return WIFI_TETHER_SETTINGS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
if (mPreference != null) {
|
||||
mContext.registerReceiver(mReceiver, WIFI_TETHER_INTENT_FILTER);
|
||||
clearSummaryForAirplaneMode();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
if (mPreference != null) {
|
||||
mContext.unregisterReceiver(mReceiver);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Everything below is copied from WifiApEnabler
|
||||
//
|
||||
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
if (WifiManager.WIFI_AP_STATE_CHANGED_ACTION.equals(action)) {
|
||||
int state = intent.getIntExtra(
|
||||
WifiManager.EXTRA_WIFI_AP_STATE, WifiManager.WIFI_AP_STATE_FAILED);
|
||||
int reason = intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_FAILURE_REASON,
|
||||
WifiManager.SAP_START_FAILURE_GENERAL);
|
||||
handleWifiApStateChanged(state, reason);
|
||||
} else if (ConnectivityManager.ACTION_TETHER_STATE_CHANGED.equals(action)) {
|
||||
List<String> active = intent.getStringArrayListExtra(
|
||||
ConnectivityManager.EXTRA_ACTIVE_TETHER);
|
||||
List<String> errored = intent.getStringArrayListExtra(
|
||||
ConnectivityManager.EXTRA_ERRORED_TETHER);
|
||||
updateTetherState(active.toArray(), errored.toArray());
|
||||
} else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
|
||||
clearSummaryForAirplaneMode();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void handleWifiApStateChanged(int state, int reason) {
|
||||
switch (state) {
|
||||
case WifiManager.WIFI_AP_STATE_ENABLED:
|
||||
/**
|
||||
* Summary on enable is handled by tether
|
||||
* broadcast notice
|
||||
*/
|
||||
break;
|
||||
case WifiManager.WIFI_AP_STATE_DISABLING:
|
||||
mPreference.setSummary(R.string.wifi_tether_stopping);
|
||||
break;
|
||||
case WifiManager.WIFI_AP_STATE_DISABLED:
|
||||
mPreference.setSummary(R.string.wifi_hotspot_off_subtext);
|
||||
clearSummaryForAirplaneMode();
|
||||
break;
|
||||
default:
|
||||
if (reason == WifiManager.SAP_START_FAILURE_NO_CHANNEL) {
|
||||
mPreference.setSummary(R.string.wifi_sap_no_channel_error);
|
||||
} else {
|
||||
mPreference.setSummary(R.string.wifi_error);
|
||||
}
|
||||
clearSummaryForAirplaneMode();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateTetherState(Object[] tethered, Object[] errored) {
|
||||
boolean wifiTethered = matchRegex(tethered);
|
||||
boolean wifiErrored = matchRegex(errored);
|
||||
|
||||
if (wifiTethered) {
|
||||
WifiConfiguration wifiConfig = mWifiManager.getWifiApConfiguration();
|
||||
updateConfigSummary(wifiConfig);
|
||||
} else if (wifiErrored) {
|
||||
mPreference.setSummary(R.string.wifi_error);
|
||||
} else {
|
||||
mPreference.setSummary(R.string.wifi_hotspot_off_subtext);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean matchRegex(Object[] tethers) {
|
||||
for (Object o : tethers) {
|
||||
String s = (String) o;
|
||||
for (String regex : mWifiRegexs) {
|
||||
if (s.matches(regex)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void updateConfigSummary(WifiConfiguration wifiConfig) {
|
||||
final String s = mContext.getString(
|
||||
com.android.internal.R.string.wifi_tether_configure_ssid_default);
|
||||
|
||||
mPreference.setSummary(mContext.getString(R.string.wifi_tether_enabled_subtext,
|
||||
BidiFormatter.getInstance().unicodeWrap(
|
||||
(wifiConfig == null) ? s : wifiConfig.SSID)));
|
||||
}
|
||||
|
||||
private void clearSummaryForAirplaneMode() {
|
||||
boolean isAirplaneMode = Settings.Global.getInt(mContext.getContentResolver(),
|
||||
Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
|
||||
if (isAirplaneMode) {
|
||||
mPreference.setSummary(R.string.summary_placeholder);
|
||||
}
|
||||
}
|
||||
//
|
||||
// Everything above is copied from WifiApEnabler
|
||||
//
|
||||
}
|
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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 android.content.Context;
|
||||
import android.net.wifi.WifiConfiguration;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v7.preference.EditTextPreference;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.widget.ValidatedEditTextPreference;
|
||||
import com.android.settings.wifi.WifiUtils;
|
||||
|
||||
public class WifiTetherSSIDPreferenceController extends WifiTetherBasePreferenceController
|
||||
implements ValidatedEditTextPreference.Validator {
|
||||
|
||||
private static final String PREF_KEY = "wifi_tether_network_name";
|
||||
@VisibleForTesting
|
||||
static final String DEFAULT_SSID = "AndroidAP";
|
||||
|
||||
private String mSSID;
|
||||
|
||||
public WifiTetherSSIDPreferenceController(Context context,
|
||||
OnTetherConfigUpdateListener listener) {
|
||||
super(context, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return PREF_KEY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
final WifiConfiguration config = mWifiManager.getWifiApConfiguration();
|
||||
if (config != null) {
|
||||
mSSID = config.SSID;
|
||||
} else {
|
||||
mSSID = DEFAULT_SSID;
|
||||
}
|
||||
((ValidatedEditTextPreference) mPreference).setValidator(this);
|
||||
updateSsidDisplay((EditTextPreference) mPreference);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
mSSID = (String) newValue;
|
||||
updateSsidDisplay((EditTextPreference) preference);
|
||||
mListener.onTetherConfigUpdated();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTextValid(String value) {
|
||||
return !WifiUtils.isSSIDTooLong(value) && !WifiUtils.isSSIDTooShort(value);
|
||||
}
|
||||
|
||||
public String getSSID() {
|
||||
return mSSID;
|
||||
}
|
||||
|
||||
private void updateSsidDisplay(EditTextPreference preference) {
|
||||
preference.setText(mSSID);
|
||||
preference.setSummary(mSSID);
|
||||
}
|
||||
}
|
192
src/com/android/settings/wifi/tether/WifiTetherSettings.java
Normal file
192
src/com/android/settings/wifi/tether/WifiTetherSettings.java
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* 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 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.SystemProperties;
|
||||
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.core.PreferenceController;
|
||||
import com.android.settings.dashboard.RestrictedDashboardFragment;
|
||||
import com.android.settings.widget.SwitchBar;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
|
||||
import static android.net.wifi.WifiManager.WIFI_AP_STATE_CHANGED_ACTION;
|
||||
|
||||
public class WifiTetherSettings extends RestrictedDashboardFragment
|
||||
implements WifiTetherBasePreferenceController.OnTetherConfigUpdateListener {
|
||||
|
||||
public static boolean isTetherSettingPageEnabled() {
|
||||
return SystemProperties.getBoolean("settings.ui.wifi.tether.enabled", true);
|
||||
}
|
||||
|
||||
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, 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<PreferenceController> getPreferenceControllers(Context context) {
|
||||
final List<PreferenceController> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* 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 android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.provider.Settings;
|
||||
import android.widget.Switch;
|
||||
|
||||
import com.android.settings.datausage.DataSaverBackend;
|
||||
import com.android.settings.widget.SwitchBar;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStart;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStop;
|
||||
|
||||
import static android.net.ConnectivityManager.TETHERING_WIFI;
|
||||
|
||||
public class WifiTetherSwitchBarController implements SwitchBar.OnSwitchChangeListener,
|
||||
LifecycleObserver, OnStart, OnStop {
|
||||
|
||||
private final Context mContext;
|
||||
private final SwitchBar mSwitchBar;
|
||||
private final ConnectivityManager mConnectivityManager;
|
||||
private final DataSaverBackend mDataSaverBackend;
|
||||
private final NoOpOnStartTetheringCallback mOnStartTetheringCallback;
|
||||
|
||||
WifiTetherSwitchBarController(Context context, SwitchBar switchBar) {
|
||||
mContext = context;
|
||||
mSwitchBar = switchBar;
|
||||
mDataSaverBackend = new DataSaverBackend(context);
|
||||
mOnStartTetheringCallback = new NoOpOnStartTetheringCallback();
|
||||
mConnectivityManager =
|
||||
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
mSwitchBar.addOnSwitchChangeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
mContext.registerReceiver(mReceiver,
|
||||
WifiTetherPreferenceController.WIFI_TETHER_INTENT_FILTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
mContext.unregisterReceiver(mReceiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwitchChanged(Switch switchView, boolean isChecked) {
|
||||
if (isChecked) {
|
||||
startTether();
|
||||
} else {
|
||||
stopTether();
|
||||
}
|
||||
}
|
||||
|
||||
void stopTether() {
|
||||
mSwitchBar.setEnabled(false);
|
||||
mConnectivityManager.stopTethering(TETHERING_WIFI);
|
||||
}
|
||||
|
||||
void startTether() {
|
||||
mSwitchBar.setEnabled(false);
|
||||
mConnectivityManager.startTethering(TETHERING_WIFI, true /* showProvisioningUi */,
|
||||
mOnStartTetheringCallback, new Handler(Looper.getMainLooper()));
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
if (WifiManager.WIFI_AP_STATE_CHANGED_ACTION.equals(action)) {
|
||||
final int state = intent.getIntExtra(
|
||||
WifiManager.EXTRA_WIFI_AP_STATE, WifiManager.WIFI_AP_STATE_FAILED);
|
||||
handleWifiApStateChanged(state);
|
||||
} else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
|
||||
enableWifiSwitch();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void handleWifiApStateChanged(int state) {
|
||||
switch (state) {
|
||||
case WifiManager.WIFI_AP_STATE_ENABLING:
|
||||
mSwitchBar.setEnabled(false);
|
||||
break;
|
||||
case WifiManager.WIFI_AP_STATE_ENABLED:
|
||||
if (!mSwitchBar.isChecked()) {
|
||||
mSwitchBar.setChecked(true);
|
||||
}
|
||||
enableWifiSwitch();
|
||||
break;
|
||||
case WifiManager.WIFI_AP_STATE_DISABLING:
|
||||
if (mSwitchBar.isChecked()) {
|
||||
mSwitchBar.setChecked(false);
|
||||
}
|
||||
mSwitchBar.setEnabled(false);
|
||||
break;
|
||||
case WifiManager.WIFI_AP_STATE_DISABLED:
|
||||
mSwitchBar.setChecked(false);
|
||||
enableWifiSwitch();
|
||||
break;
|
||||
default:
|
||||
mSwitchBar.setChecked(false);
|
||||
enableWifiSwitch();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void enableWifiSwitch() {
|
||||
boolean isAirplaneMode = Settings.Global.getInt(mContext.getContentResolver(),
|
||||
Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
|
||||
if (!isAirplaneMode) {
|
||||
mSwitchBar.setEnabled(!mDataSaverBackend.isDataSaverEnabled());
|
||||
} else {
|
||||
mSwitchBar.setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user