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 extends Fragment> 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);