Snap for 9325779 from 8d4a48e1d1 to udc-release

Change-Id: I09f48931d78d22dc982c44c7ac8084d99d095f64
This commit is contained in:
Android Build Coastguard Worker
2022-11-24 02:26:41 +00:00
43 changed files with 1084 additions and 687 deletions

View File

@@ -1,53 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2021 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:paddingStart="@dimen/preference_no_icon_padding_start"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:orientation="vertical">
<TextView
android:id="@+id/charge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:fontFamily="@*android:string/config_headlineFontFamily"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="36sp"
android:textColor="?android:attr/colorAccent" />
<com.android.settings.widget.UsageView
android:id="@+id/battery_usage"
android:layout_width="match_parent"
android:layout_height="141dp"
android:layout_marginBottom="16dp"
settings:sideLabels="@array/battery_labels"
android:colorAccent="?android:attr/colorAccent"
android:gravity="end"
settings:textColor="?android:attr/textColorSecondary" />
<TextView
android:id="@+id/bottom_summary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>

View File

@@ -4582,8 +4582,6 @@
<string name="power_usage_summary_title">Battery</string>
<!-- Activity title summary for App Fuel Gauge summary -->
<string name="power_usage_summary">What has been using the battery</string>
<!-- Message to show when battery usage data is not available [CHAR LIMIT=30] -->
<string name="power_usage_not_available">Battery usage data isn\u2019t available.</string>
<!-- Display the battery level and status [CHAR_LIMIT=60] -->
<string name="power_usage_level_and_status"><xliff:g id="level">%1$s</xliff:g>
- <xliff:g id="status">%2$s</xliff:g></string>
@@ -4631,8 +4629,6 @@
<!-- Title for the screen usage in power use UI [CHAR_LIMIT=60] -->
<string name="device_screen_usage">Screen usage since full charge</string>
<!-- Label for list of apps using battery in power use UI. Note: ^1 should be used in all translations[CHAR_LIMIT=120] -->
<string name="power_usage_list_summary">Battery usage since full charge</string>
<!-- Temp string used to debug new battery estimates [DO NOT TRANSLATE] -->
<string name="power_usage_enhanced_debug" translatable="false"><xliff:g id="time">%1$s</xliff:g> left (New ML est)</string>
<!-- Temp string used to debug old battery estimates [DO NOT TRANSLATE] -->
@@ -4800,8 +4796,6 @@
<!-- Label for power consumed by Calling -->
<string name="power_phone">Voice calls</string>
<!-- Description for battery usage time for an app, i.e. Used for 30min. Note: ^1 should be used in all translations [CHAR LIMIT=60] -->
<string name="battery_used_for">Used for <xliff:g id="time">^1</xliff:g></string>
<!-- Description for battery screen usage time for an app, i.e. Screen usage 30min. Note: ^1 should be used in all translations [CHAR LIMIT=60] -->
<string name="battery_screen_usage">Screen usage <xliff:g id="time">^1</xliff:g></string>
<!-- Description for battery usage info for an app, i.e. 60% used by facebook. [CHAR LIMIT=60] -->
@@ -4870,9 +4864,6 @@
<!-- Description for other users aggregated battery usage data [CHAR LIMIT=120] -->
<string name="battery_usage_other_users">Other users</string>
<!-- Graph subtext displayed to user when enhanced battery estimate is being used [CHAR LIMIT=120] -->
<string name="advanced_battery_graph_subtext">Battery left estimate is based on your device usage</string>
<!-- Description for battery time left, i.e. 50min Estimated time left. [CHAR LIMIT=80]-->
<string name="estimated_time_left">Estimated time left</string>
@@ -5141,6 +5132,8 @@
<string name="adaptive_connectivity_title">Adaptive connectivity</string>
<!-- Summary of Adaptive connectivity preference. [CHAR LIMIT=NONE] -->
<string name="adaptive_connectivity_summary">Extends battery life and improves device performance by automatically managing your network connections</string>
<!-- Title for adaptive connectivity main switch preferences. [CHAR LIMIT=50] -->
<string name="adaptive_connectivity_main_switch_title">Use adaptive connectivity</string>
<!-- Title of preference group for credential storage settings [CHAR LIMIT=30] -->
<string name="credentials_title">Credential storage</string>
@@ -10510,12 +10503,15 @@
<string name="wifi_calling_summary">Use Wi\u2011Fi for calls to improve quality</string>
<!-- Mobile network settings screen, title of Backup calling setting. [CHAR LIMIT=NONE] -->
<!-- Deprecated ToDo: b/260059444 remove it next version-->
<string name="backup_calling_settings_title">Backup calling</string>
<!-- Backup calling summary. [CHAR LIMIT=100] -->
<!-- Deprecated ToDo: b/260059444 remove it next version-->
<string name="backup_calling_setting_summary">If <xliff:g id="backup_calling_operator_text" example="Google Fi">%1$s</xliff:g> is unavailable or roaming, use your mobile data SIM for <xliff:g id="backup_calling_carrier_text" example="Google Fi">%1$s</xliff:g> calls.</string>
<!-- List of synonyms for the cross SIM calling titles, used to match in settings search [CHAR LIMIT=NONE] -->
<!-- Deprecated ToDo: b/260059444 remove it next version-->
<string name="keywords_backup_calling">backup calling</string>
<!-- Title for enable MMS notification when trying to receive MMS. [CHAR LIMIT=40] -->

View File

@@ -30,7 +30,7 @@
<com.android.settingslib.widget.MainSwitchPreference
android:key="adaptive_connectivity"
android:title="@string/adaptive_connectivity_title"
android:title="@string/adaptive_connectivity_main_switch_title"
settings:controller="com.android.settings.network.AdaptiveConnectivityTogglePreferenceController"/>
</PreferenceScreen>

