Snap for 7155219 from a1615409c7 to sc-v2-release

Change-Id: I71c90b8a0d3dec0b5f2549d452d69960a7f867b4
This commit is contained in:
android-build-team Robot
2021-02-19 02:08:43 +00:00
41 changed files with 737 additions and 609 deletions

View File

@@ -517,12 +517,12 @@
<activity android:name=".network.telephony.ToggleSubscriptionDialogActivity"
android:exported="false"
android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
android:theme="@*android:style/Theme.DeviceDefault.Dialog.Alert.DayNight" />
android:theme="@style/Theme.AlertDialog" />
<activity android:name=".network.telephony.DeleteEuiccSubscriptionDialogActivity"
android:exported="false"
android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
android:theme="@*android:style/Theme.DeviceDefault.Dialog.Alert.DayNight" />
android:theme="@style/Theme.AlertDialog" />
<activity
android:name="Settings$TetherSettingsActivity"
@@ -954,7 +954,7 @@
<category android:name="com.android.settings.SHORTCUT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="@string/rotate_settings_class" />
android:value="com.android.settings.display.SmartAutoRotatePreferenceFragment" />
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
android:value="true" />
</activity>
@@ -3688,14 +3688,14 @@
android:exported="false"
android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
android:launchMode="singleInstance"
android:theme="@style/Transparent" />
android:theme="@style/Theme.AlertDialog" />
<activity
android:name=".sim.DsdsDialogActivity"
android:exported="false"
android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
android:launchMode="singleInstance"
android:theme="@style/Transparent" />
android:theme="@style/Theme.AlertDialog" />
<service android:name=".sim.SimNotificationService"
android:permission="android.permission.BIND_JOB_SERVICE" />

View File

@@ -0,0 +1,63 @@
<?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.
-->
<FrameLayout
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="match_parent">
<FrameLayout
android:id="@+id/pinned_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="2dp"/>
<FrameLayout
android:id="@+id/list_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="gone">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/apps_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:scrollbars="none"
settings:fastScrollEnabled="true"
settings:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable"
settings:fastScrollHorizontalTrackDrawable="@drawable/line_drawable"
settings:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable"
settings:fastScrollVerticalTrackDrawable="@drawable/line_drawable"/>
<TextView
android:id="@android:id/empty"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:layout_gravity="center"
android:text="@string/no_applications"
android:textAppearance="?android:attr/textAppearanceLarge"
android:visibility="invisible"/>
</FrameLayout>
<include layout="@layout/loading_container"/>
</FrameLayout>

View File

@@ -2713,8 +2713,6 @@
<!-- Display settings --><skip/>
<!-- Sound & display settings screen, section header for settings related to display -->
<string name="display_settings">Display</string>
<!-- Sound & display settings screen, section header for settings related to display -->
<string name="rotate_settings_class" translatable="false">com.android.settings.DisplaySettings</string>
<!-- Sound & display settings screen, accelerometer-based rotation check box label -->
<string name="accelerometer_title">Auto-rotate screen</string>
<!-- Sound & display settings screen, locked rotation check box label [CHAR LIMIT=30] -->
@@ -12194,6 +12192,8 @@
<!-- Strings for SIM push notifications -->
<!-- Category name of the notifications related to SIM setup. [CHAR LIMIT=NONE] -->
<string name="sim_setup_channel_id">Network activation</string>
<!-- Title on a push notification indicating that the user's device is in the middle of switching between mobile networks. [CHAR LIMIT=NONE] -->
<string name="sim_switch_channel_id">Carrier switching</string>
<!-- The title of post DSDS reboot notification. The title includes carrier's name. [CHAR LIMIT=NONE] -->
<string name="post_dsds_reboot_notification_title_with_carrier"><xliff:g id="carrier_name" example="Google Fi">%1$s</xliff:g> is active</string>
<!-- The body text of post DSDS reboot notification. [CHAR LIMIT=NONE] -->
@@ -12780,4 +12780,7 @@
<string name="smart_forwarding_missing_mdn_text">Phone number is missing.</string>
<!-- Alert Dialog text when user didn't input the phone number [CHAR LIMIT=50]-->
<string name="smart_forwarding_missing_alert_dialog_text">OK</string>
<!-- Enable 2G: Title for if user wants to enable 2G [CHAR LIMIT=40] -->
<string name="enable_2g_title">Allow 2G</string>
</resources>

View File

@@ -20,6 +20,13 @@
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/accelerometer_title" >
<Preference
android:key="face_rotate_permission"
android:title="@string/adaptive_sleep_title_no_permission"
android:summary="@string/adaptive_sleep_summary_no_permission"
android:icon="@drawable/ic_info_outline_24"
settings:controller="com.android.settings.display.SmartAutoRotatePermissionController" />
<SwitchPreference
android:key="face_based_rotate"
android:title="@string/auto_rotate_switch_face_based"

View File

@@ -22,16 +22,10 @@
settings:keywords="@string/keywords_location">
<PreferenceCategory
android:key="recent_location_requests"
android:title="@string/location_category_recent_location_requests"
settings:controller="com.android.settings.location.RecentLocationRequestPreferenceController"/>
<Preference
android:key="recent_location_requests_see_all_button"
android:title="@string/location_recent_location_requests_see_all"
android:icon="@drawable/ic_chevron_right_24dp"
android:fragment="com.android.settings.location.RecentLocationRequestSeeAllFragment"
settings:searchable="false"/>
android:key="recent_location_access"
android:title="@string/location_category_recent_location_access"
settings:controller=
"com.android.settings.location.RecentLocationAccessPreferenceController"/>
<PreferenceCategory
android:key="location_advanced_settings"

View File

@@ -25,14 +25,8 @@
<PreferenceCategory
android:key="recent_location_requests"
android:title="@string/location_category_recent_location_requests"
settings:controller="com.android.settings.location.RecentLocationRequestPreferenceController"/>
<Preference
android:key="recent_location_requests_see_all_button"
android:title="@string/location_recent_location_requests_see_all"
android:icon="@drawable/ic_chevron_right_24dp"
android:fragment="com.android.settings.location.RecentLocationRequestSeeAllFragment"
settings:searchable="false"/>
settings:controller=
"com.android.settings.location.RecentLocationAccessPreferenceController"/>
<!-- This preference category gets removed if new_recent_location_ui is disabled -->
<Preference

View File

@@ -25,16 +25,8 @@
<PreferenceCategory
android:key="recent_location_requests"
android:title="@string/location_category_recent_location_requests"
settings:controller="com.android.settings.location.RecentLocationRequestPreferenceController"/>
<Preference
android:key="recent_location_requests_see_all_button"
android:title="@string/location_recent_location_requests_see_all"
android:icon="@drawable/ic_chevron_right_24dp"
android:fragment="com.android.settings.location.RecentLocationRequestSeeAllFragment"
settings:controller="com.android.settings.core.WorkPreferenceController"
settings:forWork="true"
settings:searchable="false"/>
settings:controller=
"com.android.settings.location.RecentLocationAccessPreferenceController"/>
<com.android.settingslib.RestrictedSwitchPreference
android:key="managed_profile_location_switch"

View File

@@ -255,4 +255,8 @@
settings:searchable="false"
settings:controller="com.android.settings.network.telephony.NrDisabledInDsdsFooterPreferenceController"/>
<SwitchPreference
android:key="enable_2g"
android:title="@string/enable_2g_title"
settings:controller="com.android.settings.network.telephony.Enable2gPreferenceController" />
</PreferenceScreen>

View File

