1 /* <lambda>null2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.spa.app.specialaccess 18 19 import android.content.Context 20 import android.content.pm.ApplicationInfo 21 import android.content.pm.PackageManager.GET_ACTIVITIES 22 import android.content.pm.PackageManager.PackageInfoFlags 23 import android.nfc.NfcAdapter 24 import android.util.Log 25 import androidx.compose.runtime.Composable 26 import com.android.settings.R 27 import com.android.settingslib.spa.livedata.observeAsCallback 28 import com.android.settingslib.spaprivileged.model.app.AppRecord 29 import com.android.settingslib.spaprivileged.model.app.userId 30 import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListModel 31 import com.android.settingslib.spaprivileged.template.app.TogglePermissionAppListProvider 32 import kotlinx.coroutines.flow.Flow 33 import kotlinx.coroutines.flow.combine 34 import kotlinx.coroutines.flow.map 35 36 object NfcTagAppsSettingsProvider : TogglePermissionAppListProvider { 37 override val permissionType = "NfcTagAppsSettings" 38 override fun createModel(context: Context) = NfcTagAppsSettingsListModel(context) 39 } 40 41 data class NfcTagAppsSettingsRecord( 42 override val app: ApplicationInfo, 43 val controller: NfcTagAppsSettingsController, 44 val isSupported: Boolean, 45 ) : AppRecord 46 47 class NfcTagAppsSettingsListModel(private val context: Context) : 48 TogglePermissionAppListModel<NfcTagAppsSettingsRecord> { 49 override val pageTitleResId = R.string.change_nfc_tag_apps_title 50 override val switchTitleResId = R.string.change_nfc_tag_apps_detail_switch 51 override val footerResId = R.string.change_nfc_tag_apps_detail_summary 52 53 private val packageManager = context.packageManager 54 transformnull55 override fun transform( 56 userIdFlow: Flow<Int>, 57 appListFlow: Flow<List<ApplicationInfo>> 58 ): Flow<List<NfcTagAppsSettingsRecord>> = 59 userIdFlow.combine(appListFlow) { userId, appList -> 60 // The appListFlow always refreshed on resume, need to update nfcTagAppsSettingsPackages 61 // here to handle status change. 62 val nfcTagAppsSettingsPackages = getNfcTagAppsSettingsPackages(userId) 63 appList.map { app -> 64 createNfcTagAppsSettingsRecord( 65 app = app, 66 isAllowed = nfcTagAppsSettingsPackages[app.packageName], 67 ) 68 } 69 } 70 getNfcTagAppsSettingsPackagesnull71 private fun getNfcTagAppsSettingsPackages(userId: Int): Map<String, Boolean> { 72 NfcAdapter.getDefaultAdapter(context)?.let { nfcAdapter -> 73 if (nfcAdapter.isTagIntentAppPreferenceSupported) { 74 return nfcAdapter.getTagIntentAppPreferenceForUser(userId) 75 } 76 } 77 return emptyMap() 78 } 79 transformItemnull80 override fun transformItem(app: ApplicationInfo) = 81 createNfcTagAppsSettingsRecord( 82 app = app, 83 isAllowed = getNfcTagAppsSettingsPackages(app.userId)[app.packageName], 84 ) 85 86 private fun createNfcTagAppsSettingsRecord( 87 app: ApplicationInfo, 88 isAllowed: Boolean?, 89 ) = 90 NfcTagAppsSettingsRecord( 91 app = app, 92 isSupported = isAllowed != null, 93 controller = NfcTagAppsSettingsController(isAllowed == true), 94 ) 95 96 override fun filter( 97 userIdFlow: Flow<Int>, 98 recordListFlow: Flow<List<NfcTagAppsSettingsRecord>> 99 ) = recordListFlow.map { recordList -> recordList.filter { it.isSupported } } 100 101 @Composable isAllowednull102 override fun isAllowed(record: NfcTagAppsSettingsRecord) = 103 record.controller.isAllowed.observeAsCallback() 104 105 override fun isChangeable(record: NfcTagAppsSettingsRecord) = true 106 107 override fun setAllowed(record: NfcTagAppsSettingsRecord, newAllowed: Boolean) { 108 NfcAdapter.getDefaultAdapter(context)?.let { 109 if ( 110 it.setTagIntentAppPreferenceForUser( 111 record.app.userId, 112 record.app.packageName, 113 newAllowed 114 ) == NfcAdapter.TAG_INTENT_APP_PREF_RESULT_SUCCESS 115 ) { 116 record.controller.setAllowed(newAllowed) 117 } else { 118 Log.e(TAG, "Error updating TagIntentAppPreference") 119 } 120 } 121 } 122 123 private companion object { 124 const val TAG = "NfcTagAppsSettingsListModel" 125 val GET_ACTIVITIES_FLAGS = PackageInfoFlags.of(GET_ACTIVITIES.toLong()) 126 } 127 } 128