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