Snap for 9899401 from f98cfff495 to udc-release

Change-Id: I690912609fa50fb4d04399645c7791380fd487b3
This commit is contained in:
Android Build Coastguard Worker
2023-04-07 01:32:47 +00:00
15 changed files with 385 additions and 201 deletions

View File

@@ -16,6 +16,8 @@
package com.android.settings.biometrics2.ui.viewmodel; package com.android.settings.biometrics2.ui.viewmodel;
import static android.hardware.fingerprint.FingerprintManager.ENROLL_ENROLL;
import static com.android.settings.biometrics2.ui.model.EnrollmentProgress.INITIAL_REMAINING; import static com.android.settings.biometrics2.ui.model.EnrollmentProgress.INITIAL_REMAINING;
import static com.android.settings.biometrics2.ui.model.EnrollmentProgress.INITIAL_STEPS; import static com.android.settings.biometrics2.ui.model.EnrollmentProgress.INITIAL_STEPS;
@@ -63,7 +65,6 @@ public class FingerprintEnrollProgressViewModel extends AndroidViewModel {
private final int mUserId; private final int mUserId;
private final FingerprintUpdater mFingerprintUpdater; private final FingerprintUpdater mFingerprintUpdater;
private final MessageDisplayController mMessageDisplayController;
@Nullable private CancellationSignal mCancellationSignal = null; @Nullable private CancellationSignal mCancellationSignal = null;
private final EnrollmentCallback mEnrollmentCallback = new EnrollmentCallback() { private final EnrollmentCallback mEnrollmentCallback = new EnrollmentCallback() {
@@ -81,6 +82,9 @@ public class FingerprintEnrollProgressViewModel extends AndroidViewModel {
@Override @Override
public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) { public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
if (DEBUG) {
Log.d(TAG, "onEnrollmentHelp(" + helpMsgId + ", " + helpString + ")");
}
mHelpMessageLiveData.postValue(new EnrollmentStatusMessage(helpMsgId, helpString)); mHelpMessageLiveData.postValue(new EnrollmentStatusMessage(helpMsgId, helpString));
} }
@@ -113,20 +117,6 @@ public class FingerprintEnrollProgressViewModel extends AndroidViewModel {
super(application); super(application);
mFingerprintUpdater = fingerprintUpdater; mFingerprintUpdater = fingerprintUpdater;
mUserId = userId; mUserId = userId;
final Resources res = application.getResources();
mMessageDisplayController =
res.getBoolean(R.bool.enrollment_message_display_controller_flag)
? new MessageDisplayController(
application.getMainThreadHandler(),
mEnrollmentCallback,
SystemClock.elapsedRealtimeClock(),
res.getInteger(R.integer.enrollment_help_minimum_time_display),
res.getInteger(R.integer.enrollment_progress_minimum_time_display),
res.getBoolean(R.bool.enrollment_progress_priority_over_help),
res.getBoolean(R.bool.enrollment_prioritize_acquire_messages),
res.getInteger(R.integer.enrollment_collect_time))
: null;
} }
public void setToken(byte[] token) { public void setToken(byte[] token) {
@@ -195,9 +185,24 @@ public class FingerprintEnrollProgressViewModel extends AndroidViewModel {
mErrorMessageLiveData.setValue(null); mErrorMessageLiveData.setValue(null);
mCancellationSignal = new CancellationSignal(); mCancellationSignal = new CancellationSignal();
mFingerprintUpdater.enroll(mToken, mCancellationSignal, mUserId,
mMessageDisplayController != null ? mMessageDisplayController : mEnrollmentCallback, final Resources res = getApplication().getResources();
reason); if (reason == ENROLL_ENROLL
&& res.getBoolean(R.bool.enrollment_message_display_controller_flag)) {
final EnrollmentCallback callback = new MessageDisplayController(
getApplication().getMainThreadHandler(),
mEnrollmentCallback,
SystemClock.elapsedRealtimeClock(),
res.getInteger(R.integer.enrollment_help_minimum_time_display),
res.getInteger(R.integer.enrollment_progress_minimum_time_display),
res.getBoolean(R.bool.enrollment_progress_priority_over_help),
res.getBoolean(R.bool.enrollment_prioritize_acquire_messages),
res.getInteger(R.integer.enrollment_collect_time));
mFingerprintUpdater.enroll(mToken, mCancellationSignal, mUserId, callback, reason);
} else {
mFingerprintUpdater.enroll(mToken, mCancellationSignal, mUserId, mEnrollmentCallback,
reason);
}
return true; return true;
} }

View File

@@ -22,6 +22,7 @@ import com.android.settings.accounts.AccountDashboardFragment;
import com.android.settings.applications.manageapplications.ManageApplications; import com.android.settings.applications.manageapplications.ManageApplications;
import com.android.settings.deviceinfo.StorageDashboardFragment; import com.android.settings.deviceinfo.StorageDashboardFragment;
import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment; import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment;
import com.android.settings.inputmethod.NewKeyboardLayoutEnabledLocalesFragment;
import com.android.settings.location.LocationServices; import com.android.settings.location.LocationServices;
import java.util.Map; import java.util.Map;
@@ -49,5 +50,7 @@ public class ProfileFragmentBridge {
ProfileSelectStorageFragment.class.getName()); ProfileSelectStorageFragment.class.getName());
FRAGMENT_MAP.put(AvailableVirtualKeyboardFragment.class.getName(), FRAGMENT_MAP.put(AvailableVirtualKeyboardFragment.class.getName(),
ProfileSelectKeyboardFragment.class.getName()); ProfileSelectKeyboardFragment.class.getName());
FRAGMENT_MAP.put(NewKeyboardLayoutEnabledLocalesFragment.class.getName(),
ProfileSelectPhysicalKeyboardFragment.class.getName());
} }
} }

View File

