1 /*
2  * Copyright (C) 2015 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.server.pm;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.app.ActivityManager;
22 import android.app.AppGlobals;
23 import android.content.ContentResolver;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.pm.ApplicationInfo;
27 import android.content.pm.IPackageManager;
28 import android.content.pm.PackageManager;
29 import android.content.pm.PackageManagerInternal;
30 import android.os.Binder;
31 import android.os.Bundle;
32 import android.os.Process;
33 import android.os.RemoteException;
34 import android.os.UserHandle;
35 import android.os.UserManager;
36 import android.os.UserManagerInternal;
37 import android.provider.Settings;
38 import android.provider.Settings.Global;
39 import android.telephony.SubscriptionInfo;
40 import android.telephony.SubscriptionManager;
41 import android.util.Log;
42 import android.util.Slog;
43 import android.util.SparseArray;
44 
45 import com.android.internal.util.Preconditions;
46 import com.android.server.LocalServices;
47 
48 import com.google.android.collect.Sets;
49 
50 import org.xmlpull.v1.XmlPullParser;
51 import org.xmlpull.v1.XmlSerializer;
52 
53 import java.io.IOException;
54 import java.io.PrintWriter;
55 import java.util.List;
56 import java.util.Objects;
57 import java.util.Set;
58 
59 /**
60  * Utility methods for user restrictions.
61  *
62  * <p>See {@link UserManagerService} for the method suffixes.
63  */
64 public class UserRestrictionsUtils {
65     private static final String TAG = "UserRestrictionsUtils";
66 
UserRestrictionsUtils()67     private UserRestrictionsUtils() {
68     }
69 
newSetWithUniqueCheck(String[] strings)70     private static Set<String> newSetWithUniqueCheck(String[] strings) {
71         final Set<String> ret = Sets.newArraySet(strings);
72 
73         // Make sure there's no overlap.
74         Preconditions.checkState(ret.size() == strings.length);
75         return ret;
76     }
77 
78     public static final Set<String> USER_RESTRICTIONS = newSetWithUniqueCheck(new String[] {
79             UserManager.DISALLOW_CONFIG_WIFI,
80             UserManager.DISALLOW_CONFIG_LOCALE,
81             UserManager.DISALLOW_MODIFY_ACCOUNTS,
82             UserManager.DISALLOW_INSTALL_APPS,
83             UserManager.DISALLOW_UNINSTALL_APPS,
84             UserManager.DISALLOW_SHARE_LOCATION,
85             UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
86             UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY,
87             UserManager.DISALLOW_CONFIG_BLUETOOTH,
88             UserManager.DISALLOW_BLUETOOTH,
89             UserManager.DISALLOW_BLUETOOTH_SHARING,
90             UserManager.DISALLOW_USB_FILE_TRANSFER,
91             UserManager.DISALLOW_CONFIG_CREDENTIALS,
92             UserManager.DISALLOW_REMOVE_USER,
93             UserManager.DISALLOW_REMOVE_MANAGED_PROFILE,
94             UserManager.DISALLOW_DEBUGGING_FEATURES,
95             UserManager.DISALLOW_CONFIG_VPN,
96             UserManager.DISALLOW_CONFIG_DATE_TIME,
97             UserManager.DISALLOW_CONFIG_TETHERING,
98             UserManager.DISALLOW_NETWORK_RESET,
99             UserManager.DISALLOW_FACTORY_RESET,
100             UserManager.DISALLOW_ADD_USER,
101             UserManager.DISALLOW_ADD_MANAGED_PROFILE,
102             UserManager.ENSURE_VERIFY_APPS,
103             UserManager.DISALLOW_CONFIG_CELL_BROADCASTS,
104             UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS,
105             UserManager.DISALLOW_APPS_CONTROL,
106             UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
107             UserManager.DISALLOW_UNMUTE_MICROPHONE,
108             UserManager.DISALLOW_ADJUST_VOLUME,
109             UserManager.DISALLOW_OUTGOING_CALLS,
110             UserManager.DISALLOW_SMS,
111             UserManager.DISALLOW_FUN,
112             UserManager.DISALLOW_CREATE_WINDOWS,
113             UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS,
114             UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE,
115             UserManager.DISALLOW_OUTGOING_BEAM,
116             UserManager.DISALLOW_WALLPAPER,
117             UserManager.DISALLOW_SAFE_BOOT,
118             UserManager.ALLOW_PARENT_PROFILE_APP_LINKING,
119             UserManager.DISALLOW_RECORD_AUDIO,
120             UserManager.DISALLOW_CAMERA,
121             UserManager.DISALLOW_RUN_IN_BACKGROUND,
122             UserManager.DISALLOW_DATA_ROAMING,
123             UserManager.DISALLOW_SET_USER_ICON,
124             UserManager.DISALLOW_SET_WALLPAPER,
125             UserManager.DISALLOW_OEM_UNLOCK,
126             UserManager.DISALLOW_UNMUTE_DEVICE,
127             UserManager.DISALLOW_AUTOFILL,
128             UserManager.DISALLOW_CONTENT_CAPTURE,
129             UserManager.DISALLOW_CONTENT_SUGGESTIONS,
130             UserManager.DISALLOW_USER_SWITCH,
131             UserManager.DISALLOW_UNIFIED_PASSWORD,
132             UserManager.DISALLOW_CONFIG_LOCATION,
133             UserManager.DISALLOW_AIRPLANE_MODE,
134             UserManager.DISALLOW_CONFIG_BRIGHTNESS,
135             UserManager.DISALLOW_SHARE_INTO_MANAGED_PROFILE,
136             UserManager.DISALLOW_AMBIENT_DISPLAY,
137             UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT,
138             UserManager.DISALLOW_PRINTING,
139             UserManager.DISALLOW_CONFIG_PRIVATE_DNS
140     });
141 
142     /**
143      * Set of user restriction which we don't want to persist.
144      */
145     private static final Set<String> NON_PERSIST_USER_RESTRICTIONS = Sets.newArraySet(
146             UserManager.DISALLOW_RECORD_AUDIO
147     );
148 
149     /**
150      * User restrictions that cannot be set by profile owners of secondary users. When set by DO
151      * they will be applied to all users.
152      */
153     private static final Set<String> PRIMARY_USER_ONLY_RESTRICTIONS = Sets.newArraySet(
154             UserManager.DISALLOW_BLUETOOTH,
155             UserManager.DISALLOW_USB_FILE_TRANSFER,
156             UserManager.DISALLOW_CONFIG_TETHERING,
157             UserManager.DISALLOW_NETWORK_RESET,
158             UserManager.DISALLOW_FACTORY_RESET,
159             UserManager.DISALLOW_ADD_USER,
160             UserManager.DISALLOW_CONFIG_CELL_BROADCASTS,
161             UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS,
162             UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
163             UserManager.DISALLOW_SMS,
164             UserManager.DISALLOW_FUN,
165             UserManager.DISALLOW_SAFE_BOOT,
166             UserManager.DISALLOW_CREATE_WINDOWS,
167             UserManager.DISALLOW_DATA_ROAMING,
168             UserManager.DISALLOW_AIRPLANE_MODE
169     );
170 
171     /**
172      * User restrictions that cannot be set by profile owners. Applied to all users.
173      */
174     private static final Set<String> DEVICE_OWNER_ONLY_RESTRICTIONS = Sets.newArraySet(
175             UserManager.DISALLOW_USER_SWITCH,
176             UserManager.DISALLOW_CONFIG_PRIVATE_DNS
177     );
178 
179     /**
180      * User restrictions that can't be changed by device owner or profile owner.
181      */
182     private static final Set<String> IMMUTABLE_BY_OWNERS = Sets.newArraySet(
183             UserManager.DISALLOW_RECORD_AUDIO,
184             UserManager.DISALLOW_WALLPAPER,
185             UserManager.DISALLOW_OEM_UNLOCK
186     );
187 
188     /**
189      * Special user restrictions that can be applied to a user as well as to all users globally,
190      * depending on callers.  When device owner sets them, they'll be applied to all users.
191      */
192     private static final Set<String> GLOBAL_RESTRICTIONS = Sets.newArraySet(
193             UserManager.DISALLOW_ADJUST_VOLUME,
194             UserManager.DISALLOW_BLUETOOTH_SHARING,
195             UserManager.DISALLOW_CONFIG_DATE_TIME,
196             UserManager.DISALLOW_SYSTEM_ERROR_DIALOGS,
197             UserManager.DISALLOW_RUN_IN_BACKGROUND,
198             UserManager.DISALLOW_UNMUTE_MICROPHONE,
199             UserManager.DISALLOW_UNMUTE_DEVICE,
200             UserManager.DISALLOW_CAMERA
201     );
202 
203     /**
204      * Special user restrictions that profile owner of an organization-owned managed profile can
205      * set on the parent profile instance to apply them globally.
206      */
207     private static final Set<String> PROFILE_OWNER_ORGANIZATION_OWNED_GLOBAL_RESTRICTIONS =
208             Sets.newArraySet(
209                     UserManager.DISALLOW_AIRPLANE_MODE,
210                     UserManager.DISALLOW_CONFIG_DATE_TIME,
211                     UserManager.DISALLOW_CONFIG_PRIVATE_DNS
212     );
213 
214     /**
215      * Special user restrictions that profile owner of an organization-owned managed profile can
216      * set on the parent profile instance to apply them on the personal profile.
217      */
218     private static final Set<String> PROFILE_OWNER_ORGANIZATION_OWNED_LOCAL_RESTRICTIONS =
219             Sets.newArraySet(
220                     UserManager.DISALLOW_CONFIG_BLUETOOTH,
221                     UserManager.DISALLOW_CONFIG_LOCATION,
222                     UserManager.DISALLOW_CONFIG_WIFI,
223                     UserManager.DISALLOW_CONTENT_CAPTURE,
224                     UserManager.DISALLOW_CONTENT_SUGGESTIONS,
225                     UserManager.DISALLOW_DEBUGGING_FEATURES,
226                     UserManager.DISALLOW_SHARE_LOCATION,
227                     UserManager.DISALLOW_OUTGOING_CALLS,
228                     UserManager.DISALLOW_CAMERA,
229                     UserManager.DISALLOW_BLUETOOTH,
230                     UserManager.DISALLOW_BLUETOOTH_SHARING,
231                     UserManager.DISALLOW_CONFIG_CELL_BROADCASTS,
232                     UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS,
233                     UserManager.DISALLOW_CONFIG_TETHERING,
234                     UserManager.DISALLOW_DATA_ROAMING,
235                     UserManager.DISALLOW_SAFE_BOOT,
236                     UserManager.DISALLOW_SMS,
237                     UserManager.DISALLOW_USB_FILE_TRANSFER,
238                     UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA,
239                     UserManager.DISALLOW_UNMUTE_MICROPHONE
240     );
241 
242     /**
243      * User restrictions that default to {@code true} for managed profile owners.
244      *
245      * NB: {@link UserManager#DISALLOW_INSTALL_UNKNOWN_SOURCES} is also set by default but it is
246      * not set to existing profile owners unless they used to have INSTALL_NON_MARKET_APPS disabled
247      * in settings. So it is handled separately.
248      */
249     private static final Set<String> DEFAULT_ENABLED_FOR_MANAGED_PROFILES = Sets.newArraySet(
250             UserManager.DISALLOW_BLUETOOTH_SHARING
251     );
252 
253     /**
254      * Special user restrictions that are always applied to all users no matter who sets them.
255      */
256     private static final Set<String> PROFILE_GLOBAL_RESTRICTIONS = Sets.newArraySet(
257             UserManager.ENSURE_VERIFY_APPS,
258             UserManager.DISALLOW_AIRPLANE_MODE,
259             UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY
260     );
261 
262     /**
263      * Returns whether the given restriction name is valid (and logs it if it isn't).
264      */
isValidRestriction(@onNull String restriction)265     public static boolean isValidRestriction(@NonNull String restriction) {
266         if (!USER_RESTRICTIONS.contains(restriction)) {
267             // Log this, with severity depending on the source.
268             final int uid = Binder.getCallingUid();
269             String[] pkgs = null;
270             try {
271                 pkgs = AppGlobals.getPackageManager().getPackagesForUid(uid);
272             } catch (RemoteException e) {
273                 // Ignore
274             }
275             StringBuilder msg = new StringBuilder("Unknown restriction queried by uid ");
276             msg.append(uid);
277             if (pkgs != null && pkgs.length > 0) {
278                 msg.append(" (");
279                 msg.append(pkgs[0]);
280                 if (pkgs.length > 1) {
281                     msg.append(" et al");
282                 }
283                 msg.append(")");
284             }
285             msg.append(": ");
286             msg.append(restriction);
287             if (restriction != null && isSystemApp(uid, pkgs)) {
288                 Slog.wtf(TAG, msg.toString());
289             } else {
290                 Slog.e(TAG, msg.toString());
291             }
292             return false;
293         }
294         return true;
295     }
296 
297     /** Returns whether the given uid (or corresponding packageList) is for a System app. */
isSystemApp(int uid, String[] packageList)298     private static boolean isSystemApp(int uid, String[] packageList) {
299         if (UserHandle.isCore(uid)) {
300             return true;
301         }
302         if (packageList == null) {
303             return false;
304         }
305         final IPackageManager pm = AppGlobals.getPackageManager();
306         for (int i = 0; i < packageList.length; i++) {
307             try {
308                 final int flags = PackageManager.MATCH_UNINSTALLED_PACKAGES
309                         | PackageManager.MATCH_DIRECT_BOOT_AWARE
310                         | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
311                 final ApplicationInfo appInfo =
312                         pm.getApplicationInfo(packageList[i], flags, UserHandle.getUserId(uid));
313                 if (appInfo != null && appInfo.isSystemApp()) {
314                     return true;
315                 }
316             } catch (RemoteException e) {
317                 // Ignore
318             }
319         }
320         return false;
321     }
322 
writeRestrictions(@onNull XmlSerializer serializer, @Nullable Bundle restrictions, @NonNull String tag)323     public static void writeRestrictions(@NonNull XmlSerializer serializer,
324             @Nullable Bundle restrictions, @NonNull String tag) throws IOException {
325         if (restrictions == null) {
326             return;
327         }
328 
329         serializer.startTag(null, tag);
330         for (String key : restrictions.keySet()) {
331             if (NON_PERSIST_USER_RESTRICTIONS.contains(key)) {
332                 continue; // Don't persist.
333             }
334             if (USER_RESTRICTIONS.contains(key)) {
335                 if (restrictions.getBoolean(key)) {
336                     serializer.attribute(null, key, "true");
337                 }
338                 continue;
339             }
340             Log.w(TAG, "Unknown user restriction detected: " + key);
341         }
342         serializer.endTag(null, tag);
343     }
344 
readRestrictions(XmlPullParser parser, Bundle restrictions)345     public static void readRestrictions(XmlPullParser parser, Bundle restrictions) {
346         restrictions.clear();
347         for (String key : USER_RESTRICTIONS) {
348             final String value = parser.getAttributeValue(null, key);
349             if (value != null) {
350                 restrictions.putBoolean(key, Boolean.parseBoolean(value));
351             }
352         }
353     }
354 
readRestrictions(XmlPullParser parser)355     public static Bundle readRestrictions(XmlPullParser parser) {
356         final Bundle result = new Bundle();
357         readRestrictions(parser, result);
358         return result;
359     }
360 
361     /**
362      * @return {@code in} itself when it's not null, or an empty bundle (which can writable).
363      */
nonNull(@ullable Bundle in)364     public static Bundle nonNull(@Nullable Bundle in) {
365         return in != null ? in : new Bundle();
366     }
367 
isEmpty(@ullable Bundle in)368     public static boolean isEmpty(@Nullable Bundle in) {
369         return (in == null) || (in.size() == 0);
370     }
371 
372     /**
373      * Returns {@code true} if given bundle is not null and contains {@code true} for a given
374      * restriction.
375      */
contains(@ullable Bundle in, String restriction)376     public static boolean contains(@Nullable Bundle in, String restriction) {
377         return in != null && in.getBoolean(restriction);
378     }
379 
380     /**
381      * Creates a copy of the {@code in} Bundle.  If {@code in} is null, it'll return an empty
382      * bundle.
383      *
384      * <p>The resulting {@link Bundle} is always writable. (i.e. it won't return
385      * {@link Bundle#EMPTY})
386      */
clone(@ullable Bundle in)387     public static @NonNull Bundle clone(@Nullable Bundle in) {
388         return (in != null) ? new Bundle(in) : new Bundle();
389     }
390 
merge(@onNull Bundle dest, @Nullable Bundle in)391     public static void merge(@NonNull Bundle dest, @Nullable Bundle in) {
392         Objects.requireNonNull(dest);
393         Preconditions.checkArgument(dest != in);
394         if (in == null) {
395             return;
396         }
397         for (String key : in.keySet()) {
398             if (in.getBoolean(key, false)) {
399                 dest.putBoolean(key, true);
400             }
401         }
402     }
403 
404     /**
405      * @return true if a restriction is settable by device owner.
406      */
canDeviceOwnerChange(String restriction)407     public static boolean canDeviceOwnerChange(String restriction) {
408         return !IMMUTABLE_BY_OWNERS.contains(restriction);
409     }
410 
411     /**
412      * @return true if a restriction is settable by profile owner.  Note it takes a user ID because
413      * some restrictions can be changed by PO only when it's running on the system user.
414      */
canProfileOwnerChange(String restriction, int userId)415     public static boolean canProfileOwnerChange(String restriction, int userId) {
416         return !IMMUTABLE_BY_OWNERS.contains(restriction)
417                 && !DEVICE_OWNER_ONLY_RESTRICTIONS.contains(restriction)
418                 && !(userId != UserHandle.USER_SYSTEM
419                     && PRIMARY_USER_ONLY_RESTRICTIONS.contains(restriction));
420     }
421 
422     /**
423      * @return true if a restriction is settable by profile owner of an organization owned device.
424      */
canProfileOwnerOfOrganizationOwnedDeviceChange(String restriction)425     public static boolean canProfileOwnerOfOrganizationOwnedDeviceChange(String restriction) {
426         return PROFILE_OWNER_ORGANIZATION_OWNED_GLOBAL_RESTRICTIONS.contains(restriction)
427                 || PROFILE_OWNER_ORGANIZATION_OWNED_LOCAL_RESTRICTIONS.contains(restriction);
428     }
429 
430     /**
431      * Returns the user restrictions that default to {@code true} for managed profile owners.
432      */
getDefaultEnabledForManagedProfiles()433     public static @NonNull Set<String> getDefaultEnabledForManagedProfiles() {
434         return DEFAULT_ENABLED_FOR_MANAGED_PROFILES;
435     }
436 
437     /**
438      * Whether given user restriction should be enforced globally.
439      */
isGlobal(@serManagerInternal.OwnerType int restrictionOwnerType, String key)440     public static boolean isGlobal(@UserManagerInternal.OwnerType int restrictionOwnerType,
441             String key) {
442         return ((restrictionOwnerType == UserManagerInternal.OWNER_TYPE_DEVICE_OWNER) && (
443                 PRIMARY_USER_ONLY_RESTRICTIONS.contains(key) || GLOBAL_RESTRICTIONS.contains(key)))
444                 || ((restrictionOwnerType
445                 == UserManagerInternal.OWNER_TYPE_PROFILE_OWNER_OF_ORGANIZATION_OWNED_DEVICE)
446                 && PROFILE_OWNER_ORGANIZATION_OWNED_GLOBAL_RESTRICTIONS.contains(key))
447                 || PROFILE_GLOBAL_RESTRICTIONS.contains(key)
448                 || DEVICE_OWNER_ONLY_RESTRICTIONS.contains(key);
449     }
450 
451     /**
452      * Whether given user restriction should be enforced locally.
453      */
isLocal(@serManagerInternal.OwnerType int restrictionOwnerType, String key)454     public static boolean isLocal(@UserManagerInternal.OwnerType int restrictionOwnerType,
455             String key) {
456         return !isGlobal(restrictionOwnerType, key);
457     }
458 
459     /**
460      * @return true if two Bundles contain the same user restriction.
461      * A null bundle and an empty bundle are considered to be equal.
462      */
areEqual(@ullable Bundle a, @Nullable Bundle b)463     public static boolean areEqual(@Nullable Bundle a, @Nullable Bundle b) {
464         if (a == b) {
465             return true;
466         }
467         if (isEmpty(a)) {
468             return isEmpty(b);
469         }
470         if (isEmpty(b)) {
471             return false;
472         }
473         for (String key : a.keySet()) {
474             if (a.getBoolean(key) != b.getBoolean(key)) {
475                 return false;
476             }
477         }
478         for (String key : b.keySet()) {
479             if (a.getBoolean(key) != b.getBoolean(key)) {
480                 return false;
481             }
482         }
483         return true;
484     }
485 
486     /**
487      * Takes a new use restriction set and the previous set, and apply the restrictions that have
488      * changed.
489      *
490      * <p>Note this method is called by {@link UserManagerService} without holding any locks.
491      */
applyUserRestrictions(Context context, int userId, Bundle newRestrictions, Bundle prevRestrictions)492     public static void applyUserRestrictions(Context context, int userId,
493             Bundle newRestrictions, Bundle prevRestrictions) {
494         for (String key : USER_RESTRICTIONS) {
495             final boolean newValue = newRestrictions.getBoolean(key);
496             final boolean prevValue = prevRestrictions.getBoolean(key);
497 
498             if (newValue != prevValue) {
499                 applyUserRestriction(context, userId, key, newValue);
500             }
501         }
502     }
503 
504     /**
505      * Apply each user restriction.
506      *
507      * <p>See also {@link #isSettingRestrictedForUser()},
508      * which should be in sync with this method.
509      */
applyUserRestriction(Context context, int userId, String key, boolean newValue)510     private static void applyUserRestriction(Context context, int userId, String key,
511             boolean newValue) {
512         if (UserManagerService.DBG) {
513             Log.d(TAG, "Applying user restriction: userId=" + userId
514                     + " key=" + key + " value=" + newValue);
515         }
516         // When certain restrictions are cleared, we don't update the system settings,
517         // because these settings are changeable on the Settings UI and we don't know the original
518         // value -- for example LOCATION_MODE might have been off already when the restriction was
519         // set, and in that case even if the restriction is lifted, changing it to ON would be
520         // wrong.  So just don't do anything in such a case.  If the user hopes to enable location
521         // later, they can do it on the Settings UI.
522         // WARNING: Remember that Settings.Global and Settings.Secure are changeable via adb.
523         // To prevent this from happening for a given user restriction, you have to add a check to
524         // SettingsProvider.isGlobalOrSecureSettingRestrictedForUser.
525 
526         final ContentResolver cr = context.getContentResolver();
527         final long id = Binder.clearCallingIdentity();
528         try {
529             switch (key) {
530                 case UserManager.DISALLOW_DATA_ROAMING:
531                     if (newValue) {
532                         // DISALLOW_DATA_ROAMING user restriction is set.
533 
534                         // Multi sim device.
535                         SubscriptionManager subscriptionManager = context
536                                 .getSystemService(SubscriptionManager.class);
537                         final List<SubscriptionInfo> subscriptionInfoList =
538                             subscriptionManager.getActiveSubscriptionInfoList();
539                         if (subscriptionInfoList != null) {
540                             for (SubscriptionInfo subInfo : subscriptionInfoList) {
541                                 android.provider.Settings.Global.putStringForUser(cr,
542                                     android.provider.Settings.Global.DATA_ROAMING
543                                     + subInfo.getSubscriptionId(), "0", userId);
544                             }
545                         }
546 
547                         // Single sim device.
548                         android.provider.Settings.Global.putStringForUser(cr,
549                             android.provider.Settings.Global.DATA_ROAMING, "0", userId);
550                     }
551                     break;
552                 case UserManager.DISALLOW_SHARE_LOCATION:
553                     if (newValue) {
554                         android.provider.Settings.Secure.putIntForUser(cr,
555                                 android.provider.Settings.Secure.LOCATION_MODE,
556                                 android.provider.Settings.Secure.LOCATION_MODE_OFF,
557                                 userId);
558                     }
559                     break;
560                 case UserManager.DISALLOW_DEBUGGING_FEATURES:
561                     if (newValue) {
562                         // Only disable adb if changing for system user, since it is global
563                         // TODO: should this be admin user?
564                         if (userId == UserHandle.USER_SYSTEM) {
565                             android.provider.Settings.Global.putStringForUser(cr,
566                                     android.provider.Settings.Global.ADB_ENABLED, "0",
567                                     userId);
568                             android.provider.Settings.Global.putStringForUser(cr,
569                                     android.provider.Settings.Global.ADB_WIFI_ENABLED, "0",
570                                     userId);
571                         }
572                     }
573                     break;
574                 case UserManager.ENSURE_VERIFY_APPS:
575                     if (newValue) {
576                         android.provider.Settings.Global.putStringForUser(
577                                 context.getContentResolver(),
578                                 android.provider.Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, "1",
579                                 userId);
580                     }
581                     break;
582                 case UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY:
583                     setInstallMarketAppsRestriction(cr, userId, getNewUserRestrictionSetting(
584                             context, userId, UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
585                             newValue));
586                     break;
587                 case UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES:
588                     // Since Android O, the secure setting is not available to be changed by the
589                     // user. Hence, when the restriction is cleared, we need to reset the state of
590                     // the setting to its default value which is now 1.
591                     setInstallMarketAppsRestriction(cr, userId, getNewUserRestrictionSetting(
592                             context, userId, UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY,
593                             newValue));
594                     break;
595                 case UserManager.DISALLOW_RUN_IN_BACKGROUND:
596                     if (newValue) {
597                         int currentUser = ActivityManager.getCurrentUser();
598                         if (currentUser != userId && userId != UserHandle.USER_SYSTEM) {
599                             try {
600                                 ActivityManager.getService().stopUser(userId, false, null);
601                             } catch (RemoteException e) {
602                                 throw e.rethrowAsRuntimeException();
603                             }
604                         }
605                     }
606                     break;
607                 case UserManager.DISALLOW_SAFE_BOOT:
608                     // Unlike with the other restrictions, we want to propagate the new value to
609                     // the system settings even if it is false. The other restrictions modify
610                     // settings which could be manually changed by the user from the Settings app
611                     // after the policies enforcing these restrictions have been revoked, so we
612                     // leave re-setting of those settings to the user.
613                     android.provider.Settings.Global.putInt(
614                             context.getContentResolver(),
615                             android.provider.Settings.Global.SAFE_BOOT_DISALLOWED,
616                             newValue ? 1 : 0);
617                     break;
618                 case UserManager.DISALLOW_AIRPLANE_MODE:
619                     if (newValue) {
620                         final boolean airplaneMode = Settings.Global.getInt(
621                                 context.getContentResolver(),
622                                 Settings.Global.AIRPLANE_MODE_ON, 0) == 1;
623                         if (airplaneMode) {
624                             android.provider.Settings.Global.putInt(
625                                     context.getContentResolver(),
626                                     android.provider.Settings.Global.AIRPLANE_MODE_ON, 0);
627                             // Post the intent.
628                             Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
629                             intent.putExtra("state", false);
630                             context.sendBroadcastAsUser(intent, UserHandle.ALL);
631                         }
632                     }
633                     break;
634                 case UserManager.DISALLOW_AMBIENT_DISPLAY:
635                     if (newValue) {
636                         android.provider.Settings.Secure.putIntForUser(
637                                 context.getContentResolver(),
638                                 Settings.Secure.DOZE_ENABLED, 0, userId);
639                         android.provider.Settings.Secure.putIntForUser(
640                                 context.getContentResolver(),
641                                 Settings.Secure.DOZE_ALWAYS_ON, 0, userId);
642                         android.provider.Settings.Secure.putIntForUser(
643                                 context.getContentResolver(),
644                                 Settings.Secure.DOZE_PICK_UP_GESTURE, 0, userId);
645                         android.provider.Settings.Secure.putIntForUser(
646                                 context.getContentResolver(),
647                                 Settings.Secure.DOZE_PULSE_ON_LONG_PRESS, 0, userId);
648                         android.provider.Settings.Secure.putIntForUser(
649                                 context.getContentResolver(),
650                                 Settings.Secure.DOZE_DOUBLE_TAP_GESTURE, 0, userId);
651                     }
652                     break;
653                 case UserManager.DISALLOW_CONFIG_LOCATION:
654                     // When DISALLOW_CONFIG_LOCATION is set on any user, we undo the global
655                     // kill switch.
656                     if (newValue) {
657                         android.provider.Settings.Global.putString(
658                                 context.getContentResolver(),
659                                 Global.LOCATION_GLOBAL_KILL_SWITCH, "0");
660                     }
661                     break;
662                 case UserManager.DISALLOW_APPS_CONTROL:
663                     // Intentional fall-through
664                 case UserManager.DISALLOW_UNINSTALL_APPS:
665                     final PackageManagerInternal pmi = LocalServices.getService(
666                             PackageManagerInternal.class);
667                     pmi.removeAllNonSystemPackageSuspensions(userId);
668                     pmi.removeAllDistractingPackageRestrictions(userId);
669                     pmi.flushPackageRestrictions(userId);
670                     break;
671             }
672         } finally {
673             Binder.restoreCallingIdentity(id);
674         }
675     }
676 
isSettingRestrictedForUser(Context context, @NonNull String setting, int userId, String value, int callingUid)677     public static boolean isSettingRestrictedForUser(Context context, @NonNull String setting,
678             int userId, String value, int callingUid) {
679         Objects.requireNonNull(setting);
680         final UserManager mUserManager = context.getSystemService(UserManager.class);
681         String restriction;
682         boolean checkAllUser = false;
683         switch (setting) {
684             case android.provider.Settings.Secure.LOCATION_MODE:
685                 if (mUserManager.hasUserRestriction(
686                         UserManager.DISALLOW_CONFIG_LOCATION, UserHandle.of(userId))
687                         && callingUid != Process.SYSTEM_UID) {
688                     return true;
689                 } else if (String.valueOf(Settings.Secure.LOCATION_MODE_OFF).equals(value)) {
690                     return false;
691                 }
692                 restriction = UserManager.DISALLOW_SHARE_LOCATION;
693                 break;
694 
695             case android.provider.Settings.Secure.LOCATION_PROVIDERS_ALLOWED:
696                 if (mUserManager.hasUserRestriction(
697                         UserManager.DISALLOW_CONFIG_LOCATION, UserHandle.of(userId))
698                         && callingUid != Process.SYSTEM_UID) {
699                     return true;
700                 } else if (value != null && value.startsWith("-")) {
701                     // See SettingsProvider.updateLocationProvidersAllowedLocked.  "-" is to disable
702                     // a provider, which should be allowed even if the user restriction is set.
703                     return false;
704                 }
705                 restriction = UserManager.DISALLOW_SHARE_LOCATION;
706                 break;
707 
708             case android.provider.Settings.Secure.INSTALL_NON_MARKET_APPS:
709                 if ("0".equals(value)) {
710                     return false;
711                 }
712                 restriction = UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES;
713                 break;
714 
715             case android.provider.Settings.Global.ADB_ENABLED:
716             case android.provider.Settings.Global.ADB_WIFI_ENABLED:
717                 if ("0".equals(value)) {
718                     return false;
719                 }
720                 restriction = UserManager.DISALLOW_DEBUGGING_FEATURES;
721                 break;
722 
723             case android.provider.Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB:
724                 if ("1".equals(value)) {
725                     return false;
726                 }
727                 restriction = UserManager.ENSURE_VERIFY_APPS;
728                 break;
729 
730             case android.provider.Settings.Global.PREFERRED_NETWORK_MODE:
731                 restriction = UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS;
732                 break;
733 
734             case android.provider.Settings.Secure.ALWAYS_ON_VPN_APP:
735             case android.provider.Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN:
736             case android.provider.Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST:
737                 // Whitelist system uid (ConnectivityService) and root uid to change always-on vpn
738                 final int appId = UserHandle.getAppId(callingUid);
739                 if (appId == Process.SYSTEM_UID || appId == Process.ROOT_UID) {
740                     return false;
741                 }
742                 restriction = UserManager.DISALLOW_CONFIG_VPN;
743                 break;
744 
745             case android.provider.Settings.Global.SAFE_BOOT_DISALLOWED:
746                 if ("1".equals(value)) {
747                     return false;
748                 }
749                 restriction = UserManager.DISALLOW_SAFE_BOOT;
750                 break;
751 
752             case android.provider.Settings.Global.AIRPLANE_MODE_ON:
753                 if ("0".equals(value)) {
754                     return false;
755                 }
756                 restriction = UserManager.DISALLOW_AIRPLANE_MODE;
757                 break;
758 
759             case android.provider.Settings.Secure.DOZE_ENABLED:
760             case android.provider.Settings.Secure.DOZE_ALWAYS_ON:
761             case android.provider.Settings.Secure.DOZE_PICK_UP_GESTURE:
762             case android.provider.Settings.Secure.DOZE_PULSE_ON_LONG_PRESS:
763             case android.provider.Settings.Secure.DOZE_DOUBLE_TAP_GESTURE:
764                 if ("0".equals(value)) {
765                     return false;
766                 }
767                 restriction = UserManager.DISALLOW_AMBIENT_DISPLAY;
768                 break;
769 
770             case android.provider.Settings.Global.LOCATION_GLOBAL_KILL_SWITCH:
771                 if ("0".equals(value)) {
772                     return false;
773                 }
774                 restriction = UserManager.DISALLOW_CONFIG_LOCATION;
775                 checkAllUser = true;
776                 break;
777 
778             case android.provider.Settings.System.SCREEN_BRIGHTNESS:
779             case android.provider.Settings.System.SCREEN_BRIGHTNESS_FLOAT:
780             case android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE:
781                 if (callingUid == Process.SYSTEM_UID) {
782                     return false;
783                 }
784                 restriction = UserManager.DISALLOW_CONFIG_BRIGHTNESS;
785                 break;
786 
787             case android.provider.Settings.Global.AUTO_TIME:
788             case android.provider.Settings.Global.AUTO_TIME_ZONE:
789                 if (callingUid == Process.SYSTEM_UID) {
790                     return false;
791                 }
792                 restriction = UserManager.DISALLOW_CONFIG_DATE_TIME;
793                 break;
794 
795             case android.provider.Settings.System.SCREEN_OFF_TIMEOUT:
796                 if (callingUid == Process.SYSTEM_UID) {
797                     return false;
798                 }
799                 restriction = UserManager.DISALLOW_CONFIG_SCREEN_TIMEOUT;
800                 break;
801 
802             case android.provider.Settings.Global.PRIVATE_DNS_MODE:
803             case android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER:
804                 if (callingUid == Process.SYSTEM_UID) {
805                     return false;
806                 }
807                 restriction = UserManager.DISALLOW_CONFIG_PRIVATE_DNS;
808                 break;
809             default:
810                 if (setting.startsWith(Settings.Global.DATA_ROAMING)) {
811                     if ("0".equals(value)) {
812                         return false;
813                     }
814                     restriction = UserManager.DISALLOW_DATA_ROAMING;
815                     break;
816                 }
817                 return false;
818         }
819 
820         if (checkAllUser) {
821             return mUserManager.hasUserRestrictionOnAnyUser(restriction);
822         } else {
823             return mUserManager.hasUserRestriction(restriction, UserHandle.of(userId));
824         }
825     }
826 
dumpRestrictions(PrintWriter pw, String prefix, Bundle restrictions)827     public static void dumpRestrictions(PrintWriter pw, String prefix, Bundle restrictions) {
828         boolean noneSet = true;
829         if (restrictions != null) {
830             for (String key : restrictions.keySet()) {
831                 if (restrictions.getBoolean(key, false)) {
832                     pw.println(prefix + key);
833                     noneSet = false;
834                 }
835             }
836             if (noneSet) {
837                 pw.println(prefix + "none");
838             }
839         } else {
840             pw.println(prefix + "null");
841         }
842     }
843 
844     /**
845      * Moves a particular restriction from one array of restrictions sets to a restriction set,
846      * e.g. for all users.
847      */
moveRestriction(String restrictionKey, SparseArray<RestrictionsSet> sourceRestrictionsSets, RestrictionsSet destRestrictionSet)848     public static void moveRestriction(String restrictionKey,
849             SparseArray<RestrictionsSet> sourceRestrictionsSets,
850             RestrictionsSet destRestrictionSet) {
851         for (int i = 0; i < sourceRestrictionsSets.size(); i++) {
852             final RestrictionsSet sourceRestrictionsSet = sourceRestrictionsSets.valueAt(i);
853             sourceRestrictionsSet.moveRestriction(destRestrictionSet, restrictionKey);
854         }
855     }
856 
857     /**
858      * Returns whether restrictions differ between two bundles.
859      * @param oldRestrictions old bundle of restrictions.
860      * @param newRestrictions new bundle of restrictions
861      * @param restrictions restrictions of interest, if empty, all restrictions are checked.
862      */
restrictionsChanged(Bundle oldRestrictions, Bundle newRestrictions, String... restrictions)863     public static boolean restrictionsChanged(Bundle oldRestrictions, Bundle newRestrictions,
864             String... restrictions) {
865         if (restrictions.length == 0) {
866             return areEqual(oldRestrictions, newRestrictions);
867         }
868         for (final String restriction : restrictions) {
869             if (oldRestrictions.getBoolean(restriction, false) !=
870                     newRestrictions.getBoolean(restriction, false)) {
871                 return true;
872             }
873         }
874         return false;
875     }
876 
setInstallMarketAppsRestriction(ContentResolver cr, int userId, int settingValue)877     private static void setInstallMarketAppsRestriction(ContentResolver cr, int userId,
878             int settingValue) {
879         android.provider.Settings.Secure.putIntForUser(
880                 cr, android.provider.Settings.Secure.INSTALL_NON_MARKET_APPS, settingValue, userId);
881     }
882 
getNewUserRestrictionSetting(Context context, int userId, String userRestriction, boolean newValue)883     private static int getNewUserRestrictionSetting(Context context, int userId,
884                 String userRestriction, boolean newValue) {
885         return (newValue || UserManager.get(context).hasUserRestriction(userRestriction,
886                 UserHandle.of(userId))) ? 0 : 1;
887     }
888 }
889