diff --git a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModel.java b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModel.java
index b1b420db9a3..695ea0d0c0f 100644
--- a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModel.java
+++ b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModel.java
@@ -16,6 +16,8 @@
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_STEPS;
@@ -63,7 +65,6 @@ public class FingerprintEnrollProgressViewModel extends AndroidViewModel {
private final int mUserId;
private final FingerprintUpdater mFingerprintUpdater;
- private final MessageDisplayController mMessageDisplayController;
@Nullable private CancellationSignal mCancellationSignal = null;
private final EnrollmentCallback mEnrollmentCallback = new EnrollmentCallback() {
@@ -81,6 +82,9 @@ public class FingerprintEnrollProgressViewModel extends AndroidViewModel {
@Override
public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
+ if (DEBUG) {
+ Log.d(TAG, "onEnrollmentHelp(" + helpMsgId + ", " + helpString + ")");
+ }
mHelpMessageLiveData.postValue(new EnrollmentStatusMessage(helpMsgId, helpString));
}
@@ -113,20 +117,6 @@ public class FingerprintEnrollProgressViewModel extends AndroidViewModel {
super(application);
mFingerprintUpdater = fingerprintUpdater;
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) {
@@ -195,9 +185,24 @@ public class FingerprintEnrollProgressViewModel extends AndroidViewModel {
mErrorMessageLiveData.setValue(null);
mCancellationSignal = new CancellationSignal();
- mFingerprintUpdater.enroll(mToken, mCancellationSignal, mUserId,
- mMessageDisplayController != null ? mMessageDisplayController : mEnrollmentCallback,
- reason);
+
+ final Resources res = getApplication().getResources();
+ 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;
}
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileFragmentBridge.java b/src/com/android/settings/dashboard/profileselector/ProfileFragmentBridge.java
index 2bcc02e2b04..1e5145acb6d 100644
--- a/src/com/android/settings/dashboard/profileselector/ProfileFragmentBridge.java
+++ b/src/com/android/settings/dashboard/profileselector/ProfileFragmentBridge.java
@@ -22,6 +22,7 @@ import com.android.settings.accounts.AccountDashboardFragment;
import com.android.settings.applications.manageapplications.ManageApplications;
import com.android.settings.deviceinfo.StorageDashboardFragment;
import com.android.settings.inputmethod.AvailableVirtualKeyboardFragment;
+import com.android.settings.inputmethod.NewKeyboardLayoutEnabledLocalesFragment;
import com.android.settings.location.LocationServices;
import java.util.Map;
@@ -49,5 +50,7 @@ public class ProfileFragmentBridge {
ProfileSelectStorageFragment.class.getName());
FRAGMENT_MAP.put(AvailableVirtualKeyboardFragment.class.getName(),
ProfileSelectKeyboardFragment.class.getName());
+ FRAGMENT_MAP.put(NewKeyboardLayoutEnabledLocalesFragment.class.getName(),
+ ProfileSelectPhysicalKeyboardFragment.class.getName());
}
}
diff --git a/src/com/android/settings/dashboard/profileselector/ProfileSelectPhysicalKeyboardFragment.java b/src/com/android/settings/dashboard/profileselector/ProfileSelectPhysicalKeyboardFragment.java
new file mode 100644
index 00000000000..3c1546e7d95
--- /dev/null
+++ b/src/com/android/settings/dashboard/profileselector/ProfileSelectPhysicalKeyboardFragment.java
@@ -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.
+ *
+ *
{@link NewKeyboardLayoutEnabledLocalesFragment} used to show both of personal/work user
+ * enabled IMEs and their physical keyboard layouts.
+ */
+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
+ };
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownController.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownController.java
index 0be6c988ec7..2121c60218b 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownController.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownController.java
@@ -23,6 +23,7 @@ import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
+import android.util.ArraySet;
import android.util.Log;
import android.view.View;
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.widget.FooterPreference;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
/** Controller for battery usage breakdown preference group. */
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 APP_LIST_PREFERENCE_KEY = "app_list";
private static final String PACKAGE_NAME_NONE = "none";
+ private static final List EMPTY_ENTRY_LIST = new ArrayList<>();
private static int sUiMode = Configuration.UI_MODE_NIGHT_UNDEFINED;
@@ -183,7 +187,7 @@ public class BatteryUsageBreakdownController extends BasePreferenceController
if (mSpinnerPosition != position) {
mSpinnerPosition = position;
mHandler.post(() -> {
- removeAndCacheAllPreferences();
+ removeAndCacheAllUnusedPreferences();
addAllPreferences();
mMetricsFeatureProvider.action(
mPrefContext,
@@ -238,27 +242,34 @@ public class BatteryUsageBreakdownController extends BasePreferenceController
private void showSpinnerAndAppList() {
if (mBatteryDiffData == null) {
mHandler.post(() -> {
- removeAndCacheAllPreferences();
+ removeAndCacheAllUnusedPreferences();
});
return;
}
mSpinnerPreference.setVisible(true);
mAppListPreferenceGroup.setVisible(true);
mHandler.post(() -> {
- removeAndCacheAllPreferences();
+ removeAndCacheAllUnusedPreferences();
addAllPreferences();
});
}
+ private List getBatteryDiffEntries() {
+ if (mBatteryDiffData == null) {
+ return EMPTY_ENTRY_LIST;
+ }
+ return mSpinnerPosition == 0
+ ? mBatteryDiffData.getAppDiffEntryList()
+ : mBatteryDiffData.getSystemDiffEntryList();
+ }
+
@VisibleForTesting
void addAllPreferences() {
if (mBatteryDiffData == null) {
return;
}
final long start = System.currentTimeMillis();
- final List entries = mSpinnerPosition == 0
- ? mBatteryDiffData.getAppDiffEntryList()
- : mBatteryDiffData.getSystemDiffEntryList();
+ final List entries = getBatteryDiffEntries();
int prefIndex = mAppListPreferenceGroup.getPreferenceCount();
for (BatteryDiffEntry entry : entries) {
boolean isAdded = false;
@@ -272,7 +283,6 @@ public class BatteryUsageBreakdownController extends BasePreferenceController
PowerGaugePreference pref = mAppListPreferenceGroup.findPreference(prefKey);
if (pref != null) {
isAdded = true;
- Log.w(TAG, "preference should be removed for:" + entry.getPackageName());
} else {
pref = (PowerGaugePreference) mPreferenceCache.get(prefKey);
}
@@ -301,16 +311,25 @@ public class BatteryUsageBreakdownController extends BasePreferenceController
}
@VisibleForTesting
- void removeAndCacheAllPreferences() {
+ void removeAndCacheAllUnusedPreferences() {
+ List entries = getBatteryDiffEntries();
+ Set entryKeySet = new ArraySet<>();
+ for (BatteryDiffEntry entry : entries) {
+ entryKeySet.add(entry.getKey());
+ }
+
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);
- if (TextUtils.isEmpty(pref.getKey())) {
+ if (entryKeySet.contains(pref.getKey())) {
+ // The pref is still used, don't remove.
continue;
}
- mPreferenceCache.put(pref.getKey(), pref);
+ if (!TextUtils.isEmpty(pref.getKey())) {
+ mPreferenceCache.put(pref.getKey(), pref);
+ }
+ mAppListPreferenceGroup.removePreference(pref);
}
- mAppListPreferenceGroup.removeAll();
}
@VisibleForTesting
diff --git a/src/com/android/settings/inputmethod/NewKeyboardLayoutEnabledLocalesFragment.java b/src/com/android/settings/inputmethod/NewKeyboardLayoutEnabledLocalesFragment.java
index 3344f4e99d0..054ce610944 100644
--- a/src/com/android/settings/inputmethod/NewKeyboardLayoutEnabledLocalesFragment.java
+++ b/src/com/android/settings/inputmethod/NewKeyboardLayoutEnabledLocalesFragment.java
@@ -23,6 +23,7 @@ import android.hardware.input.InputManager;
import android.hardware.input.KeyboardLayout;
import android.os.Bundle;
import android.os.UserHandle;
+import android.os.UserManager;
import android.util.Log;
import android.view.InputDevice;
import android.view.inputmethod.InputMethodInfo;
@@ -34,8 +35,10 @@ import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
+import com.android.settings.Utils;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
import com.android.settings.inputmethod.NewKeyboardSettingsUtils.KeyboardInfo;
import java.util.ArrayList;
@@ -56,6 +59,39 @@ public class NewKeyboardLayoutEnabledLocalesFragment extends DashboardFragment
private Context mContext;
private ArrayList 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
public void onActivityCreated(final Bundle icicle) {
super.onActivityCreated(icicle);
@@ -74,13 +110,39 @@ public class NewKeyboardLayoutEnabledLocalesFragment extends DashboardFragment
}
final String title = inputDevice.getName();
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();
}
+ @Override
+ public void onStop() {
+ super.onStop();
+ mIm.unregisterInputDeviceListener(this);
+ mInputDeviceId = -1;
+ }
+
private void updateCheckedState() {
if (NewKeyboardSettingsUtils.getInputDevice(mIm, mInputDeviceIdentifier) == null) {
return;
}
+
PreferenceScreen preferenceScreen = getPreferenceScreen();
preferenceScreen.removeAll();
List infoList = mImm.getEnabledInputMethodListAsUser(mUserId);
@@ -95,7 +157,7 @@ public class NewKeyboardLayoutEnabledLocalesFragment extends DashboardFragment
for (InputMethodInfo info : infoList) {
mKeyboardInfoList.clear();
List subtypes =
- mImm.getEnabledInputMethodSubtypeList(info, true);
+ mImm.getEnabledInputMethodSubtypeListAsUser(info.getId(), true, mUserId);
for (InputMethodSubtype subtype : subtypes) {
if (subtype.isSuitableForPhysicalKeyboardLayoutMapping()) {
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
protected String getLogTag() {
return TAG;
diff --git a/src/com/android/settings/network/AirplaneModePreferenceController.java b/src/com/android/settings/network/AirplaneModePreferenceController.java
index 720a33409c2..5b4ce1b00b9 100644
--- a/src/com/android/settings/network/AirplaneModePreferenceController.java
+++ b/src/com/android/settings/network/AirplaneModePreferenceController.java
@@ -79,7 +79,7 @@ public class AirplaneModePreferenceController extends TogglePreferenceController
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
- if (KEY_AIRPLANE_MODE.equals(preference.getKey())
+ if (KEY_AIRPLANE_MODE.equals(preference.getKey()) && isAvailable()
&& mAirplaneModeEnabler.isInEcmMode()) {
// In ECM mode launch ECM app dialog
if (mFragment != null) {
@@ -141,12 +141,14 @@ public class AirplaneModePreferenceController extends TogglePreferenceController
@Override
public void onDestroy() {
- mAirplaneModeEnabler.close();
+ if (isAvailable()) {
+ mAirplaneModeEnabler.close();
+ }
}
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);
// Set Airplane mode based on the return value and checkbox state
mAirplaneModeEnabler.setAirplaneModeInECM(isChoiceYes,
@@ -156,7 +158,7 @@ public class AirplaneModePreferenceController extends TogglePreferenceController
@Override
public boolean isChecked() {
- return mAirplaneModeEnabler.isAirplaneModeOn();
+ return isAvailable() && mAirplaneModeEnabler.isAirplaneModeOn();
}
@Override
@@ -164,7 +166,9 @@ public class AirplaneModePreferenceController extends TogglePreferenceController
if (isChecked() == isChecked) {
return false;
}
- mAirplaneModeEnabler.setAirplaneMode(isChecked);
+ if (isAvailable()) {
+ mAirplaneModeEnabler.setAirplaneMode(isChecked);
+ }
return true;
}
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
index ce8305308c0..83d2117af1b 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
@@ -350,10 +350,15 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme
}
}
+ @Override
+ public void onPause() {
+ mMobileNetworkRepository.removeRegister(this);
+ super.onPause();
+ }
+
@Override
public void onDestroy() {
super.onDestroy();
- mMobileNetworkRepository.removeRegister(this);
}
@VisibleForTesting
diff --git a/src/com/android/settings/nfc/NfcEnabler.java b/src/com/android/settings/nfc/NfcEnabler.java
index 88482d59d8b..fe8762b8a90 100644
--- a/src/com/android/settings/nfc/NfcEnabler.java
+++ b/src/com/android/settings/nfc/NfcEnabler.java
@@ -18,9 +18,6 @@ package com.android.settings.nfc;
import android.content.Context;
import android.nfc.NfcAdapter;
-import android.provider.Settings;
-
-import androidx.annotation.VisibleForTesting;
import com.android.settingslib.widget.MainSwitchPreference;
@@ -41,7 +38,7 @@ public class NfcEnabler extends BaseNfcEnabler {
switch (newState) {
case NfcAdapter.STATE_OFF:
mPreference.updateStatus(false);
- mPreference.setEnabled(isToggleable());
+ mPreference.setEnabled(true);
break;
case NfcAdapter.STATE_ON:
mPreference.updateStatus(true);
@@ -57,15 +54,4 @@ public class NfcEnabler extends BaseNfcEnabler {
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;
- }
}
diff --git a/src/com/android/settings/nfc/NfcPreferenceController.java b/src/com/android/settings/nfc/NfcPreferenceController.java
index 483fead807e..2ba00c6670a 100644
--- a/src/com/android/settings/nfc/NfcPreferenceController.java
+++ b/src/com/android/settings/nfc/NfcPreferenceController.java
@@ -21,7 +21,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.nfc.NfcAdapter;
-import android.provider.Settings;
import android.util.Log;
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.
*
diff --git a/src/com/android/settings/users/TimeoutToDockUserPreferenceController.java b/src/com/android/settings/users/TimeoutToDockUserPreferenceController.java
index 57e8d402825..322a4abbeed 100644
--- a/src/com/android/settings/users/TimeoutToDockUserPreferenceController.java
+++ b/src/com/android/settings/users/TimeoutToDockUserPreferenceController.java
@@ -20,6 +20,7 @@ import static android.provider.Settings.Secure.TIMEOUT_TO_DOCK_USER;
import android.content.Context;
import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.Settings;
import androidx.preference.PreferenceScreen;
@@ -34,6 +35,8 @@ import java.util.Arrays;
* automatically switch to the designated Dock User when the device is docked.
*/
public class TimeoutToDockUserPreferenceController extends BasePreferenceController {
+ private final UserManager mUserManager;
+
private final String[] mEntries;
private final String[] mValues;
@@ -41,6 +44,8 @@ public class TimeoutToDockUserPreferenceController extends BasePreferenceControl
String preferenceKey) {
super(context, preferenceKey);
+ mUserManager = context.getSystemService(UserManager.class);
+
mEntries = mContext.getResources().getStringArray(
com.android.settings.R.array.switch_to_dock_user_when_docked_timeout_entries);
mValues = mContext.getResources().getStringArray(
@@ -62,9 +67,10 @@ public class TimeoutToDockUserPreferenceController extends BasePreferenceControl
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(),
- Settings.Global.USER_SWITCHER_ENABLED, 0) != 1) {
+ Settings.Global.USER_SWITCHER_ENABLED, 0) != 1
+ || mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)) {
return CONDITIONALLY_UNAVAILABLE;
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownControllerTest.java
index 37f05bc0d8a..16fec0909e0 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryUsageBreakdownControllerTest.java
@@ -55,6 +55,7 @@ import java.util.TimeZone;
@RunWith(RobolectricTestRunner.class)
public final class BatteryUsageBreakdownControllerTest {
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";
@Mock
@@ -175,7 +176,24 @@ public final class BatteryUsageBreakdownControllerTest {
}
@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(mPowerGaugePreference).when(mAppListPreferenceGroup).getPreference(0);
doReturn(PREF_KEY).when(mBatteryHistEntry).getKey();
@@ -184,11 +202,10 @@ public final class BatteryUsageBreakdownControllerTest {
// Ensures the testing data is correct.
assertThat(mBatteryUsageBreakdownController.mPreferenceCache).isEmpty();
- mBatteryUsageBreakdownController.removeAndCacheAllPreferences();
+ mBatteryUsageBreakdownController.removeAndCacheAllUnusedPreferences();
- assertThat(mBatteryUsageBreakdownController.mPreferenceCache.get(PREF_KEY))
- .isEqualTo(mPowerGaugePreference);
- verify(mAppListPreferenceGroup).removeAll();
+ verify(mAppListPreferenceGroup, never()).removePreference(any());
+ assertThat(mBatteryUsageBreakdownController.mPreferenceCache).isEmpty();
}
@Test
diff --git a/tests/robotests/src/com/android/settings/nfc/NfcEnablerTest.java b/tests/robotests/src/com/android/settings/nfc/NfcEnablerTest.java
index cc451906214..5299bbdb10c 100644
--- a/tests/robotests/src/com/android/settings/nfc/NfcEnablerTest.java
+++ b/tests/robotests/src/com/android/settings/nfc/NfcEnablerTest.java
@@ -16,15 +16,12 @@
package com.android.settings.nfc;
-import static com.google.common.truth.Truth.assertThat;
-
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
-import android.content.ContentResolver;
import android.content.Context;
import android.nfc.NfcAdapter;
-import android.provider.Settings;
import com.android.settingslib.widget.MainSwitchPreference;
@@ -52,55 +49,14 @@ public class NfcEnablerTest {
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
public void handleNfcStateChanged_stateOff_shouldCheckIfPreferenceEnableState() {
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);
}
}
diff --git a/tests/robotests/src/com/android/settings/nfc/NfcPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/nfc/NfcPreferenceControllerTest.java
index 3ca553bc3ba..4db51aab3b6 100644
--- a/tests/robotests/src/com/android/settings/nfc/NfcPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/nfc/NfcPreferenceControllerTest.java
@@ -28,7 +28,6 @@ import android.content.Intent;
import android.nfc.NfcAdapter;
import android.nfc.NfcManager;
import android.os.UserManager;
-import android.provider.Settings;
import androidx.preference.PreferenceScreen;
@@ -188,44 +187,6 @@ public class NfcPreferenceControllerTest {
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
public void ncfSliceWorker_nfcBroadcast_noExtra_sliceDoesntUpdate() {
final NfcSliceWorker worker = spy(
diff --git a/tests/robotests/src/com/android/settings/users/TimeoutToDockUserPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/users/TimeoutToDockUserPreferenceControllerTest.java
index 2e7e2d797be..3d8e8930775 100644
--- a/tests/robotests/src/com/android/settings/users/TimeoutToDockUserPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/users/TimeoutToDockUserPreferenceControllerTest.java
@@ -27,6 +27,7 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.res.Resources;
import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.Settings;
import androidx.test.core.app.ApplicationProvider;
@@ -41,6 +42,8 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
@@ -51,6 +54,9 @@ public class TimeoutToDockUserPreferenceControllerTest {
private Resources mResources;
private TimeoutToDockUserPreferenceController mController;
+ @Mock
+ private UserManager mUserManager;
+
private static final String FAKE_PREFERENCE_KEY = "timeout_to_dock_user_preference";
private String[] mEntries;
@@ -58,9 +64,12 @@ public class TimeoutToDockUserPreferenceControllerTest {
@Before
public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
mContext = spy(ApplicationProvider.getApplicationContext());
mResources = spy(mContext.getResources());
doReturn(mResources).when(mContext).getResources();
+ when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
mEntries = mResources.getStringArray(
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,
1);
+ // User switching not blocked.
+ when(mUserManager.hasUserRestriction(UserManager.DISALLOW_USER_SWITCH)).thenReturn(false);
+
// Set to user 1;
ShadowUserHandle.setUid(1);
}
@@ -106,6 +118,14 @@ public class TimeoutToDockUserPreferenceControllerTest {
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
public void getAvailabilityStatus_isCurrentlyMainUser_returnDisabledForUser() {
when(Utils.canCurrentUserDream(mContext)).thenReturn(true);
diff --git a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModelTest.java b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModelTest.java
index 323618a1d63..6190c5e3f8f 100644
--- a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModelTest.java
+++ b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModelTest.java
@@ -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.EnrollmentCallback;
+import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME;
+
import static com.google.common.truth.Truth.assertThat;
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.never;
import static org.mockito.Mockito.only;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Application;
import android.content.res.Resources;
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.test.core.app.ApplicationProvider;
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.MessageDisplayController;
import com.android.settings.biometrics2.ui.model.EnrollmentProgress;
import com.android.settings.biometrics2.ui.model.EnrollmentStatusMessage;
import com.android.settings.testutils.InstantTaskExecutorRule;
@@ -68,12 +76,18 @@ public class FingerprintEnrollProgressViewModelTest {
private FingerprintEnrollProgressViewModel mViewModel;
private final TestWrapper mCancellationSignalWrapper = new TestWrapper<>();
private final TestWrapper mCallbackWrapper = new TestWrapper<>();
+ private int mEnrollmentMessageDisplayControllerFlagResId;
@Before
public void setUp() {
+ mEnrollmentMessageDisplayControllerFlagResId = ApplicationProvider.getApplicationContext()
+ .getResources().getIdentifier("enrollment_message_display_controller_flag", "bool",
+ SETTINGS_PACKAGE_NAME);
+
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,
TEST_USER_ID);
@@ -88,7 +102,7 @@ public class FingerprintEnrollProgressViewModelTest {
}
@Test
- public void testStartEnrollment() {
+ public void testStartFindSensor() {
@EnrollReason final int enrollReason = ENROLL_FIND_SENSOR;
final byte[] token = new byte[] { 1, 2, 3 };
mViewModel.setToken(token);
@@ -99,6 +113,54 @@ public class FingerprintEnrollProgressViewModelTest {
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 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
@@ -162,6 +224,48 @@ public class FingerprintEnrollProgressViewModelTest {
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 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
public void testGetErrorMessageLiveData() {
// Start enrollment
@@ -262,4 +366,17 @@ public class FingerprintEnrollProgressViewModelTest {
private static class TestWrapper {
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;
+ }
+ }
}