1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.role;
18 
19 import android.Manifest;
20 import android.annotation.AnyThread;
21 import android.annotation.MainThread;
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.annotation.UserIdInt;
25 import android.annotation.WorkerThread;
26 import android.app.AppOpsManager;
27 import android.app.admin.DevicePolicyManager;
28 import android.app.role.IOnRoleHoldersChangedListener;
29 import android.app.role.IRoleManager;
30 import android.app.role.RoleControllerManager;
31 import android.app.role.RoleManager;
32 import android.content.BroadcastReceiver;
33 import android.content.Context;
34 import android.content.Intent;
35 import android.content.IntentFilter;
36 import android.content.pm.PackageManager;
37 import android.database.ContentObserver;
38 import android.net.Uri;
39 import android.os.Binder;
40 import android.os.Build;
41 import android.os.Handler;
42 import android.os.ParcelFileDescriptor;
43 import android.os.RemoteCallback;
44 import android.os.RemoteCallbackList;
45 import android.os.RemoteException;
46 import android.os.UserHandle;
47 import android.os.UserManager;
48 import android.permission.flags.Flags;
49 import android.provider.Settings;
50 import android.text.TextUtils;
51 import android.util.ArraySet;
52 import android.util.IndentingPrintWriter;
53 import android.util.Log;
54 import android.util.SparseArray;
55 import android.util.proto.ProtoOutputStream;
56 
57 import androidx.annotation.Keep;
58 import androidx.annotation.RequiresApi;
59 
60 import com.android.internal.annotations.GuardedBy;
61 import com.android.internal.infra.AndroidFuture;
62 import com.android.internal.util.Preconditions;
63 import com.android.internal.util.dump.DualDumpOutputStream;
64 import com.android.modules.utils.build.SdkLevel;
65 import com.android.permission.compat.UserHandleCompat;
66 import com.android.permission.util.ArrayUtils;
67 import com.android.permission.util.CollectionUtils;
68 import com.android.permission.util.ForegroundThread;
69 import com.android.permission.util.PackageUtils;
70 import com.android.permission.util.ThrottledRunnable;
71 import com.android.permission.util.UserUtils;
72 import com.android.server.LocalManagerRegistry;
73 import com.android.server.SystemService;
74 import com.android.server.role.RoleServicePlatformHelper;
75 
76 import java.io.FileDescriptor;
77 import java.io.FileOutputStream;
78 import java.io.PrintWriter;
79 import java.util.ArrayList;
80 import java.util.Collections;
81 import java.util.List;
82 import java.util.Map;
83 import java.util.Objects;
84 import java.util.Set;
85 import java.util.concurrent.ExecutionException;
86 import java.util.concurrent.TimeUnit;
87 import java.util.concurrent.TimeoutException;
88 
89 /**
90  * Service for role management.
91  *
92  * @see RoleManager
93  */
94 @Keep
95 @RequiresApi(Build.VERSION_CODES.S)
96 public class RoleService extends SystemService implements RoleUserState.Callback {
97     private static final String LOG_TAG = RoleService.class.getSimpleName();
98 
99     private static final boolean DEBUG = false;
100 
101     private static final long GRANT_DEFAULT_ROLES_INTERVAL_MILLIS = 1000;
102 
103     private static final String[] DEFAULT_APPLICATION_ROLES;
104 
105     static {
106         List<String> defaultApplicationRoles = new ArrayList<>();
107         defaultApplicationRoles.add(RoleManager.ROLE_ASSISTANT);
108         defaultApplicationRoles.add(RoleManager.ROLE_BROWSER);
109         defaultApplicationRoles.add(RoleManager.ROLE_CALL_REDIRECTION);
110         defaultApplicationRoles.add(RoleManager.ROLE_CALL_SCREENING);
111         defaultApplicationRoles.add(RoleManager.ROLE_DIALER);
112         defaultApplicationRoles.add(RoleManager.ROLE_HOME);
113         defaultApplicationRoles.add(RoleManager.ROLE_SMS);
114         if (SdkLevel.isAtLeastV()) {
115             defaultApplicationRoles.add(RoleManager.ROLE_WALLET);
116         }
117         DEFAULT_APPLICATION_ROLES = defaultApplicationRoles.toArray(new String[0]);
118     }
119 
120     @NonNull
121     private final AppOpsManager mAppOpsManager;
122 
123     @NonNull
124     private final Object mLock = new Object();
125 
126     @NonNull
127     private final RoleServicePlatformHelper mPlatformHelper;
128 
129     /**
130      * Maps user id to its state.
131      */
132     @GuardedBy("mLock")
133     @NonNull
134     private final SparseArray<RoleUserState> mUserStates = new SparseArray<>();
135 
136     /**
137      * Maps user id to its controller.
138      */
139     @GuardedBy("mLock")
140     @NonNull
141     private final SparseArray<RoleController> mControllers = new SparseArray<>();
142 
143     /**
144      * Maps user id to its list of listeners.
145      */
146     @GuardedBy("mLock")
147     @NonNull
148     private final SparseArray<RemoteCallbackList<IOnRoleHoldersChangedListener>> mListeners =
149             new SparseArray<>();
150 
151     @NonNull
152     private final Handler mListenerHandler = ForegroundThread.getHandler();
153 
154     @GuardedBy("mLock")
155     private boolean mBypassingRoleQualification;
156 
157     /**
158      * Maps user id to its throttled runnable for granting default roles.
159      */
160     @GuardedBy("mLock")
161     @NonNull
162     private final SparseArray<ThrottledRunnable> mGrantDefaultRolesThrottledRunnables =
163             new SparseArray<>();
164 
RoleService(@onNull Context context)165     public RoleService(@NonNull Context context) {
166         super(context);
167 
168         mPlatformHelper = LocalManagerRegistry.getManager(RoleServicePlatformHelper.class);
169 
170         RoleControllerManager.initializeRemoteServiceComponentName(context);
171 
172         mAppOpsManager = context.getSystemService(AppOpsManager.class);
173 
174         LocalManagerRegistry.addManager(RoleManagerLocal.class, new Local());
175 
176         registerUserRemovedReceiver();
177     }
178 
registerUserRemovedReceiver()179     private void registerUserRemovedReceiver() {
180         IntentFilter intentFilter = new IntentFilter();
181         intentFilter.addAction(Intent.ACTION_USER_REMOVED);
182         getContext().registerReceiverForAllUsers(new BroadcastReceiver() {
183             @Override
184             public void onReceive(@NonNull Context context, @NonNull Intent intent) {
185                 if (TextUtils.equals(intent.getAction(), Intent.ACTION_USER_REMOVED)) {
186                     int userId = intent.<UserHandle>getParcelableExtra(Intent.EXTRA_USER)
187                             .getIdentifier();
188                     onRemoveUser(userId);
189                 }
190             }
191         }, intentFilter, null, null);
192     }
193 
194     @Override
onStart()195     public void onStart() {
196         publishBinderService(Context.ROLE_SERVICE, new Stub());
197 
198         Context context = getContext();
199         IntentFilter packageIntentFilter = new IntentFilter();
200         packageIntentFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
201         packageIntentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
202         packageIntentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
203         packageIntentFilter.addDataScheme("package");
204         packageIntentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
205         context.registerReceiverForAllUsers(new BroadcastReceiver() {
206             @Override
207             public void onReceive(Context context, Intent intent) {
208                 int userId = UserHandleCompat.getUserId(intent.getIntExtra(Intent.EXTRA_UID, -1));
209                 if (DEBUG) {
210                     Log.i(LOG_TAG, "Packages changed - re-running initial grants for user "
211                             + userId);
212                 }
213                 if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
214                         && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
215                     // Package is being upgraded - we're about to get ACTION_PACKAGE_ADDED
216                     return;
217                 }
218                 maybeGrantDefaultRolesAsync(userId);
219             }
220         }, packageIntentFilter, null, null);
221 
222         if (SdkLevel.isAtLeastV()) {
223             IntentFilter devicePolicyIntentFilter = new IntentFilter();
224             devicePolicyIntentFilter.addAction(
225                     DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED);
226             devicePolicyIntentFilter.addAction(
227                     DevicePolicyManager.ACTION_PROFILE_OWNER_CHANGED);
228             devicePolicyIntentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
229             context.registerReceiverForAllUsers(new BroadcastReceiver() {
230                 @Override
231                 public void onReceive(Context context, Intent intent) {
232                     int userId = getSendingUser().getIdentifier();
233                     if (DEBUG) {
234                         Log.i(LOG_TAG, "Device policy changed (" + intent.getAction()
235                             + ") - re-running initial grants for user " + userId);
236                     }
237                     maybeGrantDefaultRolesAsync(userId);
238                 }
239             }, devicePolicyIntentFilter, null, null);
240 
241             context.getContentResolver().registerContentObserver(
242                     Settings.Global.getUriFor(Settings.Global.DEVICE_DEMO_MODE), false,
243                     new ContentObserver(ForegroundThread.getHandler()) {
244                         public void onChange(boolean selfChange, Uri uri) {
245                             if (DEBUG) {
246                                 Log.i(LOG_TAG, "Settings.Global.DEVICE_DEMO_MODE changed.");
247                             }
248                             UserManager userManager =
249                                     context.getSystemService(UserManager.class);
250                             List<UserHandle> users = userManager.getUserHandles(true);
251                             int usersSize = users.size();
252                             for (int i = 0; i < usersSize; i++) {
253                                 maybeGrantDefaultRolesAsync(users.get(i).getIdentifier());
254                             }
255                         }
256                     });
257         }
258     }
259 
260     @Override
onUserStarting(@onNull TargetUser user)261     public void onUserStarting(@NonNull TargetUser user) {
262         if (SdkLevel.isAtLeastV() && Flags.systemServerRoleControllerEnabled()) {
263             upgradeLegacyFallbackEnabledRolesIfNeeded(user);
264         }
265 
266         maybeGrantDefaultRolesSync(user.getUserHandle().getIdentifier());
267     }
268 
upgradeLegacyFallbackEnabledRolesIfNeeded(@onNull TargetUser user)269     private void upgradeLegacyFallbackEnabledRolesIfNeeded(@NonNull TargetUser user) {
270         int userId = user.getUserHandle().getIdentifier();
271         RoleUserState userState = getOrCreateUserState(userId);
272         if (!userState.isVersionUpgradeNeeded()) {
273             return;
274         }
275         List<String> legacyFallbackDisabledRoles = getLegacyFallbackDisabledRolesSync(userId);
276         if (legacyFallbackDisabledRoles == null) {
277             return;
278         }
279         Log.v(LOG_TAG, "Received legacy fallback disabled roles: " + legacyFallbackDisabledRoles);
280         userState.upgradeVersion(legacyFallbackDisabledRoles);
281     }
282 
283     @MainThread
getLegacyFallbackDisabledRolesSync(@serIdInt int userId)284     private List<String> getLegacyFallbackDisabledRolesSync(@UserIdInt int userId) {
285         AndroidFuture<List<String>> future = new AndroidFuture<>();
286         RoleController controller = new RemoteRoleController(UserHandle.of(userId), getContext());
287         controller.getLegacyFallbackDisabledRoles(ForegroundThread.getExecutor(), future::complete);
288         try {
289             return future.get(30, TimeUnit.SECONDS);
290         } catch (InterruptedException | ExecutionException | TimeoutException e) {
291             Log.e(LOG_TAG, "Failed to get the legacy role fallback disabled state for user "
292                     + userId, e);
293             return null;
294         }
295     }
296 
297     @MainThread
maybeGrantDefaultRolesSync(@serIdInt int userId)298     private void maybeGrantDefaultRolesSync(@UserIdInt int userId) {
299         AndroidFuture<Void> future = maybeGrantDefaultRolesInternal(userId);
300         try {
301             future.get(30, TimeUnit.SECONDS);
302         } catch (InterruptedException | ExecutionException | TimeoutException e) {
303             Log.e(LOG_TAG, "Failed to grant default roles for user " + userId, e);
304         }
305     }
306 
maybeGrantDefaultRolesAsync(@serIdInt int userId)307     private void maybeGrantDefaultRolesAsync(@UserIdInt int userId) {
308         ThrottledRunnable runnable;
309         synchronized (mLock) {
310             runnable = mGrantDefaultRolesThrottledRunnables.get(userId);
311             if (runnable == null) {
312                 runnable = new ThrottledRunnable(ForegroundThread.getHandler(),
313                         GRANT_DEFAULT_ROLES_INTERVAL_MILLIS,
314                         () -> maybeGrantDefaultRolesInternal(userId));
315                 mGrantDefaultRolesThrottledRunnables.put(userId, runnable);
316             }
317         }
318         runnable.run();
319     }
320 
321     @AnyThread
322     @NonNull
maybeGrantDefaultRolesInternal(@serIdInt int userId)323     private AndroidFuture<Void> maybeGrantDefaultRolesInternal(@UserIdInt int userId) {
324         if (!UserUtils.isUserExistent(userId, getContext())) {
325             Log.w(LOG_TAG, "User " + userId + " does not exist");
326             return AndroidFuture.completedFuture(null);
327         }
328 
329         RoleUserState userState = getOrCreateUserState(userId);
330         String oldPackagesHash = userState.getPackagesHash();
331         String newPackagesHash = mPlatformHelper.computePackageStateHash(userId);
332         if (Objects.equals(oldPackagesHash, newPackagesHash)) {
333             if (DEBUG) {
334                 Log.i(LOG_TAG, "Already granted default roles for packages hash "
335                         + newPackagesHash);
336             }
337             return AndroidFuture.completedFuture(null);
338         }
339 
340         // Some package state has changed, so grant default roles again.
341         Log.i(LOG_TAG, "Granting default roles...");
342         AndroidFuture<Void> future = new AndroidFuture<>();
343         getOrCreateController(userId).grantDefaultRoles(ForegroundThread.getExecutor(),
344                 successful -> {
345                     if (successful) {
346                         userState.setPackagesHash(newPackagesHash);
347                         future.complete(null);
348                     } else {
349                         future.completeExceptionally(new RuntimeException());
350                     }
351                 });
352         return future;
353     }
354 
355     @NonNull
getOrCreateUserState(@serIdInt int userId)356     private RoleUserState getOrCreateUserState(@UserIdInt int userId) {
357         synchronized (mLock) {
358             RoleUserState userState = mUserStates.get(userId);
359             if (userState == null) {
360                 userState = new RoleUserState(userId, mPlatformHelper, this,
361                         mBypassingRoleQualification);
362                 mUserStates.put(userId, userState);
363             }
364             return userState;
365         }
366     }
367 
368     @NonNull
getOrCreateController(@serIdInt int userId)369     private RoleController getOrCreateController(@UserIdInt int userId) {
370         synchronized (mLock) {
371             RoleController controller = mControllers.get(userId);
372             if (controller == null) {
373                 UserHandle user = UserHandle.of(userId);
374                 Context context = getContext();
375                 if (SdkLevel.isAtLeastV() && Flags.systemServerRoleControllerEnabled()) {
376                     controller = new LocalRoleController(user, context);
377                 } else {
378                     controller = new RemoteRoleController(user, context);
379                 }
380                 mControllers.put(userId, controller);
381             }
382             return controller;
383         }
384     }
385 
386     @Nullable
getListeners(@serIdInt int userId)387     private RemoteCallbackList<IOnRoleHoldersChangedListener> getListeners(@UserIdInt int userId) {
388         synchronized (mLock) {
389             return mListeners.get(userId);
390         }
391     }
392 
393     @NonNull
getOrCreateListeners( @serIdInt int userId)394     private RemoteCallbackList<IOnRoleHoldersChangedListener> getOrCreateListeners(
395             @UserIdInt int userId) {
396         synchronized (mLock) {
397             RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = mListeners.get(userId);
398             if (listeners == null) {
399                 listeners = new RemoteCallbackList<>();
400                 mListeners.put(userId, listeners);
401             }
402             return listeners;
403         }
404     }
405 
onRemoveUser(@serIdInt int userId)406     private void onRemoveUser(@UserIdInt int userId) {
407         RemoteCallbackList<IOnRoleHoldersChangedListener> listeners;
408         RoleUserState userState;
409         synchronized (mLock) {
410             mGrantDefaultRolesThrottledRunnables.remove(userId);
411             listeners = mListeners.get(userId);
412             mListeners.remove(userId);
413             mControllers.remove(userId);
414             userState = mUserStates.get(userId);
415             mUserStates.remove(userId);
416         }
417         if (listeners != null) {
418             listeners.kill();
419         }
420         if (userState != null) {
421             userState.destroy();
422         }
423     }
424 
425     @Override
onRoleHoldersChanged(@onNull String roleName, @UserIdInt int userId)426     public void onRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId) {
427         mListenerHandler.post(() -> notifyRoleHoldersChanged(roleName, userId));
428     }
429 
430     @WorkerThread
notifyRoleHoldersChanged(@onNull String roleName, @UserIdInt int userId)431     private void notifyRoleHoldersChanged(@NonNull String roleName, @UserIdInt int userId) {
432         RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = getListeners(userId);
433         if (listeners != null) {
434             notifyRoleHoldersChangedForListeners(listeners, roleName, userId);
435         }
436 
437         RemoteCallbackList<IOnRoleHoldersChangedListener> allUsersListeners = getListeners(
438                 UserHandleCompat.USER_ALL);
439         if (allUsersListeners != null) {
440             notifyRoleHoldersChangedForListeners(allUsersListeners, roleName, userId);
441         }
442     }
443 
444     @WorkerThread
notifyRoleHoldersChangedForListeners( @onNull RemoteCallbackList<IOnRoleHoldersChangedListener> listeners, @NonNull String roleName, @UserIdInt int userId)445     private void notifyRoleHoldersChangedForListeners(
446             @NonNull RemoteCallbackList<IOnRoleHoldersChangedListener> listeners,
447             @NonNull String roleName, @UserIdInt int userId) {
448         int broadcastCount = listeners.beginBroadcast();
449         try {
450             for (int i = 0; i < broadcastCount; i++) {
451                 IOnRoleHoldersChangedListener listener = listeners.getBroadcastItem(i);
452                 try {
453                     listener.onRoleHoldersChanged(roleName, userId);
454                 } catch (RemoteException e) {
455                     Log.e(LOG_TAG, "Error calling OnRoleHoldersChangedListener", e);
456                 }
457             }
458         } finally {
459             listeners.finishBroadcast();
460         }
461     }
462 
463     private class Stub extends IRoleManager.Stub {
464 
465         @Override
isRoleAvailableAsUser(@onNull String roleName, @UserIdInt int userId)466         public boolean isRoleAvailableAsUser(@NonNull String roleName, @UserIdInt int userId) {
467             UserUtils.enforceCrossUserPermission(userId, false, "isRoleAvailableAsUser",
468                     getContext());
469             if (!UserUtils.isUserExistent(userId, getContext())) {
470                 Log.e(LOG_TAG, "user " + userId + " does not exist");
471                 return false;
472             }
473 
474             Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
475 
476             return getOrCreateUserState(userId).isRoleAvailable(roleName);
477         }
478 
479         @Override
isRoleHeldAsUser(@onNull String roleName, @NonNull String packageName, @UserIdInt int userId)480         public boolean isRoleHeldAsUser(@NonNull String roleName, @NonNull String packageName,
481                 @UserIdInt int userId) {
482             mAppOpsManager.checkPackage(getCallingUid(), packageName);
483 
484             UserUtils.enforceCrossUserPermission(userId, false, "isRoleHeldAsUser", getContext());
485             if (!UserUtils.isUserExistent(userId, getContext())) {
486                 Log.e(LOG_TAG, "user " + userId + " does not exist");
487                 return false;
488             }
489 
490             Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
491             Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
492 
493             ArraySet<String> roleHolders = getOrCreateUserState(userId).getRoleHolders(roleName);
494             if (roleHolders == null) {
495                 return false;
496             }
497             return roleHolders.contains(packageName);
498         }
499 
500         @NonNull
501         @Override
getRoleHoldersAsUser(@onNull String roleName, @UserIdInt int userId)502         public List<String> getRoleHoldersAsUser(@NonNull String roleName, @UserIdInt int userId) {
503             UserUtils.enforceCrossUserPermission(userId, false, "getRoleHoldersAsUser",
504                     getContext());
505             if (!UserUtils.isUserExistent(userId, getContext())) {
506                 Log.e(LOG_TAG, "user " + userId + " does not exist");
507                 return Collections.emptyList();
508             }
509 
510             getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
511                     "getRoleHoldersAsUser");
512 
513             Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
514 
515             ArraySet<String> roleHolders = getOrCreateUserState(userId).getRoleHolders(roleName);
516             if (roleHolders == null) {
517                 return Collections.emptyList();
518             }
519             return new ArrayList<>(roleHolders);
520         }
521 
522         @Override
addRoleHolderAsUser(@onNull String roleName, @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId, @NonNull RemoteCallback callback)523         public void addRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
524                 @RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId,
525                 @NonNull RemoteCallback callback) {
526             UserUtils.enforceCrossUserPermission(userId, false, "addRoleHolderAsUser",
527                     getContext());
528             if (!UserUtils.isUserExistent(userId, getContext())) {
529                 Log.e(LOG_TAG, "user " + userId + " does not exist");
530                 return;
531             }
532 
533             getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
534                     "addRoleHolderAsUser");
535 
536             Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
537             Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
538             Objects.requireNonNull(callback, "callback cannot be null");
539 
540             getOrCreateController(userId).onAddRoleHolder(roleName, packageName, flags, callback);
541         }
542 
543         @Override
removeRoleHolderAsUser(@onNull String roleName, @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId, @NonNull RemoteCallback callback)544         public void removeRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName,
545                 @RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId,
546                 @NonNull RemoteCallback callback) {
547             UserUtils.enforceCrossUserPermission(userId, false, "removeRoleHolderAsUser",
548                     getContext());
549             if (!UserUtils.isUserExistent(userId, getContext())) {
550                 Log.e(LOG_TAG, "user " + userId + " does not exist");
551                 return;
552             }
553 
554             getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
555                     "removeRoleHolderAsUser");
556 
557             Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
558             Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
559             Objects.requireNonNull(callback, "callback cannot be null");
560 
561             getOrCreateController(userId).onRemoveRoleHolder(roleName, packageName, flags,
562                     callback);
563         }
564 
565         @Override
clearRoleHoldersAsUser(@onNull String roleName, @RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId, @NonNull RemoteCallback callback)566         public void clearRoleHoldersAsUser(@NonNull String roleName,
567                 @RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId,
568                 @NonNull RemoteCallback callback) {
569             UserUtils.enforceCrossUserPermission(userId, false, "clearRoleHoldersAsUser",
570                     getContext());
571             if (!UserUtils.isUserExistent(userId, getContext())) {
572                 Log.e(LOG_TAG, "user " + userId + " does not exist");
573                 return;
574             }
575 
576             getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
577                     "clearRoleHoldersAsUser");
578 
579             Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
580             Objects.requireNonNull(callback, "callback cannot be null");
581 
582             getOrCreateController(userId).onClearRoleHolders(roleName, flags, callback);
583         }
584 
585         @Override
586         @Nullable
getDefaultApplicationAsUser(@onNull String roleName, @UserIdInt int userId)587         public String getDefaultApplicationAsUser(@NonNull String roleName, @UserIdInt int userId) {
588             UserUtils.enforceCrossUserPermission(userId, false, "getDefaultApplicationAsUser",
589                     getContext());
590             if (!UserUtils.isUserExistent(userId, getContext())) {
591                 Log.e(LOG_TAG, "user " + userId + " does not exist");
592                 return null;
593             }
594 
595             getContext().enforceCallingOrSelfPermission(
596                     Manifest.permission.MANAGE_DEFAULT_APPLICATIONS, "getDefaultApplicationAsUser");
597 
598             Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
599             Preconditions.checkArgumentIsSupported(DEFAULT_APPLICATION_ROLES, roleName);
600 
601             ArraySet<String> roleHolders = getOrCreateUserState(
602                     userId).getRoleHolders(roleName);
603             if (CollectionUtils.isEmpty(roleHolders)) {
604                 return null;
605             }
606             return roleHolders.valueAt(0);
607         }
608 
609         @Override
setDefaultApplicationAsUser(@onNull String roleName, @Nullable String packageName, @RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId, @NonNull RemoteCallback callback)610         public void setDefaultApplicationAsUser(@NonNull String roleName,
611                 @Nullable String packageName, @RoleManager.ManageHoldersFlags int flags,
612                 @UserIdInt int userId, @NonNull RemoteCallback callback) {
613             UserUtils.enforceCrossUserPermission(userId, false, "setDefaultApplicationAsUser",
614                     getContext());
615             if (!UserUtils.isUserExistent(userId, getContext())) {
616                 Log.e(LOG_TAG, "user " + userId + " does not exist");
617                 return;
618             }
619 
620             getContext().enforceCallingOrSelfPermission(
621                     Manifest.permission.MANAGE_DEFAULT_APPLICATIONS, "setDefaultApplicationAsUser");
622 
623             Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
624             Preconditions.checkArgumentIsSupported(DEFAULT_APPLICATION_ROLES, roleName);
625             Objects.requireNonNull(callback, "callback cannot be null");
626 
627             RoleController roleController = getOrCreateController(userId);
628             if (packageName != null) {
629                 roleController.onAddRoleHolder(roleName, packageName, flags, callback);
630             } else {
631                 roleController.onClearRoleHolders(roleName, flags, callback);
632             }
633         }
634 
635         @Override
addOnRoleHoldersChangedListenerAsUser( @onNull IOnRoleHoldersChangedListener listener, @UserIdInt int userId)636         public void addOnRoleHoldersChangedListenerAsUser(
637                 @NonNull IOnRoleHoldersChangedListener listener, @UserIdInt int userId) {
638             UserUtils.enforceCrossUserPermission(userId, true,
639                     "addOnRoleHoldersChangedListenerAsUser", getContext());
640             if (userId != UserHandleCompat.USER_ALL && !UserUtils.isUserExistent(userId,
641                     getContext())) {
642                 Log.e(LOG_TAG, "user " + userId + " does not exist");
643                 return;
644             }
645 
646             getContext().enforceCallingOrSelfPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS,
647                     "addOnRoleHoldersChangedListenerAsUser");
648 
649             Objects.requireNonNull(listener, "listener cannot be null");
650 
651             RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = getOrCreateListeners(
652                     userId);
653             listeners.register(listener);
654         }
655 
656         @Override
removeOnRoleHoldersChangedListenerAsUser( @onNull IOnRoleHoldersChangedListener listener, @UserIdInt int userId)657         public void removeOnRoleHoldersChangedListenerAsUser(
658                 @NonNull IOnRoleHoldersChangedListener listener, @UserIdInt int userId) {
659             UserUtils.enforceCrossUserPermission(userId, true,
660                     "removeOnRoleHoldersChangedListenerAsUser", getContext());
661             if (userId != UserHandleCompat.USER_ALL && !UserUtils.isUserExistent(userId,
662                     getContext())) {
663                 Log.e(LOG_TAG, "user " + userId + " does not exist");
664                 return;
665             }
666 
667             getContext().enforceCallingOrSelfPermission(Manifest.permission.OBSERVE_ROLE_HOLDERS,
668                     "removeOnRoleHoldersChangedListenerAsUser");
669 
670             Objects.requireNonNull(listener, "listener cannot be null");
671 
672             RemoteCallbackList<IOnRoleHoldersChangedListener> listeners = getListeners(userId);
673             if (listener == null) {
674                 return;
675             }
676             listeners.unregister(listener);
677         }
678 
679         @Override
isBypassingRoleQualification()680         public boolean isBypassingRoleQualification() {
681             getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
682                     "isBypassingRoleQualification");
683 
684             synchronized (mLock) {
685                 return mBypassingRoleQualification;
686             }
687         }
688 
689         @Override
setBypassingRoleQualification(boolean bypassRoleQualification)690         public void setBypassingRoleQualification(boolean bypassRoleQualification) {
691             getContext().enforceCallingOrSelfPermission(
692                     Manifest.permission.BYPASS_ROLE_QUALIFICATION, "setBypassingRoleQualification");
693 
694             synchronized (mLock) {
695                 if (mBypassingRoleQualification == bypassRoleQualification) {
696                     return;
697                 }
698                 mBypassingRoleQualification = bypassRoleQualification;
699 
700                 final int userStatesSize = mUserStates.size();
701                 for (int i = 0; i < userStatesSize; i++) {
702                     final RoleUserState userState = mUserStates.valueAt(i);
703 
704                     userState.setBypassingRoleQualification(bypassRoleQualification);
705                 }
706             }
707         }
708 
709         @Override
isRoleFallbackEnabledAsUser(@onNull String roleName, @UserIdInt int userId)710         public boolean isRoleFallbackEnabledAsUser(@NonNull String roleName,
711                 @UserIdInt int userId) {
712             UserUtils.enforceCrossUserPermission(userId, false, "isRoleFallbackEnabledAsUser",
713                     getContext());
714             if (!UserUtils.isUserExistent(userId, getContext())) {
715                 Log.e(LOG_TAG, "user " + userId + " does not exist");
716                 return false;
717             }
718 
719             getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
720                     "isRoleFallbackEnabledAsUser");
721 
722             Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
723 
724             return getOrCreateUserState(userId).isFallbackEnabled(roleName);
725         }
726 
727         @Override
setRoleFallbackEnabledAsUser(@onNull String roleName, boolean fallbackEnabled, @UserIdInt int userId)728         public void setRoleFallbackEnabledAsUser(@NonNull String roleName, boolean fallbackEnabled,
729                 @UserIdInt int userId) {
730             UserUtils.enforceCrossUserPermission(userId, false, "setRoleFallbackEnabledAsUser",
731                     getContext());
732             if (!UserUtils.isUserExistent(userId, getContext())) {
733                 Log.e(LOG_TAG, "user " + userId + " does not exist");
734                 return;
735             }
736 
737             getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
738                     "setRoleFallbackEnabledAsUser");
739 
740             Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
741 
742             getOrCreateUserState(userId).setFallbackEnabled(roleName, fallbackEnabled);
743         }
744 
745         @Override
setRoleNamesFromControllerAsUser(@onNull List<String> roleNames, @UserIdInt int userId)746         public void setRoleNamesFromControllerAsUser(@NonNull List<String> roleNames,
747                 @UserIdInt int userId) {
748             UserUtils.enforceCrossUserPermission(userId, false, "setRoleNamesFromControllerAsUser",
749                     getContext());
750             if (!UserUtils.isUserExistent(userId, getContext())) {
751                 Log.e(LOG_TAG, "user " + userId + " does not exist");
752                 return;
753             }
754 
755             getContext().enforceCallingOrSelfPermission(
756                     RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER,
757                     "setRoleNamesFromControllerAsUser");
758 
759             Objects.requireNonNull(roleNames, "roleNames cannot be null");
760 
761             getOrCreateUserState(userId).setRoleNames(roleNames);
762         }
763 
764         @Override
addRoleHolderFromControllerAsUser(@onNull String roleName, @NonNull String packageName, @UserIdInt int userId)765         public boolean addRoleHolderFromControllerAsUser(@NonNull String roleName,
766                 @NonNull String packageName, @UserIdInt int userId) {
767             UserUtils.enforceCrossUserPermission(userId, false,
768                     "addRoleHolderFromControllerAsUser", getContext());
769             if (!UserUtils.isUserExistent(userId, getContext())) {
770                 Log.e(LOG_TAG, "user " + userId + " does not exist");
771                 return false;
772             }
773 
774             getContext().enforceCallingOrSelfPermission(
775                     RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER,
776                     "addRoleHolderFromControllerAsUser");
777 
778             Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
779             Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
780 
781             return getOrCreateUserState(userId).addRoleHolder(roleName, packageName);
782         }
783 
784         @Override
removeRoleHolderFromControllerAsUser(@onNull String roleName, @NonNull String packageName, @UserIdInt int userId)785         public boolean removeRoleHolderFromControllerAsUser(@NonNull String roleName,
786                 @NonNull String packageName, @UserIdInt int userId) {
787             UserUtils.enforceCrossUserPermission(userId, false,
788                     "removeRoleHolderFromControllerAsUser", getContext());
789             if (!UserUtils.isUserExistent(userId, getContext())) {
790                 Log.e(LOG_TAG, "user " + userId + " does not exist");
791                 return false;
792             }
793 
794             getContext().enforceCallingOrSelfPermission(
795                     RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER,
796                     "removeRoleHolderFromControllerAsUser");
797 
798             Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
799             Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
800 
801             return getOrCreateUserState(userId).removeRoleHolder(roleName, packageName);
802         }
803 
804         @Override
getHeldRolesFromControllerAsUser(@onNull String packageName, @UserIdInt int userId)805         public List<String> getHeldRolesFromControllerAsUser(@NonNull String packageName,
806                 @UserIdInt int userId) {
807             UserUtils.enforceCrossUserPermission(userId, false,
808                     "getHeldRolesFromControllerAsUser", getContext());
809             if (!UserUtils.isUserExistent(userId, getContext())) {
810                 Log.e(LOG_TAG, "user " + userId + " does not exist");
811                 return Collections.emptyList();
812             }
813 
814             getContext().enforceCallingOrSelfPermission(
815                     RoleManager.PERMISSION_MANAGE_ROLES_FROM_CONTROLLER,
816                     "getHeldRolesFromControllerAsUser");
817 
818             Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
819 
820             return getOrCreateUserState(userId).getHeldRoles(packageName);
821         }
822 
823         @Override
handleShellCommand(@onNull ParcelFileDescriptor in, @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err, @NonNull String[] args)824         public int handleShellCommand(@NonNull ParcelFileDescriptor in,
825                 @NonNull ParcelFileDescriptor out, @NonNull ParcelFileDescriptor err,
826                 @NonNull String[] args) {
827             return new RoleShellCommand(this).exec(this, in.getFileDescriptor(),
828                     out.getFileDescriptor(), err.getFileDescriptor(), args);
829         }
830 
831         @Nullable
832         @Override
getBrowserRoleHolder(@serIdInt int userId)833         public String getBrowserRoleHolder(@UserIdInt int userId) {
834             final int callingUid = Binder.getCallingUid();
835             if (UserHandleCompat.getUserId(callingUid) != userId) {
836                 getContext().enforceCallingOrSelfPermission(
837                         android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
838             }
839             if (isInstantApp(callingUid)) {
840                 return null;
841             }
842 
843             final long identity = Binder.clearCallingIdentity();
844             try {
845                 return CollectionUtils.firstOrNull(getRoleHoldersAsUser(RoleManager.ROLE_BROWSER,
846                         userId));
847             } finally {
848                 Binder.restoreCallingIdentity(identity);
849             }
850         }
851 
isInstantApp(int uid)852         private boolean isInstantApp(int uid) {
853             final long identity = Binder.clearCallingIdentity();
854             try {
855                 final UserHandle user = UserHandle.getUserHandleForUid(uid);
856                 final Context userContext = getContext().createContextAsUser(user, 0);
857                 final PackageManager userPackageManager = userContext.getPackageManager();
858                 // Instant apps can not have shared UID, so it's safe to check only the first
859                 // package name here.
860                 final String packageName = ArrayUtils.firstOrNull(
861                         userPackageManager.getPackagesForUid(uid));
862                 if (packageName == null) {
863                     return false;
864                 }
865                 return userPackageManager.isInstantApp(packageName);
866             } finally {
867                 Binder.restoreCallingIdentity(identity);
868             }
869         }
870 
871         @Override
setBrowserRoleHolder(@ullable String packageName, @UserIdInt int userId)872         public boolean setBrowserRoleHolder(@Nullable String packageName, @UserIdInt int userId) {
873             final Context context = getContext();
874             context.enforceCallingOrSelfPermission(
875                     android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
876             if (UserHandleCompat.getUserId(Binder.getCallingUid()) != userId) {
877                 context.enforceCallingOrSelfPermission(
878                         android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
879             }
880 
881             if (!UserUtils.isUserExistent(userId, context)) {
882                 return false;
883             }
884 
885             final AndroidFuture<Void> future = new AndroidFuture<>();
886             final RemoteCallback callback = new RemoteCallback(result -> {
887                 boolean successful = result != null;
888                 if (successful) {
889                     future.complete(null);
890                 } else {
891                     future.completeExceptionally(new RuntimeException());
892                 }
893             });
894             final long identity = Binder.clearCallingIdentity();
895             try {
896                 if (packageName != null) {
897                     addRoleHolderAsUser(RoleManager.ROLE_BROWSER, packageName, 0, userId, callback);
898                 } else {
899                     clearRoleHoldersAsUser(RoleManager.ROLE_BROWSER, 0, userId, callback);
900                 }
901                 try {
902                     future.get(5, TimeUnit.SECONDS);
903                 } catch (InterruptedException | ExecutionException | TimeoutException e) {
904                     Log.e(LOG_TAG, "Exception while setting default browser: " + packageName, e);
905                     return false;
906                 }
907             } finally {
908                 Binder.restoreCallingIdentity(identity);
909             }
910 
911             return true;
912         }
913 
914         @Override
getSmsRoleHolder(int userId)915         public String getSmsRoleHolder(int userId) {
916             final Context context = getContext();
917             UserUtils.enforceCrossUserPermission(userId, false, "getSmsRoleHolder", context);
918             if (!UserUtils.isUserExistent(userId, getContext())) {
919                 Log.e(LOG_TAG, "user " + userId + " does not exist");
920                 return null;
921             }
922 
923             final String packageName;
924             final long identity = Binder.clearCallingIdentity();
925             try {
926                 packageName = CollectionUtils.firstOrNull(getRoleHoldersAsUser(RoleManager.ROLE_SMS,
927                         userId));
928             } finally {
929                 Binder.restoreCallingIdentity(identity);
930             }
931             if (packageName != null && !PackageUtils.canCallingOrSelfPackageQuery(packageName,
932                     userId, context)) {
933                 return null;
934             }
935             return packageName;
936         }
937 
938         @Override
getEmergencyRoleHolder(int userId)939         public String getEmergencyRoleHolder(int userId) {
940             final Context context = getContext();
941             UserUtils.enforceCrossUserPermission(userId, false, "getEmergencyRoleHolder", context);
942             if (!UserUtils.isUserExistent(userId, getContext())) {
943                 Log.e(LOG_TAG, "user " + userId + " does not exist");
944                 return null;
945             }
946 
947             getContext().enforceCallingOrSelfPermission(
948                     Manifest.permission.READ_PRIVILEGED_PHONE_STATE, "getEmergencyRoleHolder");
949 
950             final String packageName;
951             final long identity = Binder.clearCallingIdentity();
952             try {
953                 packageName = CollectionUtils.firstOrNull(getRoleHoldersAsUser(
954                         RoleManager.ROLE_EMERGENCY, userId));
955             } finally {
956                 Binder.restoreCallingIdentity(identity);
957             }
958             if (packageName != null && !PackageUtils.canCallingOrSelfPackageQuery(packageName,
959                     userId, context)) {
960                 return null;
961             }
962             return packageName;
963         }
964 
965         @Override
isRoleVisibleAsUser(@onNull String roleName, @UserIdInt int userId)966         public boolean isRoleVisibleAsUser(@NonNull String roleName, @UserIdInt int userId) {
967             UserUtils.enforceCrossUserPermission(userId, false, "isRoleVisibleAsUser",
968                     getContext());
969             if (!UserUtils.isUserExistent(userId, getContext())) {
970                 Log.e(LOG_TAG, "user " + userId + " does not exist");
971                 return false;
972             }
973 
974             getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
975                     "isRoleVisibleAsUser");
976 
977             Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
978 
979             return getOrCreateController(userId).isRoleVisible(roleName);
980         }
981 
982         @Override
isApplicationVisibleForRoleAsUser(@onNull String roleName, @NonNull String packageName, @UserIdInt int userId)983         public boolean isApplicationVisibleForRoleAsUser(@NonNull String roleName,
984                 @NonNull String packageName, @UserIdInt int userId) {
985             UserUtils.enforceCrossUserPermission(userId, false,
986                     "isApplicationVisibleForRoleAsUser", getContext());
987             if (!UserUtils.isUserExistent(userId, getContext())) {
988                 Log.e(LOG_TAG, "user " + userId + " does not exist");
989                 return false;
990             }
991 
992             getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS,
993                     "isApplicationVisibleForRoleAsUser");
994 
995             Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty");
996             Preconditions.checkStringNotEmpty(packageName, "packageName cannot be null or empty");
997 
998             return getOrCreateController(userId).isApplicationVisibleForRole(roleName, packageName);
999         }
1000 
1001         @Override
dump(@onNull FileDescriptor fd, @NonNull PrintWriter fout, @Nullable String[] args)1002         protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter fout,
1003                 @Nullable String[] args) {
1004             if (!checkDumpPermission("role", fout)) {
1005                 return;
1006             }
1007 
1008             boolean dumpAsProto = args != null && ArrayUtils.contains(args, "--proto");
1009             DualDumpOutputStream dumpOutputStream;
1010             if (dumpAsProto) {
1011                 dumpOutputStream = new DualDumpOutputStream(new ProtoOutputStream(
1012                         new FileOutputStream(fd)));
1013             } else {
1014                 fout.println("ROLE STATE (dumpsys role):");
1015                 dumpOutputStream = new DualDumpOutputStream(new IndentingPrintWriter(fout, "  "));
1016             }
1017 
1018             synchronized (mLock) {
1019                 final int userStatesSize = mUserStates.size();
1020                 for (int i = 0; i < userStatesSize; i++) {
1021                     final RoleUserState userState = mUserStates.valueAt(i);
1022 
1023                     userState.dump(dumpOutputStream, "user_states",
1024                             RoleServiceDumpProto.USER_STATES);
1025                 }
1026             }
1027 
1028             dumpOutputStream.flush();
1029         }
1030 
checkDumpPermission(@onNull String serviceName, @NonNull PrintWriter writer)1031         private boolean checkDumpPermission(@NonNull String serviceName,
1032                 @NonNull PrintWriter writer) {
1033             if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
1034                     != PackageManager.PERMISSION_GRANTED) {
1035                 writer.println("Permission Denial: can't dump " + serviceName + " from from pid="
1036                         + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
1037                         + " due to missing " + android.Manifest.permission.DUMP + " permission");
1038                 return false;
1039             } else {
1040                 return true;
1041             }
1042         }
1043     }
1044 
1045     private class Local implements RoleManagerLocal {
1046         @NonNull
1047         @Override
getRolesAndHolders(@serIdInt int userId)1048         public Map<String, Set<String>> getRolesAndHolders(@UserIdInt int userId) {
1049             // Convert ArrayMap<String, ArraySet<String>> to Map<String, Set<String>> for the API.
1050             //noinspection unchecked
1051             return (Map<String, Set<String>>) (Map<String, ?>)
1052                     getOrCreateUserState(userId).getRolesAndHolders();
1053         }
1054     }
1055 }
1056