blob: 66e8666a8a705fd2d72390bb4124c24fe99c0fc6 [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. Moltmannbc054d82018-12-21 09:41:58 -080019import static android.permission.PermissionControllerService.SERVICE_INTERFACE;
Philip P. Moltmann22b84982018-12-17 20:45:40 -080020
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -080021import static com.android.internal.util.Preconditions.checkCollectionElementsNotNull;
Philip P. Moltmann44689732018-12-04 10:08:19 -080022import static com.android.internal.util.Preconditions.checkNotNull;
Philip P. Moltmann44689732018-12-04 10:08:19 -080023
Philip P. Moltmannbc054d82018-12-21 09:41:58 -080024import android.Manifest;
Svet Ganovae0e03a2016-02-25 18:22:10 -080025import android.annotation.NonNull;
26import android.annotation.Nullable;
Philip P. Moltmannbc054d82018-12-21 09:41:58 -080027import android.annotation.RequiresPermission;
28import android.annotation.SystemService;
Svet Ganovae0e03a2016-02-25 18:22:10 -080029import android.content.ComponentName;
30import android.content.Context;
31import android.content.Intent;
Philip P. Moltmann22b84982018-12-17 20:45:40 -080032import android.content.pm.ResolveInfo;
Svet Ganovae0e03a2016-02-25 18:22:10 -080033import android.os.Handler;
34import android.os.IBinder;
Svet Ganovae0e03a2016-02-25 18:22:10 -080035import android.os.RemoteCallback;
36import android.os.RemoteException;
Philip P. Moltmann22b84982018-12-17 20:45:40 -080037import android.os.UserHandle;
Svet Ganovae0e03a2016-02-25 18:22:10 -080038import android.util.Log;
jackqdyuleia90bfb52017-06-22 16:27:29 -070039
Philip P. Moltmann22b84982018-12-17 20:45:40 -080040import com.android.internal.infra.AbstractMultiplePendingRequestsRemoteService;
41import com.android.internal.infra.AbstractRemoteService;
Svet Ganovae0e03a2016-02-25 18:22:10 -080042
Svet Ganovae0e03a2016-02-25 18:22:10 -080043import java.util.Collections;
44import java.util.List;
45
46/**
Philip P. Moltmannbc054d82018-12-21 09:41:58 -080047 * Interface for communicating with the permission controller from system apps. All UI operations
48 * regarding permissions and any changes to the permission state should flow through this
49 * interface.
Svet Ganovae0e03a2016-02-25 18:22:10 -080050 *
51 * @hide
52 */
Philip P. Moltmannbc054d82018-12-21 09:41:58 -080053@SystemService(Context.PERMISSION_CONTROLLER_SERVICE)
54public final class PermissionControllerManager {
55 private static final String TAG = PermissionControllerManager.class.getSimpleName();
Svet Ganovae0e03a2016-02-25 18:22:10 -080056
57 /**
58 * The key for retrieving the result from the returned bundle.
Svet Ganovae0e03a2016-02-25 18:22:10 -080059 */
60 public static final String KEY_RESULT =
Philip P. Moltmannbc054d82018-12-21 09:41:58 -080061 "android.permission.PermissionControllerManager.key.result";
Svet Ganovae0e03a2016-02-25 18:22:10 -080062
63 /**
Philip P. Moltmannbc054d82018-12-21 09:41:58 -080064 * Callback for delivering the result of {@link #getAppPermissions}.
Svet Ganovae0e03a2016-02-25 18:22:10 -080065 */
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -080066 public interface OnGetAppPermissionResultCallback {
Svet Ganovae0e03a2016-02-25 18:22:10 -080067 /**
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -080068 * The result for {@link #getAppPermissions(String, OnGetAppPermissionResultCallback,
69 * Handler)}.
70 *
Svet Ganovae0e03a2016-02-25 18:22:10 -080071 * @param permissions The permissions list.
72 */
Philip P. Moltmanndbf78b82018-12-04 13:44:27 -080073 void onGetAppPermissions(@NonNull List<RuntimePermissionPresentationInfo> permissions);
Svet Ganovae0e03a2016-02-25 18:22:10 -080074 }
75
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -080076 /**
Philip P. Moltmannbc054d82018-12-21 09:41:58 -080077 * Callback for delivering the result of {@link #countPermissionApps}.
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -080078 */
79 public interface OnCountPermissionAppsResultCallback {
80 /**
Philip P. Moltmann22b84982018-12-17 20:45:40 -080081 * The result for {@link #countPermissionApps(List, boolean, boolean,
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -080082 * OnCountPermissionAppsResultCallback, Handler)}.
83 *
84 * @param numApps The number of apps that have one of the permissions
85 */
86 void onCountPermissionApps(int numApps);
87 }
88
Svet Ganovae0e03a2016-02-25 18:22:10 -080089 private final RemoteService mRemoteService;
90
Philip P. Moltmannbc054d82018-12-21 09:41:58 -080091 public PermissionControllerManager(@NonNull Context context) {
Philip P. Moltmann22b84982018-12-17 20:45:40 -080092 Intent intent = new Intent(SERVICE_INTERFACE);
93 intent.setPackage(context.getPackageManager().getPermissionControllerPackageName());
94 ResolveInfo serviceInfo = context.getPackageManager().resolveService(intent, 0);
95
96 mRemoteService = new RemoteService(context,
97 serviceInfo.getComponentInfo().getComponentName());
Svet Ganovae0e03a2016-02-25 18:22:10 -080098 }
99
100 /**
101 * Gets the runtime permissions for an app.
102 *
103 * @param packageName The package for which to query.
104 * @param callback Callback to receive the result.
105 * @param handler Handler on which to invoke the callback.
106 */
Philip P. Moltmannbc054d82018-12-21 09:41:58 -0800107 @RequiresPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS)
Svet Ganovae0e03a2016-02-25 18:22:10 -0800108 public void getAppPermissions(@NonNull String packageName,
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -0800109 @NonNull OnGetAppPermissionResultCallback callback, @Nullable Handler handler) {
Philip P. Moltmann44689732018-12-04 10:08:19 -0800110 checkNotNull(packageName);
111 checkNotNull(callback);
112
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800113 mRemoteService.scheduleRequest(new PendingGetAppPermissionRequest(mRemoteService,
114 packageName, callback, handler == null ? mRemoteService.getHandler() : handler));
Svet Ganovae0e03a2016-02-25 18:22:10 -0800115 }
116
jackqdyuleia90bfb52017-06-22 16:27:29 -0700117 /**
118 * Revoke the permission {@code permissionName} for app {@code packageName}
119 *
120 * @param packageName The package for which to revoke
121 * @param permissionName The permission to revoke
122 */
Philip P. Moltmannbc054d82018-12-21 09:41:58 -0800123 @RequiresPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
Philip P. Moltmann44689732018-12-04 10:08:19 -0800124 public void revokeRuntimePermission(@NonNull String packageName,
125 @NonNull String permissionName) {
126 checkNotNull(packageName);
127 checkNotNull(permissionName);
jackqdyuleia90bfb52017-06-22 16:27:29 -0700128
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800129 mRemoteService.scheduleAsyncRequest(new PendingRevokeAppPermissionRequest(packageName,
130 permissionName));
jackqdyuleia90bfb52017-06-22 16:27:29 -0700131 }
132
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -0800133 /**
134 * Count how many apps have one of a set of permissions.
135 *
136 * @param permissionNames The permissions the app might have
137 * @param countOnlyGranted Count an app only if the permission is granted to the app
138 * @param countSystem Also count system apps
139 * @param callback Callback to receive the result
140 * @param handler Handler on which to invoke the callback
141 */
Philip P. Moltmannbc054d82018-12-21 09:41:58 -0800142 @RequiresPermission(Manifest.permission.GET_RUNTIME_PERMISSIONS)
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -0800143 public void countPermissionApps(@NonNull List<String> permissionNames,
144 boolean countOnlyGranted, boolean countSystem,
145 @NonNull OnCountPermissionAppsResultCallback callback, @Nullable Handler handler) {
146 checkCollectionElementsNotNull(permissionNames, "permissionNames");
147 checkNotNull(callback);
148
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800149 mRemoteService.scheduleRequest(new PendingCountPermissionAppsRequest(mRemoteService,
150 permissionNames, countOnlyGranted, countSystem, callback,
151 handler == null ? mRemoteService.getHandler() : handler));
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -0800152 }
153
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800154 /**
155 * A connection to the remote service
156 */
157 static final class RemoteService extends
Philip P. Moltmannbc054d82018-12-21 09:41:58 -0800158 AbstractMultiplePendingRequestsRemoteService<RemoteService, IPermissionController> {
Svet Ganovae0e03a2016-02-25 18:22:10 -0800159 private static final long UNBIND_TIMEOUT_MILLIS = 10000;
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800160 private static final long MESSAGE_TIMEOUT_MILLIS = 30000;
Svet Ganovae0e03a2016-02-25 18:22:10 -0800161
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800162 /**
163 * Create a connection to the remote service
164 *
165 * @param context A context to use
166 * @param componentName The component of the service to connect to
167 */
168 RemoteService(@NonNull Context context, @NonNull ComponentName componentName) {
169 super(context, SERVICE_INTERFACE, componentName, UserHandle.myUserId(),
170 service -> Log.e(TAG, "RuntimePermPresenterService " + service + " died"),
171 false, false, 1);
Svet Ganovae0e03a2016-02-25 18:22:10 -0800172 }
173
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800174 /**
175 * @return The default handler used by this service.
176 */
177 Handler getHandler() {
178 return mHandler;
179 }
180
181 @Override
Philip P. Moltmannbc054d82018-12-21 09:41:58 -0800182 protected @NonNull IPermissionController getServiceInterface(@NonNull IBinder binder) {
183 return IPermissionController.Stub.asInterface(binder);
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800184 }
185
186 @Override
187 protected long getTimeoutIdleBindMillis() {
188 return UNBIND_TIMEOUT_MILLIS;
189 }
190
191 @Override
192 protected long getRemoteRequestMillis() {
193 return MESSAGE_TIMEOUT_MILLIS;
194 }
195
196 @Override
197 public void scheduleRequest(@NonNull PendingRequest<RemoteService,
Philip P. Moltmannbc054d82018-12-21 09:41:58 -0800198 IPermissionController> pendingRequest) {
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800199 super.scheduleRequest(pendingRequest);
200 }
201
202 @Override
Philip P. Moltmannbc054d82018-12-21 09:41:58 -0800203 public void scheduleAsyncRequest(@NonNull AsyncRequest<IPermissionController> request) {
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800204 super.scheduleAsyncRequest(request);
205 }
206 }
207
208 /**
209 * Request for {@link #getAppPermissions}
210 */
211 private static final class PendingGetAppPermissionRequest extends
Philip P. Moltmannbc054d82018-12-21 09:41:58 -0800212 AbstractRemoteService.PendingRequest<RemoteService, IPermissionController> {
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800213 private final @NonNull String mPackageName;
214 private final @NonNull OnGetAppPermissionResultCallback mCallback;
215
216 private final @NonNull RemoteCallback mRemoteCallback;
217
218 private PendingGetAppPermissionRequest(@NonNull RemoteService service,
219 @NonNull String packageName, @NonNull OnGetAppPermissionResultCallback callback,
220 @NonNull Handler handler) {
221 super(service);
222
223 mPackageName = packageName;
224 mCallback = callback;
225
226 mRemoteCallback = new RemoteCallback(result -> {
227 final List<RuntimePermissionPresentationInfo> reportedPermissions;
228 List<RuntimePermissionPresentationInfo> permissions = null;
229 if (result != null) {
230 permissions = result.getParcelableArrayList(KEY_RESULT);
Svet Ganovae0e03a2016-02-25 18:22:10 -0800231 }
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800232 if (permissions == null) {
233 permissions = Collections.emptyList();
234 }
235 reportedPermissions = permissions;
236
237 callback.onGetAppPermissions(reportedPermissions);
238
239 finish();
240 }, handler);
Svet Ganovae0e03a2016-02-25 18:22:10 -0800241 }
242
243 @Override
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800244 protected void onTimeout(RemoteService remoteService) {
245 mCallback.onGetAppPermissions(Collections.emptyList());
Svet Ganovae0e03a2016-02-25 18:22:10 -0800246 }
247
248 @Override
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800249 public void run() {
Philip P. Moltmann44689732018-12-04 10:08:19 -0800250 try {
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800251 getService().getServiceInterface().getAppPermissions(mPackageName, mRemoteCallback);
252 } catch (RemoteException e) {
253 Log.e(TAG, "Error getting app permission", e);
Philip P. Moltmann44689732018-12-04 10:08:19 -0800254 }
255 }
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800256 }
jackqdyuleia90bfb52017-06-22 16:27:29 -0700257
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800258 /**
259 * Request for {@link #revokeRuntimePermission}
260 */
261 private static final class PendingRevokeAppPermissionRequest
Philip P. Moltmannbc054d82018-12-21 09:41:58 -0800262 implements AbstractRemoteService.AsyncRequest<IPermissionController> {
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800263 private final @NonNull String mPackageName;
264 private final @NonNull String mPermissionName;
265
266 private PendingRevokeAppPermissionRequest(@NonNull String packageName,
Philip P. Moltmann44689732018-12-04 10:08:19 -0800267 @NonNull String permissionName) {
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800268 mPackageName = packageName;
269 mPermissionName = permissionName;
Svet Ganovae0e03a2016-02-25 18:22:10 -0800270 }
271
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800272 @Override
Philip P. Moltmannbc054d82018-12-21 09:41:58 -0800273 public void run(IPermissionController remoteInterface) {
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -0800274 try {
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800275 remoteInterface.revokeRuntimePermission(mPackageName, mPermissionName);
276 } catch (RemoteException e) {
277 Log.e(TAG, "Error revoking app permission", e);
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -0800278 }
279 }
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800280 }
Philip P. Moltmann08cac8e2018-12-04 15:09:59 -0800281
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800282 /**
283 * Request for {@link #countPermissionApps}
284 */
285 private static final class PendingCountPermissionAppsRequest extends
Philip P. Moltmannbc054d82018-12-21 09:41:58 -0800286 AbstractRemoteService.PendingRequest<RemoteService, IPermissionController> {
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800287 private final @NonNull List<String> mPermissionNames;
288 private final @NonNull OnCountPermissionAppsResultCallback mCallback;
289 private final boolean mCountOnlyGranted;
290 private final boolean mCountSystem;
291
292 private final @NonNull RemoteCallback mRemoteCallback;
293
294 private PendingCountPermissionAppsRequest(@NonNull RemoteService service,
295 @NonNull List<String> permissionNames, boolean countOnlyGranted,
296 boolean countSystem, @NonNull OnCountPermissionAppsResultCallback callback,
297 @NonNull Handler handler) {
298 super(service);
299
300 mPermissionNames = permissionNames;
301 mCountOnlyGranted = countOnlyGranted;
302 mCountSystem = countSystem;
303 mCallback = callback;
304
305 mRemoteCallback = new RemoteCallback(result -> {
306 final int numApps;
307 if (result != null) {
308 numApps = result.getInt(KEY_RESULT);
309 } else {
310 numApps = 0;
Philip P. Moltmann44689732018-12-04 10:08:19 -0800311 }
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800312
313 callback.onCountPermissionApps(numApps);
314
315 finish();
316 }, handler);
Philip P. Moltmann44689732018-12-04 10:08:19 -0800317 }
318
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800319 @Override
320 protected void onTimeout(RemoteService remoteService) {
321 mCallback.onCountPermissionApps(0);
Svet Ganovae0e03a2016-02-25 18:22:10 -0800322 }
323
Philip P. Moltmann22b84982018-12-17 20:45:40 -0800324 @Override
325 public void run() {
326 try {
327 getService().getServiceInterface().countPermissionApps(mPermissionNames,
328 mCountOnlyGranted, mCountSystem, mRemoteCallback);
329 } catch (RemoteException e) {
330 Log.e(TAG, "Error counting permission apps", e);
331 }
Svet Ganovae0e03a2016-02-25 18:22:10 -0800332 }
333 }
334}