Add modify button to WifiNetworkDetailsFragment.

Adds pencil icon to Wifi Detail action bar to modify the network.
Modifies package/public visibility to allow the detail package to
use the WifiDialog. Listens for changes in WifiConfigurations to
propagate changes to the UI in WifiNetworkDetailsFragment.

Changes WifiNetworkDetail preference launch to conform to pattern
of other Settings apps. Removes unused WifiDetailActionBarObserver.

Bug: 36483704, 37082355
Test: make -j40 RunSettingsRoboTests
Change-Id: Ie9dc1892eaefdfad4a6bd7040bfc5dbf6236cfb4
This commit is contained in:
Eric Schwarzenbach
2017-07-17 14:13:02 -07:00
parent 4dec4a0730
commit 5a7e46dd80
8 changed files with 122 additions and 140 deletions

View File

@@ -22,14 +22,14 @@
android:selectable="false" android:selectable="false"
android:order="-10000"/> android:order="-10000"/>
<!-- General Details Category -->
<PreferenceCategory
android:key="general_details_category" >
<!-- Buttons --> <!-- Buttons -->
<com.android.settings.widget.ActionButtonPreference <com.android.settings.widget.ActionButtonPreference
android:key="buttons" android:key="buttons"
android:selectable="false" /> android:selectable="false" />
<!-- General Details Category -->
<PreferenceCategory
android:key="general_details_category" >
<com.android.settings.wifi.WifiDetailPreference <com.android.settings.wifi.WifiDetailPreference
android:key="signal_strength" android:key="signal_strength"
android:title="@string/wifi_signal" android:title="@string/wifi_signal"
@@ -87,5 +87,4 @@
android:key="ipv6_addresses" android:key="ipv6_addresses"
android:selectable="false"/> android:selectable="false"/>
</PreferenceCategory> </PreferenceCategory>
</PreferenceScreen> </PreferenceScreen>

View File

