Merge "Import translations. DO NOT MERGE ANYWHERE" into udc-qpr-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 2c3e7f3..185d21e 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -2397,6 +2397,7 @@
             <intent-filter android:priority="1">
                 <action android:name="android.app.action.CONFIRM_DEVICE_CREDENTIAL" />
                 <action android:name="android.app.action.CONFIRM_FRP_CREDENTIAL" />
+                <action android:name="android.app.action.PREPARE_REPAIR_MODE_DEVICE_CREDENTIAL" />
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
         </activity>
diff --git a/res/values-bn/arrays.xml b/res/values-bn/arrays.xml
index ead6ea6..d977a18 100644
--- a/res/values-bn/arrays.xml
+++ b/res/values-bn/arrays.xml
@@ -121,7 +121,7 @@
   <string-array name="wifi_proxy_settings">
     <item msgid="4669222334822978847">"কোনও কিছুই নয়"</item>
     <item msgid="6242198071587397280">"ম্যানুয়াল"</item>
-    <item msgid="464383874780058242">"প্রক্সি স্বতঃ-কনফিগারেশন"</item>
+    <item msgid="464383874780058242">"প্রক্সি অটো-কনফিগারেশন"</item>
   </string-array>
   <string-array name="apn_auth_entries">
     <item msgid="2900892411844440682">"কোনো কিছুই নয়"</item>
diff --git a/res/values-ca/arrays.xml b/res/values-ca/arrays.xml
index 5318c72..3dfd06f 100644
--- a/res/values-ca/arrays.xml
+++ b/res/values-ca/arrays.xml
@@ -121,7 +121,7 @@
   <string-array name="wifi_proxy_settings">
     <item msgid="4669222334822978847">"Cap"</item>
     <item msgid="6242198071587397280">"Manual"</item>
-    <item msgid="464383874780058242">"Serv. inter. autoconfig."</item>
+    <item msgid="464383874780058242">"Configuració automàtica"</item>
   </string-array>
   <string-array name="apn_auth_entries">
     <item msgid="2900892411844440682">"Cap"</item>
diff --git a/res/values-el/arrays.xml b/res/values-el/arrays.xml
index f3f3e13..2884bf0 100644
--- a/res/values-el/arrays.xml
+++ b/res/values-el/arrays.xml
@@ -121,7 +121,7 @@
   <string-array name="wifi_proxy_settings">
     <item msgid="4669222334822978847">"Κανένας"</item>
     <item msgid="6242198071587397280">"Μη αυτόματος"</item>
-    <item msgid="464383874780058242">"Αυτ. διαμ.διακομ.μεσολ."</item>
+    <item msgid="464383874780058242">"Αυτόματη διαμόρφωση"</item>
   </string-array>
   <string-array name="apn_auth_entries">
     <item msgid="2900892411844440682">"Κανένας"</item>
diff --git a/res/values-hu/arrays.xml b/res/values-hu/arrays.xml
index 787630e..5651324 100644
--- a/res/values-hu/arrays.xml
+++ b/res/values-hu/arrays.xml
@@ -404,7 +404,7 @@
     <item msgid="2047166446768045816">"Kezelje nem forgalomkorlátosként"</item>
   </string-array>
   <string-array name="wifi_privacy_entries">
-    <item msgid="3485945604919292489">"Véletlenszerű MAC-cím használata (alapértelmezett)"</item>
+    <item msgid="3485945604919292489">"Véletlenszerű MAC-cím (alapért.)"</item>
     <item msgid="741680937828608749">"Az eszköz MAC-címének használata"</item>
   </string-array>
   <string-array name="wifi_hidden_entries">
diff --git a/res/values-km/arrays.xml b/res/values-km/arrays.xml
index 5923c84..e460e2f 100644
--- a/res/values-km/arrays.xml
+++ b/res/values-km/arrays.xml
@@ -120,7 +120,7 @@
   </string-array>
   <string-array name="wifi_proxy_settings">
     <item msgid="4669222334822978847">"គ្មាន"</item>
-    <item msgid="6242198071587397280">"ដោយ​ដៃ"</item>
+    <item msgid="6242198071587397280">"ដោយផ្ទាល់​ដៃ"</item>
     <item msgid="464383874780058242">"រចនាសម្ព័ន្ធប្រូកស៊ីស្វ័យប្រវត្តិ"</item>
   </string-array>
   <string-array name="apn_auth_entries">
diff --git a/res/values-ko/arrays.xml b/res/values-ko/arrays.xml
index cf1f77d..e8bd555 100644
--- a/res/values-ko/arrays.xml
+++ b/res/values-ko/arrays.xml
@@ -400,7 +400,7 @@
   </string-array>
   <string-array name="wifi_metered_entries">
     <item msgid="3237321077949659241">"자동 감지"</item>
-    <item msgid="3779092145391320375">"종량제 Wi-Fi로 취급"</item>
+    <item msgid="3779092145391320375">"제한이 있는 Wi-Fi로 취급"</item>
     <item msgid="2047166446768045816">"무제한 Wi-Fi로 취급"</item>
   </string-array>
   <string-array name="wifi_privacy_entries">
diff --git a/res/values-lt/arrays.xml b/res/values-lt/arrays.xml
index 7315f49..9c66346 100644
--- a/res/values-lt/arrays.xml
+++ b/res/values-lt/arrays.xml
@@ -404,7 +404,7 @@
     <item msgid="2047166446768045816">"Laikyti nematuojamu"</item>
   </string-array>
   <string-array name="wifi_privacy_entries">
-    <item msgid="3485945604919292489">"Naudoti atsitiktine tvarka parinktą MAC (numatyta)"</item>
+    <item msgid="3485945604919292489">"Atsitiktinai parinktas MAC (numatyta)"</item>
     <item msgid="741680937828608749">"Naudoti įrenginio MAC"</item>
   </string-array>
   <string-array name="wifi_hidden_entries">
