Snap for 8961426 from 662e5722b3 to tm-qpr1-release

Change-Id: Ibcaa452224f959730e50a514b0fc7773b305ea4c
This commit is contained in:
Android Build Coastguard Worker
2022-08-17 23:30:11 +00:00
14 changed files with 398 additions and 29 deletions

View File

@@ -184,6 +184,11 @@
<!-- Keywords for bluetooth pairing item [CHAR LIMIT=30] --> <!-- Keywords for bluetooth pairing item [CHAR LIMIT=30] -->
<string name="keywords_add_bt_device">bluetooth</string> <string name="keywords_add_bt_device">bluetooth</string>
<!-- Button to help user to pair right ear of the hearing aid device. It will show when only one of the hearing aid device set is connected. [CHAR LIMIT=20] -->
<string name="bluetooth_pair_right_ear_button">Pair right ear</string>
<!-- Button to help user to pair left ear of the hearing aid device. It will show when only one of the hearing aid device set is connected. [CHAR LIMIT=20] -->
<string name="bluetooth_pair_left_ear_button">Pair left ear</string>
<!-- Connected devices settings. Title of the dialog to hint user to pair other ear of the hearing aid device. Shows when only one of the hearing aid device set is connected. [CHAR LIMIT=25] --> <!-- Connected devices settings. Title of the dialog to hint user to pair other ear of the hearing aid device. Shows when only one of the hearing aid device set is connected. [CHAR LIMIT=25] -->
<string name="bluetooth_pair_other_ear_dialog_title">Pair your other ear</string> <string name="bluetooth_pair_other_ear_dialog_title">Pair your other ear</string>
<!-- Connected devices settings. Message of the dialog to hint user to pair right ear of the hearing aid device. Shows when only left side of hearing aid device set is connected. [CHAR LIMIT=NONE] --> <!-- Connected devices settings. Message of the dialog to hint user to pair right ear of the hearing aid device. Shows when only left side of hearing aid device set is connected. [CHAR LIMIT=NONE] -->

View File

@@ -42,6 +42,12 @@
settings:searchable="false" settings:searchable="false"
settings:controller="com.android.settings.bluetooth.LeAudioBluetoothDetailsHeaderController"/> settings:controller="com.android.settings.bluetooth.LeAudioBluetoothDetailsHeaderController"/>
<com.android.settingslib.widget.ButtonPreference
android:key="hearing_aid_pair_other_button"
android:gravity="center" />
<com.android.settings.applications.SpacePreference
android:layout_height="8dp" />
<com.android.settingslib.widget.ActionButtonsPreference <com.android.settingslib.widget.ActionButtonsPreference
android:key="action_buttons" android:key="action_buttons"
settings:allowDividerBelow="true"/> settings:allowDividerBelow="true"/>

View File

@@ -18,10 +18,11 @@ import android.content.Context;
import android.os.Build; import android.os.Build;
import android.service.notification.NotificationListenerFilter; import android.service.notification.NotificationListenerFilter;
import androidx.preference.Preference;
import com.android.settings.core.BasePreferenceController; import com.android.settings.core.BasePreferenceController;
import com.android.settings.notification.NotificationBackend; import com.android.settings.notification.NotificationBackend;
public class BridgedAppsLinkPreferenceController extends BasePreferenceController { public class BridgedAppsLinkPreferenceController extends BasePreferenceController {
private ComponentName mCn; private ComponentName mCn;
@@ -61,7 +62,6 @@ public class BridgedAppsLinkPreferenceController extends BasePreferenceControlle
if (mTargetSdk > Build.VERSION_CODES.S) { if (mTargetSdk > Build.VERSION_CODES.S) {
return AVAILABLE; return AVAILABLE;
} }
mNlf = mNm.getListenerFilter(mCn, mUserId); mNlf = mNm.getListenerFilter(mCn, mUserId);
if (!mNlf.areAllTypesAllowed() || !mNlf.getDisallowedPackages().isEmpty()) { if (!mNlf.areAllTypesAllowed() || !mNlf.getDisallowedPackages().isEmpty()) {
return AVAILABLE; return AVAILABLE;
@@ -69,4 +69,10 @@ public class BridgedAppsLinkPreferenceController extends BasePreferenceControlle
} }
return DISABLED_DEPENDENT_SETTING; return DISABLED_DEPENDENT_SETTING;
} }
@Override
public void updateState(Preference pref) {
pref.setEnabled(getAvailabilityStatus() == AVAILABLE);
super.updateState(pref);
}
} }

