Merge "Change preference title if Active Unlock enabled" into udc-dev am: 42deb763e0 am: 898e1d95f3 am: a783d32ab1

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Settings/+/22997141

Change-Id: I5b9024876a444a1bf62974f72132a34ac9010f11
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/src/com/android/settings/SettingsActivityUtil.kt b/src/com/android/settings/SettingsActivityUtil.kt
index cac341f..65d26de 100644
--- a/src/com/android/settings/SettingsActivityUtil.kt
+++ b/src/com/android/settings/SettingsActivityUtil.kt
@@ -35,6 +35,7 @@
 import com.android.settings.spa.app.specialaccess.InstallUnknownAppsListProvider
 import com.android.settings.spa.app.specialaccess.MediaManagementAppsAppListProvider
 import com.android.settings.spa.app.specialaccess.ModifySystemSettingsAppListProvider
+import com.android.settings.spa.app.specialaccess.NfcTagAppsSettingsProvider
 import com.android.settings.spa.app.specialaccess.PictureInPictureListProvider
 import com.android.settings.spa.app.specialaccess.WifiControlAppListProvider
 import com.android.settings.wifi.ChangeWifiStateDetails
@@ -62,6 +63,8 @@
             MediaManagementAppsAppListProvider.getAppInfoRoutePrefix(),
         ChangeWifiStateDetails::class.qualifiedName to
             WifiControlAppListProvider.getAppInfoRoutePrefix(),
+        NfcTagAppsSettingsProvider::class.qualifiedName to
+            NfcTagAppsSettingsProvider.getAppInfoRoutePrefix(),
     )
 
     @JvmStatic
diff --git a/src/com/android/settings/applications/credentials/DefaultCombinedPicker.java b/src/com/android/settings/applications/credentials/DefaultCombinedPicker.java
index 634be4c..5381056 100644
--- a/src/com/android/settings/applications/credentials/DefaultCombinedPicker.java
+++ b/src/com/android/settings/applications/credentials/DefaultCombinedPicker.java
@@ -371,6 +371,11 @@
 
         credManProviders.addAll(primaryCredManProviders);
 
+        // If there is no provider then clear all the providers.
+        if (TextUtils.isEmpty(autofillProvider) && primaryCredManProviders.isEmpty()) {
+            credManProviders.clear();
+        }
+
         service.setEnabledProviders(
                 primaryCredManProviders,
                 credManProviders,
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplicationsUtil.kt b/src/com/android/settings/applications/manageapplications/ManageApplicationsUtil.kt
index 78a4a6b..6574f69 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplicationsUtil.kt
+++ b/src/com/android/settings/applications/manageapplications/ManageApplicationsUtil.kt
@@ -63,6 +63,7 @@
 import com.android.settings.spa.app.specialaccess.InstallUnknownAppsListProvider
 import com.android.settings.spa.app.specialaccess.MediaManagementAppsAppListProvider
 import com.android.settings.spa.app.specialaccess.ModifySystemSettingsAppListProvider
+import com.android.settings.spa.app.specialaccess.NfcTagAppsSettingsProvider
 import com.android.settings.spa.app.specialaccess.WifiControlAppListProvider
 import com.android.settings.spa.notification.AppListNotificationsPageProvider
 import com.android.settings.spa.system.AppLanguagesPageProvider
@@ -112,6 +113,7 @@
             LIST_TYPE_NOTIFICATION -> AppListNotificationsPageProvider.name
             LIST_TYPE_APPS_LOCALE -> AppLanguagesPageProvider.name
             LIST_TYPE_MAIN -> AllAppListPageProvider.name
+            LIST_TYPE_NFC_TAG_APPS -> NfcTagAppsSettingsProvider.getAppListRoute()
             else -> null
         }
     }
diff --git a/src/com/android/settings/biometrics/BiometricEnrollActivity.java b/src/com/android/settings/biometrics/BiometricEnrollActivity.java
index 4d05946..ebbe2e8 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollActivity.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollActivity.java
@@ -326,8 +326,8 @@
             }
         }
 