@@ -492,7 +492,7 @@ public class WifiConfigController implements TextWatcher,
} }
} }
/* package */ WifiConfiguration getConfig() { public WifiConfiguration getConfig() {
if (mMode == WifiConfigUiBase.MODE_VIEW) { if (mMode == WifiConfigUiBase.MODE_VIEW) {
return null; return null;
} }

View File

@@ -27,8 +27,7 @@ import com.android.settings.R;
import com.android.settingslib.RestrictedLockUtils; import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.wifi.AccessPoint; import com.android.settingslib.wifi.AccessPoint;
// TODO(b/64069122) Have this extend a dialogfragment to handle the fullscreen launch case. public class WifiDialog extends AlertDialog implements WifiConfigUiBase, DialogInterface.OnClickListener {
class WifiDialog extends AlertDialog implements WifiConfigUiBase, DialogInterface.OnClickListener {
public interface WifiDialogListener { public interface WifiDialogListener {
void onForget(WifiDialog dialog); void onForget(WifiDialog dialog);

View File

@@ -884,17 +884,20 @@ public class WifiSettings extends RestrictedSettingsFragment
* {@link #mConnectedAccessPointPreferenceCategory}. * {@link #mConnectedAccessPointPreferenceCategory}.
*/ */
private void addConnectedAccessPointPreference(AccessPoint connectedAp) { private void addConnectedAccessPointPreference(AccessPoint connectedAp) {
String key = connectedAp.getBssid(); final LongPressAccessPointPreference pref = getOrCreatePreference(connectedAp);
LongPressAccessPointPreference pref = (LongPressAccessPointPreference)
getCachedPreference(key);
if (pref == null) {
pref = createLongPressActionPointPreference(connectedAp);
}
// Save the state of the current access point in the bundle so that we can restore it // Save the state of the current access point in the bundle so that we can restore it
// in the Wifi Network Details Fragment // in the Wifi Network Details Fragment
pref.getAccessPoint().saveWifiState(pref.getExtras()); pref.getAccessPoint().saveWifiState(pref.getExtras());
pref.setFragment(WifiNetworkDetailsFragment.class.getName());
// Launch details page on click.
pref.setOnPreferenceClickListener(preference -> {
SettingsActivity activity = (SettingsActivity) WifiSettings.this.getActivity();
activity.startPreferencePanel(this,
WifiNetworkDetailsFragment.class.getName(), pref.getExtras(),
R.string.wifi_details_title, null, null, 0);
return true;
});
pref.refresh(); pref.refresh();
mConnectedAccessPointPreferenceCategory.addPreference(pref); mConnectedAccessPointPreferenceCategory.addPreference(pref);
@@ -905,6 +908,15 @@ public class WifiSettings extends RestrictedSettingsFragment
} }
} }
private LongPressAccessPointPreference getOrCreatePreference(AccessPoint ap) {
LongPressAccessPointPreference pref = (LongPressAccessPointPreference)
getCachedPreference(AccessPointPreference.generatePreferenceKey(ap));
if (pref == null) {
pref = createLongPressActionPointPreference(ap);
}
return pref;
}
/** Removes all preferences and hide the {@link #mConnectedAccessPointPreferenceCategory}. */ /** Removes all preferences and hide the {@link #mConnectedAccessPointPreferenceCategory}. */
private void removeConnectedAccessPointPreference() { private void removeConnectedAccessPointPreference() {
mConnectedAccessPointPreferenceCategory.removeAll(); mConnectedAccessPointPreferenceCategory.removeAll();

View File

@@ -1,45 +0,0 @@
/*
* 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.details;
import android.app.Fragment;
import android.content.Context;
import android.os.Bundle;
import com.android.settings.R;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnCreate;
/**
* ActionBar lifecycle observer for {@link WifiNetworkDetailsFragment}.
*/
public class WifiDetailActionBarObserver implements LifecycleObserver, OnCreate {
private final Fragment mFragment;
private final Context mContext;
public WifiDetailActionBarObserver(Context context, Fragment fragment) {
mContext = context;
mFragment = fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
if (mFragment.getActivity() != null) {
mFragment.getActivity().getActionBar()
.setTitle(mContext.getString(R.string.wifi_details_title));
}
}
}

View File

@@ -21,6 +21,7 @@ import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static com.android.settings.wifi.WifiSettings.isEditabilityLockedDown; import static com.android.settings.wifi.WifiSettings.isEditabilityLockedDown;
import android.app.Activity;
import android.app.Fragment; import android.app.Fragment;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
@@ -48,7 +49,7 @@ import android.support.v7.preference.PreferenceScreen;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.Toast;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto; import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R; import com.android.settings.R;
@@ -60,13 +61,14 @@ import com.android.settings.vpn2.ConnectivityManagerWrapper;
import com.android.settings.widget.ActionButtonPreference; import com.android.settings.widget.ActionButtonPreference;
import com.android.settings.widget.EntityHeaderController; import com.android.settings.widget.EntityHeaderController;
import com.android.settings.wifi.WifiDetailPreference; import com.android.settings.wifi.WifiDetailPreference;
import com.android.settings.wifi.WifiDialog;
import com.android.settings.wifi.WifiDialog.WifiDialogListener;
import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnPause; import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume; import com.android.settingslib.core.lifecycle.events.OnResume;
import com.android.settingslib.wifi.AccessPoint; import com.android.settingslib.wifi.AccessPoint;
import java.net.Inet4Address; import java.net.Inet4Address;
import java.net.Inet6Address; import java.net.Inet6Address;
import java.net.InetAddress; import java.net.InetAddress;
@@ -79,7 +81,9 @@ import java.util.stream.Collectors;
* {@link WifiNetworkDetailsFragment}. * {@link WifiNetworkDetailsFragment}.
*/ */
public class WifiDetailPreferenceController extends AbstractPreferenceController public class WifiDetailPreferenceController extends AbstractPreferenceController
implements PreferenceControllerMixin, LifecycleObserver, OnPause, OnResume { implements PreferenceControllerMixin, WifiDialogListener, LifecycleObserver, OnPause,
OnResume {
private static final String TAG = "WifiDetailsPrefCtrl"; private static final String TAG = "WifiDetailsPrefCtrl";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -121,7 +125,7 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
private NetworkCapabilities mNetworkCapabilities; private NetworkCapabilities mNetworkCapabilities;
private int mRssiSignalLevel = -1; private int mRssiSignalLevel = -1;
private String[] mSignalStr; private String[] mSignalStr;
private final WifiConfiguration mWifiConfig; private WifiConfiguration mWifiConfig;
private WifiInfo mWifiInfo; private WifiInfo mWifiInfo;
private final WifiManager mWifiManager; private final WifiManager mWifiManager;
private final MetricsFeatureProvider mMetricsFeatureProvider; private final MetricsFeatureProvider mMetricsFeatureProvider;
@@ -147,9 +151,21 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) { switch (intent.getAction()) {
case WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION:
if (!intent.getBooleanExtra(WifiManager.EXTRA_MULTIPLE_NETWORKS_CHANGED,
false /* defaultValue */)) {
// only one network changed
WifiConfiguration wifiConfiguration = intent
.getParcelableExtra(WifiManager.EXTRA_WIFI_CONFIGURATION);
if (mAccessPoint.matches(wifiConfiguration)) {
mWifiConfig = wifiConfiguration;
}
}
// fall through
case WifiManager.NETWORK_STATE_CHANGED_ACTION: case WifiManager.NETWORK_STATE_CHANGED_ACTION:
case WifiManager.RSSI_CHANGED_ACTION: case WifiManager.RSSI_CHANGED_ACTION:
updateInfo(); updateInfo();
break;
} }
} }
}; };
@@ -239,6 +255,8 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
mFilter = new IntentFilter(); mFilter = new IntentFilter();
mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION); mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
mFilter.addAction(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION);
lifecycle.addObserver(this); lifecycle.addObserver(this);
} }
@@ -334,7 +352,7 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
return; return;
} }
// Update whether the forgot button should be displayed. // Update whether the forget button should be displayed.
mButtonsPref.setButton1Visible(canForgetNetwork()); mButtonsPref.setButton1Visible(canForgetNetwork());
refreshNetworkState(); refreshNetworkState();
@@ -521,6 +539,32 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
mConnectivityManagerWrapper.startCaptivePortalApp(mNetwork); mConnectivityManagerWrapper.startCaptivePortalApp(mNetwork);
} }
@Override
public void onForget(WifiDialog dialog) {
// can't forget network from a 'modify' dialog
}
@Override
public void onSubmit(WifiDialog dialog) {
if (dialog.getController() != null) {
mWifiManager.save(dialog.getController().getConfig(), new WifiManager.ActionListener() {
@Override
public void onSuccess() {
}
@Override
public void onFailure(int reason) {
Activity activity = mFragment.getActivity();
if (activity != null) {
Toast.makeText(activity,
R.string.wifi_failed_save_message,
Toast.LENGTH_SHORT).show();
}
}
});
}
}
/** /**
* Wrapper for testing compatibility. * Wrapper for testing compatibility.
*/ */