diff --git a/res/values-pl/arrays.xml b/res/values-pl/arrays.xml
index 0086582..a51b5c4 100644
--- a/res/values-pl/arrays.xml
+++ b/res/values-pl/arrays.xml
@@ -404,7 +404,7 @@
     <item msgid="2047166446768045816">"Traktuj jako sieć bez pomiaru użycia danych"</item>
   </string-array>
   <string-array name="wifi_privacy_entries">
-    <item msgid="3485945604919292489">"Używaj randomizowanego adresu MAC (domyślnie)"</item>
+    <item msgid="3485945604919292489">"Randomizowany MAC (domyślnie)"</item>
     <item msgid="741680937828608749">"Używaj adresu MAC urządzenia"</item>
   </string-array>
   <string-array name="wifi_hidden_entries">
diff --git a/res/values-ro/arrays.xml b/res/values-ro/arrays.xml
index 62384de..02b5f3d 100644
--- a/res/values-ro/arrays.xml
+++ b/res/values-ro/arrays.xml
@@ -119,7 +119,7 @@
     <item msgid="6215795691318745695">"Static"</item>
   </string-array>
   <string-array name="wifi_proxy_settings">
-    <item msgid="4669222334822978847">"Niciuna"</item>
+    <item msgid="4669222334822978847">"Fără"</item>
     <item msgid="6242198071587397280">"Manual"</item>
     <item msgid="464383874780058242">"Configurare automată proxy"</item>
   </string-array>
diff --git a/res/values-sk/arrays.xml b/res/values-sk/arrays.xml
index ab20e55..b867c38 100644
--- a/res/values-sk/arrays.xml
+++ b/res/values-sk/arrays.xml
@@ -404,7 +404,7 @@
     <item msgid="2047166446768045816">"Považovať za nemeranú sieť"</item>
   </string-array>
   <string-array name="wifi_privacy_entries">
-    <item msgid="3485945604919292489">"Používať náhodnú adresu MAC (predvolené)"</item>
+    <item msgid="3485945604919292489">"Náhodná adresa MAC (predvol.)"</item>
     <item msgid="741680937828608749">"Používať adresu MAC zariadenia"</item>
   </string-array>
   <string-array name="wifi_hidden_entries">
diff --git a/res/values-th/arrays.xml b/res/values-th/arrays.xml
index 8ecdc84..dd07c77 100644
--- a/res/values-th/arrays.xml
+++ b/res/values-th/arrays.xml
@@ -404,7 +404,7 @@
     <item msgid="2047166446768045816">"ถือว่าไม่มีการจำกัดปริมาณอินเทอร์เน็ต"</item>
   </string-array>
   <string-array name="wifi_privacy_entries">
-    <item msgid="3485945604919292489">"ใช้ MAC แบบสุ่ม (ค่าเริ่มต้น)"</item>
+    <item msgid="3485945604919292489">"ใช้ที่อยู่ MAC แบบสุ่ม (ค่าเริ่มต้น)"</item>
     <item msgid="741680937828608749">"ใช้ที่อยู่ MAC ของอุปกรณ์"</item>
   </string-array>
   <string-array name="wifi_hidden_entries">
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1c08b7f..bd4e018 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2648,6 +2648,8 @@
     <string name="model_info">Model</string>
     <!-- Label for device's hardware revision value [CHAR LIMIT=40] -->
     <string name="hardware_revision">Hardware version</string>
+    <!-- Label for device's manufactured year value [CHAR LIMIT=40] -->
+    <string name="manufactured_year">Manufactured year</string>
     <!-- About phone screen, fcc equipment id label  [CHAR LIMIT=40] -->
     <string name="fcc_equipment_id">Equipment ID</string>
     <!-- About phone screen,  setting option name  [CHAR LIMIT=40] -->
diff --git a/res/xml/hardware_info.xml b/res/xml/hardware_info.xml
index 641f707..e086a48 100644
--- a/res/xml/hardware_info.xml
+++ b/res/xml/hardware_info.xml
@@ -48,4 +48,13 @@
         settings:controller="com.android.settings.deviceinfo.hardwareinfo.HardwareRevisionPreferenceController"
         settings:enableCopying="true"/>
 
+    <!-- Manufactured year -->
+    <Preference
+        android:key="hardware_info_manufactured_year"
+        android:title="@string/manufactured_year"
+        android:summary="@string/summary_placeholder"
+        android:selectable="false"
+        settings:controller="com.android.settings.deviceinfo.hardwareinfo.ManufacturedYearPreferenceController"
+        settings:enableCopying="true"/>
+
 </PreferenceScreen>
diff --git a/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminAdd.java b/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminAdd.java
index 1d45c51..c43bde6 100644
--- a/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminAdd.java
+++ b/src/com/android/settings/applications/specialaccess/deviceadmin/DeviceAdminAdd.java
@@ -66,6 +66,7 @@
 import android.util.EventLog;
 import android.util.Log;
 import android.view.Display;
+import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -155,12 +156,12 @@
 
         mHandler = new Handler(getMainLooper());
 
-        mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
-        mAppOps = (AppOpsManager)getSystemService(Context.APP_OPS_SERVICE);
+        mDPM = getSystemService(DevicePolicyManager.class);
+        mAppOps = getSystemService(AppOpsManager.class);
         mLayoutInflaternflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         PackageManager packageManager = getPackageManager();
 
