diff options
author | Scott Lobdell <slobdell@google.com> | 2022-03-11 19:27:17 +0000 |
---|---|---|
committer | Scott Lobdell <slobdell@google.com> | 2022-03-11 19:57:09 +0000 |
commit | c9218ef1b82430a07d94f74c212a30e7ccc52975 (patch) | |
tree | 241b7fdeb6bdf1cf3af925ba8996f18faa8973d9 /service/java/com/android/server/bluetooth/BluetoothManagerService.java | |
parent | a26bda4d37221f2f7ef750b413502091e3bcddd4 (diff) | |
parent | 480d2270b269a0e47bf475eb439111f3f966e2a9 (diff) |
Merge TP1A.220225.003
Change-Id: Id71ac466dbfe3707fe2e544ce22b1da8f474ec2b
Diffstat (limited to 'service/java/com/android/server/bluetooth/BluetoothManagerService.java')
-rw-r--r-- | service/java/com/android/server/bluetooth/BluetoothManagerService.java | 133 |
1 files changed, 83 insertions, 50 deletions
diff --git a/service/java/com/android/server/bluetooth/BluetoothManagerService.java b/service/java/com/android/server/bluetooth/BluetoothManagerService.java index 366104a326..f6201a7b3f 100644 --- a/service/java/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/java/com/android/server/bluetooth/BluetoothManagerService.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.bluetooth; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED; @@ -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,11 +82,13 @@ 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; import com.android.internal.annotations.VisibleForTesting; import com.android.modules.utils.SynchronousResultReceiver; +import com.android.server.BluetoothManagerServiceDumpProto; import java.io.FileDescriptor; import java.io.FileOutputStream; @@ -100,7 +105,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeoutException; import java.util.concurrent.locks.ReentrantReadWriteLock; -class BluetoothManagerService extends IBluetoothManager.Stub { +public class BluetoothManagerService extends IBluetoothManager.Stub { private static final String TAG = "BluetoothManagerService"; private static final boolean DBG = true; @@ -178,6 +183,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; @@ -275,8 +291,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 { @@ -488,10 +502,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; @@ -1282,10 +1292,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; } @@ -1324,10 +1334,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; } @@ -1374,39 +1384,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 * @@ -3528,4 +3505,60 @@ 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.checkPermission(android.Manifest.permission.NETWORK_SETTINGS, 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); + } + } } |