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