• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * 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.notification.app
18 
19 import android.Manifest.permission.USE_FULL_SCREEN_INTENT
20 import android.app.AppOpsManager
21 import android.app.AppOpsManager.OP_USE_FULL_SCREEN_INTENT
22 import android.content.AttributionSource
23 import android.content.Context
24 import android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET
25 import android.content.pm.PackageManager.GET_PERMISSIONS
26 import android.content.pm.PackageManager.NameNotFoundException
27 import android.os.UserHandle
28 import android.permission.PermissionManager
29 import android.util.Log
30 import androidx.preference.Preference
31 import androidx.preference.Preference.OnPreferenceChangeListener
32 import com.android.settings.notification.NotificationBackend
33 import com.android.settingslib.RestrictedSwitchPreference
34 
35 class FullScreenIntentPermissionPreferenceController(
36     context: Context,
37     backend: NotificationBackend
38 ) : NotificationPreferenceController(context, backend), OnPreferenceChangeListener {
39     private val packageManager = mPm!!
40     private val permissionManager = context.getSystemService(PermissionManager::class.java)!!
41     private val appOpsManager = context.getSystemService(AppOpsManager::class.java)!!
42 
43     private val packageName get() = mAppRow.pkg
44     private val uid get() = mAppRow.uid
45     private val userHandle get() = UserHandle.getUserHandleForUid(uid)
46 
getPreferenceKeynull47     override fun getPreferenceKey() = KEY_FSI_PERMISSION
48 
49     override fun isAvailable(): Boolean {
50         val inAppWidePreferences = mChannelGroup == null && mChannel == null
51 
52         if (!inAppWidePreferences) {
53             Log.wtf(TAG, "Belongs only in app-wide notification preferences!")
54         }
55 
56         return super.isAvailable() && inAppWidePreferences && isPermissionRequested()
57     }
58 
isIncludedInFilternull59     override fun isIncludedInFilter() = false
60 
61     override fun updateState(preference: Preference) {
62         check(KEY_FSI_PERMISSION.equals(preference.key))
63         check(preference is RestrictedSwitchPreference)
64 
65         preference.setDisabledByAdmin(mAdmin)
66         preference.isEnabled = !preference.isDisabledByAdmin
67         preference.isChecked = isPermissionGranted()
68         preference.parent?.isVisible = true
69     }
70 
onPreferenceChangenull71     override fun onPreferenceChange(preference: Preference, value: Any): Boolean {
72         check(KEY_FSI_PERMISSION.equals(preference.key))
73         check(preference is RestrictedSwitchPreference)
74         check(value is Boolean)
75 
76         if (isPermissionGranted() != value) {
77             setPermissionGranted(value)
78         }
79 
80         return true
81     }
82 
isPermissionRequestednull83     private fun isPermissionRequested(): Boolean {
84         try {
85             val packageInfo = packageManager.getPackageInfo(packageName, GET_PERMISSIONS)
86 
87             for (requestedPermission in packageInfo.requestedPermissions.orEmpty()) {
88                 if (USE_FULL_SCREEN_INTENT.equals(requestedPermission)) {
89                     return true
90                 }
91             }
92         } catch (exception: NameNotFoundException) {
93             Log.e(TAG, "isPermissionRequested failed: $exception")
94         }
95 
96         return false
97     }
98 
isPermissionGrantednull99     private fun isPermissionGranted(): Boolean {
100         val attributionSource = AttributionSource.Builder(uid).setPackageName(packageName).build()
101 
102         val permissionResult =
103             permissionManager.checkPermissionForPreflight(USE_FULL_SCREEN_INTENT, attributionSource)
104 
105         return (permissionResult == PermissionManager.PERMISSION_GRANTED)
106     }
107 
setPermissionGrantednull108     private fun setPermissionGranted(allowed: Boolean) {
109         val mode = if (allowed) AppOpsManager.MODE_ALLOWED else AppOpsManager.MODE_ERRORED
110         appOpsManager.setUidMode(OP_USE_FULL_SCREEN_INTENT, uid, mode)
111         packageManager.updatePermissionFlags(
112             USE_FULL_SCREEN_INTENT,
113             packageName,
114             FLAG_PERMISSION_USER_SET,
115             FLAG_PERMISSION_USER_SET,
116             userHandle
117         )
118     }
119 
120     companion object {
121         const val KEY_FSI_PERMISSION = "fsi_permission"
122         const val TAG = "FsiPermPrefController"
123     }
124 }
125