Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2e359eee authored by Rahul Sabnis's avatar Rahul Sabnis
Browse files

BluetoothGatt APIs now check for Target SDK instead of actual SDK

version when deciding functionality.

Updates the Utils#isQApp to be a generic function that checks the
calling app's target SDK.

Tag: #feature
Bug: 217742355
Test: Manual
Change-Id: Id8f31b3d68fa2523a16f5cb50cd19385baf47beb
parent fe2ee2d9
Loading
Loading
Loading
Loading
+17 −3
Original line number Diff line number Diff line
@@ -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;
    }
+2 −1
Original line number Diff line number Diff line
@@ -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;
+0 −3
Original line number Diff line number Diff line
@@ -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;

+18 −14
Original line number Diff line number Diff line
@@ -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!");