@@ -21,8 +21,10 @@ import android.app.settings.SettingsEnums;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.search.SearchIndexable;
/** Accessibility settings for accessibility shortcuts. */
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
public class ShortcutsSettingsFragment extends DashboardFragment {
private static final String TAG = "ShortcutsSettingsFragment";

View File

@@ -398,7 +398,11 @@ public class ManageApplications extends InstrumentedFragment
return mRootView;
}
mRootView = inflater.inflate(R.layout.manage_applications_apps, null);
if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.SILKY_HOME)) {
mRootView = inflater.inflate(R.layout.manage_applications_apps_v2, null);
} else {
mRootView = inflater.inflate(R.layout.manage_applications_apps, null);
}
mLoadingContainer = mRootView.findViewById(R.id.loading_container);
mListContainer = mRootView.findViewById(R.id.list_container);
if (mListContainer != null) {

View File

@@ -28,6 +28,7 @@ import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume;
// TODO b/180515542 this class is no longer needed on S+
public class AutoRotatePreferenceController extends TogglePreferenceController implements
PreferenceControllerMixin, Preference.OnPreferenceChangeListener, LifecycleObserver,
OnResume, OnPause {

View File

@@ -17,9 +17,15 @@ package com.android.settings.display;
import static android.provider.Settings.Secure.CAMERA_AUTOROTATE;
import android.Manifest;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.provider.Settings;
import android.service.rotationresolver.RotationResolverService;
import android.text.TextUtils;
import androidx.preference.Preference;
@@ -43,13 +49,17 @@ public class SmartAutoRotateController extends TogglePreferenceController implem
@Override
public int getAvailabilityStatus() {
return !RotationPolicy.isRotationLocked(mContext)
if (!isRotationResolverServiceAvailable(mContext)) {
return UNSUPPORTED_ON_DEVICE;
}
return !RotationPolicy.isRotationLocked(mContext) && hasSufficientPermission(mContext)
? AVAILABLE : DISABLED_DEPENDENT_SETTING;
}
@Override
public boolean isChecked() {
return Settings.Secure.getInt(mContext.getContentResolver(),
return hasSufficientPermission(mContext) && Settings.Secure.getInt(
mContext.getContentResolver(),
CAMERA_AUTOROTATE, 0) == 1;
}
@@ -62,4 +72,24 @@ public class SmartAutoRotateController extends TogglePreferenceController implem
isChecked ? 1 : 0);
return true;
}
static boolean isRotationResolverServiceAvailable(Context context) {
final PackageManager packageManager = context.getPackageManager();
final String resolvePackage = packageManager.getRotationResolverPackageName();
if (TextUtils.isEmpty(resolvePackage)) {
return false;
}
final Intent intent = new Intent(RotationResolverService.SERVICE_INTERFACE).setPackage(
resolvePackage);
final ResolveInfo resolveInfo = packageManager.resolveService(intent,
PackageManager.MATCH_SYSTEM_ONLY);
return resolveInfo != null && resolveInfo.serviceInfo != null;
}
static boolean hasSufficientPermission(Context context) {
final PackageManager packageManager = context.getPackageManager();
final String rotationPackage = packageManager.getRotationResolverPackageName();
return rotationPackage != null && packageManager.checkPermission(
Manifest.permission.CAMERA, rotationPackage) == PackageManager.PERMISSION_GRANTED;
}
}

View File

@@ -0,0 +1,63 @@
/*
* 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.display;
import static com.android.settings.display.SmartAutoRotateController.hasSufficientPermission;
import static com.android.settings.display.SmartAutoRotateController.isRotationResolverServiceAvailable;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.text.TextUtils;
import androidx.preference.Preference;
import com.android.settings.core.BasePreferenceController;
/**
* The controller of camera based rotate permission warning preference. The preference appears when
* the camera permission is missing for the camera based rotation feature.
*/
public class SmartAutoRotatePermissionController extends BasePreferenceController {
private final Intent mIntent;
public SmartAutoRotatePermissionController(Context context, String key) {
super(context, key);
final String packageName = context.getPackageManager().getRotationResolverPackageName();
mIntent = new Intent(
android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
mIntent.setData(Uri.parse("package:" + packageName));
}
@Override
@AvailabilityStatus
public int getAvailabilityStatus() {
return isRotationResolverServiceAvailable(mContext) && !hasSufficientPermission(mContext)
? AVAILABLE_UNSEARCHABLE
: UNSUPPORTED_ON_DEVICE;
}
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
if (TextUtils.equals(getPreferenceKey(), preference.getKey())) {
mContext.startActivity(mIntent);
return true;
}
return super.handlePreferenceTreeClick(preference);
}
}

View File

@@ -15,8 +15,10 @@
*/
package com.android.settings.display;
import static com.android.settings.display.SmartAutoRotateController.hasSufficientPermission;
import static com.android.settings.display.SmartAutoRotateController.isRotationResolverServiceAvailable;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.os.Bundle;
import android.text.Html;
import android.view.LayoutInflater;
@@ -31,16 +33,12 @@ import com.android.settings.SettingsActivity;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.widget.SettingsMainSwitchBar;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.search.Indexable;
import com.android.settingslib.widget.FooterPreference;
import com.android.settingslib.search.SearchIndexable;
import java.util.ArrayList;
import java.util.List;
import com.android.settingslib.widget.FooterPreference;
/**
* Preference fragment used to auto rotation
* Preference fragment used for auto rotation
*/
@SuppressWarnings("WeakerAccess")
@SearchIndexable
@@ -51,7 +49,6 @@ public class SmartAutoRotatePreferenceFragment extends DashboardFragment {
private RotationPolicy.RotationPolicyListener mRotationPolicyListener;
private AutoRotateSwitchBarController mSwitchBarController;
private static final String FACE_SWITCH_PREFERENCE_ID = "face_based_rotate";
private static final String SMART_AUTO_ROTATE_CONTROLLER_KEY = "auto_rotate";
@Override
protected int getPreferenceScreenResId() {
@@ -69,6 +66,12 @@ public class SmartAutoRotatePreferenceFragment extends DashboardFragment {
switchBar.show();
mSwitchBarController = new AutoRotateSwitchBarController(activity, switchBar,
getSettingsLifecycle());
final Preference footerPreference = findPreference(FooterPreference.KEY_FOOTER);
if (footerPreference != null) {
footerPreference.setTitle(Html.fromHtml(getString(R.string.smart_rotate_text_headline),
Html.FROM_HTML_MODE_COMPACT));
footerPreference.setVisible(isRotationResolverServiceAvailable(activity));
}
return view;
}
@@ -82,7 +85,7 @@ public class SmartAutoRotatePreferenceFragment extends DashboardFragment {
mSwitchBarController.onChange();
final boolean isLocked = RotationPolicy.isRotationLocked(getContext());
final Preference preference = findPreference(FACE_SWITCH_PREFERENCE_ID);
if (preference != null) {
if (preference != null && hasSufficientPermission(getContext())) {
preference.setEnabled(!isLocked);
}
}
@@ -90,17 +93,11 @@ public class SmartAutoRotatePreferenceFragment extends DashboardFragment {
}
RotationPolicy.registerRotationPolicyListener(getPrefContext(),
mRotationPolicyListener);
findPreference(FooterPreference.KEY_FOOTER).setTitle(
Html.fromHtml(getString(R.string.smart_rotate_text_headline),
Html.FROM_HTML_MODE_COMPACT));
}
@Override
public void onPause() {
super.onPause();
if (mRotationPolicyListener != null) {
RotationPolicy.unregisterRotationPolicyListener(getPrefContext(),
mRotationPolicyListener);
@@ -112,36 +109,11 @@ public class SmartAutoRotatePreferenceFragment extends DashboardFragment {
return SettingsEnums.DISPLAY_AUTO_ROTATE_SETTINGS;
}
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
return buildPreferenceControllers(context);
}
private static List<AbstractPreferenceController> buildPreferenceControllers(
Context context) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(
new SmartAutoRotatePreferenceController(context, SMART_AUTO_ROTATE_CONTROLLER_KEY));
return controllers;
}
@Override
protected String getLogTag() {
return TAG;
}
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.auto_rotate_settings) {
@Override
public List<AbstractPreferenceController> createPreferenceControllers(
Context context) {
return buildPreferenceControllers(context);
}
@Override
protected boolean isPageSearchEnabled(Context context) {
return false;
}
};
new BaseSearchIndexProvider(R.xml.auto_rotate_settings);
}