View File

@@ -233,11 +233,7 @@ public class NotificationAccessDetails extends DashboardFragment {
apc.updateState(screen.findPreference(apc.getPreferenceKey())); apc.updateState(screen.findPreference(apc.getPreferenceKey()));
getPreferenceControllers().forEach(controllers -> { getPreferenceControllers().forEach(controllers -> {
controllers.forEach(controller -> { controllers.forEach(controller -> {
if (controller instanceof TypeFilterPreferenceController) { controller.updateState(screen.findPreference(controller.getPreferenceKey()));
TypeFilterPreferenceController tfpc =
(TypeFilterPreferenceController) controller;
tfpc.updateState(screen.findPreference(tfpc.getPreferenceKey()));
}
}); });
}); });
} }
@@ -249,11 +245,7 @@ public class NotificationAccessDetails extends DashboardFragment {
apc.updateState(screen.findPreference(apc.getPreferenceKey())); apc.updateState(screen.findPreference(apc.getPreferenceKey()));
getPreferenceControllers().forEach(controllers -> { getPreferenceControllers().forEach(controllers -> {
controllers.forEach(controller -> { controllers.forEach(controller -> {
if (controller instanceof TypeFilterPreferenceController) { controller.updateState(screen.findPreference(controller.getPreferenceKey()));
TypeFilterPreferenceController tfpc =
(TypeFilterPreferenceController) controller;
tfpc.updateState(screen.findPreference(tfpc.getPreferenceKey()));
}
}); });
}); });
} }

View File

@@ -0,0 +1,102 @@
/*
* Copyright (C) 2022 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.bluetooth;
import android.content.Context;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.core.SubSettingLauncher;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.HearingAidProfile;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.widget.ButtonPreference;
/**
* This class handles button preference logic to display for hearing aid device.
*/
public class BluetoothDetailsPairOtherController extends BluetoothDetailsController {
private static final String KEY_PAIR_OTHER = "hearing_aid_pair_other_button";
private ButtonPreference mPreference;
public BluetoothDetailsPairOtherController(Context context,
PreferenceFragmentCompat fragment,
CachedBluetoothDevice device,
Lifecycle lifecycle) {
super(context, fragment, device, lifecycle);
lifecycle.addObserver(this);
}
@Override
public boolean isAvailable() {
return getButtonPreferenceVisibility(mCachedDevice);
}
@Override
public String getPreferenceKey() {
return KEY_PAIR_OTHER;
}
@Override
protected void init(PreferenceScreen screen) {
final int side = mCachedDevice.getDeviceSide();
final int stringRes = (side == HearingAidProfile.DeviceSide.SIDE_LEFT)
? R.string.bluetooth_pair_right_ear_button
: R.string.bluetooth_pair_left_ear_button;
mPreference = screen.findPreference(getPreferenceKey());
mPreference.setTitle(stringRes);
mPreference.setOnClickListener(v -> launchPairingDetail());
}
@Override
protected void refresh() {
mPreference.setVisible(getButtonPreferenceVisibility(mCachedDevice));
}
private boolean getButtonPreferenceVisibility(CachedBluetoothDevice cachedDevice) {
return isBinauralMode(cachedDevice) && isOnlyOneSideConnected(cachedDevice);
}
private void launchPairingDetail() {
new SubSettingLauncher(mContext)
.setDestination(BluetoothPairingDetail.class.getName())
.setSourceMetricsCategory(
((BluetoothDeviceDetailsFragment) mFragment).getMetricsCategory())
.launch();
}
private boolean isBinauralMode(CachedBluetoothDevice cachedDevice) {
return cachedDevice.getDeviceMode() == HearingAidProfile.DeviceMode.MODE_BINAURAL;
}
private boolean isOnlyOneSideConnected(CachedBluetoothDevice cachedDevice) {
if (!cachedDevice.isConnectedHearingAidDevice()) {
return false;
}
final CachedBluetoothDevice subDevice = cachedDevice.getSubDevice();
if (subDevice != null && subDevice.isConnectedHearingAidDevice()) {
return false;
}
return true;
}
}