@@ -0,0 +1,72 @@
/*
* Copyright (C) 2023 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.dashboard.profileselector;
import android.hardware.input.InputDeviceIdentifier;
import android.os.Bundle;
import android.provider.Settings;
import androidx.fragment.app.Fragment;
import com.android.settings.R;
import com.android.settings.inputmethod.NewKeyboardLayoutEnabledLocalesFragment;
/**
* When current user has work profile, this fragment used following fragments to represent the
* enabled IMEs keyboard layout settings page.
*
* <p>{@link NewKeyboardLayoutEnabledLocalesFragment} used to show both of personal/work user
* enabled IMEs and their physical keyboard layouts.</p>
*/
public final class ProfileSelectPhysicalKeyboardFragment extends ProfileSelectFragment {
private InputDeviceIdentifier mInputDeviceIdentifier;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
Bundle arguments = getArguments();
mInputDeviceIdentifier =
arguments.getParcelable(Settings.EXTRA_INPUT_DEVICE_IDENTIFIER);
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.keyboard_settings_enabled_locales_list;
}
@Override
public Fragment[] getFragments() {
final Bundle personalOnly = new Bundle();
personalOnly.putInt(EXTRA_PROFILE, ProfileType.PERSONAL);
final Fragment personalFragment = new NewKeyboardLayoutEnabledLocalesFragment();
personalOnly.putParcelable(
Settings.EXTRA_INPUT_DEVICE_IDENTIFIER, mInputDeviceIdentifier);
personalFragment.setArguments(personalOnly);
final Bundle workOnly = new Bundle();
workOnly.putInt(EXTRA_PROFILE, ProfileType.WORK);
final Fragment workFragment = new NewKeyboardLayoutEnabledLocalesFragment();
workOnly.putParcelable(Settings.EXTRA_INPUT_DEVICE_IDENTIFIER, mInputDeviceIdentifier);
workFragment.setArguments(workOnly);
return new Fragment[]{
personalFragment,
workFragment
};
}
}

View File

