diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 4df368bae18..78d729a0669 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -678,6 +678,18 @@
+
+
+
+
+
+
+
+ android:theme="@style/FallbackHome"
+ android:configChanges="keyboardHidden">
diff --git a/res/layout/preference_list_fragment.xml b/res/layout/preference_list_fragment.xml
index 03ba735db97..6dfec46fab1 100644
--- a/res/layout/preference_list_fragment.xml
+++ b/res/layout/preference_list_fragment.xml
@@ -20,7 +20,6 @@
+ style="@style/SettingsLibTabsStyle"/>
-
-
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 3363f929c25..9454b5ce789 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1301,6 +1301,13 @@
Encrypted
+
+ Set a screen lock
+
+ For added security, set a PIN, pattern, or password for this device.
+
+ Set screen lock
+
@@ -2574,6 +2581,10 @@
Turning hotspot on\u2026
Turning off hotspot\u2026
+
+ Tethering unavailable
+
+ Contact your carrier for details
%1$s is active
diff --git a/res/xml/security_lockscreen_settings.xml b/res/xml/security_lockscreen_settings.xml
index b61f4586f31..3bd84f81ae3 100644
--- a/res/xml/security_lockscreen_settings.xml
+++ b/res/xml/security_lockscreen_settings.xml
@@ -79,6 +79,7 @@
If the Setting is disabled by admin, returns {@link Intent} to launch an explanation.
+ * If Quiet Mode is enabled for managed profile, returns {@link Intent} to launch a dialog
+ * to disable the Quiet Mode. Otherwise, returns {@link Intent} to launch the Settings screen.
+ *
+ * @param className The class name of Settings screen to launch.
+ * @param enforcedAdmin Details of admin account that disables changing the setting.
+ * @param extras Extras to put into the result {@link Intent}.
+ */
+ public Intent getBiometricSettingsIntent(Context context, String className,
+ EnforcedAdmin enforcedAdmin, Bundle extras) {
+ if (enforcedAdmin != null) {
+ return getRestrictedDialogIntent(context, enforcedAdmin);
+ }
+ final Intent quietModeDialogIntent = getQuietModeDialogIntent(context);
+ return quietModeDialogIntent != null ? quietModeDialogIntent
+ : getSettingsPageIntent(className, extras);
+ }
+
+ private Intent getQuietModeDialogIntent(Context context) {
+ final UserManager userManager = UserManager.get(context);
+ if (userManager.isQuietModeEnabled(UserHandle.of(mUserId))) {
+ return UnlaunchableAppActivity.createInQuietModeDialogIntent(mUserId);
+ }
+ return null;
+ }
+
+ private Intent getRestrictedDialogIntent(Context context, EnforcedAdmin enforcedAdmin) {
+ final Intent intent = RestrictedLockUtils
+ .getShowAdminSupportDetailsIntent(context, enforcedAdmin);
+ int targetUserId = mUserId;
+ if (enforcedAdmin.user != null && RestrictedLockUtils
+ .isCurrentUserOrProfile(context, enforcedAdmin.user.getIdentifier())) {
+ targetUserId = enforcedAdmin.user.getIdentifier();
+ }
+ intent.putExtra(DevicePolicyManager.EXTRA_RESTRICTION, enforcedAdmin.enforcedRestriction);
+ intent.putExtra(Intent.EXTRA_USER_ID, targetUserId);
+ return intent;
+ }
+
+ private Intent getSettingsPageIntent(String className, Bundle extras) {
final Intent intent = new Intent();
intent.setClassName(SETTINGS_PACKAGE_NAME, className);
if (!extras.isEmpty()) {
@@ -59,7 +109,7 @@ public class BiometricNavigationUtils {
intent.putExtra(Intent.EXTRA_USER_ID, mUserId);
intent.putExtra(SettingsBaseActivity.EXTRA_PAGE_TRANSITION_TYPE,
SettingsTransitionHelper.TransitionType.TRANSITION_SLIDE);
- context.startActivity(intent);
- return true;
+
+ return intent;
}
}
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollSidecar.java b/src/com/android/settings/biometrics/face/FaceEnrollSidecar.java
index 6d2c301a71f..de713dd3386 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollSidecar.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollSidecar.java
@@ -19,9 +19,7 @@ package com.android.settings.biometrics.face;
import android.app.Activity;
import android.app.settings.SettingsEnums;
import android.hardware.face.FaceManager;
-import android.os.UserHandle;
-import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollSidecar;
import java.util.Arrays;
@@ -33,7 +31,7 @@ public class FaceEnrollSidecar extends BiometricEnrollSidecar {
private final int[] mDisabledFeatures;
- private FaceManager mFaceManager;
+ private FaceUpdater mFaceUpdater;
public FaceEnrollSidecar(int[] disabledFeatures) {
mDisabledFeatures = Arrays.copyOf(disabledFeatures, disabledFeatures.length);
@@ -42,13 +40,13 @@ public class FaceEnrollSidecar extends BiometricEnrollSidecar {
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
- mFaceManager = Utils.getFaceManagerOrNull(activity);
+ mFaceUpdater = new FaceUpdater(activity);
}
@Override
public void startEnrollment() {
super.startEnrollment();
- mFaceManager.enroll(mUserId, mToken, mEnrollmentCancel,
+ mFaceUpdater.enroll(mUserId, mToken, mEnrollmentCancel,
mEnrollmentCallback, mDisabledFeatures);
}
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java
index 616b736b8d6..7db59584899 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsRemoveButtonPreferenceController.java
@@ -103,6 +103,7 @@ public class FaceSettingsRemoveButtonPreferenceController extends BasePreference
private final MetricsFeatureProvider mMetricsFeatureProvider;
private final Context mContext;
private final FaceManager mFaceManager;
+ private final FaceUpdater mFaceUpdater;
private final FaceManager.RemovalCallback mRemovalCallback = new FaceManager.RemovalCallback() {
@Override
public void onRemovalError(Face face, int errMsgId, CharSequence errString) {
@@ -144,7 +145,7 @@ public class FaceSettingsRemoveButtonPreferenceController extends BasePreference
}
// Remove the first/only face
- mFaceManager.remove(faces.get(0), mUserId, mRemovalCallback);
+ mFaceUpdater.remove(faces.get(0), mUserId, mRemovalCallback);
} else {
mButton.setEnabled(true);
mRemoving = false;
@@ -157,6 +158,7 @@ public class FaceSettingsRemoveButtonPreferenceController extends BasePreference
mContext = context;
mFaceManager = context.getSystemService(FaceManager.class);
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
+ mFaceUpdater = new FaceUpdater(context, mFaceManager);
}
public FaceSettingsRemoveButtonPreferenceController(Context context) {
diff --git a/src/com/android/settings/biometrics/face/FaceUpdater.java b/src/com/android/settings/biometrics/face/FaceUpdater.java
new file mode 100644
index 00000000000..bb77caefb27
--- /dev/null
+++ b/src/com/android/settings/biometrics/face/FaceUpdater.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.biometrics.face;
+
+import android.content.Context;
+import android.hardware.face.Face;
+import android.hardware.face.FaceEnrollCell;
+import android.hardware.face.FaceManager;
+import android.os.CancellationSignal;
+import android.view.Surface;
+
+import androidx.annotation.Nullable;
+
+import com.android.settings.Utils;
+import com.android.settings.safetycenter.BiometricsSafetySource;
+
+/**
+ * Responsible for making {@link FaceManager#enroll} and {@link FaceManager#remove} calls and thus
+ * updating the face setting.
+ */
+public class FaceUpdater {
+
+ private final Context mContext;
+ private final FaceManager mFaceManager;
+
+ public FaceUpdater(Context context) {
+ mContext = context;
+ mFaceManager = Utils.getFaceManagerOrNull(context);
+ }
+
+ public FaceUpdater(Context context, FaceManager faceManager) {
+ mContext = context;
+ mFaceManager = faceManager;
+ }
+
+ /** Wrapper around the {@link FaceManager#enroll} method. */
+ public void enroll(int userId, byte[] hardwareAuthToken, CancellationSignal cancel,
+ FaceManager.EnrollmentCallback callback, int[] disabledFeatures) {
+ mFaceManager.enroll(userId, hardwareAuthToken, cancel,
+ new NotifyingEnrollmentCallback(mContext, callback), disabledFeatures);
+ }
+
+ /** Wrapper around the {@link FaceManager#enroll} method. */
+ public void enroll(int userId, byte[] hardwareAuthToken, CancellationSignal cancel,
+ FaceManager.EnrollmentCallback callback, int[] disabledFeatures,
+ @Nullable Surface previewSurface, boolean debugConsent) {
+ mFaceManager.enroll(userId, hardwareAuthToken, cancel,
+ new NotifyingEnrollmentCallback(mContext, callback), disabledFeatures,
+ previewSurface, debugConsent);
+ }
+
+ /** Wrapper around the {@link FaceManager#remove} method. */
+ public void remove(Face face, int userId, FaceManager.RemovalCallback callback) {
+ mFaceManager.remove(face, userId, new NotifyingRemovalCallback(mContext, callback));
+ }
+
+ /**
+ * Decorator of the {@link FaceManager.EnrollmentCallback} class that notifies other
+ * interested parties that a face setting has changed.
+ */
+ private static class NotifyingEnrollmentCallback
+ extends FaceManager.EnrollmentCallback {
+
+ private final Context mContext;
+ private final FaceManager.EnrollmentCallback mCallback;
+
+ NotifyingEnrollmentCallback(Context context,
+ FaceManager.EnrollmentCallback callback) {
+ mContext = context;
+ mCallback = callback;
+ }
+
+ @Override
+ public void onEnrollmentError(int errMsgId, CharSequence errString) {
+ mCallback.onEnrollmentError(errMsgId, errString);
+ }
+
+ @Override
+ public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
+ mCallback.onEnrollmentHelp(helpMsgId, helpString);
+ }
+
+ @Override
+ public void onEnrollmentFrame(int helpCode, @Nullable CharSequence helpMessage,
+ @Nullable FaceEnrollCell cell, int stage, float pan, float tilt, float distance) {
+ mCallback.onEnrollmentFrame(helpCode, helpMessage, cell, stage, pan, tilt, distance);
+ }
+
+ @Override
+ public void onEnrollmentProgress(int remaining) {
+ mCallback.onEnrollmentProgress(remaining);
+ if (remaining == 0) {
+ BiometricsSafetySource.sendSafetyData(mContext); // biometrics data changed
+ }
+ }
+ }
+
+ /**
+ * Decorator of the {@link FaceManager.RemovalCallback} class that notifies other
+ * interested parties that a face setting has changed.
+ */
+ private static class NotifyingRemovalCallback extends FaceManager.RemovalCallback {
+
+ private final Context mContext;
+ private final FaceManager.RemovalCallback mCallback;
+
+ NotifyingRemovalCallback(Context context, FaceManager.RemovalCallback callback) {
+ mContext = context;
+ mCallback = callback;
+ }
+
+ @Override
+ public void onRemovalError(Face fp, int errMsgId, CharSequence errString) {
+ mCallback.onRemovalError(fp, errMsgId, errString);
+ }
+
+ @Override
+ public void onRemovalSucceeded(@Nullable Face fp, int remaining) {
+ mCallback.onRemovalSucceeded(fp, remaining);
+ BiometricsSafetySource.sendSafetyData(mContext); // biometrics data changed
+ }
+ }
+}
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java
index 40348d47a71..d8ecd206bd3 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java
@@ -22,7 +22,6 @@ import android.hardware.fingerprint.FingerprintManager;
import android.util.Log;
import com.android.settings.R;
-import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollSidecar;
/**
@@ -31,13 +30,13 @@ import com.android.settings.biometrics.BiometricEnrollSidecar;
public class FingerprintEnrollSidecar extends BiometricEnrollSidecar {
private static final String TAG = "FingerprintEnrollSidecar";
- private FingerprintManager mFingerprintManager;
+ private FingerprintUpdater mFingerprintUpdater;
private @FingerprintManager.EnrollReason int mEnrollReason;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
- mFingerprintManager = Utils.getFingerprintManagerOrNull(activity);
+ mFingerprintUpdater = new FingerprintUpdater(activity);
}
@Override
@@ -51,7 +50,7 @@ public class FingerprintEnrollSidecar extends BiometricEnrollSidecar {
return;
}
- mFingerprintManager.enroll(mToken, mEnrollmentCancel, mUserId, mEnrollmentCallback,
+ mFingerprintUpdater.enroll(mToken, mEnrollmentCancel, mUserId, mEnrollmentCallback,
mEnrollReason);
}
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintRemoveSidecar.java b/src/com/android/settings/biometrics/fingerprint/FingerprintRemoveSidecar.java
index b356103f83f..134462d10c1 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintRemoveSidecar.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintRemoveSidecar.java
@@ -21,7 +21,6 @@ import android.app.settings.SettingsEnums;
import android.hardware.fingerprint.Fingerprint;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
-import android.os.UserHandle;
import android.util.Log;
import com.android.settings.core.InstrumentedFragment;
@@ -38,7 +37,7 @@ public class FingerprintRemoveSidecar extends InstrumentedFragment {
private Listener mListener;
private Fingerprint mFingerprintRemoving;
private Queue