blob: 9d58064ab6d0bdc2d724612385c9a5f3a86cb00e [file] [log] [blame]
Svet Ganovae0e03a2016-02-25 18:22:10 -08001/*
2 * Copyright (C) 2016 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
Philip P. Moltmanndbf78b82018-12-04 13:44:27 -080017package android.permission;
Svet Ganovae0e03a2016-02-25 18:22:10 -080018
Philip P. Moltmann41df9f92019-02-08 13:07:57 -080019import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT;
20import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED;
21import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED;
Philip P. Moltmannbc054d82018-12-21 09:41:58 -080022import static android.permission.PermissionControllerService.SERVICE_INTERFACE;
Philip P. Moltmann22b84982018-12-17 20:45:40 -080023
Philip P. Moltmann41df9f92019-02-08 13:07:57 -080024import static com.android.internal.util.Preconditions.checkArgument;
Joel Galenson5f63b832018-12-19 15:38:04 -080025import static com.android.internal.util.Preconditions.checkArgumentNonnegative;
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -080026import static com.android.internal.util.Preconditions.checkCollectionElementsNotNull;
Philip P. Moltmanne1436e852019-01-31 14:22:39 -080027import static com.android.internal.util.Preconditions.checkFlagsArgument;
Philip P. Moltmann44689732018-12-04 10:08:19 -080028import static com.android.internal.util.Preconditions.checkNotNull;
Hai Zhang19821872019-01-23 16:48:40 -080029import static com.android.internal.util.Preconditions.checkStringNotEmpty;
Philip P. Moltmann44689732018-12-04 10:08:19 -080030
Philip P. Moltmann7532c612019-01-20 09:01:19 -080031import static java.lang.Math.min;
32
Philip P. Moltmannbc054d82018-12-21 09:41:58 -080033import android.Manifest;
Philip P. Moltmann78689522018-12-17 20:45:40 -080034import android.annotation.CallbackExecutor;
35import android.annotation.IntDef;
Svet Ganovae0e03a2016-02-25 18:22:10 -080036import android.annotation.NonNull;
37import android.annotation.Nullable;
Philip P. Moltmannbc054d82018-12-21 09:41:58 -080038import android.annotation.RequiresPermission;
Philip P. Moltmann78689522018-12-17 20:45:40 -080039import android.annotation.SystemApi;
Philip P. Moltmannbc054d82018-12-21 09:41:58 -080040import android.annotation.SystemService;
Philip P. Moltmann78689522018-12-17 20:45:40 -080041import android.annotation.TestApi;
Philip P. Moltmann41df9f92019-02-08 13:07:57 -080042import android.app.admin.DevicePolicyManager.PermissionGrantState;
Svet Ganovae0e03a2016-02-25 18:22:10 -080043import android.content.ComponentName;
44import android.content.Context;
45import android.content.Intent;
Philip P. Moltmann78689522018-12-17 20:45:40 -080046import android.content.pm.PackageManager;
Philip P. Moltmann22b84982018-12-17 20:45:40 -080047import android.content.pm.ResolveInfo;
Philip P. Moltmann97142e22019-01-10 17:03:42 -080048import android.os.AsyncTask;
Philip P. Moltmann78689522018-12-17 20:45:40 -080049import android.os.Binder;
50import android.os.Bundle;
Svet Ganovae0e03a2016-02-25 18:22:10 -080051import android.os.Handler;
52import android.os.IBinder;
Philip P. Moltmann97142e22019-01-10 17:03:42 -080053import android.os.ParcelFileDescriptor;
Svet Ganovae0e03a2016-02-25 18:22:10 -080054import android.os.RemoteCallback;
55import android.os.RemoteException;
Philip P. Moltmann22b84982018-12-17 20:45:40 -080056import android.os.UserHandle;
Philip P. Moltmann78689522018-12-17 20:45:40 -080057import android.util.ArrayMap;
Svet Ganovae0e03a2016-02-25 18:22:10 -080058import android.util.Log;
Philip P. Moltmanncfd2fbc2019-02-08 13:07:57 -080059import android.util.SparseArray;
jackqdyuleia90bfb52017-06-22 16:27:29 -070060
Philip P. Moltmann5e5c41e52019-01-13 09:53:12 -080061import com.android.internal.annotations.GuardedBy;
Philip P. Moltmann22b84982018-12-17 20:45:40 -080062import com.android.internal.infra.AbstractMultiplePendingRequestsRemoteService;
63import com.android.internal.infra.AbstractRemoteService;
Philip P. Moltmann78689522018-12-17 20:45:40 -080064import com.android.internal.util.Preconditions;
Svet Ganovae0e03a2016-02-25 18:22:10 -080065
Philip P. Moltmann97142e22019-01-10 17:03:42 -080066import libcore.io.IoUtils;
67
68import java.io.ByteArrayOutputStream;
69import java.io.IOException;
70import java.io.InputStream;
Philip P. Moltmann7532c612019-01-20 09:01:19 -080071import java.io.OutputStream;
Philip P. Moltmann78689522018-12-17 20:45:40 -080072import java.lang.annotation.Retention;
73import java.lang.annotation.RetentionPolicy;
74import java.util.ArrayList;
Svet Ganovae0e03a2016-02-25 18:22:10 -080075import java.util.Collections;
76import java.util.List;
Philip P. Moltmann78689522018-12-17 20:45:40 -080077import java.util.Map;
78import java.util.concurrent.Executor;
Philip P. Moltmann97142e22019-01-10 17:03:42 -080079import java.util.function.Consumer;
Svet Ganovae0e03a2016-02-25 18:22:10 -080080
81/**
Philip P. Moltmann78689522018-12-17 20:45:40 -080082 * Interface for communicating with the permission controller.
Svet Ganovae0e03a2016-02-25 18:22:10 -080083 *
84 * @hide
85 */
Philip P. Moltmann78689522018-12-17 20:45:40 -080086@TestApi
87@SystemApi
Philip P. Moltmannbc054d82018-12-21 09:41:58 -080088@SystemService(Context.PERMISSION_CONTROLLER_SERVICE)
89public final class PermissionControllerManager {
90 private static final String TAG = PermissionControllerManager.class.getSimpleName();
Svet Ganovae0e03a2016-02-25 18:22:10 -080091
Philip P. Moltmann5e5c41e52019-01-13 09:53:12 -080092 private static final Object sLock = new Object();
93
Philip P. Moltmanncfd2fbc2019-02-08 13:07:57 -080094 /**
95 * Global remote services (per user) used by all {@link PermissionControllerManager managers}
96 */
Philip P. Moltmann5e5c41e52019-01-13 09:53:12 -080097 @GuardedBy("sLock")
Philip P. Moltmanncfd2fbc2019-02-08 13:07:57 -080098 private static SparseArray<RemoteService> sRemoteServices = new SparseArray<>(1);
Philip P. Moltmann5e5c41e52019-01-13 09:53:12 -080099
Svet Ganovae0e03a2016-02-25 18:22:10 -0800100 /**
101 * The key for retrieving the result from the returned bundle.
Philip P. Moltmann78689522018-12-17 20:45:40 -0800102 *
103 * @hide
Svet Ganovae0e03a2016-02-25 18:22:10 -0800104 */
105 public static final String KEY_RESULT =
Philip P. Moltmannbc054d82018-12-21 09:41:58 -0800106 "android.permission.PermissionControllerManager.key.result";
Svet Ganovae0e03a2016-02-25 18:22:10 -0800107
Philip P. Moltmann78689522018-12-17 20:45:40 -0800108 /** @hide */
109 @IntDef(prefix = { "REASON_" }, value = {
110 REASON_MALWARE,
111 REASON_INSTALLER_POLICY_VIOLATION,
112 })
113 @Retention(RetentionPolicy.SOURCE)
114 public @interface Reason {}
115
116 /** The permissions are revoked because the apps holding the permissions are malware */
117 public static final int REASON_MALWARE = 1;
118
119 /**
120 * The permissions are revoked because the apps holding the permissions violate a policy of the
121 * app that installed it.
122 *
123 * <p>If this reason is used only permissions of apps that are installed by the caller of the
124 * API can be revoked.
125 */
126 public static final int REASON_INSTALLER_POLICY_VIOLATION = 2;
127
Philip P. Moltmanne1436e852019-01-31 14:22:39 -0800128 /** @hide */
129 @IntDef(prefix = { "COUNT_" }, value = {
130 COUNT_ONLY_WHEN_GRANTED,
131 COUNT_WHEN_SYSTEM,
132 }, flag = true)
133 @Retention(RetentionPolicy.SOURCE)
134 public @interface CountPermissionAppsFlag {}
135
136 /** Count an app only if the permission is granted to the app. */
137 public static final int COUNT_ONLY_WHEN_GRANTED = 1;
138
139 /** Count and app even if it is a system app. */
140 public static final int COUNT_WHEN_SYSTEM = 2;
141
Philip P. Moltmann78689522018-12-17 20:45:40 -0800142 /**
143 * Callback for delivering the result of {@link #revokeRuntimePermissions}.
144 */
145 public abstract static class OnRevokeRuntimePermissionsCallback {
146 /**
147 * The result for {@link #revokeRuntimePermissions}.
148 *
149 * @param revoked The actually revoked permissions as
150 * {@code Map<packageName, List<permission>>}
151 */
152 public abstract void onRevokeRuntimePermissions(@NonNull Map<String, List<String>> revoked);
153 }
154
Svet Ganovae0e03a2016-02-25 18:22:10 -0800155 /**
Philip P. Moltmann97142e22019-01-10 17:03:42 -0800156 * Callback for delivering the result of {@link #getRuntimePermissionBackup}.
157 *
158 * @hide
159 */
160 public interface OnGetRuntimePermissionBackupCallback {
161 /**
162 * The result for {@link #getRuntimePermissionBackup}.
163 *
164 * @param backup The backup file
165 */
166 void onGetRuntimePermissionsBackup(@NonNull byte[] backup);
167 }
168
169 /**
Philip P. Moltmannbc054d82018-12-21 09:41:58 -0800170 * Callback for delivering the result of {@link #getAppPermissions}.
Philip P. Moltmann78689522018-12-17 20:45:40 -0800171 *
172 * @hide
Svet Ganovae0e03a2016-02-25 18:22:10 -0800173 */
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -0800174 public interface OnGetAppPermissionResultCallback {
Svet Ganovae0e03a2016-02-25 18:22:10 -0800175 /**
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -0800176 * The result for {@link #getAppPermissions(String, OnGetAppPermissionResultCallback,
177 * Handler)}.
178 *
Svet Ganovae0e03a2016-02-25 18:22:10 -0800179 * @param permissions The permissions list.
180 */
Philip P. Moltmanndbf78b82018-12-04 13:44:27 -0800181 void onGetAppPermissions(@NonNull List<RuntimePermissionPresentationInfo> permissions);
Svet Ganovae0e03a2016-02-25 18:22:10 -0800182 }
183
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -0800184 /**
Philip P. Moltmannbc054d82018-12-21 09:41:58 -0800185 * Callback for delivering the result of {@link #countPermissionApps}.
Philip P. Moltmann78689522018-12-17 20:45:40 -0800186 *
187 * @hide
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -0800188 */
189 public interface OnCountPermissionAppsResultCallback {
190 /**
Philip P. Moltmanne1436e852019-01-31 14:22:39 -0800191 * The result for {@link #countPermissionApps(List, int,
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -0800192 * OnCountPermissionAppsResultCallback, Handler)}.
193 *
194 * @param numApps The number of apps that have one of the permissions
195 */
196 void onCountPermissionApps(int numApps);
197 }
198
Joel Galenson5f63b832018-12-19 15:38:04 -0800199 /**
200 * Callback for delivering the result of {@link #getPermissionUsages}.
201 *
202 * @hide
203 */
204 public interface OnPermissionUsageResultCallback {
205 /**
206 * The result for {@link #getPermissionUsages}.
207 *
208 * @param users The users list.
209 */
210 void onPermissionUsageResult(@NonNull List<RuntimePermissionUsageInfo> users);
211 }
212
Philip P. Moltmann78689522018-12-17 20:45:40 -0800213 private final @NonNull Context mContext;
Philip P. Moltmanncfd2fbc2019-02-08 13:07:57 -0800214 private final @NonNull RemoteService mRemoteService;
Svet Ganovae0e03a2016-02-25 18:22:10 -0800215
Philip P. Moltmann5e5c41e52019-01-13 09:53:12 -0800216 /**
217 * Create a new {@link PermissionControllerManager}.
218 *
219 * @param context to create the manager for
220 *
221 * @hide
222 */
Philip P. Moltmannbc054d82018-12-21 09:41:58 -0800223 public PermissionControllerManager(@NonNull Context context) {
Philip P. Moltmann5e5c41e52019-01-13 09:53:12 -0800224 synchronized (sLock) {
Philip P. Moltmanncfd2fbc2019-02-08 13:07:57 -0800225 RemoteService remoteService = sRemoteServices.get(context.getUserId(), null);
226 if (remoteService == null) {
Philip P. Moltmann5e5c41e52019-01-13 09:53:12 -0800227 Intent intent = new Intent(SERVICE_INTERFACE);
228 intent.setPackage(context.getPackageManager().getPermissionControllerPackageName());
229 ResolveInfo serviceInfo = context.getPackageManager().resolveService(intent, 0);
230
Philip P. Moltmanncfd2fbc2019-02-08 13:07:57 -0800231 remoteService = new RemoteService(context.getApplicationContext(),
232 serviceInfo.getComponentInfo().getComponentName(), context.getUser());
233 sRemoteServices.put(context.getUserId(), remoteService);
Philip P. Moltmann5e5c41e52019-01-13 09:53:12 -0800234 }
Philip P. Moltmanncfd2fbc2019-02-08 13:07:57 -0800235
236 mRemoteService = remoteService;
Philip P. Moltmann5e5c41e52019-01-13 09:53:12 -0800237 }
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800238
Philip P. Moltmann78689522018-12-17 20:45:40 -0800239 mContext = context;
Svet Ganovae0e03a2016-02-25 18:22:10 -0800240 }
241
242 /**
Philip P. Moltmann78689522018-12-17 20:45:40 -0800243 * Revoke a set of runtime permissions for various apps.
244 *
245 * @param request The permissions to revoke as {@code Map<packageName, List<permission>>}
246 * @param doDryRun Compute the permissions that would be revoked, but not actually revoke them
247 * @param reason Why the permission should be revoked
248 * @param executor Executor on which to invoke the callback
249 * @param callback Callback to receive the result
250 */
251 @RequiresPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
252 public void revokeRuntimePermissions(@NonNull Map<String, List<String>> request,
253 boolean doDryRun, @Reason int reason, @NonNull @CallbackExecutor Executor executor,
254 @NonNull OnRevokeRuntimePermissionsCallback callback) {
255 // Check input to fail immediately instead of inside the async request
256 checkNotNull(executor);
257 checkNotNull(callback);
258 checkNotNull(request);
259 for (Map.Entry<String, List<String>> appRequest : request.entrySet()) {
260 checkNotNull(appRequest.getKey());
261 checkCollectionElementsNotNull(appRequest.getValue(), "permissions");
262 }
263
264 // Check required permission to fail immediately instead of inside the oneway binder call
265 if (mContext.checkSelfPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
266 != PackageManager.PERMISSION_GRANTED) {
267 throw new SecurityException(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS
268 + " required");
269 }
270
Philip P. Moltmanncfd2fbc2019-02-08 13:07:57 -0800271 mRemoteService.scheduleRequest(new PendingRevokeRuntimePermissionRequest(mRemoteService,
Philip P. Moltmann78689522018-12-17 20:45:40 -0800272 request, doDryRun, reason, mContext.getPackageName(), executor, callback));
273 }
274
275 /**
Philip P. Moltmann41df9f92019-02-08 13:07:57 -0800276 * Set the runtime permission state from a device admin.
277 *
278 * @param callerPackageName The package name of the admin requesting the change
279 * @param packageName Package the permission belongs to
280 * @param permission Permission to change
281 * @param grantState State to set the permission into
282 * @param executor Executor to run the {@code callback} on
283 * @param callback The callback
284 *
285 * @hide
286 */
287 @RequiresPermission(allOf = {Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
288 Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
289 Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY},
290 conditional = true)
291 public void setRuntimePermissionGrantStateByDeviceAdmin(@NonNull String callerPackageName,
292 @NonNull String packageName, @NonNull String permission,
293 @PermissionGrantState int grantState, @NonNull @CallbackExecutor Executor executor,
294 @NonNull Consumer<Boolean> callback) {
295 checkStringNotEmpty(callerPackageName);
296 checkStringNotEmpty(packageName);
297 checkStringNotEmpty(permission);
298 checkArgument(grantState == PERMISSION_GRANT_STATE_GRANTED
299 || grantState == PERMISSION_GRANT_STATE_DENIED
300 || grantState == PERMISSION_GRANT_STATE_DEFAULT);
301 checkNotNull(executor);
302 checkNotNull(callback);
303
304 mRemoteService.scheduleRequest(new PendingSetRuntimePermissionGrantStateByDeviceAdmin(
305 mRemoteService, callerPackageName, packageName, permission, grantState, executor,
306 callback));
307 }
308
309 /**
Philip P. Moltmann97142e22019-01-10 17:03:42 -0800310 * Create a backup of the runtime permissions.
311 *
312 * @param user The user to be backed up
313 * @param executor Executor on which to invoke the callback
314 * @param callback Callback to receive the result
315 *
316 * @hide
317 */
318 @RequiresPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS)
319 public void getRuntimePermissionBackup(@NonNull UserHandle user,
320 @NonNull @CallbackExecutor Executor executor,
321 @NonNull OnGetRuntimePermissionBackupCallback callback) {
Philip P. Moltmann9b12e372019-01-20 09:01:19 -0800322 checkNotNull(user);
Philip P. Moltmann97142e22019-01-10 17:03:42 -0800323 checkNotNull(executor);
324 checkNotNull(callback);
325
Philip P. Moltmanncfd2fbc2019-02-08 13:07:57 -0800326 mRemoteService.scheduleRequest(new PendingGetRuntimePermissionBackup(mRemoteService,
Philip P. Moltmann97142e22019-01-10 17:03:42 -0800327 user, executor, callback));
328 }
329
330 /**
Philip P. Moltmann7532c612019-01-20 09:01:19 -0800331 * Restore a backup of the runtime permissions.
332 *
333 * @param backup the backup to restore. The backup is sent asynchronously, hence it should not
334 * be modified after calling this method.
335 * @param user The user to be restore
336 *
337 * @hide
338 */
339 @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
340 public void restoreRuntimePermissionBackup(@NonNull byte[] backup, @NonNull UserHandle user) {
341 checkNotNull(backup);
342 checkNotNull(user);
343
Philip P. Moltmanncfd2fbc2019-02-08 13:07:57 -0800344 mRemoteService.scheduleAsyncRequest(
345 new PendingRestoreRuntimePermissionBackup(mRemoteService, backup, user));
Philip P. Moltmann7532c612019-01-20 09:01:19 -0800346 }
347
348 /**
349 * Restore a backup of the runtime permissions that has been delayed.
350 *
351 * @param packageName The package that is ready to have it's permissions restored.
352 * @param user The user to restore
353 * @param executor Executor to execute the callback on
354 * @param callback Is called with {@code true} iff there is still more delayed backup left
355 *
356 * @hide
357 */
358 @RequiresPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
359 public void restoreDelayedRuntimePermissionBackup(@NonNull String packageName,
360 @NonNull UserHandle user,
361 @NonNull @CallbackExecutor Executor executor,
362 @NonNull Consumer<Boolean> callback) {
363 checkNotNull(packageName);
364 checkNotNull(user);
365 checkNotNull(executor);
366 checkNotNull(callback);
367
Philip P. Moltmanncfd2fbc2019-02-08 13:07:57 -0800368 mRemoteService.scheduleRequest(
369 new PendingRestoreDelayedRuntimePermissionBackup(mRemoteService, packageName,
Philip P. Moltmann7532c612019-01-20 09:01:19 -0800370 user, executor, callback));
371 }
372
373 /**
Svet Ganovae0e03a2016-02-25 18:22:10 -0800374 * Gets the runtime permissions for an app.
375 *
376 * @param packageName The package for which to query.
377 * @param callback Callback to receive the result.
378 * @param handler Handler on which to invoke the callback.
Philip P. Moltmann78689522018-12-17 20:45:40 -0800379 *
380 * @hide
Svet Ganovae0e03a2016-02-25 18:22:10 -0800381 */
Philip P. Moltmannbc054d82018-12-21 09:41:58 -0800382 @RequiresPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS)
Svet Ganovae0e03a2016-02-25 18:22:10 -0800383 public void getAppPermissions(@NonNull String packageName,
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -0800384 @NonNull OnGetAppPermissionResultCallback callback, @Nullable Handler handler) {
Philip P. Moltmann44689732018-12-04 10:08:19 -0800385 checkNotNull(packageName);
386 checkNotNull(callback);
387
Philip P. Moltmanncfd2fbc2019-02-08 13:07:57 -0800388 mRemoteService.scheduleRequest(new PendingGetAppPermissionRequest(mRemoteService,
389 packageName, callback, handler == null ? mRemoteService.getHandler() : handler));
Svet Ganovae0e03a2016-02-25 18:22:10 -0800390 }
391
jackqdyuleia90bfb52017-06-22 16:27:29 -0700392 /**
393 * Revoke the permission {@code permissionName} for app {@code packageName}
394 *
395 * @param packageName The package for which to revoke
396 * @param permissionName The permission to revoke
Philip P. Moltmann78689522018-12-17 20:45:40 -0800397 *
398 * @hide
jackqdyuleia90bfb52017-06-22 16:27:29 -0700399 */
Philip P. Moltmannbc054d82018-12-21 09:41:58 -0800400 @RequiresPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
Philip P. Moltmann44689732018-12-04 10:08:19 -0800401 public void revokeRuntimePermission(@NonNull String packageName,
402 @NonNull String permissionName) {
403 checkNotNull(packageName);
404 checkNotNull(permissionName);
jackqdyuleia90bfb52017-06-22 16:27:29 -0700405
Philip P. Moltmanncfd2fbc2019-02-08 13:07:57 -0800406 mRemoteService.scheduleAsyncRequest(new PendingRevokeAppPermissionRequest(packageName,
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800407 permissionName));
jackqdyuleia90bfb52017-06-22 16:27:29 -0700408 }
409
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -0800410 /**
411 * Count how many apps have one of a set of permissions.
412 *
413 * @param permissionNames The permissions the app might have
Philip P. Moltmanne1436e852019-01-31 14:22:39 -0800414 * @param flags Modify which apps to count. By default all non-system apps that request a
415 * permission are counted
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -0800416 * @param callback Callback to receive the result
417 * @param handler Handler on which to invoke the callback
Philip P. Moltmann78689522018-12-17 20:45:40 -0800418 *
419 * @hide
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -0800420 */
Philip P. Moltmannbc054d82018-12-21 09:41:58 -0800421 @RequiresPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS)
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -0800422 public void countPermissionApps(@NonNull List<String> permissionNames,
Philip P. Moltmanne1436e852019-01-31 14:22:39 -0800423 @CountPermissionAppsFlag int flags,
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -0800424 @NonNull OnCountPermissionAppsResultCallback callback, @Nullable Handler handler) {
425 checkCollectionElementsNotNull(permissionNames, "permissionNames");
Philip P. Moltmanne1436e852019-01-31 14:22:39 -0800426 checkFlagsArgument(flags, COUNT_WHEN_SYSTEM | COUNT_ONLY_WHEN_GRANTED);
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -0800427 checkNotNull(callback);
428
Philip P. Moltmanncfd2fbc2019-02-08 13:07:57 -0800429 mRemoteService.scheduleRequest(new PendingCountPermissionAppsRequest(mRemoteService,
Philip P. Moltmanne1436e852019-01-31 14:22:39 -0800430 permissionNames, flags, callback,
Philip P. Moltmanncfd2fbc2019-02-08 13:07:57 -0800431 handler == null ? mRemoteService.getHandler() : handler));
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -0800432 }
433
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800434 /**
Joel Galenson5f63b832018-12-19 15:38:04 -0800435 * Count how many apps have used permissions.
436 *
437 * @param countSystem Also count system apps
438 * @param numMillis The number of milliseconds in the past to check for uses
439 * @param executor Executor on which to invoke the callback
440 * @param callback Callback to receive the result
441 *
442 * @hide
443 */
444 @RequiresPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS)
445 public void getPermissionUsages(boolean countSystem, long numMillis,
446 @NonNull @CallbackExecutor Executor executor,
447 @NonNull OnPermissionUsageResultCallback callback) {
448 checkArgumentNonnegative(numMillis);
449 checkNotNull(executor);
450 checkNotNull(callback);
451
Philip P. Moltmanncfd2fbc2019-02-08 13:07:57 -0800452 mRemoteService.scheduleRequest(new PendingGetPermissionUsagesRequest(mRemoteService,
Joel Galenson5f63b832018-12-19 15:38:04 -0800453 countSystem, numMillis, executor, callback));
454 }
455
456 /**
Hai Zhang19821872019-01-23 16:48:40 -0800457 * Check whether an application is qualified for a role.
458 *
459 * @param roleName name of the role to check for
460 * @param packageName package name of the application to check for
461 * @param executor Executor on which to invoke the callback
462 * @param callback Callback to receive the result
463 *
464 * @hide
465 */
466 @RequiresPermission(Manifest.permission.MANAGE_ROLE_HOLDERS)
467 public void isApplicationQualifiedForRole(@NonNull String roleName, @NonNull String packageName,
468 @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
469 checkStringNotEmpty(roleName);
470 checkStringNotEmpty(packageName);
471 checkNotNull(executor);
472 checkNotNull(callback);
473
Philip P. Moltmanncfd2fbc2019-02-08 13:07:57 -0800474 mRemoteService.scheduleRequest(new PendingIsApplicationQualifiedForRoleRequest(
475 mRemoteService, roleName, packageName, executor, callback));
Hai Zhang19821872019-01-23 16:48:40 -0800476 }
477
478 /**
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800479 * A connection to the remote service
480 */
481 static final class RemoteService extends
Philip P. Moltmannbc054d82018-12-21 09:41:58 -0800482 AbstractMultiplePendingRequestsRemoteService<RemoteService, IPermissionController> {
Svet Ganovae0e03a2016-02-25 18:22:10 -0800483 private static final long UNBIND_TIMEOUT_MILLIS = 10000;
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800484 private static final long MESSAGE_TIMEOUT_MILLIS = 30000;
Svet Ganovae0e03a2016-02-25 18:22:10 -0800485
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800486 /**
487 * Create a connection to the remote service
488 *
489 * @param context A context to use
490 * @param componentName The component of the service to connect to
Philip P. Moltmanncfd2fbc2019-02-08 13:07:57 -0800491 * @param user User the remote service should be connected as
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800492 */
Philip P. Moltmanncfd2fbc2019-02-08 13:07:57 -0800493 RemoteService(@NonNull Context context, @NonNull ComponentName componentName,
494 @NonNull UserHandle user) {
495 super(context, SERVICE_INTERFACE, componentName, user.getIdentifier(),
496 service -> Log.e(TAG, "RemoteService " + service + " died"), false, false, 1);
Svet Ganovae0e03a2016-02-25 18:22:10 -0800497 }
498
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800499 /**
500 * @return The default handler used by this service.
501 */
502 Handler getHandler() {
503 return mHandler;
504 }
505
506 @Override
Philip P. Moltmannbc054d82018-12-21 09:41:58 -0800507 protected @NonNull IPermissionController getServiceInterface(@NonNull IBinder binder) {
508 return IPermissionController.Stub.asInterface(binder);
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800509 }
510
511 @Override
512 protected long getTimeoutIdleBindMillis() {
513 return UNBIND_TIMEOUT_MILLIS;
514 }
515
516 @Override
517 protected long getRemoteRequestMillis() {
518 return MESSAGE_TIMEOUT_MILLIS;
519 }
520
521 @Override
Felipe Leme81299d02019-02-21 15:48:50 -0800522 public void scheduleRequest(@NonNull BasePendingRequest<RemoteService,
Philip P. Moltmannbc054d82018-12-21 09:41:58 -0800523 IPermissionController> pendingRequest) {
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800524 super.scheduleRequest(pendingRequest);
525 }
526
527 @Override
Philip P. Moltmannbc054d82018-12-21 09:41:58 -0800528 public void scheduleAsyncRequest(@NonNull AsyncRequest<IPermissionController> request) {
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800529 super.scheduleAsyncRequest(request);
530 }
531 }
532
533 /**
Philip P. Moltmann97142e22019-01-10 17:03:42 -0800534 * Task to read a large amount of data from a remote service.
535 */
536 private static class FileReaderTask<Callback extends Consumer<byte[]>>
537 extends AsyncTask<Void, Void, byte[]> {
538 private ParcelFileDescriptor mLocalPipe;
539 private ParcelFileDescriptor mRemotePipe;
540
541 private final @NonNull Callback mCallback;
542
543 FileReaderTask(@NonNull Callback callback) {
544 mCallback = callback;
545 }
546
547 @Override
548 protected void onPreExecute() {
549 ParcelFileDescriptor[] pipe;
550 try {
551 pipe = ParcelFileDescriptor.createPipe();
552 } catch (IOException e) {
553 Log.e(TAG, "Could not create pipe needed to get runtime permission backup", e);
554 return;
555 }
556
557 mLocalPipe = pipe[0];
558 mRemotePipe = pipe[1];
559 }
560
561 /**
562 * Get the file descriptor the remote service should write the data to.
563 *
564 * <p>Needs to be closed <u>locally</u> before the FileReader can finish.
565 *
566 * @return The file the data should be written to
567 */
568 ParcelFileDescriptor getRemotePipe() {
569 return mRemotePipe;
570 }
571
572 @Override
573 protected byte[] doInBackground(Void... ignored) {
574 ByteArrayOutputStream combinedBuffer = new ByteArrayOutputStream();
575
576 try (InputStream in = new ParcelFileDescriptor.AutoCloseInputStream(mLocalPipe)) {
577 byte[] buffer = new byte[16 * 1024];
578
579 while (!isCancelled()) {
580 int numRead = in.read(buffer);
581 if (numRead == -1) {
582 break;
583 }
584
585 combinedBuffer.write(buffer, 0, numRead);
586 }
587 } catch (IOException | NullPointerException e) {
588 Log.e(TAG, "Error reading runtime permission backup", e);
589 combinedBuffer.reset();
590 }
591
592 return combinedBuffer.toByteArray();
593 }
594
595 /**
596 * Interrupt the reading of the data.
597 *
598 * <p>Needs to be called when canceling this task as it might be hung.
599 */
600 void interruptRead() {
601 IoUtils.closeQuietly(mLocalPipe);
602 }
603
604 @Override
605 protected void onCancelled() {
606 onPostExecute(new byte[]{});
607 }
608
609 @Override
610 protected void onPostExecute(byte[] backup) {
611 IoUtils.closeQuietly(mLocalPipe);
612 mCallback.accept(backup);
613 }
614 }
615
616 /**
Philip P. Moltmann7532c612019-01-20 09:01:19 -0800617 * Task to send a large amount of data to a remote service.
618 */
619 private static class FileWriterTask extends AsyncTask<byte[], Void, Void> {
620 private static final int CHUNK_SIZE = 4 * 1024;
621
622 private ParcelFileDescriptor mLocalPipe;
623 private ParcelFileDescriptor mRemotePipe;
624
625 @Override
626 protected void onPreExecute() {
627 ParcelFileDescriptor[] pipe;
628 try {
629 pipe = ParcelFileDescriptor.createPipe();
630 } catch (IOException e) {
631 Log.e(TAG, "Could not create pipe needed to send runtime permission backup",
632 e);
633 return;
634 }
635
636 mRemotePipe = pipe[0];
637 mLocalPipe = pipe[1];
638 }
639
640 /**
641 * Get the file descriptor the remote service should read the data from.
642 *
643 * @return The file the data should be read from
644 */
645 ParcelFileDescriptor getRemotePipe() {
646 return mRemotePipe;
647 }
648
649 /**
650 * Send the data to the remove service.
651 *
652 * @param in The data to send
653 *
654 * @return ignored
655 */
656 @Override
657 protected Void doInBackground(byte[]... in) {
658 byte[] buffer = in[0];
659 try (OutputStream out = new ParcelFileDescriptor.AutoCloseOutputStream(mLocalPipe)) {
660 for (int offset = 0; offset < buffer.length; offset += CHUNK_SIZE) {
661 out.write(buffer, offset, min(CHUNK_SIZE, buffer.length - offset));
662 }
663 } catch (IOException | NullPointerException e) {
664 Log.e(TAG, "Error sending runtime permission backup", e);
665 }
666
667 return null;
668 }
669
670 /**
671 * Interrupt the send of the data.
672 *
673 * <p>Needs to be called when canceling this task as it might be hung.
674 */
Philip P. Moltmann48456672019-01-20 13:14:03 -0800675 void interruptWrite() {
Philip P. Moltmann7532c612019-01-20 09:01:19 -0800676 IoUtils.closeQuietly(mLocalPipe);
677 }
678
679 @Override
680 protected void onCancelled() {
681 onPostExecute(null);
682 }
683
684 @Override
685 protected void onPostExecute(Void ignored) {
686 IoUtils.closeQuietly(mLocalPipe);
687 }
688 }
689
690 /**
Philip P. Moltmann78689522018-12-17 20:45:40 -0800691 * Request for {@link #revokeRuntimePermissions}
692 */
693 private static final class PendingRevokeRuntimePermissionRequest extends
694 AbstractRemoteService.PendingRequest<RemoteService, IPermissionController> {
695 private final @NonNull Map<String, List<String>> mRequest;
696 private final boolean mDoDryRun;
697 private final int mReason;
698 private final @NonNull String mCallingPackage;
Philip P. Moltmann1117ca32019-01-10 17:03:42 -0800699 private final @NonNull Executor mExecutor;
Philip P. Moltmann78689522018-12-17 20:45:40 -0800700 private final @NonNull OnRevokeRuntimePermissionsCallback mCallback;
701
702 private final @NonNull RemoteCallback mRemoteCallback;
703
704 private PendingRevokeRuntimePermissionRequest(@NonNull RemoteService service,
705 @NonNull Map<String, List<String>> request, boolean doDryRun,
706 @Reason int reason, @NonNull String callingPackage,
707 @NonNull @CallbackExecutor Executor executor,
708 @NonNull OnRevokeRuntimePermissionsCallback callback) {
709 super(service);
710
711 mRequest = request;
712 mDoDryRun = doDryRun;
713 mReason = reason;
714 mCallingPackage = callingPackage;
Philip P. Moltmann1117ca32019-01-10 17:03:42 -0800715 mExecutor = executor;
Philip P. Moltmann78689522018-12-17 20:45:40 -0800716 mCallback = callback;
717
718 mRemoteCallback = new RemoteCallback(result -> executor.execute(() -> {
719 long token = Binder.clearCallingIdentity();
720 try {
721 Map<String, List<String>> revoked = new ArrayMap<>();
722 try {
723 Bundle bundleizedRevoked = result.getBundle(KEY_RESULT);
724
725 for (String packageName : bundleizedRevoked.keySet()) {
726 Preconditions.checkNotNull(packageName);
727
728 ArrayList<String> permissions =
729 bundleizedRevoked.getStringArrayList(packageName);
730 Preconditions.checkCollectionElementsNotNull(permissions,
731 "permissions");
732
733 revoked.put(packageName, permissions);
734 }
735 } catch (Exception e) {
736 Log.e(TAG, "Could not read result when revoking runtime permissions", e);
737 }
738
739 callback.onRevokeRuntimePermissions(revoked);
740 } finally {
741 Binder.restoreCallingIdentity(token);
742
743 finish();
744 }
745 }), null);
746 }
747
748 @Override
749 protected void onTimeout(RemoteService remoteService) {
Philip P. Moltmann1117ca32019-01-10 17:03:42 -0800750 long token = Binder.clearCallingIdentity();
751 try {
752 mExecutor.execute(
753 () -> mCallback.onRevokeRuntimePermissions(Collections.emptyMap()));
754 } finally {
755 Binder.restoreCallingIdentity(token);
756 }
Philip P. Moltmann78689522018-12-17 20:45:40 -0800757 }
758
759 @Override
760 public void run() {
761 Bundle bundledizedRequest = new Bundle();
762 for (Map.Entry<String, List<String>> appRequest : mRequest.entrySet()) {
763 bundledizedRequest.putStringArrayList(appRequest.getKey(),
764 new ArrayList<>(appRequest.getValue()));
765 }
766
767 try {
768 getService().getServiceInterface().revokeRuntimePermissions(bundledizedRequest,
769 mDoDryRun, mReason, mCallingPackage, mRemoteCallback);
770 } catch (RemoteException e) {
771 Log.e(TAG, "Error revoking runtime permission", e);
772 }
773 }
774 }
775
776 /**
Philip P. Moltmann97142e22019-01-10 17:03:42 -0800777 * Request for {@link #getRuntimePermissionBackup}
778 */
779 private static final class PendingGetRuntimePermissionBackup extends
780 AbstractRemoteService.PendingRequest<RemoteService, IPermissionController>
781 implements Consumer<byte[]> {
782 private final @NonNull FileReaderTask<PendingGetRuntimePermissionBackup> mBackupReader;
783 private final @NonNull Executor mExecutor;
784 private final @NonNull OnGetRuntimePermissionBackupCallback mCallback;
785 private final @NonNull UserHandle mUser;
786
787 private PendingGetRuntimePermissionBackup(@NonNull RemoteService service,
788 @NonNull UserHandle user, @NonNull @CallbackExecutor Executor executor,
789 @NonNull OnGetRuntimePermissionBackupCallback callback) {
790 super(service);
791
792 mUser = user;
793 mExecutor = executor;
794 mCallback = callback;
795
796 mBackupReader = new FileReaderTask<>(this);
797 }
798
799 @Override
800 protected void onTimeout(RemoteService remoteService) {
801 mBackupReader.cancel(true);
802 mBackupReader.interruptRead();
803 }
804
805 @Override
806 public void run() {
807 mBackupReader.execute();
808
809 ParcelFileDescriptor remotePipe = mBackupReader.getRemotePipe();
810 try {
811 getService().getServiceInterface().getRuntimePermissionBackup(mUser, remotePipe);
812 } catch (RemoteException e) {
813 Log.e(TAG, "Error getting runtime permission backup", e);
814 } finally {
815 // Remote pipe end is duped by binder call. Local copy is not needed anymore
816 IoUtils.closeQuietly(remotePipe);
817 }
818 }
819
820 /**
821 * Called when the {@link #mBackupReader} finished reading the file.
822 *
823 * @param backup The data read
824 */
825 @Override
826 public void accept(byte[] backup) {
827 long token = Binder.clearCallingIdentity();
828 try {
829 mExecutor.execute(() -> mCallback.onGetRuntimePermissionsBackup(backup));
830 } finally {
831 Binder.restoreCallingIdentity(token);
832 }
833
834 finish();
835 }
836 }
837
838 /**
Philip P. Moltmann41df9f92019-02-08 13:07:57 -0800839 * Request for {@link #getRuntimePermissionBackup}
840 */
841 private static final class PendingSetRuntimePermissionGrantStateByDeviceAdmin extends
842 AbstractRemoteService.PendingRequest<RemoteService, IPermissionController> {
843 private final @NonNull String mCallerPackageName;
844 private final @NonNull String mPackageName;
845 private final @NonNull String mPermission;
846 private final @PermissionGrantState int mGrantState;
847
848 private final @NonNull Executor mExecutor;
849 private final @NonNull Consumer<Boolean> mCallback;
850 private final @NonNull RemoteCallback mRemoteCallback;
851
852 private PendingSetRuntimePermissionGrantStateByDeviceAdmin(@NonNull RemoteService service,
853 @NonNull String callerPackageName, @NonNull String packageName,
854 @NonNull String permission, @PermissionGrantState int grantState,
855 @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
856 super(service);
857
858 mCallerPackageName = callerPackageName;
859 mPackageName = packageName;
860 mPermission = permission;
861 mGrantState = grantState;
862 mExecutor = executor;
863 mCallback = callback;
864
865 mRemoteCallback = new RemoteCallback(result -> executor.execute(() -> {
866 long token = Binder.clearCallingIdentity();
867 try {
868 callback.accept(result.getBoolean(KEY_RESULT, false));
869 } finally {
870 Binder.restoreCallingIdentity(token);
871
872 finish();
873 }
874 }), null);
875 }
876
877 @Override
878 protected void onTimeout(RemoteService remoteService) {
879 long token = Binder.clearCallingIdentity();
880 try {
881 mExecutor.execute(() -> mCallback.accept(false));
882 } finally {
883 Binder.restoreCallingIdentity(token);
884 }
885 }
886
887 @Override
888 public void run() {
889 try {
890 getService().getServiceInterface().setRuntimePermissionGrantStateByDeviceAdmin(
891 mCallerPackageName, mPackageName, mPermission, mGrantState, mRemoteCallback);
892 } catch (RemoteException e) {
893 Log.e(TAG, "Error setting permissions state for device admin " + mPackageName,
894 e);
895 }
896 }
897 }
898
899 /**
Philip P. Moltmann7532c612019-01-20 09:01:19 -0800900 * Request for {@link #restoreRuntimePermissionBackup}
901 */
902 private static final class PendingRestoreRuntimePermissionBackup implements
903 AbstractRemoteService.AsyncRequest<IPermissionController> {
904 private final @NonNull FileWriterTask mBackupSender;
905 private final @NonNull byte[] mBackup;
906 private final @NonNull UserHandle mUser;
907
908 private PendingRestoreRuntimePermissionBackup(@NonNull RemoteService service,
909 @NonNull byte[] backup, @NonNull UserHandle user) {
910 mBackup = backup;
911 mUser = user;
912
913 mBackupSender = new FileWriterTask();
914 }
915
916 @Override
917 public void run(@NonNull IPermissionController service) {
Philip P. Moltmann48456672019-01-20 13:14:03 -0800918 mBackupSender.execute(mBackup);
919
Philip P. Moltmann7532c612019-01-20 09:01:19 -0800920 ParcelFileDescriptor remotePipe = mBackupSender.getRemotePipe();
921 try {
922 service.restoreRuntimePermissionBackup(mUser, remotePipe);
923 } catch (RemoteException e) {
924 Log.e(TAG, "Error sending runtime permission backup", e);
925 mBackupSender.cancel(false);
Philip P. Moltmann48456672019-01-20 13:14:03 -0800926 mBackupSender.interruptWrite();
Philip P. Moltmann7532c612019-01-20 09:01:19 -0800927 } finally {
928 // Remote pipe end is duped by binder call. Local copy is not needed anymore
929 IoUtils.closeQuietly(remotePipe);
930 }
Philip P. Moltmann7532c612019-01-20 09:01:19 -0800931 }
932 }
933
934 /**
935 * Request for {@link #restoreDelayedRuntimePermissionBackup(String, UserHandle, Executor,
936 * Consumer<Boolean>)}
937 */
938 private static final class PendingRestoreDelayedRuntimePermissionBackup extends
939 AbstractRemoteService.PendingRequest<RemoteService, IPermissionController> {
940 private final @NonNull String mPackageName;
941 private final @NonNull UserHandle mUser;
942 private final @NonNull Executor mExecutor;
943 private final @NonNull Consumer<Boolean> mCallback;
944
945 private final @NonNull RemoteCallback mRemoteCallback;
946
947 private PendingRestoreDelayedRuntimePermissionBackup(@NonNull RemoteService service,
948 @NonNull String packageName, @NonNull UserHandle user, @NonNull Executor executor,
949 @NonNull Consumer<Boolean> callback) {
950 super(service);
951
952 mPackageName = packageName;
953 mUser = user;
954 mExecutor = executor;
955 mCallback = callback;
956
957 mRemoteCallback = new RemoteCallback(result -> executor.execute(() -> {
958 long token = Binder.clearCallingIdentity();
959 try {
960 callback.accept(result.getBoolean(KEY_RESULT, false));
961 } finally {
962 Binder.restoreCallingIdentity(token);
963
964 finish();
965 }
966 }), null);
967 }
968
969 @Override
970 protected void onTimeout(RemoteService remoteService) {
971 long token = Binder.clearCallingIdentity();
972 try {
973 mExecutor.execute(
974 () -> mCallback.accept(true));
975 } finally {
976 Binder.restoreCallingIdentity(token);
977 }
978 }
979
980 @Override
981 public void run() {
982 try {
983 getService().getServiceInterface().restoreDelayedRuntimePermissionBackup(
984 mPackageName, mUser, mRemoteCallback);
985 } catch (RemoteException e) {
986 Log.e(TAG, "Error restoring delayed permissions for " + mPackageName, e);
987 }
988 }
989 }
990
991 /**
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800992 * Request for {@link #getAppPermissions}
993 */
994 private static final class PendingGetAppPermissionRequest extends
Philip P. Moltmannbc054d82018-12-21 09:41:58 -0800995 AbstractRemoteService.PendingRequest<RemoteService, IPermissionController> {
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800996 private final @NonNull String mPackageName;
997 private final @NonNull OnGetAppPermissionResultCallback mCallback;
998
999 private final @NonNull RemoteCallback mRemoteCallback;
1000
1001 private PendingGetAppPermissionRequest(@NonNull RemoteService service,
1002 @NonNull String packageName, @NonNull OnGetAppPermissionResultCallback callback,
1003 @NonNull Handler handler) {
1004 super(service);
1005
1006 mPackageName = packageName;
1007 mCallback = callback;
1008
1009 mRemoteCallback = new RemoteCallback(result -> {
1010 final List<RuntimePermissionPresentationInfo> reportedPermissions;
1011 List<RuntimePermissionPresentationInfo> permissions = null;
1012 if (result != null) {
1013 permissions = result.getParcelableArrayList(KEY_RESULT);
Svet Ganovae0e03a2016-02-25 18:22:10 -08001014 }
Philip P. Moltmann22b84982018-12-17 20:45:40 -08001015 if (permissions == null) {
1016 permissions = Collections.emptyList();
1017 }
1018 reportedPermissions = permissions;
1019
1020 callback.onGetAppPermissions(reportedPermissions);
1021
1022 finish();
1023 }, handler);
Svet Ganovae0e03a2016-02-25 18:22:10 -08001024 }
1025
1026 @Override
Philip P. Moltmann22b84982018-12-17 20:45:40 -08001027 protected void onTimeout(RemoteService remoteService) {
1028 mCallback.onGetAppPermissions(Collections.emptyList());
Svet Ganovae0e03a2016-02-25 18:22:10 -08001029 }
1030
1031 @Override
Philip P. Moltmann22b84982018-12-17 20:45:40 -08001032 public void run() {
Philip P. Moltmann44689732018-12-04 10:08:19 -08001033 try {
Philip P. Moltmann22b84982018-12-17 20:45:40 -08001034 getService().getServiceInterface().getAppPermissions(mPackageName, mRemoteCallback);
1035 } catch (RemoteException e) {
1036 Log.e(TAG, "Error getting app permission", e);
Philip P. Moltmann44689732018-12-04 10:08:19 -08001037 }
1038 }
Philip P. Moltmann22b84982018-12-17 20:45:40 -08001039 }
jackqdyuleia90bfb52017-06-22 16:27:29 -07001040
Philip P. Moltmann22b84982018-12-17 20:45:40 -08001041 /**
1042 * Request for {@link #revokeRuntimePermission}
1043 */
1044 private static final class PendingRevokeAppPermissionRequest
Philip P. Moltmannbc054d82018-12-21 09:41:58 -08001045 implements AbstractRemoteService.AsyncRequest<IPermissionController> {
Philip P. Moltmann22b84982018-12-17 20:45:40 -08001046 private final @NonNull String mPackageName;
1047 private final @NonNull String mPermissionName;
1048
1049 private PendingRevokeAppPermissionRequest(@NonNull String packageName,
Philip P. Moltmann44689732018-12-04 10:08:19 -08001050 @NonNull String permissionName) {
Philip P. Moltmann22b84982018-12-17 20:45:40 -08001051 mPackageName = packageName;
1052 mPermissionName = permissionName;
Svet Ganovae0e03a2016-02-25 18:22:10 -08001053 }
1054
Philip P. Moltmann22b84982018-12-17 20:45:40 -08001055 @Override
Philip P. Moltmannbc054d82018-12-21 09:41:58 -08001056 public void run(IPermissionController remoteInterface) {
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -08001057 try {
Philip P. Moltmann22b84982018-12-17 20:45:40 -08001058 remoteInterface.revokeRuntimePermission(mPackageName, mPermissionName);
1059 } catch (RemoteException e) {
1060 Log.e(TAG, "Error revoking app permission", e);
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -08001061 }
1062 }
Philip P. Moltmann22b84982018-12-17 20:45:40 -08001063 }
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -08001064
Philip P. Moltmann22b84982018-12-17 20:45:40 -08001065 /**
1066 * Request for {@link #countPermissionApps}
1067 */
1068 private static final class PendingCountPermissionAppsRequest extends
Philip P. Moltmannbc054d82018-12-21 09:41:58 -08001069 AbstractRemoteService.PendingRequest<RemoteService, IPermissionController> {
Philip P. Moltmann22b84982018-12-17 20:45:40 -08001070 private final @NonNull List<String> mPermissionNames;
1071 private final @NonNull OnCountPermissionAppsResultCallback mCallback;
Philip P. Moltmanne1436e852019-01-31 14:22:39 -08001072 private final @CountPermissionAppsFlag int mFlags;
Philip P. Moltmann22b84982018-12-17 20:45:40 -08001073
1074 private final @NonNull RemoteCallback mRemoteCallback;
1075
1076 private PendingCountPermissionAppsRequest(@NonNull RemoteService service,
Philip P. Moltmanne1436e852019-01-31 14:22:39 -08001077 @NonNull List<String> permissionNames, @CountPermissionAppsFlag int flags,
1078 @NonNull OnCountPermissionAppsResultCallback callback, @NonNull Handler handler) {
Philip P. Moltmann22b84982018-12-17 20:45:40 -08001079 super(service);
1080
1081 mPermissionNames = permissionNames;
Philip P. Moltmanne1436e852019-01-31 14:22:39 -08001082 mFlags = flags;
Philip P. Moltmann22b84982018-12-17 20:45:40 -08001083 mCallback = callback;
1084
1085 mRemoteCallback = new RemoteCallback(result -> {
1086 final int numApps;
1087 if (result != null) {
1088 numApps = result.getInt(KEY_RESULT);
1089 } else {
1090 numApps = 0;
Philip P. Moltmann44689732018-12-04 10:08:19 -08001091 }
Philip P. Moltmann22b84982018-12-17 20:45:40 -08001092
1093 callback.onCountPermissionApps(numApps);
1094
1095 finish();
1096 }, handler);
Philip P. Moltmann44689732018-12-04 10:08:19 -08001097 }
1098
Philip P. Moltmann22b84982018-12-17 20:45:40 -08001099 @Override
1100 protected void onTimeout(RemoteService remoteService) {
1101 mCallback.onCountPermissionApps(0);
Svet Ganovae0e03a2016-02-25 18:22:10 -08001102 }
1103
Philip P. Moltmann22b84982018-12-17 20:45:40 -08001104 @Override
1105 public void run() {
1106 try {
1107 getService().getServiceInterface().countPermissionApps(mPermissionNames,
Philip P. Moltmanne1436e852019-01-31 14:22:39 -08001108 mFlags, mRemoteCallback);
Philip P. Moltmann22b84982018-12-17 20:45:40 -08001109 } catch (RemoteException e) {
1110 Log.e(TAG, "Error counting permission apps", e);
1111 }
Svet Ganovae0e03a2016-02-25 18:22:10 -08001112 }
1113 }
Joel Galenson5f63b832018-12-19 15:38:04 -08001114
1115 /**
1116 * Request for {@link #getPermissionUsages}
1117 */
1118 private static final class PendingGetPermissionUsagesRequest extends
1119 AbstractRemoteService.PendingRequest<RemoteService, IPermissionController> {
1120 private final @NonNull OnPermissionUsageResultCallback mCallback;
1121 private final boolean mCountSystem;
1122 private final long mNumMillis;
1123
1124 private final @NonNull RemoteCallback mRemoteCallback;
1125
1126 private PendingGetPermissionUsagesRequest(@NonNull RemoteService service,
1127 boolean countSystem, long numMillis, @NonNull @CallbackExecutor Executor executor,
1128 @NonNull OnPermissionUsageResultCallback callback) {
1129 super(service);
1130
1131 mCountSystem = countSystem;
1132 mNumMillis = numMillis;
1133 mCallback = callback;
1134
1135 mRemoteCallback = new RemoteCallback(result -> executor.execute(() -> {
1136 long token = Binder.clearCallingIdentity();
1137 try {
1138 final List<RuntimePermissionUsageInfo> reportedUsers;
1139 List<RuntimePermissionUsageInfo> users = null;
1140 if (result != null) {
1141 users = result.getParcelableArrayList(KEY_RESULT);
1142 } else {
1143 users = Collections.emptyList();
1144 }
1145 reportedUsers = users;
1146
1147 callback.onPermissionUsageResult(reportedUsers);
1148 } finally {
1149 Binder.restoreCallingIdentity(token);
1150
1151 finish();
1152 }
1153 }), null);
1154 }
1155
1156 @Override
1157 protected void onTimeout(RemoteService remoteService) {
1158 mCallback.onPermissionUsageResult(Collections.emptyList());
1159 }
1160
1161 @Override
1162 public void run() {
1163 try {
1164 getService().getServiceInterface().getPermissionUsages(mCountSystem, mNumMillis,
1165 mRemoteCallback);
1166 } catch (RemoteException e) {
1167 Log.e(TAG, "Error counting permission users", e);
1168 }
1169 }
1170 }
Hai Zhang19821872019-01-23 16:48:40 -08001171
1172 /**
1173 * Request for {@link #isApplicationQualifiedForRole}.
1174 */
1175 private static final class PendingIsApplicationQualifiedForRoleRequest extends
1176 AbstractRemoteService.PendingRequest<RemoteService, IPermissionController> {
1177
1178 private final @NonNull String mRoleName;
1179 private final @NonNull String mPackageName;
1180 private final @NonNull Consumer<Boolean> mCallback;
1181
1182 private final @NonNull RemoteCallback mRemoteCallback;
1183
1184 private PendingIsApplicationQualifiedForRoleRequest(@NonNull RemoteService service,
1185 @NonNull String roleName, @NonNull String packageName,
1186 @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
1187 super(service);
1188
1189 mRoleName = roleName;
1190 mPackageName = packageName;
1191 mCallback = callback;
1192
1193 mRemoteCallback = new RemoteCallback(result -> executor.execute(() -> {
1194 long token = Binder.clearCallingIdentity();
1195 try {
1196 boolean qualified;
1197 if (result != null) {
1198 qualified = result.getBoolean(KEY_RESULT);
1199 } else {
1200 qualified = false;
1201 }
1202 callback.accept(qualified);
1203 } finally {
1204 Binder.restoreCallingIdentity(token);
1205 finish();
1206 }
1207 }), null);
1208 }
1209
1210 @Override
1211 protected void onTimeout(RemoteService remoteService) {
1212 mCallback.accept(false);
1213 }
1214
1215 @Override
1216 public void run() {
1217 try {
1218 getService().getServiceInterface().isApplicationQualifiedForRole(mRoleName,
1219 mPackageName, mRemoteCallback);
1220 } catch (RemoteException e) {
1221 Log.e(TAG, "Error checking whether application qualifies for role", e);
1222 }
1223 }
1224 }
Svet Ganovae0e03a2016-02-25 18:22:10 -08001225}