-        if ((getIntent().getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
+        if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
             Log.w(TAG, "Cannot start ADD_DEVICE_ADMIN as a new task");
             finish();
             return;
@@ -170,7 +171,7 @@
                 EXTRA_CALLED_FROM_SUPPORT_DIALOG, false);
 
         String action = getIntent().getAction();
-        ComponentName who = (ComponentName)getIntent().getParcelableExtra(
+        ComponentName who = (ComponentName) getIntent().getParcelableExtra(
                 DevicePolicyManager.EXTRA_DEVICE_ADMIN);
         if (who == null) {
             String packageName = getIntent().getStringExtra(EXTRA_DEVICE_ADMIN_PACKAGE_NAME);
@@ -226,7 +227,7 @@
                     PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS);
             int count = avail == null ? 0 : avail.size();
             boolean found = false;
-            for (int i=0; i<count; i++) {
+            for (int i = 0; i < count; i++) {
                 ResolveInfo ri = avail.get(i);
                 if (ai.packageName.equals(ri.activityInfo.packageName)
                         && ai.name.equals(ri.activityInfo.name)) {
@@ -345,21 +346,21 @@
             mAdminWarning.setText(
                     mDPM.getResources().getString(NEW_DEVICE_ADMIN_WARNING_SIMPLIFIED, () ->
                             getString(R.string.device_admin_warning_simplified,
-                            profileOwnerName), profileOwnerName));
+                                    profileOwnerName), profileOwnerName));
             return;
         }
         setContentView(R.layout.device_admin_add);
 
-        mAdminIcon = (ImageView)findViewById(R.id.admin_icon);
-        mAdminName = (TextView)findViewById(R.id.admin_name);
-        mAdminDescription = (TextView)findViewById(R.id.admin_description);
+        mAdminIcon = (ImageView) findViewById(R.id.admin_icon);
+        mAdminName = (TextView) findViewById(R.id.admin_name);
+        mAdminDescription = (TextView) findViewById(R.id.admin_description);
         mProfileOwnerWarning = (TextView) findViewById(R.id.profile_owner_warning);
 
         mProfileOwnerWarning.setText(
                 mDPM.getResources().getString(SET_PROFILE_OWNER_POSTSETUP_WARNING,
                         () -> getString(R.string.adding_profile_owner_warning)));
 
-        mAddMsg = (TextView)findViewById(R.id.add_msg);
+        mAddMsg = (TextView) findViewById(R.id.add_msg);
         mAddMsgExpander = (ImageView) findViewById(R.id.add_msg_expander);
         final View.OnClickListener onClickListener = new View.OnClickListener() {
             @Override
@@ -380,7 +381,7 @@
                         boolean hideMsgExpander = mAddMsg.getLineCount() <= maxLines;
                         mAddMsgExpander.setVisibility(hideMsgExpander ? View.GONE : View.VISIBLE);
                         if (hideMsgExpander) {
-                            ((View)mAddMsgExpander.getParent()).invalidate();
+                            ((View) mAddMsgExpander.getParent()).invalidate();
                         }
                         mAddMsg.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                     }
@@ -398,7 +399,7 @@
         mCancelButton.setOnClickListener(new View.OnClickListener() {
             public void onClick(View v) {
                 EventLog.writeEvent(EventLogTags.EXP_DET_DEVICE_ADMIN_DECLINED_BY_USER,
-                    mDeviceAdmin.getActivityInfo().applicationInfo.uid);
+                        mDeviceAdmin.getActivityInfo().applicationInfo.uid);
                 finish();
             }
         });
@@ -420,58 +421,64 @@
 
         final View restrictedAction = findViewById(R.id.restricted_action);
         restrictedAction.setFilterTouchesWhenObscured(true);