View File

@@ -84,11 +84,6 @@ public interface EnterprisePrivacyFeatureProvider {
*/
boolean isAlwaysOnVpnSetInManagedProfile();
/**
* Returns whether the Device Owner set a recommended global HTTP proxy.
*/
boolean isGlobalHttpProxySet();
/**
* Returns the number of failed login attempts that the Device Owner or Profile Owner allows
* before the current user is wiped, or zero if no such limit is set.

View File

@@ -25,6 +25,7 @@ import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.VpnManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
@@ -48,18 +49,20 @@ public class EnterprisePrivacyFeatureProviderImpl implements EnterprisePrivacyFe
private final PackageManager mPm;
private final UserManager mUm;
private final ConnectivityManager mCm;
private final VpnManager mVm;
private final Resources mResources;
private static final int MY_USER_ID = UserHandle.myUserId();
public EnterprisePrivacyFeatureProviderImpl(Context context, DevicePolicyManager dpm,
PackageManager pm, UserManager um, ConnectivityManager cm,
PackageManager pm, UserManager um, ConnectivityManager cm, VpnManager vm,
Resources resources) {
mContext = context.getApplicationContext();
mDpm = dpm;
mPm = pm;
mUm = um;
mCm = cm;
mVm = vm;
mResources = resources;
}
@@ -133,19 +136,14 @@ public class EnterprisePrivacyFeatureProviderImpl implements EnterprisePrivacyFe
@Override
public boolean isAlwaysOnVpnSetInCurrentUser() {
return VpnUtils.isAlwaysOnVpnSet(mCm, MY_USER_ID);
return VpnUtils.isAlwaysOnVpnSet(mVm, MY_USER_ID);
}
@Override
public boolean isAlwaysOnVpnSetInManagedProfile() {
final int managedProfileUserId = getManagedProfileUserId();
return managedProfileUserId != UserHandle.USER_NULL &&
VpnUtils.isAlwaysOnVpnSet(mCm, managedProfileUserId);
}
@Override
public boolean isGlobalHttpProxySet() {
return mCm.getGlobalProxy() != null;
VpnUtils.isAlwaysOnVpnSet(mVm, managedProfileUserId);
}
@Override

View File

@@ -14,26 +14,25 @@
package com.android.settings.enterprise;
import android.content.Context;
import android.net.ConnectivityManager;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.AbstractPreferenceController;
public class GlobalHttpProxyPreferenceController extends AbstractPreferenceController implements
PreferenceControllerMixin {
private static final String KEY_GLOBAL_HTTP_PROXY = "global_http_proxy";
private final EnterprisePrivacyFeatureProvider mFeatureProvider;
private final ConnectivityManager mCm;
public GlobalHttpProxyPreferenceController(Context context) {
super(context);
mFeatureProvider = FeatureFactory.getFactory(context)
.getEnterprisePrivacyFeatureProvider(context);
mCm = context.getSystemService(ConnectivityManager.class);
}
@Override
public boolean isAvailable() {
return mFeatureProvider.isGlobalHttpProxySet();
return mCm.getGlobalProxy() != null;
}
@Override

View File

@@ -1,3 +1,4 @@
# Default reviewers for this and subdirectories.
millchen@google.com
tmfang@google.com
tifn@google.com
wesleycwwang@google.com
ykhung@google.com

View File

@@ -82,7 +82,7 @@ public class LocationSettings extends DashboardFragment {
super.onAttach(context);
use(AppLocationPermissionPreferenceController.class).init(this);
use(RecentLocationRequestPreferenceController.class).init(this);
use(RecentLocationAccessPreferenceController.class).init(this);
use(LocationServicePreferenceController.class).init(this);
use(LocationFooterPreferenceController.class).init(this);
use(LocationForWorkPreferenceController.class).init(this);

View File

@@ -21,7 +21,6 @@ import android.content.Context;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
/**
* Location Setting page for managed profile.
@@ -54,11 +53,9 @@ public class LocationWorkProfileSettings extends DashboardFragment {
use(LocationFooterPreferenceController.class).init(this);
use(LocationForWorkPreferenceController.class).init(this);
final int profileType = getArguments().getInt(ProfileSelectFragment.EXTRA_PROFILE);
final RecentLocationRequestPreferenceController controller = use(
RecentLocationRequestPreferenceController.class);
final RecentLocationAccessPreferenceController controller =
use(RecentLocationAccessPreferenceController.class);
controller.init(this);
controller.setProfileType(profileType);
}
@Override

View File

@@ -13,114 +13,141 @@
*/
package com.android.settings.location;
import static java.util.concurrent.TimeUnit.DAYS;
import static android.Manifest.permission_group.LOCATION;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.icu.text.RelativeDateTimeFormatter;
import android.provider.DeviceConfig;
import android.view.View;
import android.os.UserHandle;
import android.os.UserManager;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
import com.android.settingslib.location.RecentLocationAccesses;
import com.android.settingslib.utils.StringUtil;
import com.android.settingslib.widget.AppEntitiesHeaderController;
import com.android.settingslib.widget.AppEntityInfo;
import com.android.settingslib.widget.LayoutPreference;
import com.android.settingslib.widget.AppPreference;
import java.util.ArrayList;
import java.util.List;
public class RecentLocationAccessPreferenceController extends AbstractPreferenceController
implements PreferenceControllerMixin {
/** Key for the recent location apps dashboard */
private static final String KEY_APPS_DASHBOARD = "apps_dashboard";
private final RecentLocationAccesses mRecentLocationAccesses;
private AppEntitiesHeaderController mController;
private static final int MAXIMUM_APP_COUNT = 3;
/**
* Preference controller that handles the display of apps that access locations.
*/
public class RecentLocationAccessPreferenceController extends LocationBasePreferenceController {
@VisibleForTesting
RecentLocationAccesses mRecentLocationApps;
private PreferenceCategory mCategoryRecentLocationRequests;
private int mType = ProfileSelectFragment.ProfileType.ALL;
public RecentLocationAccessPreferenceController(Context context) {
this(context, new RecentLocationAccesses(context));
private static class PackageEntryClickedListener implements
Preference.OnPreferenceClickListener {
private final Context mContext;
private final String mPackage;
private final UserHandle mUserHandle;
PackageEntryClickedListener(Context context, String packageName,
UserHandle userHandle) {
mContext = context;
mPackage = packageName;
mUserHandle = userHandle;
}
@Override
public boolean onPreferenceClick(Preference preference) {
final Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSION);
intent.putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, LOCATION);
intent.putExtra(Intent.EXTRA_PACKAGE_NAME, mPackage);
intent.putExtra(Intent.EXTRA_USER, mUserHandle);
mContext.startActivity(intent);
return true;
}
}
public RecentLocationAccessPreferenceController(Context context, String key) {
this(context, key, new RecentLocationAccesses(context));
}
@VisibleForTesting
RecentLocationAccessPreferenceController(Context context,
RecentLocationAccesses recentAccesses) {
super(context);
mRecentLocationAccesses = recentAccesses;
}
@Override
public String getPreferenceKey() {
return KEY_APPS_DASHBOARD;
}
@Override
public boolean isAvailable() {
return Boolean.parseBoolean(
DeviceConfig.getProperty(DeviceConfig.NAMESPACE_PRIVACY,
Utils.PROPERTY_PERMISSIONS_HUB_ENABLED));
public RecentLocationAccessPreferenceController(Context context, String key,
RecentLocationAccesses recentLocationApps) {
super(context, key);
mRecentLocationApps = recentLocationApps;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
final LayoutPreference preference = screen.findPreference(KEY_APPS_DASHBOARD);
final View view = preference.findViewById(R.id.app_entities_header);
mController = AppEntitiesHeaderController.newInstance(mContext, view)
.setHeaderTitleRes(R.string.location_category_recent_location_access)
.setHeaderDetailsRes(R.string.location_recent_location_access_view_details)
.setHeaderEmptyRes(R.string.location_no_recent_accesses)
.setHeaderDetailsClickListener((View v) -> {
final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSION_USAGE);
intent.putExtra(Intent.EXTRA_PERMISSION_NAME,
Manifest.permission.ACCESS_FINE_LOCATION);
intent.putExtra(Intent.EXTRA_DURATION_MILLIS, DAYS.toMillis(1));
mContext.startActivity(intent);
});
mCategoryRecentLocationRequests = screen.findPreference(getPreferenceKey());
final Context prefContext = mCategoryRecentLocationRequests.getContext();
final List<RecentLocationAccesses.Access> recentLocationAccesses = new ArrayList<>();
final UserManager userManager = UserManager.get(mContext);
for (RecentLocationAccesses.Access access : mRecentLocationApps.getAppListSorted()) {
if (isRequestMatchesProfileType(userManager, access, mType)) {
recentLocationAccesses.add(access);
}
}
if (recentLocationAccesses.size() > 0) {
// Add preferences to container in original order (already sorted by recency).
for (RecentLocationAccesses.Access access : recentLocationAccesses) {
mCategoryRecentLocationRequests.addPreference(
createAppPreference(prefContext, access, mFragment));
}
} else {
// If there's no item to display, add a "No recent apps" item.
final Preference banner = new AppPreference(prefContext);
banner.setTitle(R.string.location_no_recent_accesses);
banner.setSelectable(false);
mCategoryRecentLocationRequests.addPreference(banner);
}
}
@Override
public void updateState(Preference preference) {
updateRecentApps();
public void onLocationModeChanged(int mode, boolean restricted) {
mCategoryRecentLocationRequests.setEnabled(mLocationEnabler.isEnabled(mode));
}
private void updateRecentApps() {
final List<RecentLocationAccesses.Access> recentLocationAccesses =
mRecentLocationAccesses.getAppListSorted();
if (recentLocationAccesses.size() > 0) {
// Display the top 3 preferences to container in original order.
int i = 0;
for (; i < Math.min(recentLocationAccesses.size(), MAXIMUM_APP_COUNT); i++) {
final RecentLocationAccesses.Access access = recentLocationAccesses.get(i);
final AppEntityInfo appEntityInfo = new AppEntityInfo.Builder()
.setIcon(access.icon)
.setTitle(access.label)
.setSummary(StringUtil.formatRelativeTime(mContext,
System.currentTimeMillis() - access.accessFinishTime, false,
RelativeDateTimeFormatter.Style.SHORT))
.setOnClickListener((v) -> {
final Intent intent = new Intent(Intent.ACTION_MANAGE_APP_PERMISSION);
intent.putExtra(Intent.EXTRA_PERMISSION_NAME,
Manifest.permission.ACCESS_FINE_LOCATION);
intent.putExtra(Intent.EXTRA_PACKAGE_NAME, access.packageName);
intent.putExtra(Intent.EXTRA_USER, access.userHandle);
mContext.startActivity(intent);
})
.build();
mController.setAppEntity(i, appEntityInfo);
}
for (; i < MAXIMUM_APP_COUNT; i++) {
mController.removeAppEntity(i);
}
/**
* Initialize {@link ProfileSelectFragment.ProfileType} of the controller
*
* @param type {@link ProfileSelectFragment.ProfileType} of the controller.
*/
public void setProfileType(@ProfileSelectFragment.ProfileType int type) {
mType = type;
}
/**
* Create a {@link AppPreference}
*/
public static AppPreference createAppPreference(Context prefContext,
RecentLocationAccesses.Access access, DashboardFragment fragment) {
final AppPreference pref = new AppPreference(prefContext);
pref.setIcon(access.icon);
pref.setTitle(access.label);
pref.setOnPreferenceClickListener(new PackageEntryClickedListener(
fragment.getContext(), access.packageName, access.userHandle));
return pref;
}
/**
* Return if the {@link RecentLocationAccesses.Access} matches current UI
* {@ProfileSelectFragment.ProfileType}
*/
public static boolean isRequestMatchesProfileType(UserManager userManager,
RecentLocationAccesses.Access access, @ProfileSelectFragment.ProfileType int type) {
final boolean isWorkProfile = userManager.isManagedProfile(
access.userHandle.getIdentifier());
if (isWorkProfile && (type & ProfileSelectFragment.ProfileType.WORK) != 0) {
return true;
}
mController.apply();
if (!isWorkProfile && (type & ProfileSelectFragment.ProfileType.PERSONAL) != 0) {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,102 @@
/*
* Copyright (C) 2020 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.network.telephony;
import android.content.Context;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.util.Log;
/**
* Preference controller for "Enable 2G"
*/
public class Enable2gPreferenceController extends TelephonyTogglePreferenceController {
private static final String LOG_TAG = "Enable2gPreferenceController";
private static final long BITMASK_2G = TelephonyManager.NETWORK_TYPE_BITMASK_GSM
| TelephonyManager.NETWORK_TYPE_BITMASK_GPRS
| TelephonyManager.NETWORK_TYPE_BITMASK_EDGE
| TelephonyManager.NETWORK_TYPE_BITMASK_CDMA;
private CarrierConfigManager mCarrierConfigManager;
private TelephonyManager mTelephonyManager;
/**
* Class constructor of "Enable 2G" toggle.
*
* @param context of settings
* @param key assigned within UI entry of XML file
*/
public Enable2gPreferenceController(Context context, String key) {
super(context, key);
mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
}
/**
* Initialization based on a given subscription id.
*
* @param subId is the subscription id
* @return this instance after initialization
*/
public Enable2gPreferenceController init(int subId) {
mSubId = subId;
mTelephonyManager = mContext.getSystemService(TelephonyManager.class)
.createForSubscriptionId(mSubId);
return this;
}
@Override
public int getAvailabilityStatus(int subId) {
final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId);
boolean visible =
subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID
&& carrierConfig != null
&& !carrierConfig.getBoolean(CarrierConfigManager.KEY_HIDE_ENABLE_2G)
&& mTelephonyManager.isRadioInterfaceCapabilitySupported(
mTelephonyManager.CAPABILITY_ALLOWED_NETWORK_TYPES_USED);
return visible ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
@Override
public boolean isChecked() {
long currentlyAllowedNetworkTypes = mTelephonyManager.getAllowedNetworkTypesForReason(
mTelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G);
return (currentlyAllowedNetworkTypes & BITMASK_2G) != 0;
}
@Override
public boolean setChecked(boolean isChecked) {
long currentlyAllowedNetworkTypes = mTelephonyManager.getAllowedNetworkTypesForReason(
mTelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G);
boolean enabled = (currentlyAllowedNetworkTypes & BITMASK_2G) != 0;
if (enabled == isChecked) {
return false;
}
long newAllowedNetworkTypes = currentlyAllowedNetworkTypes;
if (isChecked) {
newAllowedNetworkTypes = currentlyAllowedNetworkTypes | BITMASK_2G;
Log.i(LOG_TAG, "Enabling 2g. Allowed network types: " + newAllowedNetworkTypes);
} else {
newAllowedNetworkTypes = currentlyAllowedNetworkTypes & ~BITMASK_2G;
Log.i(LOG_TAG, "Disabling 2g. Allowed network types: " + newAllowedNetworkTypes);
}
mTelephonyManager.setAllowedNetworkTypesForReason(
mTelephonyManager.ALLOWED_NETWORK_TYPES_REASON_ENABLE_2G, newAllowedNetworkTypes);
return true;
}
}

View File

@@ -158,6 +158,7 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings {
use(PreferredNetworkModePreferenceController.class).init(mSubId);
use(EnabledNetworkModePreferenceController.class).init(getLifecycle(), mSubId);
use(DataServiceSetupPreferenceController.class).init(mSubId);
use(Enable2gPreferenceController.class).init(mSubId);
final WifiCallingPreferenceController wifiCallingPreferenceController =
use(WifiCallingPreferenceController.class).init(mSubId);

View File

@@ -1,127 +0,0 @@
/*
* Copyright (C) 2020 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.notification;
import static android.provider.Settings.Global.NOTIFICATION_FEEDBACK_ENABLED;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.provider.DeviceConfig;
import android.provider.Settings;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.core.TogglePreferenceController;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume;
import com.google.common.annotations.VisibleForTesting;
public class AssistantFeedbackPreferenceController extends TogglePreferenceController
implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener,
LifecycleObserver, OnResume, OnPause {
@VisibleForTesting
static final int ON = 1;
@VisibleForTesting
static final int OFF = 0;
private SettingObserver mSettingObserver;
public AssistantFeedbackPreferenceController(Context context,
String preferenceKey) {
super(context, preferenceKey);
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
Preference preference = screen.findPreference(NOTIFICATION_FEEDBACK_ENABLED);
if (preference != null) {
mSettingObserver = new SettingObserver(preference);
}
}
@Override
public void onResume() {
if (mSettingObserver != null) {
mSettingObserver.register(mContext.getContentResolver(), true /* register */);
}
}
@Override
public void onPause() {
if (mSettingObserver != null) {
mSettingObserver.register(mContext.getContentResolver(), false /* register */);
}
}
@Override
public int getAvailabilityStatus() {
return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.ENABLE_NAS_FEEDBACK, false)
? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
@Override
public boolean isChecked() {
return Settings.Global.getInt(mContext.getContentResolver(),
NOTIFICATION_FEEDBACK_ENABLED, ON) == ON;
}
@Override
public boolean setChecked(boolean isChecked) {
return Settings.Global.putInt(mContext.getContentResolver(),
NOTIFICATION_FEEDBACK_ENABLED, isChecked ? ON : OFF);
}
class SettingObserver extends ContentObserver {
private final Uri NOTIFICATION_URI =
Settings.Global.getUriFor(NOTIFICATION_FEEDBACK_ENABLED);
private final Preference mPreference;
SettingObserver(Preference preference) {
super(new Handler());
mPreference = preference;
}
public void register(ContentResolver cr, boolean register) {
if (register) {
cr.registerContentObserver(NOTIFICATION_URI, false, this);
} else {
cr.unregisterContentObserver(this);
}
}
@Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
if (NOTIFICATION_URI.equals(uri)) {
updateState(mPreference);
}
}
}
}

View File

@@ -20,6 +20,7 @@ import android.app.AppGlobals;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.VpnManager;
import android.os.UserManager;
import androidx.annotation.Keep;
@@ -172,7 +173,8 @@ public class FeatureFactoryImpl extends FeatureFactory {
Context.DEVICE_POLICY_SERVICE),
appContext.getPackageManager(),
UserManager.get(appContext),
(ConnectivityManager) appContext.getSystemService(Context.CONNECTIVITY_SERVICE),
appContext.getSystemService(ConnectivityManager.class),
appContext.getSystemService(VpnManager.class),
appContext.getResources());
}
return mEnterprisePrivacyFeatureProvider;

View File

@@ -88,6 +88,11 @@ public class SimActivationNotifier {
SIM_SETUP_CHANNEL_ID,
mContext.getString(R.string.sim_setup_channel_id),
NotificationManager.IMPORTANCE_HIGH));
mNotificationManager.createNotificationChannel(
new NotificationChannel(
SWITCH_SLOT_CHANNEL_ID,
mContext.getString(R.string.sim_switch_channel_id),
NotificationManager.IMPORTANCE_HIGH));
}
/**

View File

@@ -20,7 +20,6 @@ import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.content.DialogInterface;
import android.content.pm.PackageInfo;
import android.net.ConnectivityManager;
import android.net.VpnManager;
import android.os.Bundle;
import android.os.UserHandle;
@@ -48,7 +47,6 @@ public class AppDialogFragment extends InstrumentedDialogFragment implements App
private PackageInfo mPackageInfo;
private Listener mListener;
private ConnectivityManager mConnectivityManager;
private UserManager mUserManager;
private VpnManager mVpnManager;
@@ -93,7 +91,6 @@ public class AppDialogFragment extends InstrumentedDialogFragment implements App
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mConnectivityManager = getContext().getSystemService(ConnectivityManager.class);
mUserManager = UserManager.get(getContext());
mVpnManager = getContext().getSystemService(VpnManager.class);
}
@@ -158,8 +155,8 @@ public class AppDialogFragment extends InstrumentedDialogFragment implements App
}
final int userId = getUserId();
if (mPackageInfo.packageName.equals(VpnUtils.getConnectedPackage(mVpnManager, userId))) {
mConnectivityManager.setAlwaysOnVpnPackageForUser(userId, null,
/* lockdownEnabled */ false, /* lockdownAllowlist */ null);
mVpnManager.setAlwaysOnVpnPackageForUser(userId, null, /* lockdownEnabled */ false,
/* lockdownAllowlist */ null);
mVpnManager.prepareVpn(mPackageInfo.packageName, VpnConfig.LEGACY_VPN, userId);
}
}

