blob: 1c7596b80fd719f7421606ecf51e6ccb5583c1f8 [file] [log] [blame]
Hai Zhangb7776682018-09-25 15:10:57 -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 com.android.server.role;
18
19import android.Manifest;
20import android.annotation.CheckResult;
Eugene Suslad469fc12018-11-20 17:09:07 -080021import android.annotation.MainThread;
Hai Zhangb7776682018-09-25 15:10:57 -070022import android.annotation.NonNull;
23import android.annotation.Nullable;
24import android.annotation.UserIdInt;
Hai Zhang31d06ba2018-12-06 18:14:42 -080025import android.annotation.WorkerThread;
Hai Zhangb7776682018-09-25 15:10:57 -070026import android.app.ActivityManager;
27import android.app.AppOpsManager;
Hai Zhang31d06ba2018-12-06 18:14:42 -080028import android.app.role.IOnRoleHoldersChangedListener;
Hai Zhangb7776682018-09-25 15:10:57 -070029import android.app.role.IRoleManager;
30import android.app.role.IRoleManagerCallback;
31import android.app.role.RoleManager;
32import android.content.BroadcastReceiver;
33import android.content.Context;
34import android.content.Intent;
35import android.content.IntentFilter;
Eugene Suslaabdefba2018-11-09 18:06:43 -080036import android.content.pm.PackageManagerInternal;
37import android.content.pm.Signature;
Eugene Susla4ab95112018-12-17 14:45:11 -080038import android.os.Binder;
Hai Zhang31d06ba2018-12-06 18:14:42 -080039import android.os.Handler;
40import android.os.RemoteCallbackList;
41import android.os.RemoteException;
Jeff Sharkey6260c582018-11-27 13:05:15 -070042import android.os.ResultReceiver;
43import android.os.ShellCallback;
Hai Zhangb7776682018-09-25 15:10:57 -070044import android.os.UserHandle;
45import android.os.UserManagerInternal;
46import android.text.TextUtils;
47import android.util.ArraySet;
Eugene Suslaabdefba2018-11-09 18:06:43 -080048import android.util.PackageUtils;
Hai Zhangb7776682018-09-25 15:10:57 -070049import android.util.Slog;
50import android.util.SparseArray;
Hai Zhang33456fb2018-12-05 17:30:35 -080051import android.util.proto.ProtoOutputStream;
Hai Zhangb7776682018-09-25 15:10:57 -070052
53import com.android.internal.annotations.GuardedBy;
Hai Zhang33456fb2018-12-05 17:30:35 -080054import com.android.internal.util.ArrayUtils;
Eugene Suslaabdefba2018-11-09 18:06:43 -080055import com.android.internal.util.BitUtils;
56import com.android.internal.util.CollectionUtils;
Hai Zhang33456fb2018-12-05 17:30:35 -080057import com.android.internal.util.DumpUtils;
Eugene Suslaabdefba2018-11-09 18:06:43 -080058import com.android.internal.util.FunctionalUtils;
Hai Zhang33456fb2018-12-05 17:30:35 -080059import com.android.internal.util.IndentingPrintWriter;
Hai Zhangb7776682018-09-25 15:10:57 -070060import com.android.internal.util.Preconditions;
Hai Zhang33456fb2018-12-05 17:30:35 -080061import com.android.internal.util.dump.DualDumpOutputStream;
Hai Zhang31d06ba2018-12-06 18:14:42 -080062import com.android.internal.util.function.pooled.PooledLambda;
63import com.android.server.FgThread;
Hai Zhangb7776682018-09-25 15:10:57 -070064import com.android.server.LocalServices;
65import com.android.server.SystemService;
66
Eugene Suslaabdefba2018-11-09 18:06:43 -080067import java.io.ByteArrayOutputStream;
Jeff Sharkey6260c582018-11-27 13:05:15 -070068import java.io.FileDescriptor;
Hai Zhang33456fb2018-12-05 17:30:35 -080069import java.io.PrintWriter;
Hai Zhangb7776682018-09-25 15:10:57 -070070import java.util.ArrayList;
71import java.util.Collections;
72import java.util.List;
Hai Zhang458cedb2018-12-03 15:41:11 -080073import java.util.Objects;
Eugene Suslaa4200f822018-11-09 18:06:43 -080074import java.util.concurrent.CompletableFuture;
75import java.util.concurrent.ExecutionException;
76import java.util.concurrent.TimeUnit;
77import java.util.concurrent.TimeoutException;
Hai Zhangb7776682018-09-25 15:10:57 -070078
79/**
80 * Service for role management.
81 *
82 * @see RoleManager
83 */
Hai Zhang31d06ba2018-12-06 18:14:42 -080084public class RoleManagerService extends SystemService implements RoleUserState.Callback {
Hai Zhangb7776682018-09-25 15:10:57 -070085
86 private static final String LOG_TAG = RoleManagerService.class.getSimpleName();
87
88 @NonNull
89 private final UserManagerInternal mUserManagerInternal;
90 @NonNull
91 private final AppOpsManager mAppOpsManager;
92
93 @NonNull
94 private final Object mLock = new Object();
95
Eugene Susla4ab95112018-12-17 14:45:11 -080096 @NonNull
97 private final RoleHoldersResolver mLegacyRoleResolver;
98
99 /** @see #getRoleHolders(String, int) */
100 public interface RoleHoldersResolver {
101 /** @return a list of packages that hold a given role for a given user */
102 List<String> getRoleHolders(String roleName, int userId);
103 }
104
Hai Zhangb7776682018-09-25 15:10:57 -0700105 /**
106 * Maps user id to its state.
107 */
108 @GuardedBy("mLock")
109 @NonNull
110 private final SparseArray<RoleUserState> mUserStates = new SparseArray<>();
111
112 /**
113 * Maps user id to its controller service.
114 */
115 @GuardedBy("mLock")
116 @NonNull
117 private final SparseArray<RemoteRoleControllerService> mControllerServices =
118 new SparseArray<>();
119
Hai Zhang31d06ba2018-12-06 18:14:42 -0800120 /**
121 * Maps user id to its list of listeners.
122 */
123 @GuardedBy("mLock")
124 @NonNull
125 private final SparseArray<RemoteCallbackList<IOnRoleHoldersChangedListener>> mListeners =
126 new SparseArray<>();
127
128 @NonNull
129 private final Handler mListenerHandler = FgThread.getHandler();
130
Eugene Susla4ab95112018-12-17 14:45:11 -0800131 public RoleManagerService(@NonNull Context context,
132 @NonNull RoleHoldersResolver legacyRoleResolver) {
Hai Zhangb7776682018-09-25 15:10:57 -0700133 super(context);
134
Eugene Susla4ab95112018-12-17 14:45:11 -0800135 mLegacyRoleResolver = legacyRoleResolver;
136
Hai Zhangb7776682018-09-25 15:10:57 -0700137 mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
138 mAppOpsManager = context.getSystemService(AppOpsManager.class);
139
140 registerUserRemovedReceiver();
141 }
142
143 private void registerUserRemovedReceiver() {
144 IntentFilter intentFilter = new IntentFilter();
145 intentFilter.addAction(Intent.ACTION_USER_REMOVED);
146 getContext().registerReceiverAsUser(new BroadcastReceiver() {
147 @Override
Hai Zhang458cedb2018-12-03 15:41:11 -0800148 public void onReceive(@NonNull Context context, @NonNull Intent intent) {
Hai Zhangb7776682018-09-25 15:10:57 -0700149 if (TextUtils.equals(intent.getAction(), Intent.ACTION_USER_REMOVED)) {
150 int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
151 onRemoveUser(userId);
152 }
153 }
154 }, UserHandle.ALL, intentFilter, null, null);
155 }
156
157 @Override
158 public void onStart() {
159 publishBinderService(Context.ROLE_SERVICE, new Stub());
Eugene Suslad469fc12018-11-20 17:09:07 -0800160
Eugene Susla6d4922722018-11-08 16:25:28 -0800161 //TODO add watch for new user creation and run default grants for them
Eugene Suslad469fc12018-11-20 17:09:07 -0800162
163 IntentFilter intentFilter = new IntentFilter();
164 intentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
165 intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
166 intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
167 intentFilter.addDataScheme("package");
168 intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
169 getContext().registerReceiverAsUser(new BroadcastReceiver() {
170 @Override
171 public void onReceive(Context context, Intent intent) {
172 int userId = UserHandle.getUserId(intent.getIntExtra(Intent.EXTRA_UID, -1));
173 if (RemoteRoleControllerService.DEBUG) {
174 Slog.i(LOG_TAG,
175 "Packages changed - re-running initial grants for user " + userId);
176 }
177 performInitialGrantsIfNecessary(userId);
178 }
179 }, UserHandle.SYSTEM, intentFilter, null /* broadcastPermission */, null /* handler */);
Hai Zhangb7776682018-09-25 15:10:57 -0700180 }
181
182 @Override
183 public void onStartUser(@UserIdInt int userId) {
Eugene Suslad469fc12018-11-20 17:09:07 -0800184 performInitialGrantsIfNecessary(userId);
185 }
186
187 @MainThread
188 private void performInitialGrantsIfNecessary(@UserIdInt int userId) {
Eugene Suslaabdefba2018-11-09 18:06:43 -0800189 RoleUserState userState;
Hai Zhangcdc85c52018-12-06 13:56:55 -0800190 userState = getOrCreateUserState(userId);
Eugene Susla4ab95112018-12-17 14:45:11 -0800191
Eugene Suslaabdefba2018-11-09 18:06:43 -0800192 String packagesHash = computeComponentStateHash(userId);
Hai Zhangcdc85c52018-12-06 13:56:55 -0800193 String oldPackagesHash = userState.getPackagesHash();
Hai Zhang33456fb2018-12-05 17:30:35 -0800194 boolean needGrant = !Objects.equals(packagesHash, oldPackagesHash);
Eugene Suslaabdefba2018-11-09 18:06:43 -0800195 if (needGrant) {
Eugene Susla4ab95112018-12-17 14:45:11 -0800196
197 //TODO gradually add more role migrations statements here for remaining roles
198 // Make sure to implement LegacyRoleResolutionPolicy#getRoleHolders
199 // for a given role before adding a migration statement for it here
200 migrateRoleIfNecessary(RoleManager.ROLE_SMS, userId);
Philip P. Moltmann5d894502019-01-17 10:31:00 -0800201 migrateRoleIfNecessary(RoleManager.ROLE_ASSISTANT, userId);
Eugene Susla4ab95112018-12-17 14:45:11 -0800202
Eugene Suslaabdefba2018-11-09 18:06:43 -0800203 // Some vital packages state has changed since last role grant
204 // Run grants again
Eugene Susla6d4922722018-11-08 16:25:28 -0800205 Slog.i(LOG_TAG, "Granting default permissions...");
Eugene Suslaa4200f822018-11-09 18:06:43 -0800206 CompletableFuture<Void> result = new CompletableFuture<>();
Hai Zhangcdc85c52018-12-06 13:56:55 -0800207 getOrCreateControllerService(userId).onGrantDefaultRoles(
Eugene Suslaa4200f822018-11-09 18:06:43 -0800208 new IRoleManagerCallback.Stub() {
209 @Override
210 public void onSuccess() {
211 result.complete(null);
212 }
Eugene Suslaa4200f822018-11-09 18:06:43 -0800213 @Override
214 public void onFailure() {
215 result.completeExceptionally(new RuntimeException());
216 }
217 });
218 try {
219 result.get(5, TimeUnit.SECONDS);
Hai Zhangcdc85c52018-12-06 13:56:55 -0800220 userState.setPackagesHash(packagesHash);
Eugene Suslaa4200f822018-11-09 18:06:43 -0800221 } catch (InterruptedException | ExecutionException | TimeoutException e) {
222 Slog.e(LOG_TAG, "Failed to grant defaults for user " + userId, e);
223 }
Eugene Suslaabdefba2018-11-09 18:06:43 -0800224 } else if (RemoteRoleControllerService.DEBUG) {
225 Slog.i(LOG_TAG, "Already ran grants for package state " + packagesHash);
Hai Zhangb7776682018-09-25 15:10:57 -0700226 }
227 }
228
Eugene Susla4ab95112018-12-17 14:45:11 -0800229 private void migrateRoleIfNecessary(String role, @UserIdInt int userId) {
230 // Any role for which we have a record are already migrated
231 RoleUserState userState = getOrCreateUserState(userId);
232 if (!userState.isRoleAvailable(role)) {
Eugene Susla4ab95112018-12-17 14:45:11 -0800233 List<String> roleHolders = mLegacyRoleResolver.getRoleHolders(role, userId);
Hai Zhang7876adb2019-01-15 21:18:41 -0800234 if (roleHolders.isEmpty()) {
235 return;
236 }
Eugene Susla4ab95112018-12-17 14:45:11 -0800237 Slog.i(LOG_TAG, "Migrating " + role + ", legacy holders: " + roleHolders);
Hai Zhang7876adb2019-01-15 21:18:41 -0800238 userState.addRoleName(role);
Eugene Susla4ab95112018-12-17 14:45:11 -0800239 int size = roleHolders.size();
240 for (int i = 0; i < size; i++) {
241 userState.addRoleHolder(role, roleHolders.get(i));
242 }
243 }
244 }
245
Hai Zhang458cedb2018-12-03 15:41:11 -0800246 @Nullable
Hai Zhang31d06ba2018-12-06 18:14:42 -0800247 private static String computeComponentStateHash(@UserIdInt int userId) {
Eugene Suslaabdefba2018-11-09 18:06:43 -0800248 PackageManagerInternal pm = LocalServices.getService(PackageManagerInternal.class);
249 ByteArrayOutputStream out = new ByteArrayOutputStream();
250
251 pm.forEachPackage(FunctionalUtils.uncheckExceptions(pkg -> {
252 out.write(pkg.packageName.getBytes());
253 out.write(BitUtils.toBytes(pkg.getLongVersionCode()));
254 out.write(pm.getApplicationEnabledState(pkg.packageName, userId));
255
256 ArraySet<String> enabledComponents =
257 pm.getEnabledComponents(pkg.packageName, userId);
258 int numComponents = CollectionUtils.size(enabledComponents);
259 for (int i = 0; i < numComponents; i++) {
260 out.write(enabledComponents.valueAt(i).getBytes());
261 }
262
263 ArraySet<String> disabledComponents =
264 pm.getDisabledComponents(pkg.packageName, userId);
265 numComponents = CollectionUtils.size(disabledComponents);
266 for (int i = 0; i < numComponents; i++) {
267 out.write(disabledComponents.valueAt(i).getBytes());
268 }
269 for (Signature signature : pkg.mSigningDetails.signatures) {
270 out.write(signature.toByteArray());
271 }
272 }));
273
274 return PackageUtils.computeSha256Digest(out.toByteArray());
275 }
276
Hai Zhangb7776682018-09-25 15:10:57 -0700277 @NonNull
Hai Zhangcdc85c52018-12-06 13:56:55 -0800278 private RoleUserState getOrCreateUserState(@UserIdInt int userId) {
279 synchronized (mLock) {
280 RoleUserState userState = mUserStates.get(userId);
281 if (userState == null) {
Hai Zhang31d06ba2018-12-06 18:14:42 -0800282 userState = new RoleUserState(userId, this);
Hai Zhangcdc85c52018-12-06 13:56:55 -0800283 mUserStates.put(userId, userState);
284 }
285 return userState;
Hai Zhangb7776682018-09-25 15:10:57 -0700286 }
Hai Zhangb7776682018-09-25 15:10:57 -0700287 }
288
Hai Zhangb7776682018-09-25 15:10:57 -0700289 @NonNull
Hai Zhangcdc85c52018-12-06 13:56:55 -0800290 private RemoteRoleControllerService getOrCreateControllerService(@UserIdInt int userId) {
291 synchronized (mLock) {
292 RemoteRoleControllerService controllerService = mControllerServices.get(userId);
293 if (controllerService == null) {
294 controllerService = new RemoteRoleControllerService(userId, getContext());
295 mControllerServices.put(userId, controllerService);
296 }
297 return controllerService;
Hai Zhangb7776682018-09-25 15:10:57 -0700298 }
Hai Zhangb7776682018-09-25 15:10:57 -0700299 }
300
Hai Zhang31d06ba2018-12-06 18:14:42 -0800301 @Nullable
302 private RemoteCallbackList<IOnRoleHoldersChangedListener> getListeners(@UserIdInt int userId) {
303 synchronized (mLock) {
304 return mListeners.get(userId);
305 }
306 }
307
308 @NonNull
309 private RemoteCallbackList<IOnRoleHoldersChangedListener> getOrCreateListeners(
310 @UserIdInt int userId) {
311 synchronized (mLock) {
312 RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = mListeners.get(userId);
313 if (listeners == null) {
314 listeners = new RemoteCallbackList<>();
315 mListeners.put(userId, listeners);
316 }
317 return listeners;
318 }
319 }
320
Hai Zhangb7776682018-09-25 15:10:57 -0700321 private void onRemoveUser(@UserIdInt int userId) {
Hai Zhang31d06ba2018-12-06 18:14:42 -0800322 RemoteCallbackList<IOnRoleHoldersChangedListener> listeners;
Hai Zhangcdc85c52018-12-06 13:56:55 -0800323 RoleUserState userState;
Hai Zhangb7776682018-09-25 15:10:57 -0700324 synchronized (mLock) {
Hai Zhang31d06ba2018-12-06 18:14:42 -0800325 listeners = mListeners.removeReturnOld(userId);
Hai Zhangb7776682018-09-25 15:10:57 -0700326 mControllerServices.remove(userId);
Hai Zhangcdc85c52018-12-06 13:56:55 -0800327 userState = mUserStates.removeReturnOld(userId);
328 }
Hai Zhang31d06ba2018-12-06 18:14:42 -0800329 if (listeners != null) {
330 listeners.kill();
331 }
Hai Zhangcdc85c52018-12-06 13:56:55 -0800332 if (userState != null) {
333 userState.destroy();
Hai Zhangb7776682018-09-25 15:10:57 -0700334 }
335 }
336
Hai Zhang31d06ba2018-12-06 18:14:42 -0800337 @Override
338 public void onRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId) {
339 mListenerHandler.sendMessage(PooledLambda.obtainMessage(
340 RoleManagerService::notifyRoleHoldersChanged, this, roleName, userId));
341 }
342
343 @WorkerThread
344 private void notifyRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId) {
345 RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = getListeners(userId);
Philip P. Moltmann3c4a4802019-01-17 10:31:00 -0800346 if (listeners != null) {
347 notifyRoleHoldersChangedForListeners(listeners, roleName, userId);
Hai Zhang31d06ba2018-12-06 18:14:42 -0800348 }
349
Philip P. Moltmann3c4a4802019-01-17 10:31:00 -0800350 RemoteCallbackList<IOnRoleHoldersChangedListener> allUserListeners = getListeners(
351 UserHandle.USER_ALL);
352 if (allUserListeners != null) {
353 notifyRoleHoldersChangedForListeners(allUserListeners, roleName, userId);
354 }
355 }
356
357 @WorkerThread
358 private void notifyRoleHoldersChangedForListeners(
359 @NonNull RemoteCallbackList<IOnRoleHoldersChangedListener> listeners,
360 @NonNull String roleName, @UserIdInt int userId) {
Hai Zhang31d06ba2018-12-06 18:14:42 -0800361 int broadcastCount = listeners.beginBroadcast();
362 try {
363 for (int i = 0; i < broadcastCount; i++) {
364 IOnRoleHoldersChangedListener listener = listeners.getBroadcastItem(i);
365 try {
366 listener.onRoleHoldersChanged(roleName, userId);
367 } catch (RemoteException e) {
368 Slog.e(LOG_TAG, "Error calling OnRoleHoldersChangedListener", e);
369 }
370 }
371 } finally {
372 listeners.finishBroadcast();
373 }
374 }
375
Hai Zhangb7776682018-09-25 15:10:57 -0700376 private class Stub extends IRoleManager.Stub {
377
378 @Override
379 public boolean isRoleAvailable(@NonNull String roleName) {
380 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
381
382 int userId = UserHandle.getUserId(getCallingUid());
Hai Zhangcdc85c52018-12-06 13:56:55 -0800383 RoleUserState userState = getOrCreateUserState(userId);
384 return userState.isRoleAvailable(roleName);
Hai Zhangb7776682018-09-25 15:10:57 -0700385 }
386
387 @Override
388 public boolean isRoleHeld(@NonNull String roleName, @NonNull String packageName) {
389 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
390 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
391 int callingUid = getCallingUid();
392 mAppOpsManager.checkPackage(callingUid, packageName);
393
394 int userId = UserHandle.getUserId(callingUid);
395 ArraySet<String> roleHolders = getRoleHoldersInternal(roleName, userId);
396 if (roleHolders == null) {
397 return false;
398 }
399 return roleHolders.contains(packageName);
400 }
401
402 @NonNull
403 @Override
404 public List<String> getRoleHoldersAsUser(@NonNull String roleName, @UserIdInt int userId) {
405 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
406 if (!mUserManagerInternal.exists(userId)) {
407 Slog.e(LOG_TAG, "user " + userId + " does not exist");
408 return Collections.emptyList();
409 }
Philip P. Moltmann3c4a4802019-01-17 10:31:00 -0800410 userId = handleIncomingUser(userId, "getRoleHoldersAsUser", false);
Hai Zhangb7776682018-09-25 15:10:57 -0700411 getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
412 "getRoleHoldersAsUser");
413
414 ArraySet<String> roleHolders = getRoleHoldersInternal(roleName, userId);
415 if (roleHolders == null) {
416 return Collections.emptyList();
417 }
418 return new ArrayList<>(roleHolders);
419 }
420
421 @Nullable
422 private ArraySet<String> getRoleHoldersInternal(@NonNull String roleName,
423 @UserIdInt int userId) {
Hai Zhangcdc85c52018-12-06 13:56:55 -0800424 RoleUserState userState = getOrCreateUserState(userId);
425 return userState.getRoleHolders(roleName);
Hai Zhangb7776682018-09-25 15:10:57 -0700426 }
427
428 @Override
429 public void addRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
430 @UserIdInt int userId, @NonNull IRoleManagerCallback callback) {
431 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
432 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
433 Preconditions.checkNotNull(callback, "callback cannot be null");
434 if (!mUserManagerInternal.exists(userId)) {
435 Slog.e(LOG_TAG, "user " + userId + " does not exist");
436 return;
437 }
Philip P. Moltmann3c4a4802019-01-17 10:31:00 -0800438 userId = handleIncomingUser(userId, "addRoleHolderAsUser", false);
Hai Zhangb7776682018-09-25 15:10:57 -0700439 getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
440 "addRoleHolderAsUser");
441
Hai Zhangcdc85c52018-12-06 13:56:55 -0800442 getOrCreateControllerService(userId).onAddRoleHolder(roleName, packageName, callback);
Hai Zhangb7776682018-09-25 15:10:57 -0700443 }
444
445 @Override
446 public void removeRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
447 @UserIdInt int userId, @NonNull IRoleManagerCallback callback) {
448 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
449 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
450 Preconditions.checkNotNull(callback, "callback cannot be null");
451 if (!mUserManagerInternal.exists(userId)) {
452 Slog.e(LOG_TAG, "user " + userId + " does not exist");
453 return;
454 }
Philip P. Moltmann3c4a4802019-01-17 10:31:00 -0800455 userId = handleIncomingUser(userId, "removeRoleHolderAsUser", false);
Hai Zhangb7776682018-09-25 15:10:57 -0700456 getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
457 "removeRoleHolderAsUser");
458
Hai Zhangcdc85c52018-12-06 13:56:55 -0800459 getOrCreateControllerService(userId).onRemoveRoleHolder(roleName, packageName,
Hai Zhangb7776682018-09-25 15:10:57 -0700460 callback);
461 }
462
463 @Override
464 public void clearRoleHoldersAsUser(@NonNull String roleName, @UserIdInt int userId,
465 @NonNull IRoleManagerCallback callback) {
466 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
467 Preconditions.checkNotNull(callback, "callback cannot be null");
468 if (!mUserManagerInternal.exists(userId)) {
469 Slog.e(LOG_TAG, "user " + userId + " does not exist");
470 return;
471 }
Philip P. Moltmann3c4a4802019-01-17 10:31:00 -0800472 userId = handleIncomingUser(userId, "clearRoleHoldersAsUser", false);
Hai Zhangb7776682018-09-25 15:10:57 -0700473 getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
474 "clearRoleHoldersAsUser");
Hai Zhang87ed09a2018-10-22 10:43:31 -0700475
Hai Zhangcdc85c52018-12-06 13:56:55 -0800476 getOrCreateControllerService(userId).onClearRoleHolders(roleName, callback);
Hai Zhangb7776682018-09-25 15:10:57 -0700477 }
478
Hai Zhang87ed09a2018-10-22 10:43:31 -0700479 @Override
Hai Zhang31d06ba2018-12-06 18:14:42 -0800480 public void addOnRoleHoldersChangedListenerAsUser(
481 @NonNull IOnRoleHoldersChangedListener listener, @UserIdInt int userId) {
482 Preconditions.checkNotNull(listener, "listener cannot be null");
Philip P. Moltmann3c4a4802019-01-17 10:31:00 -0800483 if (userId != UserHandle.USER_ALL && !mUserManagerInternal.exists(userId)) {
Hai Zhang31d06ba2018-12-06 18:14:42 -0800484 Slog.e(LOG_TAG, "user " + userId + " does not exist");
485 return;
486 }
Philip P. Moltmann3c4a4802019-01-17 10:31:00 -0800487 userId = handleIncomingUser(userId, "addOnRoleHoldersChangedListenerAsUser",
488 true);
Hai Zhang31d06ba2018-12-06 18:14:42 -0800489 getContext().enforceCallingOrSelfPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS,
490 "addOnRoleHoldersChangedListenerAsUser");
491
492 RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = getOrCreateListeners(
493 userId);
494 listeners.register(listener);
495 }
496
497 @Override
498 public void removeOnRoleHoldersChangedListenerAsUser(
499 @NonNull IOnRoleHoldersChangedListener listener, @UserIdInt int userId) {
500 Preconditions.checkNotNull(listener, "listener cannot be null");
Philip P. Moltmann3c4a4802019-01-17 10:31:00 -0800501 if (userId != UserHandle.USER_ALL && !mUserManagerInternal.exists(userId)) {
Hai Zhang31d06ba2018-12-06 18:14:42 -0800502 Slog.e(LOG_TAG, "user " + userId + " does not exist");
503 return;
504 }
Philip P. Moltmann3c4a4802019-01-17 10:31:00 -0800505 userId = handleIncomingUser(userId, "removeOnRoleHoldersChangedListenerAsUser",
506 true);
Hai Zhang31d06ba2018-12-06 18:14:42 -0800507 getContext().enforceCallingOrSelfPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS,
508 "removeOnRoleHoldersChangedListenerAsUser");
509
510 RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = getListeners(userId);
511 if (listener == null) {
512 return;
513 }
514 listeners.unregister(listener);
515 }
516
517 @Override
Hai Zhang8e60a8f2018-11-20 11:21:09 -0800518 public void setRoleNamesFromController(@NonNull List<String> roleNames) {
519 Preconditions.checkNotNull(roleNames, "roleNames cannot be null");
520 getContext().enforceCallingOrSelfPermission(
521 RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER,
522 "setRoleNamesFromController");
523
524 int userId = UserHandle.getCallingUserId();
Hai Zhangcdc85c52018-12-06 13:56:55 -0800525 RoleUserState userState = getOrCreateUserState(userId);
526 userState.setRoleNames(roleNames);
Hai Zhang8e60a8f2018-11-20 11:21:09 -0800527 }
528
529 @Override
Hai Zhang87ed09a2018-10-22 10:43:31 -0700530 public boolean addRoleHolderFromController(@NonNull String roleName,
531 @NonNull String packageName) {
532 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
533 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
534 getContext().enforceCallingOrSelfPermission(
Hai Zhang8e60a8f2018-11-20 11:21:09 -0800535 RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER,
Hai Zhang87ed09a2018-10-22 10:43:31 -0700536 "addRoleHolderFromController");
537
538 int userId = UserHandle.getCallingUserId();
Hai Zhangcdc85c52018-12-06 13:56:55 -0800539 RoleUserState userState = getOrCreateUserState(userId);
540 return userState.addRoleHolder(roleName, packageName);
Hai Zhang87ed09a2018-10-22 10:43:31 -0700541 }
542
543 @Override
544 public boolean removeRoleHolderFromController(@NonNull String roleName,
545 @NonNull String packageName) {
546 Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
547 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
548 getContext().enforceCallingOrSelfPermission(
Hai Zhang8e60a8f2018-11-20 11:21:09 -0800549 RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER,
Hai Zhang87ed09a2018-10-22 10:43:31 -0700550 "removeRoleHolderFromController");
551
552 int userId = UserHandle.getCallingUserId();
Hai Zhangcdc85c52018-12-06 13:56:55 -0800553 RoleUserState userState = getOrCreateUserState(userId);
554 return userState.removeRoleHolder(roleName, packageName);
Hai Zhang87ed09a2018-10-22 10:43:31 -0700555 }
556
Eugene Suslaa2a80322018-12-12 17:09:38 -0800557 @Override
558 public List<String> getHeldRolesFromController(@NonNull String packageName) {
559 Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
560 getContext().enforceCallingOrSelfPermission(
561 RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER,
562 "getRolesHeldFromController");
563
564 int userId = UserHandle.getCallingUserId();
565 RoleUserState userState = getOrCreateUserState(userId);
566 return userState.getHeldRoles(packageName);
567 }
568
Hai Zhangb7776682018-09-25 15:10:57 -0700569 @CheckResult
Philip P. Moltmann3c4a4802019-01-17 10:31:00 -0800570 private int handleIncomingUser(@UserIdInt int userId, @NonNull String name,
571 boolean allowAll) {
Hai Zhangb7776682018-09-25 15:10:57 -0700572 return ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
Philip P. Moltmann3c4a4802019-01-17 10:31:00 -0800573 allowAll, true, name, null);
Hai Zhangb7776682018-09-25 15:10:57 -0700574 }
Jeff Sharkey6260c582018-11-27 13:05:15 -0700575
576 @Override
Hai Zhang458cedb2018-12-03 15:41:11 -0800577 public void onShellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
578 @Nullable FileDescriptor err, @NonNull String[] args,
579 @Nullable ShellCallback callback, @NonNull ResultReceiver resultReceiver) {
580 new RoleManagerShellCommand(this).exec(this, in, out, err, args, callback,
581 resultReceiver);
Jeff Sharkey6260c582018-11-27 13:05:15 -0700582 }
Hai Zhang33456fb2018-12-05 17:30:35 -0800583
584 @Override
Eugene Susla4ab95112018-12-17 14:45:11 -0800585 public String getDefaultSmsPackage(int userId) {
586 long identity = Binder.clearCallingIdentity();
587 try {
588 return CollectionUtils.firstOrNull(
589 getRoleHoldersAsUser(RoleManager.ROLE_SMS, userId));
590 } finally {
591 Binder.restoreCallingIdentity(identity);
592 }
593 }
594
595 @Override
Hai Zhang33456fb2018-12-05 17:30:35 -0800596 protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter fout,
597 @Nullable String[] args) {
598 if (!DumpUtils.checkDumpPermission(getContext(), LOG_TAG, fout)) {
599 return;
600 }
601
602 boolean dumpAsProto = args != null && ArrayUtils.contains(args, "--proto");
603 DualDumpOutputStream dumpOutputStream;
604 if (dumpAsProto) {
605 dumpOutputStream = new DualDumpOutputStream(new ProtoOutputStream(fd));
606 } else {
607 fout.println("ROLE MANAGER STATE (dumpsys role):");
608 dumpOutputStream = new DualDumpOutputStream(new IndentingPrintWriter(fout, " "));
609 }
610
Hai Zhangcdc85c52018-12-06 13:56:55 -0800611 int[] userIds = mUserManagerInternal.getUserIds();
612 int userIdsLength = userIds.length;
613 for (int i = 0; i < userIdsLength; i++) {
614 int userId = userIds[i];
Hai Zhang33456fb2018-12-05 17:30:35 -0800615
Hai Zhangcdc85c52018-12-06 13:56:55 -0800616 RoleUserState userState = getOrCreateUserState(userId);
617 userState.dump(dumpOutputStream, "user_states",
618 RoleManagerServiceDumpProto.USER_STATES);
Hai Zhang33456fb2018-12-05 17:30:35 -0800619 }
620
621 dumpOutputStream.flush();
622 }
Hai Zhangb7776682018-09-25 15:10:57 -0700623 }
624}