diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 185d21ec7b2..9c5d6c6a404 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -2398,6 +2398,7 @@
+
diff --git a/res/layout/udfps_enroll_view.xml b/res/layout/udfps_enroll_view.xml
index 6bf339b6b07..bd626093ce4 100644
--- a/res/layout/udfps_enroll_view.xml
+++ b/res/layout/udfps_enroll_view.xml
@@ -18,7 +18,8 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/udfps_animation_view"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent"
+ android:visibility="gone">
Also use password to unlock this device
+
+ Verify pattern
+
+ Verify PIN
+
+ Verify password
+
+ Enter your device pattern enrolled in normal mode to continue
+
+ Enter your device PIN enrolled in normal mode to continue
+
+ Enter your device password enrolled in normal mode to continue
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 68b1a48a380..a2195df1b6b 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -708,9 +708,13 @@ public final class Utils extends com.android.settingslib.Utils {
final int userId = bundle.getInt(Intent.EXTRA_USER_ID, UserHandle.myUserId());
if (userId == LockPatternUtils.USER_FRP) {
return allowAnyUser ? userId : checkUserOwnsFrpCredential(context, userId);
- } else {
- return allowAnyUser ? userId : enforceSameOwner(context, userId);
}
+ if (userId == LockPatternUtils.USER_REPAIR_MODE) {
+ enforceRepairModeActive(context);
+ // any users can exit repair mode
+ return userId;
+ }
+ return allowAnyUser ? userId : enforceSameOwner(context, userId);
}
/**
@@ -729,6 +733,16 @@ public final class Utils extends com.android.settingslib.Utils {
+ " does not own frp credential.");
}
+ /**
+ * Throws {@link SecurityException} if repair mode is not active on the device.
+ */
+ private static void enforceRepairModeActive(Context context) {
+ if (LockPatternUtils.isRepairModeActive(context)) {
+ return;
+ }
+ throw new SecurityException("Repair mode is not active on the device.");
+ }
+
/**
* Returns the given user id if it belongs to the current user.
*
diff --git a/src/com/android/settings/applications/specialaccess/DataSaverController.kt b/src/com/android/settings/applications/specialaccess/DataSaverController.kt
index 3a2fdb002b1..baed0aa5ec4 100644
--- a/src/com/android/settings/applications/specialaccess/DataSaverController.kt
+++ b/src/com/android/settings/applications/specialaccess/DataSaverController.kt
@@ -51,7 +51,7 @@ class DataSaverController(context: Context, key: String) : BasePreferenceControl
preference = screen.findPreference(preferenceKey)!!
}
- fun init(viewLifecycleOwner: LifecycleOwner) {
+ override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
preference.summary = getUnrestrictedSummary(mContext)
diff --git a/src/com/android/settings/applications/specialaccess/SpecialAccessSettings.java b/src/com/android/settings/applications/specialaccess/SpecialAccessSettings.java
index 9f4c8958cf4..2cbc30422fc 100644
--- a/src/com/android/settings/applications/specialaccess/SpecialAccessSettings.java
+++ b/src/com/android/settings/applications/specialaccess/SpecialAccessSettings.java
@@ -21,10 +21,6 @@ import static android.app.admin.DevicePolicyResources.Strings.Settings.MANAGE_DE
import android.app.settings.SettingsEnums;
import android.os.Bundle;
-import android.view.View;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
@@ -50,12 +46,6 @@ public class SpecialAccessSettings extends DashboardFragment {
MANAGE_DEVICE_ADMIN_APPS, R.string.manage_device_admin);
}
- @Override
- public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- use(DataSaverController.class).init(getViewLifecycleOwner());
- }
-
@Override
protected int getPreferenceScreenResId() {
return R.xml.special_access;
diff --git a/src/com/android/settings/biometrics/BiometricEnrollSidecar.java b/src/com/android/settings/biometrics/BiometricEnrollSidecar.java
index 97d46a420e3..369fa4b4311 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollSidecar.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollSidecar.java
@@ -48,11 +48,16 @@ public abstract class BiometricEnrollSidecar extends InstrumentedFragment {
/**
* Called when a pointer down event has occurred.
*/
- default void onPointerDown(int sensorId) { }
+ default void onUdfpsPointerDown(int sensorId) { }
/**
* Called when a pointer up event has occurred.
*/
- default void onPointerUp(int sensorId) { }
+ default void onUdfpsPointerUp(int sensorId) { }
+
+ /**
+ * Called when udfps overlay is shown.
+ */
+ default void onUdfpsOverlayShown() { }
}
private int mEnrollmentSteps = -1;
@@ -126,29 +131,36 @@ public abstract class BiometricEnrollSidecar extends InstrumentedFragment {
}
}
- private class QueuedPointerDown extends QueuedEvent {
+ private class QueuedUdfpsPointerDown extends QueuedEvent {
private final int sensorId;
- public QueuedPointerDown(int sensorId) {
+ QueuedUdfpsPointerDown(int sensorId) {
this.sensorId = sensorId;
}
@Override
public void send(Listener listener) {
- listener.onPointerDown(sensorId);
+ listener.onUdfpsPointerDown(sensorId);
}
}
- private class QueuedPointerUp extends QueuedEvent {
+ private class QueuedUdfpsPointerUp extends QueuedEvent {
private final int sensorId;
- public QueuedPointerUp(int sensorId) {
+ QueuedUdfpsPointerUp(int sensorId) {
this.sensorId = sensorId;
}
@Override
public void send(Listener listener) {
- listener.onPointerUp(sensorId);
+ listener.onUdfpsPointerUp(sensorId);
+ }
+ }
+
+ private class QueuedUdfpsOverlayShown extends QueuedEvent {
+ @Override
+ public void send(Listener listener) {
+ listener.onUdfpsOverlayShown();
}
}
@@ -249,19 +261,27 @@ public abstract class BiometricEnrollSidecar extends InstrumentedFragment {
}
}
- protected void onPointerDown(int sensorId) {
+ protected void onUdfpsPointerDown(int sensorId) {
if (mListener != null) {
- mListener.onPointerDown(sensorId);
+ mListener.onUdfpsPointerDown(sensorId);
} else {
- mQueuedEvents.add(new QueuedPointerDown(sensorId));
+ mQueuedEvents.add(new QueuedUdfpsPointerDown(sensorId));
}
}
- protected void onPointerUp(int sensorId) {
+ protected void onUdfpsPointerUp(int sensorId) {
if (mListener != null) {
- mListener.onPointerUp(sensorId);
+ mListener.onUdfpsPointerUp(sensorId);
} else {
- mQueuedEvents.add(new QueuedPointerUp(sensorId));
+ mQueuedEvents.add(new QueuedUdfpsPointerUp(sensorId));
+ }
+ }
+
+ protected void onUdfpsOverlayShown() {
+ if (mListener != null) {
+ mListener.onUdfpsOverlayShown();
+ } else {
+ mQueuedEvents.add(new QueuedUdfpsOverlayShown());
}
}
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
index 400a92ee7a7..dbdb024973a 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
@@ -828,19 +828,26 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
}
@Override
- public void onPointerDown(int sensorId) {
+ public void onUdfpsPointerDown(int sensorId) {
if (mUdfpsEnrollHelper != null) {
mUdfpsEnrollHelper.onPointerDown(sensorId);
}
}
@Override
- public void onPointerUp(int sensorId) {
+ public void onUdfpsPointerUp(int sensorId) {
if (mUdfpsEnrollHelper != null) {
mUdfpsEnrollHelper.onPointerUp(sensorId);
}
}
+ @Override
+ public void onUdfpsOverlayShown() {
+ if (mCanAssumeUdfps) {
+ findViewById(R.id.udfps_animation_view).setVisibility(View.VISIBLE);
+ }
+ }
+
private void updateProgress(boolean animate) {
if (mSidecar == null || !mSidecar.isEnrolling()) {
Log.d(TAG, "Enrollment not started yet");
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java
index 5d04cd6c5ed..493302bd13c 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java
@@ -124,13 +124,18 @@ public class FingerprintEnrollSidecar extends BiometricEnrollSidecar {
}
@Override
- public void onPointerDown(int sensorId) {
- FingerprintEnrollSidecar.super.onPointerDown(sensorId);
+ public void onUdfpsPointerDown(int sensorId) {
+ FingerprintEnrollSidecar.super.onUdfpsPointerDown(sensorId);
}
@Override
- public void onPointerUp(int sensorId) {
- FingerprintEnrollSidecar.super.onPointerUp(sensorId);
+ public void onUdfpsPointerUp(int sensorId) {
+ FingerprintEnrollSidecar.super.onUdfpsPointerUp(sensorId);
+ }
+
+ @Override
+ public void onUdfpsOverlayShown() {
+ FingerprintEnrollSidecar.super.onUdfpsOverlayShown();
}
};
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintUpdater.java b/src/com/android/settings/biometrics/fingerprint/FingerprintUpdater.java
index 36325a7b975..306b1a3e136 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintUpdater.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintUpdater.java
@@ -98,13 +98,18 @@ public class FingerprintUpdater {
}
@Override
- public void onPointerDown(int sensorId) {
- mCallback.onPointerDown(sensorId);
+ public void onUdfpsPointerDown(int sensorId) {
+ mCallback.onUdfpsPointerDown(sensorId);
}
@Override
- public void onPointerUp(int sensorId) {
- mCallback.onPointerUp(sensorId);
+ public void onUdfpsPointerUp(int sensorId) {
+ mCallback.onUdfpsPointerUp(sensorId);
+ }
+
+ @Override
+ public void onUdfpsOverlayShown() {
+ mCallback.onUdfpsOverlayShown();
}
}
diff --git a/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollEnrollingView.java b/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollEnrollingView.java
index 9225c64498f..df2f2f77d3b 100644
--- a/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollEnrollingView.java
+++ b/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollEnrollingView.java
@@ -86,7 +86,7 @@ public class UdfpsEnrollEnrollingView extends GlifLayout {
UdfpsEnrollHelper udfpsEnrollHelper,
AccessibilityManager accessibilityManager) {
mAccessibilityManager = accessibilityManager;
- initUdfpsEnrollView(mUdfpsEnrollView, udfpsProps, udfpsEnrollHelper);
+ initUdfpsEnrollView(udfpsProps, udfpsEnrollHelper);
if (!mIsLandscape) {
adjustPortraitPaddings();
@@ -117,8 +117,7 @@ public class UdfpsEnrollEnrollingView extends GlifLayout {
});
}
- private void initUdfpsEnrollView(UdfpsEnrollView udfpsEnrollView,
- FingerprintSensorPropertiesInternal udfpsProps,
+ private void initUdfpsEnrollView(FingerprintSensorPropertiesInternal udfpsProps,
UdfpsEnrollHelper udfpsEnrollHelper) {
DisplayInfo displayInfo = new DisplayInfo();
mContext.getDisplay().getDisplayInfo(displayInfo);
@@ -141,8 +140,8 @@ public class UdfpsEnrollEnrollingView extends GlifLayout {
scaleFactor,
displayInfo.rotation);
- udfpsEnrollView.setOverlayParams(params);
- udfpsEnrollView.setEnrollHelper(udfpsEnrollHelper);
+ mUdfpsEnrollView.setOverlayParams(params);
+ mUdfpsEnrollView.setEnrollHelper(udfpsEnrollHelper);
}
private void adjustPortraitPaddings() {
diff --git a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModel.java b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModel.java
index d77d9d3f7e8..7074288716e 100644
--- a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModel.java
+++ b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollProgressViewModel.java
@@ -103,12 +103,12 @@ public class FingerprintEnrollProgressViewModel extends AndroidViewModel {
}
@Override
- public void onPointerDown(int sensorId) {
+ public void onUdfpsPointerDown(int sensorId) {
mPointerDownLiveData.postValue(sensorId);
}
@Override
- public void onPointerUp(int sensorId) {
+ public void onUdfpsPointerUp(int sensorId) {
mPointerUpLiveData.postValue(sensorId);
}
};
diff --git a/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBase.java b/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBase.java
index 7ee61ee249d..f2bc6fcfde6 100644
--- a/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBase.java
+++ b/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBase.java
@@ -128,7 +128,7 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere
if (device != null && mSelectedList.contains(device)) {
setResult(RESULT_OK);
finish();
- } else if (mDevicePreferenceMap.containsKey(cachedDevice)) {
+ } else {
onDeviceDeleted(cachedDevice);
}
}
@@ -175,8 +175,6 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere
public void updateContent(int bluetoothState) {
switch (bluetoothState) {
case BluetoothAdapter.STATE_ON:
- mDevicePreferenceMap.clear();
- clearPreferenceGroupCache();
mBluetoothAdapter.enable();
enableScanning();
break;
@@ -187,14 +185,6 @@ public abstract class BluetoothDevicePairingDetailBase extends DeviceListPrefere
}
}
- /**
- * Clears all cached preferences in {@code preferenceGroup}.
- */
- private void clearPreferenceGroupCache() {
- cacheRemoveAllPrefs(mAvailableDevicesCategory);
- removeCachedPrefs(mAvailableDevicesCategory);
- }
-
@VisibleForTesting
void showBluetoothTurnedOnToast() {
Toast.makeText(getContext(), R.string.connected_device_bluetooth_turned_on_toast,
diff --git a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
index 5256f3d6596..039080b26ba 100644
--- a/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
+++ b/src/com/android/settings/bluetooth/BluetoothDevicePreference.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * 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.
@@ -35,6 +35,8 @@ import android.view.View;
import android.widget.ImageView;
import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.Preference;
@@ -52,6 +54,7 @@ import java.lang.annotation.RetentionPolicy;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* BluetoothDevicePreference is the preference type used to display each remote
@@ -79,7 +82,9 @@ public final class BluetoothDevicePreference extends GearPreference {
@VisibleForTesting
BluetoothAdapter mBluetoothAdapter;
private final boolean mShowDevicesWithoutNames;
- private final long mCurrentTime;
+ @NonNull
+ private static final AtomicInteger sNextId = new AtomicInteger();
+ private final int mId;
private final int mType;
private AlertDialog mDisconnectDialog;
@@ -127,8 +132,9 @@ public final class BluetoothDevicePreference extends GearPreference {
mCachedDevice = cachedDevice;
mCallback = new BluetoothDevicePreferenceCallback();
- mCurrentTime = System.currentTimeMillis();
+ mId = sNextId.getAndIncrement();
mType = type;
+ setVisible(false);
onPreferenceAttributesChanged();
}
@@ -229,35 +235,41 @@ public final class BluetoothDevicePreference extends GearPreference {
@SuppressWarnings("FutureReturnValueIgnored")
void onPreferenceAttributesChanged() {
- Pair pair = mCachedDevice.getDrawableWithDescription();
- setIcon(pair.first);
- contentDescription = pair.second;
-
- /*
- * The preference framework takes care of making sure the value has
- * changed before proceeding. It will also call notifyChanged() if
- * any preference info has changed from the previous value.
- */
- setTitle(mCachedDevice.getName());
try {
ThreadUtils.postOnBackgroundThread(() -> {
+ @Nullable String name = mCachedDevice.getName();
// Null check is done at the framework
- ThreadUtils.postOnMainThread(() -> setSummary(getConnectionSummary()));
+ @Nullable String connectionSummary = getConnectionSummary();
+ @NonNull Pair pair = mCachedDevice.getDrawableWithDescription();
+ boolean isBusy = mCachedDevice.isBusy();
+ // Device is only visible in the UI if it has a valid name besides MAC address or
+ // when user allows showing devices without user-friendly name in developer settings
+ boolean isVisible =
+ mShowDevicesWithoutNames || mCachedDevice.hasHumanReadableName();
+
+ ThreadUtils.postOnMainThread(() -> {
+ /*
+ * The preference framework takes care of making sure the value has
+ * changed before proceeding. It will also call notifyChanged() if
+ * any preference info has changed from the previous value.
+ */
+ setTitle(name);
+ setSummary(connectionSummary);
+ setIcon(pair.first);
+ contentDescription = pair.second;
+ // Used to gray out the item
+ setEnabled(!isBusy);
+ setVisible(isVisible);
+
+ // This could affect ordering, so notify that
+ if (mNeedNotifyHierarchyChanged) {
+ notifyHierarchyChanged();
+ }
+ });
});
} catch (RejectedExecutionException e) {
Log.w(TAG, "Handler thread unavailable, skipping getConnectionSummary!");
}
- // Used to gray out the item
- setEnabled(!mCachedDevice.isBusy());
-
- // Device is only visible in the UI if it has a valid name besides MAC address or when user
- // allows showing devices without user-friendly name in developer settings
- setVisible(mShowDevicesWithoutNames || mCachedDevice.hasHumanReadableName());
-
- // This could affect ordering, so notify that
- if (mNeedNotifyHierarchyChanged) {
- notifyHierarchyChanged();
- }
}
@Override
@@ -311,7 +323,7 @@ public final class BluetoothDevicePreference extends GearPreference {
return mCachedDevice
.compareTo(((BluetoothDevicePreference) another).mCachedDevice);
case SortType.TYPE_FIFO:
- return mCurrentTime > ((BluetoothDevicePreference) another).mCurrentTime ? 1 : -1;
+ return mId > ((BluetoothDevicePreference) another).mId ? 1 : -1;
default:
return super.compareTo(another);
}
diff --git a/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java b/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java
deleted file mode 100644
index a4a98917974..00000000000
--- a/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java
+++ /dev/null
@@ -1,351 +0,0 @@
-/*
- * Copyright (C) 2011 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.bluetooth;
-
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.le.BluetoothLeScanner;
-import android.bluetooth.le.ScanCallback;
-import android.bluetooth.le.ScanFilter;
-import android.bluetooth.le.ScanResult;
-import android.bluetooth.le.ScanSettings;
-import android.os.Bundle;
-import android.os.SystemProperties;
-import android.text.BidiFormatter;
-import android.util.Log;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceCategory;
-import androidx.preference.PreferenceGroup;
-
-import com.android.settings.R;
-import com.android.settings.dashboard.RestrictedDashboardFragment;
-import com.android.settingslib.bluetooth.BluetoothCallback;
-import com.android.settingslib.bluetooth.BluetoothDeviceFilter;
-import com.android.settingslib.bluetooth.CachedBluetoothDevice;
-import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
-import com.android.settingslib.bluetooth.LocalBluetoothManager;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * Parent class for settings fragments that contain a list of Bluetooth
- * devices.
- *
- * @see DevicePickerFragment
- */
-// TODO: Refactor this fragment
-public abstract class DeviceListPreferenceFragment extends
- RestrictedDashboardFragment implements BluetoothCallback {
-
- private static final String TAG = "DeviceListPreferenceFragment";
-
- private static final String KEY_BT_SCAN = "bt_scan";
-
- // Copied from BluetoothDeviceNoNamePreferenceController.java
- private static final String BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_PROPERTY =
- "persist.bluetooth.showdeviceswithoutnames";
-
- private BluetoothDeviceFilter.Filter mFilter;
- private List mLeScanFilters;
- private ScanCallback mScanCallback;
-
- @VisibleForTesting
- protected boolean mScanEnabled;
-
- protected BluetoothDevice mSelectedDevice;
-
- protected BluetoothAdapter mBluetoothAdapter;
- protected LocalBluetoothManager mLocalManager;
- protected CachedBluetoothDeviceManager mCachedDeviceManager;
-
- @VisibleForTesting
- protected PreferenceGroup mDeviceListGroup;
-
- protected final HashMap mDevicePreferenceMap =
- new HashMap<>();
- protected final List mSelectedList = new ArrayList<>();
-
- protected boolean mShowDevicesWithoutNames;
-
- public DeviceListPreferenceFragment(String restrictedKey) {
- super(restrictedKey);
- mFilter = BluetoothDeviceFilter.ALL_FILTER;
- }
-
- protected final void setFilter(BluetoothDeviceFilter.Filter filter) {
- mFilter = filter;
- }
-
- protected final void setFilter(int filterType) {
- mFilter = BluetoothDeviceFilter.getFilter(filterType);
- }
-
- /**
- * Sets the bluetooth device scanning filter with {@link ScanFilter}s. It will change to start
- * {@link BluetoothLeScanner} which will scan BLE device only.
- *
- * @param leScanFilters list of settings to filter scan result
- */
- protected void setFilter(List leScanFilters) {
- mFilter = null;
- mLeScanFilters = leScanFilters;
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- mLocalManager = Utils.getLocalBtManager(getActivity());
- if (mLocalManager == null) {
- Log.e(TAG, "Bluetooth is not supported on this device");
- return;
- }
- mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
- mCachedDeviceManager = mLocalManager.getCachedDeviceManager();
- mShowDevicesWithoutNames = SystemProperties.getBoolean(
- BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_PROPERTY, false);
-
- initPreferencesFromPreferenceScreen();
-
- mDeviceListGroup = (PreferenceCategory) findPreference(getDeviceListKey());
- }
-
- /** find and update preference that already existed in preference screen */
- protected abstract void initPreferencesFromPreferenceScreen();
-
- @Override
- public void onStart() {
- super.onStart();
- if (mLocalManager == null || isUiRestricted()) return;
-
- mLocalManager.setForegroundActivity(getActivity());
- mLocalManager.getEventManager().registerCallback(this);
- }
-
- @Override
- public void onStop() {
- super.onStop();
- if (mLocalManager == null || isUiRestricted()) {
- return;
- }
-
- removeAllDevices();
- mLocalManager.setForegroundActivity(null);
- mLocalManager.getEventManager().unregisterCallback(this);
- }
-
- void removeAllDevices() {
- mDevicePreferenceMap.clear();
- mDeviceListGroup.removeAll();
- }
-
- void addCachedDevices() {
- Collection cachedDevices =
- mCachedDeviceManager.getCachedDevicesCopy();
- for (CachedBluetoothDevice cachedDevice : cachedDevices) {
- onDeviceAdded(cachedDevice);
- }
- }
-
- @Override
- public boolean onPreferenceTreeClick(Preference preference) {
- if (KEY_BT_SCAN.equals(preference.getKey())) {
- startScanning();
- return true;
- }
-
- if (preference instanceof BluetoothDevicePreference) {
- BluetoothDevicePreference btPreference = (BluetoothDevicePreference) preference;
- CachedBluetoothDevice device = btPreference.getCachedDevice();
- mSelectedDevice = device.getDevice();
- mSelectedList.add(mSelectedDevice);
- onDevicePreferenceClick(btPreference);
- return true;
- }
-
- return super.onPreferenceTreeClick(preference);
- }
-
- protected void onDevicePreferenceClick(BluetoothDevicePreference btPreference) {
- btPreference.onClicked();
- }
-
- @Override
- public void onDeviceAdded(CachedBluetoothDevice cachedDevice) {
- if (mDevicePreferenceMap.get(cachedDevice) != null) {
- return;
- }
-
- // Prevent updates while the list shows one of the state messages
- if (mBluetoothAdapter.getState() != BluetoothAdapter.STATE_ON) {
- return;
- }
-
- if (mFilter != null && mFilter.matches(cachedDevice.getDevice())) {
- createDevicePreference(cachedDevice);
- }
- }
-
- void createDevicePreference(CachedBluetoothDevice cachedDevice) {
- if (mDeviceListGroup == null) {
- Log.w(TAG, "Trying to create a device preference before the list group/category "
- + "exists!");
- return;
- }
-
- String key = cachedDevice.getDevice().getAddress();
- BluetoothDevicePreference preference = (BluetoothDevicePreference) getCachedPreference(key);
-
- if (preference == null) {
- preference = new BluetoothDevicePreference(getPrefContext(), cachedDevice,
- mShowDevicesWithoutNames, BluetoothDevicePreference.SortType.TYPE_FIFO);
- preference.setKey(key);
- //Set hideSecondTarget is true if it's bonded device.
- preference.hideSecondTarget(true);
- mDeviceListGroup.addPreference(preference);
- }
-
- initDevicePreference(preference);
- mDevicePreferenceMap.put(cachedDevice, preference);
- }
-
- protected void initDevicePreference(BluetoothDevicePreference preference) {
- // Does nothing by default
- }
-
- @VisibleForTesting
- void updateFooterPreference(Preference myDevicePreference) {
- final BidiFormatter bidiFormatter = BidiFormatter.getInstance();
-
- myDevicePreference.setTitle(getString(
- R.string.bluetooth_footer_mac_message,
- bidiFormatter.unicodeWrap(mBluetoothAdapter.getAddress())));
- }
-
- @Override
- public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) {
- BluetoothDevicePreference preference = mDevicePreferenceMap.remove(cachedDevice);
- if (preference != null) {
- mDeviceListGroup.removePreference(preference);
- }
- }
-
- @VisibleForTesting
- protected void enableScanning() {
- // BluetoothAdapter already handles repeated scan requests
- if (!mScanEnabled) {
- startScanning();
- mScanEnabled = true;
- }
- }
-
- @VisibleForTesting
- protected void disableScanning() {
- if (mScanEnabled) {
- stopScanning();
- mScanEnabled = false;
- }
- }
-
- @Override
- public void onScanningStateChanged(boolean started) {
- if (!started && mScanEnabled) {
- startScanning();
- }
- }
-
- /**
- * Return the key of the {@link PreferenceGroup} that contains the bluetooth devices
- */
- public abstract String getDeviceListKey();
-
- public boolean shouldShowDevicesWithoutNames() {
- return mShowDevicesWithoutNames;
- }
-
- @VisibleForTesting
- void startScanning() {
- if (mFilter != null) {
- startClassicScanning();
- } else if (mLeScanFilters != null) {
- startLeScanning();
- }
-
- }
-
- @VisibleForTesting
- void stopScanning() {
- if (mFilter != null) {
- stopClassicScanning();
- } else if (mLeScanFilters != null) {
- stopLeScanning();
- }
- }
-
- private void startClassicScanning() {
- if (!mBluetoothAdapter.isDiscovering()) {
- mBluetoothAdapter.startDiscovery();
- }
- }
-
- private void stopClassicScanning() {
- if (mBluetoothAdapter.isDiscovering()) {
- mBluetoothAdapter.cancelDiscovery();
- }
- }
-
- private void startLeScanning() {
- final BluetoothLeScanner scanner = mBluetoothAdapter.getBluetoothLeScanner();
- final ScanSettings settings = new ScanSettings.Builder()
- .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
- .build();
- mScanCallback = new ScanCallback() {
- @Override
- public void onScanResult(int callbackType, ScanResult result) {
- final BluetoothDevice device = result.getDevice();
- CachedBluetoothDevice cachedDevice = mCachedDeviceManager.findDevice(device);
- if (cachedDevice == null) {
- cachedDevice = mCachedDeviceManager.addDevice(device);
- }
- // Only add device preference when it's not found in the map and there's no other
- // state message showing in the list
- if (mDevicePreferenceMap.get(cachedDevice) == null
- && mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {
- createDevicePreference(cachedDevice);
- }
- }
-
- @Override
- public void onScanFailed(int errorCode) {
- Log.w(TAG, "BLE Scan failed with error code " + errorCode);
- }
- };
- scanner.startScan(mLeScanFilters, settings, mScanCallback);
- }
-
- private void stopLeScanning() {
- final BluetoothLeScanner scanner = mBluetoothAdapter.getBluetoothLeScanner();
- if (scanner != null) {
- scanner.stopScan(mScanCallback);
- }
- }
-}
diff --git a/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.kt b/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.kt
new file mode 100644
index 00000000000..9c86e4398f6
--- /dev/null
+++ b/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.kt
@@ -0,0 +1,348 @@
+/*
+ * 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.bluetooth
+
+import android.bluetooth.BluetoothAdapter
+import android.bluetooth.BluetoothDevice
+import android.bluetooth.le.BluetoothLeScanner
+import android.bluetooth.le.ScanCallback
+import android.bluetooth.le.ScanFilter
+import android.bluetooth.le.ScanResult
+import android.bluetooth.le.ScanSettings
+import android.os.Bundle
+import android.os.SystemProperties
+import android.text.BidiFormatter
+import android.util.Log
+import android.view.View
+import androidx.annotation.VisibleForTesting
+import androidx.lifecycle.LifecycleCoroutineScope
+import androidx.lifecycle.lifecycleScope
+import androidx.preference.Preference
+import androidx.preference.PreferenceCategory
+import androidx.preference.PreferenceGroup
+import com.android.settings.R
+import com.android.settings.dashboard.RestrictedDashboardFragment
+import com.android.settingslib.bluetooth.BluetoothCallback
+import com.android.settingslib.bluetooth.BluetoothDeviceFilter
+import com.android.settingslib.bluetooth.CachedBluetoothDevice
+import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager
+import com.android.settingslib.bluetooth.LocalBluetoothManager
+import java.util.concurrent.ConcurrentHashMap
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+/**
+ * Parent class for settings fragments that contain a list of Bluetooth devices.
+ *
+ * @see DevicePickerFragment
+ *
+ * TODO: Refactor this fragment
+ */
+abstract class DeviceListPreferenceFragment(restrictedKey: String?) :
+ RestrictedDashboardFragment(restrictedKey), BluetoothCallback {
+
+ private var filter: BluetoothDeviceFilter.Filter? = BluetoothDeviceFilter.ALL_FILTER
+ private var leScanFilters: List? = null
+
+ @JvmField
+ @VisibleForTesting
+ var mScanEnabled = false
+
+ @JvmField
+ var mSelectedDevice: BluetoothDevice? = null
+
+ @JvmField
+ var mBluetoothAdapter: BluetoothAdapter? = null
+
+ @JvmField
+ var mLocalManager: LocalBluetoothManager? = null
+
+ @JvmField
+ var mCachedDeviceManager: CachedBluetoothDeviceManager? = null
+
+ @JvmField
+ @VisibleForTesting
+ var mDeviceListGroup: PreferenceGroup? = null
+
+ @VisibleForTesting
+ val devicePreferenceMap =
+ ConcurrentHashMap()
+
+ @JvmField
+ val mSelectedList: MutableList = ArrayList()
+
+ private var showDevicesWithoutNames = false
+
+ protected fun setFilter(filter: BluetoothDeviceFilter.Filter?) {
+ this.filter = filter
+ }
+
+ protected fun setFilter(filterType: Int) {
+ filter = BluetoothDeviceFilter.getFilter(filterType)
+ }
+
+ /**
+ * Sets the bluetooth device scanning filter with [ScanFilter]s. It will change to start
+ * [BluetoothLeScanner] which will scan BLE device only.
+ *
+ * @param leScanFilters list of settings to filter scan result
+ */
+ fun setFilter(leScanFilters: List?) {
+ filter = null
+ this.leScanFilters = leScanFilters
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ mLocalManager = Utils.getLocalBtManager(activity)
+ if (mLocalManager == null) {
+ Log.e(TAG, "Bluetooth is not supported on this device")
+ return
+ }
+ mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
+ mCachedDeviceManager = mLocalManager!!.cachedDeviceManager
+ showDevicesWithoutNames = SystemProperties.getBoolean(
+ BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_PROPERTY, false
+ )
+ initPreferencesFromPreferenceScreen()
+ mDeviceListGroup = findPreference(deviceListKey) as PreferenceCategory
+ }
+
+ /** find and update preference that already existed in preference screen */
+ protected abstract fun initPreferencesFromPreferenceScreen()
+
+ private var lifecycleScope: LifecycleCoroutineScope? = null
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ lifecycleScope = viewLifecycleOwner.lifecycleScope
+ }
+
+ override fun onStart() {
+ super.onStart()
+ if (mLocalManager == null || isUiRestricted) return
+ mLocalManager!!.foregroundActivity = activity
+ mLocalManager!!.eventManager.registerCallback(this)
+ }
+
+ override fun onStop() {
+ super.onStop()
+ if (mLocalManager == null || isUiRestricted) {
+ return
+ }
+ removeAllDevices()
+ mLocalManager!!.foregroundActivity = null
+ mLocalManager!!.eventManager.unregisterCallback(this)
+ }
+
+ fun removeAllDevices() {
+ devicePreferenceMap.clear()
+ mDeviceListGroup!!.removeAll()
+ }
+
+ fun addCachedDevices() {
+ lifecycleScope?.launch {
+ withContext(Dispatchers.Default) {
+ val cachedDevices = mCachedDeviceManager!!.cachedDevicesCopy
+ for (cachedDevice in cachedDevices) {
+ onDeviceAdded(cachedDevice)
+ }
+ }
+ }
+ }
+
+ override fun onPreferenceTreeClick(preference: Preference): Boolean {
+ if (KEY_BT_SCAN == preference.key) {
+ startScanning()
+ return true
+ }
+ if (preference is BluetoothDevicePreference) {
+ val device = preference.cachedDevice.device
+ mSelectedDevice = device
+ mSelectedList.add(device)
+ onDevicePreferenceClick(preference)
+ return true
+ }
+ return super.onPreferenceTreeClick(preference)
+ }
+
+ protected open fun onDevicePreferenceClick(btPreference: BluetoothDevicePreference) {
+ btPreference.onClicked()
+ }
+
+ override fun onDeviceAdded(cachedDevice: CachedBluetoothDevice) {
+ lifecycleScope?.launch {
+ addDevice(cachedDevice)
+ }
+ }
+
+ private suspend fun addDevice(cachedDevice: CachedBluetoothDevice) =
+ withContext(Dispatchers.Default) {
+ // Prevent updates while the list shows one of the state messages
+ if (mBluetoothAdapter!!.state == BluetoothAdapter.STATE_ON &&
+ filter?.matches(cachedDevice.device) == true
+ ) {
+ createDevicePreference(cachedDevice)
+ }
+ }
+
+ private suspend fun createDevicePreference(cachedDevice: CachedBluetoothDevice) {
+ if (mDeviceListGroup == null) {
+ Log.w(
+ TAG,
+ "Trying to create a device preference before the list group/category exists!",
+ )
+ return
+ }
+ // Only add device preference when it's not found in the map and there's no other state
+ // message showing in the list
+ val preference = devicePreferenceMap.computeIfAbsent(cachedDevice) {
+ BluetoothDevicePreference(
+ prefContext,
+ cachedDevice,
+ showDevicesWithoutNames,
+ BluetoothDevicePreference.SortType.TYPE_FIFO,
+ ).apply {
+ key = cachedDevice.device.address
+ //Set hideSecondTarget is true if it's bonded device.
+ hideSecondTarget(true)
+ }
+ }
+ withContext(Dispatchers.Main) {
+ mDeviceListGroup!!.addPreference(preference)
+ initDevicePreference(preference)
+ }
+ }
+
+ protected open fun initDevicePreference(preference: BluetoothDevicePreference?) {
+ // Does nothing by default
+ }
+
+ @VisibleForTesting
+ fun updateFooterPreference(myDevicePreference: Preference) {
+ val bidiFormatter = BidiFormatter.getInstance()
+ myDevicePreference.title = getString(
+ R.string.bluetooth_footer_mac_message,
+ bidiFormatter.unicodeWrap(mBluetoothAdapter!!.address)
+ )
+ }
+
+ override fun onDeviceDeleted(cachedDevice: CachedBluetoothDevice) {
+ devicePreferenceMap.remove(cachedDevice)?.let {
+ mDeviceListGroup!!.removePreference(it)
+ }
+ }
+
+ @VisibleForTesting
+ open fun enableScanning() {
+ // BluetoothAdapter already handles repeated scan requests
+ if (!mScanEnabled) {
+ startScanning()
+ mScanEnabled = true
+ }
+ }
+
+ @VisibleForTesting
+ fun disableScanning() {
+ if (mScanEnabled) {
+ stopScanning()
+ mScanEnabled = false
+ }
+ }
+
+ override fun onScanningStateChanged(started: Boolean) {
+ if (!started && mScanEnabled) {
+ startScanning()
+ }
+ }
+
+ /**
+ * Return the key of the [PreferenceGroup] that contains the bluetooth devices
+ */
+ abstract val deviceListKey: String
+
+ @VisibleForTesting
+ open fun startScanning() {
+ if (filter != null) {
+ startClassicScanning()
+ } else if (leScanFilters != null) {
+ startLeScanning()
+ }
+ }
+
+ @VisibleForTesting
+ open fun stopScanning() {
+ if (filter != null) {
+ stopClassicScanning()
+ } else if (leScanFilters != null) {
+ stopLeScanning()
+ }
+ }
+
+ private fun startClassicScanning() {
+ if (!mBluetoothAdapter!!.isDiscovering) {
+ mBluetoothAdapter!!.startDiscovery()
+ }
+ }
+
+ private fun stopClassicScanning() {
+ if (mBluetoothAdapter!!.isDiscovering) {
+ mBluetoothAdapter!!.cancelDiscovery()
+ }
+ }
+
+ private val scanCallback = object : ScanCallback() {
+ override fun onScanResult(callbackType: Int, result: ScanResult) {
+ lifecycleScope?.launch {
+ withContext(Dispatchers.Default) {
+ if (mBluetoothAdapter!!.state == BluetoothAdapter.STATE_ON) {
+ val device = result.device
+ val cachedDevice = mCachedDeviceManager!!.findDevice(device)
+ ?: mCachedDeviceManager!!.addDevice(device)
+ createDevicePreference(cachedDevice)
+ }
+ }
+ }
+ }
+
+ override fun onScanFailed(errorCode: Int) {
+ Log.w(TAG, "BLE Scan failed with error code $errorCode")
+ }
+ }
+
+ private fun startLeScanning() {
+ val scanner = mBluetoothAdapter!!.bluetoothLeScanner
+ val settings = ScanSettings.Builder()
+ .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
+ .build()
+ scanner.startScan(leScanFilters, settings, scanCallback)
+ }
+
+ private fun stopLeScanning() {
+ val scanner = mBluetoothAdapter!!.bluetoothLeScanner
+ scanner?.stopScan(scanCallback)
+ }
+
+ companion object {
+ private const val TAG = "DeviceListPreferenceFragment"
+ private const val KEY_BT_SCAN = "bt_scan"
+
+ // Copied from BluetoothDeviceNoNamePreferenceController.java
+ private const val BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_PROPERTY =
+ "persist.bluetooth.showdeviceswithoutnames"
+ }
+}
diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java
index f8a5d76b6fa..d4acfa11c57 100644
--- a/src/com/android/settings/dashboard/DashboardFragment.java
+++ b/src/com/android/settings/dashboard/DashboardFragment.java
@@ -25,11 +25,14 @@ import android.preference.PreferenceManager.OnActivityResultListener;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
+import android.view.View;
import androidx.annotation.CallSuper;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceGroup;
@@ -169,6 +172,15 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
}
}
+ @Override
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ LifecycleOwner viewLifecycleOwner = getViewLifecycleOwner();
+ for (AbstractPreferenceController controller : mControllers) {
+ controller.onViewCreated(viewLifecycleOwner);
+ }
+ }
+
@Override
public void onCategoriesChanged(Set categories) {
final String categoryKey = getCategoryKey();
diff --git a/src/com/android/settings/datausage/DataSaverSummary.kt b/src/com/android/settings/datausage/DataSaverSummary.kt
index 13fbbfa3069..0828d362410 100644
--- a/src/com/android/settings/datausage/DataSaverSummary.kt
+++ b/src/com/android/settings/datausage/DataSaverSummary.kt
@@ -19,11 +19,9 @@ import android.app.settings.SettingsEnums
import android.content.Context
import android.os.Bundle
import android.telephony.SubscriptionManager
-import android.view.View
import android.widget.Switch
import com.android.settings.R
import com.android.settings.SettingsActivity
-import com.android.settings.applications.specialaccess.DataSaverController
import com.android.settings.dashboard.DashboardFragment
import com.android.settings.search.BaseSearchIndexProvider
import com.android.settings.widget.SettingsMainSwitchBar
@@ -59,11 +57,6 @@ class DataSaverSummary : DashboardFragment() {
}
}
- override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
- use(DataSaverController::class.java).init(viewLifecycleOwner)
- }
-
override fun onResume() {
super.onResume()
dataSaverBackend.addListener(dataSaverBackendListener)
diff --git a/src/com/android/settings/password/ChooseLockSettingsHelper.java b/src/com/android/settings/password/ChooseLockSettingsHelper.java
index 943a937a32a..9533314c8a2 100644
--- a/src/com/android/settings/password/ChooseLockSettingsHelper.java
+++ b/src/com/android/settings/password/ChooseLockSettingsHelper.java
@@ -362,7 +362,8 @@ public final class ChooseLockSettingsHelper {
}
@NonNull public ChooseLockSettingsHelper build() {
- if (!mAllowAnyUserId && mUserId != LockPatternUtils.USER_FRP) {
+ if (!mAllowAnyUserId && mUserId != LockPatternUtils.USER_FRP
+ && mUserId != LockPatternUtils.USER_REPAIR_MODE) {
Utils.enforceSameOwner(mActivity, mUserId);
}
diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
index d409c0f9dfb..314ce053127 100644
--- a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
+++ b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
@@ -166,8 +166,12 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
mDetails = intent.getCharSequenceExtra(KeyguardManager.EXTRA_DESCRIPTION);
String alternateButton = intent.getStringExtra(
KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL);
- boolean frp = KeyguardManager.ACTION_CONFIRM_FRP_CREDENTIAL.equals(intent.getAction());
- boolean remoteValidation =
+ final boolean frp =
+ KeyguardManager.ACTION_CONFIRM_FRP_CREDENTIAL.equals(intent.getAction());
+ final boolean repairMode =
+ KeyguardManager.ACTION_CONFIRM_REPAIR_MODE_DEVICE_CREDENTIAL
+ .equals(intent.getAction());
+ final boolean remoteValidation =
KeyguardManager.ACTION_CONFIRM_REMOTE_DEVICE_CREDENTIAL.equals(intent.getAction());
mTaskOverlay = isInternalActivity()
&& intent.getBooleanExtra(KeyguardManager.EXTRA_FORCE_TASK_OVERLAY, false);
@@ -222,6 +226,14 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
.setExternal(true)
.setUserId(LockPatternUtils.USER_FRP)
.show();
+ } else if (repairMode) {
+ final ChooseLockSettingsHelper.Builder builder =
+ new ChooseLockSettingsHelper.Builder(this);
+ launchedCDC = builder.setHeader(mTitle)
+ .setDescription(mDetails)
+ .setExternal(true)
+ .setUserId(LockPatternUtils.USER_REPAIR_MODE)
+ .show();
} else if (remoteValidation) {
RemoteLockscreenValidationSession remoteLockscreenValidationSession =
intent.getParcelableExtra(
diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java b/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java
index 5a123b89315..43d8440512b 100644
--- a/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java
+++ b/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java
@@ -106,6 +106,7 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
protected boolean mFrp;
protected boolean mRemoteValidation;
protected boolean mRequestWriteRepairModePassword;
+ protected boolean mRepairMode;
protected CharSequence mAlternateButtonText;
protected BiometricManager mBiometricManager;
@Nullable protected RemoteLockscreenValidationSession mRemoteLockscreenValidationSession;
@@ -181,6 +182,7 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
mUserId = Utils.getUserIdFromBundle(getActivity(), intent.getExtras(),
isInternalActivity());
mFrp = (mUserId == LockPatternUtils.USER_FRP);
+ mRepairMode = (mUserId == LockPatternUtils.USER_REPAIR_MODE);
mUserManager = UserManager.get(getActivity());
mEffectiveUserId = mUserManager.getCredentialOwnerProfile(mUserId);
mLockPatternUtils = new LockPatternUtils(getActivity());
@@ -269,7 +271,7 @@ public abstract class ConfirmDeviceCredentialBaseFragment extends InstrumentedFr
// verifyTiedProfileChallenge. In such case, we also wanna show the user message that
// fingerprint is disabled due to device restart.
protected boolean isStrongAuthRequired() {
- return mFrp
+ return mFrp || mRepairMode
|| !mLockPatternUtils.isBiometricAllowedForUser(mEffectiveUserId)
|| !mUserManager.isUserUnlocked(mUserId);
}
diff --git a/src/com/android/settings/password/ConfirmLockPassword.java b/src/com/android/settings/password/ConfirmLockPassword.java
index 1b535069f3c..c6022b5d3ce 100644
--- a/src/com/android/settings/password/ConfirmLockPassword.java
+++ b/src/com/android/settings/password/ConfirmLockPassword.java
@@ -284,6 +284,11 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
return mIsAlpha ? getString(R.string.lockpassword_confirm_your_password_header_frp)
: getString(R.string.lockpassword_confirm_your_pin_header_frp);
}
+ if (mRepairMode) {
+ return mIsAlpha
+ ? getString(R.string.lockpassword_confirm_repair_mode_password_header)
+ : getString(R.string.lockpassword_confirm_repair_mode_pin_header);
+ }
if (mRemoteValidation) {
return getString(R.string.lockpassword_remote_validation_header);
}
@@ -307,6 +312,11 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
return mIsAlpha ? getString(R.string.lockpassword_confirm_your_password_details_frp)
: getString(R.string.lockpassword_confirm_your_pin_details_frp);
}
+ if (mRepairMode) {
+ return mIsAlpha
+ ? getString(R.string.lockpassword_confirm_repair_mode_password_details)
+ : getString(R.string.lockpassword_confirm_repair_mode_pin_details);
+ }
if (mRemoteValidation) {
return getContext().getString(mIsAlpha
? R.string.lockpassword_remote_validation_password_details
diff --git a/src/com/android/settings/password/ConfirmLockPattern.java b/src/com/android/settings/password/ConfirmLockPattern.java
index 3951bde9bac..a2bcb5af510 100644
--- a/src/com/android/settings/password/ConfirmLockPattern.java
+++ b/src/com/android/settings/password/ConfirmLockPattern.java
@@ -179,7 +179,7 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
// ability to disable the pattern in L. Remove this block after
// ensuring it's safe to do so. (Note that ConfirmLockPassword
// doesn't have this).
- if (!mFrp && !mRemoteValidation
+ if (!mFrp && !mRemoteValidation && !mRepairMode
&& !mLockPatternUtils.isLockPatternEnabled(mEffectiveUserId)) {
getActivity().setResult(Activity.RESULT_OK);
getActivity().finish();
@@ -308,6 +308,9 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
if (mFrp) {
return getString(R.string.lockpassword_confirm_your_pattern_details_frp);
}
+ if (mRepairMode) {
+ return getString(R.string.lockpassword_confirm_repair_mode_pattern_details);
+ }
if (mRemoteValidation) {
return getString(
R.string.lockpassword_remote_validation_pattern_details);
@@ -402,7 +405,12 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
}
private String getDefaultHeader() {
- if (mFrp) return getString(R.string.lockpassword_confirm_your_pattern_header_frp);
+ if (mFrp) {
+ return getString(R.string.lockpassword_confirm_your_pattern_header_frp);
+ }
+ if (mRepairMode) {
+ return getString(R.string.lockpassword_confirm_repair_mode_pattern_header);
+ }
if (mRemoteValidation) {
return getString(R.string.lockpassword_remote_validation_header);
}
diff --git a/src/com/android/settings/spa/development/UsageStats.kt b/src/com/android/settings/spa/development/UsageStats.kt
index b681d7579de..4d9c4551f10 100644
--- a/src/com/android/settings/spa/development/UsageStats.kt
+++ b/src/com/android/settings/spa/development/UsageStats.kt
@@ -32,7 +32,6 @@ object UsageStatsPageProvider : SettingsPageProvider {
AppListPage(
title = stringResource(R.string.testing_usage_stats),
listModel = rememberContext(::UsageStatsListModel),
- primaryUserOnly = true,
)
}
}
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizardTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizardTest.java
index e14e27109e0..ea2852fd75e 100644
--- a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizardTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizardTest.java
@@ -38,6 +38,7 @@ import android.content.pm.ServiceInfo;
import android.view.accessibility.AccessibilityManager;
import androidx.fragment.app.FragmentActivity;
+import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
@@ -93,6 +94,7 @@ public class AccessibilitySettingsForSetupWizardTest {
when(mAccessibilityManager.getInstalledAccessibilityServiceList()).thenReturn(
mAccessibilityServices);
doReturn(mActivity).when(mFragment).getActivity();
+ doReturn(mock(LifecycleOwner.class)).when(mFragment).getViewLifecycleOwner();
doReturn(mFooterBarMixin).when(mGlifLayoutView).getMixin(FooterBarMixin.class);
}
diff --git a/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizardTest.java b/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizardTest.java
index 1cd301f98b9..4ee2a2dedbd 100644
--- a/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizardTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizardTest.java
@@ -22,6 +22,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -29,6 +30,7 @@ import android.app.settings.SettingsEnums;
import android.content.Context;
import androidx.fragment.app.FragmentActivity;
+import androidx.lifecycle.LifecycleOwner;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
@@ -73,6 +75,7 @@ public class TextReadingPreferenceFragmentForSetupWizardTest {
final LayoutPreference resetPreference =
new LayoutPreference(mContext, R.layout.accessibility_text_reading_reset_button);
doReturn(mContext).when(mFragment).getContext();
+ doReturn(mock(LifecycleOwner.class)).when(mFragment).getViewLifecycleOwner();
doReturn(resetPreference).when(mFragment).findPreference(RESET_KEY);
doReturn(mFooterBarMixin).when(mGlifLayoutView).getMixin(FooterBarMixin.class);
}
diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizardTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizardTest.java
index 84783b21a3a..aa622f58afd 100644
--- a/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizardTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizardTest.java
@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -27,6 +28,7 @@ import static org.mockito.Mockito.when;
import android.app.settings.SettingsEnums;
import android.content.Context;
+import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
@@ -75,6 +77,7 @@ public class ToggleScreenMagnificationPreferenceFragmentForSetupWizardTest {
mFragment =
spy(new TestToggleScreenMagnificationPreferenceFragmentForSetupWizard(mContext));
doReturn(mActivity).when(mFragment).getActivity();
+ doReturn(mock(LifecycleOwner.class)).when(mFragment).getViewLifecycleOwner();
when(mActivity.getSwitchBar()).thenReturn(mSwitchBar);
doReturn(mFooterBarMixin).when(mGlifLayoutView).getMixin(FooterBarMixin.class);
}
diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizardTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizardTest.java
index c604652fd50..77e5b1f9b9d 100644
--- a/tests/robotests/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizardTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizardTest.java
@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -28,6 +29,7 @@ import android.app.settings.SettingsEnums;
import android.content.Context;
import android.os.Bundle;
+import androidx.lifecycle.LifecycleOwner;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
@@ -72,6 +74,7 @@ public class ToggleScreenReaderPreferenceFragmentForSetupWizardTest {
public void setUp() {
mFragment = spy(new TestToggleScreenReaderPreferenceFragmentForSetupWizard(mContext));
doReturn(mActivity).when(mFragment).getActivity();
+ doReturn(mock(LifecycleOwner.class)).when(mFragment).getViewLifecycleOwner();
when(mActivity.getSwitchBar()).thenReturn(mSwitchBar);
doReturn(mFooterBarMixin).when(mGlifLayoutView).getMixin(FooterBarMixin.class);
}
diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleSelectToSpeakPreferenceFragmentForSetupWizardTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleSelectToSpeakPreferenceFragmentForSetupWizardTest.java
index 78938310d9a..8878064afa0 100644
--- a/tests/robotests/src/com/android/settings/accessibility/ToggleSelectToSpeakPreferenceFragmentForSetupWizardTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/ToggleSelectToSpeakPreferenceFragmentForSetupWizardTest.java
@@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -28,6 +29,7 @@ import android.app.settings.SettingsEnums;
import android.content.Context;
import android.os.Bundle;
+import androidx.lifecycle.LifecycleOwner;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
@@ -72,6 +74,7 @@ public class ToggleSelectToSpeakPreferenceFragmentForSetupWizardTest {
public void setUp() {
mFragment = spy(new TestToggleSelectToSpeakPreferenceFragmentForSetupWizard(mContext));
doReturn(mActivity).when(mFragment).getActivity();
+ doReturn(mock(LifecycleOwner.class)).when(mFragment).getViewLifecycleOwner();
when(mActivity.getSwitchBar()).thenReturn(mSwitchBar);
doReturn(mFooterBarMixin).when(mGlifLayoutView).getMixin(FooterBarMixin.class);
}
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java
index 8c84128913f..0f12d1e5023 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java
@@ -352,6 +352,19 @@ public class FingerprintEnrollEnrollingTest {
assertThat(descriptionTextView.getVisibility()).isEqualTo(View.VISIBLE);
}
+ @Test
+ public void fingerprintUdfpsOverlayEnrollment_udfpsAnimationViewVisibility() {
+ initializeActivityWithoutCreate(TYPE_UDFPS_OPTICAL);
+ when(mMockDisplay.getRotation()).thenReturn(Surface.ROTATION_0);
+ createActivity();
+
+ final UdfpsEnrollView enrollView = mActivity.findViewById(R.id.udfps_animation_view);
+ assertThat(enrollView.getVisibility()).isEqualTo(View.GONE);
+
+ mActivity.onUdfpsOverlayShown();
+ assertThat(enrollView.getVisibility()).isEqualTo(View.VISIBLE);
+ }
+
@Test
public void forwardEnrollProgressEvents() {
initializeActivityFor(TYPE_UDFPS_OPTICAL);
@@ -393,11 +406,11 @@ public class FingerprintEnrollEnrollingTest {
}
@Test
- public void forwardEnrollPointerDownEvents() {
+ public void forwardUdfpsEnrollPointerDownEvents() {
initializeActivityFor(TYPE_UDFPS_OPTICAL);
EnrollListener listener = new EnrollListener(mActivity);
- mActivity.onPointerDown(0);
+ mActivity.onUdfpsPointerDown(0);
assertThat(listener.mProgress).isFalse();
assertThat(listener.mHelp).isFalse();
assertThat(listener.mAcquired).isFalse();
@@ -406,11 +419,11 @@ public class FingerprintEnrollEnrollingTest {
}
@Test
- public void forwardEnrollPointerUpEvents() {
+ public void forwardUdfpsEnrollPointerUpEvents() {
initializeActivityFor(TYPE_UDFPS_OPTICAL);
EnrollListener listener = new EnrollListener(mActivity);
- mActivity.onPointerUp(0);
+ mActivity.onUdfpsPointerUp(0);
assertThat(listener.mProgress).isFalse();
assertThat(listener.mHelp).isFalse();
assertThat(listener.mAcquired).isFalse();
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBaseTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBaseTest.java
index 184f5212e77..7c598e00e42 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBaseTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDevicePairingDetailBaseTest.java
@@ -202,7 +202,7 @@ public class BluetoothDevicePairingDetailBaseTest {
new BluetoothDevicePreference(mContext, mCachedBluetoothDevice,
true, BluetoothDevicePreference.SortType.TYPE_FIFO);
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS);
- mFragment.mDevicePreferenceMap.put(mCachedBluetoothDevice, preference);
+ mFragment.getDevicePreferenceMap().put(mCachedBluetoothDevice, preference);
when(mCachedBluetoothDevice.isConnected()).thenReturn(true);
when(mCachedBluetoothDevice.getDevice()).thenReturn(device);
@@ -210,7 +210,7 @@ public class BluetoothDevicePairingDetailBaseTest {
mFragment.onProfileConnectionStateChanged(mCachedBluetoothDevice,
BluetoothProfile.A2DP, BluetoothAdapter.STATE_CONNECTED);
- assertThat(mFragment.mDevicePreferenceMap.size()).isEqualTo(0);
+ assertThat(mFragment.getDevicePreferenceMap().size()).isEqualTo(0);
}
@Test
@@ -221,7 +221,7 @@ public class BluetoothDevicePairingDetailBaseTest {
true, BluetoothDevicePreference.SortType.TYPE_FIFO);
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS);
final BluetoothDevice device2 = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_B);
- mFragment.mDevicePreferenceMap.put(mCachedBluetoothDevice, preference);
+ mFragment.getDevicePreferenceMap().put(mCachedBluetoothDevice, preference);
when(mCachedBluetoothDevice.isConnected()).thenReturn(true);
when(mCachedBluetoothDevice.getDevice()).thenReturn(device);
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDetailTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDetailTest.java
index 5fbfee8b50d..ce67051a7c7 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDetailTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothPairingDetailTest.java
@@ -27,7 +27,12 @@ import static org.mockito.Mockito.verify;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.os.Bundle;
+import android.view.View;
+import androidx.annotation.NonNull;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.LifecycleOwner;
import androidx.test.core.app.ApplicationProvider;
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
@@ -53,6 +58,20 @@ public class BluetoothPairingDetailTest {
private final Context mContext = ApplicationProvider.getApplicationContext();
+ private final Lifecycle mFakeLifecycle = new Lifecycle() {
+ @Override
+ public void addObserver(@NonNull LifecycleObserver observer) {}
+
+ @Override
+ public void removeObserver(@NonNull LifecycleObserver observer) {}
+
+ @NonNull
+ @Override
+ public State getCurrentState() {
+ return State.CREATED;
+ }
+ };
+
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private LocalBluetoothManager mLocalManager;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
@@ -74,6 +93,8 @@ public class BluetoothPairingDetailTest {
.findPreference(BluetoothPairingDetail.KEY_AVAIL_DEVICES);
doReturn(mFooterPreference).when(mFragment)
.findPreference(BluetoothPairingDetail.KEY_FOOTER_PREF);
+ doReturn(new View(mContext)).when(mFragment).getView();
+ doReturn((LifecycleOwner) () -> mFakeLifecycle).when(mFragment).getViewLifecycleOwner();
doReturn(Collections.emptyList()).when(mDeviceManager).getCachedDevicesCopy();
mFragment.mBluetoothAdapter = mBluetoothAdapter;
@@ -82,7 +103,7 @@ public class BluetoothPairingDetailTest {
mFragment.mDeviceListGroup = mAvailableDevicesCategory;
mFragment.onViewCreated(mFragment.getView(), Bundle.EMPTY);
}
-//
+
@Test
public void initPreferencesFromPreferenceScreen_findPreferences() {
mFragment.initPreferencesFromPreferenceScreen();
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 bdb45b0300f..2c830ad314c 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
@@ -379,7 +379,7 @@ public class FingerprintEnrollProgressViewModelTest {
// Notify acquire message
final int value = 33;
- mCallbackWrapper.mValue.onPointerDown(value);
+ mCallbackWrapper.mValue.onUdfpsPointerDown(value);
assertThat(liveData.getValue()).isEqualTo(value);
}
@@ -397,7 +397,7 @@ public class FingerprintEnrollProgressViewModelTest {
// Notify acquire message
final int value = 44;
- mCallbackWrapper.mValue.onPointerUp(value);
+ mCallbackWrapper.mValue.onUdfpsPointerUp(value);
assertThat(liveData.getValue()).isEqualTo(value);
}