diff options
author | Etienne Ruffieux <eruffieux@google.com> | 2022-02-07 23:14:46 +0000 |
---|---|---|
committer | Etienne Ruffieux <eruffieux@google.com> | 2022-02-08 21:54:13 +0000 |
commit | 3f46b3b0f71b03593b7fe21a8d7bc704ee7618a4 (patch) | |
tree | e16c29827352ca0521dd10a9d77a2249f1af8e73 /service/java/com/android/server/bluetooth/BluetoothManagerService.java | |
parent | 0019d834f87b6711e6cdc953b92aeba79f6688c2 (diff) |
Deprecating BluetoothAdapter enable/disable
Starting from T, BluetoothAdapter enable/disable APIs
are limited to system apps or device owners.
Tag: #feature
Bug: 218493289
Test: manual
Ignore-AOSP-First: Merge conflict
Change-Id: I851830eae8a3a2bb4be4b2bcf6147fd81e092f2a
Diffstat (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java')
-rw-r--r-- | service/java/com/android/server/bluetooth/BluetoothManagerService.java | 126 |
1 files changed, 78 insertions, 48 deletions
diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 0f85fb3d95..5ad7f9d2f8 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -28,6 +28,8 @@ import android.annotation.SuppressLint; import android.app.ActivityManager; import android.app.AppOpsManager; import android.app.BroadcastOptions; +import android.app.admin.DevicePolicyManager; +import android.app.compat.CompatChanges; import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothHearingAid; @@ -43,7 +45,8 @@ import android.bluetooth.IBluetoothManager; import android.bluetooth.IBluetoothManagerCallback; import android.bluetooth.IBluetoothProfileServiceConnection; import android.bluetooth.IBluetoothStateChangeCallback; -import android.content.ActivityNotFoundException; +import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledSince; import android.content.AttributionSource; import android.content.BroadcastReceiver; import android.content.ComponentName; @@ -79,6 +82,7 @@ import android.provider.Settings.SettingNotFoundException; import android.sysprop.BluetoothProperties; import android.text.TextUtils; import android.util.Log; +import android.util.Pair; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; @@ -177,6 +181,17 @@ class BluetoothManagerService extends IBluetoothManager.Stub { private static final int SERVICE_IBLUETOOTH = 1; private static final int SERVICE_IBLUETOOTHGATT = 2; + private static final int FLAGS_SYSTEM_APP = + ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; + + /** + * Starting with {@link android.os.Build.VERSION_CODES#TIRAMISU}, applications are + * not allowed to enable/disable Bluetooth. + */ + @ChangeId + @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.TIRAMISU) + static final long RESTRICT_ENABLE_DISABLE = 218493289L; + private final Context mContext; private final UserManager mUserManager; @@ -272,8 +287,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { // bluetooth profile services private final Map<Integer, ProfileServiceConnections> mProfileServices = new HashMap<>(); - private final boolean mWirelessConsentRequired; - private final IBluetoothCallback mBluetoothCallback = new IBluetoothCallback.Stub() { @Override public void onBluetoothStateChange(int prevState, int newState) throws RemoteException { @@ -482,10 +495,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { mContext = context; - mWirelessConsentRequired = context.getResources() - .getBoolean(Resources.getSystem().getIdentifier( - "config_wirelessConsentRequired", "bool", "android")); - mCrashes = 0; mBluetooth = null; mBluetoothBinder = null; @@ -1229,10 +1238,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } final int callingUid = Binder.getCallingUid(); - final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; - if (!callerSystem && !isEnabled() && mWirelessConsentRequired - && startConsentUiIfNeeded(packageName, - callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE)) { + final int callingPid = Binder.getCallingPid(); + if (!isPrivileged(callingPid, callingUid) && !isDeviceOwner(callingUid, packageName) + && !CompatChanges.isChangeEnabled(RESTRICT_ENABLE_DISABLE, callingUid) + && !isSystem(packageName, callingUid)) { return false; } @@ -1270,10 +1279,10 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } final int callingUid = Binder.getCallingUid(); - final boolean callerSystem = UserHandle.getAppId(callingUid) == Process.SYSTEM_UID; - if (!callerSystem && isEnabled() && mWirelessConsentRequired - && startConsentUiIfNeeded(packageName, - callingUid, BluetoothAdapter.ACTION_REQUEST_DISABLE)) { + final int callingPid = Binder.getCallingPid(); + if (!isPrivileged(callingPid, callingUid) && !isDeviceOwner(callingUid, packageName) + && CompatChanges.isChangeEnabled(RESTRICT_ENABLE_DISABLE, callingUid) + && !isSystem(packageName, callingUid)) { return false; } @@ -1294,39 +1303,6 @@ class BluetoothManagerService extends IBluetoothManager.Stub { return true; } - private boolean startConsentUiIfNeeded(String packageName, - int callingUid, String intentAction) throws RemoteException { - if (checkBluetoothPermissionWhenWirelessConsentRequired()) { - return false; - } - try { - // Validate the package only if we are going to use it - ApplicationInfo applicationInfo = mContext.getPackageManager() - .getApplicationInfoAsUser(packageName, - PackageManager.MATCH_DIRECT_BOOT_AUTO, - UserHandle.getUserHandleForUid(callingUid)); - if (applicationInfo.uid != callingUid) { - throw new SecurityException("Package " + packageName - + " not in uid " + callingUid); - } - - Intent intent = new Intent(intentAction); - intent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName); - intent.setFlags( - Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); - try { - mContext.startActivity(intent); - } catch (ActivityNotFoundException e) { - // Shouldn't happen - Log.e(TAG, "Intent to handle action " + intentAction + " missing"); - return false; - } - return true; - } catch (PackageManager.NameNotFoundException e) { - throw new RemoteException(e.getMessage()); - } - } - /** * Check if AppOpsManager is available and the packageName belongs to uid * @@ -3082,4 +3058,58 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } return comp; } + + private boolean isPrivileged(int pid, int uid) { + return (mContext.checkPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED, pid, uid) + == PackageManager.PERMISSION_GRANTED) + || (mContext.getPackageManager().checkSignatures(uid, Process.SYSTEM_UID) + == PackageManager.SIGNATURE_MATCH); + } + + private Pair<UserHandle, ComponentName> getDeviceOwner() { + DevicePolicyManager devicePolicyManager = + mContext.getSystemService(DevicePolicyManager.class); + if (devicePolicyManager == null) return null; + long ident = Binder.clearCallingIdentity(); + UserHandle deviceOwnerUser = null; + ComponentName deviceOwnerComponent = null; + try { + deviceOwnerUser = devicePolicyManager.getDeviceOwnerUser(); + deviceOwnerComponent = devicePolicyManager.getDeviceOwnerComponentOnAnyUser(); + } finally { + Binder.restoreCallingIdentity(ident); + } + if (deviceOwnerUser == null || deviceOwnerComponent == null + || deviceOwnerComponent.getPackageName() == null) { + return null; + } + return new Pair<>(deviceOwnerUser, deviceOwnerComponent); + } + + private boolean isDeviceOwner(int uid, String packageName) { + if (packageName == null) { + Log.e(TAG, "isDeviceOwner: packageName is null, returning false"); + return false; + } + Pair<UserHandle, ComponentName> deviceOwner = getDeviceOwner(); + + // no device owner + if (deviceOwner == null) return false; + + return deviceOwner.first.equals(UserHandle.getUserHandleForUid(uid)) + && deviceOwner.second.getPackageName().equals(packageName); + } + + public boolean isSystem(String packageName, int uid) { + long ident = Binder.clearCallingIdentity(); + try { + ApplicationInfo info = mContext.getPackageManager().getApplicationInfoAsUser( + packageName, 0, UserHandle.getUserHandleForUid(uid)); + return (info.flags & FLAGS_SYSTEM_APP) != 0; + } catch (PackageManager.NameNotFoundException e) { + return false; + } finally { + Binder.restoreCallingIdentity(ident); + } + } } |