View File

@@ -251,6 +251,8 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
lifecycle)); lifecycle));
controllers.add(new BluetoothDetailsRelatedToolsController(context, this, mCachedDevice, controllers.add(new BluetoothDetailsRelatedToolsController(context, this, mCachedDevice,
lifecycle)); lifecycle));
controllers.add(new BluetoothDetailsPairOtherController(context, this, mCachedDevice,
lifecycle));
} }
return controllers; return controllers;
} }

View File

@@ -107,7 +107,6 @@ public class ConfigureNotificationSettings extends DashboardFragment implements
mNotificationAssistantPreferenceController = mNotificationAssistantPreferenceController =
use(NotificationAssistantPreferenceController.class); use(NotificationAssistantPreferenceController.class);
mNotificationAssistantPreferenceController.setFragment(this); mNotificationAssistantPreferenceController.setFragment(this);
mNotificationAssistantPreferenceController.setBackend(new NotificationBackend());
} }
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context, private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,

View File

@@ -44,6 +44,7 @@ public class NotificationAssistantPreferenceController extends TogglePreferenceC
public NotificationAssistantPreferenceController(Context context) { public NotificationAssistantPreferenceController(Context context) {
super(context, KEY_NAS); super(context, KEY_NAS);
mUserManager = UserManager.get(context); mUserManager = UserManager.get(context);
mNotificationBackend = new NotificationBackend();
} }
@Override @Override
@@ -101,4 +102,9 @@ public class NotificationAssistantPreferenceController extends TogglePreferenceC
void setBackend(NotificationBackend backend) { void setBackend(NotificationBackend backend) {
mNotificationBackend = backend; mNotificationBackend = backend;
} }
@Override
public boolean isSliceable() {
return (mFragment != null && mFragment instanceof ConfigureNotificationSettings);
}
} }

View File

@@ -47,4 +47,9 @@ public interface AdvancedVpnFeatureProvider {
* Returns {@code true} advanced vpn is removable. * Returns {@code true} advanced vpn is removable.
*/ */
boolean isAdvancedVpnRemovable(); boolean isAdvancedVpnRemovable();
/**
* Returns {@code true} if the disconnect dialog is enabled when advanced vpn is connected.
*/
boolean isDisconnectDialogEnabled();
} }

View File

@@ -46,4 +46,9 @@ public class AdvancedVpnFeatureProviderImpl implements AdvancedVpnFeatureProvide
public boolean isAdvancedVpnRemovable() { public boolean isAdvancedVpnRemovable() {
return true; return true;
} }
@Override
public boolean isDisconnectDialogEnabled() {
return true;
}
} }

View File

