• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2022 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.appinfo
18 
19 import android.app.ActivityManager
20 import android.content.ComponentName
21 import android.content.Context
22 import android.content.pm.ApplicationInfo
23 import android.content.pm.PackageManager
24 import android.content.pm.ResolveInfo
25 import com.android.settingslib.RestrictedLockUtils
26 import com.android.settingslib.RestrictedLockUtilsInternal
27 import com.android.settingslib.Utils
28 import com.android.settingslib.spaprivileged.framework.common.devicePolicyManager
29 import com.android.settingslib.spaprivileged.model.app.isDisallowControl
30 import com.android.settingslib.spaprivileged.model.app.userId
31 
32 class AppButtonRepository(private val context: Context) {
33     private val packageManager = context.packageManager
34     private val devicePolicyManager = context.devicePolicyManager
35 
36     /**
37      * Checks whether the given application is disallowed from modifying.
38      */
39     fun isDisallowControl(app: ApplicationInfo): Boolean = when {
40         // Not allow to control the device provisioning package.
41         Utils.isDeviceProvisioningPackage(context.resources, app.packageName) -> true
42 
43         // If the uninstallation intent is already queued, disable the button.
44         devicePolicyManager.isUninstallInQueue(app.packageName) -> true
45 
46         else -> app.isDisallowControl(context)
47     }
48 
49     /**
50      * Checks whether uninstall is blocked by admin.
51      */
52     fun isUninstallBlockedByAdmin(app: ApplicationInfo): Boolean =
53         RestrictedLockUtilsInternal.checkIfUninstallBlocked(context, app.packageName, app.userId)
54             ?.let { admin ->
55                 RestrictedLockUtils.sendShowAdminSupportDetailsIntent(context, admin)
56                 true
57             } ?: false
58 
59     fun getHomePackageInfo(): HomePackages {
60         val homePackages = mutableSetOf<String>()
61         val homeActivities = ArrayList<ResolveInfo>()
62         val currentDefaultHome = packageManager.getHomeActivities(homeActivities)
63         homeActivities.mapNotNull { it.activityInfo }.forEach { activityInfo ->
64             homePackages.add(activityInfo.packageName)
65             // Also make sure to include anything proxying for the home app
66             activityInfo.metaData?.getString(ActivityManager.META_HOME_ALTERNATE)
67                 ?.takeIf { signaturesMatch(it, activityInfo.packageName) }
68                 ?.let { homePackages.add(it) }
69         }
70         return HomePackages(homePackages, currentDefaultHome)
71     }
72 
73     private fun signaturesMatch(packageName1: String, packageName2: String): Boolean = try {
74         packageManager.checkSignatures(packageName1, packageName2) >= PackageManager.SIGNATURE_MATCH
75     } catch (e: Exception) {
76         // e.g. named alternate package not found during lookup; this is an expected case sometimes
77         false
78     }
79 
80     data class HomePackages(
81         val homePackages: Set<String>,
82         val currentDefaultHome: ComponentName?,
83     )
84 }
85