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