• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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