diff --git a/res/layout/battery_usage_graph.xml b/res/layout/battery_usage_graph.xml deleted file mode 100644 index e79c7b94f85..00000000000 --- a/res/layout/battery_usage_graph.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - diff --git a/res/values/strings.xml b/res/values/strings.xml index 0fd961702ad..2cfec6e4d10 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -4582,8 +4582,6 @@ Battery What has been using the battery - - Battery usage data isn\u2019t available. %1$s - %2$s @@ -4631,8 +4629,6 @@ Screen usage since full charge - - Battery usage since full charge %1$s left (New ML est) @@ -4800,8 +4796,6 @@ Voice calls - - Used for ^1 Screen usage ^1 @@ -4870,9 +4864,6 @@ Other users - - Battery left estimate is based on your device usage - Estimated time left @@ -5141,6 +5132,8 @@ Adaptive connectivity Extends battery life and improves device performance by automatically managing your network connections + + Use adaptive connectivity Credential storage @@ -10510,12 +10503,15 @@ Use Wi\u2011Fi for calls to improve quality + Backup calling + If %1$s is unavailable or roaming, use your mobile data SIM for %1$s calls. + backup calling diff --git a/res/xml/adaptive_connectivity_settings.xml b/res/xml/adaptive_connectivity_settings.xml index d5941ad0507..63060065f83 100644 --- a/res/xml/adaptive_connectivity_settings.xml +++ b/res/xml/adaptive_connectivity_settings.xml @@ -30,7 +30,7 @@ diff --git a/res/xml/mobile_network_settings.xml b/res/xml/mobile_network_settings.xml index 96eacbc7349..22434b1ddc2 100644 --- a/res/xml/mobile_network_settings.xml +++ b/res/xml/mobile_network_settings.xml @@ -183,14 +183,6 @@ android:persistent="true" settings:controller="com.android.settings.network.telephony.VideoCallingPreferenceController"/> - - - - diff --git a/src/com/android/settings/activityembedding/ActivityEmbeddingRulesController.java b/src/com/android/settings/activityembedding/ActivityEmbeddingRulesController.java index 0bd9996d4f2..ab3716e9eef 100644 --- a/src/com/android/settings/activityembedding/ActivityEmbeddingRulesController.java +++ b/src/com/android/settings/activityembedding/ActivityEmbeddingRulesController.java @@ -208,7 +208,7 @@ public class ActivityEmbeddingRulesController { final SplitPlaceholderRule placeholderRule = new SplitPlaceholderRule( activityFilters, intent, - true /* stickyPlaceholder */, + false /* stickyPlaceholder */, SplitRule.FINISH_ADJACENT, ActivityEmbeddingUtils.getMinCurrentScreenSplitWidthPx(mContext), ActivityEmbeddingUtils.getMinSmallestScreenSplitWidthPx(mContext), diff --git a/src/com/android/settings/applications/intentpicker/ProgressDialogFragment.java b/src/com/android/settings/applications/intentpicker/ProgressDialogFragment.java index c8f4c0b789d..6c5974558ad 100644 --- a/src/com/android/settings/applications/intentpicker/ProgressDialogFragment.java +++ b/src/com/android/settings/applications/intentpicker/ProgressDialogFragment.java @@ -19,6 +19,7 @@ package com.android.settings.applications.intentpicker; import static android.content.pm.verify.domain.DomainVerificationUserState.DOMAIN_STATE_NONE; import android.app.Dialog; +import android.app.settings.SettingsEnums; import android.content.Context; import android.content.DialogInterface; import android.content.pm.verify.domain.DomainOwner; @@ -113,7 +114,7 @@ public class ProgressDialogFragment extends InstrumentedDialogFragment { @Override public int getMetricsCategory() { - return 0; + return SettingsEnums.PROGRESS_DIALOG; } /** diff --git a/src/com/android/settings/applications/intentpicker/SupportedLinksDialogFragment.java b/src/com/android/settings/applications/intentpicker/SupportedLinksDialogFragment.java index dd5b746d75f..e67fa049155 100644 --- a/src/com/android/settings/applications/intentpicker/SupportedLinksDialogFragment.java +++ b/src/com/android/settings/applications/intentpicker/SupportedLinksDialogFragment.java @@ -17,6 +17,7 @@ package com.android.settings.applications.intentpicker; import android.app.Dialog; +import android.app.settings.SettingsEnums; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.verify.domain.DomainVerificationManager; @@ -73,7 +74,7 @@ public class SupportedLinksDialogFragment extends InstrumentedDialogFragment { @Override public int getMetricsCategory() { - return 0; + return SettingsEnums.SUPPORTED_LINKS_DIALOG; } /** Display the dialog. */ diff --git a/src/com/android/settings/biometrics2/factory/BiometricsFragmentFactory.java b/src/com/android/settings/biometrics2/factory/BiometricsFragmentFactory.java deleted file mode 100644 index 9a0cab21d5a..00000000000 --- a/src/com/android/settings/biometrics2/factory/BiometricsFragmentFactory.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings.biometrics2.factory; - -import android.app.Application; -import android.app.admin.DevicePolicyManager; - -import androidx.annotation.NonNull; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentFactory; -import androidx.lifecycle.ViewModelProvider; - -import com.android.settings.biometrics2.ui.view.FingerprintEnrollIntroFragment; - -/** - * Fragment factory for biometrics - */ -public class BiometricsFragmentFactory extends FragmentFactory { - - private final Application mApplication; - private final ViewModelProvider mViewModelProvider; - - public BiometricsFragmentFactory(Application application, - ViewModelProvider viewModelProvider) { - mApplication = application; - mViewModelProvider = viewModelProvider; - } - - @NonNull - @Override - public Fragment instantiate(@NonNull ClassLoader classLoader, @NonNull String className) { - final Class clazz = loadFragmentClass(classLoader, className); - if (FingerprintEnrollIntroFragment.class.equals(clazz)) { - final DevicePolicyManager devicePolicyManager = - mApplication.getSystemService(DevicePolicyManager.class); - if (devicePolicyManager != null) { - return new FingerprintEnrollIntroFragment(mViewModelProvider, - devicePolicyManager.getResources()); - } - } - return super.instantiate(classLoader, className); - } -} diff --git a/src/com/android/settings/biometrics2/ui/model/CredentialModel.java b/src/com/android/settings/biometrics2/ui/model/CredentialModel.java index 06caf5e6945..b943608be20 100644 --- a/src/com/android/settings/biometrics2/ui/model/CredentialModel.java +++ b/src/com/android/settings/biometrics2/ui/model/CredentialModel.java @@ -22,6 +22,7 @@ import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_C import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE; import android.content.Intent; +import android.os.Bundle; import android.os.UserHandle; import androidx.annotation.NonNull; @@ -80,17 +81,30 @@ public final class CredentialModel { @Nullable private Long mClearGkPwHandleMillis = null; - public CredentialModel(@NonNull Intent intent, @NonNull Clock clock) { - mUserId = intent.getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId()); - mSensorId = intent.getIntExtra(EXTRA_KEY_SENSOR_ID, INVALID_SENSOR_ID); - mChallenge = intent.getLongExtra(EXTRA_KEY_CHALLENGE, INVALID_CHALLENGE); - mToken = intent.getByteArrayExtra(EXTRA_KEY_CHALLENGE_TOKEN); - mGkPwHandle = intent.getLongExtra(EXTRA_KEY_GK_PW_HANDLE, - INVALID_GK_PW_HANDLE); + public CredentialModel(@NonNull Bundle bundle, @NonNull Clock clock) { + mUserId = bundle.getInt(Intent.EXTRA_USER_ID, UserHandle.myUserId()); + mSensorId = bundle.getInt(EXTRA_KEY_SENSOR_ID, INVALID_SENSOR_ID); + mChallenge = bundle.getLong(EXTRA_KEY_CHALLENGE, INVALID_CHALLENGE); + mToken = bundle.getByteArray(EXTRA_KEY_CHALLENGE_TOKEN); + mGkPwHandle = bundle.getLong(EXTRA_KEY_GK_PW_HANDLE, INVALID_GK_PW_HANDLE); mClock = clock; mInitMillis = mClock.millis(); } + /** + * Get a bundle which can be used to recreate CredentialModel + */ + @NonNull + public Bundle getBundle() { + final Bundle bundle = new Bundle(); + bundle.putInt(Intent.EXTRA_USER_ID, mUserId); + bundle.putInt(EXTRA_KEY_SENSOR_ID, mSensorId); + bundle.putLong(EXTRA_KEY_CHALLENGE, mChallenge); + bundle.putByteArray(EXTRA_KEY_CHALLENGE_TOKEN, mToken); + bundle.putLong(EXTRA_KEY_GK_PW_HANDLE, mGkPwHandle); + return bundle; + } + /** * Get userId for this credential */ diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollIntroFragment.java b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollIntroFragment.java index 2308f2ef9d1..ecec36f50de 100644 --- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollIntroFragment.java +++ b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollIntroFragment.java @@ -25,7 +25,7 @@ import static com.android.settings.biometrics2.ui.model.FingerprintEnrollIntroSt import static com.google.android.setupdesign.util.DynamicColorPalette.ColorType.ACCENT; import android.app.Activity; -import android.app.admin.DevicePolicyResourcesManager; +import android.app.admin.DevicePolicyManager; import android.content.Context; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; @@ -44,6 +44,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.StringRes; import androidx.fragment.app.Fragment; +import androidx.lifecycle.LiveData; import androidx.lifecycle.ViewModelProvider; import com.android.settings.R; @@ -63,9 +64,6 @@ public class FingerprintEnrollIntroFragment extends Fragment { private static final String TAG = "FingerprintEnrollIntroFragment"; - @NonNull private final ViewModelProvider mViewModelProvider; - @Nullable private final DevicePolicyResourcesManager mDevicePolicyMgrRes; - private FingerprintEnrollIntroViewModel mViewModel = null; private View mView = null; @@ -75,12 +73,8 @@ public class FingerprintEnrollIntroFragment extends Fragment { private TextView mFooterMessage6 = null; @Nullable private PorterDuffColorFilter mIconColorFilter; - public FingerprintEnrollIntroFragment( - @NonNull ViewModelProvider viewModelProvider, - @Nullable DevicePolicyResourcesManager devicePolicyMgrRes) { + public FingerprintEnrollIntroFragment() { super(); - mViewModelProvider = viewModelProvider; - mDevicePolicyMgrRes = devicePolicyMgrRes; } @Nullable @@ -127,15 +121,6 @@ public class FingerprintEnrollIntroFragment extends Fragment { footerTitle2.setText( R.string.security_settings_fingerprint_enroll_introduction_footer_title_2); - return mView; - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - - final Context context = view.getContext(); - final TextView footerLink = mView.findViewById(R.id.footer_learn_more); footerLink.setMovementMethod(LinkMovementMethod.getInstance()); final String footerLinkStr = getContext().getString( @@ -146,18 +131,28 @@ public class FingerprintEnrollIntroFragment extends Fragment { // footer buttons mPrimaryFooterButton = new FooterButton.Builder(context) .setText(R.string.security_settings_fingerprint_enroll_introduction_agree) - .setListener(mViewModel::onNextButtonClick) .setButtonType(FooterButton.ButtonType.OPT_IN) .setTheme(R.style.SudGlifButton_Primary) .build(); mSecondaryFooterButton = new FooterButton.Builder(context) - .setListener(mViewModel::onSkipOrCancelButtonClick) .setButtonType(FooterButton.ButtonType.NEXT) .setTheme(R.style.SudGlifButton_Primary) .build(); getFooterBarMixin().setPrimaryButton(mPrimaryFooterButton); getFooterBarMixin().setSecondaryButton(mSecondaryFooterButton, true /* usePrimaryStyle */); + return mView; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + final Context context = view.getContext(); + + mPrimaryFooterButton.setOnClickListener(mViewModel::onNextButtonClick); + mSecondaryFooterButton.setOnClickListener(mViewModel::onSkipOrCancelButtonClick); + if (mViewModel.canAssumeUdfps()) { mFooterMessage6.setVisibility(View.VISIBLE); mIconShield.setVisibility(View.VISIBLE); @@ -165,7 +160,7 @@ public class FingerprintEnrollIntroFragment extends Fragment { mFooterMessage6.setVisibility(View.GONE); mIconShield.setVisibility(View.GONE); } - mSecondaryFooterButton.setText(getContext(), + mSecondaryFooterButton.setText(context, mViewModel.getEnrollmentRequest().isAfterSuwOrSuwSuggestedAction() ? R.string.security_settings_fingerprint_enroll_introduction_cancel : R.string.security_settings_fingerprint_enroll_introduction_no_thanks); @@ -181,23 +176,37 @@ public class FingerprintEnrollIntroFragment extends Fragment { setHeaderText(getActivity(), R.string.security_settings_fingerprint_enroll_introduction_title); } + observePageStatusLiveDataIfNeed(); + } - mViewModel.getPageStatusLiveData().observe(this, this::updateFooterButtons); + private void observePageStatusLiveDataIfNeed() { + final LiveData statusLiveData = + mViewModel.getPageStatusLiveData(); + final FingerprintEnrollIntroStatus status = statusLiveData.getValue(); + if (status != null && status.hasScrollToBottom()) { + // Do not requireScrollWithButton() again when "I agree" or "Done" button is visible, + // because if we requireScrollWithButton() again, it will become "More" after scroll-up. + return; + } final RequireScrollMixin requireScrollMixin = getLayout() .getMixin(RequireScrollMixin.class); requireScrollMixin.requireScrollWithButton(getActivity(), mPrimaryFooterButton, getMoreButtonTextRes(), mViewModel::onNextButtonClick); - requireScrollMixin.setOnRequireScrollStateChangedListener(scrollNeeded -> { - if (!scrollNeeded) { - mViewModel.setHasScrolledToBottom(); - } - }); + + // Always set true to setHasScrolledToBottom() before registering listener through + // setOnRequireScrollStateChangedListener(), because listener will not be called if first + // scrollNeeded is true + mViewModel.setHasScrolledToBottom(true); + requireScrollMixin.setOnRequireScrollStateChangedListener( + scrollNeeded -> mViewModel.setHasScrolledToBottom(!scrollNeeded)); + statusLiveData.observe(this, this::updateFooterButtons); } @Override public void onAttach(@NonNull Context context) { - mViewModel = mViewModelProvider.get(FingerprintEnrollIntroViewModel.class); + mViewModel = new ViewModelProvider(getActivity()) + .get(FingerprintEnrollIntroViewModel.class); getLifecycle().addObserver(mViewModel); super.onAttach(context); } @@ -232,12 +241,16 @@ public class FingerprintEnrollIntroFragment extends Fragment { private String getDescriptionDisabledByAdmin(@NonNull Context context) { final int defaultStrId = R.string.security_settings_fingerprint_enroll_introduction_message_unlock_disabled; - if (mDevicePolicyMgrRes == null) { + + final DevicePolicyManager devicePolicyManager = getActivity() + .getSystemService(DevicePolicyManager.class); + if (devicePolicyManager != null) { + return devicePolicyManager.getResources().getString(FINGERPRINT_UNLOCK_DISABLED, + () -> context.getString(defaultStrId)); + } else { Log.w(TAG, "getDescriptionDisabledByAdmin, null device policy manager res"); return ""; } - return mDevicePolicyMgrRes.getString(FINGERPRINT_UNLOCK_DISABLED, - () -> context.getString(defaultStrId)); } private void setHeaderText(@NonNull Activity activity, int resId) { diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollmentActivity.java b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollmentActivity.java index e9cf6fd49b1..1f67100afcf 100644 --- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollmentActivity.java +++ b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollmentActivity.java @@ -19,20 +19,19 @@ package com.android.settings.biometrics2.ui.view; import static androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY; import static com.android.settings.biometrics2.factory.BiometricsViewModelFactory.CHALLENGE_GENERATOR; -import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_FAIL_DURING_GENERATE_CHALLENGE; import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK; import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK; +import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_IS_GENERATING_CHALLENGE; +import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_VALID; import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroViewModel.FINGERPRINT_ENROLL_INTRO_ACTION_CONTINUE_ENROLL; import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroViewModel.FINGERPRINT_ENROLL_INTRO_ACTION_DONE_AND_FINISH; import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroViewModel.FINGERPRINT_ENROLL_INTRO_ACTION_SKIP_OR_CANCEL; -import android.app.Activity; import android.app.Application; import android.content.Intent; import android.content.res.ColorStateList; import android.graphics.Color; import android.os.Bundle; -import android.os.SystemClock; import android.util.Log; import androidx.activity.result.ActivityResult; @@ -42,7 +41,6 @@ import androidx.annotation.ColorInt; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.FragmentActivity; -import androidx.fragment.app.FragmentManager; import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.viewmodel.CreationExtras; import androidx.lifecycle.viewmodel.MutableCreationExtras; @@ -51,11 +49,9 @@ import com.android.settings.R; import com.android.settings.Utils; import com.android.settings.biometrics.BiometricEnrollBase; import com.android.settings.biometrics.fingerprint.FingerprintEnrollFindSensor; -import com.android.settings.biometrics.fingerprint.SetupFingerprintEnrollEnrolling; +import com.android.settings.biometrics.fingerprint.SetupFingerprintEnrollFindSensor; import com.android.settings.biometrics2.data.repository.FingerprintRepository; -import com.android.settings.biometrics2.factory.BiometricsFragmentFactory; import com.android.settings.biometrics2.factory.BiometricsViewModelFactory; -import com.android.settings.biometrics2.ui.model.CredentialModel; import com.android.settings.biometrics2.ui.model.EnrollmentRequest; import com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel; import com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.FingerprintChallengeGenerator; @@ -99,15 +95,10 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { mViewModel = viewModelProvider.get(FingerprintEnrollmentViewModel.class); mViewModel.setRequest(new EnrollmentRequest(getIntent(), getApplicationContext())); mViewModel.setSavedInstanceState(savedInstanceState); - getLifecycle().addObserver(mViewModel); mAutoCredentialViewModel = viewModelProvider.get(AutoCredentialViewModel.class); - mAutoCredentialViewModel.setCredentialModel(new CredentialModel(getIntent(), - SystemClock.elapsedRealtimeClock())); - getLifecycle().addObserver(mAutoCredentialViewModel); - - mViewModel.getSetResultLiveData().observe(this, this::onSetActivityResult); - mAutoCredentialViewModel.getActionLiveData().observe(this, this::onCredentialAction); + mAutoCredentialViewModel.setCredentialModel(savedInstanceState, getIntent()); + checkCredential(); // Theme setTheme(mViewModel.getRequest().getTheme()); @@ -116,21 +107,35 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { // fragment setContentView(R.layout.biometric_enrollment_container); - final FragmentManager fragmentManager = getSupportFragmentManager(); - fragmentManager.setFragmentFactory( - new BiometricsFragmentFactory(getApplication(), viewModelProvider)); - final FingerprintEnrollIntroViewModel fingerprintEnrollIntroViewModel = + final FingerprintEnrollIntroViewModel introViewModel = viewModelProvider.get(FingerprintEnrollIntroViewModel.class); - fingerprintEnrollIntroViewModel.setEnrollmentRequest(mViewModel.getRequest()); - fingerprintEnrollIntroViewModel.setUserId(mAutoCredentialViewModel.getUserId()); - fingerprintEnrollIntroViewModel.getActionLiveData().observe( - this, this::observeIntroAction); - final String tag = "FingerprintEnrollIntroFragment"; - fragmentManager.beginTransaction() - .setReorderingAllowed(true) - .add(R.id.fragment_container_view, FingerprintEnrollIntroFragment.class, null, tag) - .commit(); + introViewModel.setEnrollmentRequest(mViewModel.getRequest()); + introViewModel.setUserId(mAutoCredentialViewModel.getUserId()); + if (savedInstanceState == null) { + final String tag = "FingerprintEnrollIntroFragment"; + getSupportFragmentManager().beginTransaction() + .setReorderingAllowed(true) + .add(R.id.fragment_container_view, FingerprintEnrollIntroFragment.class, null, + tag) + .commit(); + } + + // observe LiveData + getLifecycle().addObserver(mViewModel); + mViewModel.getSetResultLiveData().observe(this, this::onSetActivityResult); + + mAutoCredentialViewModel.getGenerateChallengeFailedLiveData().observe(this, + this::onGenerateChallengeFailed); + + // Clear ActionLiveData in FragmentViewModel to prevent getting previous action during + // recreate, like press 'I agree' then press 'back' in FingerprintEnrollFindSensor activity. + introViewModel.clearActionLiveData(); + introViewModel.getActionLiveData().observe(this, this::observeIntroAction); + } + + private void onGenerateChallengeFailed(@NonNull Boolean ignoredBoolean) { + onSetActivityResult(new ActivityResult(RESULT_CANCELED, null)); } private void onSetActivityResult(@NonNull ActivityResult result) { @@ -141,10 +146,10 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { finish(); } - private void onCredentialAction(@NonNull Integer action) { - switch (action) { + private void checkCredential() { + switch (mAutoCredentialViewModel.checkCredential()) { case CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK: { - final Intent intent = mAutoCredentialViewModel.getChooseLockIntent(this, + final Intent intent = mAutoCredentialViewModel.createChooseLockIntent(this, mViewModel.getRequest().isSuw(), mViewModel.getRequest().getSuwExtras()); if (!mViewModel.isWaitingActivityResult().compareAndSet(false, true)) { Log.w(TAG, "chooseLock, fail to set isWaiting flag to true"); @@ -153,7 +158,7 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { return; } case CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK: { - final boolean launched = mAutoCredentialViewModel.getConfirmLockLauncher( + final boolean launched = mAutoCredentialViewModel.createConfirmLockLauncher( this, LAUNCH_CONFIRM_LOCK_ACTIVITY, getString(R.string.security_settings_fingerprint_preference_title) @@ -168,12 +173,9 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { } return; } - case CREDENTIAL_FAIL_DURING_GENERATE_CHALLENGE: { - Log.w(TAG, "observeCredentialLiveData, finish with action:" + action); - if (mViewModel.getRequest().isAfterSuwOrSuwSuggestedAction()) { - setResult(Activity.RESULT_CANCELED); - } - finish(); + case CREDENTIAL_VALID: + case CREDENTIAL_IS_GENERATING_CHALLENGE: { + // Do nothing } } } @@ -186,10 +188,15 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { if (mAutoCredentialViewModel.checkNewCredentialFromActivityResult( isChooseLock, activityResult)) { overridePendingTransition(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out); + } else { + onSetActivityResult(activityResult); } } - private void observeIntroAction(@NonNull Integer action) { + private void observeIntroAction(@Nullable Integer action) { + if (action == null) { + return; + } switch (action) { case FINGERPRINT_ENROLL_INTRO_ACTION_DONE_AND_FINISH: { onSetActivityResult( @@ -207,9 +214,9 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { Log.w(TAG, "startNext, isSuw:" + isSuw + ", fail to set isWaiting flag"); } final Intent intent = new Intent(this, isSuw - ? SetupFingerprintEnrollEnrolling.class + ? SetupFingerprintEnrollFindSensor.class : FingerprintEnrollFindSensor.class); - intent.putExtras(mAutoCredentialViewModel.getCredentialBundle()); + intent.putExtras(mAutoCredentialViewModel.createCredentialIntentExtra()); intent.putExtras(mViewModel.getNextActivityBaseIntentExtras()); mNextActivityLauncher.launch(intent); } @@ -272,5 +279,6 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { protected void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); mViewModel.onSaveInstanceState(outState); + mAutoCredentialViewModel.onSaveInstanceState(outState); } } diff --git a/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModel.java b/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModel.java index b1a7f90e33f..3b7a436fe5c 100644 --- a/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModel.java +++ b/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModel.java @@ -30,20 +30,21 @@ import android.app.Application; import android.content.Context; import android.content.Intent; import android.os.Bundle; +import android.os.SystemClock; import android.util.Log; import androidx.activity.result.ActivityResult; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; import androidx.lifecycle.AndroidViewModel; -import androidx.lifecycle.DefaultLifecycleObserver; -import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.VerifyCredentialResponse; import com.android.settings.biometrics.BiometricUtils; +import com.android.settings.biometrics.BiometricUtils.GatekeeperCredentialNotMatchException; import com.android.settings.biometrics2.data.repository.FingerprintRepository; import com.android.settings.biometrics2.ui.model.CredentialModel; import com.android.settings.password.ChooseLockGeneric; @@ -57,31 +58,40 @@ import java.lang.annotation.RetentionPolicy; * AutoCredentialViewModel which uses CredentialModel to determine next actions for activity, like * start ChooseLockActivity, start ConfirmLockActivity, GenerateCredential, or do nothing. */ -public class AutoCredentialViewModel extends AndroidViewModel implements DefaultLifecycleObserver { +public class AutoCredentialViewModel extends AndroidViewModel { private static final String TAG = "AutoCredentialViewModel"; - private static final boolean DEBUG = true; + + @VisibleForTesting + static final String KEY_CREDENTIAL_MODEL = "credential_model"; + + private static final boolean DEBUG = false; + + /** + * Valid credential, activity does nothing. + */ + public static final int CREDENTIAL_VALID = 0; + + /** + * This credential looks good, but still need to run generateChallenge(). + */ + public static final int CREDENTIAL_IS_GENERATING_CHALLENGE = 1; /** * Need activity to run choose lock */ - public static final int CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK = 1; + public static final int CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK = 2; /** * Need activity to run confirm lock */ - public static final int CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK = 2; - - /** - * Fail to use challenge from hardware generateChallenge(), shall finish activity with proper - * error code - */ - public static final int CREDENTIAL_FAIL_DURING_GENERATE_CHALLENGE = 3; + public static final int CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK = 3; @IntDef(prefix = { "CREDENTIAL_" }, value = { + CREDENTIAL_VALID, + CREDENTIAL_IS_GENERATING_CHALLENGE, CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK, - CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK, - CREDENTIAL_FAIL_DURING_GENERATE_CHALLENGE + CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK }) @Retention(RetentionPolicy.SOURCE) public @interface CredentialAction {} @@ -157,11 +167,10 @@ public class AutoCredentialViewModel extends AndroidViewModel implements Default } } - @NonNull private final LockPatternUtils mLockPatternUtils; @NonNull private final ChallengeGenerator mChallengeGenerator; private CredentialModel mCredentialModel = null; - @NonNull private final MutableLiveData mActionLiveData = + @NonNull private final MutableLiveData mGenerateChallengeFailedLiveData = new MutableLiveData<>(); public AutoCredentialViewModel( @@ -173,51 +182,65 @@ public class AutoCredentialViewModel extends AndroidViewModel implements Default mChallengeGenerator = challengeGenerator; } - public void setCredentialModel(@NonNull CredentialModel credentialModel) { - mCredentialModel = credentialModel; + /** + * Set CredentialModel, the source is coming from savedInstanceState or activity intent + */ + public void setCredentialModel(@Nullable Bundle savedInstanceState, @NonNull Intent intent) { + final Bundle bundle; + if (savedInstanceState != null) { + bundle = savedInstanceState.getBundle(KEY_CREDENTIAL_MODEL); + } else { + bundle = intent.getExtras(); + } + mCredentialModel = new CredentialModel(bundle, SystemClock.elapsedRealtimeClock()); + + if (DEBUG) { + Log.d(TAG, "setCredentialModel " + mCredentialModel + ", savedInstanceState exist:" + + (savedInstanceState != null)); + } } /** - * Observe ActionLiveData for actions about choosing lock, confirming lock, or finishing - * activity + * Handle onSaveInstanceState from activity */ - @NonNull - public LiveData getActionLiveData() { - return mActionLiveData; + public void onSaveInstanceState(@NonNull Bundle outState) { + outState.putBundle(KEY_CREDENTIAL_MODEL, mCredentialModel.getBundle()); } - @Override - public void onCreate(@NonNull LifecycleOwner owner) { - checkCredential(); + @NonNull + public LiveData getGenerateChallengeFailedLiveData() { + return mGenerateChallengeFailedLiveData; } /** * Check credential status for biometric enrollment. */ - private void checkCredential() { + @CredentialAction + public int checkCredential() { if (isValidCredential()) { - return; + return CREDENTIAL_VALID; } final long gkPwHandle = mCredentialModel.getGkPwHandle(); if (isUnspecifiedPassword()) { - mActionLiveData.postValue(CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK); + return CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK; } else if (CredentialModel.isValidGkPwHandle(gkPwHandle)) { generateChallenge(gkPwHandle); + return CREDENTIAL_IS_GENERATING_CHALLENGE; } else { - mActionLiveData.postValue(CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK); + return CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK; } } private void generateChallenge(long gkPwHandle) { mChallengeGenerator.setCallback((sensorId, userId, challenge) -> { - mCredentialModel.setSensorId(sensorId); - mCredentialModel.setChallenge(challenge); try { final byte[] newToken = requestGatekeeperHat(gkPwHandle, challenge, userId); + mCredentialModel.setSensorId(sensorId); + mCredentialModel.setChallenge(challenge); mCredentialModel.setToken(newToken); } catch (IllegalStateException e) { Log.e(TAG, "generateChallenge, IllegalStateException", e); - mActionLiveData.postValue(CREDENTIAL_FAIL_DURING_GENERATE_CHALLENGE); + mGenerateChallengeFailedLiveData.postValue(true); return; } @@ -231,7 +254,7 @@ public class AutoCredentialViewModel extends AndroidViewModel implements Default // Check credential again if (!isValidCredential()) { Log.w(TAG, "generateChallenge, invalid Credential"); - mActionLiveData.postValue(CREDENTIAL_FAIL_DURING_GENERATE_CHALLENGE); + mGenerateChallengeFailedLiveData.postValue(true); } }); mChallengeGenerator.generateChallenge(getUserId()); @@ -282,16 +305,16 @@ public class AutoCredentialViewModel extends AndroidViewModel implements Default final VerifyCredentialResponse response = mLockPatternUtils .verifyGatekeeperPasswordHandle(gkPwHandle, challenge, userId); if (!response.isMatched()) { - throw new IllegalStateException("Unable to request Gatekeeper HAT"); + throw new GatekeeperCredentialNotMatchException("Unable to request Gatekeeper HAT"); } return response.getGatekeeperHAT(); } /** - * Get Credential bundle which will be used to launch next activity. + * Get Credential intent extra which will be used to launch next activity. */ @NonNull - public Bundle getCredentialBundle() { + public Bundle createCredentialIntentExtra() { final Bundle retBundle = new Bundle(); final long gkPwHandle = mCredentialModel.getGkPwHandle(); if (CredentialModel.isValidGkPwHandle(gkPwHandle)) { @@ -311,10 +334,10 @@ public class AutoCredentialViewModel extends AndroidViewModel implements Default } /** - * Get Intent for choosing lock + * Create Intent for choosing lock */ @NonNull - public Intent getChooseLockIntent(@NonNull Context context, boolean isSuw, + public Intent createChooseLockIntent(@NonNull Context context, boolean isSuw, @NonNull Bundle suwExtras) { final Intent intent = BiometricUtils.getChooseLockIntent(context, isSuw, suwExtras); @@ -331,10 +354,10 @@ public class AutoCredentialViewModel extends AndroidViewModel implements Default } /** - * Get ConfirmLockLauncher + * Create ConfirmLockLauncher */ @NonNull - public ChooseLockSettingsHelper getConfirmLockLauncher(@NonNull Activity activity, + public ChooseLockSettingsHelper createConfirmLockLauncher(@NonNull Activity activity, int requestCode, @NonNull String title) { final ChooseLockSettingsHelper.Builder builder = new ChooseLockSettingsHelper.Builder(activity); diff --git a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModel.java b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModel.java index 252a508e630..72611a7c791 100644 --- a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModel.java +++ b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModel.java @@ -144,6 +144,13 @@ public class FingerprintEnrollIntroViewModel extends AndroidViewModel return mPageStatusLiveData; } + /** + * Clear user's action live data + */ + public void clearActionLiveData() { + mActionLiveData.setValue(null); + } + /** * Get user's action live data (like clicking Agree, Skip, or Done) */ @@ -161,8 +168,8 @@ public class FingerprintEnrollIntroViewModel extends AndroidViewModel /** * Update onboarding intro page has scrolled to bottom */ - public void setHasScrolledToBottom() { - mHasScrolledToBottomLiveData.postValue(true); + public void setHasScrolledToBottom(boolean value) { + mHasScrolledToBottomLiveData.postValue(value); } /** diff --git a/src/com/android/settings/deviceinfo/PrivateVolumeForget.java b/src/com/android/settings/deviceinfo/PrivateVolumeForget.java index bd0772c668d..759c7d80997 100644 --- a/src/com/android/settings/deviceinfo/PrivateVolumeForget.java +++ b/src/com/android/settings/deviceinfo/PrivateVolumeForget.java @@ -48,7 +48,7 @@ public class PrivateVolumeForget extends InstrumentedFragment { @Override public int getMetricsCategory() { - return SettingsEnums.DEVICEINFO_STORAGE; + return SettingsEnums.PRIVATE_VOLUME_FORGET; } @Override diff --git a/src/com/android/settings/deviceinfo/PrivateVolumeFormat.java b/src/com/android/settings/deviceinfo/PrivateVolumeFormat.java index dadff3c1dbb..3820eb65334 100644 --- a/src/com/android/settings/deviceinfo/PrivateVolumeFormat.java +++ b/src/com/android/settings/deviceinfo/PrivateVolumeFormat.java @@ -44,7 +44,7 @@ public class PrivateVolumeFormat extends InstrumentedFragment { @Override public int getMetricsCategory() { - return SettingsEnums.DEVICEINFO_STORAGE; + return SettingsEnums.PRIVATE_VOLUME_FORMAT; } @Override diff --git a/src/com/android/settings/deviceinfo/PrivateVolumeUnmount.java b/src/com/android/settings/deviceinfo/PrivateVolumeUnmount.java index 738c3ca520a..dccb12dd4ec 100644 --- a/src/com/android/settings/deviceinfo/PrivateVolumeUnmount.java +++ b/src/com/android/settings/deviceinfo/PrivateVolumeUnmount.java @@ -40,7 +40,7 @@ public class PrivateVolumeUnmount extends InstrumentedFragment { @Override public int getMetricsCategory() { - return SettingsEnums.DEVICEINFO_STORAGE; + return SettingsEnums.PRIVATE_VOLUME_UNMOUNT; } @Override diff --git a/src/com/android/settings/deviceinfo/PublicVolumeSettings.java b/src/com/android/settings/deviceinfo/PublicVolumeSettings.java index d43b2541db7..4fd63af281a 100644 --- a/src/com/android/settings/deviceinfo/PublicVolumeSettings.java +++ b/src/com/android/settings/deviceinfo/PublicVolumeSettings.java @@ -95,7 +95,7 @@ public class PublicVolumeSettings extends SettingsPreferenceFragment { @Override public int getMetricsCategory() { - return SettingsEnums.DEVICEINFO_STORAGE; + return SettingsEnums.PUBLIC_VOLUME_SETTINGS; } @Override diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java index 7a33a6231b2..2faacb749f8 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java +++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java @@ -20,10 +20,8 @@ import android.content.Context; import android.content.Intent; import android.util.SparseIntArray; -import com.android.settings.fuelgauge.batteryusage.BatteryHistEntry; import com.android.settingslib.fuelgauge.Estimate; -import java.util.Map; import java.util.Set; /** @@ -103,12 +101,6 @@ public interface PowerUsageFeatureProvider { */ String getOldEstimateDebugString(String timeRemaining); - /** - * Returns the string to show in the advanced usage battery page when enhanced estimates are - * enabled. This string notifies users that the estimate is using enhanced prediction. - */ - String getAdvancedUsageScreenInfoString(); - /** * Returns a signal to indicate if the device will need to warn the user they may not make it * to their next charging time. @@ -143,11 +135,6 @@ public interface PowerUsageFeatureProvider { */ Intent getResumeChargeIntent(); - /** - * Returns battery history data with corresponding timestamp key. - */ - Map> getBatteryHistory(Context context); - /** * Returns {@link Set} for hidding applications background usage time. */ diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java index 3fe4275fa3c..ff1edecac8c 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java +++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java @@ -24,10 +24,8 @@ import android.util.ArraySet; import android.util.SparseIntArray; import com.android.internal.util.ArrayUtils; -import com.android.settings.fuelgauge.batteryusage.BatteryHistEntry; import com.android.settingslib.fuelgauge.Estimate; -import java.util.Map; import java.util.Set; /** Implementation of {@code PowerUsageFeatureProvider} */ @@ -122,11 +120,6 @@ public class PowerUsageFeatureProviderImpl implements PowerUsageFeatureProvider return null; } - @Override - public String getAdvancedUsageScreenInfoString() { - return null; - } - @Override public boolean getEarlyWarningSignal(Context context, String id) { return false; @@ -158,11 +151,6 @@ public class PowerUsageFeatureProviderImpl implements PowerUsageFeatureProvider return false; } - @Override - public Map> getBatteryHistory(Context context) { - return null; - } - @Override public Set getHideBackgroundUsageTimeSet(Context context) { return new ArraySet<>(); diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java index 738229937db..0eca3a6eca3 100644 --- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java +++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java @@ -167,7 +167,7 @@ public class BatterySaverScheduleSettings extends RadioButtonPickerFragment { @Override public int getMetricsCategory() { - return 0; + return SettingsEnums.FUELGAUGE_BATTERY_SAVER_SCHEDULE; } private void logPowerSaver() { diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java index af67610d2ec..cb870f4d174 100644 --- a/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java +++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java @@ -70,9 +70,6 @@ public class BatteryEntry { } } - public static final int MSG_UPDATE_NAME_ICON = 1; - public static final int MSG_REPORT_FULLY_DRAWN = 2; - private static final String TAG = "BatteryEntry"; private static final String PACKAGE_SYSTEM = "android"; diff --git a/src/com/android/settings/network/InternetResetHelper.java b/src/com/android/settings/network/InternetResetHelper.java index 086ef1b1c5d..7920cca8f61 100644 --- a/src/com/android/settings/network/InternetResetHelper.java +++ b/src/com/android/settings/network/InternetResetHelper.java @@ -21,14 +21,9 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.net.wifi.WifiManager; -import android.os.HandlerThread; -import android.os.Process; -import android.text.TextUtils; import android.util.Log; -import androidx.annotation.UiThread; import androidx.annotation.VisibleForTesting; -import androidx.annotation.WorkerThread; import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleObserver; import androidx.lifecycle.OnLifecycleEvent; @@ -38,14 +33,14 @@ import androidx.preference.PreferenceCategory; import com.android.settingslib.connectivity.ConnectivitySubsystemsRecoveryManager; import com.android.settingslib.utils.HandlerInjector; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; /** * Helper class to restart connectivity for all requested subsystems. */ -public class InternetResetHelper implements LifecycleObserver, - ConnectivitySubsystemsRecoveryManager.RecoveryStatusCallback { +public class InternetResetHelper implements LifecycleObserver { protected static final String TAG = "InternetResetHelper"; public static final long RESTART_TIMEOUT_MS = 15_000; // 15 seconds @@ -61,41 +56,40 @@ public class InternetResetHelper implements LifecycleObserver, protected final IntentFilter mWifiStateFilter; protected final BroadcastReceiver mWifiStateReceiver = new BroadcastReceiver() { @Override - @WorkerThread public void onReceive(Context context, Intent intent) { - if (intent != null && TextUtils.equals(intent.getAction(), - WifiManager.NETWORK_STATE_CHANGED_ACTION)) { - updateWifiStateChange(); - } + updateWifiStateChange(); } }; - protected ConnectivitySubsystemsRecoveryManager mConnectivitySubsystemsRecoveryManager; - protected HandlerThread mWorkerThread; - protected boolean mIsRecoveryReady; - protected boolean mIsWifiReady; + protected RecoveryWorker mRecoveryWorker; + protected boolean mIsWifiReady = true; protected HandlerInjector mHandlerInjector; - protected final Runnable mResumeRunnable = () -> { - resumePreferences(); - }; protected final Runnable mTimeoutRunnable = () -> { - mIsRecoveryReady = true; + Log.w(TAG, "Resume preferences due to connectivity subsystems recovery timed out."); + mRecoveryWorker.clearRecovering(); mIsWifiReady = true; resumePreferences(); }; - public InternetResetHelper(Context context, Lifecycle lifecycle) { + public InternetResetHelper(Context context, Lifecycle lifecycle, + NetworkMobileProviderController mobileNetworkController, + Preference wifiTogglePreferences, + PreferenceCategory connectedWifiEntryPreferenceCategory, + PreferenceCategory firstWifiEntryPreferenceCategory, + PreferenceCategory wifiEntryPreferenceCategory, + Preference resettingPreference) { mContext = context; + mMobileNetworkController = mobileNetworkController; + mWifiTogglePreferences = wifiTogglePreferences; + mWifiNetworkPreferences.add(connectedWifiEntryPreferenceCategory); + mWifiNetworkPreferences.add(firstWifiEntryPreferenceCategory); + mWifiNetworkPreferences.add(wifiEntryPreferenceCategory); + mResettingPreference = resettingPreference; + mHandlerInjector = new HandlerInjector(context.getMainThreadHandler()); mWifiManager = mContext.getSystemService(WifiManager.class); mWifiStateFilter = new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION); - - mWorkerThread = new HandlerThread(TAG - + "{" + Integer.toHexString(System.identityHashCode(this)) + "}", - Process.THREAD_PRIORITY_BACKGROUND); - mWorkerThread.start(); - mConnectivitySubsystemsRecoveryManager = new ConnectivitySubsystemsRecoveryManager( - mContext, mWorkerThread.getThreadHandler()); + mRecoveryWorker = RecoveryWorker.getInstance(mContext, this); if (lifecycle != null) { lifecycle.addObserver(this); @@ -118,72 +112,18 @@ public class InternetResetHelper implements LifecycleObserver, /** @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) */ @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) public void onDestroy() { - mHandlerInjector.removeCallbacks(mResumeRunnable); mHandlerInjector.removeCallbacks(mTimeoutRunnable); - mWorkerThread.quit(); - } - - @Override - @WorkerThread - public void onSubsystemRestartOperationBegin() { - Log.d(TAG, "The connectivity subsystem is starting for recovery."); - } - - @Override - @WorkerThread - public void onSubsystemRestartOperationEnd() { - Log.d(TAG, "The connectivity subsystem is done for recovery."); - if (!mIsRecoveryReady) { - mIsRecoveryReady = true; - mHandlerInjector.postDelayed(mResumeRunnable, 0 /* delayMillis */); - } } @VisibleForTesting - @WorkerThread protected void updateWifiStateChange() { if (!mIsWifiReady && mWifiManager.isWifiEnabled()) { Log.d(TAG, "The Wi-Fi subsystem is done for recovery."); mIsWifiReady = true; - mHandlerInjector.postDelayed(mResumeRunnable, 0 /* delayMillis */); + resumePreferences(); } } - /** - * Sets the resetting preference. - */ - @UiThread - public void setResettingPreference(Preference preference) { - mResettingPreference = preference; - } - - /** - * Sets the mobile network controller. - */ - @UiThread - public void setMobileNetworkController(NetworkMobileProviderController controller) { - mMobileNetworkController = controller; - } - - /** - * Sets the Wi-Fi toggle preference. - */ - @UiThread - public void setWifiTogglePreference(Preference preference) { - mWifiTogglePreferences = preference; - } - - /** - * Adds the Wi-Fi network preference. - */ - @UiThread - public void addWifiNetworkPreference(PreferenceCategory preference) { - if (preference != null) { - mWifiNetworkPreferences.add(preference); - } - } - - @UiThread protected void suspendPreferences() { Log.d(TAG, "Suspend the subsystem preferences"); if (mMobileNetworkController != null) { @@ -201,9 +141,9 @@ public class InternetResetHelper implements LifecycleObserver, } } - @UiThread protected void resumePreferences() { - if (mIsRecoveryReady && mMobileNetworkController != null) { + boolean isRecoveryReady = !mRecoveryWorker.isRecovering(); + if (isRecoveryReady && mMobileNetworkController != null) { Log.d(TAG, "Resume the Mobile Network controller"); mMobileNetworkController.hidePreference(false /* hide */, true /* immediately */); } @@ -214,7 +154,7 @@ public class InternetResetHelper implements LifecycleObserver, pref.setVisible(true); } } - if (mIsRecoveryReady && mIsWifiReady) { + if (isRecoveryReady && mIsWifiReady) { mHandlerInjector.removeCallbacks(mTimeoutRunnable); if (mResettingPreference != null) { Log.d(TAG, "Resume the Resetting preference"); @@ -223,21 +163,99 @@ public class InternetResetHelper implements LifecycleObserver, } } - /** - * Restart connectivity for all requested subsystems. - */ - @UiThread + protected void showResettingAndSendTimeoutChecks() { + suspendPreferences(); + mHandlerInjector.postDelayed(mTimeoutRunnable, RESTART_TIMEOUT_MS); + } + + /** Restart connectivity for all requested subsystems. */ public void restart() { - if (!mConnectivitySubsystemsRecoveryManager.isRecoveryAvailable()) { + if (!mRecoveryWorker.isRecoveryAvailable()) { Log.e(TAG, "The connectivity subsystem is not available to restart."); return; } - - Log.d(TAG, "The connectivity subsystem is restarting for recovery."); - suspendPreferences(); - mIsRecoveryReady = false; + showResettingAndSendTimeoutChecks(); mIsWifiReady = !mWifiManager.isWifiEnabled(); - mHandlerInjector.postDelayed(mTimeoutRunnable, RESTART_TIMEOUT_MS); - mConnectivitySubsystemsRecoveryManager.triggerSubsystemRestart(null /* reason */, this); + mRecoveryWorker.triggerRestart(); + } + + /** Check if the connectivity subsystem is under recovering. */ + public void checkRecovering() { + if (!mRecoveryWorker.isRecovering()) return; + mIsWifiReady = false; + showResettingAndSendTimeoutChecks(); + } + + /** + * This is a singleton class for ConnectivitySubsystemsRecoveryManager worker. + */ + @VisibleForTesting + public static class RecoveryWorker implements + ConnectivitySubsystemsRecoveryManager.RecoveryStatusCallback { + private static final String TAG = "RecoveryWorker"; + private static RecoveryWorker sInstance; + private static WeakReference sCallback; + private static ConnectivitySubsystemsRecoveryManager sRecoveryManager; + private static boolean sIsRecovering; + + /** + * Create a singleton class for ConnectivitySubsystemsRecoveryManager. + * + * @param context The context to use for the content resolver. + * @param callback The callback of {@link InternetResetHelper} object. + * @return an instance of {@link RecoveryWorker} object. + */ + public static RecoveryWorker getInstance(Context context, InternetResetHelper callback) { + sCallback = new WeakReference<>(callback); + if (sInstance != null) return sInstance; + + sInstance = new RecoveryWorker(); + Context appContext = context.getApplicationContext(); + sRecoveryManager = new ConnectivitySubsystemsRecoveryManager(appContext, + appContext.getMainThreadHandler()); + return sInstance; + } + + /** Returns true, If the subsystem service is recovering. */ + public boolean isRecovering() { + return sIsRecovering; + } + + /** Clear the recovering flag. */ + public void clearRecovering() { + sIsRecovering = false; + } + + /** Returns true, If the subsystem service is recovery available. */ + public boolean isRecoveryAvailable() { + return sRecoveryManager.isRecoveryAvailable(); + } + + /** Trigger connectivity recovery for all requested technologies. */ + public boolean triggerRestart() { + if (!isRecoveryAvailable()) { + Log.e(TAG, "The connectivity subsystem is not available to restart."); + return false; + } + sIsRecovering = true; + sRecoveryManager.triggerSubsystemRestart(null /* reason */, sInstance); + Log.d(TAG, "The connectivity subsystem is restarting for recovery."); + return true; + } + + @Override + public void onSubsystemRestartOperationBegin() { + Log.d(TAG, "The connectivity subsystem is starting for recovery."); + sIsRecovering = true; + } + + @Override + public void onSubsystemRestartOperationEnd() { + Log.d(TAG, "The connectivity subsystem is done for recovery."); + sIsRecovering = false; + InternetResetHelper callback = sCallback.get(); + if (callback == null) return; + callback.resumePreferences(); + } } } diff --git a/src/com/android/settings/network/MobileNetworkRepository.java b/src/com/android/settings/network/MobileNetworkRepository.java index f6881380ea8..5de4c726f45 100644 --- a/src/com/android/settings/network/MobileNetworkRepository.java +++ b/src/com/android/settings/network/MobileNetworkRepository.java @@ -88,6 +88,7 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions private Uri mAirplaneModeSettingUri; private MetricsFeatureProvider mMetricsFeatureProvider; private IntentFilter mFilter = new IntentFilter(); + private MobileDataContentObserver mDataContentObserver; private int mPhysicalSlotIndex = SubscriptionManager.INVALID_SIM_SLOT_INDEX; private int mLogicalSlotIndex = SubscriptionManager.INVALID_SIM_SLOT_INDEX; @@ -125,6 +126,13 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions mMobileNetworkInfoDao = mMobileNetworkDatabase.mMobileNetworkInfoDao(); mAirplaneModeObserver = new AirplaneModeObserver(new Handler(Looper.getMainLooper())); mAirplaneModeSettingUri = Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON); + mDataContentObserver = new MobileDataContentObserver( + new Handler(Looper.getMainLooper())); + mDataContentObserver.setOnMobileDataChangedListener(() -> { + mExecutor.execute(() -> { + insertMobileNetworkInfo(context); + }); + }); mFilter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED); mFilter.addAction(SubscriptionManager.ACTION_DEFAULT_SUBSCRIPTION_CHANGED); mFilter.addAction(ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED); @@ -163,6 +171,9 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions public void addRegister(LifecycleOwner lifecycleOwner) { mSubscriptionManager.addOnSubscriptionsChangedListener(mContext.getMainExecutor(), this); mAirplaneModeObserver.register(mContext); + if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + mDataContentObserver.register(mContext, mSubId); + } mContext.registerReceiver(mDataSubscriptionChangedReceiver, mFilter); observeAllSubInfo(lifecycleOwner); observeAllUiccInfo(lifecycleOwner); @@ -170,6 +181,9 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions } public void removeRegister() { + if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + mDataContentObserver.unRegister(mContext); + } mAirplaneModeObserver.unRegister(mContext); if (mDataSubscriptionChangedReceiver != null) { mContext.unregisterReceiver(mDataSubscriptionChangedReceiver); @@ -404,7 +418,7 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions return new MobileNetworkInfoEntity(String.valueOf(mSubId), MobileNetworkUtils.isContactDiscoveryEnabled(context, mSubId), MobileNetworkUtils.isContactDiscoveryVisible(context, mSubId), - MobileNetworkUtils.isMobileDataEnabled(context), + mTelephonyManager.isDataEnabled(), MobileNetworkUtils.isCdmaOptions(context, mSubId), MobileNetworkUtils.isGsmOptions(context, mSubId), MobileNetworkUtils.isWorldMode(context, mSubId), diff --git a/src/com/android/settings/network/NetworkProviderCallsSmsFragment.java b/src/com/android/settings/network/NetworkProviderCallsSmsFragment.java index ab247f1a87c..772db452fcf 100644 --- a/src/com/android/settings/network/NetworkProviderCallsSmsFragment.java +++ b/src/com/android/settings/network/NetworkProviderCallsSmsFragment.java @@ -26,7 +26,6 @@ import com.android.settings.R; import com.android.settings.Utils; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.network.telephony.CallsDefaultSubscriptionController; -import com.android.settings.network.telephony.NetworkProviderBackupCallingPreferenceController; import com.android.settings.network.telephony.NetworkProviderWifiCallingPreferenceController; import com.android.settings.network.telephony.SmsDefaultSubscriptionController; import com.android.settings.search.BaseSearchIndexProvider; @@ -42,9 +41,6 @@ public class NetworkProviderCallsSmsFragment extends DashboardFragment { static final String LOG_TAG = "NetworkProviderCallsSmsFragment"; @VisibleForTesting static final String KEY_PREFERENCE_CATEGORY_CALLING = "provider_model_calling_category"; - @VisibleForTesting - static final String KEY_PREFERENCE_CATEGORY_BACKUP_CALLING = - "provider_model_backup_calling_category"; @VisibleForTesting static final String KEY_PREFERENCE_CALLS= "provider_model_calls_preference"; @@ -67,12 +63,6 @@ public class NetworkProviderCallsSmsFragment extends DashboardFragment { mNetworkProviderWifiCallingPreferenceController.init(getSettingsLifecycle()); controllers.add(mNetworkProviderWifiCallingPreferenceController); - NetworkProviderBackupCallingPreferenceController backupCallingPrefCtrl = - new NetworkProviderBackupCallingPreferenceController(context, - KEY_PREFERENCE_CATEGORY_BACKUP_CALLING); - backupCallingPrefCtrl.init(getSettingsLifecycle()); - controllers.add(backupCallingPrefCtrl); - return controllers; } diff --git a/src/com/android/settings/network/NetworkProviderDownloadedSimListController.java b/src/com/android/settings/network/NetworkProviderDownloadedSimListController.java index abde7c08074..421a8541d09 100644 --- a/src/com/android/settings/network/NetworkProviderDownloadedSimListController.java +++ b/src/com/android/settings/network/NetworkProviderDownloadedSimListController.java @@ -41,6 +41,7 @@ import com.android.settings.network.telephony.MobileNetworkUtils; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.mobile.dataservice.DataServiceUtils; import com.android.settingslib.mobile.dataservice.MobileNetworkInfoEntity; import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity; import com.android.settingslib.mobile.dataservice.UiccInfoEntity; @@ -181,10 +182,7 @@ public class NetworkProviderDownloadedSimListController extends @Override public void onAvailableSubInfoChanged(List subInfoEntityList) { - if ((mSubInfoEntityList != null && - (subInfoEntityList.isEmpty() || !subInfoEntityList.equals(mSubInfoEntityList))) - || (!subInfoEntityList.isEmpty() && mSubInfoEntityList == null)) { - Log.d(TAG, "subInfo list from framework is changed, update the subInfo entity list."); + if (DataServiceUtils.shouldUpdateEntityList(mSubInfoEntityList, subInfoEntityList)) { mSubInfoEntityList = subInfoEntityList; mPreferenceCategory.setVisible(isAvailable()); update(); diff --git a/src/com/android/settings/network/NetworkProviderSettings.java b/src/com/android/settings/network/NetworkProviderSettings.java index b622a3c308d..7b7cdca37d1 100644 --- a/src/com/android/settings/network/NetworkProviderSettings.java +++ b/src/com/android/settings/network/NetworkProviderSettings.java @@ -337,6 +337,8 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment addConnectedEthernetNetworkController(); addWifiSwitchPreferenceController(); mWifiStatusMessagePreference = findPreference(PREF_KEY_WIFI_STATUS_MESSAGE); + + checkConnectivityRecovering(); } private void updateAirplaneModeMsgPreference(boolean visible) { @@ -382,6 +384,17 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment mWifiSwitchPreferenceController.displayPreference(getPreferenceScreen()); } + private void checkConnectivityRecovering() { + mInternetResetHelper = new InternetResetHelper(getContext(), getLifecycle(), + mNetworkMobileProviderController, + findPreference(WifiSwitchPreferenceController.KEY), + mConnectedWifiEntryPreferenceCategory, + mFirstWifiEntryPreferenceCategory, + mWifiEntryPreferenceCategory, + mResetInternetPreference); + mInternetResetHelper.checkRecovering(); + } + @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); @@ -1455,16 +1468,6 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment EventLog.writeEvent(0x534e4554, "252995826", UserHandle.myUserId(), "User is a guest"); return; } - if (mInternetResetHelper == null) { - mInternetResetHelper = new InternetResetHelper(getContext(), getLifecycle()); - mInternetResetHelper.setResettingPreference(mResetInternetPreference); - mInternetResetHelper.setMobileNetworkController(mNetworkMobileProviderController); - mInternetResetHelper.setWifiTogglePreference( - findPreference(WifiSwitchPreferenceController.KEY)); - mInternetResetHelper.addWifiNetworkPreference(mConnectedWifiEntryPreferenceCategory); - mInternetResetHelper.addWifiNetworkPreference(mFirstWifiEntryPreferenceCategory); - mInternetResetHelper.addWifiNetworkPreference(mWifiEntryPreferenceCategory); - } mInternetResetHelper.restart(); } diff --git a/src/com/android/settings/network/ResetNetworkOperationBuilder.java b/src/com/android/settings/network/ResetNetworkOperationBuilder.java index 3b5c9bce646..3583d06b2b4 100644 --- a/src/com/android/settings/network/ResetNetworkOperationBuilder.java +++ b/src/com/android/settings/network/ResetNetworkOperationBuilder.java @@ -28,8 +28,10 @@ import android.net.wifi.WifiManager; import android.net.wifi.p2p.WifiP2pManager; import android.os.Looper; import android.os.RecoverySystem; +import android.os.SystemClock; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; +import android.util.Log; import com.android.settings.network.apn.ApnSettings; @@ -43,6 +45,10 @@ import java.util.function.Consumer; */ public class ResetNetworkOperationBuilder { + private static final String TAG = "ResetNetworkOpBuilder"; + + private static final boolean DRY_RUN = false; + private Context mContext; private List mResetSequence = new ArrayList(); @@ -127,10 +133,17 @@ public class ResetNetworkOperationBuilder { public ResetNetworkOperationBuilder resetEsim(String callerPackage, Consumer resultCallback) { Runnable runnable = () -> { - Boolean wipped = RecoverySystem.wipeEuiccData(mContext, callerPackage); - if (resultCallback != null) { - resultCallback.accept(wipped); + long startTime = SystemClock.elapsedRealtime(); + + if (!DRY_RUN) { + Boolean wipped = RecoverySystem.wipeEuiccData(mContext, callerPackage); + if (resultCallback != null) { + resultCallback.accept(wipped); + } } + + long endTime = SystemClock.elapsedRealtime(); + Log.i(TAG, "Reset eSIM, takes " + (endTime - startTime) + " ms"); }; mResetSequence.add(runnable); return this; @@ -179,14 +192,21 @@ public class ResetNetworkOperationBuilder { */ public ResetNetworkOperationBuilder resetApn(int subscriptionId) { Runnable runnable = () -> { + long startTime = SystemClock.elapsedRealtime(); + Uri uri = Uri.parse(ApnSettings.RESTORE_CARRIERS_URI); if (SubscriptionManager.isUsableSubscriptionId(subscriptionId)) { uri = Uri.withAppendedPath(uri, "subId/" + String.valueOf(subscriptionId)); } - ContentResolver resolver = mContext.getContentResolver(); - resolver.delete(uri, null, null); + if (!DRY_RUN) { + ContentResolver resolver = mContext.getContentResolver(); + resolver.delete(uri, null, null); + } + + long endTime = SystemClock.elapsedRealtime(); + Log.i(TAG, "Reset " + uri + ", takes " + (endTime - startTime) + " ms"); }; mResetSequence.add(runnable); return this; @@ -205,7 +225,14 @@ public class ResetNetworkOperationBuilder { if (service == null) { return; } - Runnable runnable = () -> serviceAccess.accept(service); + Runnable runnable = () -> { + long startTime = SystemClock.elapsedRealtime(); + if (!DRY_RUN) { + serviceAccess.accept(service); + } + long endTime = SystemClock.elapsedRealtime(); + Log.i(TAG, "Reset " + serviceName + ", takes " + (endTime - startTime) + " ms"); + }; mResetSequence.add(runnable); } } diff --git a/src/com/android/settings/network/telephony/BackupCallingPreferenceController.java b/src/com/android/settings/network/telephony/BackupCallingPreferenceController.java index 4f64399f524..3db6dfe87e8 100644 --- a/src/com/android/settings/network/telephony/BackupCallingPreferenceController.java +++ b/src/com/android/settings/network/telephony/BackupCallingPreferenceController.java @@ -38,6 +38,7 @@ import java.util.Objects; /** * Preference controller for "Backup Calling" + * Deprecated ToDo: b/260059444 remove it next version **/ public class BackupCallingPreferenceController extends TelephonyTogglePreferenceController { diff --git a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java index 69951bf43a0..8543770dc0d 100644 --- a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java +++ b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java @@ -16,14 +16,19 @@ package com.android.settings.network.telephony; +import static androidx.lifecycle.Lifecycle.Event.ON_START; +import static androidx.lifecycle.Lifecycle.Event.ON_STOP; + import android.content.Context; import android.os.Handler; import android.os.Looper; -import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.text.TextUtils; +import androidx.lifecycle.LifecycleObserver; +import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.OnLifecycleEvent; import androidx.annotation.VisibleForTesting; import androidx.fragment.app.FragmentManager; import androidx.preference.Preference; @@ -32,16 +37,22 @@ import androidx.preference.SwitchPreference; import com.android.settings.R; import com.android.settings.network.MobileDataContentObserver; +import com.android.settings.network.MobileNetworkRepository; import com.android.settings.wifi.WifiPickerTrackerHelper; -import com.android.settingslib.core.lifecycle.LifecycleObserver; -import com.android.settingslib.core.lifecycle.events.OnStart; -import com.android.settingslib.core.lifecycle.events.OnStop; +import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.mobile.dataservice.DataServiceUtils; +import com.android.settingslib.mobile.dataservice.MobileNetworkInfoEntity; +import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity; +import com.android.settingslib.mobile.dataservice.UiccInfoEntity; + +import java.util.ArrayList; +import java.util.List; /** * Preference controller for "Mobile data" */ public class MobileDataPreferenceController extends TelephonyTogglePreferenceController - implements LifecycleObserver, OnStart, OnStop { + implements LifecycleObserver, MobileNetworkRepository.MobileNetworkCallback { private static final String DIALOG_TAG = "MobileDataDialog"; @@ -56,12 +67,26 @@ public class MobileDataPreferenceController extends TelephonyTogglePreferenceCon boolean mNeedDialog; private WifiPickerTrackerHelper mWifiPickerTrackerHelper; + protected MobileNetworkRepository mMobileNetworkRepository; + protected LifecycleOwner mLifecycleOwner; + private List mSubscriptionInfoEntityList = new ArrayList<>(); + private List mMobileNetworkInfoEntityList = new ArrayList<>(); + private int mDefaultSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; + SubscriptionInfoEntity mSubscriptionInfoEntity; + MobileNetworkInfoEntity mMobileNetworkInfoEntity; - public MobileDataPreferenceController(Context context, String key) { + public MobileDataPreferenceController(Context context, String key, Lifecycle lifecycle, + LifecycleOwner lifecycleOwner, int subId) { super(context, key); + mSubId = subId; mSubscriptionManager = context.getSystemService(SubscriptionManager.class); mDataContentObserver = new MobileDataContentObserver(new Handler(Looper.getMainLooper())); mDataContentObserver.setOnMobileDataChangedListener(() -> updateState(mPreference)); + mMobileNetworkRepository = MobileNetworkRepository.createBySubId(context, this, mSubId); + mLifecycleOwner = lifecycleOwner; + if (lifecycle != null) { + lifecycle.addObserver(this); + } } @Override @@ -77,18 +102,14 @@ public class MobileDataPreferenceController extends TelephonyTogglePreferenceCon mPreference = screen.findPreference(getPreferenceKey()); } - @Override + @OnLifecycleEvent(ON_START) public void onStart() { - if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { - mDataContentObserver.register(mContext, mSubId); - } + mMobileNetworkRepository.addRegister(mLifecycleOwner); } - @Override + @OnLifecycleEvent(ON_STOP) public void onStop() { - if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { - mDataContentObserver.unRegister(mContext); - } + mMobileNetworkRepository.removeRegister(); } @Override @@ -122,39 +143,47 @@ public class MobileDataPreferenceController extends TelephonyTogglePreferenceCon @Override public boolean isChecked() { - mTelephonyManager = getTelephonyManager(); - return mTelephonyManager.isDataEnabled(); + return mMobileNetworkInfoEntity == null ? false + : mMobileNetworkInfoEntity.isMobileDataEnabled; } @Override public void updateState(Preference preference) { super.updateState(preference); - if (isOpportunistic()) { - preference.setEnabled(false); - preference.setSummary(R.string.mobile_data_settings_summary_auto_switch); - } else { - preference.setEnabled(true); - preference.setSummary(R.string.mobile_data_settings_summary); + mPreference = (SwitchPreference) preference; + update(); + } + + private void update() { + + if (mSubscriptionInfoEntity == null || mPreference == null) { + return; } - if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { - preference.setSelectable(false); - preference.setSummary(R.string.mobile_data_settings_summary_unavailable); + mPreference.setChecked(isChecked()); + if (mSubscriptionInfoEntity.isOpportunistic) { + mPreference.setEnabled(false); + mPreference.setSummary(R.string.mobile_data_settings_summary_auto_switch); } else { - preference.setSelectable(true); + mPreference.setEnabled(true); + mPreference.setSummary(R.string.mobile_data_settings_summary); + } + if (!mSubscriptionInfoEntity.isValidSubscription) { + mPreference.setSelectable(false); + mPreference.setSummary(R.string.mobile_data_settings_summary_unavailable); + } else { + mPreference.setSelectable(true); } } - private boolean isOpportunistic() { - SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(mSubId); - return info != null && info.isOpportunistic(); - } - - public void init(FragmentManager fragmentManager, int subId) { + public void init(FragmentManager fragmentManager, int subId, + SubscriptionInfoEntity subInfoEntity, MobileNetworkInfoEntity networkInfoEntity) { mFragmentManager = fragmentManager; mSubId = subId; mTelephonyManager = null; mTelephonyManager = getTelephonyManager(); + mSubscriptionInfoEntity = subInfoEntity; + mMobileNetworkInfoEntity = networkInfoEntity; } private TelephonyManager getTelephonyManager() { @@ -179,9 +208,8 @@ public class MobileDataPreferenceController extends TelephonyTogglePreferenceCon final boolean enableData = !isChecked(); mTelephonyManager = getTelephonyManager(); final boolean isMultiSim = (mTelephonyManager.getActiveModemCount() > 1); - final int defaultSubId = mSubscriptionManager.getDefaultDataSubscriptionId(); - final boolean needToDisableOthers = mSubscriptionManager - .isActiveSubscriptionId(defaultSubId) && defaultSubId != mSubId; + final boolean needToDisableOthers = mDefaultSubId != mSubId; + if (enableData && isMultiSim && needToDisableOthers) { mDialogType = MobileDataDialogFragment.TYPE_MULTI_SIM_DIALOG; return true; @@ -194,4 +222,62 @@ public class MobileDataPreferenceController extends TelephonyTogglePreferenceCon mSubId); dialogFragment.show(mFragmentManager, DIALOG_TAG); } + + @VisibleForTesting + public void setSubscriptionInfoEntity(SubscriptionInfoEntity subscriptionInfoEntity) { + mSubscriptionInfoEntity = subscriptionInfoEntity; + } + + @VisibleForTesting + public void setMobileNetworkInfoEntity(MobileNetworkInfoEntity mobileNetworkInfoEntity) { + mMobileNetworkInfoEntity = mobileNetworkInfoEntity; + } + + @Override + public void onAirplaneModeChanged(boolean airplaneModeEnabled) { + } + + @Override + public void onAvailableSubInfoChanged(List subInfoEntityList) { + } + + @Override + public void onActiveSubInfoChanged(List subInfoEntityList) { + if (DataServiceUtils.shouldUpdateEntityList(mSubscriptionInfoEntityList, + subInfoEntityList)) { + mSubscriptionInfoEntityList = subInfoEntityList; + mSubscriptionInfoEntityList.forEach(entity -> { + if (Integer.parseInt(entity.subId) == mSubId) { + mSubscriptionInfoEntity = entity; + } + }); + if (mSubscriptionInfoEntity != null + && mSubscriptionInfoEntity.isDefaultDataSubscription) { + mDefaultSubId = Integer.parseInt(mSubscriptionInfoEntity.subId); + } + update(); + refreshSummary(mPreference); + } + } + + @Override + public void onAllUiccInfoChanged(List uiccInfoEntityList) { + } + + @Override + public void onAllMobileNetworkInfoChanged( + List mobileNetworkInfoEntityList) { + if (DataServiceUtils.shouldUpdateEntityList(mMobileNetworkInfoEntityList, + mobileNetworkInfoEntityList)) { + mMobileNetworkInfoEntityList = mobileNetworkInfoEntityList; + mMobileNetworkInfoEntityList.forEach(entity -> { + if (Integer.parseInt(entity.subId) == mSubId) { + mMobileNetworkInfoEntity = entity; + update(); + refreshSummary(mPreference); + return; + } + }); + } + } } diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java index ae83c43c5bc..88c365654e5 100644 --- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java +++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java @@ -79,6 +79,7 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme private static final String KEY_ROAMING_PREF = "button_roaming_key"; private static final String KEY_CALLS_PREF = "calls_preference"; private static final String KEY_SMS_PREF = "sms_preference"; + private static final String KEY_MOBILE_DATA_PREF = "mobile_data_enable"; //String keys for preference lookup private static final String BUTTON_CDMA_SYSTEM_SELECT_KEY = "cdma_system_select_key"; @@ -175,7 +176,9 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme new CallsDefaultSubscriptionController(context, KEY_CALLS_PREF, getSettingsLifecycle(), this), new SmsDefaultSubscriptionController(context, KEY_SMS_PREF, getSettingsLifecycle(), - this)); + this), + new MobileDataPreferenceController(context, KEY_MOBILE_DATA_PREF, + getSettingsLifecycle(), this, mSubId)); } @Override @@ -231,10 +234,16 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme REQUEST_CODE_DELETE_SUBSCRIPTION); use(DisableSimFooterPreferenceController.class).init(mSubId); use(NrDisabledInDsdsFooterPreferenceController.class).init(mSubId); - use(MobileDataPreferenceController.class).init(getFragmentManager(), mSubId); - use(MobileDataPreferenceController.class).setWifiPickerTrackerHelper( - new WifiPickerTrackerHelper(getSettingsLifecycle(), context, - null /* WifiPickerTrackerCallback */)); + + final MobileDataPreferenceController mobileDataPreferenceController = + use(MobileDataPreferenceController.class); + if (mobileDataPreferenceController != null) { + mobileDataPreferenceController.init(getFragmentManager(), mSubId, + mSubscriptionInfoEntity, mMobileNetworkInfoEntity); + mobileDataPreferenceController.setWifiPickerTrackerHelper( + new WifiPickerTrackerHelper(getSettingsLifecycle(), context, + null /* WifiPickerTrackerCallback */)); + } final RoamingPreferenceController roamingPreferenceController = use(RoamingPreferenceController.class); @@ -269,11 +278,6 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme final VideoCallingPreferenceController videoCallingPreferenceController = use(VideoCallingPreferenceController.class).init(mSubId); - final BackupCallingPreferenceController crossSimCallingPreferenceController = - use(BackupCallingPreferenceController.class).init(mSubId); - use(CallingPreferenceCategoryController.class).setChildren( - Arrays.asList(wifiCallingPreferenceController, videoCallingPreferenceController, - crossSimCallingPreferenceController)); use(Enhanced4gLtePreferenceController.class).init(mSubId) .addListener(videoCallingPreferenceController); use(Enhanced4gCallingPreferenceController.class).init(mSubId) diff --git a/src/com/android/settings/network/telephony/NetworkProviderBackupCallingGroup.java b/src/com/android/settings/network/telephony/NetworkProviderBackupCallingGroup.java index 58dd18f2c62..3659f651336 100644 --- a/src/com/android/settings/network/telephony/NetworkProviderBackupCallingGroup.java +++ b/src/com/android/settings/network/telephony/NetworkProviderBackupCallingGroup.java @@ -49,6 +49,7 @@ import java.util.Map; /** * Preference controller for "Backup Calling" + * Deprecated ToDo: b/260059444 remove it next version **/ public class NetworkProviderBackupCallingGroup extends TelephonyTogglePreferenceController implements LifecycleObserver, diff --git a/src/com/android/settings/network/telephony/NetworkProviderBackupCallingPreferenceController.java b/src/com/android/settings/network/telephony/NetworkProviderBackupCallingPreferenceController.java index 5c336efc507..c10bfb83d7c 100644 --- a/src/com/android/settings/network/telephony/NetworkProviderBackupCallingPreferenceController.java +++ b/src/com/android/settings/network/telephony/NetworkProviderBackupCallingPreferenceController.java @@ -32,6 +32,7 @@ import java.util.List; /** * Preference controller for "Backup Calling" summary list + * Deprecated ToDo: b/260059444 remove it next version */ public class NetworkProviderBackupCallingPreferenceController extends BasePreferenceController implements LifecycleObserver { diff --git a/tests/componenttests/Android.bp b/tests/componenttests/Android.bp index 77ee1648d01..5c03aa97fb3 100644 --- a/tests/componenttests/Android.bp +++ b/tests/componenttests/Android.bp @@ -26,6 +26,7 @@ android_test { "androidx.test.runner", "androidx.test.rules", "androidx.test.ext.junit", + "mockito-target", ], test_suites: ["device-tests"], diff --git a/tests/componenttests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerComponentTest.java b/tests/componenttests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerComponentTest.java index 78a2c92f329..df3dd2effd2 100644 --- a/tests/componenttests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerComponentTest.java +++ b/tests/componenttests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerComponentTest.java @@ -20,6 +20,8 @@ import static com.android.settings.testutils.CommonUtils.set_wifi_enabled; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.mock; + import android.app.Instrumentation; import android.content.Context; import android.content.Intent; @@ -31,6 +33,7 @@ import android.util.Log; import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; +import androidx.lifecycle.LifecycleOwner; import androidx.test.core.app.ActivityScenario; import androidx.test.ext.junit.rules.ActivityScenarioRule; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -40,6 +43,9 @@ import androidx.test.platform.app.InstrumentationRegistry; import com.android.settings.Settings; import com.android.settings.testutils.CommonUtils; import com.android.settings.testutils.UiUtils; +import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.mobile.dataservice.MobileNetworkInfoEntity; +import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity; import org.junit.After; import org.junit.Assume; @@ -47,6 +53,8 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; import java.io.IOException; import java.net.URL; @@ -54,6 +62,12 @@ import java.net.URL; @RunWith(AndroidJUnit4.class) @SmallTest public class MobileDataPreferenceControllerComponentTest { + + @Mock + private Lifecycle mLifecycle; + @Mock + private LifecycleOwner mLifecycleOwner; + public static final int TIMEOUT = 2000; private static int sSubscriptionId = 2; public final String TAG = this.getClass().getName(); @@ -116,9 +130,11 @@ public class MobileDataPreferenceControllerComponentTest { try { URL url = new URL("https://www.google.net"); MobileDataPreferenceController controller = new MobileDataPreferenceController( - mInstrumentation.getTargetContext(), "mobile_data"); + mInstrumentation.getTargetContext(), "mobile_data", mLifecycle, + mLifecycleOwner, sSubscriptionId); FragmentManager manager = ((FragmentActivity) activity).getSupportFragmentManager(); - controller.init(manager, sSubscriptionId); + controller.init(manager, sSubscriptionId, mock(SubscriptionInfoEntity.class), mock( + MobileNetworkInfoEntity.class)); // Make sure mobile network can connect at first. assertThat(UiUtils.waitUntilCondition(1000, diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettingsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettingsTest.java index 270a6252ef4..dc9cac40bdd 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettingsTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettingsTest.java @@ -1,5 +1,6 @@ package com.android.settings.fuelgauge.batterysaver; +import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -82,6 +83,12 @@ public final class BatterySaverScheduleSettingsTest { verifySchedule("key_battery_saver_percentage", expectedPercentage); } + @Test + public void getMetricsCategory_returnExpectedResult() { + assertThat(mBatterySaverScheduleSettings.getMetricsCategory()) + .isEqualTo(SettingsEnums.FUELGAUGE_BATTERY_SAVER_SCHEDULE); + } + private void setSchedule(int scheduleType, int schedulePercentage) { Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AUTOMATIC_POWER_SAVE_MODE, scheduleType); diff --git a/tests/unit/src/com/android/settings/biometrics2/ui/model/CredentialModelTest.java b/tests/unit/src/com/android/settings/biometrics2/ui/model/CredentialModelTest.java new file mode 100644 index 00000000000..1fac8b5b084 --- /dev/null +++ b/tests/unit/src/com/android/settings/biometrics2/ui/model/CredentialModelTest.java @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.biometrics2.ui.model; + +import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_KEY_CHALLENGE; +import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_KEY_SENSOR_ID; +import static com.android.settings.biometrics2.ui.model.CredentialModel.INVALID_CHALLENGE; +import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; + +import android.annotation.NonNull; +import android.content.Intent; +import android.os.Bundle; +import android.os.SystemClock; + +import androidx.annotation.Nullable; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.android.settings.password.ChooseLockSettingsHelper; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.time.Clock; +import java.util.Arrays; +import java.util.Set; + +@RunWith(AndroidJUnit4.class) +public class CredentialModelTest { + + private final Clock mClock = SystemClock.elapsedRealtimeClock(); + + public static Bundle newCredentialModelIntentExtras(int userId, long challenge, int sensorId, + @Nullable byte[] token, long gkPwHandle) { + final Bundle bundle = new Bundle(); + bundle.putInt(Intent.EXTRA_USER_ID, userId); + bundle.putInt(EXTRA_KEY_SENSOR_ID, sensorId); + bundle.putLong(EXTRA_KEY_CHALLENGE, challenge); + bundle.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token); + bundle.putLong(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle); + return bundle; + } + + public static Bundle newValidTokenCredentialIntentExtras(int userId) { + return newCredentialModelIntentExtras(userId, 1L, 1, new byte[] { 0 }, 0L); + } + + public static Bundle newInvalidChallengeCredentialIntentExtras(int userId) { + return newCredentialModelIntentExtras(userId, INVALID_CHALLENGE, 1, null, 0L); + } + + public static Bundle newGkPwHandleCredentialIntentExtras(int userId, long gkPwHandle) { + return newCredentialModelIntentExtras(userId, INVALID_CHALLENGE, 1, null, gkPwHandle); + } + + private static void checkBundleLongValue(@NonNull Bundle bundle1, @NonNull Bundle bundle2, + @NonNull String key) { + if (!bundle1.containsKey(key)) { + return; + } + final int value1 = bundle1.getInt(key); + final int value2 = bundle2.getInt(key); + assertWithMessage("bundle not match, key:" + key + ", value1:" + value1 + ", value2:" + + value2).that(value1).isEqualTo(value2); + } + + private static void checkBundleIntValue(@NonNull Bundle bundle1, @NonNull Bundle bundle2, + @NonNull String key) { + if (!bundle1.containsKey(key)) { + return; + } + final long value1 = bundle1.getLong(key); + final long value2 = bundle2.getLong(key); + assertWithMessage("bundle not match, key:" + key + ", value1:" + value1 + ", value2:" + + value2).that(value1).isEqualTo(value2); + } + + private static void checkBundleByteArrayValue(@NonNull Bundle bundle1, @NonNull Bundle bundle2, + @NonNull String key) { + if (!bundle1.containsKey(key)) { + return; + } + final byte[] value1 = bundle1.getByteArray(key); + final byte[] value2 = bundle2.getByteArray(key); + final String errMsg = "bundle not match, key:" + key + ", value1:" + Arrays.toString(value1) + + ", value2:" + Arrays.toString(value2); + if (value1 == null) { + assertWithMessage(errMsg).that(value2).isNull(); + } else { + assertWithMessage(errMsg).that(value1.length).isEqualTo(value2.length); + for (int i = 0; i < value1.length; ++i) { + assertWithMessage(errMsg).that(value1[i]).isEqualTo(value2[i]); + } + } + } + + public static void verifySameCredentialModels(@NonNull CredentialModel model1, + @NonNull CredentialModel model2) { + + assertThat(model1.getUserId()).isEqualTo(model2.getUserId()); + assertThat(model1.getSensorId()).isEqualTo(model2.getSensorId()); + assertThat(model1.getChallenge()).isEqualTo(model2.getChallenge()); + assertThat(model1.getGkPwHandle()).isEqualTo(model2.getGkPwHandle()); + + final byte[] token1 = model1.getToken(); + final byte[] token2 = model2.getToken(); + if (token1 == null) { + assertThat(token2).isNull(); + } else { + assertThat(token2).isNotNull(); + assertThat(token1.length).isEqualTo(token2.length); + for (int i = 0; i < token1.length; ++i) { + assertThat(token1[i]).isEqualTo(token2[i]); + } + } + + final Bundle bundle1 = model1.getBundle(); + final Bundle bundle2 = model2.getBundle(); + final Set keySet1 = bundle1.keySet(); + assertThat(keySet1.equals(bundle2.keySet())).isTrue(); + checkBundleIntValue(bundle1, bundle2, Intent.EXTRA_USER_ID); + checkBundleIntValue(bundle1, bundle2, EXTRA_KEY_SENSOR_ID); + checkBundleLongValue(bundle1, bundle2, EXTRA_KEY_CHALLENGE); + checkBundleByteArrayValue(bundle1, bundle2, EXTRA_KEY_CHALLENGE); + checkBundleLongValue(bundle1, bundle2, EXTRA_KEY_GK_PW_HANDLE); + } + + @Test + public void sameValueFromBundle() { + final Bundle bundle = newCredentialModelIntentExtras(1234, 6677L, 1, + new byte[] { 33, 44, 55 }, 987654321); + + final CredentialModel model1 = new CredentialModel(bundle, mClock); + final CredentialModel model2 = new CredentialModel(model1.getBundle(), mClock); + + verifySameCredentialModels(model1, model2); + } + + @Test + public void sameValueFromBundle_nullToken() { + final Bundle bundle = newCredentialModelIntentExtras(22, 33L, 1, null, 21L); + + final CredentialModel model1 = new CredentialModel(bundle, mClock); + final CredentialModel model2 = new CredentialModel(model1.getBundle(), mClock); + + verifySameCredentialModels(model1, model2); + } +} diff --git a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModelTest.java b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModelTest.java index 7a13875a8fa..3abbca6cb68 100644 --- a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModelTest.java +++ b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModelTest.java @@ -24,12 +24,24 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_KEY_CHALLENGE; import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_KEY_SENSOR_ID; import static com.android.settings.biometrics2.ui.model.CredentialModel.INVALID_CHALLENGE; +import static com.android.settings.biometrics2.ui.model.CredentialModel.INVALID_GK_PW_HANDLE; import static com.android.settings.biometrics2.ui.model.CredentialModel.INVALID_SENSOR_ID; +import static com.android.settings.biometrics2.ui.model.CredentialModel.isValidGkPwHandle; +import static com.android.settings.biometrics2.ui.model.CredentialModel.isValidToken; +import static com.android.settings.biometrics2.ui.model.CredentialModelTest.newCredentialModelIntentExtras; +import static com.android.settings.biometrics2.ui.model.CredentialModelTest.newGkPwHandleCredentialIntentExtras; +import static com.android.settings.biometrics2.ui.model.CredentialModelTest.newInvalidChallengeCredentialIntentExtras; +import static com.android.settings.biometrics2.ui.model.CredentialModelTest.newValidTokenCredentialIntentExtras; import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK; import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK; +import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_IS_GENERATING_CHALLENGE; +import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_VALID; import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.ChallengeGenerator; import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CredentialAction; import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.GenerateChallengeCallback; +import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.KEY_CREDENTIAL_MODEL; +import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN; +import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE; import static com.google.common.truth.Truth.assertThat; @@ -38,20 +50,17 @@ import static org.mockito.Mockito.when; import android.annotation.NonNull; import android.app.Activity; import android.content.Intent; -import android.os.SystemClock; +import android.os.Bundle; import android.os.UserHandle; import androidx.activity.result.ActivityResult; import androidx.annotation.Nullable; -import androidx.lifecycle.LifecycleOwner; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.VerifyCredentialResponse; -import com.android.settings.biometrics2.ui.model.CredentialModel; import com.android.settings.password.ChooseLockPattern; -import com.android.settings.password.ChooseLockSettingsHelper; import com.android.settings.testutils.InstantTaskExecutorRule; import org.junit.Before; @@ -68,248 +77,326 @@ public class AutoCredentialViewModelTest { @Rule public final MockitoRule mockito = MockitoJUnit.rule(); @Rule public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule(); - @Mock private LifecycleOwner mLifecycleOwner; @Mock private LockPatternUtils mLockPatternUtils; private TestChallengeGenerator mChallengeGenerator = null; - private AutoCredentialViewModel mAutoCredentialViewModel; + private AutoCredentialViewModel mViewModel; @Before public void setUp() { mChallengeGenerator = new TestChallengeGenerator(); - mAutoCredentialViewModel = new AutoCredentialViewModel( + mViewModel = new AutoCredentialViewModel( ApplicationProvider.getApplicationContext(), mLockPatternUtils, mChallengeGenerator); } - private CredentialModel newCredentialModel(int userId, long challenge, - @Nullable byte[] token, long gkPwHandle) { - final Intent intent = new Intent(); - intent.putExtra(Intent.EXTRA_USER_ID, userId); - intent.putExtra(EXTRA_KEY_SENSOR_ID, 1); - intent.putExtra(EXTRA_KEY_CHALLENGE, challenge); - intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token); - intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle); - return new CredentialModel(intent, SystemClock.elapsedRealtimeClock()); - } - - private CredentialModel newValidTokenCredentialModel(int userId) { - return newCredentialModel(userId, 1L, new byte[] { 0 }, 0L); - } - - private CredentialModel newInvalidChallengeCredentialModel(int userId) { - return newCredentialModel(userId, INVALID_CHALLENGE, null, 0L); - } - - private CredentialModel newGkPwHandleCredentialModel(int userId, long gkPwHandle) { - return newCredentialModel(userId, INVALID_CHALLENGE, null, gkPwHandle); - } - - private void verifyNothingHappen() { - assertThat(mAutoCredentialViewModel.getActionLiveData().getValue()).isNull(); - } - - private void verifyOnlyActionLiveData(@CredentialAction int action) { - final Integer value = mAutoCredentialViewModel.getActionLiveData().getValue(); - assertThat(value).isEqualTo(action); - } - - private void setupGenerateTokenFlow(long gkPwHandle, int userId, int newSensorId, - long newChallenge) { + private void setupGenerateChallenge(int userId, int newSensorId, long newChallenge) { when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( PASSWORD_QUALITY_SOMETHING); mChallengeGenerator.mUserId = userId; mChallengeGenerator.mSensorId = newSensorId; mChallengeGenerator.mChallenge = newChallenge; - when(mLockPatternUtils.verifyGatekeeperPasswordHandle(gkPwHandle, newChallenge, userId)) - .thenReturn(newGoodCredential(gkPwHandle, new byte[] { 1 })); } @Test - public void checkCredential_validCredentialCase() { + public void testSetCredentialModel_sameResultFromSavedInstanceOrIntent() { + final Bundle extras = newCredentialModelIntentExtras(12, 33, 1, new byte[] { 2, 3 }, 3L); + + AutoCredentialViewModel viewModel2 = new AutoCredentialViewModel( + ApplicationProvider.getApplicationContext(), + mLockPatternUtils, + mChallengeGenerator); + + mViewModel.setCredentialModel(null, new Intent().putExtras(extras)); + final Bundle savedInstance = new Bundle(); + savedInstance.putBundle(KEY_CREDENTIAL_MODEL, extras); + viewModel2.setCredentialModel(savedInstance, new Intent()); + + final Bundle bundle1 = mViewModel.createCredentialIntentExtra(); + final Bundle bundle2 = viewModel2.createCredentialIntentExtra(); + assertThat(bundle1.getLong(EXTRA_KEY_GK_PW_HANDLE)) + .isEqualTo(bundle2.getLong(EXTRA_KEY_GK_PW_HANDLE)); + assertThat(bundle1.getLong(Intent.EXTRA_USER_ID)) + .isEqualTo(bundle2.getLong(Intent.EXTRA_USER_ID)); + assertThat(bundle1.getLong(EXTRA_KEY_CHALLENGE)) + .isEqualTo(bundle2.getLong(EXTRA_KEY_CHALLENGE)); + assertThat(bundle1.getInt(EXTRA_KEY_SENSOR_ID)) + .isEqualTo(bundle2.getInt(EXTRA_KEY_SENSOR_ID)); + final byte[] token1 = bundle1.getByteArray(EXTRA_KEY_CHALLENGE_TOKEN); + final byte[] token2 = bundle2.getByteArray(EXTRA_KEY_CHALLENGE_TOKEN); + assertThat(token1).isNotNull(); + assertThat(token2).isNotNull(); + assertThat(token1.length).isEqualTo(token2.length); + for (int i = 0; i < token2.length; ++i) { + assertThat(token1[i]).isEqualTo(token2[i]); + } + } + + @Test + public void testSetCredentialModel_sameResultFromSavedInstanceOrIntent_invalidValues() { + final Bundle extras = newCredentialModelIntentExtras(UserHandle.USER_NULL, + INVALID_CHALLENGE, INVALID_SENSOR_ID, null, INVALID_GK_PW_HANDLE); + + AutoCredentialViewModel viewModel2 = new AutoCredentialViewModel( + ApplicationProvider.getApplicationContext(), + mLockPatternUtils, + mChallengeGenerator); + + mViewModel.setCredentialModel(null, new Intent().putExtras(extras)); + final Bundle savedInstance = new Bundle(); + savedInstance.putBundle(KEY_CREDENTIAL_MODEL, extras); + viewModel2.setCredentialModel(savedInstance, new Intent()); + + final Bundle bundle1 = mViewModel.createCredentialIntentExtra(); + final Bundle bundle2 = viewModel2.createCredentialIntentExtra(); + assertThat(bundle1.containsKey(EXTRA_KEY_GK_PW_HANDLE)).isFalse(); + assertThat(bundle2.containsKey(EXTRA_KEY_GK_PW_HANDLE)).isFalse(); + assertThat(bundle1.containsKey(EXTRA_KEY_CHALLENGE_TOKEN)).isFalse(); + assertThat(bundle2.containsKey(EXTRA_KEY_CHALLENGE_TOKEN)).isFalse(); + assertThat(bundle1.containsKey(EXTRA_KEY_SENSOR_ID)).isTrue(); + assertThat(bundle2.containsKey(EXTRA_KEY_SENSOR_ID)).isTrue(); + assertThat(bundle1.containsKey(Intent.EXTRA_USER_ID)).isFalse(); + assertThat(bundle2.containsKey(Intent.EXTRA_USER_ID)).isFalse(); + } + + @Test + public void testCheckCredential_validCredentialCase() { final int userId = 99; - mAutoCredentialViewModel.setCredentialModel(newValidTokenCredentialModel(userId)); + mViewModel.setCredentialModel(null, + new Intent().putExtras(newValidTokenCredentialIntentExtras(userId))); when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( PASSWORD_QUALITY_SOMETHING); // Run credential check - mAutoCredentialViewModel.onCreate(mLifecycleOwner); + @CredentialAction final int action = mViewModel.checkCredential(); - verifyNothingHappen(); + assertThat(action).isEqualTo(CREDENTIAL_VALID); + assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull(); } @Test - public void checkCredential_needToChooseLock() { + public void testCheckCredential_needToChooseLock() { final int userId = 100; - mAutoCredentialViewModel.setCredentialModel(newInvalidChallengeCredentialModel(userId)); + mViewModel.setCredentialModel(null, + new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId))); when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( PASSWORD_QUALITY_UNSPECIFIED); // Run credential check - mAutoCredentialViewModel.onCreate(mLifecycleOwner); + @CredentialAction final int action = mViewModel.checkCredential(); - verifyOnlyActionLiveData(CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK); + assertThat(action).isEqualTo(CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK); + assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull(); } @Test - public void checkCredential_needToConfirmLockFoSomething() { + public void testCheckCredential_needToConfirmLockFoSomething() { final int userId = 101; - mAutoCredentialViewModel.setCredentialModel(newInvalidChallengeCredentialModel(userId)); + mViewModel.setCredentialModel(null, + new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId))); when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( PASSWORD_QUALITY_SOMETHING); // Run credential check - mAutoCredentialViewModel.onCreate(mLifecycleOwner); + @CredentialAction final int action = mViewModel.checkCredential(); - verifyOnlyActionLiveData(CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK); + assertThat(action).isEqualTo(CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK); + assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull(); } @Test - public void checkCredential_needToConfirmLockForNumeric() { + public void testCheckCredential_needToConfirmLockForNumeric() { final int userId = 102; - mAutoCredentialViewModel.setCredentialModel(newInvalidChallengeCredentialModel(userId)); + mViewModel.setCredentialModel(null, + new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId))); when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( PASSWORD_QUALITY_NUMERIC); // Run credential check - mAutoCredentialViewModel.onCreate(mLifecycleOwner); + @CredentialAction final int action = mViewModel.checkCredential(); - verifyOnlyActionLiveData(CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK); + assertThat(action).isEqualTo(CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK); + assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull(); } @Test - public void checkCredential_needToConfirmLockForAlphabetic() { + public void testCheckCredential_needToConfirmLockForAlphabetic() { final int userId = 103; - mAutoCredentialViewModel.setCredentialModel(newInvalidChallengeCredentialModel(userId)); + mViewModel.setCredentialModel(null, + new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId))); when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( PASSWORD_QUALITY_ALPHABETIC); // Run credential check - mAutoCredentialViewModel.onCreate(mLifecycleOwner); + @CredentialAction final int action = mViewModel.checkCredential(); - verifyOnlyActionLiveData(CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK); + assertThat(action).isEqualTo(CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK); + assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull(); } @Test - public void checkCredential_generateChallenge() { + public void testCheckCredential_generateChallenge() { final int userId = 104; final long gkPwHandle = 1111L; - final CredentialModel credentialModel = newGkPwHandleCredentialModel(userId, gkPwHandle); - mAutoCredentialViewModel.setCredentialModel(credentialModel); + mViewModel.setCredentialModel(null, + new Intent().putExtras(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))); when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( PASSWORD_QUALITY_SOMETHING); final int newSensorId = 10; final long newChallenge = 20L; - setupGenerateTokenFlow(gkPwHandle, userId, newSensorId, newChallenge); + setupGenerateChallenge(userId, newSensorId, newChallenge); + when(mLockPatternUtils.verifyGatekeeperPasswordHandle(gkPwHandle, newChallenge, userId)) + .thenReturn(newGoodCredential(gkPwHandle, new byte[] { 1 })); // Run credential check - mAutoCredentialViewModel.onCreate(mLifecycleOwner); + @CredentialAction final int action = mViewModel.checkCredential(); - assertThat(mAutoCredentialViewModel.getActionLiveData().getValue()).isNull(); - assertThat(credentialModel.getSensorId()).isEqualTo(newSensorId); - assertThat(credentialModel.getChallenge()).isEqualTo(newChallenge); - assertThat(CredentialModel.isValidToken(credentialModel.getToken())).isTrue(); - assertThat(CredentialModel.isValidGkPwHandle(credentialModel.getGkPwHandle())).isFalse(); + assertThat(action).isEqualTo(CREDENTIAL_IS_GENERATING_CHALLENGE); + assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull(); + final Bundle extras = mViewModel.createCredentialIntentExtra(); + assertThat(extras.getInt(EXTRA_KEY_SENSOR_ID)).isEqualTo(newSensorId); + assertThat(extras.getLong(EXTRA_KEY_CHALLENGE)).isEqualTo(newChallenge); + assertThat(isValidToken(extras.getByteArray(EXTRA_KEY_CHALLENGE_TOKEN))).isTrue(); + assertThat(isValidGkPwHandle(extras.getLong(EXTRA_KEY_GK_PW_HANDLE))).isFalse(); assertThat(mChallengeGenerator.mCallbackRunCount).isEqualTo(1); } @Test - public void testGetUserId() { + public void testCheckCredential_generateChallengeFail() { + final int userId = 104; + final long gkPwHandle = 1111L; + mViewModel.setCredentialModel(null, + new Intent().putExtras(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))); + when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( + PASSWORD_QUALITY_SOMETHING); + + final int newSensorId = 10; + final long newChallenge = 20L; + setupGenerateChallenge(userId, newSensorId, newChallenge); + when(mLockPatternUtils.verifyGatekeeperPasswordHandle(gkPwHandle, newChallenge, userId)) + .thenReturn(newBadCredential(0)); + + // Run credential check + @CredentialAction final int action = mViewModel.checkCredential(); + + assertThat(action).isEqualTo(CREDENTIAL_IS_GENERATING_CHALLENGE); + assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isTrue(); + assertThat(mChallengeGenerator.mCallbackRunCount).isEqualTo(1); + } + + @Test + public void testGetUserId_fromIntent() { final int userId = 106; - mAutoCredentialViewModel.setCredentialModel(newInvalidChallengeCredentialModel(userId)); + mViewModel.setCredentialModel(null, + new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId))); // Get userId - assertThat(mAutoCredentialViewModel.getUserId()).isEqualTo(userId); + assertThat(mViewModel.getUserId()).isEqualTo(userId); + } + + @Test + public void testGetUserId_fromSavedInstance() { + final int userId = 106; + final Bundle savedInstance = new Bundle(); + savedInstance.putBundle(KEY_CREDENTIAL_MODEL, + newInvalidChallengeCredentialIntentExtras(userId)); + mViewModel.setCredentialModel(savedInstance, new Intent()); + + // Get userId + assertThat(mViewModel.getUserId()).isEqualTo(userId); } @Test public void testCheckNewCredentialFromActivityResult_invalidChooseLock() { final int userId = 107; final long gkPwHandle = 3333L; - mAutoCredentialViewModel.setCredentialModel( - newGkPwHandleCredentialModel(userId, gkPwHandle)); + mViewModel.setCredentialModel(null, + new Intent().putExtras(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))); final Intent intent = new Intent(); - intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle); + intent.putExtra(EXTRA_KEY_GK_PW_HANDLE, gkPwHandle); // run checkNewCredentialFromActivityResult() - final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(true, + final boolean ret = mViewModel.checkNewCredentialFromActivityResult(true, new ActivityResult(ChooseLockPattern.RESULT_FINISHED + 1, intent)); assertThat(ret).isFalse(); - verifyNothingHappen(); + assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull(); } @Test public void testCheckNewCredentialFromActivityResult_invalidConfirmLock() { final int userId = 107; final long gkPwHandle = 3333L; - mAutoCredentialViewModel.setCredentialModel( - newGkPwHandleCredentialModel(userId, gkPwHandle)); + mViewModel.setCredentialModel(null, + new Intent().putExtras(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))); final Intent intent = new Intent(); - intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle); + intent.putExtra(EXTRA_KEY_GK_PW_HANDLE, gkPwHandle); // run checkNewCredentialFromActivityResult() - final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(false, + final boolean ret = mViewModel.checkNewCredentialFromActivityResult(false, new ActivityResult(Activity.RESULT_OK + 1, intent)); assertThat(ret).isFalse(); - verifyNothingHappen(); + assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull(); } @Test public void testCheckNewCredentialFromActivityResult_nullDataChooseLock() { final int userId = 108; final long gkPwHandle = 4444L; - mAutoCredentialViewModel.setCredentialModel( - newGkPwHandleCredentialModel(userId, gkPwHandle)); + mViewModel.setCredentialModel(null, + new Intent().putExtras(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))); // run checkNewCredentialFromActivityResult() - final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(true, + final boolean ret = mViewModel.checkNewCredentialFromActivityResult(true, new ActivityResult(ChooseLockPattern.RESULT_FINISHED, null)); assertThat(ret).isFalse(); - verifyNothingHappen(); + assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull(); } @Test public void testCheckNewCredentialFromActivityResult_nullDataConfirmLock() { final int userId = 109; - mAutoCredentialViewModel.setCredentialModel(newInvalidChallengeCredentialModel(userId)); + mViewModel.setCredentialModel(null, + new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId))); // run checkNewCredentialFromActivityResult() - final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(false, + final boolean ret = mViewModel.checkNewCredentialFromActivityResult(false, new ActivityResult(Activity.RESULT_OK, null)); assertThat(ret).isFalse(); - verifyNothingHappen(); + assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull(); } @Test public void testCheckNewCredentialFromActivityResult_validChooseLock() { final int userId = 108; - final CredentialModel credentialModel = newInvalidChallengeCredentialModel(userId); - mAutoCredentialViewModel.setCredentialModel(credentialModel); + mViewModel.setCredentialModel(null, + new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId))); when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( PASSWORD_QUALITY_SOMETHING); final long gkPwHandle = 6666L; final int newSensorId = 50; final long newChallenge = 60L; - setupGenerateTokenFlow(gkPwHandle, userId, newSensorId, newChallenge); - final Intent intent = new Intent(); - intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle); + setupGenerateChallenge(userId, newSensorId, newChallenge); + when(mLockPatternUtils.verifyGatekeeperPasswordHandle(gkPwHandle, newChallenge, userId)) + .thenReturn(newGoodCredential(gkPwHandle, new byte[] { 1 })); // Run checkNewCredentialFromActivityResult() - final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(true, + final Intent intent = new Intent().putExtra(EXTRA_KEY_GK_PW_HANDLE, gkPwHandle); + final boolean ret = mViewModel.checkNewCredentialFromActivityResult(true, new ActivityResult(ChooseLockPattern.RESULT_FINISHED, intent)); assertThat(ret).isTrue(); - assertThat(mAutoCredentialViewModel.getActionLiveData().getValue()).isNull(); - assertThat(credentialModel.getSensorId()).isEqualTo(newSensorId); - assertThat(credentialModel.getChallenge()).isEqualTo(newChallenge); - assertThat(CredentialModel.isValidToken(credentialModel.getToken())).isTrue(); - assertThat(CredentialModel.isValidGkPwHandle(credentialModel.getGkPwHandle())).isFalse(); + assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull(); + final Bundle extras = mViewModel.createCredentialIntentExtra(); + assertThat(extras.getInt(EXTRA_KEY_SENSOR_ID)).isEqualTo(newSensorId); + assertThat(extras.getLong(EXTRA_KEY_CHALLENGE)).isEqualTo(newChallenge); + assertThat(isValidToken(extras.getByteArray(EXTRA_KEY_CHALLENGE_TOKEN))).isTrue(); + assertThat(isValidGkPwHandle(extras.getLong(EXTRA_KEY_GK_PW_HANDLE))).isFalse(); assertThat(mChallengeGenerator.mCallbackRunCount).isEqualTo(1); } @@ -317,28 +404,30 @@ public class AutoCredentialViewModelTest { @Test public void testCheckNewCredentialFromActivityResult_validConfirmLock() { final int userId = 109; - final CredentialModel credentialModel = newInvalidChallengeCredentialModel(userId); - mAutoCredentialViewModel.setCredentialModel(credentialModel); + mViewModel.setCredentialModel(null, + new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId))); when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( PASSWORD_QUALITY_SOMETHING); final long gkPwHandle = 5555L; final int newSensorId = 80; final long newChallenge = 90L; - setupGenerateTokenFlow(gkPwHandle, userId, newSensorId, newChallenge); - final Intent intent = new Intent(); - intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle); + setupGenerateChallenge(userId, newSensorId, newChallenge); + when(mLockPatternUtils.verifyGatekeeperPasswordHandle(gkPwHandle, newChallenge, userId)) + .thenReturn(newGoodCredential(gkPwHandle, new byte[] { 1 })); // Run checkNewCredentialFromActivityResult() - final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(false, + final Intent intent = new Intent().putExtra(EXTRA_KEY_GK_PW_HANDLE, gkPwHandle); + final boolean ret = mViewModel.checkNewCredentialFromActivityResult(false, new ActivityResult(Activity.RESULT_OK, intent)); assertThat(ret).isTrue(); - assertThat(mAutoCredentialViewModel.getActionLiveData().getValue()).isNull(); - assertThat(credentialModel.getSensorId()).isEqualTo(newSensorId); - assertThat(credentialModel.getChallenge()).isEqualTo(newChallenge); - assertThat(CredentialModel.isValidToken(credentialModel.getToken())).isTrue(); - assertThat(CredentialModel.isValidGkPwHandle(credentialModel.getGkPwHandle())).isFalse(); + assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull(); + final Bundle extras = mViewModel.createCredentialIntentExtra(); + assertThat(extras.getInt(EXTRA_KEY_SENSOR_ID)).isEqualTo(newSensorId); + assertThat(extras.getLong(EXTRA_KEY_CHALLENGE)).isEqualTo(newChallenge); + assertThat(isValidToken(extras.getByteArray(EXTRA_KEY_CHALLENGE_TOKEN))).isTrue(); + assertThat(isValidGkPwHandle(extras.getLong(EXTRA_KEY_GK_PW_HANDLE))).isFalse(); assertThat(mChallengeGenerator.mCallbackRunCount).isEqualTo(1); } @@ -377,4 +466,12 @@ public class AutoCredentialViewModelTest { .setGatekeeperHAT(hat) .build(); } + + private VerifyCredentialResponse newBadCredential(int timeout) { + if (timeout > 0) { + return VerifyCredentialResponse.fromTimeout(timeout); + } else { + return VerifyCredentialResponse.fromError(); + } + } } diff --git a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModelTest.java b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModelTest.java index 5069ea1962a..a9536cffcbf 100644 --- a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModelTest.java +++ b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModelTest.java @@ -46,6 +46,7 @@ import android.hardware.fingerprint.FingerprintManager; import androidx.annotation.NonNull; import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.MutableLiveData; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -92,6 +93,18 @@ public class FingerprintEnrollIntroViewModelTest { assertThat(status.getEnrollableStatus()).isEqualTo(FINGERPRINT_ENROLLABLE_UNKNOWN); } + @Test + public void testClearActionLiveData() { + final MutableLiveData actionLiveData = + (MutableLiveData) mViewModel.getActionLiveData(); + actionLiveData.postValue(1); + assertThat(actionLiveData.getValue()).isEqualTo(1); + + mViewModel.clearActionLiveData(); + + assertThat(actionLiveData.getValue()).isNull(); + } + @Test public void testGetEnrollmentRequest() { final EnrollmentRequest request = newAllFalseRequest(mApplication); @@ -202,11 +215,13 @@ public class FingerprintEnrollIntroViewModelTest { @Test public void testSetHasScrolledToBottom() { - mViewModel.setHasScrolledToBottom(); - + mViewModel.setHasScrolledToBottom(true); FingerprintEnrollIntroStatus status = mViewModel.getPageStatusLiveData().getValue(); - assertThat(status.hasScrollToBottom()).isEqualTo(true); + + mViewModel.setHasScrolledToBottom(false); + status = mViewModel.getPageStatusLiveData().getValue(); + assertThat(status.hasScrollToBottom()).isEqualTo(false); } @Test diff --git a/tests/unit/src/com/android/settings/network/InternetResetHelperTest.java b/tests/unit/src/com/android/settings/network/InternetResetHelperTest.java index e6df8a06451..3fe688273d8 100644 --- a/tests/unit/src/com/android/settings/network/InternetResetHelperTest.java +++ b/tests/unit/src/com/android/settings/network/InternetResetHelperTest.java @@ -16,6 +16,8 @@ package com.android.settings.network; +import static com.android.settings.network.InternetResetHelper.RESTART_TIMEOUT_MS; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -29,8 +31,6 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.IntentFilter; import android.net.wifi.WifiManager; -import android.os.Handler; -import android.os.HandlerThread; import android.os.Looper; import androidx.lifecycle.Lifecycle; @@ -39,7 +39,6 @@ import androidx.preference.PreferenceCategory; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; -import com.android.settingslib.connectivity.ConnectivitySubsystemsRecoveryManager; import com.android.settingslib.utils.HandlerInjector; import org.junit.Before; @@ -47,6 +46,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.Spy; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @@ -55,66 +55,46 @@ public class InternetResetHelperTest { @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Spy + private final Context mContext = ApplicationProvider.getApplicationContext(); @Mock private WifiManager mWifiManager; @Mock - public HandlerThread mWorkerThread; + InternetResetHelper.RecoveryWorker mRecoveryWorker; @Mock - public ConnectivitySubsystemsRecoveryManager mConnectivitySubsystemsRecoveryManager; + HandlerInjector mHandlerInjector; @Mock public NetworkMobileProviderController mMobileNetworkController; - private Context mContext; private InternetResetHelper mInternetResetHelper; private Preference mResettingPreference; private Preference mWifiTogglePreferences; private PreferenceCategory mConnectedWifiEntryPreferences; + private PreferenceCategory mFirstWifiEntryPreference; private PreferenceCategory mWifiEntryPreferences; - private FakeHandlerInjector mFakeHandlerInjector; - - private static class FakeHandlerInjector extends HandlerInjector { - - private Runnable mRunnable; - - FakeHandlerInjector(Handler handler) { - super(handler); - } - - @Override - public void postDelayed(Runnable runnable, long delayMillis) { - mRunnable = runnable; - } - - public Runnable getRunnable() { - return mRunnable; - } - } - @Before public void setUp() { - mContext = spy(ApplicationProvider.getApplicationContext()); when(mContext.getSystemService(WifiManager.class)).thenReturn(mWifiManager); + when(mRecoveryWorker.isRecovering()).thenReturn(false); if (Looper.myLooper() == null) { Looper.prepare(); } - mResettingPreference = new Preference(mContext); + mResettingPreference = spy(new Preference(mContext)); mWifiTogglePreferences = new Preference(mContext); mConnectedWifiEntryPreferences = spy(new PreferenceCategory(mContext)); + mFirstWifiEntryPreference = spy(new PreferenceCategory(mContext)); mWifiEntryPreferences = spy(new PreferenceCategory(mContext)); - final Lifecycle lifecycle = mock(Lifecycle.class); - mInternetResetHelper = new InternetResetHelper(mContext, lifecycle); - mInternetResetHelper.mWorkerThread = mWorkerThread; - mFakeHandlerInjector = new FakeHandlerInjector(mContext.getMainThreadHandler()); - mInternetResetHelper.mHandlerInjector = mFakeHandlerInjector; - mInternetResetHelper.mConnectivitySubsystemsRecoveryManager = - mConnectivitySubsystemsRecoveryManager; - mInternetResetHelper.setResettingPreference(mResettingPreference); - mInternetResetHelper.setMobileNetworkController(mMobileNetworkController); - mInternetResetHelper.setWifiTogglePreference(mWifiTogglePreferences); - mInternetResetHelper.addWifiNetworkPreference(mConnectedWifiEntryPreferences); - mInternetResetHelper.addWifiNetworkPreference(mWifiEntryPreferences); + mInternetResetHelper = new InternetResetHelper(mContext, mock(Lifecycle.class), + mMobileNetworkController, + mWifiTogglePreferences, + mConnectedWifiEntryPreferences, + mFirstWifiEntryPreference, + mWifiEntryPreferences, + mResettingPreference); + mInternetResetHelper.mHandlerInjector = mHandlerInjector; + mInternetResetHelper.mRecoveryWorker = mRecoveryWorker; } @Test @@ -135,30 +115,10 @@ public class InternetResetHelperTest { } @Test - public void onDestroy_quitWorkerThread() { + public void onDestroy_removeCallbacks() { mInternetResetHelper.onDestroy(); - verify(mWorkerThread).quit(); - } - - @Test - public void onSubsystemRestartOperationEnd_recoveryIsNotReady_postResumeRunnable() { - mInternetResetHelper.mIsRecoveryReady = false; - - mInternetResetHelper.onSubsystemRestartOperationEnd(); - - assertThat(mInternetResetHelper.mIsRecoveryReady).isTrue(); - assertThat(mFakeHandlerInjector.getRunnable()) - .isEqualTo(mInternetResetHelper.mResumeRunnable); - } - - @Test - public void onSubsystemRestartOperationEnd_recoveryIsReady_doNothing() { - mInternetResetHelper.mIsRecoveryReady = true; - - mInternetResetHelper.onSubsystemRestartOperationEnd(); - - assertThat(mFakeHandlerInjector.getRunnable()).isNull(); + verify(mHandlerInjector).removeCallbacks(any()); } @Test @@ -169,19 +129,16 @@ public class InternetResetHelperTest { mInternetResetHelper.updateWifiStateChange(); assertThat(mInternetResetHelper.mIsWifiReady).isFalse(); - assertThat(mFakeHandlerInjector.getRunnable()).isNull(); } @Test - public void updateWifiStateChange_wifiIsNotReadyAndWifiEnabled_postResumeRunnable() { + public void updateWifiStateChange_wifiIsNotReadyAndWifiEnabled_updateWifiIsReady() { mInternetResetHelper.mIsWifiReady = false; when(mWifiManager.isWifiEnabled()).thenReturn(true); mInternetResetHelper.updateWifiStateChange(); assertThat(mInternetResetHelper.mIsWifiReady).isTrue(); - assertThat(mFakeHandlerInjector.getRunnable()) - .isEqualTo(mInternetResetHelper.mResumeRunnable); } @Test @@ -191,7 +148,6 @@ public class InternetResetHelperTest { mInternetResetHelper.updateWifiStateChange(); assertThat(mInternetResetHelper.mIsWifiReady).isTrue(); - assertThat(mFakeHandlerInjector.getRunnable()).isNull(); } @Test @@ -203,16 +159,15 @@ public class InternetResetHelperTest { // Hide subsystem preferences verify(mMobileNetworkController).hidePreference(true /* hide */, true /* immediately*/); assertThat(mWifiTogglePreferences.isVisible()).isFalse(); - verify(mConnectedWifiEntryPreferences).removeAll(); assertThat(mConnectedWifiEntryPreferences.isVisible()).isFalse(); - verify(mWifiEntryPreferences).removeAll(); + assertThat(mFirstWifiEntryPreference.isVisible()).isFalse(); assertThat(mWifiEntryPreferences.isVisible()).isFalse(); } @Test public void resumePreferences_onlyRecoveryReady_shouldShowSubSysHideResetting() { mInternetResetHelper.suspendPreferences(); - mInternetResetHelper.mIsRecoveryReady = true; + when(mRecoveryWorker.isRecovering()).thenReturn(false); mInternetResetHelper.mIsWifiReady = false; mInternetResetHelper.resumePreferences(); @@ -224,13 +179,14 @@ public class InternetResetHelperTest { // Hide Wi-Fi preferences assertThat(mWifiTogglePreferences.isVisible()).isFalse(); assertThat(mConnectedWifiEntryPreferences.isVisible()).isFalse(); + assertThat(mFirstWifiEntryPreference.isVisible()).isFalse(); assertThat(mWifiEntryPreferences.isVisible()).isFalse(); } @Test public void resumePreferences_onlyWifiReady_shouldShowSubSysHideResetting() { mInternetResetHelper.suspendPreferences(); - mInternetResetHelper.mIsRecoveryReady = false; + when(mRecoveryWorker.isRecovering()).thenReturn(true); mInternetResetHelper.mIsWifiReady = true; mInternetResetHelper.resumePreferences(); @@ -240,6 +196,7 @@ public class InternetResetHelperTest { // Show Wi-Fi preferences assertThat(mWifiTogglePreferences.isVisible()).isTrue(); assertThat(mConnectedWifiEntryPreferences.isVisible()).isTrue(); + assertThat(mFirstWifiEntryPreference.isVisible()).isTrue(); assertThat(mWifiEntryPreferences.isVisible()).isTrue(); // Hide Mobile Network controller verify(mMobileNetworkController, never()) @@ -249,14 +206,16 @@ public class InternetResetHelperTest { @Test public void resumePreferences_allReady_shouldShowSubSysHideResetting() { mInternetResetHelper.suspendPreferences(); - mInternetResetHelper.mIsRecoveryReady = true; + when(mRecoveryWorker.isRecovering()).thenReturn(false); mInternetResetHelper.mIsWifiReady = true; + mInternetResetHelper.resumePreferences(); // Show subsystem preferences verify(mMobileNetworkController).hidePreference(false, true); assertThat(mWifiTogglePreferences.isVisible()).isTrue(); assertThat(mConnectedWifiEntryPreferences.isVisible()).isTrue(); + assertThat(mFirstWifiEntryPreference.isVisible()).isTrue(); assertThat(mWifiEntryPreferences.isVisible()).isTrue(); // Hide resetting preference assertThat(mResettingPreference.isVisible()).isFalse(); @@ -264,22 +223,39 @@ public class InternetResetHelperTest { @Test public void restart_recoveryNotAvailable_shouldDoTriggerSubsystemRestart() { - when(mConnectivitySubsystemsRecoveryManager.isRecoveryAvailable()).thenReturn(false); + when(mRecoveryWorker.isRecoveryAvailable()).thenReturn(false); mInternetResetHelper.restart(); - verify(mConnectivitySubsystemsRecoveryManager, never()) - .triggerSubsystemRestart(any(), any()); + verify(mRecoveryWorker, never()).triggerRestart(); } @Test public void restart_recoveryAvailable_triggerSubsystemRestart() { - when(mConnectivitySubsystemsRecoveryManager.isRecoveryAvailable()).thenReturn(true); + when(mRecoveryWorker.isRecoveryAvailable()).thenReturn(true); mInternetResetHelper.restart(); - assertThat(mFakeHandlerInjector.getRunnable()) - .isEqualTo(mInternetResetHelper.mTimeoutRunnable); - verify(mConnectivitySubsystemsRecoveryManager).triggerSubsystemRestart(any(), any()); + verify(mHandlerInjector) + .postDelayed(mInternetResetHelper.mTimeoutRunnable, RESTART_TIMEOUT_MS); + verify(mRecoveryWorker).triggerRestart(); + } + + @Test + public void checkRecovering_isRecovering_showResetting() { + when(mRecoveryWorker.isRecovering()).thenReturn(true); + + mInternetResetHelper.checkRecovering(); + + verify(mResettingPreference).setVisible(true); + } + + @Test + public void checkRecovering_isNotRecovering_doNotShowResetting() { + when(mRecoveryWorker.isRecovering()).thenReturn(false); + + mInternetResetHelper.checkRecovering(); + + verify(mResettingPreference, never()).setVisible(true); } } diff --git a/tests/unit/src/com/android/settings/network/telephony/BackupCallingPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/BackupCallingPreferenceControllerTest.java index 4e110f0d018..34d7c925b40 100644 --- a/tests/unit/src/com/android/settings/network/telephony/BackupCallingPreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/network/telephony/BackupCallingPreferenceControllerTest.java @@ -28,9 +28,13 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import com.android.settings.core.BasePreferenceController; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; +/** + * Deprecated ToDo: b/260059444 remove it next version + */ @RunWith(AndroidJUnit4.class) public class BackupCallingPreferenceControllerTest { private static final int SUB_ID = 2; @@ -47,6 +51,7 @@ public class BackupCallingPreferenceControllerTest { } @Test + @Ignore public void controller_isUnavailable() { assertThat(mController.getAvailabilityStatus()) .isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE); diff --git a/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java index 45f3693a298..16e3963b738 100644 --- a/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java @@ -28,18 +28,24 @@ import static org.mockito.Mockito.when; import android.app.Instrumentation; import android.content.Context; +import android.os.Looper; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; +import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.LifecycleRegistry; import androidx.preference.SwitchPreference; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.platform.app.InstrumentationRegistry; import com.android.settings.testutils.ResourcesUtils; +import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.mobile.dataservice.MobileNetworkInfoEntity; +import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity; import org.junit.Before; import org.junit.Test; @@ -49,6 +55,10 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) public class MobileDataPreferenceControllerTest { + private static final String SUB_ID_1 = "1"; + private static final String SUB_ID_2 = "2"; + private static final String DISPLAY_NAME_1 = "Sub 1"; + private static final String DISPLAY_NAME_2 = "Sub 2"; private static final int SUB_ID = 2; private static final int SUB_ID_OTHER = 3; @@ -64,7 +74,15 @@ public class MobileDataPreferenceControllerTest { private SubscriptionInfo mSubscriptionInfo; @Mock private FragmentTransaction mFragmentTransaction; - + @Mock + private Lifecycle mLifecycle; + @Mock + private LifecycleOwner mLifecycleOwner; + private SubscriptionInfoEntity mSubInfo1; + private SubscriptionInfoEntity mSubInfo2; + private MobileNetworkInfoEntity mNetworkInfo1; + private MobileNetworkInfoEntity mNetworkInfo2; + private LifecycleRegistry mLifecycleRegistry; private MobileDataPreferenceController mController; private SwitchPreference mPreference; private Context mContext; @@ -73,6 +91,10 @@ public class MobileDataPreferenceControllerTest { public void setUp() { MockitoAnnotations.initMocks(this); + if (Looper.myLooper() == null) { + Looper.prepare(); + } + mContext = spy(ApplicationProvider.getApplicationContext()); doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE); @@ -83,22 +105,45 @@ public class MobileDataPreferenceControllerTest { doReturn(mFragmentTransaction).when(mFragmentManager).beginTransaction(); mPreference = new SwitchPreference(mContext); - mController = new MobileDataPreferenceController(mContext, "mobile_data"); - mController.init(mFragmentManager, SUB_ID); + mController = new MobileDataPreferenceController(mContext, "mobile_data", mLifecycle, + mLifecycleOwner, SUB_ID); + mController.init(mFragmentManager, SUB_ID, mSubInfo1, mNetworkInfo1); mPreference.setKey(mController.getPreferenceKey()); + mLifecycleRegistry = new LifecycleRegistry(mLifecycleOwner); + when(mLifecycleOwner.getLifecycle()).thenReturn(mLifecycleRegistry); + } + + private SubscriptionInfoEntity setupSubscriptionInfoEntity(String subId, String displayName, + boolean isOpportunistic, boolean isValid, boolean isActive, boolean isAvailable, + boolean isDefaultData) { + int id = Integer.parseInt(subId); + return new SubscriptionInfoEntity(subId, id, id, + displayName, displayName, 0, "mcc", "mnc", "countryIso", false, id, + TelephonyManager.DEFAULT_PORT_INDEX, isOpportunistic, null, + SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, displayName, false, + "1234567890", true, "default", false, isValid, true, isActive, isAvailable, false, + false, isDefaultData, false, false); + } + + private MobileNetworkInfoEntity setupMobileNetworkInfoEntity(String subId, + boolean isDatEnabled) { + return new MobileNetworkInfoEntity(subId, false, false, isDatEnabled, false, false, false, + false, false, false, false, false); } @Test public void getAvailabilityStatus_invalidSubscription_returnAvailableUnsearchable() { - mController.init(mFragmentManager, SubscriptionManager.INVALID_SUBSCRIPTION_ID); + mController.init(mFragmentManager, SubscriptionManager.INVALID_SUBSCRIPTION_ID, mSubInfo1, + mNetworkInfo1); assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE); } @Test public void isDialogNeeded_disableSingleSim_returnFalse() { - doReturn(true).when(mTelephonyManager).isDataEnabled(); - doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID); + mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, false, true, true, true, + true); + mNetworkInfo1 = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), true); doReturn(1).when(mTelephonyManager).getActiveModemCount(); assertThat(mController.isDialogNeeded()).isFalse(); @@ -106,12 +151,15 @@ public class MobileDataPreferenceControllerTest { @Test public void isDialogNeeded_enableNonDefaultSimInMultiSimMode_returnTrue() { - doReturn(false).when(mTelephonyManager).isDataEnabled(); - doReturn(mSubscriptionInfo).when(mSubscriptionManager) - .getActiveSubscriptionInfo(SUB_ID); + mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, false, true, true, true, + false); + mNetworkInfo1 = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), false); + doReturn(1).when(mTelephonyManager).getActiveModemCount(); // Ideally, it would be better if we could set the default data subscription to // SUB_ID_OTHER, and set that as an active subscription id. - when(mSubscriptionManager.isActiveSubscriptionId(anyInt())).thenReturn(true); + mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, DISPLAY_NAME_2, false, true, true, true, + true); + mNetworkInfo1 = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), true); doReturn(2).when(mTelephonyManager).getActiveModemCount(); assertThat(mController.isDialogNeeded()).isTrue(); @@ -132,8 +180,11 @@ public class MobileDataPreferenceControllerTest { @Test public void onPreferenceChange_singleSim_On_shouldEnableData() { - doReturn(true).when(mTelephonyManager).isDataEnabled(); - doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID); + mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, true, true, true, true, + true); + mNetworkInfo1 = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), true); + mController.setSubscriptionInfoEntity(mSubInfo1); + mController.setMobileNetworkInfoEntity(mNetworkInfo1); doReturn(1).when(mTelephonyManager).getActiveModemCount(); mController.onPreferenceChange(mPreference, true); @@ -143,8 +194,11 @@ public class MobileDataPreferenceControllerTest { @Test public void onPreferenceChange_multiSim_On_shouldEnableData() { - doReturn(true).when(mTelephonyManager).isDataEnabled(); - doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID); + mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, true, true, true, true, + true); + mNetworkInfo1 = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), true); + mController.setSubscriptionInfoEntity(mSubInfo1); + mController.setMobileNetworkInfoEntity(mNetworkInfo1); doReturn(2).when(mTelephonyManager).getActiveModemCount(); mController.onPreferenceChange(mPreference, true); @@ -154,18 +208,20 @@ public class MobileDataPreferenceControllerTest { @Test public void isChecked_returnUserDataEnabled() { - mController.init(mFragmentManager, SUB_ID); + mNetworkInfo1 = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), false); + mController.init(mFragmentManager, SUB_ID, mSubInfo1, mNetworkInfo1); assertThat(mController.isChecked()).isFalse(); - doReturn(true).when(mTelephonyManager).isDataEnabled(); + mNetworkInfo1 = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), true); + mController.setMobileNetworkInfoEntity(mNetworkInfo1); assertThat(mController.isChecked()).isTrue(); } @Test public void updateState_opportunistic_disabled() { - doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID); - mController.init(mFragmentManager, SUB_ID); - doReturn(true).when(mSubscriptionInfo).isOpportunistic(); + mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, true, true, true, true, + true); + mController.init(mFragmentManager, SUB_ID, mSubInfo1, mNetworkInfo1); mController.updateState(mPreference); assertThat(mPreference.isEnabled()).isFalse(); @@ -176,9 +232,9 @@ public class MobileDataPreferenceControllerTest { @Test public void updateState_notOpportunistic_enabled() { - doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID); - mController.init(mFragmentManager, SUB_ID); - doReturn(false).when(mSubscriptionInfo).isOpportunistic(); + mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, false, true, true, true, + true); + mController.init(mFragmentManager, SUB_ID, mSubInfo1, mNetworkInfo1); mController.updateState(mPreference); assertThat(mPreference.isEnabled()).isTrue(); diff --git a/tests/unit/src/com/android/settings/network/telephony/NetworkProviderBackupCallingGroupTest.java b/tests/unit/src/com/android/settings/network/telephony/NetworkProviderBackupCallingGroupTest.java index a5717ef519a..09f020085f3 100644 --- a/tests/unit/src/com/android/settings/network/telephony/NetworkProviderBackupCallingGroupTest.java +++ b/tests/unit/src/com/android/settings/network/telephony/NetworkProviderBackupCallingGroupTest.java @@ -40,6 +40,7 @@ import com.android.settings.network.CarrierConfigCache; import com.android.settingslib.core.lifecycle.Lifecycle; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -47,6 +48,9 @@ import org.mockito.MockitoAnnotations; import java.util.List; +/** + * Deprecated ToDo: b/260059444 remove it next version + */ @RunWith(AndroidJUnit4.class) public class NetworkProviderBackupCallingGroupTest { @@ -133,12 +137,14 @@ public class NetworkProviderBackupCallingGroupTest { } @Test + @Ignore public void shouldShowBackupCallingForSub_invalidSubId_returnFalse() { assertThat(mNetworkProviderBackupCallingGroup.hasBackupCallingFeature( SubscriptionManager.INVALID_SUBSCRIPTION_ID)).isEqualTo(false); } @Test + @Ignore public void shouldShowBackupCallingForSub_carrierConfigIsUnavailable_returnFalse() { mCarrierConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL, false); @@ -148,6 +154,7 @@ public class NetworkProviderBackupCallingGroupTest { } @Test + @Ignore public void shouldShowBackupCallingForSub_crossSimDisabled_returnFalse() { doReturn(false).when(mNetworkProviderBackupCallingGroup).isCrossSimEnabledByPlatform( @@ -158,6 +165,7 @@ public class NetworkProviderBackupCallingGroupTest { } @Test + @Ignore public void shouldBackupCallingForSub_crossSimEnabled_returnTrue() { doReturn(true).when(mNetworkProviderBackupCallingGroup).isCrossSimEnabledByPlatform( mContext, SUB_ID_1);