1 /*
<lambda>null2  * Copyright (C) 2019 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 @file:Suppress("DEPRECATION")
17 
18 package com.android.permissioncontroller.permission.model.livedatatypes
19 
20 import android.app.Application
21 import android.content.pm.ApplicationInfo
22 import android.content.pm.Attribution
23 import android.content.pm.PackageInfo
24 import android.content.pm.PackageManager
25 import android.os.UserHandle
26 import android.util.Log
27 import com.android.modules.utils.build.SdkLevel
28 import com.android.permissioncontroller.permission.utils.ContextCompat
29 import com.android.permissioncontroller.permission.utils.Utils
30 
31 /**
32  * A lighter version of the system's PackageInfo class, containing select information about the
33  * package.
34  *
35  * @param packageName The name of the packages
36  * @param permissions The list of LightPermInfos representing the permissions this package defines
37  * @param requestedPermissions The names of the permissions this package requests
38  * @param requestedPermissionsFlags The grant state of the permissions this package requests
39  * @param uid The UID of this package
40  * @param targetSdkVersion The target SDK of this package
41  * @param isInstantApp Whether or not this package is an instant app
42  * @param enabled Whether or not this package is enabled.
43  */
44 data class LightPackageInfo(
45     val packageName: String,
46     val permissions: List<LightPermInfo>,
47     val requestedPermissions: List<String>,
48     var requestedPermissionsFlags: List<Int>,
49     val uid: Int,
50     val targetSdkVersion: Int,
51     val isInstantApp: Boolean,
52     val enabled: Boolean,
53     val appFlags: Int,
54     val firstInstallTime: Long,
55     val lastUpdateTime: Long,
56     val areAttributionsUserVisible: Boolean,
57     val attributionTagsToLabels: Map<String, Int>,
58     var deviceId: Int
59 ) {
60     constructor(
61         pI: PackageInfo
62     ) : this(
63         pI.packageName,
64         pI.permissions?.map { perm -> LightPermInfo(perm) } ?: emptyList(),
65         pI.requestedPermissions?.toList() ?: emptyList(),
66         pI.requestedPermissionsFlags?.toList() ?: emptyList(),
67         pI.applicationInfo!!.uid,
68         pI.applicationInfo!!.targetSdkVersion,
69         pI.applicationInfo!!.isInstantApp,
70         pI.applicationInfo!!.enabled,
71         pI.applicationInfo!!.flags,
72         pI.firstInstallTime,
73         pI.lastUpdateTime,
74         if (SdkLevel.isAtLeastS()) pI.applicationInfo!!.areAttributionsUserVisible() else false,
75         if (SdkLevel.isAtLeastS()) buildAttributionTagsToLabelsMap(pI.attributions) else emptyMap(),
76         ContextCompat.DEVICE_ID_DEFAULT
77     )
78 
79     constructor(
80         pI: PackageInfo,
81         deviceId: Int,
82         requestedPermissionsFlagsForDevice: List<Int>
83     ) : this(pI) {
84         this.deviceId = deviceId
85         this.requestedPermissionsFlags = requestedPermissionsFlagsForDevice
86     }
87 
88     /** Permissions which are granted according to the [requestedPermissionsFlags] */
89     val grantedPermissions: List<String>
90         get() {
91             val grantedPermissions = mutableListOf<String>()
92             for (i in 0 until requestedPermissions.size) {
93                 if (
94                     (requestedPermissionsFlags[i] and PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0
95                 ) {
96                     grantedPermissions.add(requestedPermissions[i])
97                 }
98             }
99             return grantedPermissions
100         }
101 
102     /**
103      * Gets the ApplicationInfo for this package from the system. Can be expensive if called too
104      * often.
105      *
106      * @param app The current application, which will be used to get the ApplicationInfo
107      * @return The ApplicationInfo corresponding to this package, with this UID, or null, if no such
108      *   package exists
109      */
110     fun getApplicationInfo(app: Application): ApplicationInfo? {
111         try {
112             val userContext = Utils.getUserContext(app, UserHandle.getUserHandleForUid(uid))
113             return userContext.packageManager.getApplicationInfo(packageName, 0)
114         } catch (e: PackageManager.NameNotFoundException) {}
115         return null
116     }
117 
118     /**
119      * Gets the PackageInfo for this package from the system. Can be expensive if called too often.
120      *
121      * @param app The current application, which will be used to get the PackageInfo
122      * @return The PackageInfo corresponding to this package, with this UID, or null, if no such
123      *   package exists
124      */
125     fun toPackageInfo(app: Application): PackageInfo? {
126         try {
127             val userContext = Utils.getUserContext(app, UserHandle.getUserHandleForUid(uid))
128             return userContext.packageManager.getPackageInfo(
129                 packageName,
130                 PackageManager.GET_PERMISSIONS
131             )
132         } catch (e: PackageManager.NameNotFoundException) {
133             Log.e(
134                 LightPackageInfo::class.java.simpleName,
135                 "Failed to get real package info for $packageName, $uid",
136                 e
137             )
138         }
139         return null
140     }
141 
142     /** Companion object for [LightPackageInfo]. */
143     companion object {
144         /** Creates a mapping of attribution tag to labels from the provided attributions. */
145         fun buildAttributionTagsToLabelsMap(attributions: Array<Attribution>?): Map<String, Int> {
146             val attributionTagToLabel = mutableMapOf<String, Int>()
147             attributions?.forEach { attributionTagToLabel[it.tag] = it.label }
148 
149             return attributionTagToLabel.toMap()
150         }
151     }
152 }
153