blob: 3c45b0ce55deedc228c99868b183632dd5397fd9 [file] [log] [blame]
Philip P. Moltmann039678e2018-09-18 13:04:38 -07001/*
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
17package android.permission;
18
Svet Ganovd8eb8b22019-04-05 18:52:08 -070019import android.Manifest;
20import android.annotation.IntRange;
Philip P. Moltmann039678e2018-09-18 13:04:38 -070021import android.annotation.NonNull;
Aurimas Liutikas00be9512019-08-28 13:01:05 -070022import android.annotation.Nullable;
Svet Ganovd8eb8b22019-04-05 18:52:08 -070023import android.annotation.RequiresPermission;
Philip P. Moltmann039678e2018-09-18 13:04:38 -070024import android.annotation.SystemApi;
25import android.annotation.SystemService;
Svet Ganovd8eb8b22019-04-05 18:52:08 -070026import android.annotation.TestApi;
Philip P. Moltmann039678e2018-09-18 13:04:38 -070027import android.content.Context;
Svet Ganovd8eb8b22019-04-05 18:52:08 -070028import android.content.pm.IPackageManager;
Anthony Hugh6f5eadc2019-08-22 15:35:48 -070029import android.content.pm.permission.SplitPermissionInfoParcelable;
Svet Ganovd8eb8b22019-04-05 18:52:08 -070030import android.os.RemoteException;
Anthony Hugh6f5eadc2019-08-22 15:35:48 -070031import android.util.Log;
Philip P. Moltmann039678e2018-09-18 13:04:38 -070032
33import com.android.internal.annotations.Immutable;
34
Zimuzocc2932f2018-10-29 16:04:41 +000035import java.util.ArrayList;
Anthony Hugh6f5eadc2019-08-22 15:35:48 -070036import java.util.Collections;
Philip P. Moltmann039678e2018-09-18 13:04:38 -070037import java.util.List;
38
39/**
40 * System level service for accessing the permission capabilities of the platform.
41 *
42 * @hide
43 */
Winsonf27394e2019-06-07 14:44:40 -070044@TestApi
Philip P. Moltmann039678e2018-09-18 13:04:38 -070045@SystemApi
46@SystemService(Context.PERMISSION_SERVICE)
47public final class PermissionManager {
Anthony Hugh6f5eadc2019-08-22 15:35:48 -070048 private static final String TAG = PermissionManager.class.getName();
Philip P. Moltmann039678e2018-09-18 13:04:38 -070049
50 private final @NonNull Context mContext;
51
Svet Ganovd8eb8b22019-04-05 18:52:08 -070052 private final IPackageManager mPackageManager;
53
Anthony Hugh6f5eadc2019-08-22 15:35:48 -070054 private List<SplitPermissionInfo> mSplitPermissionInfos;
55
Philip P. Moltmann039678e2018-09-18 13:04:38 -070056 /**
57 * Creates a new instance.
58 *
59 * @param context The current context in which to operate.
60 * @hide
61 */
Svet Ganovd8eb8b22019-04-05 18:52:08 -070062 public PermissionManager(@NonNull Context context, IPackageManager packageManager) {
Philip P. Moltmann039678e2018-09-18 13:04:38 -070063 mContext = context;
Svet Ganovd8eb8b22019-04-05 18:52:08 -070064 mPackageManager = packageManager;
65 }
66
67 /**
68 * Gets the version of the runtime permission database.
69 *
Philip P. Moltmann1ae81a52019-05-21 15:31:36 -070070 * @return The database version, -1 when this is an upgrade from pre-Q, 0 when this is a fresh
71 * install.
Svet Ganovd8eb8b22019-04-05 18:52:08 -070072 *
73 * @hide
74 */
75 @TestApi
76 @SystemApi
77 @RequiresPermission(Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY)
78 public @IntRange(from = 0) int getRuntimePermissionsVersion() {
79 try {
80 return mPackageManager.getRuntimePermissionsVersion(mContext.getUserId());
81 } catch (RemoteException e) {
82 throw e.rethrowFromSystemServer();
83 }
84 }
85
86 /**
87 * Sets the version of the runtime permission database.
88 *
89 * @param version The new version.
90 *
91 * @hide
92 */
93 @TestApi
94 @SystemApi
95 @RequiresPermission(Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY)
96 public void setRuntimePermissionsVersion(@IntRange(from = 0) int version) {
97 try {
98 mPackageManager.setRuntimePermissionsVersion(version, mContext.getUserId());
99 } catch (RemoteException e) {
100 throw e.rethrowFromSystemServer();
101 }
Philip P. Moltmann039678e2018-09-18 13:04:38 -0700102 }
103
104 /**
Philip P. Moltmanna3ba4d92018-10-08 11:50:07 -0700105 * Get set of permissions that have been split into more granular or dependent permissions.
Philip P. Moltmann039678e2018-09-18 13:04:38 -0700106 *
Howard Chenfff50fe2019-04-29 14:46:32 +0800107 * <p>E.g. before {@link android.os.Build.VERSION_CODES#Q} an app that was granted
Philip P. Moltmann039678e2018-09-18 13:04:38 -0700108 * {@link Manifest.permission#ACCESS_COARSE_LOCATION} could access he location while it was in
Howard Chenfff50fe2019-04-29 14:46:32 +0800109 * foreground and background. On platforms after {@link android.os.Build.VERSION_CODES#Q}
Philip P. Moltmann039678e2018-09-18 13:04:38 -0700110 * the location permission only grants location access while the app is in foreground. This
Howard Chenfff50fe2019-04-29 14:46:32 +0800111 * would break apps that target before {@link android.os.Build.VERSION_CODES#Q}. Hence whenever
Philip P. Moltmann039678e2018-09-18 13:04:38 -0700112 * such an old app asks for a location permission (i.e. the
Philip P. Moltmanna3ba4d92018-10-08 11:50:07 -0700113 * {@link SplitPermissionInfo#getSplitPermission()}), then the
Philip P. Moltmann039678e2018-09-18 13:04:38 -0700114 * {@link Manifest.permission#ACCESS_BACKGROUND_LOCATION} permission (inside
Philip P. Moltmanne1b277a2018-11-01 16:22:50 -0700115 * {@link SplitPermissionInfo#getNewPermissions}) is added.
Philip P. Moltmann039678e2018-09-18 13:04:38 -0700116 *
117 * <p>Note: Regular apps do not have to worry about this. The platform and permission controller
118 * automatically add the new permissions where needed.
119 *
120 * @return All permissions that are split.
121 */
Philip P. Moltmanne1b277a2018-11-01 16:22:50 -0700122 public @NonNull List<SplitPermissionInfo> getSplitPermissions() {
Anthony Hugh6f5eadc2019-08-22 15:35:48 -0700123 if (mSplitPermissionInfos != null) {
124 return mSplitPermissionInfos;
125 }
126
127 List<SplitPermissionInfoParcelable> parcelableList;
128 try {
129 parcelableList = mPackageManager.getSplitPermissions();
130 } catch (RemoteException e) {
131 Log.w(TAG, "Error getting split permissions", e);
132 return Collections.emptyList();
133 }
134
135 mSplitPermissionInfos = splitPermissionInfoListToNonParcelableList(parcelableList);
136
137 return mSplitPermissionInfos;
138 }
139
140 private List<SplitPermissionInfo> splitPermissionInfoListToNonParcelableList(
141 List<SplitPermissionInfoParcelable> parcelableList) {
142 final int size = parcelableList.size();
143 List<SplitPermissionInfo> list = new ArrayList<>(size);
144 for (int i = 0; i < size; i++) {
145 list.add(new SplitPermissionInfo(parcelableList.get(i)));
146 }
147 return list;
148 }
149
150 /**
151 * Converts a {@link List} of {@link SplitPermissionInfo} into a List of
152 * {@link SplitPermissionInfoParcelable} and returns it.
153 * @hide
154 */
155 public static List<SplitPermissionInfoParcelable> splitPermissionInfoListToParcelableList(
156 List<SplitPermissionInfo> splitPermissionsList) {
157 final int size = splitPermissionsList.size();
158 List<SplitPermissionInfoParcelable> outList = new ArrayList<>(size);
159 for (int i = 0; i < size; i++) {
160 SplitPermissionInfo info = splitPermissionsList.get(i);
161 outList.add(new SplitPermissionInfoParcelable(
162 info.getSplitPermission(), info.getNewPermissions(), info.getTargetSdk()));
163 }
164 return outList;
Philip P. Moltmann039678e2018-09-18 13:04:38 -0700165 }
166
167 /**
168 * A permission that was added in a previous API level might have split into several
169 * permissions. This object describes one such split.
170 */
171 @Immutable
172 public static final class SplitPermissionInfo {
Anthony Hugh6f5eadc2019-08-22 15:35:48 -0700173 private @NonNull final SplitPermissionInfoParcelable mSplitPermissionInfoParcelable;
Philip P. Moltmann039678e2018-09-18 13:04:38 -0700174
Philip P. Moltmanna3ba4d92018-10-08 11:50:07 -0700175 @Override
Aurimas Liutikas00be9512019-08-28 13:01:05 -0700176 public boolean equals(@Nullable Object o) {
Philip P. Moltmanna3ba4d92018-10-08 11:50:07 -0700177 if (this == o) return true;
178 if (o == null || getClass() != o.getClass()) return false;
179 SplitPermissionInfo that = (SplitPermissionInfo) o;
Anthony Hugh6f5eadc2019-08-22 15:35:48 -0700180 return mSplitPermissionInfoParcelable.equals(that.mSplitPermissionInfoParcelable);
Philip P. Moltmanna3ba4d92018-10-08 11:50:07 -0700181 }
182
183 @Override
184 public int hashCode() {
Anthony Hugh6f5eadc2019-08-22 15:35:48 -0700185 return mSplitPermissionInfoParcelable.hashCode();
Philip P. Moltmanna3ba4d92018-10-08 11:50:07 -0700186 }
187
Philip P. Moltmann039678e2018-09-18 13:04:38 -0700188 /**
189 * Get the permission that is split.
190 */
Philip P. Moltmanna3ba4d92018-10-08 11:50:07 -0700191 public @NonNull String getSplitPermission() {
Anthony Hugh6f5eadc2019-08-22 15:35:48 -0700192 return mSplitPermissionInfoParcelable.getSplitPermission();
Philip P. Moltmann039678e2018-09-18 13:04:38 -0700193 }
194
195 /**
196 * Get the permissions that are added.
197 */
Philip P. Moltmanna3ba4d92018-10-08 11:50:07 -0700198 public @NonNull List<String> getNewPermissions() {
Anthony Hugh6f5eadc2019-08-22 15:35:48 -0700199 return mSplitPermissionInfoParcelable.getNewPermissions();
Philip P. Moltmann039678e2018-09-18 13:04:38 -0700200 }
201
202 /**
203 * Get the target API level when the permission was split.
204 */
205 public int getTargetSdk() {
Anthony Hugh6f5eadc2019-08-22 15:35:48 -0700206 return mSplitPermissionInfoParcelable.getTargetSdk();
Philip P. Moltmann039678e2018-09-18 13:04:38 -0700207 }
208
Zimuzocc2932f2018-10-29 16:04:41 +0000209 /**
210 * Constructs a split permission.
211 *
212 * @param splitPerm old permission that will be split
213 * @param newPerms list of new permissions that {@code rootPerm} will be split into
214 * @param targetSdk apps targetting SDK versions below this will have {@code rootPerm}
215 * split into {@code newPerms}
216 * @hide
217 */
218 public SplitPermissionInfo(@NonNull String splitPerm, @NonNull List<String> newPerms,
Philip P. Moltmann039678e2018-09-18 13:04:38 -0700219 int targetSdk) {
Anthony Hugh6f5eadc2019-08-22 15:35:48 -0700220 this(new SplitPermissionInfoParcelable(splitPerm, newPerms, targetSdk));
221 }
222
223 private SplitPermissionInfo(@NonNull SplitPermissionInfoParcelable parcelable) {
224 mSplitPermissionInfoParcelable = parcelable;
Philip P. Moltmann039678e2018-09-18 13:04:38 -0700225 }
226 }
227}