Merge "Use a Quantity String for the autofill password count." into sc-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 71941d1..437ffbe 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1234,7 +1234,6 @@
<activity android:name=".applications.InstalledAppOpenByDefaultActivity"
android:label="@string/application_info_label"
- android:permission="android.permission.OPEN_APP_OPEN_BY_DEFAULT_SETTINGS"
android:exported="true">
<intent-filter android:priority="1">
<action android:name="com.android.settings.APP_OPEN_BY_DEFAULT_SETTINGS" />
diff --git a/res/layout/more_settings_button.xml b/res/layout/more_settings_button.xml
new file mode 100644
index 0000000..4bbe119
--- /dev/null
+++ b/res/layout/more_settings_button.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2021 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.
+ -->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <Button
+ android:id="@+id/button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginTop="20dip"
+ android:layout_marginBottom="20dip"
+ style="@style/ActionPrimaryButton"
+ settings:allowDividerBelow="true"
+ android:gravity="center" />
+
+</LinearLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 4ef23a5..8aca71a 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -839,6 +839,8 @@
<string name="security_settings_face_settings_use_face_for_apps">App sign-in \u0026 payments</string>
<!-- Title for a category shown for the face settings page, followed by items that the user can toggle on/off to require/disable. -->
<string name="security_settings_face_settings_require_category">Requirements for face unlock</string>
+ <!-- Title for a category shown for the face settings page, followed by items that the user can toggle on/off to require/disable. [CHAR LIMIT=50] -->
+ <string name="security_settings_face_settings_preferences_category">When using face unlock</string>
<!-- Text shown on a toggle which disables/enables face unlock, depending if the user's eyes are open. [CHAR LIMIT=30] -->
<string name="security_settings_face_settings_require_attention">Require eyes to be open</string>
<!-- Text shown on the details of a toggle which disables/enables face unlock, depending if the user's eyes are open. [CHAR LIMIT=70] -->
@@ -849,6 +851,8 @@
<string name="security_settings_face_settings_require_confirmation_details">When using face unlock in apps, always require confirmation step</string>
<!-- Button text in face settings which removes the user's faces from the device [CHAR LIMIT=20] -->
<string name="security_settings_face_settings_remove_face_data">Delete face data</string>
+ <!-- Button text in face settings which removes the user's face model from the device [CHAR LIMIT=40] -->
+ <string name="security_settings_face_settings_remove_face_model">Delete face model</string>
<!-- Button text in face settings which lets the user enroll their face [CHAR LIMIT=40] -->
<string name="security_settings_face_settings_enroll">Set up face unlock</string>
<!-- Text shown in face settings explaining what your face can be used for. [CHAR LIMIT=NONE] -->
@@ -861,6 +865,10 @@
<string name="security_settings_face_settings_remove_dialog_title">Delete face data?</string>
<!-- Dialog contents shown when the user removes an enrollment [CHAR LIMIT=NONE] -->
<string name="security_settings_face_settings_remove_dialog_details">The face data used by face unlock will be permanently and securely deleted. After removal, you will need your PIN, pattern, or password to unlock your phone, sign in to apps, and confirm payments.</string>
+ <!-- Dialog title shown when the user chooses to delete an existing enrolled face model. [CHAR LIMIT=35] -->
+ <string name="security_settings_face_settings_remove_model_dialog_title">Delete face model?</string>
+ <!-- Dialog contents shown when the user chooses to delete an existing enrolled face model. [CHAR LIMIT=NONE] -->
+ <string name="security_settings_face_settings_remove_model_dialog_details">Your face model will be permanently and securely deleted.\n\nAfter deletion, you will need your fingerprint, PIN, pattern, or password to unlock your phone or for authentication in apps.</string>
<!-- Subtitle shown for contextual setting face enrollment [CHAR LIMIT=NONE] -->
<string name="security_settings_face_settings_context_subtitle">Use face unlock to unlock your phone</string>
@@ -1064,6 +1072,25 @@
<!-- Button to confirm the last removing the last fingerprint. [CHAR LIMIT=20]-->
<string name="fingerprint_last_delete_confirm">Yes, remove</string>
+ <!-- Title of the combined biometrics settings screen. [CHAR LIMIT=40] -->
+ <string name="security_settings_biometrics_title">Face \u0026 fingerprint unlock</string>
+ <!-- Summary of the current biometrics setting when no biometrics have been enrolled. [CHAR LIMIT=50] -->
+ <string name="security_settings_biometrics_summary_none">Tap to set up</string>
+ <!-- Summary of the current biometrics setting when the user has enrolled a face but no fingerprint. [CHAR LIMIT=50] -->
+ <string name="security_settings_biometrics_summary_face">Face only</string>
+ <!-- Summary of the current biometrics setting when the user has enrolled a fingerprint but no face. [CHAR LIMIT=50] -->
+ <string name="security_settings_biometrics_summary_fingerprint">Fingerprint only</string>
+ <!-- Summary of the current biometrics setting when the user has enrolled both a face and a fingerprint. [CHAR LIMIT=50] -->
+ <string name="security_settings_biometrics_summary_both">Face and fingerprint</string>
+ <!-- Description shown on the combined biometrics settings screen. [CHAR LIMIT=NONE] -->
+ <string name="security_settings_biometrics_description">When you set up face and fingerprint unlock, your phone will ask for your fingerprint when you wear a mask or are in a dark area</string>
+ <!-- Title of a section on the biometrics settings screen for setting up different types of authentication. [CHAR LIMIT=50] -->
+ <string name="security_settings_biometrics_types_category">Ways to unlock</string>
+ <!-- Title of a section on the biometrics settings screen for adjusting authentication preferences. [CHAR LIMIT=50] -->
+ <string name="security_settings_biometrics_preferences_category">Use face or fingerprint for</string>
+ <!-- Title of a section on the biometrics settings screen for adjusting authentication preferences. [CHAR LIMIT=50] -->
+ <string name="security_settings_biometrics_preference_use_with_apps">Authentication in apps</string>
+
<!-- Title of the preferences category for preference items to control encryption -->
<string name="crypt_keeper_settings_title">Encryption</string>
@@ -1328,15 +1355,15 @@
<string name="face_unlock_title">You can unlock your phone using your face. For security, this option requires a backup screen lock.</string>
<!-- Title for preference that guides the user through creating a backup unlock pattern for biometrics unlock [CHAR LIMIT=45]-->
- <string name="biometrics_unlock_set_unlock_pattern">Biometrics + Pattern</string>
+ <string name="biometrics_unlock_set_unlock_pattern">Pattern \u2022 Face \u2022 Fingerprint</string>
<!-- Title for preference that guides the user through creating a backup unlock PIN for biometrics unlock [CHAR LIMIT=45]-->
- <string name="biometrics_unlock_set_unlock_pin">Biometrics + PIN</string>
+ <string name="biometrics_unlock_set_unlock_pin">PIN \u2022 Face \u2022 Fingerprint</string>
<!-- Title for preference that guides the user through creating a backup unlock password for biometrics unlock [CHAR LIMIT=45]-->
- <string name="biometrics_unlock_set_unlock_password">Biometrics + Password</string>
+ <string name="biometrics_unlock_set_unlock_password">Password \u2022 Face \u2022 Fingerprint</string>
<!-- Title for preference that guides the user to skip face unlock setup [CHAR LIMIT=60]-->
- <string name="biometrics_unlock_skip_biometrics">Continue without biometrics</string>
+ <string name="biometrics_unlock_skip_biometrics">Continue without face or fingerprint</string>
<!-- Message shown in screen lock picker while setting up the new screen lock with biometrics option. [CHAR LIMIT=NONE] -->
- <string name="biometrics_unlock_title">You can unlock your phone using your biometrics. For security, this option requires a backup screen lock.</string>
+ <string name="biometrics_unlock_title">You can unlock your phone using your face or fingerprint. For security, this option requires a backup screen lock.</string>
<!-- Summary for preference that has been disabled by because of the DevicePolicyAdmin, or because device encryption is enabled, or because there are credentials in the credential storage [CHAR LIMIT=50] -->
<string name="unlock_set_unlock_disabled_summary">Disabled by admin, encryption policy, or
@@ -3400,22 +3427,6 @@
<!-- Section header above list of external storage devices [CHAR LIMIT=30]-->
<string name="storage_external_title">Portable storage</string>
- <!-- Label for the settings activity for controlling apps that can schedule alarms [CHAR LIMIT=30] -->
- <string name="alarms_and_reminders_label">Alarms and reminders</string>
- <!-- Label for the switch to toggler the permission for scheduling alarms [CHAR LIMIT=50] -->
- <string name="alarms_and_reminders_switch_title">Allow to set alarms or reminders</string>
- <!-- Title for the setting screen for controlling apps that can schedule alarms [CHAR LIMIT=30] -->
- <string name="alarms_and_reminders_title">Alarms and reminders</string>
- <!-- Description that appears below the alarms_and_reminders switch [CHAR LIMIT=NONE] -->
- <string name="alarms_and_reminders_footer_title">
- Allow this app to schedule alarms or other timing based events.
- This will allow the app to wake up and run even when you are not using the device.
- Note that revoking this permission may cause the app to malfunction, specifically any alarms
- that the app has scheduled will no longer work.
- </string>
- <!-- Keywords for setting screen for controlling apps that can schedule alarms [CHAR LIMIT=100] -->
- <string name="keywords_alarms_and_reminders">schedule, alarm, reminder, event</string>
-
<!-- Summary of a single storage volume, constrasting available and total storage space. [CHAR LIMIT=48]-->
<string name="storage_volume_summary"><xliff:g id="used" example="1.2GB">%1$s</xliff:g> used of <xliff:g id="total" example="32GB">%2$s</xliff:g></string>
<!-- Summary of a single storage volume used space. [CHAR LIMIT=24] -->
@@ -5067,7 +5078,7 @@
<!-- Title for the accessibility magnification switch shortcut dialog. [CHAR LIMIT=48] -->
<string name="accessibility_magnification_switch_shortcut_title">Switch to accessibility button?</string>
<!-- Message for the accessibility magnification switch shortcut dialog. [CHAR LIMIT=none] -->
- <string name="accessibility_magnification_switch_shortcut_message">Using triple-tap to magnify part of the screen causes typing and other delays.\n\nThe accessibility button floats on your screen over other apps. Tap it to magnify.</string>
+ <string name="accessibility_magnification_switch_shortcut_message">Using triple-tap to magnify part of your screen causes typing and other delays.\n\nThe accessibility button floats on your screen over other apps. Tap it to magnify.</string>
<!-- Title for the switch shortcut button in accessibility switch shortcut dialog to change the config shortcut value. [CHAR LIMIT=45] -->
<string name="accessibility_magnification_switch_shortcut_positive_button">Switch to accessibility button</string>
<!-- Title for the cancel button in accessibility switch shortcut dialog to keep the config shortcut value. [CHAR LIMIT=54] -->
@@ -6400,6 +6411,10 @@
<!-- Title of preference to enter the VPN settings activity -->
<string name="vpn_settings_title">VPN</string>
+ <!-- Title of preference to enter the VPN settings activity [CHAR LIMIT=30] -->
+ <string name="vpn_settings_insecure_single">Not secure</string>
+ <!-- Title of preference to enter the VPN settings activity [CHAR LIMIT=30] -->
+ <string name="vpn_settings_insecure_multiple"><xliff:g id="vpn_count" example="1">%d</xliff:g> not secure</string>
<!-- Title of Adaptive connectivity. Adaptive connectivity is a feature which automatically manages network connections for better battery life and performance. [CHAR LIMIT=60] -->
<string name="adaptive_connectivity_title">Adaptive connectivity</string>
diff --git a/res/xml/emergency_settings.xml b/res/xml/emergency_settings.xml
index 28ae8b1..80d6ac0 100644
--- a/res/xml/emergency_settings.xml
+++ b/res/xml/emergency_settings.xml
@@ -32,6 +32,13 @@
android:order="100"
android:fragment="com.android.settings.emergency.EmergencyGestureSettings"
settings:controller="com.android.settings.emergency.EmergencyGestureEntrypointPreferenceController" />
+ <com.android.settingslib.widget.LayoutPreference
+ android:key="more_settings"
+ android:layout="@layout/more_settings_button"
+ android:order="180"
+ android:selectable="false"
+ settings:allowDividerBelow="true"
+ settings:controller="com.android.settings.emergency.MoreSettingsPreferenceController" />
<com.android.settingslib.RestrictedPreference
android:key="app_and_notif_cell_broadcast_settings"
android:title="@string/cell_broadcast_settings"
diff --git a/src/com/android/settings/emergency/MoreSettingsPreferenceController.java b/src/com/android/settings/emergency/MoreSettingsPreferenceController.java
new file mode 100644
index 0000000..34c11c7
--- /dev/null
+++ b/src/com/android/settings/emergency/MoreSettingsPreferenceController.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2021 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.emergency;
+
+import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
+import static android.content.pm.PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
+import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.widget.Button;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.widget.LayoutPreference;
+
+import java.util.List;
+
+/**
+ * Preference controller for More settings button
+ */
+public class MoreSettingsPreferenceController extends BasePreferenceController implements
+ View.OnClickListener {
+
+ private static final String EXTRA_KEY_ATTRIBUTION = "attribution";
+ private static final String TAG = "MoreSettingsPrefCtrl";
+ @VisibleForTesting
+ Intent mIntent;
+
+ public MoreSettingsPreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ final String packageName = mContext.getResources().getString(
+ R.string.config_emergency_package_name);
+
+ if (TextUtils.isEmpty(packageName)) {
+ return;
+ }
+ mIntent = new Intent(Intent.ACTION_MAIN)
+ .setPackage(packageName);
+
+ final List<ResolveInfo> info = mContext.getPackageManager()
+ .queryIntentActivities(mIntent, MATCH_SYSTEM_ONLY);
+
+ if (info != null && !info.isEmpty()) {
+ mIntent.setClassName(packageName, info.get(0).activityInfo.name);
+ } else {
+ mIntent = null;
+ }
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ final LayoutPreference pref = screen.findPreference(getPreferenceKey());
+ final Button button = pref.findViewById(R.id.button);
+ button.setText(getButtonText());
+ button.setOnClickListener(this);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (mIntent == null) {
+ return UNSUPPORTED_ON_DEVICE;
+ } else {
+ return AVAILABLE;
+ }
+ }
+
+ @Override
+ public void onClick(View v) {
+ final Intent intent = new Intent(mIntent)
+ .addCategory(Intent.CATEGORY_LAUNCHER)
+ .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ Bundle bundle = new Bundle();
+ bundle.putString(EXTRA_KEY_ATTRIBUTION, mContext.getPackageName());
+ mContext.startActivity(intent, bundle);
+ }
+
+ private CharSequence getButtonText() {
+ final String packageName = mContext.getResources().getString(
+ R.string.config_emergency_package_name);
+ try {
+ final PackageManager pm = mContext.getPackageManager();
+ final ApplicationInfo appInfo = pm.getApplicationInfo(
+ packageName, MATCH_DISABLED_COMPONENTS
+ | MATCH_DISABLED_UNTIL_USED_COMPONENTS);
+ return mContext.getString(R.string.open_app_button, appInfo.loadLabel(pm));
+ } catch (Exception e) {
+ Log.d(TAG, "Failed to get open app button text, falling back.");
+ return "";
+ }
+ }
+}
diff --git a/src/com/android/settings/network/VpnPreferenceController.java b/src/com/android/settings/network/VpnPreferenceController.java
index 3116dd4..0bec7ac 100644
--- a/src/com/android/settings/network/VpnPreferenceController.java
+++ b/src/com/android/settings/network/VpnPreferenceController.java
@@ -124,6 +124,7 @@
// Copied from SystemUI::SecurityControllerImpl
SparseArray<VpnConfig> vpns = new SparseArray<>();
final List<UserInfo> users = mUserManager.getUsers();
+ int connectedLegacyVpnCount = 0;
for (UserInfo user : users) {
VpnConfig cfg = mVpnManager.getVpnConfig(user.id);
if (cfg == null) {
@@ -134,6 +135,8 @@
final LegacyVpnInfo legacyVpn = mVpnManager.getLegacyVpnInfo(user.id);
if (legacyVpn == null || legacyVpn.state != LegacyVpnInfo.STATE_CONNECTED) {
continue;
+ } else {
+ connectedLegacyVpnCount++;
}
}
vpns.put(user.id, cfg);
@@ -146,7 +149,7 @@
uid = userInfo.id;
}
VpnConfig vpn = vpns.get(uid);
- final String summary;
+ String summary;
if (vpn == null) {
summary = mContext.getString(R.string.vpn_disconnected_summary);
} else {
@@ -154,9 +157,26 @@
}
// Optionally add warning icon if an insecure VPN is present.
if (Utils.isProviderModelEnabled(mContext) && mPreference instanceof VpnInfoPreference) {
- ((VpnInfoPreference) mPreference).setInsecureVpn(hasInsecureVpn());
+ final int insecureVpnCount = getInsecureVpnCount();
+ boolean isInsecureVPN = insecureVpnCount > 0;
+ ((VpnInfoPreference) mPreference).setInsecureVpn(isInsecureVPN);
+ // Set the summary based on the total number of VPNs and insecure VPNs.
+ if (isInsecureVPN) {
+ // Add the users and the number of legacy vpns to determine if there is more than
+ // one vpn, since there can be more than one VPN per user.
+ final int vpnCount = vpns.size()
+ + LegacyVpnProfileStore.list(Credentials.VPN).length
+ - connectedLegacyVpnCount;
+ if (vpnCount == 1) {
+ summary = mContext.getString(R.string.vpn_settings_insecure_single);
+ } else {
+ summary = mContext.getString(
+ R.string.vpn_settings_insecure_multiple, insecureVpnCount);
+ }
+ }
}
- ThreadUtils.postOnMainThread(() -> mPreference.setSummary(summary));
+ final String finalSummary = summary;
+ ThreadUtils.postOnMainThread(() -> mPreference.setSummary(finalSummary));
}
@VisibleForTesting
@@ -177,17 +197,18 @@
}
@VisibleForTesting
- protected boolean hasInsecureVpn() {
+ protected int getInsecureVpnCount() {
+ int count = 0;
for (String key : LegacyVpnProfileStore.list(Credentials.VPN)) {
final VpnProfile profile = VpnProfile.decode(key,
LegacyVpnProfileStore.get(Credentials.VPN + key));
// Return whether any profile is an insecure type.
if (VpnProfile.isLegacyType(profile.type)) {
- return true;
+ count++;
}
}
// We did not find any insecure VPNs.
- return false;
+ return count;
}
// Copied from SystemUI::SecurityControllerImpl
diff --git a/tests/unit/src/com/android/settings/network/EraseEuiccDataControllerTest.java b/tests/unit/src/com/android/settings/network/EraseEuiccDataControllerTest.java
index 6ddef5d..879b9f7 100644
--- a/tests/unit/src/com/android/settings/network/EraseEuiccDataControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/EraseEuiccDataControllerTest.java
@@ -18,8 +18,6 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.spy;
-
import android.content.Context;
import androidx.test.core.app.ApplicationProvider;
diff --git a/tests/robotests/src/com/android/settings/network/VpnPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/VpnPreferenceControllerTest.java
similarity index 72%
rename from tests/robotests/src/com/android/settings/network/VpnPreferenceControllerTest.java
rename to tests/unit/src/com/android/settings/network/VpnPreferenceControllerTest.java
index fb66d29..ee239ba 100644
--- a/tests/robotests/src/com/android/settings/network/VpnPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/VpnPreferenceControllerTest.java
@@ -22,7 +22,6 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -32,34 +31,38 @@
import android.net.ConnectivityManager;
import android.net.NetworkRequest;
import android.net.VpnManager;
+import android.os.Looper;
import android.os.UserHandle;
+import android.provider.Settings;
import android.provider.SettingsSlicesContract;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
+import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.internal.net.VpnConfig;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-@RunWith(RobolectricTestRunner.class)
+@RunWith(AndroidJUnit4.class)
public class VpnPreferenceControllerTest {
+ private static final String VPN_PREFERENCE_KEY = "vpn_settings";
- @Mock
private Context mContext;
@Mock
private ConnectivityManager mConnectivityManager;
@Mock
private VpnManager mVpnManager;
- @Mock
private PreferenceScreen mScreen;
@Mock
private Preference mPreference;
@@ -68,12 +71,21 @@
private LifecycleOwner mLifecycleOwner;
@Before
+ @UiThreadTest
public void setUp() {
MockitoAnnotations.initMocks(this);
+ mContext = spy(ApplicationProvider.getApplicationContext());
when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
.thenReturn(mConnectivityManager);
when(mContext.getSystemService(VpnManager.class)).thenReturn(mVpnManager);
- when(mScreen.findPreference(anyString())).thenReturn(mPreference);
+
+ if (Looper.myLooper() == null) {
+ Looper.prepare();
+ }
+ PreferenceManager preferenceManager = new PreferenceManager(mContext);
+ mScreen = preferenceManager.createPreferenceScreen(mContext);
+ when(mPreference.getKey()).thenReturn(VPN_PREFERENCE_KEY);
+ mScreen.addPreference(mPreference);
mController = spy(new VpnPreferenceController(mContext));
mLifecycleOwner = () -> mLifecycle;
@@ -83,13 +95,20 @@
@Test
public void displayPreference_available_shouldSetDependency() {
- doReturn(true).when(mController).isAvailable();
- mController.displayPreference(mScreen);
+ Settings.Global.putString(mContext.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS, "");
+ VpnPreferenceController controller = spy(new VpnPreferenceController(mContext));
+ doReturn(true).when(controller).isAvailable();
+
+ controller.displayPreference(mScreen);
verify(mPreference).setDependency(SettingsSlicesContract.KEY_AIRPLANE_MODE);
}
@Test
+ // TODO(b/176821216) re-enable this test once VpnPreferenceController is edited to notify
+ // the preference of legacy VPNs
+ @Ignore
public void goThroughLifecycle_shouldRegisterUnregisterListener() {
doReturn(true).when(mController).isAvailable();
@@ -107,7 +126,7 @@
final VpnConfig config = new VpnConfig();
config.legacy = true;
final VpnPreferenceController controller =
- new VpnPreferenceController(RuntimeEnvironment.application);
+ new VpnPreferenceController(ApplicationProvider.getApplicationContext());
final String summary = controller.getNameForVpnConfig(config, UserHandle.CURRENT);