@@ -366,7 +366,7 @@ public class VpnSettings extends RestrictedSettingsFragment implements
public void setShownPreferences(final Collection<Preference> updates) { public void setShownPreferences(final Collection<Preference> updates) {
retainAllPreference(updates); retainAllPreference(updates);
final PreferenceGroup vpnGroup = getPreferenceScreen(); final PreferenceGroup vpnGroup = mPreferenceScreen;
updatePreferenceGroup(vpnGroup, updates); updatePreferenceGroup(vpnGroup, updates);
// Show all new preferences on the screen // Show all new preferences on the screen
@@ -448,14 +448,16 @@ public class VpnSettings extends RestrictedSettingsFragment implements
} else if (preference instanceof AppPreference) { } else if (preference instanceof AppPreference) {
AppPreference pref = (AppPreference) preference; AppPreference pref = (AppPreference) preference;
boolean connected = (pref.getState() == AppPreference.STATE_CONNECTED); boolean connected = (pref.getState() == AppPreference.STATE_CONNECTED);
String vpnPackageName = pref.getPackageName();
if (!connected) { if ((!connected) || (isAdvancedVpn(mFeatureProvider, vpnPackageName, getContext())
&& !mFeatureProvider.isDisconnectDialogEnabled())) {
try { try {
UserHandle user = UserHandle.of(pref.getUserId()); UserHandle user = UserHandle.of(pref.getUserId());
Context userContext = getActivity().createPackageContextAsUser( Context userContext = getContext().createPackageContextAsUser(
getActivity().getPackageName(), 0 /* flags */, user); getContext().getPackageName(), 0 /* flags */, user);
PackageManager pm = userContext.getPackageManager(); PackageManager pm = userContext.getPackageManager();
Intent appIntent = pm.getLaunchIntentForPackage(pref.getPackageName()); Intent appIntent = pm.getLaunchIntentForPackage(vpnPackageName);
if (appIntent != null) { if (appIntent != null) {
userContext.startActivityAsUser(appIntent, user); userContext.startActivityAsUser(appIntent, user);
return true; return true;

View File

@@ -0,0 +1,121 @@
/*
* Copyright (C) 2022 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.bluetooth;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
import com.android.settings.R;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.HearingAidProfile;
import com.android.settingslib.widget.ButtonPreference;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
/** Tests for {@link BluetoothDetailsPairOtherController}. */
@RunWith(RobolectricTestRunner.class)
public class BluetoothDetailsPairOtherControllerTest extends BluetoothDetailsControllerTestBase {
@Rule
public final MockitoRule mockito = MockitoJUnit.rule();
@Mock
private CachedBluetoothDevice mSubCachedDevice;
private BluetoothDetailsPairOtherController mController;
private ButtonPreference mPreference;
@Override
public void setUp() {
super.setUp();
mController = new BluetoothDetailsPairOtherController(mContext, mFragment, mCachedDevice,
mLifecycle);
mPreference = new ButtonPreference(mContext);
mPreference.setKey(mController.getPreferenceKey());
mScreen.addPreference(mPreference);
}
@Test
public void init_leftSideDevice_expectedTitle() {
when(mCachedDevice.getDeviceSide()).thenReturn(HearingAidProfile.DeviceSide.SIDE_LEFT);
mController.init(mScreen);
assertThat(mPreference.getTitle().toString()).isEqualTo(
mContext.getString(R.string.bluetooth_pair_right_ear_button));
}
@Test
public void init_rightSideDevice_expectedTitle() {
when(mCachedDevice.getDeviceSide()).thenReturn(HearingAidProfile.DeviceSide.SIDE_RIGHT);
mController.init(mScreen);
assertThat(mPreference.getTitle().toString()).isEqualTo(
mContext.getString(R.string.bluetooth_pair_left_ear_button));
}
@Test
public void isAvailable_isConnectedHearingAidDevice_available() {
when(mCachedDevice.isConnectedHearingAidDevice()).thenReturn(false);
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void isAvailable_notConnectedHearingAidDevice_notAvailable() {
when(mCachedDevice.isConnectedHearingAidDevice()).thenReturn(true);
when(mCachedDevice.getDeviceMode()).thenReturn(HearingAidProfile.DeviceMode.MODE_MONAURAL);
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void isAvailable_subDeviceIsConnectedHearingAidDevice_notAvailable() {
when(mCachedDevice.isConnectedHearingAidDevice()).thenReturn(true);
when(mCachedDevice.getDeviceMode()).thenReturn(HearingAidProfile.DeviceMode.MODE_BINAURAL);
when(mSubCachedDevice.isConnectedHearingAidDevice()).thenReturn(true);
when(mCachedDevice.getSubDevice()).thenReturn(mSubCachedDevice);
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void isAvailable_subDeviceNotConnectedHearingAidDevice_available() {
when(mCachedDevice.isConnectedHearingAidDevice()).thenReturn(true);
when(mCachedDevice.getDeviceMode()).thenReturn(HearingAidProfile.DeviceMode.MODE_BINAURAL);
when(mSubCachedDevice.isConnectedHearingAidDevice()).thenReturn(false);
when(mCachedDevice.getSubDevice()).thenReturn(mSubCachedDevice);
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void isAvailable_subDeviceNotExist_available() {
when(mCachedDevice.isConnectedHearingAidDevice()).thenReturn(true);
when(mCachedDevice.getDeviceMode()).thenReturn(HearingAidProfile.DeviceMode.MODE_BINAURAL);
when(mCachedDevice.getSubDevice()).thenReturn(null);
assertThat(mController.isAvailable()).isTrue();
}
}

View File

@@ -31,6 +31,7 @@ import android.content.Context;
import android.os.Build; import android.os.Build;
import android.service.notification.NotificationListenerFilter; import android.service.notification.NotificationListenerFilter;
import androidx.preference.Preference;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -68,6 +69,11 @@ public class BridgedAppsLinkPreferenceControllerTest {
mController.setTargetSdk(Build.VERSION_CODES.CUR_DEVELOPMENT + 1); mController.setTargetSdk(Build.VERSION_CODES.CUR_DEVELOPMENT + 1);
assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING); assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING);
// disables field
Preference p = new Preference(mContext);
mController.updateState(p);
assertThat(p.isEnabled()).isFalse();
} }
@Test @Test
@@ -77,6 +83,11 @@ public class BridgedAppsLinkPreferenceControllerTest {
when(mNm.getListenerFilter(mCn, 0)).thenReturn(new NotificationListenerFilter()); when(mNm.getListenerFilter(mCn, 0)).thenReturn(new NotificationListenerFilter());
assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING); assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING);
// disables field
Preference p = new Preference(mContext);
mController.updateState(p);
assertThat(p.isEnabled()).isFalse();
} }
@Test @Test
@@ -88,6 +99,11 @@ public class BridgedAppsLinkPreferenceControllerTest {
when(mNm.getListenerFilter(mCn, 0)).thenReturn(nlf); when(mNm.getListenerFilter(mCn, 0)).thenReturn(nlf);
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
// enables field
Preference p = new Preference(mContext);
mController.updateState(p);
assertThat(p.isEnabled()).isTrue();
} }
@Test @Test
@@ -97,5 +113,10 @@ public class BridgedAppsLinkPreferenceControllerTest {
when(mNm.getListenerFilter(mCn, 0)).thenReturn(new NotificationListenerFilter()); when(mNm.getListenerFilter(mCn, 0)).thenReturn(new NotificationListenerFilter());
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
// enables field
Preference p = new Preference(mContext);
mController.updateState(p);
assertThat(p.isEnabled()).isTrue();
} }
} }

View File

@@ -21,16 +21,21 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.app.AppOpsManager; import android.app.AppOpsManager;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.Looper; import android.os.Looper;
import android.os.UserHandle; import android.os.UserHandle;
import android.text.TextUtils;
import android.util.ArraySet; import android.util.ArraySet;
import androidx.preference.Preference; import androidx.preference.Preference;
@@ -48,6 +53,7 @@ import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule; import org.mockito.junit.MockitoRule;
@@ -58,13 +64,18 @@ import java.util.Set;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public class VpnSettingsTest { public class VpnSettingsTest {
private static final String ADVANCED_VPN_GROUP_KEY = "advanced_vpn_group";
private static final String VPN_GROUP_KEY = "vpn_group";
private static final String ADVANCED_VPN_GROUP_TITLE = "advanced_vpn_group_title";
private static final String VPN_GROUP_TITLE = "vpn_group_title";
private static final String FAKE_PACKAGE_NAME = "com.fake.package.name";
private static final String ADVANCED_VPN_GROUP_PACKAGE_NAME = "com.advanced.package.name";
private static final int USER_ID_1 = UserHandle.USER_NULL; private static final int USER_ID_1 = UserHandle.USER_NULL;
private static final String VPN_GROUP_KEY = "vpn_group";
private static final String VPN_GROUP_TITLE = "vpn_group_title";
private static final String VPN_PACKAGE_NAME = "vpn.package.name";
private static final String VPN_LAUNCH_INTENT = "vpn.action";
private static final String ADVANCED_VPN_GROUP_KEY = "advanced_vpn_group";
private static final String ADVANCED_VPN_GROUP_TITLE = "advanced_vpn_group_title";
private static final String ADVANCED_VPN_PACKAGE_NAME = "advanced.vpn.package.name";
private static final String ADVANCED_VPN_LAUNCH_INTENT = "advanced.vpn.action";
private final Intent mVpnIntent = new Intent().setAction(VPN_LAUNCH_INTENT);
private final Intent mAdvancedVpnIntent = new Intent().setAction(ADVANCED_VPN_LAUNCH_INTENT);
@Rule @Rule
public final MockitoRule mMockitoRule = MockitoJUnit.rule(); public final MockitoRule mMockitoRule = MockitoJUnit.rule();
@@ -108,7 +119,7 @@ public class VpnSettingsTest {
when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.getVpnPreferenceGroupTitle(mContext)) when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.getVpnPreferenceGroupTitle(mContext))
.thenReturn(VPN_GROUP_TITLE); .thenReturn(VPN_GROUP_TITLE);
when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.getAdvancedVpnPackageName()) when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.getAdvancedVpnPackageName())
.thenReturn(ADVANCED_VPN_GROUP_PACKAGE_NAME); .thenReturn(ADVANCED_VPN_PACKAGE_NAME);
when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.isAdvancedVpnSupported(any())) when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.isAdvancedVpnSupported(any()))
.thenReturn(true); .thenReturn(true);
when(mContext.getPackageManager()).thenReturn(mPackageManager); when(mContext.getPackageManager()).thenReturn(mPackageManager);
@@ -122,7 +133,7 @@ public class VpnSettingsTest {
public void setShownAdvancedPreferences_hasGeneralVpn_returnsVpnCountAs1() { public void setShownAdvancedPreferences_hasGeneralVpn_returnsVpnCountAs1() {
Set<Preference> updates = new ArraySet<>(); Set<Preference> updates = new ArraySet<>();
AppPreference pref = AppPreference pref =
spy(new AppPreference(mContext, USER_ID_1, FAKE_PACKAGE_NAME)); spy(new AppPreference(mContext, USER_ID_1, VPN_PACKAGE_NAME));
updates.add(pref); updates.add(pref);
mVpnSettings.setShownAdvancedPreferences(updates); mVpnSettings.setShownAdvancedPreferences(updates);
@@ -136,7 +147,7 @@ public class VpnSettingsTest {
public void setShownAdvancedPreferences_hasAdvancedVpn_returnsAdvancedVpnCountAs1() { public void setShownAdvancedPreferences_hasAdvancedVpn_returnsAdvancedVpnCountAs1() {
Set<Preference> updates = new ArraySet<>(); Set<Preference> updates = new ArraySet<>();
AppPreference pref = AppPreference pref =
spy(new AppPreference(mContext, USER_ID_1, ADVANCED_VPN_GROUP_PACKAGE_NAME)); spy(new AppPreference(mContext, USER_ID_1, ADVANCED_VPN_PACKAGE_NAME));
updates.add(pref); updates.add(pref);
mVpnSettings.setShownAdvancedPreferences(updates); mVpnSettings.setShownAdvancedPreferences(updates);
@@ -175,7 +186,7 @@ public class VpnSettingsTest {
List<AppOpsManager.OpEntry> opEntries = new ArrayList<>(); List<AppOpsManager.OpEntry> opEntries = new ArrayList<>();
List<AppOpsManager.PackageOps> apps = new ArrayList<>(); List<AppOpsManager.PackageOps> apps = new ArrayList<>();
AppOpsManager.PackageOps packageOps = AppOpsManager.PackageOps packageOps =
new AppOpsManager.PackageOps(FAKE_PACKAGE_NAME, uid, opEntries); new AppOpsManager.PackageOps(VPN_PACKAGE_NAME, uid, opEntries);
apps.add(packageOps); apps.add(packageOps);
when(mAppOpsManager.getPackagesForOps((int[]) any())).thenReturn(apps); when(mAppOpsManager.getPackagesForOps((int[]) any())).thenReturn(apps);
when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.isAdvancedVpnSupported(any())) when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.isAdvancedVpnSupported(any()))
@@ -185,4 +196,90 @@ public class VpnSettingsTest {
mFakeFeatureFactory.getAdvancedVpnFeatureProvider(), mFakeFeatureFactory.getAdvancedVpnFeatureProvider(),
mAppOpsManager)).isEmpty(); mAppOpsManager)).isEmpty();
} }
@Test
public void clickVpn_VpnConnected_doesNotStartVpnLaunchIntent()
throws PackageManager.NameNotFoundException {
Set<Preference> updates = new ArraySet<>();
AppPreference pref = spy(new AppPreference(mContext, USER_ID_1, VPN_PACKAGE_NAME));
pref.setState(AppPreference.STATE_CONNECTED);
updates.add(pref);
when(mContext.createPackageContextAsUser(any(), anyInt(), any())).thenReturn(mContext);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mPackageManager.getLaunchIntentForPackage(any())).thenReturn(mVpnIntent);
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
doNothing().when(mContext).startActivityAsUser(captor.capture(), any());
mVpnSettings.setShownPreferences(updates);
mVpnSettings.onPreferenceClick(pref);
verify(mContext, never()).startActivityAsUser(any(), any());
}
@Test
public void clickVpn_VpnDisconnected_startsVpnLaunchIntent()
throws PackageManager.NameNotFoundException {
Set<Preference> updates = new ArraySet<>();
AppPreference pref = spy(new AppPreference(mContext, USER_ID_1, VPN_PACKAGE_NAME));
pref.setState(AppPreference.STATE_DISCONNECTED);
updates.add(pref);
when(mContext.createPackageContextAsUser(any(), anyInt(), any())).thenReturn(mContext);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mPackageManager.getLaunchIntentForPackage(any())).thenReturn(mVpnIntent);
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
doNothing().when(mContext).startActivityAsUser(captor.capture(), any());
mVpnSettings.setShownPreferences(updates);
mVpnSettings.onPreferenceClick(pref);
verify(mContext).startActivityAsUser(captor.capture(), any());
assertThat(TextUtils.equals(captor.getValue().getAction(),
VPN_LAUNCH_INTENT)).isTrue();
}
@Test
public void clickAdvancedVpn_VpnConnectedDisconnectDialogDisabled_startsAppLaunchIntent()
throws PackageManager.NameNotFoundException {
Set<Preference> updates = new ArraySet<>();
AppPreference pref =
spy(new AppPreference(mContext, USER_ID_1, ADVANCED_VPN_PACKAGE_NAME));
pref.setState(AppPreference.STATE_CONNECTED);
updates.add(pref);
when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.isDisconnectDialogEnabled())
.thenReturn(false);
when(mContext.createPackageContextAsUser(any(), anyInt(), any())).thenReturn(mContext);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mPackageManager.getLaunchIntentForPackage(any())).thenReturn(mAdvancedVpnIntent);
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
doNothing().when(mContext).startActivityAsUser(captor.capture(), any());
mVpnSettings.setShownAdvancedPreferences(updates);
mVpnSettings.onPreferenceClick(pref);
verify(mContext).startActivityAsUser(captor.capture(), any());
assertThat(TextUtils.equals(captor.getValue().getAction(),
ADVANCED_VPN_LAUNCH_INTENT)).isTrue();
}
@Test
public void clickAdvancedVpn_VpnConnectedDisconnectDialogEnabled_doesNotStartAppLaunchIntent()
throws PackageManager.NameNotFoundException {
Set<Preference> updates = new ArraySet<>();
AppPreference pref =
spy(new AppPreference(mContext, USER_ID_1, ADVANCED_VPN_PACKAGE_NAME));
pref.setState(AppPreference.STATE_CONNECTED);
updates.add(pref);
when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.isDisconnectDialogEnabled())
.thenReturn(true);
when(mContext.createPackageContextAsUser(any(), anyInt(), any())).thenReturn(mContext);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mPackageManager.getLaunchIntentForPackage(any())).thenReturn(mAdvancedVpnIntent);
ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
doNothing().when(mContext).startActivityAsUser(captor.capture(), any());
mVpnSettings.setShownAdvancedPreferences(updates);
mVpnSettings.onPreferenceClick(pref);
verify(mContext, never()).startActivityAsUser(any(), any());
}
} }