diff --git a/Android.bp b/Android.bp index 866b7064b23..2637686381d 100644 --- a/Android.bp +++ b/Android.bp @@ -109,3 +109,21 @@ android_library_import { name: "contextualcards", aars: ["libs/contextualcards.aar"], } + +filegroup { + name: "Settings_proguard_flags", + srcs: ["proguard.flags"], +} + +// The sources for Settings need to be exposed to SettingsGoogle, etc. +// so they can run the com.android.settingslib.search.IndexableProcessor +// over all the sources together. +filegroup { + name: "Settings_srcs", + srcs: ["src/**/*.java"], +} + +filegroup { + name: "Settings_manifest", + srcs: ["AndroidManifest.xml"], +} diff --git a/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminListPreferenceController.java b/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminListPreferenceController.java index e25bb1e4fc0..ead5a5a7358 100644 --- a/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminListPreferenceController.java +++ b/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminListPreferenceController.java @@ -207,6 +207,7 @@ public class DeviceAdminListPreferenceController extends BasePreferenceControlle return true; }); pref.setOnPreferenceChangeListener((preference, newValue) -> false); + pref.setSingleLineTitle(true); } /** diff --git a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java index 4d1fd492437..3bc2c0f736c 100644 --- a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java +++ b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java @@ -229,7 +229,8 @@ public class SimStatusDialogController implements LifecycleObserver, OnResume, O if (mSubscriptionInfo == null) { return; } - + mTelephonyManager = + mTelephonyManager.createForSubscriptionId(mSubscriptionInfo.getSubscriptionId()); mPhoneStateListener = getPhoneStateListener(); updateLatestAreaInfo(); updateSubscriptionStatus(); diff --git a/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java index 906644482c6..11d756470dd 100644 --- a/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java +++ b/src/com/android/settings/fuelgauge/BatteryHeaderPreferenceController.java @@ -52,7 +52,8 @@ import com.android.settingslib.widget.LayoutPreference; * Controller that update the battery header view */ public class BatteryHeaderPreferenceController extends BasePreferenceController - implements PreferenceControllerMixin, LifecycleObserver, OnStart { + implements PreferenceControllerMixin, LifecycleObserver, OnStart, + BatteryPreferenceController { @VisibleForTesting static final String KEY_BATTERY_HEADER = "battery_header"; private static final String ANNOTATION_URL = "url"; @@ -121,16 +122,20 @@ public class BatteryHeaderPreferenceController extends BasePreferenceController .styleActionBar(mActivity); } + private CharSequence generateLabel(BatteryInfo info) { + if (BatteryUtils.isBatteryDefenderOn(info)) { + return null; + } else if (info.remainingLabel == null) { + return info.statusLabel; + } else { + return info.remainingLabel; + } + } + public void updateHeaderPreference(BatteryInfo info) { mBatteryPercentText.setText(formatBatteryPercentageText(info.batteryLevel)); if (!mBatteryStatusFeatureProvider.triggerBatteryStatusUpdate(this, info)) { - if (BatteryUtils.isBatteryDefenderOn(info)) { - mSummary1.setText(null); - } else if (info.remainingLabel == null) { - mSummary1.setText(info.statusLabel); - } else { - mSummary1.setText(info.remainingLabel); - } + mSummary1.setText(generateLabel(info)); } mBatteryMeterView.setBatteryLevel(info.batteryLevel); @@ -141,8 +146,8 @@ public class BatteryHeaderPreferenceController extends BasePreferenceController /** * Callback which receives text for the summary line. */ - public void updateBatteryStatus(String statusLabel) { - mSummary1.setText(statusLabel); + public void updateBatteryStatus(String label, BatteryInfo info) { + mSummary1.setText(label != null ? label : generateLabel(info)); } public void quickUpdateHeaderPreference() { diff --git a/src/com/android/settings/fuelgauge/BatteryPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryPreferenceController.java new file mode 100644 index 00000000000..badf5c8c517 --- /dev/null +++ b/src/com/android/settings/fuelgauge/BatteryPreferenceController.java @@ -0,0 +1,30 @@ +/* + * 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.fuelgauge; + +/** + * Common interface for a preference controller that updates battery status + */ +public interface BatteryPreferenceController { + + /** + * Updates the label for the preference controller. If the label is null, the + * implementation should revert back to the original label based on the + * battery info. + */ + void updateBatteryStatus(String label, BatteryInfo info); +} diff --git a/src/com/android/settings/fuelgauge/BatteryStatusFeatureProvider.java b/src/com/android/settings/fuelgauge/BatteryStatusFeatureProvider.java index c3fc24756fe..46f00c79f4f 100644 --- a/src/com/android/settings/fuelgauge/BatteryStatusFeatureProvider.java +++ b/src/com/android/settings/fuelgauge/BatteryStatusFeatureProvider.java @@ -25,5 +25,5 @@ public interface BatteryStatusFeatureProvider { * Trigger a battery status update; return false if built-in status should be used. */ boolean triggerBatteryStatusUpdate( - BatteryHeaderPreferenceController batteryHeaderPreferenceController, BatteryInfo info); + BatteryPreferenceController controller, BatteryInfo info); } diff --git a/src/com/android/settings/fuelgauge/BatteryStatusFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/BatteryStatusFeatureProviderImpl.java index 47d376dd9d7..dc4b5db467c 100644 --- a/src/com/android/settings/fuelgauge/BatteryStatusFeatureProviderImpl.java +++ b/src/com/android/settings/fuelgauge/BatteryStatusFeatureProviderImpl.java @@ -31,7 +31,7 @@ public class BatteryStatusFeatureProviderImpl implements BatteryStatusFeaturePro @Override public boolean triggerBatteryStatusUpdate( - BatteryHeaderPreferenceController batteryHeaderPreferenceController, BatteryInfo info) { + BatteryPreferenceController controller, BatteryInfo info) { return false; } } diff --git a/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceController.java b/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceController.java index e428d49a0f3..99eb05d8116 100644 --- a/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceController.java +++ b/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceController.java @@ -24,18 +24,21 @@ import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; +import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnStart; import com.android.settingslib.core.lifecycle.events.OnStop; public class TopLevelBatteryPreferenceController extends BasePreferenceController implements - LifecycleObserver, OnStart, OnStop { + LifecycleObserver, OnStart, OnStop, BatteryPreferenceController { @VisibleForTesting - boolean mIsBatteryPresent = true; + protected boolean mIsBatteryPresent = true; private final BatteryBroadcastReceiver mBatteryBroadcastReceiver; private Preference mPreference; private BatteryInfo mBatteryInfo; + private BatteryStatusFeatureProvider mBatteryStatusFeatureProvider; + private String mBatteryStatusLabel; public TopLevelBatteryPreferenceController(Context context, String preferenceKey) { super(context, preferenceKey); @@ -49,6 +52,9 @@ public class TopLevelBatteryPreferenceController extends BasePreferenceControlle updateState(mPreference); }, true /* shortString */); }); + + mBatteryStatusFeatureProvider = FeatureFactory.getFactory(context) + .getBatteryStatusFeatureProvider(context); } @Override @@ -75,27 +81,56 @@ public class TopLevelBatteryPreferenceController extends BasePreferenceControlle @Override public CharSequence getSummary() { + return getSummary(true /* batteryStatusUpdate */); + } + + private CharSequence getSummary(boolean batteryStatusUpdate) { // Display help message if battery is not present. if (!mIsBatteryPresent) { return mContext.getText(R.string.battery_missing_message); } - return getDashboardLabel(mContext, mBatteryInfo); + return getDashboardLabel(mContext, mBatteryInfo, batteryStatusUpdate); } - static CharSequence getDashboardLabel(Context context, BatteryInfo info) { + protected CharSequence getDashboardLabel(Context context, BatteryInfo info, + boolean batteryStatusUpdate) { if (info == null || context == null) { return null; } - CharSequence label; + + if (batteryStatusUpdate) { + if (!mBatteryStatusFeatureProvider.triggerBatteryStatusUpdate(this, info)) { + mBatteryStatusLabel = null; // will generateLabel() + } + } + + return (mBatteryStatusLabel == null) ? generateLabel(info) : mBatteryStatusLabel; + } + + private CharSequence generateLabel(BatteryInfo info) { if (!info.discharging && info.chargeLabel != null) { - label = info.chargeLabel; + return info.chargeLabel; } else if (info.remainingLabel == null) { - label = info.batteryPercentString; + return info.batteryPercentString; } else { - label = context.getString(R.string.power_remaining_settings_home_page, + return mContext.getString(R.string.power_remaining_settings_home_page, info.batteryPercentString, info.remainingLabel); } - return label; + } + + /** + * Callback which receives text for the label. + */ + public void updateBatteryStatus(String label, BatteryInfo info) { + mBatteryStatusLabel = label; // Null if adaptive charging is not active + + if (mPreference != null) { + // Do not triggerBatteryStatusUpdate(), otherwise there will be an infinite loop + final CharSequence summary = getSummary(false /* batteryStatusUpdate */); + if (summary != null) { + mPreference.setSummary(summary); + } + } } } diff --git a/src/com/android/settings/media/MediaOutputSlice.java b/src/com/android/settings/media/MediaOutputSlice.java index 2cc7a49b4e6..ae7e0e80a50 100644 --- a/src/com/android/settings/media/MediaOutputSlice.java +++ b/src/com/android/settings/media/MediaOutputSlice.java @@ -147,7 +147,8 @@ public class MediaOutputSlice implements CustomSliceable { .setSourceMetricsCategory(SettingsEnums.PANEL_MEDIA_OUTPUT) .toIntent(); final SliceAction primarySliceAction = SliceAction.createDeeplink( - PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, 0 /* flags */), + PendingIntent.getActivity(mContext, 0 /* requestCode */, intent, + PendingIntent.FLAG_IMMUTABLE), IconCompat.createWithResource(mContext, R.drawable.ic_add_24dp/*ic_add_blue_24dp*/), ListBuilder.ICON_IMAGE, mContext.getText(R.string.bluetooth_pairing_pref_title)); @@ -248,7 +249,8 @@ public class MediaOutputSlice implements CustomSliceable { .putExtra(MEDIA_DEVICE_ID, id) .setClass(mContext, SliceBroadcastReceiver.class); - return PendingIntent.getBroadcast(mContext, requestCode, intent, 0); + return PendingIntent.getBroadcast(mContext, requestCode, intent, + PendingIntent.FLAG_IMMUTABLE); } private SliceAction getEndItemSliceAction() { @@ -261,7 +263,8 @@ public class MediaOutputSlice implements CustomSliceable { ? 0 : getWorker().getPackageName().hashCode(); return SliceAction.createDeeplink( - PendingIntent.getActivity(mContext, requestCode, intent, 0 /* flags */), + PendingIntent.getActivity(mContext, requestCode, intent, + PendingIntent.FLAG_IMMUTABLE), IconCompat.createWithResource(mContext, R.drawable.ic_add_blue_24dp), ListBuilder.ICON_IMAGE, mContext.getText(R.string.add)); @@ -350,7 +353,7 @@ public class MediaOutputSlice implements CustomSliceable { intent.putExtra(MEDIA_DEVICE_ID, id); intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); return PendingIntent.getBroadcast(context, requestCode, intent, - PendingIntent.FLAG_UPDATE_CURRENT); + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); } @Override diff --git a/src/com/android/settings/network/ApnSettings.java b/src/com/android/settings/network/ApnSettings.java index f7617fc1fd0..477d85dc040 100755 --- a/src/com/android/settings/network/ApnSettings.java +++ b/src/com/android/settings/network/ApnSettings.java @@ -342,7 +342,7 @@ public class ApnSettings extends RestrictedSettingsFragment pref.setSummary(apn); } - final boolean selectable = ((type == null) || !type.equals("mms")); + final boolean selectable = ((type == null) || type.contains("default")); pref.setSelectable(selectable); if (selectable) { if ((mSelectedKey != null) && mSelectedKey.equals(key)) { diff --git a/src/com/android/settings/security/CredentialStorage.java b/src/com/android/settings/security/CredentialStorage.java index 7b9f419e224..e88a5c3df23 100644 --- a/src/com/android/settings/security/CredentialStorage.java +++ b/src/com/android/settings/security/CredentialStorage.java @@ -44,6 +44,7 @@ import androidx.fragment.app.FragmentActivity; import com.android.internal.widget.LockPatternUtils; import com.android.settings.R; +import com.android.settings.core.HideNonSystemOverlayMixin; import com.android.settings.password.ChooseLockSettingsHelper; import com.android.settings.vpn2.VpnUtils; @@ -74,6 +75,7 @@ public final class CredentialStorage extends FragmentActivity { protected void onCreate(Bundle savedState) { super.onCreate(savedState); mUtils = new LockPatternUtils(this); + getLifecycle().addObserver(new HideNonSystemOverlayMixin(this)); } @Override diff --git a/src/com/android/settings/utils/AndroidKeystoreAliasLoader.java b/src/com/android/settings/utils/AndroidKeystoreAliasLoader.java index c4e8124c3ed..dee58178d88 100644 --- a/src/com/android/settings/utils/AndroidKeystoreAliasLoader.java +++ b/src/com/android/settings/utils/AndroidKeystoreAliasLoader.java @@ -44,7 +44,7 @@ public class AndroidKeystoreAliasLoader { private final Collection mKeyCertAliases; private final Collection mCaCertAliases; /** - * This Constructor loads all aliases of asymmetric key pairs and certificates in the + * This Constructor loads all aliases of asymmetric keys pairs and certificates in the * AndroidKeyStore within the given namespace. * Viable namespaces are {@link KeyProperties#NAMESPACE_WIFI}, * {@link KeyProperties#NAMESPACE_APPLICATION}, or null. The latter two are equivalent in diff --git a/src/com/android/settings/vpn2/AppDialogFragment.java b/src/com/android/settings/vpn2/AppDialogFragment.java index 626a271e7fc..b5623fd1ca3 100644 --- a/src/com/android/settings/vpn2/AppDialogFragment.java +++ b/src/com/android/settings/vpn2/AppDialogFragment.java @@ -17,6 +17,7 @@ package com.android.settings.vpn2; import android.app.Dialog; +import android.app.admin.DevicePolicyManager; import android.app.settings.SettingsEnums; import android.content.DialogInterface; import android.content.pm.PackageInfo; @@ -48,6 +49,7 @@ public class AppDialogFragment extends InstrumentedDialogFragment implements App private Listener mListener; private UserManager mUserManager; + private DevicePolicyManager mDevicePolicyManager; private VpnManager mVpnManager; @Override @@ -91,7 +93,11 @@ public class AppDialogFragment extends InstrumentedDialogFragment implements App @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + mPackageInfo = getArguments().getParcelable(ARG_PACKAGE); mUserManager = UserManager.get(getContext()); + mDevicePolicyManager = getContext() + .createContextAsUser(UserHandle.of(getUserId()), /* flags= */ 0) + .getSystemService(DevicePolicyManager.class); mVpnManager = getContext().getSystemService(VpnManager.class); } @@ -101,7 +107,6 @@ public class AppDialogFragment extends InstrumentedDialogFragment implements App final String label = args.getString(ARG_LABEL); boolean managing = args.getBoolean(ARG_MANAGING); boolean connected = args.getBoolean(ARG_CONNECTED); - mPackageInfo = args.getParcelable(ARG_PACKAGE); if (managing) { return new AppDialog(getActivity(), this, mPackageInfo, label); @@ -163,7 +168,10 @@ public class AppDialogFragment extends InstrumentedDialogFragment implements App private boolean isUiRestricted() { final UserHandle userHandle = UserHandle.of(getUserId()); - return mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN, userHandle); + if (mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_VPN, userHandle)) { + return true; + } + return mPackageInfo.packageName.equals(mDevicePolicyManager.getAlwaysOnVpnPackage()); } private int getUserId() { diff --git a/src/com/android/settings/vpn2/AppPreference.java b/src/com/android/settings/vpn2/AppPreference.java index 6b64250df32..8ee2f5f2d0c 100644 --- a/src/com/android/settings/vpn2/AppPreference.java +++ b/src/com/android/settings/vpn2/AppPreference.java @@ -16,6 +16,7 @@ package com.android.settings.vpn2; +import android.app.admin.DevicePolicyManager; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; @@ -26,6 +27,8 @@ import androidx.preference.Preference; import com.android.internal.net.LegacyVpnInfo; import com.android.internal.net.VpnConfig; +import com.android.settingslib.RestrictedLockUtils; +import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; /** * {@link androidx.preference.Preference} containing information about a VPN @@ -43,6 +46,7 @@ public class AppPreference extends ManageablePreference { super.setUserId(userId); mPackageName = packageName; + disableIfConfiguredByAdmin(); // Fetch icon and VPN label String label = packageName; @@ -74,6 +78,25 @@ public class AppPreference extends ManageablePreference { setIcon(icon); } + /** + * Disable this preference if VPN is set as always on by a profile or device owner. + * NB: it should be called after super.setUserId() otherwise admin information can be lost. + */ + private void disableIfConfiguredByAdmin() { + if (isDisabledByAdmin()) { + // Already disabled due to user restriction. + return; + } + final DevicePolicyManager dpm = getContext() + .createContextAsUser(UserHandle.of(getUserId()), /* flags= */ 0) + .getSystemService(DevicePolicyManager.class); + if (mPackageName.equals(dpm.getAlwaysOnVpnPackage())) { + final EnforcedAdmin admin = RestrictedLockUtils.getProfileOrDeviceOwner( + getContext(), UserHandle.of(mUserId)); + setDisabledByAdmin(admin); + } + } + public PackageInfo getPackageInfo() { try { PackageManager pm = getUserContext().getPackageManager(); diff --git a/src/com/android/settings/wifi/WifiScanModeActivity.java b/src/com/android/settings/wifi/WifiScanModeActivity.java index 024dc104125..9d502810d5a 100644 --- a/src/com/android/settings/wifi/WifiScanModeActivity.java +++ b/src/com/android/settings/wifi/WifiScanModeActivity.java @@ -25,6 +25,7 @@ import android.content.pm.PackageManager; import android.net.wifi.WifiManager; import android.os.Bundle; import android.text.TextUtils; +import android.view.WindowManager; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.DialogFragment; @@ -43,6 +44,8 @@ public class WifiScanModeActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + getWindow().addSystemFlags( + WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); Intent intent = getIntent(); if (savedInstanceState == null) { if (intent != null && WifiManager.ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE diff --git a/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2.java b/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2.java index d0708eababf..553da81c77b 100644 --- a/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2.java +++ b/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2.java @@ -75,7 +75,8 @@ public class WifiNetworkDetailsFragment2 extends DashboardFragment implements // Interval between initiating SavedNetworkTracker scans private static final long SCAN_INTERVAL_MILLIS = 10_000; - private NetworkDetailsTracker mNetworkDetailsTracker; + @VisibleForTesting + NetworkDetailsTracker mNetworkDetailsTracker; private HandlerThread mWorkerThread; private WifiDetailPreferenceController2 mWifiDetailPreferenceController2; private List mWifiDialogListeners = new ArrayList<>(); @@ -125,9 +126,11 @@ public class WifiNetworkDetailsFragment2 extends DashboardFragment implements @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - MenuItem item = menu.add(0, Menu.FIRST, 0, R.string.wifi_modify); - item.setIcon(com.android.internal.R.drawable.ic_mode_edit); - item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); + if (isEditable()) { + MenuItem item = menu.add(0, Menu.FIRST, 0, R.string.wifi_modify); + item.setIcon(com.android.internal.R.drawable.ic_mode_edit); + item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); + } super.onCreateOptionsMenu(menu, inflater); } @@ -253,6 +256,17 @@ public class WifiNetworkDetailsFragment2 extends DashboardFragment implements getArguments().getString(KEY_CHOSEN_WIFIENTRY_KEY)); } + private boolean isEditable() { + if (mNetworkDetailsTracker == null) { + return false; + } + final WifiEntry wifiEntry = mNetworkDetailsTracker.getWifiEntry(); + if (wifiEntry == null) { + return false; + } + return wifiEntry.isSaved(); + } + /** * API call for refreshing the preferences in this fragment. */ diff --git a/tests/robotests/Android.bp b/tests/robotests/Android.bp index 6f0931e9f1e..6abf6b6bece 100644 --- a/tests/robotests/Android.bp +++ b/tests/robotests/Android.bp @@ -98,3 +98,15 @@ android_robolectric_test { "SettingsLib-search", ], } + +java_library { + name: "Settings-robo-testutils", + srcs: ["src/com/android/settings/testutils/**/*.java"], + + libs: [ + "Settings-core", + "Robolectric_all-target", + "mockito-robolectric-prebuilt", + "truth-prebuilt", + ], +} diff --git a/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceControllerTest.java index 974a52b519d..6ae670dc120 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceControllerTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceControllerTest.java @@ -34,6 +34,7 @@ import androidx.test.core.content.pm.ApplicationInfoBuilder; import com.android.settings.R; import com.android.settings.nfc.NfcPreferenceController; +import com.android.settings.testutils.shadow.ShadowNfcAdapter; import org.junit.Before; import org.junit.Test; @@ -43,7 +44,7 @@ import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.Shadows; import org.robolectric.annotation.Config; -import org.robolectric.shadows.ShadowNfcAdapter; +import org.robolectric.shadow.api.Shadow; import org.robolectric.shadows.ShadowPackageManager; import org.robolectric.util.ReflectionHelpers; @@ -70,7 +71,7 @@ public class AdvancedConnectedDeviceControllerTest { mContentResolver = mContext.getContentResolver(); mNfcController = new NfcPreferenceController(mContext, NfcPreferenceController.KEY_TOGGLE_NFC); - mShadowNfcAdapter = Shadows.shadowOf(NfcAdapter.getNfcAdapter(mContext)); + mShadowNfcAdapter = Shadow.extract(NfcAdapter.getDefaultAdapter(mContext)); mShadowPackageManager = Shadows.shadowOf(mContext.getPackageManager()); } diff --git a/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragmentTest.java index d6bcb127667..aed3787b0fa 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragmentTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/AdvancedConnectedDeviceDashboardFragmentTest.java @@ -18,7 +18,6 @@ package com.android.settings.connecteddevice; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.when; import android.content.Context; import android.nfc.NfcAdapter; @@ -26,35 +25,38 @@ import android.provider.SearchIndexableResource; import com.android.settings.nfc.AndroidBeamPreferenceController; import com.android.settings.testutils.shadow.ShadowConnectivityManager; +import com.android.settings.testutils.shadow.ShadowNfcAdapter; import com.android.settings.testutils.shadow.ShadowUserManager; import com.android.settingslib.drawer.CategoryKey; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; +import org.robolectric.shadow.api.Shadow; import java.util.List; @RunWith(RobolectricTestRunner.class) @Config(shadows = {ShadowUserManager.class, - ShadowConnectivityManager.class}) + ShadowConnectivityManager.class, ShadowNfcAdapter.class}) public class AdvancedConnectedDeviceDashboardFragmentTest { private AdvancedConnectedDeviceDashboardFragment mFragment; - @Mock - private NfcAdapter mNfcAdapter; + private Context mContext; + private ShadowNfcAdapter mShadowNfcAdapter; @Before public void setUp() { MockitoAnnotations.initMocks(this); + mContext = spy(RuntimeEnvironment.application); mFragment = new AdvancedConnectedDeviceDashboardFragment(); + mShadowNfcAdapter = Shadow.extract(NfcAdapter.getDefaultAdapter(mContext)); } @Test @@ -79,13 +81,10 @@ public class AdvancedConnectedDeviceDashboardFragmentTest { @Test public void testSearchIndexProvider_correctNonIndexables() { - Context context = spy(RuntimeEnvironment.application); - when(context.getApplicationContext()).thenReturn(context); - when(NfcAdapter.getDefaultAdapter(context)).thenReturn(mNfcAdapter); - when(mNfcAdapter.isSecureNfcSupported()).thenReturn(true); + mShadowNfcAdapter.setSecureNfcSupported(true); final List niks = AdvancedConnectedDeviceDashboardFragment.SEARCH_INDEX_DATA_PROVIDER - .getNonIndexableKeys(context); + .getNonIndexableKeys(mContext); assertThat(niks).contains(AndroidBeamPreferenceController.KEY_ANDROID_BEAM_SETTINGS); } diff --git a/tests/robotests/src/com/android/settings/connecteddevice/NfcAndPaymentFragmentControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/NfcAndPaymentFragmentControllerTest.java index ffaade3fda3..8acb81cf28c 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/NfcAndPaymentFragmentControllerTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/NfcAndPaymentFragmentControllerTest.java @@ -29,6 +29,7 @@ import android.nfc.NfcManager; import android.os.UserManager; import com.android.settings.R; +import com.android.settings.testutils.shadow.ShadowNfcAdapter; import org.junit.Before; import org.junit.Test; @@ -37,9 +38,12 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; +import org.robolectric.shadow.api.Shadow; import org.robolectric.util.ReflectionHelpers; @RunWith(RobolectricTestRunner.class) +@Config(shadows = ShadowNfcAdapter.class) public class NfcAndPaymentFragmentControllerTest { private NfcAndPaymentFragmentController mController; private Context mContext; @@ -50,29 +54,28 @@ public class NfcAndPaymentFragmentControllerTest { private UserManager mUserManager; @Mock private NfcManager mNfcManager; - @Mock - private NfcAdapter mNfcAdapter; + + private ShadowNfcAdapter mShadowNfcAdapter; @Before public void setUp() { MockitoAnnotations.initMocks(this); mContext = spy(RuntimeEnvironment.application); + mShadowNfcAdapter = Shadow.extract(NfcAdapter.getDefaultAdapter(mContext)); when(mContext.getApplicationContext()).thenReturn(mContext); when(mContext.getPackageManager()).thenReturn(mPackageManager); when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); when(mContext.getSystemService(Context.NFC_SERVICE)).thenReturn(mNfcManager); - when(NfcAdapter.getDefaultAdapter(mContext)).thenReturn(mNfcAdapter); mController = new NfcAndPaymentFragmentController(mContext, "fakeKey"); - ReflectionHelpers.setField(mController, "mNfcAdapter", mNfcAdapter); } @Test public void getAvailabilityStatus_hasNfc_shouldReturnAvailable() { when(mPackageManager.hasSystemFeature(anyString())).thenReturn(true); when(mUserManager.isAdminUser()).thenReturn(true); - when(mNfcAdapter.isEnabled()).thenReturn(true); + mShadowNfcAdapter.setEnabled(true); assertThat(mController.getAvailabilityStatus()) .isEqualTo(NfcAndPaymentFragmentController.AVAILABLE); @@ -87,14 +90,14 @@ public class NfcAndPaymentFragmentControllerTest { @Test public void getSummary_nfcOn_shouldProvideOnSummary() { - when(mNfcAdapter.isEnabled()).thenReturn(true); + mShadowNfcAdapter.setEnabled(true); assertThat(mController.getSummary().toString()).contains( mContext.getString(R.string.switch_on_text)); } @Test public void getSummary_nfcOff_shouldProvideOffSummary() { - when(mNfcAdapter.isEnabled()).thenReturn(false); + mShadowNfcAdapter.setEnabled(false); assertThat(mController.getSummary().toString()).contains( mContext.getString(R.string.switch_off_text)); } diff --git a/tests/robotests/src/com/android/settings/connecteddevice/NfcAndPaymentFragmentTest.java b/tests/robotests/src/com/android/settings/connecteddevice/NfcAndPaymentFragmentTest.java index 46c9cbb2ab0..dea0c7388a0 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/NfcAndPaymentFragmentTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/NfcAndPaymentFragmentTest.java @@ -22,9 +22,12 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.content.Context; +import android.content.pm.PackageManager; import android.nfc.NfcAdapter; import android.provider.SearchIndexableResource; +import com.android.settings.testutils.shadow.ShadowNfcAdapter; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -32,16 +35,20 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; +import org.robolectric.shadow.api.Shadow; import java.util.List; @RunWith(RobolectricTestRunner.class) +@Config(shadows = ShadowNfcAdapter.class) public class NfcAndPaymentFragmentTest { + @Mock + private PackageManager mPackageManager; + private NfcAndPaymentFragment mFragment; private Context mContext; - - @Mock - private NfcAdapter mNfcAdapter; + private ShadowNfcAdapter mShadowNfcAdapter; @Before public void setUp() { @@ -49,6 +56,9 @@ public class NfcAndPaymentFragmentTest { mFragment = new NfcAndPaymentFragment(); mContext = spy(RuntimeEnvironment.application); + mShadowNfcAdapter = Shadow.extract(NfcAdapter.getDefaultAdapter(mContext)); + + when(mContext.getPackageManager()).thenReturn(mPackageManager); } @Test @@ -64,8 +74,10 @@ public class NfcAndPaymentFragmentTest { @Test public void searchIndexProvider_shouldIndexValidItems() { when(mContext.getApplicationContext()).thenReturn(mContext); - when(NfcAdapter.getDefaultAdapter(mContext)).thenReturn(mNfcAdapter); - when(mNfcAdapter.isSecureNfcSupported()).thenReturn(true); + when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_NFC)).thenReturn(true); + when(mPackageManager.hasSystemFeature( + PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)).thenReturn(true); + mShadowNfcAdapter.setSecureNfcSupported(true); final List niks = NfcAndPaymentFragment.SEARCH_INDEX_DATA_PROVIDER .getNonIndexableKeys(mContext); diff --git a/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java index afe9cfcc3ca..bccccf514d3 100644 --- a/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java +++ b/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java @@ -161,6 +161,8 @@ public class SimStatusDialogControllerTest { doReturn(null).when(mSignalStrength).getCellSignalStrengths(); doReturn(mPhoneStateListener).when(mController).getPhoneStateListener(); doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt()); + when(mSubscriptionInfo.getSubscriptionId()) + .thenReturn(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID); ReflectionHelpers.setField(mController, "mTelephonyManager", mTelephonyManager); ReflectionHelpers.setField(mController, "mCarrierConfigManager", mCarrierConfigManager); diff --git a/tests/robotests/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceControllerTest.java index 10893c927be..1a3c98f8ba1 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/TopLevelBatteryPreferenceControllerTest.java @@ -18,7 +18,6 @@ package com.android.settings.fuelgauge; import static com.android.settings.core.BasePreferenceController.AVAILABLE; import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE; -import static com.android.settings.fuelgauge.TopLevelBatteryPreferenceController.getDashboardLabel; import static com.google.common.truth.Truth.assertThat; @@ -59,14 +58,16 @@ public class TopLevelBatteryPreferenceControllerTest { public void getDashboardLabel_returnsCorrectLabel() { BatteryInfo info = new BatteryInfo(); info.batteryPercentString = "3%"; - assertThat(getDashboardLabel(mContext, info)).isEqualTo(info.batteryPercentString); + assertThat(mController.getDashboardLabel(mContext, info, true)) + .isEqualTo(info.batteryPercentString); info.remainingLabel = "Phone will shut down soon"; - assertThat(getDashboardLabel(mContext, info)).isEqualTo("3% - Phone will shut down soon"); + assertThat(mController.getDashboardLabel(mContext, info, true)) + .isEqualTo("3% - Phone will shut down soon"); info.discharging = false; info.chargeLabel = "5% - charging"; - assertThat(getDashboardLabel(mContext, info)).isEqualTo("5% - charging"); + assertThat(mController.getDashboardLabel(mContext, info, true)).isEqualTo("5% - charging"); } @Test diff --git a/tests/robotests/src/com/android/settings/nfc/AndroidBeamPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/nfc/AndroidBeamPreferenceControllerTest.java index cd70d662022..7e1561863cc 100644 --- a/tests/robotests/src/com/android/settings/nfc/AndroidBeamPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/nfc/AndroidBeamPreferenceControllerTest.java @@ -31,6 +31,7 @@ import android.provider.Settings; import androidx.preference.PreferenceScreen; +import com.android.settings.testutils.shadow.ShadowNfcAdapter; import com.android.settingslib.RestrictedLockUtilsInternal; import com.android.settingslib.RestrictedPreference; @@ -41,19 +42,20 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; +import org.robolectric.shadow.api.Shadow; import org.robolectric.util.ReflectionHelpers; import java.util.ArrayList; import java.util.List; @RunWith(RobolectricTestRunner.class) +@Config(shadows = ShadowNfcAdapter.class) public class AndroidBeamPreferenceControllerTest { Context mContext; @Mock - private NfcAdapter mNfcAdapter; - @Mock - NfcManager mManager; + NfcManager mNfcManager; @Mock private UserManager mUserManager; @Mock @@ -63,18 +65,19 @@ public class AndroidBeamPreferenceControllerTest { private RestrictedPreference mAndroidBeamPreference; private AndroidBeamPreferenceController mAndroidBeamController; + private ShadowNfcAdapter mShadowNfcAdapter; @Before public void setUp() { MockitoAnnotations.initMocks(this); mContext = spy(RuntimeEnvironment.application); + mShadowNfcAdapter = Shadow.extract(NfcAdapter.getDefaultAdapter(mContext)); when(mContext.getApplicationContext()).thenReturn(mContext); when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); - when(mContext.getSystemService(Context.NFC_SERVICE)).thenReturn(mManager); + when(mContext.getSystemService(Context.NFC_SERVICE)).thenReturn(mNfcManager); when(RestrictedLockUtilsInternal.hasBaseUserRestriction(mContext, UserManager.DISALLOW_OUTGOING_BEAM, UserHandle.myUserId())).thenReturn(false); - when(NfcAdapter.getDefaultAdapter(mContext)).thenReturn(mNfcAdapter); mAndroidBeamController = new AndroidBeamPreferenceController(mContext, AndroidBeamPreferenceController.KEY_ANDROID_BEAM_SETTINGS); @@ -95,13 +98,13 @@ public class AndroidBeamPreferenceControllerTest { @Test public void isAvailable_hasNfc_shouldReturnTrue() { - when(mNfcAdapter.isEnabled()).thenReturn(true); + mShadowNfcAdapter.setEnabled(true); assertThat(mAndroidBeamController.isAvailable()).isTrue(); } @Test public void isAvailable_noNfcFeature_shouldReturnFalse() { - when(mNfcAdapter.isEnabled()).thenReturn(true); + mShadowNfcAdapter.setEnabled(true); when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_NFC_BEAM)).thenReturn(false); assertThat(mAndroidBeamController.isAvailable()).isFalse(); } @@ -114,7 +117,7 @@ public class AndroidBeamPreferenceControllerTest { @Test public void isBeamEnable_disAllowBeam_shouldReturnFalse() { - when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_OFF); + mShadowNfcAdapter.setAdapterState(NfcAdapter.STATE_OFF); when(RestrictedLockUtilsInternal.hasBaseUserRestriction(mContext, UserManager.DISALLOW_OUTGOING_BEAM, UserHandle.myUserId())).thenReturn(true); @@ -125,7 +128,7 @@ public class AndroidBeamPreferenceControllerTest { @Test public void isBeamEnable_nfcStateOn_shouldReturnTrue() { - when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_ON); + mShadowNfcAdapter.setAdapterState(NfcAdapter.STATE_ON); try { mAndroidBeamController.onResume(); } catch (NullPointerException e) { @@ -137,22 +140,22 @@ public class AndroidBeamPreferenceControllerTest { @Test public void isBeamEnable_nfcStateNotOn_shouldReturnFalse() { - when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_OFF); + mShadowNfcAdapter.setAdapterState(NfcAdapter.STATE_OFF); mAndroidBeamController.onResume(); assertThat(mAndroidBeamPreference.isEnabled()).isFalse(); - when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_TURNING_ON); + mShadowNfcAdapter.setAdapterState(NfcAdapter.STATE_TURNING_ON); mAndroidBeamController.onResume(); assertThat(mAndroidBeamPreference.isEnabled()).isFalse(); - when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_TURNING_OFF); + mShadowNfcAdapter.setAdapterState(NfcAdapter.STATE_TURNING_OFF); mAndroidBeamController.onResume(); assertThat(mAndroidBeamPreference.isEnabled()).isFalse(); } @Test public void updateNonIndexableKeys_available_shouldNotUpdate() { - when(mNfcAdapter.isEnabled()).thenReturn(true); + mShadowNfcAdapter.setEnabled(true); final List keys = new ArrayList<>(); mAndroidBeamController.updateNonIndexableKeys(keys); diff --git a/tests/robotests/src/com/android/settings/nfc/NfcPaymentPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/nfc/NfcPaymentPreferenceControllerTest.java index b69e1727762..026fdeebf9a 100644 --- a/tests/robotests/src/com/android/settings/nfc/NfcPaymentPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/nfc/NfcPaymentPreferenceControllerTest.java @@ -29,6 +29,7 @@ import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.nfc.PaymentBackend.PaymentAppInfo; +import com.android.settings.testutils.shadow.ShadowNfcAdapter; import org.junit.Before; import org.junit.Test; @@ -37,10 +38,12 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; import java.util.ArrayList; @RunWith(RobolectricTestRunner.class) +@Config(shadows = ShadowNfcAdapter.class) public class NfcPaymentPreferenceControllerTest { private static final String PREF_KEY = PaymentSettingsTest.PAYMENT_KEY; diff --git a/tests/robotests/src/com/android/settings/nfc/NfcPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/nfc/NfcPreferenceControllerTest.java index 872c7124119..1d0516230a4 100644 --- a/tests/robotests/src/com/android/settings/nfc/NfcPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/nfc/NfcPreferenceControllerTest.java @@ -35,6 +35,7 @@ import androidx.preference.SwitchPreference; import com.android.settings.nfc.NfcPreferenceController.NfcSliceWorker; import com.android.settings.nfc.NfcPreferenceController.NfcSliceWorker.NfcUpdateReceiver; +import com.android.settings.testutils.shadow.ShadowNfcAdapter; import org.junit.Before; import org.junit.Test; @@ -43,16 +44,17 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; +import org.robolectric.shadow.api.Shadow; import org.robolectric.util.ReflectionHelpers; import java.util.ArrayList; import java.util.List; @RunWith(RobolectricTestRunner.class) +@Config(shadows = ShadowNfcAdapter.class) public class NfcPreferenceControllerTest { - @Mock - private NfcAdapter mNfcAdapter; @Mock NfcManager mManager; @Mock @@ -63,16 +65,19 @@ public class NfcPreferenceControllerTest { private Context mContext; private SwitchPreference mNfcPreference; private NfcPreferenceController mNfcController; + private ShadowNfcAdapter mShadowNfcAdapter; + private NfcAdapter mNfcAdapter; @Before public void setUp() { MockitoAnnotations.initMocks(this); mContext = spy(RuntimeEnvironment.application); + mShadowNfcAdapter = Shadow.extract(NfcAdapter.getDefaultAdapter(mContext)); + mNfcAdapter = NfcAdapter.getDefaultAdapter(mContext); when(mContext.getApplicationContext()).thenReturn(mContext); when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); when(mContext.getSystemService(Context.NFC_SERVICE)).thenReturn(mManager); - when(NfcAdapter.getDefaultAdapter(mContext)).thenReturn(mNfcAdapter); mNfcController = new NfcPreferenceController(mContext, NfcPreferenceController.KEY_TOGGLE_NFC); @@ -83,7 +88,7 @@ public class NfcPreferenceControllerTest { @Test public void getAvailabilityStatus_hasNfc_shouldReturnAvailable() { - when(mNfcAdapter.isEnabled()).thenReturn(true); + mShadowNfcAdapter.setEnabled(true); assertThat(mNfcController.getAvailabilityStatus()) .isEqualTo(NfcPreferenceController.AVAILABLE); } @@ -98,11 +103,11 @@ public class NfcPreferenceControllerTest { @Test public void isNfcEnable_nfcStateNotTurning_shouldReturnTrue() { mNfcController.displayPreference(mScreen); - when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_ON); + mShadowNfcAdapter.setAdapterState(NfcAdapter.STATE_ON); mNfcController.onResume(); assertThat(mNfcPreference.isEnabled()).isTrue(); - when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_OFF); + mShadowNfcAdapter.setAdapterState(NfcAdapter.STATE_OFF); mNfcController.onResume(); assertThat(mNfcPreference.isEnabled()).isTrue(); } @@ -110,11 +115,11 @@ public class NfcPreferenceControllerTest { @Test public void isNfcEnable_nfcStateTurning_shouldReturnFalse() { mNfcController.displayPreference(mScreen); - when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_TURNING_ON); + mShadowNfcAdapter.setAdapterState(NfcAdapter.STATE_TURNING_ON); mNfcController.onResume(); assertThat(mNfcPreference.isEnabled()).isFalse(); - when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_TURNING_OFF); + mShadowNfcAdapter.setAdapterState(NfcAdapter.STATE_TURNING_OFF); mNfcController.onResume(); assertThat(mNfcPreference.isEnabled()).isFalse(); } @@ -122,29 +127,29 @@ public class NfcPreferenceControllerTest { @Test public void isNfcChecked_nfcStateOn_shouldReturnTrue() { mNfcController.displayPreference(mScreen); - when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_ON); + mShadowNfcAdapter.setAdapterState(NfcAdapter.STATE_ON); mNfcController.onResume(); assertThat(mNfcPreference.isChecked()).isTrue(); - when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_TURNING_ON); + mShadowNfcAdapter.setAdapterState(NfcAdapter.STATE_TURNING_ON); mNfcController.onResume(); assertThat(mNfcPreference.isChecked()).isTrue(); } @Test public void isNfcChecked_nfcStateOff_shouldReturnFalse() { - when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_OFF); + mShadowNfcAdapter.setAdapterState(NfcAdapter.STATE_OFF); mNfcController.onResume(); assertThat(mNfcPreference.isChecked()).isFalse(); - when(mNfcAdapter.getAdapterState()).thenReturn(NfcAdapter.STATE_TURNING_OFF); + mShadowNfcAdapter.setAdapterState(NfcAdapter.STATE_TURNING_OFF); mNfcController.onResume(); assertThat(mNfcPreference.isChecked()).isFalse(); } @Test public void updateNonIndexableKeys_available_shouldNotUpdate() { - when(mNfcAdapter.isEnabled()).thenReturn(true); + mShadowNfcAdapter.setEnabled(true); final List keys = new ArrayList<>(); mNfcController.updateNonIndexableKeys(keys); @@ -167,7 +172,7 @@ public class NfcPreferenceControllerTest { mNfcController.setChecked(true); mNfcController.onResume(); - verify(mNfcAdapter).enable(); + assertThat(mNfcAdapter.isEnabled()).isTrue(); } @Test @@ -175,7 +180,7 @@ public class NfcPreferenceControllerTest { mNfcController.setChecked(false); mNfcController.onResume(); - verify(mNfcAdapter).disable(); + assertThat(mNfcAdapter.isEnabled()).isFalse(); } @Test diff --git a/tests/robotests/src/com/android/settings/nfc/PaymentSettingsTest.java b/tests/robotests/src/com/android/settings/nfc/PaymentSettingsTest.java index 6740cb0c9b2..32eedd87b3a 100644 --- a/tests/robotests/src/com/android/settings/nfc/PaymentSettingsTest.java +++ b/tests/robotests/src/com/android/settings/nfc/PaymentSettingsTest.java @@ -33,6 +33,8 @@ import androidx.preference.Preference; import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; +import com.android.settings.testutils.shadow.ShadowNfcAdapter; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -48,7 +50,7 @@ import java.util.ArrayList; import java.util.List; @RunWith(RobolectricTestRunner.class) -@Config(shadows = PaymentSettingsTest.ShadowPaymentBackend.class) +@Config(shadows = {PaymentSettingsTest.ShadowPaymentBackend.class, ShadowNfcAdapter.class}) public class PaymentSettingsTest { static final String PAYMENT_KEY = "nfc_payment"; diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowNfcAdapter.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowNfcAdapter.java index fb8c068f3ba..54f665c75d9 100644 --- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowNfcAdapter.java +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowNfcAdapter.java @@ -16,6 +16,8 @@ package com.android.settings.testutils.shadow; +import static org.robolectric.shadow.api.Shadow.newInstanceOf; + import android.app.Activity; import android.content.Context; import android.nfc.NfcAdapter; @@ -24,16 +26,18 @@ import android.os.Bundle; import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; import org.robolectric.annotation.Resetter; -import org.robolectric.util.ReflectionHelpers; -import org.robolectric.util.ReflectionHelpers.ClassParameter; /** * Shadow of {@link NfcAdapter}. */ -@Implements(NfcAdapter.class) -public class ShadowNfcAdapter { +@Implements(value = NfcAdapter.class) +public class ShadowNfcAdapter extends org.robolectric.shadows.ShadowNfcAdapter { private static boolean sReaderModeEnabled; + private static Object sNfcAdapter = newInstanceOf("android.nfc.NfcAdapter"); + private boolean mIsNfcEnabled = false; + private int mState = NfcAdapter.STATE_ON; + private boolean mIsSecureNfcSupported = false; @Implementation protected void enableReaderMode(Activity activity, NfcAdapter.ReaderCallback callback, @@ -43,8 +47,7 @@ public class ShadowNfcAdapter { @Implementation protected static NfcAdapter getDefaultAdapter(Context context) { - return ReflectionHelpers.callConstructor( - NfcAdapter.class, ClassParameter.from(Context.class, context)); + return (NfcAdapter) sNfcAdapter; } @Implementation @@ -52,6 +55,28 @@ public class ShadowNfcAdapter { return mIsNfcEnabled; } + public void setEnabled(boolean enable) { + mIsNfcEnabled = enable; + } + + @Implementation + protected int getAdapterState() { + return mState; + } + + public void setAdapterState(int state) { + this.mState = state; + } + + @Implementation + protected boolean isSecureNfcSupported() { + return mIsSecureNfcSupported; + } + + public void setSecureNfcSupported(boolean supported) { + this.mIsSecureNfcSupported = supported; + } + @Implementation protected boolean enable() { mIsNfcEnabled = true; diff --git a/tests/robotests/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2Test.java b/tests/robotests/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2Test.java index e0fb578b8ea..66b5bcb9bcc 100644 --- a/tests/robotests/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2Test.java +++ b/tests/robotests/src/com/android/settings/wifi/details2/WifiNetworkDetailsFragment2Test.java @@ -24,9 +24,9 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; import android.app.settings.SettingsEnums; import android.view.Menu; @@ -36,12 +36,17 @@ import android.view.MenuItem; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; +import com.android.settings.R; import com.android.settings.core.BasePreferenceController; import com.android.settingslib.core.AbstractPreferenceController; +import com.android.wifitrackerlib.NetworkDetailsTracker; +import com.android.wifitrackerlib.WifiEntry; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; @@ -52,11 +57,22 @@ public class WifiNetworkDetailsFragment2Test { final String TEST_PREFERENCE_KEY = "TEST_PREFERENCE_KEY"; + @Mock + WifiEntry mWifiEntry; + @Mock + NetworkDetailsTracker mNetworkDetailsTracker; + @Mock + Menu mMenu; private WifiNetworkDetailsFragment2 mFragment; @Before public void setUp() { + MockitoAnnotations.initMocks(this); + doReturn(mWifiEntry).when(mNetworkDetailsTracker).getWifiEntry(); + doReturn(true).when(mWifiEntry).isSaved(); + mFragment = new WifiNetworkDetailsFragment2(); + mFragment.mNetworkDetailsTracker = mNetworkDetailsTracker; } @Test @@ -77,15 +93,23 @@ public class WifiNetworkDetailsFragment2Test { @Test public void onCreateOptionsMenu_shouldSetCorrectIcon() { - final Menu menu = mock(Menu.class); final MenuItem menuItem = mock(MenuItem.class); - doReturn(menuItem).when(menu).add(anyInt(), eq(Menu.FIRST), anyInt(), anyInt()); + doReturn(menuItem).when(mMenu).add(anyInt(), eq(Menu.FIRST), anyInt(), anyInt()); - mFragment.onCreateOptionsMenu(menu, mock(MenuInflater.class)); + mFragment.onCreateOptionsMenu(mMenu, mock(MenuInflater.class)); verify(menuItem).setIcon(com.android.internal.R.drawable.ic_mode_edit); } + @Test + public void onCreateOptionsMenu_isNotSavedNetwork_shouldNotAddEditMenu() { + doReturn(false).when(mWifiEntry).isSaved(); + + mFragment.onCreateOptionsMenu(mMenu, mock(MenuInflater.class)); + + verify(mMenu, never()).add(anyInt(), anyInt(), anyInt(), eq(R.string.wifi_modify)); + } + @Test public void refreshPreferences_controllerShouldUpdateStateAndDisplayPreference() { final FakeFragment fragment = spy(new FakeFragment());