diff options
4 files changed, 37 insertions, 21 deletions
diff --git a/android/app/src/com/android/bluetooth/Utils.java b/android/app/src/com/android/bluetooth/Utils.java index df02fc2513..63b987b6c1 100644 --- a/android/app/src/com/android/bluetooth/Utils.java +++ b/android/app/src/com/android/bluetooth/Utils.java @@ -826,12 +826,26 @@ public final class Utils { android.Manifest.permission.WRITE_SMS) == PackageManager.PERMISSION_GRANTED; } - public static boolean isQApp(Context context, String pkgName) { + /** + * Checks that the target sdk of the app corresponding to the provided package name is greater + * than or equal to the passed in target sdk. + * <p> + * For example, if the calling app has target SDK {@link Build.VERSION_CODES#S} and we pass in + * the targetSdk {@link Build.VERSION_CODES#R}, the API will return true because S >= R. + * + * @param context Bluetooth service context + * @param pkgName caller's package name + * @param expectedMinimumTargetSdk one of the values from {@link Build.VERSION_CODES} + * @return {@code true} if the caller's target sdk is greater than or equal to + * expectedMinimumTargetSdk, {@code false} otherwise + */ + public static boolean checkCallerTargetSdk(Context context, String pkgName, + int expectedMinimumTargetSdk) { try { return context.getPackageManager().getApplicationInfo(pkgName, 0).targetSdkVersion - >= Build.VERSION_CODES.Q; + >= expectedMinimumTargetSdk; } catch (PackageManager.NameNotFoundException e) { - // In case of exception, assume Q app + // In case of exception, assume true } return true; } diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java index 3ba407327d..6ab5781d41 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java @@ -74,6 +74,7 @@ import android.content.pm.PackageManager; import android.os.AsyncTask; import android.os.BatteryStatsManager; import android.os.Binder; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -3789,7 +3790,7 @@ public class AdapterService extends Service { debugLog("startDiscovery"); String callingPackage = attributionSource.getPackageName(); mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); - boolean isQApp = Utils.isQApp(this, callingPackage); + boolean isQApp = Utils.checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.Q); boolean hasDisavowedLocation = Utils.hasDisavowedLocationForScan(this, attributionSource, mTestModeEnabled); String permission = null; diff --git a/android/app/src/com/android/bluetooth/gatt/ContextMap.java b/android/app/src/com/android/bluetooth/gatt/ContextMap.java index d4525327f1..ed95301ad6 100644 --- a/android/app/src/com/android/bluetooth/gatt/ContextMap.java +++ b/android/app/src/com/android/bluetooth/gatt/ContextMap.java @@ -95,9 +95,6 @@ import java.util.UUID; /** The user handle of the app that started the scan */ UserHandle mUserHandle; - /** Whether the calling app is targeting Q or better */ - boolean mIsQApp; - /** Whether the calling app has the network settings permission */ boolean mHasNetworkSettingsPermission; diff --git a/android/app/src/com/android/bluetooth/gatt/GattService.java b/android/app/src/com/android/bluetooth/gatt/GattService.java index 43bd8dd7a1..00d045e04d 100644 --- a/android/app/src/com/android/bluetooth/gatt/GattService.java +++ b/android/app/src/com/android/bluetooth/gatt/GattService.java @@ -16,6 +16,7 @@ package com.android.bluetooth.gatt; +import static com.android.bluetooth.Utils.checkCallerTargetSdk; import static com.android.bluetooth.Utils.enforceBluetoothPrivilegedPermission; import android.annotation.RequiresPermission; @@ -2303,8 +2304,8 @@ public class GattService extends ProfileService { try { permissionCheck(connId, handle); } catch (SecurityException ex) { - // Only throws on T+ as this is an older API and did not throw prior to T - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + // Only throws on apps with target SDK T+ as this old API did not throw prior to T + if (checkCallerTargetSdk(this, app.name, Build.VERSION_CODES.TIRAMISU)) { throw ex; } Log.w(TAG, "onNotify() - permission check failed!"); @@ -2966,7 +2967,7 @@ public class GattService extends ProfileService { scanClient.hasDisavowedLocation = Utils.hasDisavowedLocationForScan(this, attributionSource, isTestModeEnabled()); - scanClient.isQApp = Utils.isQApp(this, callingPackage); + scanClient.isQApp = checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.Q); if (!scanClient.hasDisavowedLocation) { if (scanClient.isQApp) { scanClient.hasLocationPermission = Utils.checkCallerHasFineLocation( @@ -3042,10 +3043,9 @@ public class GattService extends ProfileService { app.mHasDisavowedLocation = Utils.hasDisavowedLocationForScan(this, attributionSource, isTestModeEnabled()); - app.mIsQApp = Utils.isQApp(this, callingPackage); if (!app.mHasDisavowedLocation) { try { - if (app.mIsQApp) { + if (checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.Q)) { app.hasLocationPermission = Utils.checkCallerHasFineLocation( this, attributionSource, app.mUserHandle); } else { @@ -3079,7 +3079,7 @@ public class GattService extends ProfileService { new ScanClient(scannerId, piInfo.settings, piInfo.filters); scanClient.hasLocationPermission = app.hasLocationPermission; scanClient.userHandle = app.mUserHandle; - scanClient.isQApp = app.mIsQApp; + scanClient.isQApp = checkCallerTargetSdk(this, app.name, Build.VERSION_CODES.Q); scanClient.eligibleForSanitizedExposureNotification = app.mEligibleForSanitizedExposureNotification; scanClient.hasNetworkSettingsPermission = app.mHasNetworkSettingsPermission; @@ -3546,8 +3546,9 @@ public class GattService extends ProfileService { try { permissionCheck(connId, handle); } catch (SecurityException ex) { - // Only throws on T+ as this is an older API and did not throw prior to T - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + String callingPackage = attributionSource.getPackageName(); + // Only throws on apps with target SDK T+ as this old API did not throw prior to T + if (checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.TIRAMISU)) { throw ex; } Log.w(TAG, "readCharacteristic() - permission check failed!"); @@ -3578,8 +3579,9 @@ public class GattService extends ProfileService { try { permissionCheck(uuid); } catch (SecurityException ex) { - // Only throws on T+ as this is an older API and did not throw prior to T - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + String callingPackage = attributionSource.getPackageName(); + // Only throws on apps with target SDK T+ as this old API did not throw prior to T + if (checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.TIRAMISU)) { throw ex; } Log.w(TAG, "readUsingCharacteristicUuid() - permission check failed!"); @@ -3655,8 +3657,9 @@ public class GattService extends ProfileService { try { permissionCheck(connId, handle); } catch (SecurityException ex) { - // Only throws on T+ as this is an older API and did not throw prior to T - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + String callingPackage = attributionSource.getPackageName(); + // Only throws on apps with target SDK T+ as this old API did not throw prior to T + if (checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.TIRAMISU)) { throw ex; } Log.w(TAG, "readDescriptor() - permission check failed!"); @@ -3741,8 +3744,9 @@ public class GattService extends ProfileService { try { permissionCheck(connId, handle); } catch (SecurityException ex) { - // Only throws on T+ as this is an older API and did not throw prior to T - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + String callingPackage = attributionSource.getPackageName(); + // Only throws on apps with target SDK T+ as this old API did not throw prior to T + if (checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.TIRAMISU)) { throw ex; } Log.w(TAG, "registerForNotification() - permission check failed!"); |