View File

@@ -28,7 +28,6 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.ConnectivityManager;
import android.net.VpnManager;
import android.os.Bundle;
import android.os.UserHandle;
@@ -69,7 +68,6 @@ public class AppManagementFragment extends SettingsPreferenceFragment
private PackageManager mPackageManager;
private DevicePolicyManager mDevicePolicyManager;
private ConnectivityManager mConnectivityManager;
private VpnManager mVpnManager;
// VPN app info
@@ -122,7 +120,6 @@ public class AppManagementFragment extends SettingsPreferenceFragment
mPackageManager = getContext().getPackageManager();
mDevicePolicyManager = getContext().getSystemService(DevicePolicyManager.class);
mConnectivityManager = getContext().getSystemService(ConnectivityManager.class);
mVpnManager = getContext().getSystemService(VpnManager.class);
mPreferenceVersion = findPreference(KEY_VERSION);
@@ -227,7 +224,7 @@ public class AppManagementFragment extends SettingsPreferenceFragment
}
private boolean setAlwaysOnVpn(boolean isEnabled, boolean isLockdown) {
return mConnectivityManager.setAlwaysOnVpnPackageForUser(mUserId,
return mVpnManager.setAlwaysOnVpnPackageForUser(mUserId,
isEnabled ? mPackageName : null, isLockdown, /* lockdownAllowlist */ null);
}
@@ -261,7 +258,7 @@ public class AppManagementFragment extends SettingsPreferenceFragment
mPreferenceLockdown.setDisabledByAdmin(admin);
}
}
if (mConnectivityManager.isAlwaysOnVpnPackageSupportedForUser(mUserId, mPackageName)) {
if (mVpnManager.isAlwaysOnVpnPackageSupportedForUser(mUserId, mPackageName)) {
// setSummary doesn't override the admin message when user restriction is applied
mPreferenceAlwaysOn.setSummary(R.string.vpn_always_on_summary);
// setEnabled is not required here, as checkRestrictionAndSetDisabled
@@ -275,7 +272,7 @@ public class AppManagementFragment extends SettingsPreferenceFragment
}
private String getAlwaysOnVpnPackage() {
return mConnectivityManager.getAlwaysOnVpnPackageForUser(mUserId);
return mVpnManager.getAlwaysOnVpnPackageForUser(mUserId);
}
private boolean isVpnAlwaysOn() {

View File

@@ -20,7 +20,6 @@ import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.DialogInterface;
import android.net.ConnectivityManager;
import android.net.VpnManager;
import android.os.Bundle;
import android.os.RemoteException;
@@ -177,8 +176,7 @@ public class ConfigDialogFragment extends InstrumentedDialogFragment implements
return;
}
final ConnectivityManager conn = ConnectivityManager.from(mContext);
conn.setAlwaysOnVpnPackageForUser(UserHandle.myUserId(), null,
mService.setAlwaysOnVpnPackageForUser(UserHandle.myUserId(), null,
/* lockdownEnabled */ false, /* lockdownAllowlist */ null);
VpnUtils.setLockdownVpn(mContext, profile.key);
} else {

View File

@@ -490,7 +490,7 @@ public class VpnSettings extends RestrictedSettingsFragment implements
Set<AppVpnInfo> result = new ArraySet<>();
for (UserHandle profile : mUserManager.getUserProfiles()) {
final int profileId = profile.getIdentifier();
final String packageName = mConnectivityManager.getAlwaysOnVpnPackageForUser(profileId);
final String packageName = mVpnManager.getAlwaysOnVpnPackageForUser(profileId);
if (packageName != null) {
result.add(new AppVpnInfo(profileId, packageName));
}

View File

@@ -16,7 +16,6 @@
package com.android.settings.vpn2;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.VpnManager;
import android.os.RemoteException;
import android.provider.Settings;
@@ -43,15 +42,15 @@ public class VpnUtils {
public static void clearLockdownVpn(Context context) {
KeyStore.getInstance().delete(Credentials.LOCKDOWN_VPN);
// Always notify ConnectivityManager after keystore update
getConnectivityManager(context).updateLockdownVpn();
// Always notify VpnManager after keystore update
getVpnManager(context).updateLockdownVpn();
}
public static void setLockdownVpn(Context context, String lockdownKey) {
KeyStore.getInstance().put(Credentials.LOCKDOWN_VPN, lockdownKey.getBytes(),
KeyStore.UID_SELF, /* flags */ 0);
// Always notify ConnectivityManager after keystore update
getConnectivityManager(context).updateLockdownVpn();
// Always notify VpnManager after keystore update
getVpnManager(context).updateLockdownVpn();
}
public static boolean isVpnLockdown(String key) {
@@ -63,7 +62,7 @@ public class VpnUtils {
if (getLockdownVpn() != null) {
return true;
}
return getConnectivityManager(context).getAlwaysOnVpnPackageForUser(userId) != null
return getVpnManager(context).getAlwaysOnVpnPackageForUser(userId) != null
&& Settings.Secure.getIntForUser(context.getContentResolver(),
Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN, /* default */ 0, userId) != 0;
}
@@ -77,16 +76,12 @@ public class VpnUtils {
return config != null ? config.user : null;
}
private static ConnectivityManager getConnectivityManager(Context context) {
return context.getSystemService(ConnectivityManager.class);
}
private static VpnManager getVpnManager(Context context) {
return context.getSystemService(VpnManager.class);
}
public static boolean isAlwaysOnVpnSet(ConnectivityManager cm, final int userId) {
return cm.getAlwaysOnVpnPackageForUser(userId) != null;
public static boolean isAlwaysOnVpnSet(VpnManager vm, final int userId) {
return vm.getAlwaysOnVpnPackageForUser(userId) != null;
}
public static boolean disconnectLegacyVpn(Context context) {

View File

@@ -74,6 +74,7 @@ public final class WifiSummaryUpdater extends SummaryUpdater {
@Override
public void register(boolean register) {
if (register) {
mWifiTracker.fetchInitialState();
notifyChangeIfNeeded();
mContext.registerReceiver(mReceiver, INTENT_FILTER);
} else {

View File

@@ -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.display;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING;
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
import android.Manifest;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.os.UserHandle;
import android.provider.Settings;
import androidx.preference.Preference;
import com.android.settings.testutils.ResolveInfoBuilder;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class SmartAutoRotateControllerTest {
private static final String PACKAGE_NAME = "package_name";
private SmartAutoRotateController mController;
@Mock
private PackageManager mPackageManager;
@Mock
private Preference mPreference;
private ContentResolver mContentResolver;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
final Context context = Mockito.spy(RuntimeEnvironment.application);
mContentResolver = RuntimeEnvironment.application.getContentResolver();
when(context.getPackageManager()).thenReturn(mPackageManager);
when(context.getContentResolver()).thenReturn(mContentResolver);
doReturn(PACKAGE_NAME).when(mPackageManager).getRotationResolverPackageName();
doReturn(PackageManager.PERMISSION_GRANTED).when(mPackageManager).checkPermission(
Manifest.permission.CAMERA, PACKAGE_NAME);
mController = new SmartAutoRotateController(context, "test_key");
doReturn(mController.getPreferenceKey()).when(mPreference).getKey();
final ResolveInfo resolveInfo = new ResolveInfoBuilder(PACKAGE_NAME).build();
resolveInfo.serviceInfo = new ServiceInfo();
when(mPackageManager.resolveService(any(), anyInt())).thenReturn(resolveInfo);
enableAutoRotation();
}
@Test
public void getAvailabilityStatus_returnAvailable() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
@Test
public void getAvailabilityStatus_resolveInfoIsNull_returnUnsupportedOnDevice() {
when(mPackageManager.resolveService(any(), anyInt())).thenReturn(null);
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
}
@Test
public void getAvailabilityStatus_noCameraPermission_returnDisableDependentSetting() {
doReturn(PackageManager.PERMISSION_DENIED).when(mPackageManager).checkPermission(
Manifest.permission.CAMERA, PACKAGE_NAME);
assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING);
}
@Test
public void getAvailabilityStatus_rotationLocked_returnDisableDependentSetting() {
disableAutoRotation();
assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING);
}
private void enableAutoRotation() {
Settings.System.putIntForUser(mContentResolver,
Settings.System.ACCELEROMETER_ROTATION, 1, UserHandle.USER_CURRENT);
}
private void disableAutoRotation() {
Settings.System.putIntForUser(mContentResolver,
Settings.System.ACCELEROMETER_ROTATION, 0, UserHandle.USER_CURRENT);
}
}

View File

@@ -39,7 +39,7 @@ import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.ProxyInfo;
import android.net.VpnManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
@@ -91,6 +91,8 @@ public class EnterprisePrivacyFeatureProviderImplTest {
private UserManager mUserManager;
@Mock
private ConnectivityManager mConnectivityManger;
@Mock
private VpnManager mVpnManager;
private Resources mResources;
private EnterprisePrivacyFeatureProvider mProvider;
@@ -106,7 +108,7 @@ public class EnterprisePrivacyFeatureProviderImplTest {
mResources = RuntimeEnvironment.application.getResources();
mProvider = new EnterprisePrivacyFeatureProviderImpl(mContext, mDevicePolicyManager,
mPackageManager, mUserManager, mConnectivityManger, mResources);
mPackageManager, mUserManager, mConnectivityManger, mVpnManager, mResources);
}
@Test
@@ -208,11 +210,10 @@ public class EnterprisePrivacyFeatureProviderImplTest {
@Test
public void testIsAlwaysOnVpnSetInCurrentUser() {
when(mConnectivityManger.getAlwaysOnVpnPackageForUser(mUserId)).thenReturn(null);
when(mVpnManager.getAlwaysOnVpnPackageForUser(mUserId)).thenReturn(null);
assertThat(mProvider.isAlwaysOnVpnSetInCurrentUser()).isFalse();
when(mConnectivityManger.getAlwaysOnVpnPackageForUser(mUserId))
.thenReturn(VPN_PACKAGE_ID);
when(mVpnManager.getAlwaysOnVpnPackageForUser(mUserId)).thenReturn(VPN_PACKAGE_ID);
assertThat(mProvider.isAlwaysOnVpnSetInCurrentUser()).isTrue();
}
@@ -222,25 +223,14 @@ public class EnterprisePrivacyFeatureProviderImplTest {
mProfiles.add(new UserInfo(mManagedProfileUserId, "", "", UserInfo.FLAG_MANAGED_PROFILE));
when(mConnectivityManger.getAlwaysOnVpnPackageForUser(mManagedProfileUserId))
.thenReturn(null);
when(mVpnManager.getAlwaysOnVpnPackageForUser(mManagedProfileUserId)).thenReturn(null);
assertThat(mProvider.isAlwaysOnVpnSetInManagedProfile()).isFalse();
when(mConnectivityManger.getAlwaysOnVpnPackageForUser(mManagedProfileUserId))
when(mVpnManager.getAlwaysOnVpnPackageForUser(mManagedProfileUserId))
.thenReturn(VPN_PACKAGE_ID);
assertThat(mProvider.isAlwaysOnVpnSetInManagedProfile()).isTrue();
}
@Test
public void testIsGlobalHttpProxySet() {
when(mConnectivityManger.getGlobalProxy()).thenReturn(null);
assertThat(mProvider.isGlobalHttpProxySet()).isFalse();
when(mConnectivityManger.getGlobalProxy())
.thenReturn(ProxyInfo.buildDirectProxy("localhost", 123));
assertThat(mProvider.isGlobalHttpProxySet()).isTrue();
}
@Test
public void testGetMaximumFailedPasswordsForWipeInCurrentUser() {
when(mDevicePolicyManager.getDeviceOwnerComponentOnCallingUser()).thenReturn(null);

View File

@@ -21,11 +21,11 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.ProxyInfo;
import androidx.preference.Preference;
import com.android.settings.testutils.FakeFeatureFactory;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -41,25 +41,23 @@ public class GlobalHttpProxyPreferenceControllerTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
private FakeFeatureFactory mFeatureFactory;
@Mock
private ConnectivityManager mCm;
private GlobalHttpProxyPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mFeatureFactory = FakeFeatureFactory.setupForTest();
mController = new GlobalHttpProxyPreferenceController(mContext);
}
@Test
public void testIsAvailable() {
when(mFeatureFactory.enterprisePrivacyFeatureProvider.isGlobalHttpProxySet())
.thenReturn(false);
when(mCm.getGlobalProxy()).thenReturn(null);
assertThat(mController.isAvailable()).isFalse();
when(mFeatureFactory.enterprisePrivacyFeatureProvider.isGlobalHttpProxySet())
.thenReturn(true);
when(mCm.getGlobalProxy()).thenReturn(ProxyInfo.buildDirectProxy("localhost", 123));
assertThat(mController.isAvailable()).isTrue();
}

View File

@@ -24,19 +24,17 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.provider.DeviceConfig;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.testutils.shadow.ShadowDeviceConfig;
import com.android.settingslib.location.RecentLocationAccesses;
import com.android.settingslib.widget.LayoutPreference;
import org.junit.After;
import org.junit.Before;
@@ -55,11 +53,14 @@ import java.util.List;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowDeviceConfig.class})
public class RecentLocationAccessPreferenceControllerTest {
private static final String PREFERENCE_KEY = "test_preference_key";
@Mock
private LayoutPreference mLayoutPreference;
private PreferenceCategory mLayoutPreference;
@Mock
private PreferenceScreen mScreen;
@Mock
private DashboardFragment mDashboardFragment;
@Mock
private RecentLocationAccesses mRecentLocationApps;
private Context mContext;
@@ -71,15 +72,16 @@ public class RecentLocationAccessPreferenceControllerTest {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
mController = spy(
new RecentLocationAccessPreferenceController(mContext, mRecentLocationApps));
new RecentLocationAccessPreferenceController(mContext, PREFERENCE_KEY,
mRecentLocationApps));
mController.init(mDashboardFragment);
final String key = mController.getPreferenceKey();
mAppEntitiesHeaderView = LayoutInflater.from(mContext).inflate(
R.layout.app_entities_header, null /* root */);
when(mScreen.findPreference(key)).thenReturn(mLayoutPreference);
when(mLayoutPreference.getKey()).thenReturn(key);
when(mLayoutPreference.getContext()).thenReturn(mContext);
when(mLayoutPreference.findViewById(R.id.app_entities_header)).thenReturn(
mAppEntitiesHeaderView);
when(mDashboardFragment.getContext()).thenReturn(mContext);
}
@After
@@ -88,16 +90,7 @@ public class RecentLocationAccessPreferenceControllerTest {
}
@Test
public void isAvailable_permissionHubNotSet_shouldReturnFalse() {
// We have not yet set the property to show the Permissions Hub.
assertThat(mController.isAvailable()).isEqualTo(false);
}
@Test
public void isAvailable_permissionHubEnabled_shouldReturnTrue() {
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_PRIVACY,
Utils.PROPERTY_PERMISSIONS_HUB_ENABLED, "true", true);
public void isAvailable_shouldReturnTrue() {
assertThat(mController.isAvailable()).isEqualTo(true);
}
@@ -118,39 +111,6 @@ public class RecentLocationAccessPreferenceControllerTest {
assertThat(details.hasOnClickListeners()).isTrue();
}
@Test
public void updateState_whenAppListMoreThanThree_shouldDisplayTopThreeApps() {
final List<RecentLocationAccesses.Access> accesses = createMockAccesses(6);
doReturn(accesses).when(mRecentLocationApps).getAppListSorted();
mController.displayPreference(mScreen);
mController.updateState(mLayoutPreference);
// The widget can display the top 3 apps from the list when there're more than 3.
final View app1View = mAppEntitiesHeaderView.findViewById(R.id.app1_view);
final ImageView appIconView1 = app1View.findViewById(R.id.app_icon);
final TextView appTitle1 = app1View.findViewById(R.id.app_title);
assertThat(app1View.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(appIconView1.getDrawable()).isNotNull();
assertThat(appTitle1.getText()).isEqualTo("appTitle0");
final View app2View = mAppEntitiesHeaderView.findViewById(R.id.app2_view);
final ImageView appIconView2 = app2View.findViewById(R.id.app_icon);
final TextView appTitle2 = app2View.findViewById(R.id.app_title);
assertThat(app2View.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(appIconView2.getDrawable()).isNotNull();
assertThat(appTitle2.getText()).isEqualTo("appTitle1");
final View app3View = mAppEntitiesHeaderView.findViewById(R.id.app3_view);
final ImageView appIconView3 = app3View.findViewById(R.id.app_icon);
final TextView appTitle3 = app3View.findViewById(R.id.app_title);
assertThat(app3View.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(appIconView3.getDrawable()).isNotNull();
assertThat(appTitle3.getText()).isEqualTo("appTitle2");
}
private List<RecentLocationAccesses.Access> createMockAccesses(int count) {
final List<RecentLocationAccesses.Access> accesses = new ArrayList<>();
for (int i = 0; i < count; i++) {

View File

@@ -30,11 +30,9 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
import android.net.NetworkRequest;
import android.os.IBinder;
import android.net.VpnManager;
import android.os.UserHandle;
import android.os.ServiceManager;
import android.provider.SettingsSlicesContract;
import androidx.lifecycle.LifecycleOwner;
@@ -60,9 +58,7 @@ public class VpnPreferenceControllerTest {
@Mock
private ConnectivityManager mConnectivityManager;
@Mock
private IBinder mBinder;
@Mock
private IConnectivityManager mConnectivityManagerService;
private VpnManager mVpnManager;
@Mock
private PreferenceScreen mScreen;
@Mock
@@ -76,9 +72,7 @@ public class VpnPreferenceControllerTest {
MockitoAnnotations.initMocks(this);
when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
.thenReturn(mConnectivityManager);
when(mBinder.queryLocalInterface("android.net.IConnectivityManager"))
.thenReturn(mConnectivityManagerService);
ServiceManager.addService(Context.CONNECTIVITY_SERVICE, mBinder);
when(mContext.getSystemService(VpnManager.class)).thenReturn(mVpnManager);
when(mScreen.findPreference(anyString())).thenReturn(mPreference);
mController = spy(new VpnPreferenceController(mContext));

View File

@@ -1,176 +0,0 @@
/*
* Copyright (C) 2020 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.notification;
import static android.provider.Settings.Global.NOTIFICATION_FEEDBACK_ENABLED;
import static com.android.settings.notification.AssistantFeedbackPreferenceController.OFF;
import static com.android.settings.notification.AssistantFeedbackPreferenceController.ON;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.provider.DeviceConfig;
import android.provider.Settings;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import androidx.preference.TwoStatePreference;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.testutils.shadow.ShadowDeviceConfig;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowDeviceConfig.class})
public class AssistantFeedbackPreferenceControllerTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private PreferenceScreen mScreen;
private AssistantFeedbackPreferenceController mController;
private Preference mPreference;
private static final String KEY = "asst_feedback_indicator";
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mController = new AssistantFeedbackPreferenceController(mContext, KEY);
mPreference = new Preference(RuntimeEnvironment.application);
mPreference.setKey(mController.getPreferenceKey());
when(mScreen.findPreference(mPreference.getKey())).thenReturn(mPreference);
}
@After
public void tearDown() {
ShadowDeviceConfig.reset();
}
@Test
public void testIsVisible_DeviceConfigOn() {
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.ENABLE_NAS_FEEDBACK, "true", true);
mController.displayPreference(mScreen);
assertThat(mPreference.isVisible()).isTrue();
}
@Test
public void testIsVisible_DeviceConfigOff() {
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.ENABLE_NAS_FEEDBACK, "false", true);
mController.displayPreference(mScreen);
assertThat(mPreference.isVisible()).isFalse();
}
@Test
public void getAvailabilityStatus_DeviceConfigOn_returnAvailable() {
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.ENABLE_NAS_FEEDBACK, "true", true);
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.AVAILABLE);
}
@Test
public void getAvailabilityStatus_DeviceConfigOff_returnUnavailable() {
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.ENABLE_NAS_FEEDBACK, "false", true);
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.CONDITIONALLY_UNAVAILABLE);
}
@Test
public void updateState_preferenceSetCheckedWhenSettingIsOn() {
final TwoStatePreference preference = mock(TwoStatePreference.class);
final Context context = RuntimeEnvironment.application;
Settings.Global.putInt(context.getContentResolver(), NOTIFICATION_FEEDBACK_ENABLED, ON);
mController = new AssistantFeedbackPreferenceController(context, KEY);
mController.updateState(preference);
verify(preference).setChecked(true);
}
@Test
public void updateState_preferenceSetUncheckedWhenSettingIsOff() {
final TwoStatePreference preference = mock(TwoStatePreference.class);
final Context context = RuntimeEnvironment.application;
Settings.Global.putInt(context.getContentResolver(), NOTIFICATION_FEEDBACK_ENABLED, OFF);
mController = new AssistantFeedbackPreferenceController(context, KEY);
mController.updateState(preference);
verify(preference).setChecked(false);
}
@Test
public void isChecked_settingIsOff_shouldReturnFalse() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_FEEDBACK_ENABLED, OFF);
assertThat(mController.isChecked()).isFalse();
}
@Test
public void isChecked_settingIsOn_shouldReturnTrue() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_FEEDBACK_ENABLED, ON);
assertThat(mController.isChecked()).isTrue();
}
@Test
public void setChecked_setFalse_disablesSetting() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_FEEDBACK_ENABLED, ON);
mController.setChecked(false);
int updatedValue = Settings.Global.getInt(mContext.getContentResolver(),
NOTIFICATION_FEEDBACK_ENABLED, -1);
assertThat(updatedValue).isEqualTo(OFF);
}
@Test
public void setChecked_setTrue_enablesSetting() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_FEEDBACK_ENABLED, OFF);
mController.setChecked(true);
int updatedValue = Settings.Global.getInt(mContext.getContentResolver(),
NOTIFICATION_FEEDBACK_ENABLED, -1);
assertThat(updatedValue).isEqualTo(ON);
}
}

View File

@@ -64,6 +64,14 @@ public class WifiSummaryUpdaterTest {
verify(mWifiTracker).setListening(true);
}
@Test
public void register_true_shouldFetchInitialStateAndSendSummaryChange() {
mSummaryUpdater.register(true);
verify(mWifiTracker).fetchInitialState();
verify(mListener).onSummaryChanged(anyString());
}
@Test
public void register_false_shouldUnregisterListenerAndTracker() {
mSummaryUpdater.register(true);

View File

@@ -0,0 +1,120 @@
/*
* Copyright (C) 2020 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.network.telephony;
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@RunWith(AndroidJUnit4.class)
public final class Enable2gPreferenceControllerTest {
private static final int SUB_ID = 2;
@Mock
private TelephonyManager mTelephonyManager;
@Mock
private CarrierConfigManager mCarrierConfigManager;
private PersistableBundle mPersistableBundle;
private Enable2gPreferenceController mController;
private Context mContext;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(ApplicationProvider.getApplicationContext());
when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
when(mContext.getSystemService(CarrierConfigManager.class))
.thenReturn(mCarrierConfigManager);
doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
mPersistableBundle = new PersistableBundle();
doReturn(mPersistableBundle).when(mCarrierConfigManager).getConfigForSubId(SUB_ID);
doReturn(mPersistableBundle).when(mCarrierConfigManager).getConfigForSubId(
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
mController = new Enable2gPreferenceController(mContext, "mobile_data");
mController.init(SUB_ID);
}
@Test
public void getAvailabilityStatus_invalidSubId_returnUnavailable() {
mController.init(SubscriptionManager.INVALID_SUBSCRIPTION_ID);
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_hideEnable2g_returnUnavailable() {
mPersistableBundle.putBoolean(CarrierConfigManager.KEY_HIDE_ENABLE_2G,
true);
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_nullCarrierConfig_returnUnavailable() {
doReturn(true).when(mTelephonyManager).isRadioInterfaceCapabilitySupported(
mTelephonyManager.CAPABILITY_ALLOWED_NETWORK_TYPES_USED);
mPersistableBundle.putBoolean(CarrierConfigManager.KEY_HIDE_ENABLE_2G,
false);
doReturn(null).when(mCarrierConfigManager);
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_capabilityNotSupported_returnUnavailable() {
doReturn(false).when(mTelephonyManager).isRadioInterfaceCapabilitySupported(
mTelephonyManager.CAPABILITY_ALLOWED_NETWORK_TYPES_USED);
mPersistableBundle.putBoolean(CarrierConfigManager.KEY_HIDE_ENABLE_2G,
false);
assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
}
@Test
public void getAvailabilityStatus_returnAvailable() {
doReturn(true).when(mTelephonyManager).isRadioInterfaceCapabilitySupported(
mTelephonyManager.CAPABILITY_ALLOWED_NETWORK_TYPES_USED);
mPersistableBundle.putBoolean(CarrierConfigManager.KEY_HIDE_ENABLE_2G,
false);
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
}

View File

@@ -21,7 +21,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.net.ConnectivityManager;
import android.net.VpnManager;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -32,11 +32,11 @@ import org.junit.runner.RunWith;
public final class VpnUtilsTest {
@Test
public void testIsAlwaysOnVpnSet() {
final ConnectivityManager cm = mock(ConnectivityManager.class);
when(cm.getAlwaysOnVpnPackageForUser(0)).thenReturn("com.example.vpn");
assertThat(VpnUtils.isAlwaysOnVpnSet(cm, 0)).isTrue();
final VpnManager vm = mock(VpnManager.class);
when(vm.getAlwaysOnVpnPackageForUser(0)).thenReturn("com.example.vpn");
assertThat(VpnUtils.isAlwaysOnVpnSet(vm, 0)).isTrue();
when(cm.getAlwaysOnVpnPackageForUser(0)).thenReturn(null);
assertThat(VpnUtils.isAlwaysOnVpnSet(cm, 0)).isFalse();
when(vm.getAlwaysOnVpnPackageForUser(0)).thenReturn(null);
assertThat(VpnUtils.isAlwaysOnVpnSet(vm, 0)).isFalse();
}
}