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

Commit 2c8e3e32 authored by Jayden Kim's avatar Jayden Kim
Browse files

Reland 'Apply uid of original caller when starting LE scan by PendingIntent'

- When starting LE scan by PendingItent, uid of btservice was applied in
  ScanClient. ScanManager misunderstood the ScanClient is owned by
  foreground service.
- This fix is to apply the uid of orignal caller so that
  ScanManager decides scan policy correctly.
- Verified in multi user settings

Bug: 299231195
Bug: 300866864
Test: atest BluetoothInstrumentationTests and device test
Change-Id: I97fa1af47401c9674dd12fd835ec6f8e7abde35c
parent 3fc63129
Loading
Loading
Loading
Loading
+17 −7
Original line number Original line Diff line number Diff line
@@ -209,12 +209,22 @@ public class ContextMap<C, T> {
    private Set<Connection> mConnections = new HashSet<Connection>();
    private Set<Connection> mConnections = new HashSet<Connection>();
    private final Object mConnectionsLock = new Object();
    private final Object mConnectionsLock = new Object();


    /**
    /** Add an entry to the application context list. */
     * Add an entry to the application context list.
    App add(
     */
            UUID uuid,
    App add(UUID uuid, WorkSource workSource, C callback, T info, GattService service) {
            WorkSource workSource,
        int appUid = Binder.getCallingUid();
            C callback,
        String appName = service.getPackageManager().getNameForUid(appUid);
            GattService.PendingIntentInfo piInfo,
            GattService service) {
        int appUid;
        String appName = null;
        if (piInfo != null) {
            appUid = piInfo.callingUid;
            appName = piInfo.callingPackage;
        } else {
            appUid = Binder.getCallingUid();
            appName = service.getPackageManager().getNameForUid(appUid);
        }
        if (appName == null) {
        if (appName == null) {
            // Assign an app name if one isn't found
            // Assign an app name if one isn't found
            appName = "Unknown App (UID: " + appUid + ")";
            appName = "Unknown App (UID: " + appUid + ")";
@@ -225,7 +235,7 @@ public class ContextMap<C, T> {
                appScanStats = new AppScanStats(appName, workSource, this, service);
                appScanStats = new AppScanStats(appName, workSource, this, service);
                mAppScanStats.put(appUid, appScanStats);
                mAppScanStats.put(appUid, appScanStats);
            }
            }
            App app = new App(uuid, callback, info, appName, appScanStats);
            App app = new App(uuid, callback, (T) piInfo, appName, appScanStats);
            mApps.add(app);
            mApps.add(app);
            appScanStats.isRegistered = true;
            appScanStats.isRegistered = true;
            return app;
            return app;
+12 −4
Original line number Original line Diff line number Diff line
@@ -209,6 +209,7 @@ public class GattService extends ProfileService {
        public ScanSettings settings;
        public ScanSettings settings;
        public List<ScanFilter> filters;
        public List<ScanFilter> filters;
        public String callingPackage;
        public String callingPackage;
        public int callingUid;


        @Override
        @Override
        public boolean equals(Object other) {
        public boolean equals(Object other) {
@@ -3254,15 +3255,22 @@ public class GattService extends ProfileService {
        settings = enforceReportDelayFloor(settings);
        settings = enforceReportDelayFloor(settings);
        enforcePrivilegedPermissionIfNeeded(filters);
        enforcePrivilegedPermissionIfNeeded(filters);
        UUID uuid = UUID.randomUUID();
        UUID uuid = UUID.randomUUID();
        if (DBG) {
            Log.d(TAG, "startScan(PI) - UUID=" + uuid);
        }
        String callingPackage = attributionSource.getPackageName();
        String callingPackage = attributionSource.getPackageName();
        int callingUid = attributionSource.getUid();
        PendingIntentInfo piInfo = new PendingIntentInfo();
        PendingIntentInfo piInfo = new PendingIntentInfo();
        piInfo.intent = pendingIntent;
        piInfo.intent = pendingIntent;
        piInfo.settings = settings;
        piInfo.settings = settings;
        piInfo.filters = filters;
        piInfo.filters = filters;
        piInfo.callingPackage = callingPackage;
        piInfo.callingPackage = callingPackage;
        piInfo.callingUid = callingUid;
        if (DBG) {
            Log.d(
                    TAG,
                    "startScan(PI) -"
                            + (" UUID=" + uuid)
                            + (" Package=" + callingPackage)
                            + (" UID=" + callingUid));
        }


        // Don't start scan if the Pi scan already in mScannerMap.
        // Don't start scan if the Pi scan already in mScannerMap.
        if (mScannerMap.getByContextInfo(piInfo) != null) {
        if (mScannerMap.getByContextInfo(piInfo) != null) {
@@ -3313,7 +3321,7 @@ public class GattService extends ProfileService {
    void continuePiStartScan(int scannerId, ScannerMap.App app) {
    void continuePiStartScan(int scannerId, ScannerMap.App app) {
        final PendingIntentInfo piInfo = app.info;
        final PendingIntentInfo piInfo = app.info;
        final ScanClient scanClient =
        final ScanClient scanClient =
                new ScanClient(scannerId, piInfo.settings, piInfo.filters);
                new ScanClient(scannerId, piInfo.settings, piInfo.filters, piInfo.callingUid);
        scanClient.hasLocationPermission = app.hasLocationPermission;
        scanClient.hasLocationPermission = app.hasLocationPermission;
        scanClient.userHandle = app.mUserHandle;
        scanClient.userHandle = app.mUserHandle;
        scanClient.isQApp = checkCallerTargetSdk(this, app.name, Build.VERSION_CODES.Q);
        scanClient.isQApp = checkCallerTargetSdk(this, app.name, Build.VERSION_CODES.Q);
+5 −1
Original line number Original line Diff line number Diff line
@@ -58,11 +58,15 @@ import java.util.Objects;
    }
    }


    ScanClient(int scannerId, ScanSettings settings, List<ScanFilter> filters) {
    ScanClient(int scannerId, ScanSettings settings, List<ScanFilter> filters) {
        this(scannerId, settings, filters, Binder.getCallingUid());
    }

    ScanClient(int scannerId, ScanSettings settings, List<ScanFilter> filters, int appUid) {
        this.scannerId = scannerId;
        this.scannerId = scannerId;
        this.settings = settings;
        this.settings = settings;
        this.scanModeApp = settings.getScanMode();
        this.scanModeApp = settings.getScanMode();
        this.filters = filters;
        this.filters = filters;
        this.appUid = Binder.getCallingUid();
        this.appUid = appUid;
    }
    }


    @Override
    @Override
+14 −0
Original line number Original line Diff line number Diff line
@@ -384,6 +384,7 @@ public class ScanManager {
            if (DBG) {
            if (DBG) {
                Log.d(TAG, "handling starting scan");
                Log.d(TAG, "handling starting scan");
            }
            }
            fetchAppForegroundState(client);


            if (!isScanSupported(client)) {
            if (!isScanSupported(client)) {
                Log.e(TAG, "Scan settings not supported");
                Log.e(TAG, "Scan settings not supported");
@@ -730,6 +731,19 @@ public class ScanManager {
            return mIsUidForegroundMap.get(client.appUid, DEFAULT_UID_IS_FOREGROUND);
            return mIsUidForegroundMap.get(client.appUid, DEFAULT_UID_IS_FOREGROUND);
        }
        }


        private void fetchAppForegroundState(ScanClient client) {
            if (mActivityManager == null || mAdapterService.getPackageManager() == null) {
                return;
            }
            String packageName =
                    mAdapterService.getPackageManager().getPackagesForUid(client.appUid)[0];
            int importance = mActivityManager.getPackageImportance(packageName);
            boolean isForeground =
                    importance
                            <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
            mIsUidForegroundMap.put(client.appUid, isForeground);
        }

        private boolean updateScanModeBeforeStart(ScanClient client) {
        private boolean updateScanModeBeforeStart(ScanClient client) {
            if (upgradeScanModeBeforeStart(client)) {
            if (upgradeScanModeBeforeStart(client)) {
                return true;
                return true;
+27 −0
Original line number Original line Diff line number Diff line
@@ -62,6 +62,7 @@ import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoAnnotations;


@@ -263,6 +264,32 @@ public class GattServiceTest {
        verify(mScanManager).startScan(any());
        verify(mScanManager).startScan(any());
    }
    }


    @Test
    public void continuePiStartScanCheckUid() {
        int scannerId = 1;

        mPiInfo.settings = new ScanSettings.Builder().build();
        mPiInfo.callingUid = 123;
        mApp.info = mPiInfo;

        AppScanStats appScanStats = mock(AppScanStats.class);
        doReturn(appScanStats).when(mScannerMap).getAppScanStatsById(scannerId);

        mService.continuePiStartScan(scannerId, mApp);

        verify(appScanStats)
                .recordScanStart(mPiInfo.settings, mPiInfo.filters, false, false, scannerId);
        verify(mScanManager)
                .startScan(
                        argThat(
                                new ArgumentMatcher<ScanClient>() {
                                    @Override
                                    public boolean matches(ScanClient client) {
                                        return mPiInfo.callingUid == client.appUid;
                                    }
                                }));
    }

    @Test
    @Test
    public void onBatchScanReportsInternal_deliverBatchScan() throws RemoteException {
    public void onBatchScanReportsInternal_deliverBatchScan() throws RemoteException {
        int status = 1;
        int status = 1;