From c1854cae9a4bccafc535b967d265fb1742f3444a Mon Sep 17 00:00:00 2001 From: cosmohsieh Date: Mon, 24 Dec 2018 11:24:48 +0800 Subject: [PATCH 1/8] Implement persisting time for onUserSelectionConnectSuccess. When onUserSelectionConnectSuccess callbacks, holding a second for user to be aware of success connection. Then, go to destory network request dialog. Bug: 117399926 Test: make RunSettingsRoboTests -j32 ROBOTEST_FILTER=com.android.settings.wifi.NetworkRequestDialogFragmentTest Change-Id: I12d8fb2e8955cf24ddad43d1fe8b863682b6ae32 --- .../wifi/NetworkRequestDialogFragment.java | 79 +++++++++++++------ .../NetworkRequestDialogFragmentTest.java | 30 ++++--- 2 files changed, 76 insertions(+), 33 deletions(-) diff --git a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java index 7a1bdb43f51..06e36e5caa9 100644 --- a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java +++ b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java @@ -16,7 +16,6 @@ package com.android.settings.wifi; -import android.app.Activity; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; @@ -67,9 +66,15 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp /** Message sent to us to stop scanning wifi and pop up timeout dialog. */ private static final int MESSAGE_STOP_SCAN_WIFI_LIST = 0; + /** Message sent to us to finish activity. */ + private static final int MESSAGE_FINISH_ACTIVITY = 1; + /** Spec defines there should be 5 wifi ap on the list at most. */ private static final int MAX_NUMBER_LIST_ITEM = 5; + /** Holding time to let user be aware that selected wifi ap is connected */ + private static final int DELAY_TIME_USER_AWARE_CONNECTED_MS = 1 * 1000; + /** Delayed time to stop scanning wifi. */ private static final int DELAY_TIME_STOP_SCAN_MS = 30 * 1000; @@ -155,7 +160,9 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp public void onCancel(@NonNull DialogInterface dialog) { super.onCancel(dialog); // Finishes the activity when user clicks back key or outside of the dialog. - getActivity().finish(); + if (getActivity() != null) { + getActivity().finish(); + } } @Override @@ -177,6 +184,8 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp @Override public void onDestroy() { super.onDestroy(); + + mHandler.removeMessages(MESSAGE_FINISH_ACTIVITY); if (mFilterWifiTracker != null) { mFilterWifiTracker.onDestroy(); mFilterWifiTracker = null; @@ -207,7 +216,10 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp switch (msg.what) { case MESSAGE_STOP_SCAN_WIFI_LIST: removeMessages(MESSAGE_STOP_SCAN_WIFI_LIST); - stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE.TIME_OUT); + stopScanningAndMaybePopErrorDialog(ERROR_DIALOG_TYPE.TIME_OUT); + break; + case MESSAGE_FINISH_ACTIVITY: + stopScanningAndMaybePopErrorDialog(/* ERROR_DIALOG_TYPE */ null); break; default: // Do nothing. @@ -216,18 +228,29 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp } }; - protected void stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE type) { + protected void stopScanningAndMaybePopErrorDialog(ERROR_DIALOG_TYPE type) { // Dismisses current dialog. - dismiss(); + final Dialog dialog = getDialog(); + if (dialog != null && dialog.isShowing()) { + dismiss(); + } + + if (type == null) { + // If no error, finishes activity. + if (getActivity() != null) { + getActivity().finish(); + } + } else { + // Throws error dialog. + final NetworkRequestErrorDialogFragment fragment = NetworkRequestErrorDialogFragment + .newInstance(); + final Bundle bundle = new Bundle(); + bundle.putSerializable(NetworkRequestErrorDialogFragment.DIALOG_TYPE, type); + fragment.setArguments(bundle); + fragment.show(getActivity().getSupportFragmentManager(), + NetworkRequestDialogFragment.class.getSimpleName()); + } - // Throws new timeout dialog. - final NetworkRequestErrorDialogFragment fragment = NetworkRequestErrorDialogFragment - .newInstance(); - final Bundle bundle = new Bundle(); - bundle.putSerializable(NetworkRequestErrorDialogFragment.DIALOG_TYPE, type); - fragment.setArguments(bundle); - fragment.show(getActivity().getSupportFragmentManager(), - NetworkRequestDialogFragment.class.getSimpleName()); } @Override @@ -284,7 +307,7 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp @Override public void onAbort() { - stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE.ABORT); + stopScanningAndMaybePopErrorDialog(ERROR_DIALOG_TYPE.ABORT); } @Override @@ -295,10 +318,13 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp @Override public void onMatch(List scanResults) { - mHandler.removeMessages(MESSAGE_STOP_SCAN_WIFI_LIST); - renewAccessPointList(scanResults); + // Shouldn't need to renew cached list, since input result is empty. + if (scanResults != null && scanResults.size() > 0) { + mHandler.removeMessages(MESSAGE_STOP_SCAN_WIFI_LIST); + renewAccessPointList(scanResults); - notifyAdapterRefresh(); + notifyAdapterRefresh(); + } } // Updates internal AccessPoint list from WifiTracker. scanResults are used to update key list @@ -329,17 +355,24 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp @Override public void onUserSelectionConnectSuccess(WifiConfiguration wificonfiguration) { - // Dismisses current dialog and finishes Activity, since connection is success. - dismiss(); - final Activity activity = getActivity(); - if (activity != null) { - activity.finish(); + // Removes the progress icon. + final Dialog dialog = getDialog(); + if (dialog != null) { + final View view = dialog.findViewById(R.id.network_request_title_progress); + if (view != null) { + view.setVisibility(View.GONE); + } } + + // Posts delay to finish self since connection is success. + mHandler.removeMessages(MESSAGE_STOP_SCAN_WIFI_LIST); + mHandler.sendEmptyMessageDelayed(MESSAGE_FINISH_ACTIVITY, + DELAY_TIME_USER_AWARE_CONNECTED_MS); } @Override public void onUserSelectionConnectFailure(WifiConfiguration wificonfiguration) { - stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE.ABORT); + stopScanningAndMaybePopErrorDialog(ERROR_DIALOG_TYPE.ABORT); } private final class FilterWifiTracker { diff --git a/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java b/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java index e64fae714e6..17516e90284 100644 --- a/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java +++ b/tests/robotests/src/com/android/settings/wifi/NetworkRequestDialogFragmentTest.java @@ -111,14 +111,17 @@ public class NetworkRequestDialogFragmentTest { ShadowLooper.getShadowMainLooper().runToEndOfTasks(); assertThat(fakeFragment.bCalledStopAndPop).isTrue(); + assertThat(fakeFragment.errorType).isEqualTo(ERROR_DIALOG_TYPE.TIME_OUT); } class FakeNetworkRequestDialogFragment extends NetworkRequestDialogFragment { boolean bCalledStopAndPop = false; + ERROR_DIALOG_TYPE errorType = null; @Override - public void stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE type) { + public void stopScanningAndMaybePopErrorDialog(ERROR_DIALOG_TYPE type) { bCalledStopAndPop = true; + errorType = type; } } @@ -150,22 +153,28 @@ public class NetworkRequestDialogFragmentTest { @Test public void updateAccessPointList_onUserSelectionConnectSuccess_shouldCloseTheDialog() { - List accessPointList = createAccessPointList(); - when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList); - networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null); - AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog(); - assertThat(alertDialog.isShowing()).isTrue(); + // Assert + FakeNetworkRequestDialogFragment fakeFragment = new FakeNetworkRequestDialogFragment(); + FakeNetworkRequestDialogFragment spyFakeFragment = spy(fakeFragment); - // Test if config would update list. + List accessPointList = createAccessPointList(); + when(spyFakeFragment.getAccessPointList()).thenReturn(accessPointList); + + spyFakeFragment.show(mActivity.getSupportFragmentManager(), null); + + // Action WifiConfiguration config = new WifiConfiguration(); config.SSID = "Test AP 3"; - networkRequestDialogFragment.onUserSelectionConnectSuccess(config); + spyFakeFragment.onUserSelectionConnectSuccess(config); - assertThat(alertDialog.isShowing()).isFalse(); + // Check + ShadowLooper.getShadowMainLooper().runToEndOfTasks(); + assertThat(fakeFragment.bCalledStopAndPop).isTrue(); + assertThat(fakeFragment.errorType).isNull(); } @Test - public void updateAccessPointList_onUserSelectionConnectFailure_shouldCallTimeoutDialog() { + public void updateAccessPointList_onUserSelectionConnectFailure_shouldCallAbortDialog() { FakeNetworkRequestDialogFragment fakeFragment = new FakeNetworkRequestDialogFragment(); FakeNetworkRequestDialogFragment spyFakeFragment = spy(fakeFragment); List accessPointList = createAccessPointList(); @@ -181,6 +190,7 @@ public class NetworkRequestDialogFragmentTest { fakeFragment.onUserSelectionConnectFailure(config); assertThat(fakeFragment.bCalledStopAndPop).isTrue(); + assertThat(fakeFragment.errorType).isEqualTo(ERROR_DIALOG_TYPE.ABORT); } @Test From 7bdf8b3d378f0cfdec98c821ee2b0b210d7c554a Mon Sep 17 00:00:00 2001 From: Johnson Lu Date: Mon, 7 Jan 2019 11:44:21 +0800 Subject: [PATCH 2/8] Implement Wi-Fi DPP flow 1. As DPP configurator initiator. 2. As DPP enrollee initiator. 3. Pass whole DPP url to DPP API due to API cahnged. Bug: 122331217 Test: manual test Change-Id: I8005b78b82453badf253dbde8022ff20722b39fd --- .../wifi/dpp/WifiDppAddDeviceFragment.java | 41 +++++++++++++++++- .../wifi/dpp/WifiDppConfiguratorActivity.java | 23 ++++------ .../wifi/dpp/WifiDppEnrolleeActivity.java | 42 ++++++++++++++++++- .../dpp/WifiDppQrCodeScannerFragment.java | 19 ++++----- .../settings/wifi/dpp/WifiDppUtils.java | 8 ++++ .../settings/wifi/dpp/WifiNetworkConfig.java | 21 +++++++--- .../android/settings/wifi/dpp/WifiQrCode.java | 3 +- 7 files changed, 121 insertions(+), 36 deletions(-) diff --git a/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java b/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java index 12814f8ef01..8fa58f3ca47 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java +++ b/src/com/android/settings/wifi/dpp/WifiDppAddDeviceFragment.java @@ -18,7 +18,10 @@ package com.android.settings.wifi.dpp; import android.app.ActionBar; import android.app.Activity; +import android.content.Context; +import android.net.wifi.WifiManager; import android.os.Bundle; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -35,11 +38,42 @@ import com.android.settings.R; * to the Wi-Fi network. */ public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment { + private static final String TAG = "WifiDppAddDeviceFragment"; + private ImageView mWifiApPictureView; private TextView mChooseDifferentNetwork; private Button mButtonLeft; private Button mButtonRight; + private class DppStatusCallback extends android.net.wifi.DppStatusCallback { + @Override + public void onEnrolleeSuccess(int newNetworkId) { + // Do nothing + } + + @Override + public void onConfiguratorSuccess(int code) { + // Update success UI. + mTitle.setText(R.string.wifi_dpp_wifi_shared_with_device); + mSummary.setVisibility(View.INVISIBLE); + mButtonLeft.setText(R.string.wifi_dpp_add_another_device); + mButtonLeft.setOnClickListener(v -> getFragmentManager().popBackStack()); + mButtonRight.setText(R.string.done); + mButtonRight.setOnClickListener(v -> getActivity().finish()); + } + + @Override + public void onFailure(int code) { + //TODO(b/122429170): Show DPP configuration error state UI + Log.d(TAG, "DppStatusCallback.onFailure " + code); + } + + @Override + public void onProgress(int code) { + // Do nothing + } + } + @Override public int getMetricsCategory() { return MetricsProto.MetricsEvent.SETTINGS_WIFI_DPP_CONFIGURATOR; @@ -86,6 +120,11 @@ public class WifiDppAddDeviceFragment extends WifiDppQrCodeBaseFragment { } private void startWifiDppInitiator() { - //TODO(b/122331217): starts Wi-Fi DPP initiator handshake here + final String enrolleeUri = ((WifiDppConfiguratorActivity) getActivity()).getDppUri(); + final int networkId = + ((WifiDppConfiguratorActivity) getActivity()).getWifiNetworkConfig().getNetworkId(); + final WifiManager wifiManager = getContext().getSystemService(WifiManager.class); + wifiManager.startDppAsConfiguratorInitiator(enrolleeUri, networkId, + WifiManager.DPP_NETWORK_ROLE_STA, /* handler */ null, new DppStatusCallback()); } } diff --git a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java index 9c65d1019bf..b08546cc484 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java +++ b/src/com/android/settings/wifi/dpp/WifiDppConfiguratorActivity.java @@ -66,11 +66,8 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements /** The Wi-Fi network which will be configured */ private WifiNetworkConfig mWifiNetworkConfig; - /** The public key from Wi-Fi DPP QR code */ - private String mPublicKey; - - /** The information from Wi-Fi DPP QR code */ - private String mInformation; + /** The uri from Wi-Fi DPP QR code */ + private String mDppUri; /** The Wi-Fi DPP QR code from intent ACTION_PROCESS_WIFI_DPP_QR_CODE */ private WifiQrCode mWifiDppQrCode; @@ -228,12 +225,8 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements return mWifiNetworkConfig; } - public String getPublicKey() { - return mPublicKey; - } - - public String getInformation() { - return mInformation; + public String getDppUri() { + return mDppUri; } public WifiQrCode getWifiDppQrCode() { @@ -270,17 +263,15 @@ public class WifiDppConfiguratorActivity extends InstrumentedActivity implements } @Override - public void onScanWifiDppSuccess(String publicKey, String information) { - mPublicKey = publicKey; - mInformation = information; + public void onScanWifiDppSuccess(String uri) { + mDppUri = uri; showAddDeviceFragment(/* addToBackStack */ true); } @Override public void onScanZxingWifiFormatSuccess(WifiNetworkConfig wifiNetworkConfig) { - mPublicKey = null; - mInformation = null; + mDppUri = null; mWifiNetworkConfig = new WifiNetworkConfig(wifiNetworkConfig); showAddDeviceFragment(/* addToBackStack */ true); diff --git a/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java b/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java index 584a819c72d..8c0e1f050d0 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java +++ b/src/com/android/settings/wifi/dpp/WifiDppEnrolleeActivity.java @@ -16,6 +16,8 @@ package com.android.settings.wifi.dpp; +import android.content.Context; +import android.net.wifi.WifiConfiguration; import android.provider.Settings; import android.app.ActionBar; import android.app.Activity; @@ -32,6 +34,8 @@ import com.android.internal.logging.nano.MetricsProto; import com.android.settings.core.InstrumentedActivity; import com.android.settings.R; +import java.util.List; + /** * To provision "this" device with specified Wi-Fi network. * @@ -49,6 +53,39 @@ public class WifiDppEnrolleeActivity extends InstrumentedActivity implements private FragmentManager mFragmentManager; + private class DppStatusCallback extends android.net.wifi.DppStatusCallback { + @Override + public void onEnrolleeSuccess(int newNetworkId) { + // Connect to the new network. + final WifiManager wifiManager = getSystemService(WifiManager.class); + final List wifiConfigs = wifiManager.getPrivilegedConfiguredNetworks(); + for (WifiConfiguration wifiConfig : wifiConfigs) { + if (wifiConfig.networkId == newNetworkId) { + wifiManager.connect(wifiConfig, WifiDppEnrolleeActivity.this); + return; + } + } + Log.e(TAG, "Invalid networkId " + newNetworkId); + WifiDppEnrolleeActivity.this.onFailure(WifiManager.ERROR_AUTHENTICATING); + } + + @Override + public void onConfiguratorSuccess(int code) { + // Do nothing + } + + @Override + public void onFailure(int code) { + //TODO(b/122429170): Show DPP enrollee error state UI + Log.d(TAG, "DppStatusCallback.onFailure " + code); + } + + @Override + public void onProgress(int code) { + // Do nothing + } + } + @Override public int getMetricsCategory() { return MetricsProto.MetricsEvent.SETTINGS_WIFI_DPP_ENROLLEE; @@ -108,8 +145,9 @@ public class WifiDppEnrolleeActivity extends InstrumentedActivity implements } @Override - public void onScanWifiDppSuccess(String publicKey, String information) { - // TODO(b/1023597): starts DPP enrollee handshake here + public void onScanWifiDppSuccess(String uri) { + final WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE); + wifiManager.startDppAsEnrolleeInitiator(uri, /* handler */ null, new DppStatusCallback()); } @Override diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java index c7c1461a62c..2f59e188ade 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java +++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java @@ -62,9 +62,8 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl private static final long SHOW_ERROR_MESSAGE_INTERVAL = 2000; private static final long SHOW_SUCCESS_SQUARE_INTERVAL = 1000; - // Keys for Bundle usage - private static final String KEY_PUBLIC_KEY = "key_public_key"; - private static final String KEY_INFORMATION = "key_information"; + // Key for Bundle usage + private static final String KEY_PUBLIC_URI = "key_public_uri"; private QrCamera mCamera; private TextureView mTextureView; @@ -91,7 +90,7 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl // Container Activity must implement this interface public interface OnScanWifiDppSuccessListener { - public void onScanWifiDppSuccess(String publicKey, String information); + public void onScanWifiDppSuccess(String uri); } OnScanWifiDppSuccessListener mScanWifiDppSuccessListener; @@ -269,7 +268,7 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl public void handleSuccessfulResult(String qrCode) { switch (mWifiQrCode.getScheme()) { case WifiQrCode.SCHEME_DPP: - handleWifiDpp(mWifiQrCode.getPublicKey(), mWifiQrCode.getInformation()); + handleWifiDpp(qrCode); break; case WifiQrCode.SCHEME_ZXING_WIFI_NETWORK_CONFIG: @@ -281,13 +280,12 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl } } - private void handleWifiDpp(String publicKey, String information) { + private void handleWifiDpp(String uri) { destroyCamera(); mDecorateView.setFocused(true); final Bundle bundle = new Bundle(); - bundle.putString(KEY_PUBLIC_KEY, publicKey); - bundle.putString(KEY_INFORMATION, information); + bundle.putString(KEY_PUBLIC_URI, uri); Message message = mHandler.obtainMessage(MESSAGE_SCAN_WIFI_DPP_SUCCESS); message.setData(bundle); @@ -352,10 +350,9 @@ public class WifiDppQrCodeScannerFragment extends WifiDppQrCodeBaseFragment impl return; } final Bundle bundle = msg.getData(); - final String publicKey = bundle.getString(KEY_PUBLIC_KEY); - final String information = bundle.getString(KEY_INFORMATION); + final String uri = bundle.getString(KEY_PUBLIC_URI); - mScanWifiDppSuccessListener.onScanWifiDppSuccess(publicKey, information); + mScanWifiDppSuccessListener.onScanWifiDppSuccess(uri); break; case MESSAGE_SCAN_ZXING_WIFI_FORMAT_SUCCESS: diff --git a/src/com/android/settings/wifi/dpp/WifiDppUtils.java b/src/com/android/settings/wifi/dpp/WifiDppUtils.java index 3a40e252e76..0205ec1dc13 100644 --- a/src/com/android/settings/wifi/dpp/WifiDppUtils.java +++ b/src/com/android/settings/wifi/dpp/WifiDppUtils.java @@ -64,6 +64,9 @@ public class WifiDppUtils { /** The data corresponding to {@code WifiConfiguration} hiddenSSID */ public static final String EXTRA_WIFI_HIDDEN_SSID = "hiddenSsid"; + /** The data corresponding to {@code WifiConfiguration} networkId */ + public static final String EXTRA_WIFI_NETWORK_ID = "networkId"; + /** @see WifiQrCode */ public static final String EXTRA_QR_CODE = "qrCode"; @@ -164,6 +167,11 @@ public class WifiDppUtils { if (!TextUtils.isEmpty(preSharedKey)) { intent.putExtra(EXTRA_WIFI_PRE_SHARED_KEY, preSharedKey); } + if (wifiConfig.networkId == WifiConfiguration.INVALID_NETWORK_ID) { + throw new IllegalArgumentException("Invalid network ID"); + } else { + intent.putExtra(EXTRA_WIFI_NETWORK_ID, wifiConfig.networkId); + } return intent; } diff --git a/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java b/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java index c9bfbd6487b..a9e88a9f0a8 100644 --- a/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java +++ b/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java @@ -46,13 +46,15 @@ public class WifiNetworkConfig { private String mSsid; private String mPreSharedKey; private boolean mHiddenSsid; + private int mNetworkId; - private WifiNetworkConfig(String security, String ssid, String preSharedKey, - boolean hiddenSsid) { + private WifiNetworkConfig(String security, String ssid, String preSharedKey, boolean hiddenSsid, + int networkId) { mSecurity = security; mSsid = ssid; mPreSharedKey = preSharedKey; mHiddenSsid = hiddenSsid; + mNetworkId = networkId; } public WifiNetworkConfig(WifiNetworkConfig config) { @@ -60,6 +62,7 @@ public class WifiNetworkConfig { mSsid = config.mSsid; mPreSharedKey = config.mPreSharedKey; mHiddenSsid = config.mHiddenSsid; + mNetworkId = config.mNetworkId; } /** @@ -82,17 +85,19 @@ public class WifiNetworkConfig { String ssid = intent.getStringExtra(WifiDppUtils.EXTRA_WIFI_SSID); String preSharedKey = intent.getStringExtra(WifiDppUtils.EXTRA_WIFI_PRE_SHARED_KEY); boolean hiddenSsid = intent.getBooleanExtra(WifiDppUtils.EXTRA_WIFI_HIDDEN_SSID, false); + int networkId = intent.getIntExtra(WifiDppUtils.EXTRA_WIFI_NETWORK_ID, + WifiConfiguration.INVALID_NETWORK_ID); - return getValidConfigOrNull(security, ssid, preSharedKey, hiddenSsid); + return getValidConfigOrNull(security, ssid, preSharedKey, hiddenSsid, networkId); } public static WifiNetworkConfig getValidConfigOrNull(String security, String ssid, - String preSharedKey, boolean hiddenSsid) { + String preSharedKey, boolean hiddenSsid, int networkId) { if (!isValidConfig(security, ssid, preSharedKey, hiddenSsid)) { return null; } - return new WifiNetworkConfig(security, ssid, preSharedKey, hiddenSsid); + return new WifiNetworkConfig(security, ssid, preSharedKey, hiddenSsid, networkId); } public static boolean isValidConfig(WifiNetworkConfig config) { @@ -184,6 +189,11 @@ public class WifiNetworkConfig { return mHiddenSsid; } + @Keep + public int getNetworkId() { + return mNetworkId; + } + public void connect(Context context, WifiManager.ActionListener listener) { WifiConfiguration wifiConfiguration = getWifiConfigurationOrNull(); if (wifiConfiguration == null) { @@ -208,6 +218,7 @@ public class WifiNetworkConfig { final WifiConfiguration wifiConfiguration = new WifiConfiguration(); wifiConfiguration.SSID = addQuotationIfNeeded(mSsid); wifiConfiguration.hiddenSSID = mHiddenSsid; + wifiConfiguration.networkId = mNetworkId; if (TextUtils.isEmpty(mSecurity) || SECURITY_NO_PASSWORD.equals(mSecurity)) { wifiConfiguration.allowedKeyManagement.set(KeyMgmt.NONE); diff --git a/src/com/android/settings/wifi/dpp/WifiQrCode.java b/src/com/android/settings/wifi/dpp/WifiQrCode.java index a8562bb21c5..8eae3a455a2 100644 --- a/src/com/android/settings/wifi/dpp/WifiQrCode.java +++ b/src/com/android/settings/wifi/dpp/WifiQrCode.java @@ -17,6 +17,7 @@ package com.android.settings.wifi.dpp; import android.content.Intent; +import android.net.wifi.WifiConfiguration; import android.text.TextUtils; import androidx.annotation.Keep; @@ -135,7 +136,7 @@ public class WifiQrCode { password = removeBackSlash(password); mWifiNetworkConfig = WifiNetworkConfig.getValidConfigOrNull(security, ssid, password, - hiddenSsid); + hiddenSsid, WifiConfiguration.INVALID_NETWORK_ID); if (mWifiNetworkConfig == null) { throw new IllegalArgumentException("Invalid format"); From 7c91342ffa1ef1a171802170389fcb72690ca3e0 Mon Sep 17 00:00:00 2001 From: Yi-Ling Chuang Date: Tue, 8 Jan 2019 15:47:40 +0800 Subject: [PATCH 3/8] Update the background colour for dismissal view. Change-Id: I14cfa176c80581ea8f4de099015e4ff148acf59a Fixes: 119170360 Test: visual --- res/layout/homepage_dismissal_view.xml | 1 + res/values-night/colors.xml | 1 + res/values/colors.xml | 1 + 3 files changed, 3 insertions(+) diff --git a/res/layout/homepage_dismissal_view.xml b/res/layout/homepage_dismissal_view.xml index e31d436715f..7d1abf348a0 100644 --- a/res/layout/homepage_dismissal_view.xml +++ b/res/layout/homepage_dismissal_view.xml @@ -20,6 +20,7 @@ android:id="@+id/dismissal_view" android:layout_width="match_parent" android:layout_height="match_parent" + android:background="@color/homepage_card_dismissal_background" android:orientation="vertical"> #3F5FBD #cc000000 + @*android:color/material_grey_800 diff --git a/res/values/colors.xml b/res/values/colors.xml index 5539d685304..a1381c3986e 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -104,6 +104,7 @@ #9FA8DA #5E97F6 #1f000000 + @*android:color/material_grey_50 @android:color/white From 0a830d4f483f3600021ec1a6ba7867e5ac8f6000 Mon Sep 17 00:00:00 2001 From: Antony Sargent Date: Tue, 8 Jan 2019 14:17:39 -0800 Subject: [PATCH 4/8] Make Network & internet v2 feature flag be persistent In ag/5386198 we added a flag to turn on the new features of the network and internet settings page, but that flag resets to the default value (currently false) every time you reboot, which is annoying and hostile for dogfooders. This CL makes the flag persistent. Bug: 116349402 Test: manual / should be covered by existing tests Change-Id: I098073e81feb199751e967a9652bec6a6445b95e --- .../development/featureflags/FeatureFlagPersistent.java | 1 + .../android/settings/network/NetworkDashboardFragment.java | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/com/android/settings/development/featureflags/FeatureFlagPersistent.java b/src/com/android/settings/development/featureflags/FeatureFlagPersistent.java index d27af64d593..33de9c3dbee 100644 --- a/src/com/android/settings/development/featureflags/FeatureFlagPersistent.java +++ b/src/com/android/settings/development/featureflags/FeatureFlagPersistent.java @@ -37,6 +37,7 @@ public class FeatureFlagPersistent { static { PERSISTENT_FLAGS = new HashSet<>(); PERSISTENT_FLAGS.add(FeatureFlags.HEARING_AID_SETTINGS); + PERSISTENT_FLAGS.add(FeatureFlags.NETWORK_INTERNET_V2); } public static boolean isEnabled(Context context, String feature) { diff --git a/src/com/android/settings/network/NetworkDashboardFragment.java b/src/com/android/settings/network/NetworkDashboardFragment.java index 7d94bbaece3..c2b4a2b1c0a 100644 --- a/src/com/android/settings/network/NetworkDashboardFragment.java +++ b/src/com/android/settings/network/NetworkDashboardFragment.java @@ -21,7 +21,6 @@ import static com.android.settings.network.MobilePlanPreferenceController import android.app.Dialog; import android.content.Context; import android.provider.SearchIndexableResource; -import android.util.FeatureFlagUtils; import android.util.Log; import androidx.appcompat.app.AlertDialog; @@ -31,6 +30,7 @@ import com.android.internal.logging.nano.MetricsProto; import com.android.settings.R; import com.android.settings.core.FeatureFlags; import com.android.settings.dashboard.DashboardFragment; +import com.android.settings.development.featureflags.FeatureFlagPersistent; import com.android.settings.network.MobilePlanPreferenceController.MobilePlanPreferenceHost; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.wifi.WifiMasterSwitchPreferenceController; @@ -61,7 +61,7 @@ public class NetworkDashboardFragment extends DashboardFragment implements @Override protected int getPreferenceScreenResId() { - if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.NETWORK_INTERNET_V2)) { + if (FeatureFlagPersistent.isEnabled(getContext(), FeatureFlags.NETWORK_INTERNET_V2)) { return R.xml.network_and_internet_v2; } else { return R.xml.network_and_internet; @@ -72,7 +72,7 @@ public class NetworkDashboardFragment extends DashboardFragment implements public void onAttach(Context context) { super.onAttach(context); - if (FeatureFlagUtils.isEnabled(context, FeatureFlags.NETWORK_INTERNET_V2)) { + if (FeatureFlagPersistent.isEnabled(context, FeatureFlags.NETWORK_INTERNET_V2)) { use(MultiNetworkHeaderController.class).init(getSettingsLifecycle()); } use(AirplaneModePreferenceController.class).setFragment(this); From bb42ce2608bb501c2948241b643a18d634b7615b Mon Sep 17 00:00:00 2001 From: tmfang Date: Wed, 9 Jan 2019 14:50:43 +0800 Subject: [PATCH 5/8] Implement an "Advance" button on Privacy page. - Also rearrange the order for "show password". Test: visual Fixes: 122556325 Change-Id: Iac15baa83a2ba863ad75c0a309a0e4c6deaa522e --- res/xml/privacy_dashboard_settings.xml | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/res/xml/privacy_dashboard_settings.xml b/res/xml/privacy_dashboard_settings.xml index 79e2e714dc7..a580f5ff91e 100644 --- a/res/xml/privacy_dashboard_settings.xml +++ b/res/xml/privacy_dashboard_settings.xml @@ -19,7 +19,8 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:settings="http://schemas.android.com/apk/res-auto" android:key="privacy_dashboard_page" - android:title="@string/privacy_dashboard_title"> + android:title="@string/privacy_dashboard_title" + settings:initialExpandedChildrenCount="3"> - - - + + + From 26127c627148d4be88155739a5b7e76a2a2c0d34 Mon Sep 17 00:00:00 2001 From: Yi-Ling Chuang Date: Wed, 9 Jan 2019 11:54:16 +0800 Subject: [PATCH 6/8] Update the layout of half width suggestion cards. When switching to the dismissal view, the background color of suggestion cards that were built as half cards with only 1 line text in it won't fully cover the whole card. The alignments are not consistent as well. Make layout_height of ViewFlipper and the main content to be match_parent. Change-Id: If345d00d21150e184614029a34e79b3210ec52ff Fixes: 122559038 Test: visual --- res/layout/homepage_slice_half_tile.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/res/layout/homepage_slice_half_tile.xml b/res/layout/homepage_slice_half_tile.xml index 7de9eb6e006..46f3cdaf8e0 100644 --- a/res/layout/homepage_slice_half_tile.xml +++ b/res/layout/homepage_slice_half_tile.xml @@ -24,12 +24,12 @@ + android:layout_height="match_parent"> Date: Wed, 9 Jan 2019 17:59:07 +0800 Subject: [PATCH 7/8] use android:textAppearanceListItem to replace Preference subhead Use android:attr/textAppearanceListItem to replace style/Preference_TextAppearanceMaterialSubhead in the time_zone_search_item.xml Bug: 122043378 Test: compilation Change-Id: I8a19e6aa662b01fd4d8c2a0a139c787438d6d11c --- res/layout/time_zone_search_item.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/layout/time_zone_search_item.xml b/res/layout/time_zone_search_item.xml index bb75226714d..8d059a8a205 100644 --- a/res/layout/time_zone_search_item.xml +++ b/res/layout/time_zone_search_item.xml @@ -63,7 +63,7 @@ instead of an ImageView --> android:layout_width="match_parent" android:layout_height="wrap_content" android:singleLine="true" - android:textAppearance="@style/Preference_TextAppearanceMaterialSubhead" + android:textAppearance="?android:attr/textAppearanceListItem" android:ellipsize="marquee" /> Date: Mon, 7 Jan 2019 16:41:10 -0800 Subject: [PATCH 8/8] Allow OEM customizing max screen timeout value. Side fix - update string for select timezone. Change-Id: Id61128b7dfcc27da8ed07225af3b6bec4e93b512 Fixes: 113346164 Fixes: 121986474 Test: robotest --- res/values/config.xml | 3 + res/values/strings.xml | 3 - res/xml/date_time_prefs.xml | 2 +- .../display/TimeoutListPreference.java | 58 ++++++++++++++----- .../display/TimeoutPreferenceController.java | 9 ++- tests/robotests/res/values-mcc999/config.xml | 3 + .../display/TimeoutListPreferenceTest.java | 21 ++++++- 7 files changed, 74 insertions(+), 25 deletions(-) diff --git a/res/values/config.xml b/res/values/config.xml index 82e185c8371..8efa6b2ab49 100755 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -171,4 +171,7 @@ + + + 1800000 diff --git a/res/values/strings.xml b/res/values/strings.xml index c80ba95735f..ad946148af8 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -5828,9 +5828,6 @@ Used in SetupWizard for XLarge screen [CHAR LIMIT=20] --> Network details - - Select Time Zone - Sync enabled diff --git a/res/xml/date_time_prefs.xml b/res/xml/date_time_prefs.xml index edda1ba66d9..e8af64c374c 100644 --- a/res/xml/date_time_prefs.xml +++ b/res/xml/date_time_prefs.xml @@ -58,7 +58,7 @@ diff --git a/src/com/android/settings/display/TimeoutListPreference.java b/src/com/android/settings/display/TimeoutListPreference.java index f9a731d32eb..5ed427fb252 100644 --- a/src/com/android/settings/display/TimeoutListPreference.java +++ b/src/com/android/settings/display/TimeoutListPreference.java @@ -26,6 +26,7 @@ import android.util.AttributeSet; import android.util.Log; import android.view.View; +import androidx.annotation.VisibleForTesting; import androidx.appcompat.app.AlertDialog.Builder; import com.android.settings.R; @@ -33,18 +34,18 @@ import com.android.settings.RestrictedListPreference; import com.android.settingslib.RestrictedLockUtils; import java.util.ArrayList; +import java.util.List; public class TimeoutListPreference extends RestrictedListPreference { private static final String TAG = "TimeoutListPreference"; private EnforcedAdmin mAdmin; - private final CharSequence[] mInitialEntries; - private final CharSequence[] mInitialValues; + private CharSequence[] mInitialEntries; + private CharSequence[] mInitialValues; public TimeoutListPreference(Context context, AttributeSet attrs) { super(context, attrs); - mInitialEntries = getEntries(); - mInitialValues = getEntryValues(); + updateInitialValues(); } @Override @@ -65,13 +66,8 @@ public class TimeoutListPreference extends RestrictedListPreference { if (mAdmin != null) { View footerView = dialog.findViewById(R.id.admin_disabled_other_options); footerView.findViewById(R.id.admin_more_details_link).setOnClickListener( - new View.OnClickListener() { - @Override - public void onClick(View view) { - RestrictedLockUtils.sendShowAdminSupportDetailsIntent( - getContext(), mAdmin); - } - }); + view -> RestrictedLockUtils.sendShowAdminSupportDetailsIntent( + getContext(), mAdmin)); } } @@ -89,8 +85,8 @@ public class TimeoutListPreference extends RestrictedListPreference { maxTimeout = Long.MAX_VALUE; } - ArrayList revisedEntries = new ArrayList(); - ArrayList revisedValues = new ArrayList(); + final ArrayList revisedEntries = new ArrayList<>(); + final ArrayList revisedValues = new ArrayList<>(); for (int i = 0; i < mInitialValues.length; ++i) { long timeout = Long.parseLong(mInitialValues[i].toString()); if (timeout <= maxTimeout) { @@ -101,7 +97,7 @@ public class TimeoutListPreference extends RestrictedListPreference { // If there are no possible options for the user, then set this preference as disabled // by admin, otherwise remove the padlock in case it was set earlier. - if (revisedValues.size() == 0) { + if (revisedValues.isEmpty()) { setDisabledByAdmin(admin); return; } else { @@ -117,7 +113,7 @@ public class TimeoutListPreference extends RestrictedListPreference { setValue(String.valueOf(userPreference)); } else if (revisedValues.size() > 0 && Long.parseLong(revisedValues.get(revisedValues.size() - 1).toString()) - == maxTimeout) { + == maxTimeout) { // If the last one happens to be the same as the max timeout, select that setValue(String.valueOf(maxTimeout)); } else { @@ -128,4 +124,36 @@ public class TimeoutListPreference extends RestrictedListPreference { } } } + + @VisibleForTesting + void updateInitialValues() { + // Read default list of candidate values. + final CharSequence[] entries = getEntries(); + final CharSequence[] values = getEntryValues(); + // Filter out values based on config + final List revisedEntries = new ArrayList<>(); + final List revisedValues = new ArrayList<>(); + final long maxTimeout = getContext().getResources().getInteger( + R.integer.max_lock_after_timeout_ms); + if (entries == null || values == null) { + return; + } + Log.d(TAG, "max timeout: " + maxTimeout); + for (int i = 0; i < values.length; ++i) { + long timeout = Long.parseLong(values[i].toString()); + if (timeout <= maxTimeout) { + Log.d(TAG, "keeping timeout: " + values[i]); + revisedEntries.add(entries[i]); + revisedValues.add(values[i]); + } else { + Log.d(TAG, "Dropping timeout: " + values[i]); + } + } + + // Store final candidates in initial value lists. + mInitialEntries = revisedEntries.toArray(new CharSequence[0]); + setEntries(mInitialEntries); + mInitialValues = revisedValues.toArray(new CharSequence[0]); + setEntryValues(mInitialValues); + } } diff --git a/src/com/android/settings/display/TimeoutPreferenceController.java b/src/com/android/settings/display/TimeoutPreferenceController.java index 60b7e24b85b..c1c50690a0c 100644 --- a/src/com/android/settings/display/TimeoutPreferenceController.java +++ b/src/com/android/settings/display/TimeoutPreferenceController.java @@ -13,8 +13,6 @@ */ package com.android.settings.display; -import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT; - import android.app.admin.DevicePolicyManager; import android.content.Context; import android.os.UserHandle; @@ -60,7 +58,7 @@ public class TimeoutPreferenceController extends AbstractPreferenceController im public void updateState(Preference preference) { final TimeoutListPreference timeoutListPreference = (TimeoutListPreference) preference; final long currentTimeout = Settings.System.getLong(mContext.getContentResolver(), - SCREEN_OFF_TIMEOUT, FALLBACK_SCREEN_TIMEOUT_VALUE); + Settings.System.SCREEN_OFF_TIMEOUT, FALLBACK_SCREEN_TIMEOUT_VALUE); timeoutListPreference.setValue(String.valueOf(currentTimeout)); final DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE); @@ -86,7 +84,8 @@ public class TimeoutPreferenceController extends AbstractPreferenceController im public boolean onPreferenceChange(Preference preference, Object newValue) { try { int value = Integer.parseInt((String) newValue); - Settings.System.putInt(mContext.getContentResolver(), SCREEN_OFF_TIMEOUT, value); + Settings.System.putInt(mContext.getContentResolver(), + Settings.System.SCREEN_OFF_TIMEOUT, value); updateTimeoutPreferenceDescription((TimeoutListPreference) preference, value); } catch (NumberFormatException e) { Log.e(TAG, "could not persist screen timeout setting", e); @@ -94,7 +93,7 @@ public class TimeoutPreferenceController extends AbstractPreferenceController im return true; } - public static CharSequence getTimeoutDescription( + private static CharSequence getTimeoutDescription( long currentTimeout, CharSequence[] entries, CharSequence[] values) { if (currentTimeout < 0 || entries == null || values == null || values.length != entries.length) { diff --git a/tests/robotests/res/values-mcc999/config.xml b/tests/robotests/res/values-mcc999/config.xml index 101a6b813f4..59028d3daf8 100644 --- a/tests/robotests/res/values-mcc999/config.xml +++ b/tests/robotests/res/values-mcc999/config.xml @@ -88,4 +88,7 @@ test@test.test + + + 1700000 diff --git a/tests/robotests/src/com/android/settings/display/TimeoutListPreferenceTest.java b/tests/robotests/src/com/android/settings/display/TimeoutListPreferenceTest.java index 55fcdacea51..7b67f0f54b1 100644 --- a/tests/robotests/src/com/android/settings/display/TimeoutListPreferenceTest.java +++ b/tests/robotests/src/com/android/settings/display/TimeoutListPreferenceTest.java @@ -17,11 +17,11 @@ package com.android.settings.display; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.mock; import static org.robolectric.RuntimeEnvironment.application; import android.util.AttributeSet; +import com.android.settings.R; import com.android.settings.testutils.shadow.ShadowUserManager; import com.android.settingslib.RestrictedLockUtils; @@ -69,4 +69,23 @@ public class TimeoutListPreferenceTest { // should set to largest allowed value, which is 5 minute assertThat(mPreference.getValue()).isEqualTo("300000"); } + + @Test + @Config(qualifiers = "mcc999") + public void newInstance_hasLowTimeoutConfig_shouldRemoveLongTimeouts() { + final AttributeSet attributeSet = Robolectric.buildAttributeSet().build(); + final TimeoutListPreference pref = new TimeoutListPreference(application, attributeSet); + final long maxTimeout = application.getResources().getInteger( + R.integer.max_lock_after_timeout_ms); + pref.setEntries(R.array.screen_timeout_entries); + pref.setEntryValues(R.array.screen_timeout_values); + + pref.updateInitialValues(); + + final CharSequence[] values = pref.getEntryValues(); + for (CharSequence value : values) { + long timeout = Long.parseLong(value.toString()); + assertThat(timeout).isAtMost(maxTimeout); + } + } }