diff --git a/AndroidManifest.xml b/AndroidManifest.xml index ee11802232f..cfda9b75e6b 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -517,12 +517,12 @@ + android:theme="@style/Theme.AlertDialog" /> + android:theme="@style/Theme.AlertDialog" /> + android:value="com.android.settings.display.SmartAutoRotatePreferenceFragment" /> @@ -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" /> + android:theme="@style/Theme.AlertDialog" /> diff --git a/res/layout/manage_applications_apps_v2.xml b/res/layout/manage_applications_apps_v2.xml new file mode 100644 index 00000000000..ecc764a9217 --- /dev/null +++ b/res/layout/manage_applications_apps_v2.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index 1ac3a281f6a..90aad1bea10 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -2713,8 +2713,6 @@ Display - - com.android.settings.DisplaySettings Auto-rotate screen @@ -12194,6 +12192,8 @@ Network activation + + Carrier switching %1$s is active @@ -12780,4 +12780,7 @@ Phone number is missing. OK + + + Allow 2G diff --git a/res/xml/auto_rotate_settings.xml b/res/xml/auto_rotate_settings.xml index dfa31f71aaa..a316b8fb29f 100644 --- a/res/xml/auto_rotate_settings.xml +++ b/res/xml/auto_rotate_settings.xml @@ -20,6 +20,13 @@ xmlns:settings="http://schemas.android.com/apk/res-auto" android:title="@string/accelerometer_title" > + + - - + android:key="recent_location_access" + android:title="@string/location_category_recent_location_access" + settings:controller= + "com.android.settings.location.RecentLocationAccessPreferenceController"/> - - + settings:controller= + "com.android.settings.location.RecentLocationAccessPreferenceController"/> - - + settings:controller= + "com.android.settings.location.RecentLocationAccessPreferenceController"/> + diff --git a/src/com/android/settings/accessibility/ShortcutsSettingsFragment.java b/src/com/android/settings/accessibility/ShortcutsSettingsFragment.java index 91e16f623f3..84268349b7c 100644 --- a/src/com/android/settings/accessibility/ShortcutsSettingsFragment.java +++ b/src/com/android/settings/accessibility/ShortcutsSettingsFragment.java @@ -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"; diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java index c699425e0ae..707e6f44a1a 100644 --- a/src/com/android/settings/applications/manageapplications/ManageApplications.java +++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java @@ -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) { diff --git a/src/com/android/settings/display/AutoRotatePreferenceController.java b/src/com/android/settings/display/AutoRotatePreferenceController.java index 202a085e890..eed8583c2cd 100644 --- a/src/com/android/settings/display/AutoRotatePreferenceController.java +++ b/src/com/android/settings/display/AutoRotatePreferenceController.java @@ -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 { diff --git a/src/com/android/settings/display/SmartAutoRotateController.java b/src/com/android/settings/display/SmartAutoRotateController.java index 228d0c7b177..ca196ba9c8f 100644 --- a/src/com/android/settings/display/SmartAutoRotateController.java +++ b/src/com/android/settings/display/SmartAutoRotateController.java @@ -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; + } } diff --git a/src/com/android/settings/display/SmartAutoRotatePermissionController.java b/src/com/android/settings/display/SmartAutoRotatePermissionController.java new file mode 100644 index 00000000000..484db31f371 --- /dev/null +++ b/src/com/android/settings/display/SmartAutoRotatePermissionController.java @@ -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); + } +} diff --git a/src/com/android/settings/display/SmartAutoRotatePreferenceFragment.java b/src/com/android/settings/display/SmartAutoRotatePreferenceFragment.java index 205317d6150..130bbd80f17 100644 --- a/src/com/android/settings/display/SmartAutoRotatePreferenceFragment.java +++ b/src/com/android/settings/display/SmartAutoRotatePreferenceFragment.java @@ -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 createPreferenceControllers(Context context) { - return buildPreferenceControllers(context); - } - - private static List buildPreferenceControllers( - Context context) { - final List 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 createPreferenceControllers( - Context context) { - return buildPreferenceControllers(context); - } - - @Override - protected boolean isPageSearchEnabled(Context context) { - return false; - } - }; + new BaseSearchIndexProvider(R.xml.auto_rotate_settings); } diff --git a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProvider.java b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProvider.java index 62f15b92653..7d28d82954c 100644 --- a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProvider.java +++ b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProvider.java @@ -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. diff --git a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java index 7a5b4897623..f461fe1e556 100644 --- a/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java +++ b/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImpl.java @@ -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 diff --git a/src/com/android/settings/enterprise/GlobalHttpProxyPreferenceController.java b/src/com/android/settings/enterprise/GlobalHttpProxyPreferenceController.java index 04e63aa1e8b..6de6cde359e 100644 --- a/src/com/android/settings/enterprise/GlobalHttpProxyPreferenceController.java +++ b/src/com/android/settings/enterprise/GlobalHttpProxyPreferenceController.java @@ -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 diff --git a/src/com/android/settings/fuelgauge/OWNERS b/src/com/android/settings/fuelgauge/OWNERS index 4e5ee0e10eb..ab3da898aac 100644 --- a/src/com/android/settings/fuelgauge/OWNERS +++ b/src/com/android/settings/fuelgauge/OWNERS @@ -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 diff --git a/src/com/android/settings/location/LocationSettings.java b/src/com/android/settings/location/LocationSettings.java index b4f0f1f1c11..0bc7fc774bf 100644 --- a/src/com/android/settings/location/LocationSettings.java +++ b/src/com/android/settings/location/LocationSettings.java @@ -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); diff --git a/src/com/android/settings/location/LocationWorkProfileSettings.java b/src/com/android/settings/location/LocationWorkProfileSettings.java index 2bf5f980cdc..c3127143e7b 100644 --- a/src/com/android/settings/location/LocationWorkProfileSettings.java +++ b/src/com/android/settings/location/LocationWorkProfileSettings.java @@ -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 diff --git a/src/com/android/settings/location/RecentLocationAccessPreferenceController.java b/src/com/android/settings/location/RecentLocationAccessPreferenceController.java index c835a514b1a..245118d31fb 100644 --- a/src/com/android/settings/location/RecentLocationAccessPreferenceController.java +++ b/src/com/android/settings/location/RecentLocationAccessPreferenceController.java @@ -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 = 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 = - 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; } } diff --git a/src/com/android/settings/network/telephony/Enable2gPreferenceController.java b/src/com/android/settings/network/telephony/Enable2gPreferenceController.java new file mode 100644 index 00000000000..1fa430004b3 --- /dev/null +++ b/src/com/android/settings/network/telephony/Enable2gPreferenceController.java @@ -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; + } +} diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java index 0d842ef838a..9a4cb408f20 100644 --- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java +++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java @@ -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); diff --git a/src/com/android/settings/notification/AssistantFeedbackPreferenceController.java b/src/com/android/settings/notification/AssistantFeedbackPreferenceController.java deleted file mode 100644 index 491fd8b7bfc..00000000000 --- a/src/com/android/settings/notification/AssistantFeedbackPreferenceController.java +++ /dev/null @@ -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); - } - } - } -} diff --git a/src/com/android/settings/overlay/FeatureFactoryImpl.java b/src/com/android/settings/overlay/FeatureFactoryImpl.java index ebbe87cfdac..a1b70d99ff5 100644 --- a/src/com/android/settings/overlay/FeatureFactoryImpl.java +++ b/src/com/android/settings/overlay/FeatureFactoryImpl.java @@ -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; diff --git a/src/com/android/settings/sim/SimActivationNotifier.java b/src/com/android/settings/sim/SimActivationNotifier.java index 735cb463c3e..c90836e5b78 100644 --- a/src/com/android/settings/sim/SimActivationNotifier.java +++ b/src/com/android/settings/sim/SimActivationNotifier.java @@ -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)); } /** diff --git a/src/com/android/settings/vpn2/AppDialogFragment.java b/src/com/android/settings/vpn2/AppDialogFragment.java index 45fb9bdb820..626a271e7fc 100644 --- a/src/com/android/settings/vpn2/AppDialogFragment.java +++ b/src/com/android/settings/vpn2/AppDialogFragment.java @@ -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); } } diff --git a/src/com/android/settings/vpn2/AppManagementFragment.java b/src/com/android/settings/vpn2/AppManagementFragment.java index 9422010aed0..0543fee7dbe 100644 --- a/src/com/android/settings/vpn2/AppManagementFragment.java +++ b/src/com/android/settings/vpn2/AppManagementFragment.java @@ -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() { diff --git a/src/com/android/settings/vpn2/ConfigDialogFragment.java b/src/com/android/settings/vpn2/ConfigDialogFragment.java index e88e4efd588..f339a694c03 100644 --- a/src/com/android/settings/vpn2/ConfigDialogFragment.java +++ b/src/com/android/settings/vpn2/ConfigDialogFragment.java @@ -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 { diff --git a/src/com/android/settings/vpn2/VpnSettings.java b/src/com/android/settings/vpn2/VpnSettings.java index 79f6be3c75b..0a3b2b01cd7 100644 --- a/src/com/android/settings/vpn2/VpnSettings.java +++ b/src/com/android/settings/vpn2/VpnSettings.java @@ -490,7 +490,7 @@ public class VpnSettings extends RestrictedSettingsFragment implements Set 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)); } diff --git a/src/com/android/settings/vpn2/VpnUtils.java b/src/com/android/settings/vpn2/VpnUtils.java index c6b79b4432b..4c9338ccd68 100644 --- a/src/com/android/settings/vpn2/VpnUtils.java +++ b/src/com/android/settings/vpn2/VpnUtils.java @@ -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) { diff --git a/src/com/android/settings/wifi/WifiSummaryUpdater.java b/src/com/android/settings/wifi/WifiSummaryUpdater.java index 79bab36054a..19ef200b005 100644 --- a/src/com/android/settings/wifi/WifiSummaryUpdater.java +++ b/src/com/android/settings/wifi/WifiSummaryUpdater.java @@ -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 { diff --git a/tests/robotests/src/com/android/settings/display/SmartAutoRotateControllerTest.java b/tests/robotests/src/com/android/settings/display/SmartAutoRotateControllerTest.java new file mode 100644 index 00000000000..2d56c0efd88 --- /dev/null +++ b/tests/robotests/src/com/android/settings/display/SmartAutoRotateControllerTest.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.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); + } +} diff --git a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java index c28267b9609..28a790690fa 100644 --- a/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java +++ b/tests/robotests/src/com/android/settings/enterprise/EnterprisePrivacyFeatureProviderImplTest.java @@ -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); diff --git a/tests/robotests/src/com/android/settings/enterprise/GlobalHttpProxyPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/enterprise/GlobalHttpProxyPreferenceControllerTest.java index 05d1c640fd0..11676a28378 100644 --- a/tests/robotests/src/com/android/settings/enterprise/GlobalHttpProxyPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/enterprise/GlobalHttpProxyPreferenceControllerTest.java @@ -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(); } diff --git a/tests/robotests/src/com/android/settings/location/RecentLocationAccessPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/location/RecentLocationAccessPreferenceControllerTest.java index 71a80de0689..5feee6002e0 100644 --- a/tests/robotests/src/com/android/settings/location/RecentLocationAccessPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/location/RecentLocationAccessPreferenceControllerTest.java @@ -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 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 createMockAccesses(int count) { final List accesses = new ArrayList<>(); for (int i = 0; i < count; i++) { diff --git a/tests/robotests/src/com/android/settings/network/VpnPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/VpnPreferenceControllerTest.java index 89d0465fab2..fb66d299ccd 100644 --- a/tests/robotests/src/com/android/settings/network/VpnPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/network/VpnPreferenceControllerTest.java @@ -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)); diff --git a/tests/robotests/src/com/android/settings/notification/AssistantFeedbackPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/AssistantFeedbackPreferenceControllerTest.java deleted file mode 100644 index 9f172a6df1f..00000000000 --- a/tests/robotests/src/com/android/settings/notification/AssistantFeedbackPreferenceControllerTest.java +++ /dev/null @@ -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); - } -} diff --git a/tests/robotests/src/com/android/settings/wifi/WifiSummaryUpdaterTest.java b/tests/robotests/src/com/android/settings/wifi/WifiSummaryUpdaterTest.java index 02bf172e891..1ae31e8d75d 100644 --- a/tests/robotests/src/com/android/settings/wifi/WifiSummaryUpdaterTest.java +++ b/tests/robotests/src/com/android/settings/wifi/WifiSummaryUpdaterTest.java @@ -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); diff --git a/tests/unit/src/com/android/settings/network/telephony/Enable2gPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/Enable2gPreferenceControllerTest.java new file mode 100644 index 00000000000..9b9bb1131d3 --- /dev/null +++ b/tests/unit/src/com/android/settings/network/telephony/Enable2gPreferenceControllerTest.java @@ -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); + } +} diff --git a/tests/unit/src/com/android/settings/vpn2/VpnUtilsTest.java b/tests/unit/src/com/android/settings/vpn2/VpnUtilsTest.java index f214764ca75..ff5bb81df64 100644 --- a/tests/unit/src/com/android/settings/vpn2/VpnUtilsTest.java +++ b/tests/unit/src/com/android/settings/vpn2/VpnUtilsTest.java @@ -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(); } }