-        restrictedAction.setOnClickListener(new View.OnClickListener() {
-            public void onClick(View v) {
-                if (!mActionButton.isEnabled()) {
-                    showPolicyTransparencyDialogIfRequired();
-                    return;
-                }
-                if (mAdding) {
-                    addAndFinish();
-                } else if (isManagedProfile(mDeviceAdmin)
-                        && mDeviceAdmin.getComponent().equals(mDPM.getProfileOwner())) {
-                    final int userId = UserHandle.myUserId();
-                    UserDialogs.createRemoveDialog(DeviceAdminAdd.this, userId,
-                            new DialogInterface.OnClickListener() {
-                                @Override
-                                public void onClick(DialogInterface dialog, int which) {
-                                    UserManager um = UserManager.get(DeviceAdminAdd.this);
-                                    um.removeUser(userId);
-                                    finish();
-                                }
-                            }
-                    ).show();
-                } else if (mUninstalling) {
-                    mDPM.uninstallPackageWithActiveAdmins(mDeviceAdmin.getPackageName());
-                    finish();
-                } else if (!mWaitingForRemoveMsg) {
-                    try {
-                        // Don't allow the admin to put a dialog up in front
-                        // of us while we interact with the user.
-                        ActivityManager.getService().stopAppSwitches();
-                    } catch (RemoteException e) {
-                    }
-                    mWaitingForRemoveMsg = true;
-                    mDPM.getRemoveWarning(mDeviceAdmin.getComponent(),
-                            new RemoteCallback(new RemoteCallback.OnResultListener() {
-                                @Override
-                                public void onResult(Bundle result) {
-                                    CharSequence msg = result != null
-                                            ? result.getCharSequence(
-                                            DeviceAdminReceiver.EXTRA_DISABLE_WARNING)
-                                            : null;
-                                    continueRemoveAction(msg);
-                                }
-                            }, mHandler));
-                    // Don't want to wait too long.
-                    getWindow().getDecorView().getHandler().postDelayed(new Runnable() {
-                        @Override public void run() {
-                            continueRemoveAction(null);
-                        }
-                    }, 2*1000);
-                }
+
+        final View.OnClickListener restrictedActionClickListener = v -> {
+            if (!mActionButton.isEnabled()) {
+                showPolicyTransparencyDialogIfRequired();
+                return;
             }
+            if (mAdding) {
+                addAndFinish();
+            } else if (isManagedProfile(mDeviceAdmin)
+                    && mDeviceAdmin.getComponent().equals(mDPM.getProfileOwner())) {
+                final int userId = UserHandle.myUserId();
+                UserDialogs.createRemoveDialog(DeviceAdminAdd.this, userId,
+                        new DialogInterface.OnClickListener() {
+                            @Override
+                            public void onClick(DialogInterface dialog, int which) {
+                                UserManager um = UserManager.get(DeviceAdminAdd.this);
+                                um.removeUser(userId);
+                                finish();
+                            }
+                        }
+                ).show();
+            } else if (mUninstalling) {
+                mDPM.uninstallPackageWithActiveAdmins(mDeviceAdmin.getPackageName());
+                finish();
+            } else if (!mWaitingForRemoveMsg) {
+                try {
+                    // Don't allow the admin to put a dialog up in front
+                    // of us while we interact with the user.
+                    ActivityManager.getService().stopAppSwitches();
+                } catch (RemoteException e) {
+                }
+                mWaitingForRemoveMsg = true;
+                mDPM.getRemoveWarning(mDeviceAdmin.getComponent(),
+                        new RemoteCallback(new RemoteCallback.OnResultListener() {
+                            @Override
+                            public void onResult(Bundle result) {
+                                CharSequence msg = result != null
+                                        ? result.getCharSequence(
+                                        DeviceAdminReceiver.EXTRA_DISABLE_WARNING)
+                                        : null;
+                                continueRemoveAction(msg);
+                            }
+                        }, mHandler));
+                // Don't want to wait too long.
+                getWindow().getDecorView().getHandler().postDelayed(
+                        () -> continueRemoveAction(null), 2 * 1000);
+            }
+        };
+        restrictedAction.setOnKeyListener((view, keyCode, keyEvent) -> {
+            if ((keyEvent.getFlags() & KeyEvent.FLAG_FROM_SYSTEM) == 0) {
+                Log.e(TAG, "Can not activate device-admin with KeyEvent from non-system app.");
+                // Consume event to suppress click.
+                return true;
+            }
+            // Fallback to view click handler.
+            return false;
         });
+        restrictedAction.setOnClickListener(restrictedActionClickListener);
     }
 
     /**
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
index bff998a..bea0c33 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
@@ -120,6 +120,8 @@
     protected void onCreate(Bundle savedInstanceState) {
         mFaceManager = getFaceManager();
 
+        super.onCreate(savedInstanceState);
+
         if (savedInstanceState == null
                 && !WizardManagerHelper.isAnySetupWizard(getIntent())
                 && !getIntent().getBooleanExtra(EXTRA_FROM_SETTINGS_SUMMARY, false)
@@ -130,8 +132,6 @@
             finish();
         }
 
-        super.onCreate(savedInstanceState);
-
         // Wait super::onCreated() then return because SuperNotCalledExceptio will be thrown
         // if we don't wait for it.
         if (isFinishing()) {
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintAuthenticateSidecar.java b/src/com/android/settings/biometrics/fingerprint/FingerprintAuthenticateSidecar.java
index 4264056..f3c8aba 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintAuthenticateSidecar.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintAuthenticateSidecar.java
@@ -21,6 +21,7 @@
 import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
 import android.os.CancellationSignal;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.core.InstrumentedFragment;
 
 /**
@@ -80,7 +81,6 @@
 
                 @Override
                 public void onAuthenticationError(int errMsgId, CharSequence errString) {
-                    mCancellationSignal = null;
                     if (mListener != null) {
                         mListener.onAuthenticationError(errMsgId, errString);
                     } else {
@@ -108,10 +108,12 @@
     }
 
     public void stopAuthentication() {
-        if (mCancellationSignal != null && !mCancellationSignal.isCanceled()) {
+        if (mCancellationSignal != null) {
+            // This will automatically check if the cancel has been sent and if so
+            // it won't send it again.
             mCancellationSignal.cancel();
+            mCancellationSignal = null;
         }
-        mCancellationSignal = null;
     }
 
     public void setListener(Listener listener) {
@@ -129,4 +131,9 @@
         }
         mListener = listener;
     }
+
+    @VisibleForTesting
+    boolean isCancelled() {
+        return mCancellationSignal == null || mCancellationSignal.isCanceled();
+    }
 }
\ No newline at end of file
diff --git a/src/com/android/settings/deviceinfo/hardwareinfo/HardwareInfoFeatureProvider.kt b/src/com/android/settings/deviceinfo/hardwareinfo/HardwareInfoFeatureProvider.kt
new file mode 100644
index 0000000..400ece9
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/hardwareinfo/HardwareInfoFeatureProvider.kt
@@ -0,0 +1,26 @@
+/*
+ * 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.deviceinfo.hardwareinfo
+
+/**
+ * Feature provider for hardware info
+ */
+interface HardwareInfoFeatureProvider {
+    /**
+     * Returns the manufactured year
+     */
+    val manufacturedYear: String?
+}
\ No newline at end of file
diff --git a/src/com/android/settings/deviceinfo/hardwareinfo/HardwareInfoFeatureProviderImpl.kt b/src/com/android/settings/deviceinfo/hardwareinfo/HardwareInfoFeatureProviderImpl.kt
new file mode 100644
index 0000000..54a112b
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/hardwareinfo/HardwareInfoFeatureProviderImpl.kt
@@ -0,0 +1,24 @@
+/*
+ * 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.deviceinfo.hardwareinfo
+
+/**
+ * Feature provider for hardware info
+ */
+object HardwareInfoFeatureProviderImpl : HardwareInfoFeatureProvider {
+    override val manufacturedYear: String?
+        get() = null
+}
\ No newline at end of file
diff --git a/src/com/android/settings/deviceinfo/hardwareinfo/ManufacturedYearPreferenceController.kt b/src/com/android/settings/deviceinfo/hardwareinfo/ManufacturedYearPreferenceController.kt
new file mode 100644
index 0000000..0b0eeb7
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/hardwareinfo/ManufacturedYearPreferenceController.kt
@@ -0,0 +1,32 @@
+/*
+ * 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.deviceinfo.hardwareinfo
+
+import android.content.Context
+import com.android.settings.core.BasePreferenceController
+import com.android.settings.overlay.FeatureFactory
+
+/** Preference controller for Manufactured Year. */
+class ManufacturedYearPreferenceController(context: Context, preferenceKey: String) :
+    BasePreferenceController(context, preferenceKey) {
+    private val year: String? =
+        FeatureFactory.getFactory(context).hardwareInfoFeatureProvider.manufacturedYear
+
+    override fun getAvailabilityStatus(): Int =
+        if (!year.isNullOrEmpty()) AVAILABLE else UNSUPPORTED_ON_DEVICE
+
+    override fun getSummary(): CharSequence = year ?: ""
+}
\ No newline at end of file
diff --git a/src/com/android/settings/network/telephony/MmsMessagePreferenceController.java b/src/com/android/settings/network/telephony/MmsMessagePreferenceController.java
index 5908ecd..54a106a 100644
--- a/src/com/android/settings/network/telephony/MmsMessagePreferenceController.java
+++ b/src/com/android/settings/network/telephony/MmsMessagePreferenceController.java
@@ -31,21 +31,19 @@
 import com.android.settingslib.core.lifecycle.events.OnStop;
 
 /**
- * Preference controller for "Mobile data"
+ * Preference controller for "MMS messages"
  */
 public class MmsMessagePreferenceController extends TelephonyTogglePreferenceController implements
         LifecycleObserver, OnStart, OnStop {
     private TelephonyManager mTelephonyManager;
-    private SubscriptionManager mSubscriptionManager;
     private MobileDataContentObserver mMobileDataContentObserver;
     private PreferenceScreen mScreen;
 
     public MmsMessagePreferenceController(Context context, String key) {
         super(context, key);
-        mSubscriptionManager = context.getSystemService(SubscriptionManager.class);
         mMobileDataContentObserver = new MobileDataContentObserver(
                 new Handler(Looper.getMainLooper()));
-        mMobileDataContentObserver.setOnMobileDataChangedListener(()->refreshPreference());
+        mMobileDataContentObserver.setOnMobileDataChangedListener(() -> refreshPreference());
     }
 
     @Override
@@ -88,12 +86,15 @@
 
     @Override
     public boolean setChecked(boolean isChecked) {
+        if (mTelephonyManager == null) {
+            return false;
+        }
         mTelephonyManager.setMobileDataPolicyEnabled(
                 TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED, isChecked);
-        return isChecked == mTelephonyManager.isMobileDataPolicyEnabled(
-                TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED);
+        return true;
     }
 
+
     @Override
     public boolean isChecked() {
         return mTelephonyManager != null && mTelephonyManager.isDataEnabledForApn(
diff --git a/src/com/android/settings/overlay/FeatureFactory.java b/src/com/android/settings/overlay/FeatureFactory.java
index 5cbdb25..249caa1 100644
--- a/src/com/android/settings/overlay/FeatureFactory.java
+++ b/src/com/android/settings/overlay/FeatureFactory.java
@@ -33,6 +33,7 @@
 import com.android.settings.bluetooth.BluetoothFeatureProvider;
 import com.android.settings.dashboard.DashboardFeatureProvider;
 import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
+import com.android.settings.deviceinfo.hardwareinfo.HardwareInfoFeatureProvider;
 import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
 import com.android.settings.fuelgauge.BatterySettingsFeatureProvider;
 import com.android.settings.fuelgauge.BatteryStatusFeatureProvider;
@@ -110,6 +111,11 @@
      */
     public abstract SuggestionFeatureProvider getSuggestionFeatureProvider();
 
+    /**
+     * Retrieves implementation for Hardware Info feature.
+     */
+    public abstract HardwareInfoFeatureProvider getHardwareInfoFeatureProvider();
+
     public abstract SupportFeatureProvider getSupportFeatureProvider(Context context);
 
     public abstract MetricsFeatureProvider getMetricsFeatureProvider();
diff --git a/src/com/android/settings/overlay/FeatureFactoryImpl.java b/src/com/android/settings/overlay/FeatureFactoryImpl.java
index ba16377..60adf95 100644
--- a/src/com/android/settings/overlay/FeatureFactoryImpl.java
+++ b/src/com/android/settings/overlay/FeatureFactoryImpl.java
@@ -47,6 +47,8 @@
 import com.android.settings.dashboard.DashboardFeatureProviderImpl;
 import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
 import com.android.settings.dashboard.suggestions.SuggestionFeatureProviderImpl;
+import com.android.settings.deviceinfo.hardwareinfo.HardwareInfoFeatureProvider;
+import com.android.settings.deviceinfo.hardwareinfo.HardwareInfoFeatureProviderImpl;
 import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
 import com.android.settings.enterprise.EnterprisePrivacyFeatureProviderImpl;
 import com.android.settings.fuelgauge.BatterySettingsFeatureProvider;
@@ -119,6 +121,11 @@
     private KeyboardSettingsFeatureProvider mKeyboardSettingsFeatureProvider;
 
     @Override
+    public HardwareInfoFeatureProvider getHardwareInfoFeatureProvider() {
+        return HardwareInfoFeatureProviderImpl.INSTANCE;
+    }
+
+    @Override
     public SupportFeatureProvider getSupportFeatureProvider(Context context) {
         return null;
     }
diff --git a/src/com/android/settings/password/ChooseLockSettingsHelper.java b/src/com/android/settings/password/ChooseLockSettingsHelper.java
index 216f7db..943a937 100644
--- a/src/com/android/settings/password/ChooseLockSettingsHelper.java
+++ b/src/com/android/settings/password/ChooseLockSettingsHelper.java
@@ -71,6 +71,8 @@
     // Gatekeeper password handle, which can subsequently be used to generate Gatekeeper
     // HardwareAuthToken(s) via LockSettingsService#verifyGatekeeperPasswordHandle
     public static final String EXTRA_KEY_GK_PW_HANDLE = "gk_pw_handle";
+    public static final String EXTRA_KEY_REQUEST_WRITE_REPAIR_MODE_PW =
+            "request_write_repair_mode_pw";
 
     /**
      * When EXTRA_KEY_UNIFICATION_PROFILE_CREDENTIAL and EXTRA_KEY_UNIFICATION_PROFILE_ID are
@@ -152,6 +154,7 @@
         @Nullable private RemoteLockscreenValidationSession mRemoteLockscreenValidationSession;
         @Nullable private ComponentName mRemoteLockscreenValidationServiceComponent;
         private boolean mRequestGatekeeperPasswordHandle;
+        private boolean mRequestWriteRepairModePassword;
         private boolean mTaskOverlay;
 
         public Builder(@NonNull Activity activity) {
@@ -336,6 +339,17 @@
         }
 
         /**
+         * @param requestWriteRepairModePassword Set {@code true} to request that
+         * LockSettingsService writes the password data to the repair mode file after the user
+         * credential is verified successfully.
+         */
+        @NonNull public Builder setRequestWriteRepairModePassword(
+                boolean requestWriteRepairModePassword) {
+            mRequestWriteRepairModePassword = requestWriteRepairModePassword;
+            return this;
+        }
+
+        /**
          * Support of ActivityResultLauncher.
          *
          * Which allowing the launch operation be controlled externally.
@@ -385,7 +399,7 @@
                 mBuilder.mRemoteLockscreenValidationSession,
                 mBuilder.mRemoteLockscreenValidationServiceComponent, mBuilder.mAllowAnyUserId,
                 mBuilder.mForegroundOnly, mBuilder.mRequestGatekeeperPasswordHandle,
-                mBuilder.mTaskOverlay);
+                mBuilder.mRequestWriteRepairModePassword, mBuilder.mTaskOverlay);
     }
 
     private boolean launchConfirmationActivity(int request, @Nullable CharSequence title,
@@ -396,7 +410,7 @@
             @Nullable RemoteLockscreenValidationSession remoteLockscreenValidationSession,
             @Nullable ComponentName remoteLockscreenValidationServiceComponent,
             boolean allowAnyUser, boolean foregroundOnly, boolean requestGatekeeperPasswordHandle,
-            boolean taskOverlay) {
+            boolean requestWriteRepairModePassword, boolean taskOverlay) {
         Optional<Class<?>> activityClass = determineAppropriateActivityClass(
                 returnCredentials, forceVerifyPath, userId, remoteLockscreenValidationSession);
         if (activityClass.isEmpty()) {
@@ -407,7 +421,7 @@
                 returnCredentials, external, forceVerifyPath, userId, alternateButton,
                 checkboxLabel, remoteLockscreenValidation, remoteLockscreenValidationSession,
                 remoteLockscreenValidationServiceComponent, allowAnyUser, foregroundOnly,
-                requestGatekeeperPasswordHandle, taskOverlay);
+                requestGatekeeperPasswordHandle, requestWriteRepairModePassword, taskOverlay);
     }
 
     private boolean launchConfirmationActivity(int request, CharSequence title, CharSequence header,
@@ -418,7 +432,7 @@
             @Nullable RemoteLockscreenValidationSession remoteLockscreenValidationSession,
             @Nullable ComponentName remoteLockscreenValidationServiceComponent,
             boolean allowAnyUser, boolean foregroundOnly, boolean requestGatekeeperPasswordHandle,
-            boolean taskOverlay) {
+            boolean requestWriteRepairModePassword, boolean taskOverlay) {
         final Intent intent = new Intent();
         intent.putExtra(ConfirmDeviceCredentialBaseFragment.TITLE_TEXT, title);
         intent.putExtra(ConfirmDeviceCredentialBaseFragment.HEADER_TEXT, header);
@@ -442,6 +456,8 @@
         intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_ALLOW_ANY_USER, allowAnyUser);
         intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE,
                 requestGatekeeperPasswordHandle);
+        intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_WRITE_REPAIR_MODE_PW,
+                requestWriteRepairModePassword);
 
         intent.setClassName(SETTINGS_PACKAGE_NAME, activityClass.getName());
         intent.putExtra(SettingsBaseActivity.EXTRA_PAGE_TRANSITION_TYPE,
diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
index fabca6b..d409c0f 100644
--- a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
+++ b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
@@ -171,6 +171,9 @@
                 KeyguardManager.ACTION_CONFIRM_REMOTE_DEVICE_CREDENTIAL.equals(intent.getAction());
         mTaskOverlay = isInternalActivity()
                 && intent.getBooleanExtra(KeyguardManager.EXTRA_FORCE_TASK_OVERLAY, false);
+        final boolean prepareRepairMode =
+                KeyguardManager.ACTION_PREPARE_REPAIR_MODE_DEVICE_CREDENTIAL.equals(
+                        intent.getAction());
 
         mUserId = UserHandle.myUserId();
         if (isInternalActivity()) {
@@ -244,6 +247,17 @@
                     .setExternal(true)
                     .show();
             return;
+        } else if (prepareRepairMode) {
+            final ChooseLockSettingsHelper.Builder builder =
+                    new ChooseLockSettingsHelper.Builder(this);
+            launchedCDC = builder.setHeader(mTitle)
+                    .setDescription(mDetails)
+                    .setExternal(true)
+                    .setUserId(mUserId)
+                    .setTaskOverlay(mTaskOverlay)
+                    .setRequestWriteRepairModePassword(true)
+                    .setForceVerifyPath(true)
+                    .show();
         } else if (isEffectiveUserManagedProfile && isInternalActivity()) {
             mCredentialMode = CREDENTIAL_MANAGED;
             if (isBiometricAllowed(effectiveUserId, mUserId)) {
diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java b/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java
index f4cfabc..5a123b8 100644
--- a/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java
+++ b/src/com/android/settings/password/ConfirmDeviceCredentialBaseFragment.java
@@ -105,6 +105,7 @@
     protected final Handler mHandler = new Handler();
     protected boolean mFrp;
     protected boolean mRemoteValidation;
+    protected boolean mRequestWriteRepairModePassword;
     protected CharSequence mAlternateButtonText;
     protected BiometricManager mBiometricManager;
     @Nullable protected RemoteLockscreenValidationSession mRemoteLockscreenValidationSession;
@@ -130,6 +131,8 @@
                 ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, false);
         mForceVerifyPath = intent.getBooleanExtra(
                 ChooseLockSettingsHelper.EXTRA_KEY_FORCE_VERIFY, false);
+        mRequestWriteRepairModePassword = intent.getBooleanExtra(
+                ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_WRITE_REPAIR_MODE_PW, false);
 
         if (intent.getBooleanExtra(IS_REMOTE_LOCKSCREEN_VALIDATION, false)) {
             if (FeatureFlagUtils.isEnabled(getContext(),
diff --git a/src/com/android/settings/password/ConfirmLockPassword.java b/src/com/android/settings/password/ConfirmLockPassword.java
index 03b89f2..1b53506 100644
--- a/src/com/android/settings/password/ConfirmLockPassword.java
+++ b/src/com/android/settings/password/ConfirmLockPassword.java
@@ -496,7 +496,9 @@
                 }
             } else if (mForceVerifyPath)  {
                 if (isInternalActivity()) {
-                    startVerifyPassword(credential, intent, 0 /* flags */);
+                    final int flags = mRequestWriteRepairModePassword
+                            ? LockPatternUtils.VERIFY_FLAG_WRITE_REPAIR_MODE_PW : 0;
+                    startVerifyPassword(credential, intent, flags);
                     return;
                 }
             } else {
diff --git a/src/com/android/settings/password/ConfirmLockPattern.java b/src/com/android/settings/password/ConfirmLockPattern.java
index e99a986..3951bde 100644
--- a/src/com/android/settings/password/ConfirmLockPattern.java
+++ b/src/com/android/settings/password/ConfirmLockPattern.java
@@ -512,7 +512,9 @@
                     }
                 } else if (mForceVerifyPath) {
                     if (isInternalActivity()) {
-                        startVerifyPattern(credential, intent, 0 /* flags */);
+                        final int flags = mRequestWriteRepairModePassword
+                                ? LockPatternUtils.VERIFY_FLAG_WRITE_REPAIR_MODE_PW : 0;
+                        startVerifyPattern(credential, intent, flags);
                         return;
                     }
                 } else {
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index 28e02ec..d9fbc42 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -885,7 +885,6 @@
                 this::startActivityForResult,
                 userIcon,
                 user.name,
-                getString(com.android.settingslib.R.string.profile_info_settings_title),
                 (newUserName, newUserIcon) -> {
                     if (newUserIcon != userIcon) {
                         ThreadUtils.postOnBackgroundThread(() ->
diff --git a/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollIntroductionTest.java b/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollIntroductionTest.java
index c4da133..df15e5c 100644
--- a/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollIntroductionTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/face/FaceEnrollIntroductionTest.java
@@ -40,6 +40,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.hardware.face.Face;
 import android.hardware.face.FaceManager;
 import android.hardware.face.FaceSensorProperties;
@@ -116,6 +117,7 @@
     private FaceEnrollIntroduction mSpyActivity;
     private FakeFeatureFactory mFakeFeatureFactory;
     private ShadowUserManager mUserManager;
+    private Resources mResources;
 
     enum GateKeeperAction {CALL_SUPER, RETURN_BYTE_ARRAY, THROW_CREDENTIAL_NOT_MATCH}
 
@@ -245,6 +247,14 @@
         when(mFaceManager.getEnrolledFaces(anyInt())).thenReturn(faces);
     }
 
+    private void setFaceManagerToHaveWithUserId(int numEnrollments, int userId) {
+        List<Face> faces = new ArrayList<>();
+        for (int i = 0; i < numEnrollments; i++) {
+            faces.add(new Face("Face " + i /* name */, 1 /*faceId */, 1 /* deviceId */));
+        }
+        when(mFaceManager.getEnrolledFaces(userId)).thenReturn(faces);
+    }
+
     @Test
     public void intro_CheckCanEnroll() {
         setFaceManagerToHave(0 /* numEnrollments */);
@@ -546,4 +556,40 @@
         assertThat(mActivity.getPostureCallback()).isNull();
     }
 
+    @Test
+    public void testFaceEnrollIntroduction_maxFacesNotEnrolled_addUserProfile() {
+        // Enroll a face for one user
+        setFaceManagerToHaveWithUserId(1, 0);
+
+        mContext = spy(ApplicationProvider.getApplicationContext());
+        mResources = spy(mContext.getResources());
+        when(mResources.getInteger(R.integer.suw_max_faces_enrollable)).thenReturn(1);
+
+        mController = Robolectric.buildActivity(TestFaceEnrollIntroduction.class, new Intent());
+        mActivity = (TestFaceEnrollIntroduction) mController.get();
+
+        mController.create();
+
+        // The maximum number of faces is already enrolled
+        int result = mActivity.checkMaxEnrolled();
+        assertThat(result).isEqualTo(R.string.face_intro_error_max);
+
+        // Add another user profile
+        mUserManager.addUser(10, "", 0);
+        final Intent intent = new Intent();
+        intent.putExtra(Intent.EXTRA_USER_ID, 10);
+
+        when(mResources.getInteger(R.integer.suw_max_faces_enrollable)).thenReturn(2);
+
+        mController = Robolectric.buildActivity(TestFaceEnrollIntroduction.class, intent);
+        mActivity = (TestFaceEnrollIntroduction) mController.get();
+
+        mController.create();
+
+        // The maximum number of faces hasn't been enrolled, so a new face
+        // can be enrolled for the added user profile
+        result = mActivity.checkMaxEnrolled();
+        assertThat(result).isEqualTo(0);
+    }
+
 }
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsFragmentTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsFragmentTest.java
index 18b05ad..1998d56 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsFragmentTest.java
@@ -44,6 +44,7 @@
 import android.hardware.fingerprint.FingerprintManager;
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
 import android.os.Bundle;
+import android.os.CancellationSignal;
 import android.view.LayoutInflater;
 import android.view.ViewGroup;
 
@@ -68,6 +69,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
@@ -92,6 +94,16 @@
     @Mock
     private FragmentTransaction mFragmentTransaction;
 
+    @Captor
+    private ArgumentCaptor<CancellationSignal> mCancellationSignalArgumentCaptor =
+            ArgumentCaptor.forClass(CancellationSignal.class);
+    @Captor
+    private ArgumentCaptor<FingerprintManager.AuthenticationCallback>
+            mAuthenticationCallbackArgumentCaptor = ArgumentCaptor.forClass(
+            FingerprintManager.AuthenticationCallback.class);
+
+    private FingerprintAuthenticateSidecar mFingerprintAuthenticateSidecar;
+
     @Before
     public void setUp() {
         doReturn(true).when(mFingerprintManager).isHardwareDetected();
@@ -146,6 +158,34 @@
                 false)).isTrue();
     }
 
+    // Test the case when FingerprintAuthenticateSidecar receives an error callback from the
+    // framework or from another authentication client. The cancellation signal should not be set
+    // to null because there may exist a running authentication client.
+    // The signal can only be cancelled from the caller in FingerprintSettings.
+    @Test
+    public void testCancellationSignalLifeCycle() {
+        setUpFragment(false);
+
+        mFingerprintAuthenticateSidecar.setFingerprintManager(mFingerprintManager);
+
+        doNothing().when(mFingerprintManager).authenticate(any(),
+                mCancellationSignalArgumentCaptor.capture(),
+                mAuthenticationCallbackArgumentCaptor.capture(), any(), anyInt());
+
+        mFingerprintAuthenticateSidecar.startAuthentication(1);
+
+        assertThat(mAuthenticationCallbackArgumentCaptor.getValue()).isNotNull();
+        assertThat(mCancellationSignalArgumentCaptor.getValue()).isNotNull();
+
+        // Authentication error callback should not cancel the signal.
+        mAuthenticationCallbackArgumentCaptor.getValue().onAuthenticationError(0, "");
+        assertThat(mFingerprintAuthenticateSidecar.isCancelled()).isFalse();
+
+        // The signal should be cancelled when caller stops the authentication.
+        mFingerprintAuthenticateSidecar.stopAuthentication();
+        assertThat(mFingerprintAuthenticateSidecar.isCancelled()).isTrue();
+    }
+
     private void setUpFragment(boolean showChooseLock) {
         Intent intent = new Intent();
         if (!showChooseLock) {
@@ -166,6 +206,10 @@
         doReturn(fragmentManager).when(mFragment).getFragmentManager();
         doReturn(fragmentManager).when(mActivity).getSupportFragmentManager();
 
+        mFingerprintAuthenticateSidecar = new FingerprintAuthenticateSidecar();
+        doReturn(mFingerprintAuthenticateSidecar).when(fragmentManager).findFragmentByTag(
+                "authenticate_sidecar");
+
         doNothing().when(mFragment).startActivityForResult(any(Intent.class), anyInt());
 
         setSensor();
diff --git a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
index a6c4cd2..fcb01b4 100644
--- a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
+++ b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
@@ -31,6 +31,8 @@
 import com.android.settings.bluetooth.BluetoothFeatureProvider;
 import com.android.settings.dashboard.DashboardFeatureProvider;
 import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
+import com.android.settings.deviceinfo.hardwareinfo.HardwareInfoFeatureProvider;
+import com.android.settings.deviceinfo.hardwareinfo.HardwareInfoFeatureProviderImpl;
 import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
 import com.android.settings.fuelgauge.BatterySettingsFeatureProvider;
 import com.android.settings.fuelgauge.BatteryStatusFeatureProvider;
@@ -291,6 +293,11 @@
     }
 
     @Override
+    public HardwareInfoFeatureProvider getHardwareInfoFeatureProvider() {
+        return HardwareInfoFeatureProviderImpl.INSTANCE;
+    }
+
+    @Override
     public AdvancedVpnFeatureProvider getAdvancedVpnFeatureProvider() {
         return mAdvancedVpnFeatureProvider;
     }
diff --git a/tests/spa_unit/src/com/android/settings/testutils/FakeFeatureFactory.kt b/tests/spa_unit/src/com/android/settings/testutils/FakeFeatureFactory.kt
index bdaf805..68078f8 100644
--- a/tests/spa_unit/src/com/android/settings/testutils/FakeFeatureFactory.kt
+++ b/tests/spa_unit/src/com/android/settings/testutils/FakeFeatureFactory.kt
@@ -27,6 +27,7 @@
 import com.android.settings.bluetooth.BluetoothFeatureProvider
 import com.android.settings.dashboard.DashboardFeatureProvider
 import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider
+import com.android.settings.deviceinfo.hardwareinfo.HardwareInfoFeatureProvider
 import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider
 import com.android.settings.fuelgauge.BatterySettingsFeatureProvider
 import com.android.settings.fuelgauge.BatteryStatusFeatureProvider
@@ -174,6 +175,10 @@
         TODO("Not yet implemented")
     }
 
+    override fun getHardwareInfoFeatureProvider(): HardwareInfoFeatureProvider {
+        TODO("Not yet implemented")
+    }
+
     override fun getAdvancedVpnFeatureProvider(): AdvancedVpnFeatureProvider {
         TODO("Not yet implemented")
     }
diff --git a/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java
index db2339f..7a49865 100644
--- a/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java
+++ b/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java
@@ -29,6 +29,8 @@
 import com.android.settings.bluetooth.BluetoothFeatureProvider;
 import com.android.settings.dashboard.DashboardFeatureProvider;
 import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
+import com.android.settings.deviceinfo.hardwareinfo.HardwareInfoFeatureProvider;
+import com.android.settings.deviceinfo.hardwareinfo.HardwareInfoFeatureProviderImpl;
 import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
 import com.android.settings.fuelgauge.BatterySettingsFeatureProvider;
 import com.android.settings.fuelgauge.BatteryStatusFeatureProvider;
@@ -277,6 +279,11 @@
     }
 
     @Override
+    public HardwareInfoFeatureProvider getHardwareInfoFeatureProvider() {
+        return HardwareInfoFeatureProviderImpl.INSTANCE;
+    }
+
+    @Override
     public AdvancedVpnFeatureProvider getAdvancedVpnFeatureProvider() {
         return mAdvancedVpnFeatureProvider;
     }