1 /*
2  * 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.permissioncontroller.permission.service
18 
19 import android.permission.PermissionManager
20 import com.android.permissioncontroller.permission.utils.PermissionMapping
21 
22 /**
23  * Takes a list of split permissions, and provides methods that return which split-permissions will
24  * be active given an app's targetSdk.
25  */
26 class SplitPermissionIndex() {
27     private lateinit var permToGroupSplits: Set<SplitPermissionIndexEntry>
28     private lateinit var groupToGroupSplits: Set<SplitPermissionIndexEntry>
29 
30     constructor(groupToGroupSplits: Set<SplitPermissionIndexEntry>) : this() {
31         this.groupToGroupSplits = groupToGroupSplits
32     }
33 
34     constructor(splitPermissionInfos: List<PermissionManager.SplitPermissionInfo>) : this() {
35         val permToGroupSplits: MutableSet<SplitPermissionIndexEntry> = mutableSetOf()
36         val groupToGroupSplits: MutableSet<SplitPermissionIndexEntry> = mutableSetOf()
37         for (splitPermissionInfo in splitPermissionInfos) {
38             val splitPermission = splitPermissionInfo.splitPermission
39             for (newPerm in splitPermissionInfo.newPermissions) {
40                 val splitPermissionGroup =
41                     PermissionMapping.getGroupOfPlatformPermission(splitPermission)
42                 val newPermGroup = PermissionMapping.getGroupOfPlatformPermission(newPerm)
43                 if (newPermGroup != null) {
44                     permToGroupSplits.add(
45                         SplitPermissionIndexEntry(
46                             splitPermission,
47                             splitPermissionInfo.targetSdk,
48                             newPermGroup
49                         )
50                     )
51                 }
52                 if (splitPermissionGroup != null && newPermGroup != null) {
53                     groupToGroupSplits.add(
54                         SplitPermissionIndexEntry(
55                             splitPermissionGroup,
56                             splitPermissionInfo.targetSdk,
57                             newPermGroup
58                         )
59                     )
60                 }
61             }
62         }
63         this.permToGroupSplits = permToGroupSplits
64         this.groupToGroupSplits = groupToGroupSplits
65     }
66 
67     /**
68      * Given a split permission, and a package targetSdkVersion, return permission groups of new
69      * permissions. See <split-permission> tag.
70      *
71      * @param splitPermission the split permission (i.e. old permission)
72      * @param appTargetSdk app target sdk
73      * @return the permission groups calculated from new permissions
74      */
getPermissionGroupsFromSplitPermissionnull75     fun getPermissionGroupsFromSplitPermission(
76         splitPermission: String,
77         appTargetSdk: Int
78     ): List<String> {
79         return permToGroupSplits
80             .filter { it.splitPermissionOrGroup == splitPermission && appTargetSdk < it.targetSdk }
81             .map { it.newPermissionGroup }
82             .toList()
83     }
84 
85     /**
86      * Given a split permission, and a package targetSdkVersion, return permission groups of new
87      * permissions. See <split-permission> tag.
88      *
89      * @param splitPermissionGroup permission group of a split permission
90      * @param appTargetSdk app target sdk
91      * @return the permission groups calculated from new permissions
92      */
getPermissionGroupsFromSplitPermissionGroupnull93     fun getPermissionGroupsFromSplitPermissionGroup(
94         splitPermissionGroup: String,
95         appTargetSdk: Int
96     ): List<String> {
97         return groupToGroupSplits
98             .filter {
99                 it.splitPermissionOrGroup == splitPermissionGroup && appTargetSdk < it.targetSdk
100             }
101             .map { it.newPermissionGroup }
102             .toList()
103     }
104 
105     /**
106      * Given a permission group, and package's target sdk find permission groups of the split
107      * permissions, see <split-permission> tag.
108      *
109      * @param permissionGroup permission group mapped to new permissions in <split-permission> tag
110      * @param appTargetSdk app target sdk
111      * @return the permission group for the split permissions
112      */
getSplitPermissionGroupsnull113     fun getSplitPermissionGroups(permissionGroup: String, appTargetSdk: Int): List<String> {
114         return groupToGroupSplits
115             .filter { it.newPermissionGroup == permissionGroup && appTargetSdk < it.targetSdk }
116             .map { it.splitPermissionOrGroup }
117             .toList()
118     }
119 
120     data class SplitPermissionIndexEntry(
121         val splitPermissionOrGroup: String,
122         /** The split only applies to app target sdk below this */
123         val targetSdk: Int,
124         val newPermissionGroup: String
125     )
126 }
127