View File

@@ -15,17 +15,25 @@
*/ */
package com.android.settings.wifi.details; package com.android.settings.wifi.details;
import static com.android.settings.wifi.WifiSettings.WIFI_DIALOG_ID;
import android.app.Dialog;
import android.content.Context; import android.content.Context;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.wifi.WifiManager; import android.net.wifi.WifiManager;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import com.android.internal.logging.nano.MetricsProto; import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment; import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.vpn2.ConnectivityManagerWrapperImpl; import com.android.settings.vpn2.ConnectivityManagerWrapperImpl;
import com.android.settings.wifi.WifiDetailPreference; import com.android.settings.wifi.WifiConfigUiBase;
import com.android.settings.wifi.WifiDialog;
import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.wifi.AccessPoint; import com.android.settingslib.wifi.AccessPoint;
import java.util.ArrayList; import java.util.ArrayList;
@@ -44,13 +52,9 @@ public class WifiNetworkDetailsFragment extends DashboardFragment {
private AccessPoint mAccessPoint; private AccessPoint mAccessPoint;
private WifiDetailPreferenceController mWifiDetailPreferenceController; private WifiDetailPreferenceController mWifiDetailPreferenceController;
private WifiDetailActionBarObserver mWifiDetailActionBarObserver;
@Override @Override
public void onAttach(Context context) { public void onAttach(Context context) {
mWifiDetailActionBarObserver = new WifiDetailActionBarObserver(context, this);
getLifecycle().addObserver(mWifiDetailActionBarObserver);
mAccessPoint = new AccessPoint(context, getArguments()); mAccessPoint = new AccessPoint(context, getArguments());
super.onAttach(context); super.onAttach(context);
} }
@@ -70,6 +74,44 @@ public class WifiNetworkDetailsFragment extends DashboardFragment {
return R.xml.wifi_network_details_fragment; return R.xml.wifi_network_details_fragment;
} }
@Override
public int getDialogMetricsCategory(int dialogId) {
if (dialogId == WIFI_DIALOG_ID) {
return MetricsEvent.DIALOG_WIFI_AP_EDIT;
}
return 0;
}
@Override
public Dialog onCreateDialog(int dialogId) {
if (getActivity() == null || mWifiDetailPreferenceController == null
|| mAccessPoint == null) {
return null;
}
return WifiDialog.createModal(getActivity(), mWifiDetailPreferenceController, mAccessPoint,
WifiConfigUiBase.MODE_MODIFY);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
MenuItem item = menu.add(0, Menu.FIRST, 0, R.string.wifi_modify);
item.setIcon(R.drawable.ic_mode_edit);
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(MenuItem menuItem) {
switch (menuItem.getItemId()) {
case Menu.FIRST:
showDialog(WIFI_DIALOG_ID);
return true;
default:
return super.onOptionsItemSelected(menuItem);
}
}
@Override @Override
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) { protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
ConnectivityManager cm = context.getSystemService(ConnectivityManager.class); ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);

View File

@@ -1,69 +0,0 @@
/*
* 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.details;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.ActionBar;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import com.android.settings.R;
import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class WifiDetailActionBarObserverTest {
@Mock private Bundle mockBundle;
@Mock private Activity mockActivity;
@Mock private ActionBar mockActionBar;
@Mock private WifiNetworkDetailsFragment mockFragment;
private Context mContext = RuntimeEnvironment.application;
private Lifecycle mLifecycle;
private WifiDetailActionBarObserver mObserver;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mLifecycle = new Lifecycle();
when(mockFragment.getActivity()).thenReturn(mockActivity);
when(mockActivity.getActionBar()).thenReturn(mockActionBar);
mObserver = new WifiDetailActionBarObserver(mContext, mockFragment);
mLifecycle.addObserver(mObserver);
}
@Test
public void actionBarIsSetToNetworkInfo() {
mLifecycle.onCreate(mockBundle);
verify(mockActionBar).setTitle(mContext.getString(R.string.wifi_details_title));
}
}