-        boolean canUseFace = mIsFaceEnrollable;
-        boolean canUseFingerprint = mIsFingerprintEnrollable;
+        boolean canUseFace = mHasFeatureFace;
+        boolean canUseFingerprint = mHasFeatureFingerprint;
         if (mParentalOptionsRequired) {
             if (mParentalOptions == null) {
                 throw new IllegalStateException("consent options required, but not set");
@@ -345,10 +345,12 @@
         } else if (canUseFace || canUseFingerprint) {
             if (mGkPwHandle == null) {
                 setOrConfirmCredentialsNow();
-            } else if (canUseFingerprint) {
+            } else if (canUseFingerprint && mIsFingerprintEnrollable) {
                 launchFingerprintOnlyEnroll();
-            } else {
+            } else if (canUseFace && mIsFaceEnrollable) {
                 launchFaceOnlyEnroll();
+            } else {
+                setOrConfirmCredentialsNow();
             }
         } else { // no modalities available
             if (mParentalOptionsRequired) {
diff --git a/src/com/android/settings/spa/SettingsSpaEnvironment.kt b/src/com/android/settings/spa/SettingsSpaEnvironment.kt
index 455fe9f..caf5b15 100644
--- a/src/com/android/settings/spa/SettingsSpaEnvironment.kt
+++ b/src/com/android/settings/spa/SettingsSpaEnvironment.kt
@@ -29,6 +29,7 @@
 import com.android.settings.spa.app.specialaccess.InstallUnknownAppsListProvider
 import com.android.settings.spa.app.specialaccess.MediaManagementAppsAppListProvider
 import com.android.settings.spa.app.specialaccess.ModifySystemSettingsAppListProvider
+import com.android.settings.spa.app.specialaccess.NfcTagAppsSettingsProvider
 import com.android.settings.spa.app.specialaccess.PictureInPictureListProvider
 import com.android.settings.spa.app.specialaccess.SpecialAppAccessPageProvider
 import com.android.settings.spa.app.specialaccess.WifiControlAppListProvider
@@ -61,6 +62,7 @@
             InstallUnknownAppsListProvider,
             AlarmsAndRemindersAppListProvider,
             WifiControlAppListProvider,
+            NfcTagAppsSettingsProvider,
         )
     }
 
diff --git a/src/com/android/settings/spa/app/specialaccess/NfcTagAppsSettings.kt b/src/com/android/settings/spa/app/specialaccess/NfcTagAppsSettings.kt
new file mode 100644
index 0000000..3dede42
--- /dev/null
+++ b/src/com/android/settings/spa/app/specialaccess/NfcTagAppsSettings.kt
@@ -0,0 +1,127 @@
+/*
+ * 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.spa.app.specialaccess
+
+import android.content.Context
+import android.content.pm.ApplicationInfo
+import android.content.pm.PackageManager.GET_ACTIVITIES
+import android.content.pm.PackageManager.PackageInfoFlags
+import android.nfc.NfcAdapter
+import android.util.Log
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.livedata.observeAsState
+import com.android.settings.R
+import com.android.settingslib.spaprivileged.model.app.AppRecord
+import com.android.settingslib.spaprivileged.model.app.userId
+import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListModel
+import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListProvider
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.map
+
+object NfcTagAppsSettingsProvider : TogglePermissionAppListProvider {
+    override val permissionType = "NfcTagAppsSettings"
+    override fun createModel(context: Context) = NfcTagAppsSettingsListModel(context)
+}
+
+data class NfcTagAppsSettingsRecord(
+    override val app: ApplicationInfo,
+    val controller: NfcTagAppsSettingsController,
+    val isSupported: Boolean,
+) : AppRecord
+
+class NfcTagAppsSettingsListModel(private val context: Context) :
+    TogglePermissionAppListModel<NfcTagAppsSettingsRecord> {
+    override val pageTitleResId = R.string.change_nfc_tag_apps_title
+    override val switchTitleResId = R.string.change_nfc_tag_apps_detail_switch
+    override val footerResId = R.string.change_nfc_tag_apps_detail_summary
+
+    private val packageManager = context.packageManager
+
+    override fun transform(
+        userIdFlow: Flow<Int>,
+        appListFlow: Flow<List<ApplicationInfo>>
+    ): Flow<List<NfcTagAppsSettingsRecord>> =
+        userIdFlow.combine(appListFlow) { userId, appList ->
+            // The appListFlow always refreshed on resume, need to update nfcTagAppsSettingsPackages
+            // here to handle status change.
+            val nfcTagAppsSettingsPackages = getNfcTagAppsSettingsPackages(userId)
+            appList.map { app ->
+                createNfcTagAppsSettingsRecord(
+                    app = app,
+                    isAllowed = nfcTagAppsSettingsPackages[app.packageName],
+                )
+            }
+        }
+
+    private fun getNfcTagAppsSettingsPackages(userId: Int): Map<String, Boolean> {
+        NfcAdapter.getDefaultAdapter(context)?.let { nfcAdapter ->
+            if (nfcAdapter.isTagIntentAppPreferenceSupported) {
+                return nfcAdapter.getTagIntentAppPreferenceForUser(userId)
+            }
+        }
+        return emptyMap()
+    }
+
+    override fun transformItem(app: ApplicationInfo) =
+        createNfcTagAppsSettingsRecord(
+            app = app,
+            isAllowed = getNfcTagAppsSettingsPackages(app.userId)[app.packageName],
+        )
+
+    private fun createNfcTagAppsSettingsRecord(
+        app: ApplicationInfo,
+        isAllowed: Boolean?,
+    ) =
+        NfcTagAppsSettingsRecord(
+            app = app,
+            isSupported = isAllowed != null,
+            controller = NfcTagAppsSettingsController(isAllowed == true),
+        )
+
+    override fun filter(
+        userIdFlow: Flow<Int>,
+        recordListFlow: Flow<List<NfcTagAppsSettingsRecord>>
+    ) = recordListFlow.map { recordList -> recordList.filter { it.isSupported } }
+
+    @Composable
+    override fun isAllowed(record: NfcTagAppsSettingsRecord) =
+        record.controller.isAllowed.observeAsState()
+
+    override fun isChangeable(record: NfcTagAppsSettingsRecord) = true
+
+    override fun setAllowed(record: NfcTagAppsSettingsRecord, newAllowed: Boolean) {
+        NfcAdapter.getDefaultAdapter(context)?.let {
+            if (
+                it.setTagIntentAppPreferenceForUser(
+                    record.app.userId,
+                    record.app.packageName,
+                    newAllowed
+                ) == NfcAdapter.TAG_INTENT_APP_PREF_RESULT_SUCCESS
+            ) {
+                record.controller.setAllowed(newAllowed)
+            } else {
+                Log.e(TAG, "Error updating TagIntentAppPreference")
+            }
+        }
+    }
+
+    private companion object {
+        const val TAG = "NfcTagAppsSettingsListModel"
+        val GET_ACTIVITIES_FLAGS = PackageInfoFlags.of(GET_ACTIVITIES.toLong())
+    }
+}
diff --git a/src/com/android/settings/spa/app/specialaccess/NfcTagAppsSettingsController.kt b/src/com/android/settings/spa/app/specialaccess/NfcTagAppsSettingsController.kt
new file mode 100644
index 0000000..6e1b7b3
--- /dev/null
+++ b/src/com/android/settings/spa/app/specialaccess/NfcTagAppsSettingsController.kt
@@ -0,0 +1,30 @@
+/*
+ * 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.spa.app.specialaccess
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+
+class NfcTagAppsSettingsController(initialStatus: Boolean) {
+    val isAllowed: LiveData<Boolean>
+        get() = _allowed
+
+    fun setAllowed(newAllowed: Boolean) {
+        _allowed.postValue(newAllowed)
+    }
+    private val _allowed = MutableLiveData<Boolean>(initialStatus)
+}