diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 7daf136a40b..69d000a9e89 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -140,7 +140,7 @@ - + diff --git a/src/com/android/settings/ResetNetworkRequest.java b/src/com/android/settings/ResetNetworkRequest.java index 7632ea01d71..8df67e771b2 100644 --- a/src/com/android/settings/ResetNetworkRequest.java +++ b/src/com/android/settings/ResetNetworkRequest.java @@ -271,12 +271,12 @@ public class ResetNetworkRequest { builder.resetIms(mSubscriptionIdToResetIms); } // Reset phone process and RILD may impact above components, keep them at the end - if ((mResetOptions & RESET_PHONE_PROCESS) != 0) { - builder.restartPhoneProcess(); - } if ((mResetOptions & RESET_RILD) != 0) { builder.restartRild(); } + if ((mResetOptions & RESET_PHONE_PROCESS) != 0) { + builder.restartPhoneProcess(); + } return builder; } } diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java index 44915fe2829..5f9957b9121 100644 --- a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java +++ b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java @@ -142,13 +142,23 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment } @VisibleForTesting + @Nullable CachedBluetoothDevice getCachedDevice(String deviceAddress) { if (sTestDataFactory != null) { return sTestDataFactory.getDevice(deviceAddress); } BluetoothDevice remoteDevice = mManager.getBluetoothAdapter().getRemoteDevice(deviceAddress); - return mManager.getCachedDeviceManager().findDevice(remoteDevice); + if (remoteDevice == null) { + return null; + } + CachedBluetoothDevice cachedDevice = + mManager.getCachedDeviceManager().findDevice(remoteDevice); + if (cachedDevice != null) { + return cachedDevice; + } + Log.i(TAG, "Add device to cached device manager: " + remoteDevice.getAnonymizedAddress()); + return mManager.getCachedDeviceManager().addDevice(remoteDevice); } @VisibleForTesting diff --git a/src/com/android/settings/development/AdbQrcodeScannerFragment.java b/src/com/android/settings/development/AdbQrcodeScannerFragment.java index 1d384544447..ca44747f163 100644 --- a/src/com/android/settings/development/AdbQrcodeScannerFragment.java +++ b/src/com/android/settings/development/AdbQrcodeScannerFragment.java @@ -16,7 +16,6 @@ package com.android.settings.development; -import android.annotation.Nullable; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; @@ -27,7 +26,6 @@ import android.debug.IAdbManager; import android.graphics.Matrix; import android.graphics.Rect; import android.graphics.SurfaceTexture; -import android.net.wifi.WifiConfiguration; import android.os.Bundle; import android.os.Handler; import android.os.Message; @@ -49,6 +47,7 @@ import com.android.settings.R; import com.android.settings.SetupWizardUtils; import com.android.settings.wifi.dpp.AdbQrCode; import com.android.settings.wifi.dpp.WifiDppQrCodeBaseFragment; +import com.android.settings.wifi.dpp.WifiNetworkConfig; import com.android.settingslib.qrcode.QrCamera; import com.android.settingslib.qrcode.QrDecorateView; @@ -82,8 +81,7 @@ public class AdbQrcodeScannerFragment extends WifiDppQrCodeBaseFragment implemen /** QR code data scanned by camera */ private AdbQrCode mAdbQrCode; - @Nullable - private WifiConfiguration mAdbConfig; + private WifiNetworkConfig mAdbConfig; private IAdbManager mAdbManager; @@ -289,16 +287,13 @@ public class AdbQrcodeScannerFragment extends WifiDppQrCodeBaseFragment implemen AdbQrCode.triggerVibrationForQrCodeRecognition(getContext()); mVerifyingTextView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED); try { - if (mAdbConfig != null) { - mAdbManager.enablePairingByQrCode(mAdbConfig.SSID, - mAdbConfig.preSharedKey); - return; - } + mAdbManager.enablePairingByQrCode(mAdbConfig.getSsid(), + mAdbConfig.getPreSharedKey()); } catch (RemoteException e) { - Log.e(TAG, "Unable to enable QR code pairing" + e); + Log.e(TAG, "Unable to enable QR code pairing"); + getActivity().setResult(Activity.RESULT_CANCELED); + getActivity().finish(); } - getActivity().setResult(Activity.RESULT_CANCELED); - getActivity().finish(); } @Override diff --git a/src/com/android/settings/network/ResetNetworkOperationBuilder.java b/src/com/android/settings/network/ResetNetworkOperationBuilder.java index 6f36074d145..47c06d4480d 100644 --- a/src/com/android/settings/network/ResetNetworkOperationBuilder.java +++ b/src/com/android/settings/network/ResetNetworkOperationBuilder.java @@ -18,6 +18,7 @@ package com.android.settings.network; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothManager; +import android.content.ContentProviderClient; import android.content.ContentResolver; import android.content.Context; import android.net.ConnectivityManager; @@ -28,11 +29,14 @@ import android.net.wifi.WifiManager; import android.net.wifi.p2p.WifiP2pManager; import android.os.Looper; import android.os.RecoverySystem; +import android.os.RemoteException; import android.os.SystemClock; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.util.Log; +import androidx.annotation.Nullable; + import com.android.internal.annotations.VisibleForTesting; import com.android.settings.R; import com.android.settings.ResetNetworkRequest; @@ -257,15 +261,15 @@ public class ResetNetworkOperationBuilder { */ public ResetNetworkOperationBuilder restartPhoneProcess() { Runnable runnable = () -> { - try { - mContext.getContentResolver().call( - getResetTelephonyContentProviderAuthority(), - METHOD_RESTART_PHONE_PROCESS, - /* arg= */ null, - /* extras= */ null); - Log.i(TAG, "Phone process was restarted."); - } catch (IllegalArgumentException iae) { - Log.w(TAG, "Fail to restart phone process: " + iae); + // Unstable content provider can avoid us getting killed together with phone process + try (ContentProviderClient client = getUnstableTelephonyContentProviderClient()) { + if (client != null) { + client.call(METHOD_RESTART_PHONE_PROCESS, /* arg= */ null, /* extra= */ null); + Log.i(TAG, "Phone process was restarted."); + } + } catch (RemoteException re) { + // It's normal to throw RE since phone process immediately dies + Log.i(TAG, "Phone process has been restarted: " + re); } }; mResetSequence.add(runnable); @@ -279,15 +283,13 @@ public class ResetNetworkOperationBuilder { */ public ResetNetworkOperationBuilder restartRild() { Runnable runnable = () -> { - try { - mContext.getContentResolver().call( - getResetTelephonyContentProviderAuthority(), - METHOD_RESTART_RILD, - /* arg= */ null, - /* extras= */ null); - Log.i(TAG, "RILD was restarted."); - } catch (IllegalArgumentException iae) { - Log.w(TAG, "Fail to restart RILD: " + iae); + try (ContentProviderClient client = getUnstableTelephonyContentProviderClient()) { + if (client != null) { + client.call(METHOD_RESTART_RILD, /* arg= */ null, /* extra= */ null); + Log.i(TAG, "RILD was restarted."); + } + } catch (RemoteException re) { + Log.w(TAG, "Fail to restart RILD: " + re); } }; mResetSequence.add(runnable); @@ -322,9 +324,18 @@ public class ResetNetworkOperationBuilder { * @return the authority of the telephony content provider that support methods * resetPhoneProcess and resetRild. */ - @VisibleForTesting - String getResetTelephonyContentProviderAuthority() { + private String getResetTelephonyContentProviderAuthority() { return mContext.getResources().getString( R.string.reset_telephony_stack_content_provider_authority); } + + /** + * @return the unstable content provider to avoid us getting killed with phone process + */ + @Nullable + @VisibleForTesting + public ContentProviderClient getUnstableTelephonyContentProviderClient() { + return mContext.getContentResolver().acquireUnstableContentProviderClient( + getResetTelephonyContentProviderAuthority()); + } } diff --git a/src/com/android/settings/network/telephony/CellularSecuritySettingsFragment.java b/src/com/android/settings/network/telephony/CellularSecuritySettingsFragment.java index 3e37352867d..20385b93fc0 100644 --- a/src/com/android/settings/network/telephony/CellularSecuritySettingsFragment.java +++ b/src/com/android/settings/network/telephony/CellularSecuritySettingsFragment.java @@ -20,13 +20,10 @@ import android.os.Bundle; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; -import com.android.settings.search.BaseSearchIndexProvider; -import com.android.settingslib.search.SearchIndexable; /** * Cellular Security features (insecure network notifications, network security controls, etc) */ -@SearchIndexable public class CellularSecuritySettingsFragment extends DashboardFragment { private static final String TAG = "CellularSecuritySettingsFragment"; @@ -53,7 +50,4 @@ public class CellularSecuritySettingsFragment extends DashboardFragment { super.onCreatePreferences(bundle, rootKey); setPreferencesFromResource(R.xml.cellular_security, rootKey); } - - public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider(R.xml.cellular_security); } diff --git a/src/com/android/settings/wifi/dpp/AdbQrCode.java b/src/com/android/settings/wifi/dpp/AdbQrCode.java index 2d830b2820a..8a578ea4d3d 100644 --- a/src/com/android/settings/wifi/dpp/AdbQrCode.java +++ b/src/com/android/settings/wifi/dpp/AdbQrCode.java @@ -16,11 +16,14 @@ package com.android.settings.wifi.dpp; import android.content.Context; -import android.net.wifi.UriParserResults; import android.net.wifi.WifiConfiguration; import android.text.TextUtils; -import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; + +import java.util.Arrays; +import java.util.List; +import java.util.regex.Pattern; /** * Extension of WifiQrCode to support ADB QR code format. @@ -28,34 +31,74 @@ import androidx.annotation.NonNull; * * WIFI:T:ADB;S:myname;P:mypassword;; */ -public class AdbQrCode extends WifiQrCode { +public class AdbQrCode { static final String SECURITY_ADB = "ADB"; + static final String SCHEME_DPP = "DPP"; + static final String SCHEME_ZXING_WIFI_NETWORK_CONFIG = "WIFI"; + static final String PREFIX_DPP = "DPP:"; + static final String PREFIX_ZXING_WIFI_NETWORK_CONFIG = "WIFI:"; - private WifiConfiguration mAdbConfig; + static final String PREFIX_DPP_PUBLIC_KEY = "K:"; + static final String PREFIX_DPP_INFORMATION = "I:"; + + static final String PREFIX_ZXING_SECURITY = "T:"; + static final String PREFIX_ZXING_SSID = "S:"; + static final String PREFIX_ZXING_PASSWORD = "P:"; + static final String PREFIX_ZXING_HIDDEN_SSID = "H:"; + static final String DELIMITER_QR_CODE = ";"; + // Ignores password if security is SECURITY_NO_PASSWORD or absent + static final String SECURITY_NO_PASSWORD = "nopass"; //open network or OWE + static final String SECURITY_WEP = "WEP"; + static final String SECURITY_WPA_PSK = "WPA"; + static final String SECURITY_SAE = "SAE"; + private String mQrCode; + /** + * SCHEME_DPP for standard Wi-Fi device provision protocol; SCHEME_ZXING_WIFI_NETWORK_CONFIG + * for ZXing reader library' Wi-Fi Network config format + */ + private String mScheme; + // Data from parsed Wi-Fi DPP QR code + private String mPublicKey; + private String mInformation; + // Data from parsed ZXing reader library's Wi-Fi Network config format + private WifiNetworkConfig mAdbConfig; public AdbQrCode(String qrCode) throws IllegalArgumentException { - super(qrCode); + if (TextUtils.isEmpty(qrCode)) { + throw new IllegalArgumentException("Empty QR code"); + } + + mQrCode = qrCode; + if (qrCode.startsWith(PREFIX_DPP)) { + mScheme = SCHEME_DPP; + parseWifiDppQrCode(qrCode); + } else if (qrCode.startsWith(PREFIX_ZXING_WIFI_NETWORK_CONFIG)) { + mScheme = SCHEME_ZXING_WIFI_NETWORK_CONFIG; + parseZxingWifiQrCode(qrCode); + } else { + throw new IllegalArgumentException("Invalid scheme"); + } // Only accept the zxing format. - if (getScheme() != UriParserResults.URI_SCHEME_ZXING_WIFI_NETWORK_CONFIG) { + if (!SCHEME_ZXING_WIFI_NETWORK_CONFIG.equals(getScheme())) { throw new IllegalArgumentException("DPP format not supported for ADB QR code"); } - mAdbConfig = getWifiConfiguration(); + mAdbConfig = getWifiNetworkConfig(); - if (mAdbConfig == null) { - throw new IllegalArgumentException("Null config when parsing ADB QR code"); + if (!SECURITY_ADB.equals(mAdbConfig.getSecurity())) { + throw new IllegalArgumentException("Invalid security type"); } - if (TextUtils.isEmpty(mAdbConfig.SSID)) { + + if (TextUtils.isEmpty(mAdbConfig.getSsid())) { throw new IllegalArgumentException("Empty service name"); } - if (TextUtils.isEmpty(mAdbConfig.preSharedKey)) { + if (TextUtils.isEmpty(mAdbConfig.getPreSharedKey())) { throw new IllegalArgumentException("Empty password"); } } - @NonNull - public WifiConfiguration getAdbNetworkConfig() { + public WifiNetworkConfig getAdbNetworkConfig() { return mAdbConfig; } @@ -67,4 +110,117 @@ public class AdbQrCode extends WifiQrCode { public static void triggerVibrationForQrCodeRecognition(Context context) { WifiDppUtils.triggerVibrationForQrCodeRecognition(context); } + + /** Parses Wi-Fi DPP QR code string */ + private void parseWifiDppQrCode(String qrCode) throws IllegalArgumentException { + List keyValueList = getKeyValueList(qrCode, PREFIX_DPP, DELIMITER_QR_CODE); + String publicKey = getValueOrNull(keyValueList, PREFIX_DPP_PUBLIC_KEY); + if (TextUtils.isEmpty(publicKey)) { + throw new IllegalArgumentException("Invalid format"); + } + mPublicKey = publicKey; + mInformation = getValueOrNull(keyValueList, PREFIX_DPP_INFORMATION); + } + + /** Parses ZXing reader library's Wi-Fi Network config format */ + private void parseZxingWifiQrCode(String qrCode) throws IllegalArgumentException { + List keyValueList = getKeyValueList(qrCode, PREFIX_ZXING_WIFI_NETWORK_CONFIG, + DELIMITER_QR_CODE); + String security = getValueOrNull(keyValueList, PREFIX_ZXING_SECURITY); + String ssid = getValueOrNull(keyValueList, PREFIX_ZXING_SSID); + String password = getValueOrNull(keyValueList, PREFIX_ZXING_PASSWORD); + String hiddenSsidString = getValueOrNull(keyValueList, PREFIX_ZXING_HIDDEN_SSID); + boolean hiddenSsid = "true".equalsIgnoreCase(hiddenSsidString); + //"\", ";", "," and ":" are escaped with a backslash "\", should remove at first + security = removeBackSlash(security); + ssid = removeBackSlash(ssid); + password = removeBackSlash(password); + mAdbConfig = WifiNetworkConfig.getValidConfigOrNull(security, ssid, password, + hiddenSsid, WifiConfiguration.INVALID_NETWORK_ID, /* isHotspot */ false); + if (mAdbConfig == null) { + throw new IllegalArgumentException("Invalid format"); + } + } + + /** + * Splits key/value pairs from qrCode + * + * @param qrCode the QR code raw string + * @param prefixQrCode the string before all key/value pairs in qrCode + * @param delimiter the string to split key/value pairs, can't contain a backslash + * @return a list contains string of key/value (e.g. K:key1) + */ + private List getKeyValueList(String qrCode, String prefixQrCode, + String delimiter) { + String keyValueString = qrCode.substring(prefixQrCode.length()); + // Should not treat \delimiter as a delimiter + String regex = "(? keyValueList, String prefix) { + for (String keyValue : keyValueList) { + String strippedKeyValue = keyValue.stripLeading(); + if (strippedKeyValue.startsWith(prefix)) { + return strippedKeyValue.substring(prefix.length()); + } + } + return null; + } + + @VisibleForTesting + String removeBackSlash(String input) { + if (input == null) { + return null; + } + StringBuilder sb = new StringBuilder(); + boolean backSlash = false; + for (char ch : input.toCharArray()) { + if (ch != '\\') { + sb.append(ch); + backSlash = false; + } else { + if (backSlash) { + sb.append(ch); + backSlash = false; + continue; + } + backSlash = true; + } + } + return sb.toString(); + } + + String getQrCode() { + return mQrCode; + } + + /** + * Uses to check type of QR code + * + * SCHEME_DPP for standard Wi-Fi device provision protocol; SCHEME_ZXING_WIFI_NETWORK_CONFIG + * for ZXing reader library' Wi-Fi Network config format + */ + public String getScheme() { + return mScheme; + } + + /** Available when {@code getScheme()} returns SCHEME_DPP */ + @VisibleForTesting + String getPublicKey() { + return mPublicKey; + } + + /** May be available when {@code getScheme()} returns SCHEME_DPP */ + public String getInformation() { + return mInformation; + } + + /** Available when {@code getScheme()} returns SCHEME_ZXING_WIFI_NETWORK_CONFIG */ + WifiNetworkConfig getWifiNetworkConfig() { + if (mAdbConfig == null) { + return null; + } + return new WifiNetworkConfig(mAdbConfig); + } } diff --git a/tests/unit/src/com/android/settings/network/ResetNetworkOperationBuilderTest.java b/tests/unit/src/com/android/settings/network/ResetNetworkOperationBuilderTest.java index 5f544064924..7f1c475dbfd 100644 --- a/tests/unit/src/com/android/settings/network/ResetNetworkOperationBuilderTest.java +++ b/tests/unit/src/com/android/settings/network/ResetNetworkOperationBuilderTest.java @@ -16,20 +16,16 @@ package com.android.settings.network; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import android.content.ContentProvider; -import android.content.ContentResolver; +import android.content.ContentProviderClient; import android.content.Context; import android.net.ConnectivityManager; import android.net.NetworkPolicyManager; @@ -67,7 +63,7 @@ public class ResetNetworkOperationBuilderTest { @Mock private NetworkPolicyManager mNetworkPolicyManager; @Mock - private ContentProvider mContentProvider;; + private ContentProviderClient mContentProviderClient; private Context mContext; @@ -77,9 +73,8 @@ public class ResetNetworkOperationBuilderTest { public void setUp() { MockitoAnnotations.initMocks(this); mContext = spy(ApplicationProvider.getApplicationContext()); - doReturn(ContentResolver.wrap(mContentProvider)).when(mContext).getContentResolver(); - mBuilder = spy(new ResetNetworkOperationBuilder(mContext)); + doReturn(mContentProviderClient).when(mBuilder).getUnstableTelephonyContentProviderClient(); } @Test @@ -184,38 +179,38 @@ public class ResetNetworkOperationBuilderTest { } @Test - public void restartPhoneProcess_withoutTelephonyContentProvider_shouldNotCrash() { - doThrow(new IllegalArgumentException()).when(mContentProvider).call( - anyString(), anyString(), anyString(), any()); + public void restartPhoneProcess_withoutTelephonyContentProvider_shouldNotCrash() + throws Exception { + doReturn(null).when(mBuilder).getUnstableTelephonyContentProviderClient(); mBuilder.restartPhoneProcess().build().run(); } @Test - public void restartRild_withoutTelephonyContentProvider_shouldNotCrash() { - doThrow(new IllegalArgumentException()).when(mContentProvider).call( - anyString(), anyString(), anyString(), any()); + public void restartRild_withoutTelephonyContentProvider_shouldNotCrash() + throws Exception { + doReturn(null).when(mBuilder).getUnstableTelephonyContentProviderClient(); mBuilder.restartRild().build().run(); } @Test - public void restartPhoneProcess_withTelephonyContentProvider_shouldCallRestartPhoneProcess() { + public void restartPhoneProcess_withTelephonyContentProvider_shouldCallRestartPhoneProcess() + throws Exception { mBuilder.restartPhoneProcess().build().run(); - verify(mContentProvider).call( - eq(mBuilder.getResetTelephonyContentProviderAuthority()), + verify(mContentProviderClient).call( eq(ResetNetworkOperationBuilder.METHOD_RESTART_PHONE_PROCESS), isNull(), isNull()); } @Test - public void restartRild_withTelephonyContentProvider_shouldCallRestartRild() { + public void restartRild_withTelephonyContentProvider_shouldCallRestartRild() + throws Exception { mBuilder.restartRild().build().run(); - verify(mContentProvider).call( - eq(mBuilder.getResetTelephonyContentProviderAuthority()), + verify(mContentProviderClient).call( eq(ResetNetworkOperationBuilder.METHOD_RESTART_RILD), isNull(), isNull()); diff --git a/tests/unit/src/com/android/settings/wifi/dpp/AdbQrCodeTest.java b/tests/unit/src/com/android/settings/wifi/dpp/AdbQrCodeTest.java new file mode 100644 index 00000000000..44f6c56aa18 --- /dev/null +++ b/tests/unit/src/com/android/settings/wifi/dpp/AdbQrCodeTest.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2024 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.dpp; + +import static com.google.common.truth.Truth.assertThat; + +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class AdbQrCodeTest { + @Test + public void testZxParsing_validCode() { + WifiNetworkConfig config = new AdbQrCode( + "WIFI:S:reallyLONGone;T:ADB;P:somepasswo#%^**123rd").getWifiNetworkConfig(); + assertThat(config.getSsid()).isEqualTo("reallyLONGone"); + assertThat(config.getSecurity()).isEqualTo("ADB"); + assertThat(config.getPreSharedKey()).isEqualTo("somepasswo#%^**123rd"); + + config = new AdbQrCode("WIFI:S:anotherone;T:ADB;P:3#=3j9asicla").getWifiNetworkConfig(); + assertThat(config.getSsid()).isEqualTo("anotherone"); + assertThat(config.getSecurity()).isEqualTo("ADB"); + assertThat(config.getPreSharedKey()).isEqualTo("3#=3j9asicla"); + + config = new AdbQrCode("WIFI:S:xx;T:ADB;P:a").getWifiNetworkConfig(); + assertThat(config.getSsid()).isEqualTo("xx"); + assertThat(config.getSecurity()).isEqualTo("ADB"); + assertThat(config.getPreSharedKey()).isEqualTo("a"); + } + + @Test + public void testZxParsing_invalidCodeButShouldWork() { + WifiNetworkConfig config = new AdbQrCode( + "WIFI:S:reallyLONGone;T:ADB; P:somepassword").getWifiNetworkConfig(); + assertThat(config.getSsid()).isEqualTo("reallyLONGone"); + assertThat(config.getSecurity()).isEqualTo("ADB"); + assertThat(config.getPreSharedKey()).isEqualTo("somepassword"); + + config = new AdbQrCode("WIFI: S:anotherone;T:ADB;P:abcdefghihklmn").getWifiNetworkConfig(); + assertThat(config.getSsid()).isEqualTo("anotherone"); + assertThat(config.getSecurity()).isEqualTo("ADB"); + assertThat(config.getPreSharedKey()).isEqualTo("abcdefghihklmn"); + + config = new AdbQrCode("WIFI: S:xx; T:ADB; P:a").getWifiNetworkConfig(); + assertThat(config.getSsid()).isEqualTo("xx"); + assertThat(config.getSecurity()).isEqualTo("ADB"); + assertThat(config.getPreSharedKey()).isEqualTo("a"); + } +} +