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

Commit ea8da603 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Fix location for BLE and classic scan results"

parents 324db978 0c5c1904
Loading
Loading
Loading
Loading
+21 −27
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.location.LocationManager;
import android.os.Binder;
import android.os.Build;
import android.os.ParcelUuid;
@@ -277,41 +278,34 @@ public final class Utils {
    }

    /**
     * Checks that calling process has android.Manifest.permission.ACCESS_COARSE_LOCATION or
     * android.Manifest.permission.ACCESS_FINE_LOCATION and a corresponding app op is allowed
     * Checks whether location is off and must be on for us to perform some operation
     */
    public static boolean blockedByLocationOff(Context context, UserHandle userHandle) {
        return !context.getSystemService(LocationManager.class)
                .isLocationEnabledForUser(userHandle);
    }

    /**
     * Checks that calling process has android.Manifest.permission.ACCESS_FINE_LOCATION and
     * OP_FINE_LOCATION is allowed
     */
    public static boolean checkCallerHasLocationPermission(Context context, AppOpsManager appOps,
            String callingPackage) {
            String callingPackage, UserHandle userHandle) {
        if (context.checkCallingOrSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED && isAppOppAllowed(
                != PackageManager.PERMISSION_GRANTED || !isAppOppAllowed(
                        appOps, AppOpsManager.OP_FINE_LOCATION, callingPackage)) {
            return true;
            Log.e(TAG, "Permission denial: Need ACCESS_FINE_LOCATION "
                    + "permission to get scan results");
            return false;
        }

        if (context.checkCallingOrSelfPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION)
                == PackageManager.PERMISSION_GRANTED && isAppOppAllowed(
                        appOps, AppOpsManager.OP_COARSE_LOCATION, callingPackage)) {
            return true;
        if (blockedByLocationOff(context, userHandle)) {
            Log.e(TAG, "Permission denial: Location is off.");
            return false;
        }
        // Enforce location permission for apps targeting M and later versions
        if (isMApp(context, callingPackage)) {
            // PEERS_MAC_ADDRESS is another way to get scan results without
            // requiring location permissions, so only throw an exception here
            // if PEERS_MAC_ADDRESS permission is missing as well
            if (!checkCallerHasPeersMacAddressPermission(context)) {
                throw new SecurityException("Need ACCESS_COARSE_LOCATION or "
                        + "ACCESS_FINE_LOCATION permission to get scan results");
            }
        } else {
            // Pre-M apps running in the foreground should continue getting scan results
            if (isForegroundApp(context, callingPackage)) {

        return true;
    }
            Log.e(TAG, "Permission denial: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION "
                    + "permission to get scan results");
        }
        return false;
    }

    /**
     * Returns true if the caller holds PEERS_MAC_ADDRESS.
+10 −3
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.bluetooth.btservice;

import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.AppOpsManager;
import android.app.PendingIntent;
import android.app.Service;
import android.bluetooth.BluetoothActivityEnergyInfo;
@@ -183,6 +184,7 @@ public class AdapterService extends Service {
    private ProfileObserver mProfileObserver;
    private PhonePolicy mPhonePolicy;
    private ActiveDeviceManager mActiveDeviceManager;
    private AppOpsManager mAppOps;

    /**
     * Register a {@link ProfileService} with AdapterService.
@@ -382,6 +384,7 @@ public class AdapterService extends Service {
        initNative();
        mNativeAvailable = true;
        mCallbacks = new RemoteCallbackList<IBluetoothCallback>();
        mAppOps = getSystemService(AppOpsManager.class);
        //Load the name and address
        getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDADDR);
        getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_BDNAME);
@@ -1007,7 +1010,7 @@ public class AdapterService extends Service {
        }

        @Override
        public boolean startDiscovery() {
        public boolean startDiscovery(String callingPackage) {
            if (!Utils.checkCaller()) {
                Log.w(TAG, "startDiscovery() - Not allowed for non-active user");
                return false;
@@ -1017,7 +1020,7 @@ public class AdapterService extends Service {
            if (service == null) {
                return false;
            }
            return service.startDiscovery();
            return service.startDiscovery(callingPackage);
        }

        @Override
@@ -1811,9 +1814,13 @@ public class AdapterService extends Service {
        return mAdapterProperties.setDiscoverableTimeout(timeout);
    }

    boolean startDiscovery() {
    boolean startDiscovery(String callingPackage) {
        UserHandle callingUser = UserHandle.of(UserHandle.getCallingUserId());
        debugLog("startDiscovery");
        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission");
        if (!Utils.checkCallerHasLocationPermission(this, mAppOps, callingPackage, callingUser)) {
            return false;
        }

        return startDiscoveryNative();
    }
+3 −2
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.os.IBinder;
import android.os.IInterface;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.WorkSource;
import android.util.Log;

@@ -88,8 +89,8 @@ import java.util.UUID;
        /** Whether the calling app has location permission */
        boolean hasLocationPermisson;

        /** Whether the calling app has peers mac address permission */
        boolean hasPeersMacAddressPermission;
        /** The user handle of the app that started the scan */
        UserHandle mUserHandle;

        /** Internal callback info queue, waiting to be send on congestion clear */
        private List<CallbackInfo> mCongestionQueue = new ArrayList<CallbackInfo>();
+11 −25
Original line number Diff line number Diff line
@@ -50,8 +50,8 @@ import android.os.IBinder;
import android.os.ParcelUuid;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.WorkSource;
import android.provider.Settings;
import android.util.Log;

import com.android.bluetooth.BluetoothMetricsProto;
@@ -1000,8 +1000,7 @@ public class GattService extends ProfileService {
                            txPower, rssi, periodicAdvInt,
                            ScanRecord.parseFromBytes(scanRecordData),
                            SystemClock.elapsedRealtimeNanos());
            // Do no report if location mode is OFF or the client has no location permission
            // PEERS_MAC_ADDRESS permission holders always get results
            // Do not report if location mode is OFF or the client has no location permission
            if (!hasScanResultPermission(client) || !matchesFilters(client, result)) {
                continue;
            }
@@ -1088,15 +1087,7 @@ public class GattService extends ProfileService {

    /** Determines if the given scan client has the appropriate permissions to receive callbacks. */
    private boolean hasScanResultPermission(final ScanClient client) {
        final boolean requiresLocationEnabled =
                getResources().getBoolean(R.bool.strict_location_check);
        final boolean locationEnabledSetting =
                Settings.Secure.getInt(getContentResolver(), Settings.Secure.LOCATION_MODE,
                        Settings.Secure.LOCATION_MODE_OFF) != Settings.Secure.LOCATION_MODE_OFF;
        final boolean locationEnabled =
                !requiresLocationEnabled || locationEnabledSetting || client.legacyForegroundApp;
        return (client.hasPeersMacAddressPermission || (client.hasLocationPermission
                && locationEnabled));
        return client.hasLocationPermission && !Utils.blockedByLocationOff(this, client.userHandle);
    }

    // Check if a scan record matches a specific filters.
@@ -1917,16 +1908,16 @@ public class GattService extends ProfileService {
        if (DBG) {
            Log.d(TAG, "start scan with filters");
        }
        UserHandle callingUser = UserHandle.of(UserHandle.getCallingUserId());
        enforceAdminPermission();
        if (needsPrivilegedPermissionForScan(settings)) {
            enforcePrivilegedPermission();
        }
        final ScanClient scanClient = new ScanClient(scannerId, settings, filters, storages);
        scanClient.userHandle = UserHandle.of(UserHandle.getCallingUserId());
        scanClient.hasLocationPermission =
                Utils.checkCallerHasLocationPermission(this, mAppOps, callingPackage);
        scanClient.hasPeersMacAddressPermission =
                Utils.checkCallerHasPeersMacAddressPermission(this);
        scanClient.legacyForegroundApp = Utils.isLegacyForegroundApp(this, callingPackage);
                Utils.checkCallerHasLocationPermission(
                        this, mAppOps, callingPackage, scanClient.userHandle);

        AppScanStats app = mScannerMap.getAppScanStatsById(scannerId);
        if (app != null) {
@@ -1958,19 +1949,15 @@ public class GattService extends ProfileService {
        piInfo.filters = filters;
        piInfo.callingPackage = callingPackage;
        ScannerMap.App app = mScannerMap.add(uuid, null, null, piInfo, this);
        app.mUserHandle = UserHandle.of(UserHandle.getCallingUserId());
        try {
            app.hasLocationPermisson =
                    Utils.checkCallerHasLocationPermission(this, mAppOps, callingPackage);
                    Utils.checkCallerHasLocationPermission(
                            this, mAppOps, callingPackage, app.mUserHandle);
        } catch (SecurityException se) {
            // No need to throw here. Just mark as not granted.
            app.hasLocationPermisson = false;
        }
        try {
            app.hasPeersMacAddressPermission = Utils.checkCallerHasPeersMacAddressPermission(this);
        } catch (SecurityException se) {
            // No need to throw here. Just mark as not granted.
            app.hasPeersMacAddressPermission = false;
        }
        mScanManager.registerScanner(uuid);
    }

@@ -1979,8 +1966,7 @@ public class GattService extends ProfileService {
        final ScanClient scanClient =
                new ScanClient(scannerId, piInfo.settings, piInfo.filters, null);
        scanClient.hasLocationPermission = app.hasLocationPermisson;
        scanClient.hasPeersMacAddressPermission = app.hasPeersMacAddressPermission;
        scanClient.legacyForegroundApp = Utils.isLegacyForegroundApp(this, piInfo.callingPackage);
        scanClient.userHandle = app.mUserHandle;

        AppScanStats scanStats = mScannerMap.getAppScanStatsById(scannerId);
        if (scanStats != null) {
+2 −3
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.bluetooth.le.ResultStorageDescriptor;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanSettings;
import android.os.Binder;
import android.os.UserHandle;

import java.util.List;
import java.util.Objects;
@@ -41,9 +42,7 @@ import java.util.UUID;
    // App associated with the scan client died.
    public boolean appDied;
    public boolean hasLocationPermission;
    public boolean hasPeersMacAddressPermission;
    // Pre-M apps are allowed to get scan results even if location is disabled
    public boolean legacyForegroundApp;
    public UserHandle userHandle;

    public AppScanStats stats = null;

Loading