blob: dc3a0297641620967d7bc968ad94394319a3fa25 [file] [log] [blame]
Tony Mak1b708e62017-10-12 10:59:11 +01001/*
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 */
Tony Makb0d22622018-01-18 12:49:49 +000016package android.content.pm;
Tony Mak1b708e62017-10-12 10:59:11 +010017
18import android.annotation.NonNull;
kholoud mohamed5b2dfe32020-01-02 11:55:22 +000019import android.annotation.Nullable;
Varun Shahacad1382018-11-28 11:56:08 -080020import android.annotation.RequiresPermission;
21import android.annotation.SystemApi;
Alex Kershaw16406c32020-02-17 12:28:53 +000022import android.app.Activity;
Alex Kershaw6fb8a022020-01-09 11:33:56 +000023import android.app.AppOpsManager.Mode;
Tony Mak1b708e62017-10-12 10:59:11 +010024import android.content.ComponentName;
25import android.content.Context;
kholoud mohamed5b2dfe32020-01-02 11:55:22 +000026import android.content.Intent;
Tony Mak82465132017-11-29 21:00:30 +000027import android.content.res.Resources;
Tony Mak82465132017-11-29 21:00:30 +000028import android.graphics.drawable.Drawable;
kholoud mohamed5b2dfe32020-01-02 11:55:22 +000029import android.net.Uri;
Alex Kershawa9f00522020-03-10 16:29:49 +000030import android.os.Bundle;
Tony Mak1b708e62017-10-12 10:59:11 +010031import android.os.RemoteException;
32import android.os.UserHandle;
33import android.os.UserManager;
kholoud mohamed5b2dfe32020-01-02 11:55:22 +000034import android.provider.Settings;
Tony Mak1b708e62017-10-12 10:59:11 +010035
Tony Mak82465132017-11-29 21:00:30 +000036import com.android.internal.R;
37import com.android.internal.util.UserIcons;
38
Alex Kershaw4b0197d2020-01-15 20:00:05 +000039import java.util.Collection;
Tony Mak1b708e62017-10-12 10:59:11 +010040import java.util.List;
kholoud mohamed946df392019-12-12 17:43:32 +000041import java.util.Set;
Alex Kershaw4b0197d2020-01-15 20:00:05 +000042import java.util.stream.Collectors;
Tony Mak1b708e62017-10-12 10:59:11 +010043
44/**
45 * Class for handling cross profile operations. Apps can use this class to interact with its
46 * instance in any profile that is in {@link #getTargetUserProfiles()}. For example, app can
47 * use this class to start its main activity in managed profile.
48 */
49public class CrossProfileApps {
Alex Kershaw6fb8a022020-01-09 11:33:56 +000050
51 /**
Alex Kershawc4b5cc52020-02-13 19:10:08 +000052 * Broadcast signalling that the receiving app's permission to interact across profiles has
53 * changed. This includes the user, admin, or OEM changing their consent such that the
54 * permission for the app to interact across profiles has changed.
55 *
56 * <p>This broadcast is not sent when other circumstances result in a change to being able to
57 * interact across profiles in practice, such as the profile being turned off or removed, apps
58 * being uninstalled, etc. The methods {@link #canInteractAcrossProfiles()} and {@link
59 * #canRequestInteractAcrossProfiles()} can be used by apps prior to attempting to interact
60 * across profiles or attempting to request user consent to interact across profiles.
Alex Kershaw6fb8a022020-01-09 11:33:56 +000061 *
62 * <p>Apps that have set the {@code android:crossProfile} manifest attribute to {@code true}
63 * can receive this broadcast in manifest broadcast receivers. Otherwise, it can only be
64 * received by dynamically-registered broadcast receivers.
65 */
66 public static final String ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED =
67 "android.content.pm.action.CAN_INTERACT_ACROSS_PROFILES_CHANGED";
68
Tony Mak1b708e62017-10-12 10:59:11 +010069 private final Context mContext;
70 private final ICrossProfileApps mService;
Tony Mak82465132017-11-29 21:00:30 +000071 private final UserManager mUserManager;
72 private final Resources mResources;
Tony Mak1b708e62017-10-12 10:59:11 +010073
74 /** @hide */
75 public CrossProfileApps(Context context, ICrossProfileApps service) {
76 mContext = context;
77 mService = service;
Tony Mak82465132017-11-29 21:00:30 +000078 mUserManager = context.getSystemService(UserManager.class);
79 mResources = context.getResources();
Tony Mak1b708e62017-10-12 10:59:11 +010080 }
81
82 /**
83 * Starts the specified main activity of the caller package in the specified profile.
84 *
85 * @param component The ComponentName of the activity to launch, it must be exported and has
86 * action {@link android.content.Intent#ACTION_MAIN}, category
87 * {@link android.content.Intent#CATEGORY_LAUNCHER}. Otherwise, SecurityException will
88 * be thrown.
Tony Makb0d22622018-01-18 12:49:49 +000089 * @param targetUser The UserHandle of the profile, must be one of the users returned by
Tony Mak1b708e62017-10-12 10:59:11 +010090 * {@link #getTargetUserProfiles()}, otherwise a {@link SecurityException} will
91 * be thrown.
Tony Mak1b708e62017-10-12 10:59:11 +010092 */
Tony Makb0d22622018-01-18 12:49:49 +000093 public void startMainActivity(@NonNull ComponentName component,
94 @NonNull UserHandle targetUser) {
Tony Mak1b708e62017-10-12 10:59:11 +010095 try {
Tony Makde32b832018-04-30 15:11:57 +010096 mService.startActivityAsUser(
97 mContext.getIApplicationThread(),
98 mContext.getPackageName(),
Philip P. Moltmann12ac3f42020-03-05 15:01:29 -080099 mContext.getAttributionTag(),
Tony Makde32b832018-04-30 15:11:57 +0100100 component,
Varun Shahacad1382018-11-28 11:56:08 -0800101 targetUser.getIdentifier(),
102 true);
103 } catch (RemoteException ex) {
104 throw ex.rethrowFromSystemServer();
105 }
106 }
107
108 /**
Jonathan Scottd72fc8d2020-01-20 16:22:58 +0000109 * Starts the specified activity of the caller package in the specified profile.
110 *
Alex Kershawc4b5cc52020-02-13 19:10:08 +0000111 * <p>The caller must have the {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES},
112 * {@code android.Manifest.permission#INTERACT_ACROSS_USERS}, or {@code
113 * android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission. Both the caller and
114 * target user profiles must be in the same profile group. The target user must be a valid user
115 * returned from {@link #getTargetUserProfiles()}.
Jonathan Scottd72fc8d2020-01-20 16:22:58 +0000116 *
117 * @param intent The intent to launch. A component in the caller package must be specified.
118 * @param targetUser The {@link UserHandle} of the profile; must be one of the users returned by
119 * {@link #getTargetUserProfiles()} if different to the calling user, otherwise a
120 * {@link SecurityException} will be thrown.
Alex Kershaw16406c32020-02-17 12:28:53 +0000121 * @param callingActivity The activity to start the new activity from for the purposes of
122 * deciding which task the new activity should belong to. If {@code null}, the activity
123 * will always be started in a new task.
Jonathan Scottd72fc8d2020-01-20 16:22:58 +0000124 */
125 @RequiresPermission(anyOf = {
126 android.Manifest.permission.INTERACT_ACROSS_PROFILES,
127 android.Manifest.permission.INTERACT_ACROSS_USERS})
Alex Kershaw16406c32020-02-17 12:28:53 +0000128 public void startActivity(
129 @NonNull Intent intent,
130 @NonNull UserHandle targetUser,
131 @Nullable Activity callingActivity) {
Alex Kershawa9f00522020-03-10 16:29:49 +0000132 startActivity(intent, targetUser, callingActivity, /* options= */ null);
133 }
134
135 /**
136 * Starts the specified activity of the caller package in the specified profile.
137 *
138 * <p>The caller must have the {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES},
139 * {@code android.Manifest.permission#INTERACT_ACROSS_USERS}, or {@code
140 * android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission. Both the caller and
141 * target user profiles must be in the same profile group. The target user must be a valid user
142 * returned from {@link #getTargetUserProfiles()}.
143 *
144 * @param intent The intent to launch. A component in the caller package must be specified.
145 * @param targetUser The {@link UserHandle} of the profile; must be one of the users returned by
146 * {@link #getTargetUserProfiles()} if different to the calling user, otherwise a
147 * {@link SecurityException} will be thrown.
148 * @param callingActivity The activity to start the new activity from for the purposes of
149 * deciding which task the new activity should belong to. If {@code null}, the activity
150 * will always be started in a new task.
151 * @param options The activity options or {@code null}. See {@link android.app.ActivityOptions}.
152 */
153 @RequiresPermission(anyOf = {
154 android.Manifest.permission.INTERACT_ACROSS_PROFILES,
155 android.Manifest.permission.INTERACT_ACROSS_USERS})
156 public void startActivity(
157 @NonNull Intent intent,
158 @NonNull UserHandle targetUser,
159 @Nullable Activity callingActivity,
160 @Nullable Bundle options) {
Jonathan Scottd72fc8d2020-01-20 16:22:58 +0000161 try {
162 mService.startActivityAsUserByIntent(
163 mContext.getIApplicationThread(),
164 mContext.getPackageName(),
Philip P. Moltmann12ac3f42020-03-05 15:01:29 -0800165 mContext.getAttributionTag(),
Jonathan Scottd72fc8d2020-01-20 16:22:58 +0000166 intent,
Alex Kershaw16406c32020-02-17 12:28:53 +0000167 targetUser.getIdentifier(),
Alex Kershawa9f00522020-03-10 16:29:49 +0000168 callingActivity != null ? callingActivity.getActivityToken() : null,
169 options);
Jonathan Scottd72fc8d2020-01-20 16:22:58 +0000170 } catch (RemoteException ex) {
171 throw ex.rethrowFromSystemServer();
172 }
173 }
174
175 /**
Varun Shahbdb849f2019-01-16 12:06:18 -0800176 * Starts the specified activity of the caller package in the specified profile. Unlike
177 * {@link #startMainActivity}, this can start any activity of the caller package, not just
178 * the main activity.
179 * The caller must have the {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES}
180 * permission and both the caller and target user profiles must be in the same profile group.
Varun Shahacad1382018-11-28 11:56:08 -0800181 *
182 * @param component The ComponentName of the activity to launch. It must be exported.
183 * @param targetUser The UserHandle of the profile, must be one of the users returned by
184 * {@link #getTargetUserProfiles()}, otherwise a {@link SecurityException} will
185 * be thrown.
186 * @hide
187 */
188 @SystemApi
189 @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_PROFILES)
Varun Shahbdb849f2019-01-16 12:06:18 -0800190 public void startActivity(@NonNull ComponentName component, @NonNull UserHandle targetUser) {
Varun Shahacad1382018-11-28 11:56:08 -0800191 try {
192 mService.startActivityAsUser(mContext.getIApplicationThread(),
Philip P. Moltmann12ac3f42020-03-05 15:01:29 -0800193 mContext.getPackageName(), mContext.getAttributionTag(), component,
Philip P. Moltmannee295092020-02-10 08:46:26 -0800194 targetUser.getIdentifier(), false);
Tony Mak1b708e62017-10-12 10:59:11 +0100195 } catch (RemoteException ex) {
196 throw ex.rethrowFromSystemServer();
197 }
198 }
199
200 /**
201 * Return a list of user profiles that that the caller can use when calling other APIs in this
202 * class.
203 * <p>
204 * A user profile would be considered as a valid target user profile, provided that:
205 * <ul>
206 * <li>It gets caller app installed</li>
207 * <li>It is not equal to the calling user</li>
208 * <li>It is in the same profile group of calling user profile</li>
209 * <li>It is enabled</li>
210 * </ul>
211 *
212 * @see UserManager#getUserProfiles()
213 */
214 public @NonNull List<UserHandle> getTargetUserProfiles() {
215 try {
216 return mService.getTargetUserProfiles(mContext.getPackageName());
217 } catch (RemoteException ex) {
218 throw ex.rethrowFromSystemServer();
219 }
220 }
Tony Mak82465132017-11-29 21:00:30 +0000221
222 /**
223 * Return a label that calling app can show to user for the semantic of profile switching --
224 * launching its own activity in specified user profile. For example, it may return
225 * "Switch to work" if the given user handle is the managed profile one.
226 *
227 * @param userHandle The UserHandle of the target profile, must be one of the users returned by
228 * {@link #getTargetUserProfiles()}, otherwise a {@link SecurityException} will
229 * be thrown.
230 * @return a label that calling app can show user for the semantic of launching its own
231 * activity in the specified user profile.
232 *
Aurimas Liutikas7f695332018-05-31 21:07:32 -0700233 * @see #startMainActivity(ComponentName, UserHandle)
Tony Mak82465132017-11-29 21:00:30 +0000234 */
235 public @NonNull CharSequence getProfileSwitchingLabel(@NonNull UserHandle userHandle) {
236 verifyCanAccessUser(userHandle);
237
238 final int stringRes = mUserManager.isManagedProfile(userHandle.getIdentifier())
239 ? R.string.managed_profile_label
240 : R.string.user_owner_label;
241 return mResources.getString(stringRes);
242 }
243
244 /**
Tony Makb0d22622018-01-18 12:49:49 +0000245 * Return a drawable that calling app can show to user for the semantic of profile switching --
Tony Mak82465132017-11-29 21:00:30 +0000246 * launching its own activity in specified user profile. For example, it may return a briefcase
247 * icon if the given user handle is the managed profile one.
248 *
249 * @param userHandle The UserHandle of the target profile, must be one of the users returned by
250 * {@link #getTargetUserProfiles()}, otherwise a {@link SecurityException} will
251 * be thrown.
252 * @return an icon that calling app can show user for the semantic of launching its own
253 * activity in specified user profile.
254 *
Tony Makb0d22622018-01-18 12:49:49 +0000255 * @see #startMainActivity(ComponentName, UserHandle)
Tony Mak82465132017-11-29 21:00:30 +0000256 */
Tony Makb0d22622018-01-18 12:49:49 +0000257 public @NonNull Drawable getProfileSwitchingIconDrawable(@NonNull UserHandle userHandle) {
Tony Mak82465132017-11-29 21:00:30 +0000258 verifyCanAccessUser(userHandle);
259
260 final boolean isManagedProfile =
261 mUserManager.isManagedProfile(userHandle.getIdentifier());
262 if (isManagedProfile) {
263 return mResources.getDrawable(R.drawable.ic_corp_badge, null);
264 } else {
265 return UserIcons.getDefaultUserIcon(
266 mResources, UserHandle.USER_SYSTEM, true /* light */);
267 }
268 }
269
kholoud mohamed946df392019-12-12 17:43:32 +0000270 /**
Alex Kershawc4b5cc52020-02-13 19:10:08 +0000271 * Returns whether the calling package can request user consent to interact across profiles.
kholoud mohamed946df392019-12-12 17:43:32 +0000272 *
Alex Kershawc4b5cc52020-02-13 19:10:08 +0000273 * <p>If {@code true}, user consent can be obtained via {@link
274 * #createRequestInteractAcrossProfilesIntent()}. The package can then listen to {@link
275 * #ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED} broadcasts.
kholoud mohamed946df392019-12-12 17:43:32 +0000276 *
277 * <p>Specifically, returns whether the following are all true:
278 * <ul>
279 * <li>{@link #getTargetUserProfiles()} returns a non-empty list for the calling user.</li>
280 * <li>The calling app has requested</li>
281 * {@code android.Manifest.permission.INTERACT_ACROSS_PROFILES} in its manifest.
282 * <li>The calling package has either been whitelisted by default by the OEM or has been
283 * explicitly whitelisted by the admin via
284 * {@link android.app.admin.DevicePolicyManager#setCrossProfilePackages(ComponentName, Set)}.
285 * </li>
286 * </ul>
287 *
Alex Kershawc4b5cc52020-02-13 19:10:08 +0000288 * <p>Note that user consent could already be granted if given a return value of {@code true}.
289 * The package's current ability to interact across profiles can be checked with {@link
290 * #canInteractAcrossProfiles()}.
291 *
kholoud mohamed946df392019-12-12 17:43:32 +0000292 * @return true if the calling package can request to interact across profiles.
293 */
294 public boolean canRequestInteractAcrossProfiles() {
295 try {
296 return mService.canRequestInteractAcrossProfiles(mContext.getPackageName());
297 } catch (RemoteException ex) {
298 throw ex.rethrowFromSystemServer();
299 }
300 }
301
302 /**
303 * Returns whether the calling package can interact across profiles.
Alex Kershawc4b5cc52020-02-13 19:10:08 +0000304
kholoud mohamed946df392019-12-12 17:43:32 +0000305 * <p>Specifically, returns whether the following are all true:
306 * <ul>
307 * <li>{@link #getTargetUserProfiles()} returns a non-empty list for the calling user.</li>
308 * <li>The user has previously consented to cross-profile communication for the calling
309 * package.</li>
310 * <li>The calling package has either been whitelisted by default by the OEM or has been
311 * explicitly whitelisted by the admin via
312 * {@link android.app.admin.DevicePolicyManager#setCrossProfilePackages(ComponentName, Set)}.
313 * </li>
314 * </ul>
315 *
Alex Kershawc4b5cc52020-02-13 19:10:08 +0000316 * <p>If {@code false}, the package's current ability to request user consent to interact across
317 * profiles can be checked with {@link #canRequestInteractAcrossProfiles()}. If {@code true},
318 * user consent can be obtained via {@link #createRequestInteractAcrossProfilesIntent()}. The
319 * package can then listen to {@link #ACTION_CAN_INTERACT_ACROSS_PROFILES_CHANGED} broadcasts.
320 *
kholoud mohamed946df392019-12-12 17:43:32 +0000321 * @return true if the calling package can interact across profiles.
322 * @throws SecurityException if {@code mContext.getPackageName()} does not belong to the
323 * calling UID.
324 */
325 public boolean canInteractAcrossProfiles() {
326 try {
327 return mService.canInteractAcrossProfiles(mContext.getPackageName());
328 } catch (RemoteException ex) {
329 throw ex.rethrowFromSystemServer();
330 }
331 }
332
kholoud mohamed5b2dfe32020-01-02 11:55:22 +0000333 /**
334 * Returns an {@link Intent} to open the settings page that allows the user to decide whether
Alex Kershawc4b5cc52020-02-13 19:10:08 +0000335 * the calling app can interact across profiles.
kholoud mohamed5b2dfe32020-01-02 11:55:22 +0000336 *
337 * <p>Returns {@code null} if {@link #canRequestInteractAcrossProfiles()} is {@code false}.
338 *
Alex Kershawc4b5cc52020-02-13 19:10:08 +0000339 * <p>Note that the user may already have given consent and the app may already be able to
340 * interact across profiles, even if {@link #canRequestInteractAcrossProfiles()} is {@code
341 * true}. The current ability to interact across profiles is given by {@link
342 * #canInteractAcrossProfiles()}.
343 *
kholoud mohamed5b2dfe32020-01-02 11:55:22 +0000344 * @return an {@link Intent} to open the settings page that allows the user to decide whether
345 * the app can interact across profiles
346 *
347 * @throws SecurityException if {@code mContext.getPackageName()} does not belong to the
348 * calling UID.
349 */
350 public @Nullable Intent createRequestInteractAcrossProfilesIntent() {
351 if (!canRequestInteractAcrossProfiles()) {
352 return null;
353 }
354 final Intent settingsIntent = new Intent();
355 settingsIntent.setAction(Settings.ACTION_MANAGE_CROSS_PROFILE_ACCESS);
356 final Uri packageUri = Uri.parse("package:" + mContext.getPackageName());
357 settingsIntent.setData(packageUri);
358 return settingsIntent;
359 }
360
Alex Kershaw6fb8a022020-01-09 11:33:56 +0000361 /**
362 * Sets the app-op for {@link android.Manifest.permission#INTERACT_ACROSS_PROFILES} that is
363 * configurable by users in Settings. This configures it for the profile group of the calling
364 * package.
365 *
Alex Kershaw4b0197d2020-01-15 20:00:05 +0000366 * <p>Before calling, check {@link #canConfigureInteractAcrossProfiles(String)} and do not call
367 * if it is {@code false}. If presenting a user interface, do not allow the user to configure
368 * the app-op in that case.
Alex Kershaw6fb8a022020-01-09 11:33:56 +0000369 *
370 * <p>The underlying app-op {@link android.app.AppOpsManager#OP_INTERACT_ACROSS_PROFILES} should
371 * never be set directly. This method ensures that the app-op is kept in sync for the app across
372 * each user in the profile group and that those apps are sent a broadcast when their ability to
373 * interact across profiles changes.
374 *
Alex Kershaw4b0197d2020-01-15 20:00:05 +0000375 * <p>This method should be used directly whenever a user's action results in a change in an
376 * app's ability to interact across profiles, as defined by the return value of {@link
377 * #canInteractAcrossProfiles()}. This includes user consent changes in Settings or during
378 * provisioning.
379 *
380 * <p>If other changes could have affected the app's ability to interact across profiles, as
381 * defined by the return value of {@link #canInteractAcrossProfiles()}, such as changes to the
Alex Kershaw0124a092020-02-07 14:02:48 +0000382 * admin or OEM consent whitelists, then {@link #resetInteractAcrossProfilesAppOps(Collection,
383 * Set)} should be used.
384 *
385 * <p>If the caller does not have the {@link android.Manifest.permission
386 * #CONFIGURE_INTERACT_ACROSS_PROFILES} permission, then they must have the permissions that
387 * would have been required to call {@link android.app.AppOpsManager#setMode(int, int, String,
388 * int)}, which includes {@link android.Manifest.permission#MANAGE_APP_OPS_MODES}.
389 *
390 * <p>Also requires either {@link android.Manifest.permission#INTERACT_ACROSS_USERS} or {@link
391 * android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}.
Alex Kershaw6fb8a022020-01-09 11:33:56 +0000392 *
393 * @hide
394 */
395 @RequiresPermission(
Alex Kershaw0124a092020-02-07 14:02:48 +0000396 allOf={android.Manifest.permission.CONFIGURE_INTERACT_ACROSS_PROFILES,
Alex Kershaw6fb8a022020-01-09 11:33:56 +0000397 android.Manifest.permission.INTERACT_ACROSS_USERS})
398 public void setInteractAcrossProfilesAppOp(@NonNull String packageName, @Mode int newMode) {
399 try {
400 mService.setInteractAcrossProfilesAppOp(packageName, newMode);
401 } catch (RemoteException ex) {
402 throw ex.rethrowFromSystemServer();
403 }
404 }
405
Alex Kershaw4b0197d2020-01-15 20:00:05 +0000406 /**
407 * Returns whether the given package can have its ability to interact across profiles configured
408 * by the user. This means that every other condition to interact across profiles has been set.
409 *
410 * <p>This differs from {@link #canRequestInteractAcrossProfiles()} since it will not return
411 * {@code false} simply when the target profile is disabled.
412 *
413 * @hide
414 */
415 public boolean canConfigureInteractAcrossProfiles(@NonNull String packageName) {
416 try {
417 return mService.canConfigureInteractAcrossProfiles(packageName);
418 } catch (RemoteException ex) {
419 throw ex.rethrowFromSystemServer();
420 }
421 }
422
423 /**
424 * For each of the packages defined in {@code previousCrossProfilePackages} but not included in
425 * {@code newCrossProfilePackages}, resets the app-op for {@link android.Manifest.permission
426 * #INTERACT_ACROSS_PROFILES} back to its default value if it can no longer be configured by
427 * users in Settings, as defined by {@link #canConfigureInteractAcrossProfiles(String)}.
428 *
429 * <p>This method should be used whenever an app's ability to interact across profiles could
430 * have changed as a result of non-user actions, such as changes to admin or OEM consent
431 * whitelists.
432 *
Alex Kershaw0124a092020-02-07 14:02:48 +0000433 * <p>If the caller does not have the {@link android.Manifest.permission
434 * #CONFIGURE_INTERACT_ACROSS_PROFILES} permission, then they must have the permissions that
435 * would have been required to call {@link android.app.AppOpsManager#setMode(int, int, String,
436 * int)}, which includes {@link android.Manifest.permission#MANAGE_APP_OPS_MODES}.
437 *
438 * <p>Also requires either {@link android.Manifest.permission#INTERACT_ACROSS_USERS} or {@link
439 * android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}.
440 *
Alex Kershaw4b0197d2020-01-15 20:00:05 +0000441 * @hide
442 */
443 @RequiresPermission(
Alex Kershaw0124a092020-02-07 14:02:48 +0000444 allOf={android.Manifest.permission.CONFIGURE_INTERACT_ACROSS_PROFILES,
Alex Kershaw4b0197d2020-01-15 20:00:05 +0000445 android.Manifest.permission.INTERACT_ACROSS_USERS})
446 public void resetInteractAcrossProfilesAppOps(
447 @NonNull Collection<String> previousCrossProfilePackages,
448 @NonNull Set<String> newCrossProfilePackages) {
449 if (previousCrossProfilePackages.isEmpty()) {
450 return;
451 }
452 final List<String> unsetCrossProfilePackages =
453 previousCrossProfilePackages.stream()
454 .filter(packageName -> !newCrossProfilePackages.contains(packageName))
455 .collect(Collectors.toList());
456 if (unsetCrossProfilePackages.isEmpty()) {
457 return;
458 }
459 try {
460 mService.resetInteractAcrossProfilesAppOps(unsetCrossProfilePackages);
461 } catch (RemoteException ex) {
462 throw ex.rethrowFromSystemServer();
463 }
464 }
465
Tony Mak82465132017-11-29 21:00:30 +0000466 private void verifyCanAccessUser(UserHandle userHandle) {
467 if (!getTargetUserProfiles().contains(userHandle)) {
468 throw new SecurityException("Not allowed to access " + userHandle);
469 }
470 }
Tony Mak1b708e62017-10-12 10:59:11 +0100471}