View File

@@ -183,14 +183,6 @@
android:persistent="true"
settings:controller="com.android.settings.network.telephony.VideoCallingPreferenceController"/>
<SwitchPreference
android:key="backup_calling_key"
android:title="@string/backup_calling_settings_title"
android:persistent="false"
android:summary="@string/backup_calling_setting_summary"
settings:keywords="@string/keywords_backup_calling"
settings:controller="com.android.settings.network.telephony.BackupCallingPreferenceController"/>
</PreferenceCategory>
<com.android.settings.network.telephony.cdma.CdmaListPreference

View File

@@ -43,12 +43,4 @@
settings:controller="com.android.settings.network.telephony.NetworkProviderWifiCallingPreferenceController"
settings:allowDividerAbove="true"
/>
<PreferenceCategory
android:key="provider_model_backup_calling_category"
android:title="@string/backup_calling_settings_title"
android:order="25"
settings:controller="com.android.settings.network.telephony.NetworkProviderBackupCallingPreferenceController"
settings:allowDividerAbove="true"
/>
</PreferenceScreen>

View File

@@ -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),

View File

@@ -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;
}
/**

View File

@@ -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. */

View File

@@ -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);
}
}

View File

@@ -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
*/

View File

@@ -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<FingerprintEnrollIntroStatus> 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) {

View File

@@ -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);
}
}

View File

@@ -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<Integer> mActionLiveData =
@NonNull private final MutableLiveData<Boolean> 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<Integer> 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<Boolean> 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);

View File

@@ -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);
}
/**

View File

@@ -48,7 +48,7 @@ public class PrivateVolumeForget extends InstrumentedFragment {
@Override
public int getMetricsCategory() {
return SettingsEnums.DEVICEINFO_STORAGE;
return SettingsEnums.PRIVATE_VOLUME_FORGET;
}
@Override

View File

@@ -44,7 +44,7 @@ public class PrivateVolumeFormat extends InstrumentedFragment {
@Override
public int getMetricsCategory() {
return SettingsEnums.DEVICEINFO_STORAGE;
return SettingsEnums.PRIVATE_VOLUME_FORMAT;
}
@Override

View File

@@ -40,7 +40,7 @@ public class PrivateVolumeUnmount extends InstrumentedFragment {
@Override
public int getMetricsCategory() {
return SettingsEnums.DEVICEINFO_STORAGE;
return SettingsEnums.PRIVATE_VOLUME_UNMOUNT;
}
@Override

View File

@@ -95,7 +95,7 @@ public class PublicVolumeSettings extends SettingsPreferenceFragment {
@Override
public int getMetricsCategory() {
return SettingsEnums.DEVICEINFO_STORAGE;
return SettingsEnums.PUBLIC_VOLUME_SETTINGS;
}
@Override

View File

@@ -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<Long, Map<String, BatteryHistEntry>> getBatteryHistory(Context context);
/**
* Returns {@link Set} for hidding applications background usage time.
*/

View File

@@ -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<Long, Map<String, BatteryHistEntry>> getBatteryHistory(Context context) {
return null;
}
@Override
public Set<CharSequence> getHideBackgroundUsageTimeSet(Context context) {
return new ArraySet<>();

View File

@@ -167,7 +167,7 @@ public class BatterySaverScheduleSettings extends RadioButtonPickerFragment {
@Override
public int getMetricsCategory() {
return 0;
return SettingsEnums.FUELGAUGE_BATTERY_SAVER_SCHEDULE;
}
private void logPowerSaver() {

View File

@@ -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";

View File

@@ -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<InternetResetHelper> 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();
}
}
}

View File

@@ -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),

View File

@@ -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;
}

View File

@@ -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<SubscriptionInfoEntity> 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();

View File

@@ -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();
}

View File

@@ -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<Runnable> mResetSequence = new ArrayList<Runnable>();
@@ -127,10 +133,17 @@ public class ResetNetworkOperationBuilder {
public ResetNetworkOperationBuilder resetEsim(String callerPackage,
Consumer<Boolean> 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);
}
}

View File

@@ -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 {

View File

@@ -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<SubscriptionInfoEntity> mSubscriptionInfoEntityList = new ArrayList<>();
private List<MobileNetworkInfoEntity> 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<SubscriptionInfoEntity> subInfoEntityList) {
}
@Override
public void onActiveSubInfoChanged(List<SubscriptionInfoEntity> 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<UiccInfoEntity> uiccInfoEntityList) {
}
@Override
public void onAllMobileNetworkInfoChanged(
List<MobileNetworkInfoEntity> mobileNetworkInfoEntityList) {
if (DataServiceUtils.shouldUpdateEntityList(mMobileNetworkInfoEntityList,
mobileNetworkInfoEntityList)) {
mMobileNetworkInfoEntityList = mobileNetworkInfoEntityList;
mMobileNetworkInfoEntityList.forEach(entity -> {
if (Integer.parseInt(entity.subId) == mSubId) {
mMobileNetworkInfoEntity = entity;
update();
refreshSummary(mPreference);
return;
}
});
}
}
}

View File

@@ -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)

View File

@@ -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,

View File

@@ -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 {

View File

@@ -26,6 +26,7 @@ android_test {
"androidx.test.runner",
"androidx.test.rules",
"androidx.test.ext.junit",
"mockito-target",
],
test_suites: ["device-tests"],

View File

@@ -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,

View File

@@ -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);

View File

@@ -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<String> 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);
}
}

View File

@@ -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();
}
}
}

View File

@@ -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<Integer> actionLiveData =
(MutableLiveData<Integer>) 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

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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();

View File

@@ -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);