@@ -23,6 +23,7 @@ import android.graphics.drawable.Drawable;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.widget.AdapterView; import android.widget.AdapterView;
@@ -48,9 +49,11 @@ import com.android.settingslib.core.lifecycle.events.OnDestroy;
import com.android.settingslib.core.lifecycle.events.OnResume; import com.android.settingslib.core.lifecycle.events.OnResume;
import com.android.settingslib.widget.FooterPreference; import com.android.settingslib.widget.FooterPreference;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
/** Controller for battery usage breakdown preference group. */ /** Controller for battery usage breakdown preference group. */
public class BatteryUsageBreakdownController extends BasePreferenceController public class BatteryUsageBreakdownController extends BasePreferenceController
@@ -61,6 +64,7 @@ public class BatteryUsageBreakdownController extends BasePreferenceController
private static final String SPINNER_PREFERENCE_KEY = "battery_usage_spinner"; private static final String SPINNER_PREFERENCE_KEY = "battery_usage_spinner";
private static final String APP_LIST_PREFERENCE_KEY = "app_list"; private static final String APP_LIST_PREFERENCE_KEY = "app_list";
private static final String PACKAGE_NAME_NONE = "none"; private static final String PACKAGE_NAME_NONE = "none";
private static final List<BatteryDiffEntry> EMPTY_ENTRY_LIST = new ArrayList<>();
private static int sUiMode = Configuration.UI_MODE_NIGHT_UNDEFINED; private static int sUiMode = Configuration.UI_MODE_NIGHT_UNDEFINED;
@@ -183,7 +187,7 @@ public class BatteryUsageBreakdownController extends BasePreferenceController
if (mSpinnerPosition != position) { if (mSpinnerPosition != position) {
mSpinnerPosition = position; mSpinnerPosition = position;
mHandler.post(() -> { mHandler.post(() -> {
removeAndCacheAllPreferences(); removeAndCacheAllUnusedPreferences();
addAllPreferences(); addAllPreferences();
mMetricsFeatureProvider.action( mMetricsFeatureProvider.action(
mPrefContext, mPrefContext,
@@ -238,27 +242,34 @@ public class BatteryUsageBreakdownController extends BasePreferenceController
private void showSpinnerAndAppList() { private void showSpinnerAndAppList() {
if (mBatteryDiffData == null) { if (mBatteryDiffData == null) {
mHandler.post(() -> { mHandler.post(() -> {
removeAndCacheAllPreferences(); removeAndCacheAllUnusedPreferences();
}); });
return; return;
} }
mSpinnerPreference.setVisible(true); mSpinnerPreference.setVisible(true);
mAppListPreferenceGroup.setVisible(true); mAppListPreferenceGroup.setVisible(true);
mHandler.post(() -> { mHandler.post(() -> {
removeAndCacheAllPreferences(); removeAndCacheAllUnusedPreferences();
addAllPreferences(); addAllPreferences();
}); });
} }
private List<BatteryDiffEntry> getBatteryDiffEntries() {
if (mBatteryDiffData == null) {
return EMPTY_ENTRY_LIST;
}
return mSpinnerPosition == 0
? mBatteryDiffData.getAppDiffEntryList()
: mBatteryDiffData.getSystemDiffEntryList();
}
@VisibleForTesting @VisibleForTesting
void addAllPreferences() { void addAllPreferences() {
if (mBatteryDiffData == null) { if (mBatteryDiffData == null) {
return; return;
} }
final long start = System.currentTimeMillis(); final long start = System.currentTimeMillis();
final List<BatteryDiffEntry> entries = mSpinnerPosition == 0 final List<BatteryDiffEntry> entries = getBatteryDiffEntries();
? mBatteryDiffData.getAppDiffEntryList()
: mBatteryDiffData.getSystemDiffEntryList();
int prefIndex = mAppListPreferenceGroup.getPreferenceCount(); int prefIndex = mAppListPreferenceGroup.getPreferenceCount();
for (BatteryDiffEntry entry : entries) { for (BatteryDiffEntry entry : entries) {
boolean isAdded = false; boolean isAdded = false;
@@ -272,7 +283,6 @@ public class BatteryUsageBreakdownController extends BasePreferenceController
PowerGaugePreference pref = mAppListPreferenceGroup.findPreference(prefKey); PowerGaugePreference pref = mAppListPreferenceGroup.findPreference(prefKey);
if (pref != null) { if (pref != null) {
isAdded = true; isAdded = true;
Log.w(TAG, "preference should be removed for:" + entry.getPackageName());
} else { } else {
pref = (PowerGaugePreference) mPreferenceCache.get(prefKey); pref = (PowerGaugePreference) mPreferenceCache.get(prefKey);
} }
@@ -301,16 +311,25 @@ public class BatteryUsageBreakdownController extends BasePreferenceController
} }
@VisibleForTesting @VisibleForTesting
void removeAndCacheAllPreferences() { void removeAndCacheAllUnusedPreferences() {
List<BatteryDiffEntry> entries = getBatteryDiffEntries();
Set<String> entryKeySet = new ArraySet<>();
for (BatteryDiffEntry entry : entries) {
entryKeySet.add(entry.getKey());
}
final int prefsCount = mAppListPreferenceGroup.getPreferenceCount(); final int prefsCount = mAppListPreferenceGroup.getPreferenceCount();
for (int index = 0; index < prefsCount; index++) { for (int index = prefsCount - 1; index >= 0; index--) {
final Preference pref = mAppListPreferenceGroup.getPreference(index); final Preference pref = mAppListPreferenceGroup.getPreference(index);
if (TextUtils.isEmpty(pref.getKey())) { if (entryKeySet.contains(pref.getKey())) {
// The pref is still used, don't remove.
continue; continue;
} }
mPreferenceCache.put(pref.getKey(), pref); if (!TextUtils.isEmpty(pref.getKey())) {
mPreferenceCache.put(pref.getKey(), pref);
}
mAppListPreferenceGroup.removePreference(pref);
} }
mAppListPreferenceGroup.removeAll();
} }
@VisibleForTesting @VisibleForTesting

View File

@@ -23,6 +23,7 @@ import android.hardware.input.InputManager;
import android.hardware.input.KeyboardLayout; import android.hardware.input.KeyboardLayout;
import android.os.Bundle; import android.os.Bundle;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log; import android.util.Log;
import android.view.InputDevice; import android.view.InputDevice;
import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodInfo;
@@ -34,8 +35,10 @@ import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.core.SubSettingLauncher; import com.android.settings.core.SubSettingLauncher;
import com.android.settings.dashboard.DashboardFragment; import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
import com.android.settings.inputmethod.NewKeyboardSettingsUtils.KeyboardInfo; import com.android.settings.inputmethod.NewKeyboardSettingsUtils.KeyboardInfo;
import java.util.ArrayList; import java.util.ArrayList;
@@ -56,6 +59,39 @@ public class NewKeyboardLayoutEnabledLocalesFragment extends DashboardFragment
private Context mContext; private Context mContext;
private ArrayList<KeyboardInfo> mKeyboardInfoList = new ArrayList<>(); private ArrayList<KeyboardInfo> mKeyboardInfoList = new ArrayList<>();
@Override
public void onAttach(Context context) {
super.onAttach(context);
mContext = context;
final int profileType = getArguments().getInt(ProfileSelectFragment.EXTRA_PROFILE);
final int currentUserId = UserHandle.myUserId();
final int newUserId;
final UserManager userManager = mContext.getSystemService(UserManager.class);
switch (profileType) {
case ProfileSelectFragment.ProfileType.WORK: {
// If the user is a managed profile user, use currentUserId directly. Or get the
// managed profile userId instead.
newUserId = userManager.isManagedProfile()
? currentUserId : Utils.getManagedProfileId(userManager, currentUserId);
break;
}
case ProfileSelectFragment.ProfileType.PERSONAL: {
final UserHandle primaryUser = userManager.getPrimaryUser().getUserHandle();
newUserId = primaryUser.getIdentifier();
break;
}
default:
newUserId = currentUserId;
}
mUserId = newUserId;
mIm = mContext.getSystemService(InputManager.class);
mImm = mContext.getSystemService(InputMethodManager.class);
mInputDeviceId = -1;
}
@Override @Override
public void onActivityCreated(final Bundle icicle) { public void onActivityCreated(final Bundle icicle) {
super.onActivityCreated(icicle); super.onActivityCreated(icicle);
@@ -74,13 +110,39 @@ public class NewKeyboardLayoutEnabledLocalesFragment extends DashboardFragment
} }
final String title = inputDevice.getName(); final String title = inputDevice.getName();
getActivity().setTitle(title); getActivity().setTitle(title);
}
@Override
public void onStart() {
super.onStart();
mIm.registerInputDeviceListener(this, null);
InputDevice inputDevice =
NewKeyboardSettingsUtils.getInputDevice(mIm, mInputDeviceIdentifier);
if (inputDevice == null) {
getActivity().finish();
return;
}
mInputDeviceId = inputDevice.getId();
}
@Override
public void onResume() {
super.onResume();
updateCheckedState(); updateCheckedState();
} }
@Override
public void onStop() {
super.onStop();
mIm.unregisterInputDeviceListener(this);
mInputDeviceId = -1;
}
private void updateCheckedState() { private void updateCheckedState() {
if (NewKeyboardSettingsUtils.getInputDevice(mIm, mInputDeviceIdentifier) == null) { if (NewKeyboardSettingsUtils.getInputDevice(mIm, mInputDeviceIdentifier) == null) {
return; return;
} }
PreferenceScreen preferenceScreen = getPreferenceScreen(); PreferenceScreen preferenceScreen = getPreferenceScreen();
preferenceScreen.removeAll(); preferenceScreen.removeAll();
List<InputMethodInfo> infoList = mImm.getEnabledInputMethodListAsUser(mUserId); List<InputMethodInfo> infoList = mImm.getEnabledInputMethodListAsUser(mUserId);
@@ -95,7 +157,7 @@ public class NewKeyboardLayoutEnabledLocalesFragment extends DashboardFragment
for (InputMethodInfo info : infoList) { for (InputMethodInfo info : infoList) {
mKeyboardInfoList.clear(); mKeyboardInfoList.clear();
List<InputMethodSubtype> subtypes = List<InputMethodSubtype> subtypes =
mImm.getEnabledInputMethodSubtypeList(info, true); mImm.getEnabledInputMethodSubtypeListAsUser(info.getId(), true, mUserId);
for (InputMethodSubtype subtype : subtypes) { for (InputMethodSubtype subtype : subtypes) {
if (subtype.isSuitableForPhysicalKeyboardLayoutMapping()) { if (subtype.isSuitableForPhysicalKeyboardLayoutMapping()) {
mapLanguageWithLayout(info, subtype); mapLanguageWithLayout(info, subtype);
@@ -188,42 +250,6 @@ public class NewKeyboardLayoutEnabledLocalesFragment extends DashboardFragment
} }
} }
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = getContext();
mIm = mContext.getSystemService(InputManager.class);
mImm = mContext.getSystemService(InputMethodManager.class);
mInputDeviceId = -1;
mUserId = UserHandle.myUserId();
}
@Override
public void onStart() {
super.onStart();
mIm.registerInputDeviceListener(this, null);
InputDevice inputDevice =
NewKeyboardSettingsUtils.getInputDevice(mIm, mInputDeviceIdentifier);
if (inputDevice == null) {
getActivity().finish();
return;
}
mInputDeviceId = inputDevice.getId();
}
@Override
public void onStop() {
super.onStop();
mIm.unregisterInputDeviceListener(this);
mInputDeviceId = -1;
}
@Override
public void onResume() {
super.onResume();
updateCheckedState();
}
@Override @Override
protected String getLogTag() { protected String getLogTag() {
return TAG; return TAG;

View File

@@ -79,7 +79,7 @@ public class AirplaneModePreferenceController extends TogglePreferenceController
@Override @Override
public boolean handlePreferenceTreeClick(Preference preference) { public boolean handlePreferenceTreeClick(Preference preference) {
if (KEY_AIRPLANE_MODE.equals(preference.getKey()) if (KEY_AIRPLANE_MODE.equals(preference.getKey()) && isAvailable()
&& mAirplaneModeEnabler.isInEcmMode()) { && mAirplaneModeEnabler.isInEcmMode()) {
// In ECM mode launch ECM app dialog // In ECM mode launch ECM app dialog
if (mFragment != null) { if (mFragment != null) {
@@ -141,12 +141,14 @@ public class AirplaneModePreferenceController extends TogglePreferenceController
@Override @Override
public void onDestroy() { public void onDestroy() {
mAirplaneModeEnabler.close(); if (isAvailable()) {
mAirplaneModeEnabler.close();
}
} }
public void onActivityResult(int requestCode, int resultCode, Intent data) { public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_EXIT_ECM) { if (requestCode == REQUEST_CODE_EXIT_ECM && isAvailable()) {
final boolean isChoiceYes = (resultCode == Activity.RESULT_OK); final boolean isChoiceYes = (resultCode == Activity.RESULT_OK);
// Set Airplane mode based on the return value and checkbox state // Set Airplane mode based on the return value and checkbox state
mAirplaneModeEnabler.setAirplaneModeInECM(isChoiceYes, mAirplaneModeEnabler.setAirplaneModeInECM(isChoiceYes,
@@ -156,7 +158,7 @@ public class AirplaneModePreferenceController extends TogglePreferenceController
@Override @Override
public boolean isChecked() { public boolean isChecked() {
return mAirplaneModeEnabler.isAirplaneModeOn(); return isAvailable() && mAirplaneModeEnabler.isAirplaneModeOn();
} }
@Override @Override
@@ -164,7 +166,9 @@ public class AirplaneModePreferenceController extends TogglePreferenceController
if (isChecked() == isChecked) { if (isChecked() == isChecked) {
return false; return false;
} }
mAirplaneModeEnabler.setAirplaneMode(isChecked); if (isAvailable()) {
mAirplaneModeEnabler.setAirplaneMode(isChecked);
}
return true; return true;
} }

View File

@@ -350,10 +350,15 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme
} }
} }
@Override
public void onPause() {
mMobileNetworkRepository.removeRegister(this);
super.onPause();
}
@Override @Override
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
mMobileNetworkRepository.removeRegister(this);
} }
@VisibleForTesting @VisibleForTesting

View File

@@ -18,9 +18,6 @@ package com.android.settings.nfc;
import android.content.Context; import android.content.Context;
import android.nfc.NfcAdapter; import android.nfc.NfcAdapter;
import android.provider.Settings;
import androidx.annotation.VisibleForTesting;
import com.android.settingslib.widget.MainSwitchPreference; import com.android.settingslib.widget.MainSwitchPreference;
@@ -41,7 +38,7 @@ public class NfcEnabler extends BaseNfcEnabler {
switch (newState) { switch (newState) {
case NfcAdapter.STATE_OFF: case NfcAdapter.STATE_OFF:
mPreference.updateStatus(false); mPreference.updateStatus(false);
mPreference.setEnabled(isToggleable()); mPreference.setEnabled(true);
break; break;
case NfcAdapter.STATE_ON: case NfcAdapter.STATE_ON:
mPreference.updateStatus(true); mPreference.updateStatus(true);
@@ -57,15 +54,4 @@ public class NfcEnabler extends BaseNfcEnabler {
break; break;
} }
} }
@VisibleForTesting
boolean isToggleable() {
if (NfcPreferenceController.isToggleableInAirplaneMode(mContext)
|| !NfcPreferenceController.shouldTurnOffNFCInAirplaneMode(mContext)) {
return true;
}
final int airplaneMode = Settings.Global.getInt(
mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0);
return airplaneMode != 1;
}
} }

View File

@@ -21,7 +21,6 @@ import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.net.Uri; import android.net.Uri;
import android.nfc.NfcAdapter; import android.nfc.NfcAdapter;
import android.provider.Settings;
import android.util.Log; import android.util.Log;
import android.widget.Switch; import android.widget.Switch;
@@ -128,18 +127,6 @@ public class NfcPreferenceController extends TogglePreferenceController
} }
} }
public static boolean shouldTurnOffNFCInAirplaneMode(Context context) {
final String airplaneModeRadios = Settings.Global.getString(context.getContentResolver(),
Settings.Global.AIRPLANE_MODE_RADIOS);
return airplaneModeRadios != null && airplaneModeRadios.contains(Settings.Global.RADIO_NFC);
}
public static boolean isToggleableInAirplaneMode(Context context) {
final String toggleable = Settings.Global.getString(context.getContentResolver(),
Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS);
return toggleable != null && toggleable.contains(Settings.Global.RADIO_NFC);
}
/** /**
* Listener for background changes to NFC. * Listener for background changes to NFC.
* *

View File

@@ -20,6 +20,7 @@ import static android.provider.Settings.Secure.TIMEOUT_TO_DOCK_USER;
import android.content.Context; import android.content.Context;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings; import android.provider.Settings;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
@@ -34,6 +35,8 @@ import java.util.Arrays;
* automatically switch to the designated Dock User when the device is docked. * automatically switch to the designated Dock User when the device is docked.
*/ */
public class TimeoutToDockUserPreferenceController extends BasePreferenceController { public class TimeoutToDockUserPreferenceController extends BasePreferenceController {
private final UserManager mUserManager;
private final String[] mEntries; private final String[] mEntries;
private final String[] mValues; private final String[] mValues;
@@ -41,6 +44,8 @@ public class TimeoutToDockUserPreferenceController extends BasePreferenceControl
String preferenceKey) { String preferenceKey) {
super(context, preferenceKey); super(context, preferenceKey);
mUserManager = context.getSystemService(UserManager.class);
mEntries = mContext.getResources().getStringArray( mEntries = mContext.getResources().getStringArray(
com.android.settings.R.array.switch_to_dock_user_when_docked_timeout_entries); com.android.settings.R.array.switch_to_dock_user_when_docked_timeout_entries);
mValues = mContext.getResources().getStringArray( mValues = mContext.getResources().getStringArray(
@@ -62,9 +67,10 @@ public class TimeoutToDockUserPreferenceController extends BasePreferenceControl
return UNSUPPORTED_ON_DEVICE; return UNSUPPORTED_ON_DEVICE;
} }
// Multi-user feature disabled by user. // Multi-user feature disabled by user, or user switching blocked on the user.
if (Settings.Global.getInt(mContext.getContentResolver(), if (Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.USER_SWITCHER_ENABLED, 0) != 1) { Settings.Global.USER_SWITCHER_ENABLED, 0) != 1
|| mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)) {
return CONDITIONALLY_UNAVAILABLE; return CONDITIONALLY_UNAVAILABLE;
} }

View File

@@ -55,6 +55,7 @@ import java.util.TimeZone;
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
public final class BatteryUsageBreakdownControllerTest { public final class BatteryUsageBreakdownControllerTest {
private static final String PREF_KEY = "pref_key"; private static final String PREF_KEY = "pref_key";
private static final String PREF_KEY2 = "pref_key2";
private static final String PREF_SUMMARY = "fake preference summary"; private static final String PREF_SUMMARY = "fake preference summary";
@Mock @Mock
@@ -175,7 +176,24 @@ public final class BatteryUsageBreakdownControllerTest {
} }
@Test @Test
public void removeAndCacheAllPreferences_buildCacheAndRemoveAllPreference() { public void removeAndCacheAllUnusedPreferences_removePerf_buildCacheAndRemoveAllPreference() {
doReturn(1).when(mAppListPreferenceGroup).getPreferenceCount();
doReturn(mPowerGaugePreference).when(mAppListPreferenceGroup).getPreference(0);
doReturn(PREF_KEY2).when(mBatteryHistEntry).getKey();
doReturn(PREF_KEY).when(mPowerGaugePreference).getKey();
doReturn(mPowerGaugePreference).when(mAppListPreferenceGroup).findPreference(PREF_KEY);
// Ensures the testing data is correct.
assertThat(mBatteryUsageBreakdownController.mPreferenceCache).isEmpty();
mBatteryUsageBreakdownController.removeAndCacheAllUnusedPreferences();
assertThat(mBatteryUsageBreakdownController.mPreferenceCache.get(PREF_KEY))
.isEqualTo(mPowerGaugePreference);
verify(mAppListPreferenceGroup).removePreference(mPowerGaugePreference);
}
@Test
public void removeAndCacheAllUnusedPreferences_keepPerf_KeepAllPreference() {
doReturn(1).when(mAppListPreferenceGroup).getPreferenceCount(); doReturn(1).when(mAppListPreferenceGroup).getPreferenceCount();
doReturn(mPowerGaugePreference).when(mAppListPreferenceGroup).getPreference(0); doReturn(mPowerGaugePreference).when(mAppListPreferenceGroup).getPreference(0);
doReturn(PREF_KEY).when(mBatteryHistEntry).getKey(); doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
@@ -184,11 +202,10 @@ public final class BatteryUsageBreakdownControllerTest {
// Ensures the testing data is correct. // Ensures the testing data is correct.
assertThat(mBatteryUsageBreakdownController.mPreferenceCache).isEmpty(); assertThat(mBatteryUsageBreakdownController.mPreferenceCache).isEmpty();
mBatteryUsageBreakdownController.removeAndCacheAllPreferences(); mBatteryUsageBreakdownController.removeAndCacheAllUnusedPreferences();
assertThat(mBatteryUsageBreakdownController.mPreferenceCache.get(PREF_KEY)) verify(mAppListPreferenceGroup, never()).removePreference(any());
.isEqualTo(mPowerGaugePreference); assertThat(mBatteryUsageBreakdownController.mPreferenceCache).isEmpty();
verify(mAppListPreferenceGroup).removeAll();
} }
@Test @Test

View File

@@ -16,15 +16,12 @@
package com.android.settings.nfc; package com.android.settings.nfc;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.nfc.NfcAdapter; import android.nfc.NfcAdapter;
import android.provider.Settings;
import com.android.settingslib.widget.MainSwitchPreference; import com.android.settingslib.widget.MainSwitchPreference;
@@ -52,55 +49,14 @@ public class NfcEnablerTest {
mNfcEnabler = spy(new NfcEnabler(mContext, mNfcPreference)); mNfcEnabler = spy(new NfcEnabler(mContext, mNfcPreference));
} }
@Test
public void isToggleable_AirplaneModeOff_shouldReturnTrue() {
final ContentResolver contentResolver = mContext.getContentResolver();
Settings.Global.putInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0);
Settings.Global.putString(contentResolver,
Settings.Global.AIRPLANE_MODE_RADIOS, Settings.Global.RADIO_NFC);
Settings.Global.putString(contentResolver,
Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS, Settings.Global.RADIO_NFC);
assertThat(mNfcEnabler.isToggleable()).isTrue();
}
@Test
public void isToggleable_AirplaneModeOnNfcNotInAirplaneModeRadio_shouldReturnTrue() {
final ContentResolver contentResolver = mContext.getContentResolver();
Settings.Global.putInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 1);
Settings.Global.putString(contentResolver, Settings.Global.AIRPLANE_MODE_RADIOS, "");
assertThat(mNfcEnabler.isToggleable()).isTrue();
}
@Test
public void isToggleable_AirplaneModeOnNfcToggleable_shouldReturnTrue() {
final ContentResolver contentResolver = mContext.getContentResolver();
Settings.Global.putInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 1);
Settings.Global.putString(contentResolver,
Settings.Global.AIRPLANE_MODE_RADIOS, Settings.Global.RADIO_NFC);
Settings.Global.putString(contentResolver,
Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS, Settings.Global.RADIO_NFC);
assertThat(mNfcEnabler.isToggleable()).isTrue();
}
@Test
public void isToggleable_AirplaneModeOnNfcNotToggleable_shouldReturnFalse() {
final ContentResolver contentResolver = mContext.getContentResolver();
Settings.Global.putInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 1);
Settings.Global.putString(contentResolver,
Settings.Global.AIRPLANE_MODE_RADIOS, Settings.Global.RADIO_NFC);
Settings.Global.putString(contentResolver,
Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS, "");
assertThat(mNfcEnabler.isToggleable()).isFalse();
}
@Test @Test
public void handleNfcStateChanged_stateOff_shouldCheckIfPreferenceEnableState() { public void handleNfcStateChanged_stateOff_shouldCheckIfPreferenceEnableState() {
mNfcEnabler.handleNfcStateChanged(NfcAdapter.STATE_OFF); mNfcEnabler.handleNfcStateChanged(NfcAdapter.STATE_OFF);
verify(mNfcPreference).updateStatus(false);
verify(mNfcPreference).setEnabled(true);
verify(mNfcEnabler).isToggleable(); mNfcEnabler.handleNfcStateChanged(NfcAdapter.STATE_ON);
verify(mNfcPreference).updateStatus(true);
verify(mNfcPreference, times(2)).setEnabled(true);
} }
} }

View File

@@ -28,7 +28,6 @@ import android.content.Intent;
import android.nfc.NfcAdapter; import android.nfc.NfcAdapter;
import android.nfc.NfcManager; import android.nfc.NfcManager;
import android.os.UserManager; import android.os.UserManager;
import android.provider.Settings;
import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceScreen;
@@ -188,44 +187,6 @@ public class NfcPreferenceControllerTest {
assertThat(mNfcController.hasAsyncUpdate()).isTrue(); assertThat(mNfcController.hasAsyncUpdate()).isTrue();
} }
@Test
public void isToggleableInAirplaneMode_containNfc_shouldReturnTrue() {
Settings.Global.putString(mContext.getContentResolver(),
Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS,
Settings.Global.RADIO_NFC);
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON, 1);
assertThat(NfcPreferenceController.isToggleableInAirplaneMode(mContext)).isTrue();
}
@Test
public void isToggleableInAirplaneMode_withoutNfc_shouldReturnFalse() {
Settings.Global.putString(mContext.getContentResolver(),
Settings.Global.AIRPLANE_MODE_TOGGLEABLE_RADIOS,
"null");
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON, 1);
assertThat(NfcPreferenceController.isToggleableInAirplaneMode(mContext)).isFalse();
}
@Test
public void shouldTurnOffNFCInAirplaneMode_airplaneModeRadiosContainsNfc_shouldReturnTrue() {
Settings.Global.putString(mContext.getContentResolver(),
Settings.Global.AIRPLANE_MODE_RADIOS, Settings.Global.RADIO_NFC);
assertThat(NfcPreferenceController.shouldTurnOffNFCInAirplaneMode(mContext)).isTrue();
}
@Test
public void shouldTurnOffNFCInAirplaneMode_airplaneModeRadiosWithoutNfc_shouldReturnFalse() {
Settings.Global.putString(mContext.getContentResolver(),
Settings.Global.AIRPLANE_MODE_RADIOS, "");
assertThat(NfcPreferenceController.shouldTurnOffNFCInAirplaneMode(mContext)).isFalse();
}
@Test @Test
public void ncfSliceWorker_nfcBroadcast_noExtra_sliceDoesntUpdate() { public void ncfSliceWorker_nfcBroadcast_noExtra_sliceDoesntUpdate() {
final NfcSliceWorker worker = spy( final NfcSliceWorker worker = spy(

View File

@@ -27,6 +27,7 @@ import static org.mockito.Mockito.when;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings; import android.provider.Settings;
import androidx.test.core.app.ApplicationProvider; import androidx.test.core.app.ApplicationProvider;
@@ -41,6 +42,8 @@ import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner; import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
@@ -51,6 +54,9 @@ public class TimeoutToDockUserPreferenceControllerTest {
private Resources mResources; private Resources mResources;
private TimeoutToDockUserPreferenceController mController; private TimeoutToDockUserPreferenceController mController;
@Mock
private UserManager mUserManager;
private static final String FAKE_PREFERENCE_KEY = "timeout_to_dock_user_preference"; private static final String FAKE_PREFERENCE_KEY = "timeout_to_dock_user_preference";
private String[] mEntries; private String[] mEntries;
@@ -58,9 +64,12 @@ public class TimeoutToDockUserPreferenceControllerTest {
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(ApplicationProvider.getApplicationContext()); mContext = spy(ApplicationProvider.getApplicationContext());
mResources = spy(mContext.getResources()); mResources = spy(mContext.getResources());
doReturn(mResources).when(mContext).getResources(); doReturn(mResources).when(mContext).getResources();
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
mEntries = mResources.getStringArray( mEntries = mResources.getStringArray(
R.array.switch_to_dock_user_when_docked_timeout_entries); R.array.switch_to_dock_user_when_docked_timeout_entries);
@@ -78,6 +87,9 @@ public class TimeoutToDockUserPreferenceControllerTest {
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.USER_SWITCHER_ENABLED, Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.USER_SWITCHER_ENABLED,
1); 1);
// User switching not blocked.
when(mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)).thenReturn(false);
// Set to user 1; // Set to user 1;
ShadowUserHandle.setUid(1); ShadowUserHandle.setUid(1);
} }
@@ -106,6 +118,14 @@ public class TimeoutToDockUserPreferenceControllerTest {
BasePreferenceController.CONDITIONALLY_UNAVAILABLE); BasePreferenceController.CONDITIONALLY_UNAVAILABLE);
} }
@Test
public void getAvailabilityStatus_userSwitchingBlocked_returnConditionallyUnavailable() {
when(mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)).thenReturn(true);
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.CONDITIONALLY_UNAVAILABLE);
}
@Test @Test
public void getAvailabilityStatus_isCurrentlyMainUser_returnDisabledForUser() { public void getAvailabilityStatus_isCurrentlyMainUser_returnDisabledForUser() {
when(Utils.canCurrentUserDream(mContext)).thenReturn(true); when(Utils.canCurrentUserDream(mContext)).thenReturn(true);

View File

@@ -21,6 +21,8 @@ import static android.hardware.fingerprint.FingerprintManager.ENROLL_FIND_SENSOR
import static android.hardware.fingerprint.FingerprintManager.EnrollReason; import static android.hardware.fingerprint.FingerprintManager.EnrollReason;
import static android.hardware.fingerprint.FingerprintManager.EnrollmentCallback; import static android.hardware.fingerprint.FingerprintManager.EnrollmentCallback;
import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
@@ -29,18 +31,24 @@ import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.eq; import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.only; import static org.mockito.Mockito.only;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import android.app.Application; import android.app.Application;
import android.content.res.Resources; import android.content.res.Resources;
import android.os.CancellationSignal; import android.os.CancellationSignal;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.settings.R;
import com.android.settings.biometrics.fingerprint.FingerprintUpdater; import com.android.settings.biometrics.fingerprint.FingerprintUpdater;
import com.android.settings.biometrics.fingerprint.MessageDisplayController;
import com.android.settings.biometrics2.ui.model.EnrollmentProgress; import com.android.settings.biometrics2.ui.model.EnrollmentProgress;
import com.android.settings.biometrics2.ui.model.EnrollmentStatusMessage; import com.android.settings.biometrics2.ui.model.EnrollmentStatusMessage;
import com.android.settings.testutils.InstantTaskExecutorRule; import com.android.settings.testutils.InstantTaskExecutorRule;
@@ -68,12 +76,18 @@ public class FingerprintEnrollProgressViewModelTest {
private FingerprintEnrollProgressViewModel mViewModel; private FingerprintEnrollProgressViewModel mViewModel;
private final TestWrapper<CancellationSignal> mCancellationSignalWrapper = new TestWrapper<>(); private final TestWrapper<CancellationSignal> mCancellationSignalWrapper = new TestWrapper<>();
private final TestWrapper<EnrollmentCallback> mCallbackWrapper = new TestWrapper<>(); private final TestWrapper<EnrollmentCallback> mCallbackWrapper = new TestWrapper<>();
private int mEnrollmentMessageDisplayControllerFlagResId;
@Before @Before
public void setUp() { public void setUp() {
mEnrollmentMessageDisplayControllerFlagResId = ApplicationProvider.getApplicationContext()
.getResources().getIdentifier("enrollment_message_display_controller_flag", "bool",
SETTINGS_PACKAGE_NAME);
when(mApplication.getResources()).thenReturn(mResources); when(mApplication.getResources()).thenReturn(mResources);
when(mResources.getBoolean(R.bool.enrollment_message_display_controller_flag))
.thenReturn(false); // Not use MessageDisplayController by default
when(mResources.getBoolean(mEnrollmentMessageDisplayControllerFlagResId)).thenReturn(false);
mViewModel = new FingerprintEnrollProgressViewModel(mApplication, mFingerprintUpdater, mViewModel = new FingerprintEnrollProgressViewModel(mApplication, mFingerprintUpdater,
TEST_USER_ID); TEST_USER_ID);
@@ -88,7 +102,7 @@ public class FingerprintEnrollProgressViewModelTest {
} }
@Test @Test
public void testStartEnrollment() { public void testStartFindSensor() {
@EnrollReason final int enrollReason = ENROLL_FIND_SENSOR; @EnrollReason final int enrollReason = ENROLL_FIND_SENSOR;
final byte[] token = new byte[] { 1, 2, 3 }; final byte[] token = new byte[] { 1, 2, 3 };
mViewModel.setToken(token); mViewModel.setToken(token);
@@ -99,6 +113,54 @@ public class FingerprintEnrollProgressViewModelTest {
assertThat(ret).isTrue(); assertThat(ret).isTrue();
verify(mFingerprintUpdater, only()).enroll(eq(token), any(CancellationSignal.class), verify(mFingerprintUpdater, only()).enroll(eq(token), any(CancellationSignal.class),
eq(TEST_USER_ID), any(EnrollmentCallback.class), eq(enrollReason)); eq(TEST_USER_ID), any(EnrollmentCallback.class), eq(enrollReason));
assertThat(mCallbackWrapper.mValue instanceof MessageDisplayController).isFalse();
}
@Test
public void testStartEnrolling() {
@EnrollReason final int enrollReason = ENROLL_ENROLL;
final byte[] token = new byte[] { 1, 2, 3 };
mViewModel.setToken(token);
// Start enrollment
final boolean ret = mViewModel.startEnrollment(enrollReason);
assertThat(ret).isTrue();
verify(mFingerprintUpdater, only()).enroll(eq(token), any(CancellationSignal.class),
eq(TEST_USER_ID), any(EnrollmentCallback.class), eq(enrollReason));
assertThat(mCallbackWrapper.mValue instanceof MessageDisplayController).isFalse();
}
@Test
public void testStartEnrollingWithMessageDisplayController() {
// Enable MessageDisplayController and mock handler for it
when(mResources.getBoolean(mEnrollmentMessageDisplayControllerFlagResId)).thenReturn(true);
when(mApplication.getMainThreadHandler()).thenReturn(new TestHandler());
@EnrollReason final int enrollReason = ENROLL_ENROLL;
final byte[] token = new byte[] { 1, 2, 3 };
mViewModel.setToken(token);
// Start enrollment
final boolean ret = mViewModel.startEnrollment(enrollReason);
assertThat(ret).isTrue();
verify(mFingerprintUpdater, only()).enroll(eq(token), any(CancellationSignal.class),
eq(TEST_USER_ID), any(MessageDisplayController.class), eq(enrollReason));
assertThat(mCallbackWrapper.mValue).isNotNull();
assertThat(mCallbackWrapper.mValue instanceof MessageDisplayController).isTrue();
final EnrollmentCallback callback1 = mCallbackWrapper.mValue;
// Cancel and start again
mViewModel.cancelEnrollment();
mViewModel.startEnrollment(enrollReason);
// Shall not use the same MessageDisplayController
verify(mFingerprintUpdater, times(2)).enroll(eq(token), any(CancellationSignal.class),
eq(TEST_USER_ID), any(MessageDisplayController.class), eq(enrollReason));
assertThat(mCallbackWrapper.mValue).isNotNull();
assertThat(callback1).isNotEqualTo(mCallbackWrapper.mValue);
} }
@Test @Test
@@ -162,6 +224,48 @@ public class FingerprintEnrollProgressViewModelTest {
assertThat(progress.getRemaining()).isEqualTo(0); assertThat(progress.getRemaining()).isEqualTo(0);
} }
@Test
public void testProgressUpdateWithMessageDisplayController() {
// Enable MessageDisplayController and mock handler for it
when(mResources.getBoolean(mEnrollmentMessageDisplayControllerFlagResId)).thenReturn(true);
when(mApplication.getMainThreadHandler()).thenReturn(new TestHandler());
mViewModel.setToken(new byte[] { 1, 2, 3 });
// Start enrollment
final boolean ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isTrue();
assertThat(mCallbackWrapper.mValue).isNotNull();
// Test default value
final LiveData<EnrollmentProgress> progressLiveData = mViewModel.getProgressLiveData();
EnrollmentProgress progress = progressLiveData.getValue();
assertThat(progress).isNotNull();
assertThat(progress.getSteps()).isEqualTo(-1);
assertThat(progress.getRemaining()).isEqualTo(0);
// Update first progress
mCallbackWrapper.mValue.onEnrollmentProgress(25);
progress = progressLiveData.getValue();
assertThat(progress).isNotNull();
assertThat(progress.getSteps()).isEqualTo(25);
assertThat(progress.getRemaining()).isEqualTo(25);
// Update second progress
mCallbackWrapper.mValue.onEnrollmentProgress(20);
progress = progressLiveData.getValue();
assertThat(progress).isNotNull();
assertThat(progress.getSteps()).isEqualTo(25);
assertThat(progress.getRemaining()).isEqualTo(20);
// Update latest progress
mCallbackWrapper.mValue.onEnrollmentProgress(0);
progress = progressLiveData.getValue();
assertThat(progress).isNotNull();
assertThat(progress.getSteps()).isEqualTo(25);
assertThat(progress.getRemaining()).isEqualTo(0);
}
@Test @Test
public void testGetErrorMessageLiveData() { public void testGetErrorMessageLiveData() {
// Start enrollment // Start enrollment
@@ -262,4 +366,17 @@ public class FingerprintEnrollProgressViewModelTest {
private static class TestWrapper<T> { private static class TestWrapper<T> {
T mValue; T mValue;
} }
private static class TestHandler extends Handler {
TestHandler() {
super(Looper.getMainLooper());
}
@Override
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
msg.getCallback().run();
return true;
}
}
} }