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