• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 package android.content.pm;
17 
18 import static android.app.admin.DevicePolicyResources.Strings.Core.SWITCH_TO_PERSONAL_LABEL;
19 import static android.app.admin.DevicePolicyResources.Strings.Core.SWITCH_TO_WORK_LABEL;
20 
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.annotation.RequiresPermission;
24 import android.annotation.SystemApi;
25 import android.annotation.TestApi;
26 import android.app.Activity;
27 import android.app.AppOpsManager.Mode;
28 import android.app.admin.DevicePolicyManager;
29 import android.content.ComponentName;
30 import android.content.Context;
31 import android.content.Intent;
32 import android.content.res.Resources;
33 import android.graphics.drawable.Drawable;
34 import android.net.Uri;
35 import android.os.Bundle;
36 import android.os.RemoteException;
37 import android.os.UserHandle;
38 import android.os.UserManager;
39 import android.provider.Settings;
40 
41 import com.android.internal.R;
42 import com.android.internal.util.UserIcons;
43 
44 import java.util.Collection;
45 import java.util.List;
46 import java.util.Set;
47 import java.util.stream.Collectors;
48 
49 /**
50  * Class for handling cross profile operations. Apps can use this class to interact with its
51  * instance in any profile that is in {@link #getTargetUserProfiles()}. For example, app can
52  * use this class to start its main activity in managed profile.
53  */
54 public class CrossProfileApps {
55 
56     /**
57      * Broadcast signalling that the receiving app's permission to interact across profiles has
58      * changed. This includes the user, admin, or OEM changing their consent such that the
59      * permission for the app to interact across profiles has changed.
60      *
61      * <p>This broadcast is not sent when other circumstances result in a change to being able to
62      * interact across profiles in practice, such as the profile being turned off or removed, apps
63      * being uninstalled, etc. The methods {@link #canInteractAcrossProfiles()} and {@link
64      * #canRequestInteractAcrossProfiles()} can be used by apps prior to attempting to interact
65      * across profiles or attempting to request user consent to interact across profiles.
66      *
67      * <p>Apps that have set the {@code android:crossProfile} manifest attribute to {@code true}
68      * can receive this broadcast in manifest broadcast receivers. Otherwise, it can only be
69      * received by dynamically-registered broadcast receivers.
70      */
71     public static final String ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED =
72             "android.content.pm.action.CAN_INTERACT_ACROSS_PROFILES_CHANGED";
73 
74     private final Context mContext;
75     private final ICrossProfileApps mService;
76     private final UserManager mUserManager;
77     private final Resources mResources;
78 
79     /** @hide */
CrossProfileApps(Context context, ICrossProfileApps service)80     public CrossProfileApps(Context context, ICrossProfileApps service) {
81         mContext = context;
82         mService = service;
83         mUserManager = context.getSystemService(UserManager.class);
84         mResources = context.getResources();
85     }
86 
87     /**
88      * Starts the specified main activity of the caller package in the specified profile.
89      *
90      * @param component The ComponentName of the activity to launch, it must be exported and has
91      *        action {@link android.content.Intent#ACTION_MAIN}, category
92      *        {@link android.content.Intent#CATEGORY_LAUNCHER}. Otherwise, SecurityException will
93      *        be thrown.
94      * @param targetUser The UserHandle of the profile, must be one of the users returned by
95      *        {@link #getTargetUserProfiles()}, otherwise a {@link SecurityException} will
96      *        be thrown.
97      */
startMainActivity(@onNull ComponentName component, @NonNull UserHandle targetUser)98     public void startMainActivity(@NonNull ComponentName component,
99             @NonNull UserHandle targetUser) {
100         try {
101             mService.startActivityAsUser(
102                     mContext.getIApplicationThread(),
103                     mContext.getPackageName(),
104                     mContext.getAttributionTag(),
105                     component,
106                     targetUser.getIdentifier(),
107                     true,
108                     null,
109                     null);
110         } catch (RemoteException ex) {
111             throw ex.rethrowFromSystemServer();
112         }
113     }
114 
115     /**
116      * Starts the specified main activity of the caller package in the specified profile, launching
117      * in the specified activity.
118      *
119      * @param component The ComponentName of the activity to launch, it must be exported and has
120      *        action {@link android.content.Intent#ACTION_MAIN}, category
121      *        {@link android.content.Intent#CATEGORY_LAUNCHER}. Otherwise, SecurityException will
122      *        be thrown.
123      * @param targetUser The UserHandle of the profile, must be one of the users returned by
124      *        {@link #getTargetUserProfiles()}, otherwise a {@link SecurityException} will
125      *        be thrown.
126      * @param callingActivity The activity to start the new activity from for the purposes of
127      *        deciding which task the new activity should belong to. If {@code null}, the activity
128      *        will always be started in a new task.
129      * @param options The activity options or {@code null}. See {@link android.app.ActivityOptions}.
130      */
startMainActivity(@onNull ComponentName component, @NonNull UserHandle targetUser, @Nullable Activity callingActivity, @Nullable Bundle options)131     public void startMainActivity(@NonNull ComponentName component,
132             @NonNull UserHandle targetUser,
133             @Nullable Activity callingActivity,
134             @Nullable Bundle options) {
135         try {
136             mService.startActivityAsUser(
137                     mContext.getIApplicationThread(),
138                     mContext.getPackageName(),
139                     mContext.getAttributionTag(),
140                     component,
141                     targetUser.getIdentifier(),
142                     true,
143                     callingActivity != null ? callingActivity.getActivityToken() : null,
144                     options);
145         } catch (RemoteException ex) {
146             throw ex.rethrowFromSystemServer();
147         }
148     }
149 
150     /**
151      * Starts the specified activity of the caller package in the specified profile.
152      *
153      * <p>The caller must have the {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES},
154      * {@code android.Manifest.permission#INTERACT_ACROSS_USERS}, or {@code
155      * android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission. Both the caller and
156      * target user profiles must be in the same profile group. The target user must be a valid user
157      * returned from {@link #getTargetUserProfiles()}.
158      *
159      * @param intent The intent to launch. A component in the caller package must be specified.
160      * @param targetUser The {@link UserHandle} of the profile; must be one of the users returned by
161      *        {@link #getTargetUserProfiles()} if different to the calling user, otherwise a
162      *        {@link SecurityException} will be thrown.
163      * @param callingActivity The activity to start the new activity from for the purposes of
164      *        passing back any result and deciding which task the new activity should belong to. If
165      *        {@code null}, the activity will always be started in a new task and no result will be
166      *        returned.
167      */
168     @RequiresPermission(anyOf = {
169             android.Manifest.permission.INTERACT_ACROSS_PROFILES,
170             android.Manifest.permission.INTERACT_ACROSS_USERS})
startActivity( @onNull Intent intent, @NonNull UserHandle targetUser, @Nullable Activity callingActivity)171     public void startActivity(
172             @NonNull Intent intent,
173             @NonNull UserHandle targetUser,
174             @Nullable Activity callingActivity) {
175         startActivity(intent, targetUser, callingActivity, /* options= */ null);
176     }
177 
178     /**
179      * Starts the specified activity of the caller package in the specified profile.
180      *
181      * <p>The caller must have the {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES},
182      * {@code android.Manifest.permission#INTERACT_ACROSS_USERS}, or {@code
183      * android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission. Both the caller and
184      * target user profiles must be in the same profile group. The target user must be a valid user
185      * returned from {@link #getTargetUserProfiles()}.
186      *
187      * @param intent The intent to launch. A component in the caller package must be specified.
188      * @param targetUser The {@link UserHandle} of the profile; must be one of the users returned by
189      *        {@link #getTargetUserProfiles()} if different to the calling user, otherwise a
190      *        {@link SecurityException} will be thrown.
191      * @param callingActivity The activity to start the new activity from for the purposes of
192      *        passing back any result and deciding which task the new activity should belong to. If
193      *        {@code null}, the activity will always be started in a new task and no result will be
194      *        returned.
195      * @param options The activity options or {@code null}. See {@link android.app.ActivityOptions}.
196      */
197     @RequiresPermission(anyOf = {
198             android.Manifest.permission.INTERACT_ACROSS_PROFILES,
199             android.Manifest.permission.INTERACT_ACROSS_USERS})
startActivity( @onNull Intent intent, @NonNull UserHandle targetUser, @Nullable Activity callingActivity, @Nullable Bundle options)200     public void startActivity(
201             @NonNull Intent intent,
202             @NonNull UserHandle targetUser,
203             @Nullable Activity callingActivity,
204             @Nullable Bundle options) {
205         try {
206             mService.startActivityAsUserByIntent(
207                     mContext.getIApplicationThread(),
208                     mContext.getPackageName(),
209                     mContext.getAttributionTag(),
210                     intent,
211                     targetUser.getIdentifier(),
212                     callingActivity != null ? callingActivity.getActivityToken() : null,
213                     options);
214         } catch (RemoteException ex) {
215             throw ex.rethrowFromSystemServer();
216         }
217     }
218 
219     /**
220      * Starts the specified activity of the caller package in the specified profile. Unlike
221      * {@link #startMainActivity}, this can start any activity of the caller package, not just
222      * the main activity.
223      * The caller must have the {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES}
224      * or {@link android.Manifest.permission#START_CROSS_PROFILE_ACTIVITIES}
225      * permission and both the caller and target user profiles must be in the same profile group.
226      *
227      * @param component The ComponentName of the activity to launch. It must be exported.
228      * @param targetUser The UserHandle of the profile, must be one of the users returned by
229      *        {@link #getTargetUserProfiles()}, otherwise a {@link SecurityException} will
230      *        be thrown.
231      * @param callingActivity The activity to start the new activity from for the purposes of
232      *        deciding which task the new activity should belong to. If {@code null}, the activity
233      *        will always be started in a new task.
234      * @param options The activity options or {@code null}. See {@link android.app.ActivityOptions}.
235      * @hide
236      */
237     @SystemApi
238     @RequiresPermission(anyOf = {
239             android.Manifest.permission.INTERACT_ACROSS_PROFILES,
240             android.Manifest.permission.START_CROSS_PROFILE_ACTIVITIES})
startActivity( @onNull ComponentName component, @NonNull UserHandle targetUser, @Nullable Activity callingActivity, @Nullable Bundle options)241     public void startActivity(
242             @NonNull ComponentName component,
243             @NonNull UserHandle targetUser,
244             @Nullable Activity callingActivity,
245             @Nullable Bundle options) {
246         try {
247             mService.startActivityAsUser(
248                     mContext.getIApplicationThread(),
249                     mContext.getPackageName(),
250                     mContext.getAttributionTag(),
251                     component,
252                     targetUser.getIdentifier(),
253                     false,
254                     callingActivity != null ? callingActivity.getActivityToken() : null,
255                     options);
256         } catch (RemoteException ex) {
257             throw ex.rethrowFromSystemServer();
258         }
259     }
260 
261     /**
262      * Starts the specified activity of the caller package in the specified profile. Unlike
263      * {@link #startMainActivity}, this can start any activity of the caller package, not just
264      * the main activity.
265      * The caller must have the {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES}
266      * or {@link android.Manifest.permission#START_CROSS_PROFILE_ACTIVITIES}
267      * permission and both the caller and target user profiles must be in the same profile group.
268      *
269      * @param component The ComponentName of the activity to launch. It must be exported.
270      * @param targetUser The UserHandle of the profile, must be one of the users returned by
271      *        {@link #getTargetUserProfiles()}, otherwise a {@link SecurityException} will
272      *        be thrown.
273      * @hide
274      */
275     @SystemApi
276     @RequiresPermission(anyOf = {
277             android.Manifest.permission.INTERACT_ACROSS_PROFILES,
278             android.Manifest.permission.START_CROSS_PROFILE_ACTIVITIES})
startActivity(@onNull ComponentName component, @NonNull UserHandle targetUser)279     public void startActivity(@NonNull ComponentName component, @NonNull UserHandle targetUser) {
280         try {
281             mService.startActivityAsUser(mContext.getIApplicationThread(),
282                     mContext.getPackageName(), mContext.getAttributionTag(), component,
283                     targetUser.getIdentifier(), false, null, null);
284         } catch (RemoteException ex) {
285             throw ex.rethrowFromSystemServer();
286         }
287     }
288 
289     /**
290      * Return a list of user profiles that that the caller can use when calling other APIs in this
291      * class.
292      * <p>
293      * A user profile would be considered as a valid target user profile, provided that:
294      * <ul>
295      * <li>It gets caller app installed</li>
296      * <li>It is not equal to the calling user</li>
297      * <li>It is in the same profile group of calling user profile</li>
298      * <li>It is enabled</li>
299      * </ul>
300      *
301      * @see UserManager#getUserProfiles()
302      */
getTargetUserProfiles()303     public @NonNull List<UserHandle> getTargetUserProfiles() {
304         try {
305             return mService.getTargetUserProfiles(mContext.getPackageName());
306         } catch (RemoteException ex) {
307             throw ex.rethrowFromSystemServer();
308         }
309     }
310 
311     /**
312      * Return a label that calling app can show to user for the semantic of profile switching --
313      * launching its own activity in specified user profile. For example, it may return
314      * "Switch to work" if the given user handle is the managed profile one.
315      *
316      * @param userHandle The UserHandle of the target profile, must be one of the users returned by
317      *        {@link #getTargetUserProfiles()}, otherwise a {@link SecurityException} will
318      *        be thrown.
319      * @return a label that calling app can show user for the semantic of launching its own
320      *         activity in the specified user profile.
321      *
322      * @see #startMainActivity(ComponentName, UserHandle)
323      */
getProfileSwitchingLabel(@onNull UserHandle userHandle)324     public @NonNull CharSequence getProfileSwitchingLabel(@NonNull UserHandle userHandle) {
325         verifyCanAccessUser(userHandle);
326 
327         final boolean isManagedProfile = mUserManager.isManagedProfile(userHandle.getIdentifier());
328         final DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
329         return dpm.getResources().getString(
330                 getUpdatableProfileSwitchingLabelId(isManagedProfile),
331                 () -> getDefaultProfileSwitchingLabel(isManagedProfile));
332     }
333 
getUpdatableProfileSwitchingLabelId(boolean isManagedProfile)334     private String getUpdatableProfileSwitchingLabelId(boolean isManagedProfile) {
335         return isManagedProfile ? SWITCH_TO_WORK_LABEL : SWITCH_TO_PERSONAL_LABEL;
336     }
337 
getDefaultProfileSwitchingLabel(boolean isManagedProfile)338     private String getDefaultProfileSwitchingLabel(boolean isManagedProfile) {
339         final int stringRes = isManagedProfile
340                 ? R.string.managed_profile_label : R.string.user_owner_label;
341         return mResources.getString(stringRes);
342     }
343 
344 
345     /**
346      * Return a drawable that calling app can show to user for the semantic of profile switching --
347      * launching its own activity in specified user profile. For example, it may return a briefcase
348      * icon if the given user handle is the managed profile one.
349      *
350      * @param userHandle The UserHandle of the target profile, must be one of the users returned by
351      *        {@link #getTargetUserProfiles()}, otherwise a {@link SecurityException} will
352      *        be thrown.
353      * @return an icon that calling app can show user for the semantic of launching its own
354      *         activity in specified user profile.
355      *
356      * @see #startMainActivity(ComponentName, UserHandle)
357      */
getProfileSwitchingIconDrawable(@onNull UserHandle userHandle)358     public @NonNull Drawable getProfileSwitchingIconDrawable(@NonNull UserHandle userHandle) {
359         verifyCanAccessUser(userHandle);
360 
361         final boolean isManagedProfile =
362                 mUserManager.isManagedProfile(userHandle.getIdentifier());
363         if (isManagedProfile) {
364             return mContext.getPackageManager().getUserBadgeForDensityNoBackground(
365                     userHandle, /* density= */ 0);
366         } else {
367             return UserIcons.getDefaultUserIcon(
368                     mResources, UserHandle.USER_SYSTEM, true /* light */);
369         }
370     }
371 
372     /**
373      * Returns whether the calling package can request to navigate the user to
374      * the relevant settings page to request user consent to interact across profiles.
375      *
376      * <p>If {@code true}, the navigation intent can be obtained via {@link
377      * #createRequestInteractAcrossProfilesIntent()}. The package can then listen to {@link
378      * #ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED} broadcasts.
379      *
380      * <p>Specifically, returns whether the following are all true:
381      * <ul>
382      * <li>{@code UserManager#getEnabledProfileIds(int)} returns at least one other profile for the
383      * calling user.</li>
384      * <li>The calling app has requested
385      * {@code android.Manifest.permission.INTERACT_ACROSS_PROFILES} in its manifest.</li>
386      * <li>The calling app is not a profile owner within the profile group of the calling user.</li>
387      * </ul>
388      *
389      * <p>Note that in order for the user to be able to grant the consent, the requesting package
390      * must be allowlisted by the admin or the OEM and installed in the other profile. If this is
391      * not the case the user will be shown a message explaining why they can't grant the consent.
392      *
393      * <p>Note that user consent could already be granted if given a return value of {@code true}.
394      * The package's current ability to interact across profiles can be checked with {@link
395      * #canInteractAcrossProfiles()}.
396      *
397      * @return true if the calling package can request to interact across profiles.
398      */
canRequestInteractAcrossProfiles()399     public boolean canRequestInteractAcrossProfiles() {
400         try {
401             return mService.canRequestInteractAcrossProfiles(mContext.getPackageName());
402         } catch (RemoteException ex) {
403             throw ex.rethrowFromSystemServer();
404         }
405     }
406 
407     /**
408      * Returns whether the calling package can interact across profiles.
409 
410      * <p>Specifically, returns whether the following are all true:
411      * <ul>
412      * <li>{@link #getTargetUserProfiles()} returns a non-empty list for the calling user.</li>
413      * <li>The user has previously consented to cross-profile communication for the calling
414      * package.</li>
415      * <li>The calling package has either been allowlisted by default by the OEM or has been
416      * explicitly allowlisted by the admin via
417      * {@link android.app.admin.DevicePolicyManager#setCrossProfilePackages(ComponentName, Set)}.
418      * </li>
419      * </ul>
420      *
421      * <p>If {@code false}, the package's current ability to request user consent to interact across
422      * profiles can be checked with {@link #canRequestInteractAcrossProfiles()}. If {@code true},
423      * user consent can be obtained via {@link #createRequestInteractAcrossProfilesIntent()}. The
424      * package can then listen to {@link #ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED} broadcasts.
425      *
426      * @return true if the calling package can interact across profiles.
427      * @throws SecurityException if {@code mContext.getPackageName()} does not belong to the
428      * calling UID.
429      */
canInteractAcrossProfiles()430     public boolean canInteractAcrossProfiles() {
431         try {
432             return mService.canInteractAcrossProfiles(mContext.getPackageName());
433         } catch (RemoteException ex) {
434             throw ex.rethrowFromSystemServer();
435         }
436     }
437 
438     /**
439      * Returns an {@link Intent} to open the settings page that allows the user to decide whether
440      * the calling app can interact across profiles.
441      *
442      * <p>The method {@link #canRequestInteractAcrossProfiles()} must be returning {@code true}.
443      *
444      * <p>Note that the user may already have given consent and the app may already be able to
445      * interact across profiles, even if {@link #canRequestInteractAcrossProfiles()} is {@code
446      * true}. The current ability to interact across profiles is given by {@link
447      * #canInteractAcrossProfiles()}.
448      *
449      * @return an {@link Intent} to open the settings page that allows the user to decide whether
450      * the app can interact across profiles
451      *
452      * @throws SecurityException if {@code mContext.getPackageName()} does not belong to the
453      * calling UID, or {@link #canRequestInteractAcrossProfiles()} is {@code false}.
454      */
createRequestInteractAcrossProfilesIntent()455     public @NonNull Intent createRequestInteractAcrossProfilesIntent() {
456         if (!canRequestInteractAcrossProfiles()) {
457             throw new SecurityException(
458                     "The calling package can not request to interact across profiles.");
459         }
460         final Intent settingsIntent = new Intent();
461         settingsIntent.setAction(Settings.ACTION_MANAGE_CROSS_PROFILE_ACCESS);
462         final Uri packageUri = Uri.parse("package:" + mContext.getPackageName());
463         settingsIntent.setData(packageUri);
464         return settingsIntent;
465     }
466 
467     /**
468      * Sets the app-op for {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES} that is
469      * configurable by users in Settings. This configures it for the profile group of the calling
470      * package.
471      *
472      * <p>Before calling, check {@link #canConfigureInteractAcrossProfiles(String)} and do not call
473      * if it is {@code false}. If presenting a user interface, do not allow the user to configure
474      * the app-op in that case.
475      *
476      * <p>The underlying app-op {@link android.app.AppOpsManager#OP_INTERACT_ACROSS_PROFILES} should
477      * never be set directly. This method ensures that the app-op is kept in sync for the app across
478      * each user in the profile group and that those apps are sent a broadcast when their ability to
479      * interact across profiles changes.
480      *
481      * <p>This method should be used directly whenever a user's action results in a change in an
482      * app's ability to interact across profiles, as defined by the return value of {@link
483      * #canInteractAcrossProfiles()}. This includes user consent changes in Settings or during
484      * provisioning.
485      *
486      * <p>If other changes could have affected the app's ability to interact across profiles, as
487      * defined by the return value of {@link #canInteractAcrossProfiles()}, such as changes to the
488      * admin or OEM consent whitelists, then {@link #resetInteractAcrossProfilesAppOps(Collection,
489      * Set)} should be used.
490      *
491      * <p>If the caller does not have the {@link android.Manifest.permission
492      * #CONFIGURE_INTERACT_ACROSS_PROFILES} permission, then they must have the permissions that
493      * would have been required to call {@link android.app.AppOpsManager#setMode(int, int, String,
494      * int)}, which includes {@link android.Manifest.permission#MANAGE_APP_OPS_MODES}.
495      *
496      * <p>Also requires either {@link android.Manifest.permission#INTERACT_ACROSS_USERS} or {@link
497      * android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}.
498      *
499      * @hide
500      */
501     @RequiresPermission(
502             allOf={android.Manifest.permission.CONFIGURE_INTERACT_ACROSS_PROFILES,
503                     android.Manifest.permission.INTERACT_ACROSS_USERS})
setInteractAcrossProfilesAppOp(@onNull String packageName, @Mode int newMode)504     public void setInteractAcrossProfilesAppOp(@NonNull String packageName, @Mode int newMode) {
505         try {
506             mService.setInteractAcrossProfilesAppOp(packageName, newMode);
507         } catch (RemoteException ex) {
508             throw ex.rethrowFromSystemServer();
509         }
510     }
511 
512     /**
513      * Returns whether the given package can have its ability to interact across profiles configured
514      * by the user. This means that every other condition to interact across profiles has been set.
515      *
516      * <p>This differs from {@link #canRequestInteractAcrossProfiles()} since it will not return
517      * {@code false} simply when the target profile is disabled.
518      *
519      * @hide
520      */
521     @TestApi
canConfigureInteractAcrossProfiles(@onNull String packageName)522     public boolean canConfigureInteractAcrossProfiles(@NonNull String packageName) {
523         try {
524             return mService.canConfigureInteractAcrossProfiles(packageName);
525         } catch (RemoteException ex) {
526             throw ex.rethrowFromSystemServer();
527         }
528     }
529 
530     /**
531      * Returns {@code true} if the given package has requested
532      * {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES} and the user has at least one
533      * other profile in the same profile group.
534      *
535      * <p>This differs from {@link #canConfigureInteractAcrossProfiles(String)} since it will
536      * not return {@code false} if the app is not allowlisted or not installed in the other profile.
537      *
538      * <p>Note that platform-signed apps that are automatically granted the permission and are not
539      * allowlisted by the OEM will not be included in this list.
540      *
541      * @hide
542      */
canUserAttemptToConfigureInteractAcrossProfiles(String packageName)543     public boolean canUserAttemptToConfigureInteractAcrossProfiles(String packageName) {
544         try {
545             return mService.canUserAttemptToConfigureInteractAcrossProfiles(packageName);
546         } catch (RemoteException ex) {
547             throw ex.rethrowFromSystemServer();
548         }
549     }
550     /**
551      * For each of the packages defined in {@code previousCrossProfilePackages} but not included in
552      * {@code newCrossProfilePackages}, resets the app-op for {@link android.Manifest.permission
553      * #INTERACT_ACROSS_PROFILES} back to its default value if it can no longer be configured by
554      * users in Settings, as defined by {@link #canConfigureInteractAcrossProfiles(String)}.
555      *
556      * <p>This method should be used whenever an app's ability to interact across profiles could
557      * have changed as a result of non-user actions, such as changes to admin or OEM consent
558      * whitelists.
559      *
560      * <p>If the caller does not have the {@link android.Manifest.permission
561      * #CONFIGURE_INTERACT_ACROSS_PROFILES} permission, then they must have the permissions that
562      * would have been required to call {@link android.app.AppOpsManager#setMode(int, int, String,
563      * int)}, which includes {@link android.Manifest.permission#MANAGE_APP_OPS_MODES}.
564      *
565      * <p>Also requires either {@link android.Manifest.permission#INTERACT_ACROSS_USERS} or {@link
566      * android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}.
567      *
568      * @hide
569      */
570     @RequiresPermission(
571             allOf={android.Manifest.permission.CONFIGURE_INTERACT_ACROSS_PROFILES,
572                     android.Manifest.permission.INTERACT_ACROSS_USERS})
resetInteractAcrossProfilesAppOps( @onNull Collection<String> previousCrossProfilePackages, @NonNull Set<String> newCrossProfilePackages)573     public void resetInteractAcrossProfilesAppOps(
574             @NonNull Collection<String> previousCrossProfilePackages,
575             @NonNull Set<String> newCrossProfilePackages) {
576         if (previousCrossProfilePackages.isEmpty()) {
577             return;
578         }
579         final List<String> unsetCrossProfilePackages =
580                 previousCrossProfilePackages.stream()
581                         .filter(packageName -> !newCrossProfilePackages.contains(packageName))
582                         .collect(Collectors.toList());
583         if (unsetCrossProfilePackages.isEmpty()) {
584             return;
585         }
586         try {
587             mService.resetInteractAcrossProfilesAppOps(unsetCrossProfilePackages);
588         } catch (RemoteException ex) {
589             throw ex.rethrowFromSystemServer();
590         }
591     }
592 
593     /**
594      * Clears the app-op for {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES} back to
595      * its default value for every package on the device.
596      *
597      * <p>This method can be used to ensure that app-op state is not left around on existing users
598      * for previously-configured profiles.
599      *
600      * <p>If the caller does not have the {@link android.Manifest.permission
601      * #CONFIGURE_INTERACT_ACROSS_PROFILES} permission, then they must have the permissions that
602      * would have been required to call {@link android.app.AppOpsManager#setMode(int, int, String,
603      * int)}, which includes {@link android.Manifest.permission#MANAGE_APP_OPS_MODES}.
604      *
605      * <p>Also requires either {@link android.Manifest.permission#INTERACT_ACROSS_USERS} or {@link
606      * android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}.
607      *
608      * @hide
609      */
610     @RequiresPermission(
611             allOf={android.Manifest.permission.CONFIGURE_INTERACT_ACROSS_PROFILES,
612                     android.Manifest.permission.INTERACT_ACROSS_USERS})
clearInteractAcrossProfilesAppOps()613     public void clearInteractAcrossProfilesAppOps() {
614         try {
615             mService.clearInteractAcrossProfilesAppOps();
616         } catch (RemoteException ex) {
617             throw ex.rethrowFromSystemServer();
618         }
619     }
620 
verifyCanAccessUser(UserHandle userHandle)621     private void verifyCanAccessUser(UserHandle userHandle) {
622         if (!getTargetUserProfiles().contains(userHandle)) {
623             throw new SecurityException("Not allowed to access " + userHandle);
624         }
625     }
626 }
627