• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 android.permission;
18 
19 import android.Manifest;
20 import android.annotation.IntRange;
21 import android.annotation.NonNull;
22 import android.annotation.RequiresPermission;
23 import android.annotation.SystemApi;
24 import android.annotation.SystemService;
25 import android.annotation.TestApi;
26 import android.content.Context;
27 import android.content.pm.IPackageManager;
28 import android.os.RemoteException;
29 
30 import com.android.internal.annotations.Immutable;
31 import com.android.server.SystemConfig;
32 
33 import java.util.ArrayList;
34 import java.util.List;
35 import java.util.Objects;
36 
37 /**
38  * System level service for accessing the permission capabilities of the platform.
39  *
40  * @hide
41  */
42 @TestApi
43 @SystemApi
44 @SystemService(Context.PERMISSION_SERVICE)
45 public final class PermissionManager {
46     /**
47      * {@link android.content.pm.PackageParser} needs access without having a {@link Context}.
48      *
49      * @hide
50      */
51     public static final ArrayList<SplitPermissionInfo> SPLIT_PERMISSIONS =
52             SystemConfig.getInstance().getSplitPermissions();
53 
54     private final @NonNull Context mContext;
55 
56     private final IPackageManager mPackageManager;
57 
58     /**
59      * Creates a new instance.
60      *
61      * @param context The current context in which to operate.
62      * @hide
63      */
PermissionManager(@onNull Context context, IPackageManager packageManager)64     public PermissionManager(@NonNull Context context, IPackageManager packageManager) {
65         mContext = context;
66         mPackageManager = packageManager;
67     }
68 
69     /**
70      * Gets the version of the runtime permission database.
71      *
72      * @return The database version, -1 when this is an upgrade from pre-Q, 0 when this is a fresh
73      * install.
74      *
75      * @hide
76      */
77     @TestApi
78     @SystemApi
79     @RequiresPermission(Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY)
getRuntimePermissionsVersion()80     public @IntRange(from = 0) int getRuntimePermissionsVersion() {
81         try {
82             return mPackageManager.getRuntimePermissionsVersion(mContext.getUserId());
83         } catch (RemoteException e) {
84             throw e.rethrowFromSystemServer();
85         }
86     }
87 
88     /**
89      * Sets the version of the runtime permission database.
90      *
91      * @param version The new version.
92      *
93      * @hide
94      */
95     @TestApi
96     @SystemApi
97     @RequiresPermission(Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY)
setRuntimePermissionsVersion(@ntRangefrom = 0) int version)98     public void setRuntimePermissionsVersion(@IntRange(from = 0) int version) {
99         try {
100             mPackageManager.setRuntimePermissionsVersion(version, mContext.getUserId());
101         } catch (RemoteException e) {
102             throw e.rethrowFromSystemServer();
103         }
104     }
105 
106     /**
107      * Get set of permissions that have been split into more granular or dependent permissions.
108      *
109      * <p>E.g. before {@link android.os.Build.VERSION_CODES#Q} an app that was granted
110      * {@link Manifest.permission#ACCESS_COARSE_LOCATION} could access he location while it was in
111      * foreground and background. On platforms after {@link android.os.Build.VERSION_CODES#Q}
112      * the location permission only grants location access while the app is in foreground. This
113      * would break apps that target before {@link android.os.Build.VERSION_CODES#Q}. Hence whenever
114      * such an old app asks for a location permission (i.e. the
115      * {@link SplitPermissionInfo#getSplitPermission()}), then the
116      * {@link Manifest.permission#ACCESS_BACKGROUND_LOCATION} permission (inside
117      * {@link SplitPermissionInfo#getNewPermissions}) is added.
118      *
119      * <p>Note: Regular apps do not have to worry about this. The platform and permission controller
120      * automatically add the new permissions where needed.
121      *
122      * @return All permissions that are split.
123      */
getSplitPermissions()124     public @NonNull List<SplitPermissionInfo> getSplitPermissions() {
125         return SPLIT_PERMISSIONS;
126     }
127 
128     /**
129      * A permission that was added in a previous API level might have split into several
130      * permissions. This object describes one such split.
131      */
132     @Immutable
133     public static final class SplitPermissionInfo {
134         private final @NonNull String mSplitPerm;
135         private final @NonNull List<String> mNewPerms;
136         private final int mTargetSdk;
137 
138         @Override
equals(Object o)139         public boolean equals(Object o) {
140             if (this == o) return true;
141             if (o == null || getClass() != o.getClass()) return false;
142             SplitPermissionInfo that = (SplitPermissionInfo) o;
143             return mTargetSdk == that.mTargetSdk
144                     && mSplitPerm.equals(that.mSplitPerm)
145                     && mNewPerms.equals(that.mNewPerms);
146         }
147 
148         @Override
hashCode()149         public int hashCode() {
150             return Objects.hash(mSplitPerm, mNewPerms, mTargetSdk);
151         }
152 
153         /**
154          * Get the permission that is split.
155          */
getSplitPermission()156         public @NonNull String getSplitPermission() {
157             return mSplitPerm;
158         }
159 
160         /**
161          * Get the permissions that are added.
162          */
getNewPermissions()163         public @NonNull List<String> getNewPermissions() {
164             return mNewPerms;
165         }
166 
167         /**
168          * Get the target API level when the permission was split.
169          */
getTargetSdk()170         public int getTargetSdk() {
171             return mTargetSdk;
172         }
173 
174         /**
175          * Constructs a split permission.
176          *
177          * @param splitPerm old permission that will be split
178          * @param newPerms list of new permissions that {@code rootPerm} will be split into
179          * @param targetSdk apps targetting SDK versions below this will have {@code rootPerm}
180          * split into {@code newPerms}
181          * @hide
182          */
SplitPermissionInfo(@onNull String splitPerm, @NonNull List<String> newPerms, int targetSdk)183         public SplitPermissionInfo(@NonNull String splitPerm, @NonNull List<String> newPerms,
184                 int targetSdk) {
185             mSplitPerm = splitPerm;
186             mNewPerms = newPerms;
187             mTargetSdk = targetSdk;
188         }
189     }
190 }
191