diff --git a/api/current.txt b/api/current.txt index 68467fdc020ae..2788f3648eb66 100644 --- a/api/current.txt +++ b/api/current.txt @@ -29379,6 +29379,7 @@ package android.os { field public static final java.lang.String DISALLOW_ADD_USER = "no_add_user"; field public static final java.lang.String DISALLOW_ADJUST_VOLUME = "no_adjust_volume"; field public static final java.lang.String DISALLOW_APPS_CONTROL = "no_control_apps"; + field public static final java.lang.String DISALLOW_BLUETOOTH = "no_bluetooth"; field public static final java.lang.String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth"; field public static final java.lang.String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts"; field public static final java.lang.String DISALLOW_CONFIG_CREDENTIALS = "no_config_credentials"; diff --git a/api/system-current.txt b/api/system-current.txt index ef503324ff75e..3347560a69901 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -31956,6 +31956,7 @@ package android.os { field public static final java.lang.String DISALLOW_ADD_USER = "no_add_user"; field public static final java.lang.String DISALLOW_ADJUST_VOLUME = "no_adjust_volume"; field public static final java.lang.String DISALLOW_APPS_CONTROL = "no_control_apps"; + field public static final java.lang.String DISALLOW_BLUETOOTH = "no_bluetooth"; field public static final java.lang.String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth"; field public static final java.lang.String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts"; field public static final java.lang.String DISALLOW_CONFIG_CREDENTIALS = "no_config_credentials"; diff --git a/api/test-current.txt b/api/test-current.txt index dfd1bdd28dfca..8e3d4ef6cbadc 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -29454,6 +29454,7 @@ package android.os { field public static final java.lang.String DISALLOW_ADD_USER = "no_add_user"; field public static final java.lang.String DISALLOW_ADJUST_VOLUME = "no_adjust_volume"; field public static final java.lang.String DISALLOW_APPS_CONTROL = "no_control_apps"; + field public static final java.lang.String DISALLOW_BLUETOOTH = "no_bluetooth"; field public static final java.lang.String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth"; field public static final java.lang.String DISALLOW_CONFIG_CELL_BROADCASTS = "no_config_cell_broadcasts"; field public static final java.lang.String DISALLOW_CONFIG_CREDENTIALS = "no_config_credentials"; diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 03d3cf2e70f4e..a4db940d4fdb8 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -186,6 +186,8 @@ public class UserManager { * Specifies if a user is disallowed from configuring bluetooth. * This does not restrict the user from turning bluetooth on or off. * The default value is false. + *

This restriction doesn't prevent the user from using bluetooth. For disallowing usage of + * bluetooth completely on the device, use {@link #DISALLOW_BLUETOOTH}. *

This restriction has no effect in a managed profile. * *

Key for user restrictions. @@ -196,6 +198,20 @@ public class UserManager { */ public static final String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth"; + /** + * Specifies if bluetooth is disallowed on the device. + * + *

This restriction can only be set by the device owner and the profile owner on the + * primary user and it applies globally - i.e. it disables bluetooth on the entire device. + *

The default value is false. + *

Key for user restrictions. + *

Type: Boolean + * @see DevicePolicyManager#addUserRestriction(ComponentName, String) + * @see DevicePolicyManager#clearUserRestriction(ComponentName, String) + * @see #getUserRestrictions() + */ + public static final String DISALLOW_BLUETOOTH = "no_bluetooth"; + /** * Specifies if a user is disallowed from transferring files over * USB. This can only be set by device owners and profile owners on the primary user. diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index 7bf8c743c8eb5..c16c229ed45e6 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -39,6 +39,7 @@ import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.database.ContentObserver; import android.os.Binder; +import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -49,6 +50,8 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; +import android.os.UserManagerInternal; +import android.os.UserManagerInternal.UserRestrictionsListener; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.util.Slog; @@ -172,6 +175,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } }; + private final UserRestrictionsListener mUserRestrictionsListener = + new UserRestrictionsListener() { + @Override + public void onUserRestrictionsChanged(int userId, Bundle newRestrictions, + Bundle prevRestrictions) { + final boolean bluetoothDisallowed = + newRestrictions.getBoolean(UserManager.DISALLOW_BLUETOOTH); + if ((mEnable || mEnableExternal) && bluetoothDisallowed) { + disable(true); + } + } + }; + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -625,6 +641,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { public boolean enableNoAutoConnect() { + if (isBluetoothDisallowed()) { + if (DBG) { + Slog.d(TAG, "enableNoAutoConnect(): not enabling - bluetooth disallowed"); + } + return false; + } + mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); @@ -647,6 +670,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } public boolean enable() { + if (isBluetoothDisallowed()) { + if (DBG) { + Slog.d(TAG,"enable(): not enabling - bluetooth disallowed"); + } + return false; + } + if ((Binder.getCallingUid() != Process.SYSTEM_UID) && (!checkIfCallerIsForegroundUser())) { Slog.w(TAG,"enable(): not allowed for non-active and non system user"); @@ -808,6 +838,12 @@ class BluetoothManagerService extends IBluetoothManager.Stub { */ public void handleOnBootPhase() { if (DBG) Slog.d(TAG, "Bluetooth boot completed"); + UserManagerInternal userManagerInternal = + LocalServices.getService(UserManagerInternal.class); + userManagerInternal.addUserRestrictionsListener(mUserRestrictionsListener); + if (isBluetoothDisallowed()) { + return; + } if (mEnableExternal && isBluetoothPersistedStateOnBluetooth()) { if (DBG) Slog.d(TAG, "Auto-enabling Bluetooth."); sendEnableMsg(mQuietEnableExternal); @@ -1851,6 +1887,16 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } } + private boolean isBluetoothDisallowed() { + long callingIdentity = Binder.clearCallingIdentity(); + try { + return mContext.getSystemService(UserManager.class) + .hasUserRestriction(UserManager.DISALLOW_BLUETOOTH, UserHandle.SYSTEM); + } finally { + Binder.restoreCallingIdentity(callingIdentity); + } + } + @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java index 3df13a9c637f0..634f3cd567905 100644 --- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java +++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java @@ -72,6 +72,7 @@ public class UserRestrictionsUtils { UserManager.DISALLOW_SHARE_LOCATION, UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, UserManager.DISALLOW_CONFIG_BLUETOOTH, + UserManager.DISALLOW_BLUETOOTH, UserManager.DISALLOW_USB_FILE_TRANSFER, UserManager.DISALLOW_CONFIG_CREDENTIALS, UserManager.DISALLOW_REMOVE_USER, @@ -118,6 +119,7 @@ public class UserRestrictionsUtils { * User restrictions that can not be set by profile owners. */ private static final Set DEVICE_OWNER_ONLY_RESTRICTIONS = Sets.newArraySet( + UserManager.DISALLOW_BLUETOOTH, UserManager.DISALLOW_USB_FILE_TRANSFER, UserManager.DISALLOW_CONFIG_TETHERING, UserManager.DISALLOW_NETWORK_RESET,