diff --git a/src/com/android/settings/SettingsActivityUtil.kt b/src/com/android/settings/SettingsActivityUtil.kt index cac341fff02..65d26defbf8 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.DisplayOverOtherAppsAppListPro 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 @@ object SettingsActivityUtil { MediaManagementAppsAppListProvider.getAppInfoRoutePrefix(), ChangeWifiStateDetails::class.qualifiedName to WifiControlAppListProvider.getAppInfoRoutePrefix(), + NfcTagAppsSettingsProvider::class.qualifiedName to + NfcTagAppsSettingsProvider.getAppInfoRoutePrefix(), ) @JvmStatic diff --git a/src/com/android/settings/applications/manageapplications/ManageApplicationsUtil.kt b/src/com/android/settings/applications/manageapplications/ManageApplicationsUtil.kt index 78a4a6bfe54..6574f6926fc 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.DisplayOverOtherAppsAppListPro 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 @@ object ManageApplicationsUtil { 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/spa/SettingsSpaEnvironment.kt b/src/com/android/settings/spa/SettingsSpaEnvironment.kt index 455fe9ff4b9..caf5b1532ce 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.DisplayOverOtherAppsAppListPro 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 @@ open class SettingsSpaEnvironment(context: Context) : SpaEnvironment(context) { 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 00000000000..3dede42a34d --- /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 { + 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, + appListFlow: Flow> + ): Flow> = + 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 { + 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, + recordListFlow: Flow> + ) = 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 00000000000..6e1b7b36f70 --- /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 + get() = _allowed + + fun setAllowed(newAllowed: Boolean) { + _allowed.postValue(newAllowed) + } + private val _allowed = MutableLiveData(initialStatus) +}