Final platform settings UX for ephemeral networks.

Show "Connected via Wi-Fi assistant" instead of just "Connected" when
a Wi-Fi connection is ephemeral. Otherwise, treat ephemeral
connections just like saved ones - show (read-only) connection stats
when you click the network, and offer the ability to "forget" the
network, which prevents further ephemeral connections.

Bug: 18525241
Change-Id: I0d2146ab47b82d32c50b2ef883f176a6b6066713
This commit is contained in:
Jeff Davidson
2014-11-26 15:29:36 -08:00
parent 45893e65b6
commit 5ead6b92fd
6 changed files with 52 additions and 34 deletions

View File

@@ -595,7 +595,7 @@ class AccessPoint extends Preference {
* For ephemeral connections (networkId is invalid), this returns false if the network is * For ephemeral connections (networkId is invalid), this returns false if the network is
* disconnected. * disconnected.
*/ */
private boolean isActive() { boolean isActive() {
return mNetworkInfo != null && return mNetworkInfo != null &&
(networkId != WifiConfiguration.INVALID_NETWORK_ID || (networkId != WifiConfiguration.INVALID_NETWORK_ID ||
mNetworkInfo.getState() != State.DISCONNECTED); mNetworkInfo.getState() != State.DISCONNECTED);
@@ -617,7 +617,8 @@ class AccessPoint extends Preference {
StringBuilder summary = new StringBuilder(); StringBuilder summary = new StringBuilder();
if (isActive()) { // This is the active connection if (isActive()) { // This is the active connection
summary.append(Summary.get(context, getState())); summary.append(Summary.get(context, getState(),
networkId == WifiConfiguration.INVALID_NETWORK_ID));
} else if (mConfig != null } else if (mConfig != null
&& mConfig.hasNoInternetAccess()) { && mConfig.hasNoInternetAccess()) {
summary.append(context.getString(R.string.wifi_no_internet)); summary.append(context.getString(R.string.wifi_no_internet));

View File

@@ -22,7 +22,12 @@ import android.content.Context;
import android.net.NetworkInfo.DetailedState; import android.net.NetworkInfo.DetailedState;
class Summary { class Summary {
static String get(Context context, String ssid, DetailedState state) { static String get(Context context, String ssid, DetailedState state, boolean isEphemeral) {
if (state == DetailedState.CONNECTED && isEphemeral && ssid == null) {
// Special case for connected + ephemeral networks.
return context.getString(R.string.connected_via_wfa);
}
String[] formats = context.getResources().getStringArray((ssid == null) String[] formats = context.getResources().getStringArray((ssid == null)
? R.array.wifi_status : R.array.wifi_status_with_ssid); ? R.array.wifi_status : R.array.wifi_status_with_ssid);
int index = state.ordinal(); int index = state.ordinal();
@@ -33,7 +38,7 @@ class Summary {
return String.format(formats[index], ssid); return String.format(formats[index], ssid);
} }
static String get(Context context, DetailedState state) { static String get(Context context, DetailedState state, boolean isEphemeral) {
return get(context, null, state); return get(context, null, state, isEphemeral);
} }
} }

View File

@@ -242,7 +242,8 @@ public class WifiConfigController implements TextWatcher,
} }
} }
if (mAccessPoint.networkId == INVALID_NETWORK_ID || mEdit) { if ((mAccessPoint.networkId == INVALID_NETWORK_ID && !mAccessPoint.isActive())
|| mEdit) {
showSecurityFields(); showSecurityFields();
showIpConfigFields(); showIpConfigFields();
showProxyFields(); showProxyFields();
@@ -266,7 +267,8 @@ public class WifiConfigController implements TextWatcher,
} else { } else {
if (state != null) { if (state != null) {
addRow(group, R.string.wifi_status, Summary.get(mConfigUi.getContext(), addRow(group, R.string.wifi_status, Summary.get(mConfigUi.getContext(),
state)); state, mAccessPoint.networkId ==
WifiConfiguration.INVALID_NETWORK_ID));
} }
if (signalLevel != null) { if (signalLevel != null) {
@@ -300,7 +302,7 @@ public class WifiConfigController implements TextWatcher,
addRow(group, R.string.wifi_security, mAccessPoint.getSecurityString(false)); addRow(group, R.string.wifi_security, mAccessPoint.getSecurityString(false));
mView.findViewById(R.id.ip_fields).setVisibility(View.GONE); mView.findViewById(R.id.ip_fields).setVisibility(View.GONE);
} }
if (mAccessPoint.networkId != INVALID_NETWORK_ID if ((mAccessPoint.networkId != INVALID_NETWORK_ID || mAccessPoint.isActive())
&& ActivityManager.getCurrentUser() == UserHandle.USER_OWNER) { && ActivityManager.getCurrentUser() == UserHandle.USER_OWNER) {
mConfigUi.setForgetButton(res.getString(R.string.wifi_forget)); mConfigUi.setForgetButton(res.getString(R.string.wifi_forget));
} }

View File

@@ -502,26 +502,21 @@ public class WifiSettings extends RestrictedSettingsFragment
mSelectedAccessPoint = (AccessPoint) preference; mSelectedAccessPoint = (AccessPoint) preference;
menu.setHeaderTitle(mSelectedAccessPoint.ssid); menu.setHeaderTitle(mSelectedAccessPoint.ssid);
if (mSelectedAccessPoint.getLevel() != -1) { if (mSelectedAccessPoint.getLevel() != -1) {
int connectStringRes = 0;
if (mSelectedAccessPoint.getState() == null) { if (mSelectedAccessPoint.getState() == null) {
connectStringRes = R.string.wifi_menu_connect; menu.add(Menu.NONE, MENU_ID_CONNECT, 0, R.string.wifi_menu_connect);
} else if (mSelectedAccessPoint.networkId == INVALID_NETWORK_ID && }
mSelectedAccessPoint.getNetworkInfo().getState()
!= State.DISCONNECTED) {
// State is non-null (and not disconnected) but this network has no
// configuration, which means it is ephemeral. Allow the user to save the
// configuration permanently (but still issue this as a CONNECT command).
connectStringRes = R.string.wifi_menu_remember;
} }
if (connectStringRes != 0) { if (ActivityManager.getCurrentUser() == UserHandle.USER_OWNER &&
menu.add(Menu.NONE, MENU_ID_CONNECT, 0, connectStringRes); (mSelectedAccessPoint.networkId != INVALID_NETWORK_ID ||
} (mSelectedAccessPoint.getNetworkInfo() != null &&
} mSelectedAccessPoint.getNetworkInfo().getState() != State.DISCONNECTED))) {
if (mSelectedAccessPoint.networkId != INVALID_NETWORK_ID) { // Allow forgetting a network if the current user is the owner and either the
if (ActivityManager.getCurrentUser() == UserHandle.USER_OWNER) { // network is saved or ephemerally connected. (In the latter case, "forget"
// blacklists the network so it won't be used again, ephemerally).
menu.add(Menu.NONE, MENU_ID_FORGET, 0, R.string.wifi_menu_forget); menu.add(Menu.NONE, MENU_ID_FORGET, 0, R.string.wifi_menu_forget);
} }
if (mSelectedAccessPoint.networkId != INVALID_NETWORK_ID) {
menu.add(Menu.NONE, MENU_ID_MODIFY, 0, R.string.wifi_menu_modify); menu.add(Menu.NONE, MENU_ID_MODIFY, 0, R.string.wifi_menu_modify);
if (mSelectedAccessPoint.security != AccessPoint.SECURITY_NONE) { if (mSelectedAccessPoint.security != AccessPoint.SECURITY_NONE) {
@@ -552,7 +547,7 @@ public class WifiSettings extends RestrictedSettingsFragment
return true; return true;
} }
case MENU_ID_FORGET: { case MENU_ID_FORGET: {
mWifiManager.forget(mSelectedAccessPoint.networkId, mForgetListener); forget();
return true; return true;
} }
case MENU_ID_MODIFY: { case MENU_ID_MODIFY: {
@@ -571,9 +566,10 @@ public class WifiSettings extends RestrictedSettingsFragment
public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) { public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
if (preference instanceof AccessPoint) { if (preference instanceof AccessPoint) {
mSelectedAccessPoint = (AccessPoint) preference; mSelectedAccessPoint = (AccessPoint) preference;
/** Bypass dialog for unsecured, unsaved networks */ /** Bypass dialog for unsecured, unsaved, and inactive networks */
if (mSelectedAccessPoint.security == AccessPoint.SECURITY_NONE && if (mSelectedAccessPoint.security == AccessPoint.SECURITY_NONE &&
mSelectedAccessPoint.networkId == INVALID_NETWORK_ID) { mSelectedAccessPoint.networkId == INVALID_NETWORK_ID &&
!mSelectedAccessPoint.isActive()) {
mSelectedAccessPoint.generateOpenNetworkConfig(); mSelectedAccessPoint.generateOpenNetworkConfig();
if (!savedNetworksExist) { if (!savedNetworksExist) {
savedNetworksExist = true; savedNetworksExist = true;
@@ -903,12 +899,19 @@ public class WifiSettings extends RestrictedSettingsFragment
/* package */ void forget() { /* package */ void forget() {
if (mSelectedAccessPoint.networkId == INVALID_NETWORK_ID) { if (mSelectedAccessPoint.networkId == INVALID_NETWORK_ID) {
if (mSelectedAccessPoint.getNetworkInfo().getState() != State.DISCONNECTED) {
// Network is active but has no network ID - must be ephemeral.
mWifiManager.disableEphemeralNetwork(
AccessPoint.convertToQuotedString(mSelectedAccessPoint.ssid));
} else {
// Should not happen, but a monkey seems to trigger it // Should not happen, but a monkey seems to trigger it
Log.e(TAG, "Failed to forget invalid network " + mSelectedAccessPoint.getConfig()); Log.e(TAG, "Failed to forget invalid network " + mSelectedAccessPoint.getConfig());
return; return;
} }
} else {
mWifiManager.forget(mSelectedAccessPoint.networkId, mForgetListener); mWifiManager.forget(mSelectedAccessPoint.networkId, mForgetListener);
}
if (mWifiManager.isWifiEnabled()) { if (mWifiManager.isWifiEnabled()) {
mScanner.resume(); mScanner.resume();

View File

@@ -285,7 +285,7 @@ public class WifiSettingsForSetupWizardXL extends Activity implements OnClickLis
default: // DISCONNECTED, FAILED default: // DISCONNECTED, FAILED
if (mScreenState != SCREEN_STATE_CONNECTED && if (mScreenState != SCREEN_STATE_CONNECTED &&
mWifiSettings.getAccessPointsCount() > 0) { mWifiSettings.getAccessPointsCount() > 0) {
showDisconnectedState(Summary.get(this, state)); showDisconnectedState(Summary.get(this, state, false /* isEphemeral */));
} }
break; break;
} }

View File

@@ -17,12 +17,16 @@
package com.android.settings.wifi; package com.android.settings.wifi;
import com.android.settings.R; import com.android.settings.R;
import android.net.wifi.ScanResult; import android.net.wifi.ScanResult;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient; import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.DefaultHttpClient;
import java.util.List; import java.util.List;
import android.app.Activity; import android.app.Activity;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
@@ -30,6 +34,7 @@ import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.net.NetworkInfo; import android.net.NetworkInfo;
import android.net.wifi.SupplicantState; import android.net.wifi.SupplicantState;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo; import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;
import android.os.Bundle; import android.os.Bundle;
@@ -40,6 +45,7 @@ import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.widget.Button; import android.widget.Button;
import android.widget.TextView; import android.widget.TextView;
import java.io.IOException; import java.io.IOException;
import java.net.UnknownHostException; import java.net.UnknownHostException;
@@ -294,8 +300,9 @@ public class WifiStatusTest extends Activity {
private void handleNetworkStateChanged(NetworkInfo networkInfo) { private void handleNetworkStateChanged(NetworkInfo networkInfo) {
if (mWifiManager.isWifiEnabled()) { if (mWifiManager.isWifiEnabled()) {
String summary = Summary.get(this, mWifiManager.getConnectionInfo().getSSID(), WifiInfo info = mWifiManager.getConnectionInfo();
networkInfo.getDetailedState()); String summary = Summary.get(this, info.getSSID(), networkInfo.getDetailedState(),
info.getNetworkId() == WifiConfiguration.INVALID_NETWORK_ID);
mNetworkState.setText(summary); mNetworkState.setText(summary);
} }
} }