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

Commit 46fb236e authored by William Escande's avatar William Escande
Browse files

Split nativeInterface of AdvertiseManager

This allow to mock the interface and remove the flakiness of this test
since it depends on the native library

Bug: 285959170
Test: atest AdvertiseManagerTest
Change-Id: Ifc86eff6f5055ee26fe1060333a84225741914d5
parent b88ffcbd
Loading
Loading
Loading
Loading
+4 −4
Original line number Original line Diff line number Diff line
@@ -2682,7 +2682,7 @@ static void stopDistanceMeasurementNative(JNIEnv* env, jobject object,
 * JNI function definitinos
 * JNI function definitinos
 */
 */


// JNI functions defined in AdvertiseManager class.
// JNI functions defined in AdvertiseManagerNativeInterface class.
static JNINativeMethod sAdvertiseMethods[] = {
static JNINativeMethod sAdvertiseMethods[] = {
    {"classInitNative", "()V", (void*)advertiseClassInitNative},
    {"classInitNative", "()V", (void*)advertiseClassInitNative},
    {"initializeNative", "()V", (void*)advertiseInitializeNative},
    {"initializeNative", "()V", (void*)advertiseInitializeNative},
@@ -2691,8 +2691,8 @@ static JNINativeMethod sAdvertiseMethods[] = {
     "(Landroid/bluetooth/le/AdvertisingSetParameters;[B[BLandroid/bluetooth/"
     "(Landroid/bluetooth/le/AdvertisingSetParameters;[B[BLandroid/bluetooth/"
     "le/PeriodicAdvertisingParameters;[BIIII)V",
     "le/PeriodicAdvertisingParameters;[BIIII)V",
     (void*)startAdvertisingSetNative},
     (void*)startAdvertisingSetNative},
    {"getOwnAddressNative", "(I)V", (void*)getOwnAddressNative},
    {"stopAdvertisingSetNative", "(I)V", (void*)stopAdvertisingSetNative},
    {"stopAdvertisingSetNative", "(I)V", (void*)stopAdvertisingSetNative},
    {"getOwnAddressNative", "(I)V", (void*)getOwnAddressNative},
    {"enableAdvertisingSetNative", "(IZII)V",
    {"enableAdvertisingSetNative", "(IZII)V",
     (void*)enableAdvertisingSetNative},
     (void*)enableAdvertisingSetNative},
    {"setAdvertisingDataNative", "(I[B)V", (void*)setAdvertisingDataNative},
    {"setAdvertisingDataNative", "(I[B)V", (void*)setAdvertisingDataNative},
@@ -2848,8 +2848,8 @@ int register_com_android_bluetooth_gatt(JNIEnv* env) {
      env, "com/android/bluetooth/gatt/ScanNativeInterface", sScanMethods,
      env, "com/android/bluetooth/gatt/ScanNativeInterface", sScanMethods,
      NELEM(sScanMethods));
      NELEM(sScanMethods));
  register_success &= jniRegisterNativeMethods(
  register_success &= jniRegisterNativeMethods(
      env, "com/android/bluetooth/gatt/AdvertiseManager", sAdvertiseMethods,
      env, "com/android/bluetooth/gatt/AdvertiseManagerNativeInterface",
      NELEM(sAdvertiseMethods));
      sAdvertiseMethods, NELEM(sAdvertiseMethods));
  register_success &= jniRegisterNativeMethods(
  register_success &= jniRegisterNativeMethods(
      env, "com/android/bluetooth/gatt/PeriodicScanManager",
      env, "com/android/bluetooth/gatt/PeriodicScanManager",
      sPeriodicScanMethods, NELEM(sPeriodicScanMethods));
      sPeriodicScanMethods, NELEM(sPeriodicScanMethods));
+31 −57
Original line number Original line Diff line number Diff line
@@ -51,20 +51,23 @@ public class AdvertiseManager {


    private final GattService mService;
    private final GattService mService;
    private final AdapterService mAdapterService;
    private final AdapterService mAdapterService;
    private final AdvertiseManagerNativeInterface mNativeInterface;
    private final AdvertiserMap mAdvertiserMap;
    private final AdvertiserMap mAdvertiserMap;
    private Handler mHandler;
    private Handler mHandler;
    Map<IBinder, AdvertiserInfo> mAdvertisers = Collections.synchronizedMap(new HashMap<>());
    Map<IBinder, AdvertiserInfo> mAdvertisers = Collections.synchronizedMap(new HashMap<>());
    static int sTempRegistrationId = -1;
    static int sTempRegistrationId = -1;


    /**
    /** Constructor of {@link AdvertiseManager}. */
     * Constructor of {@link AdvertiseManager}.
    AdvertiseManager(
     */
            GattService service,
    AdvertiseManager(GattService service, AdapterService adapterService,
            AdvertiseManagerNativeInterface nativeInterface,
            AdapterService adapterService,
            AdvertiserMap advertiserMap) {
            AdvertiserMap advertiserMap) {
        if (DBG) {
        if (DBG) {
            Log.d(TAG, "advertise manager created");
            Log.d(TAG, "advertise manager created");
        }
        }
        mService = service;
        mService = service;
        mNativeInterface = nativeInterface;
        mAdapterService = adapterService;
        mAdapterService = adapterService;
        mAdvertiserMap = advertiserMap;
        mAdvertiserMap = advertiserMap;
    }
    }
@@ -73,7 +76,7 @@ public class AdvertiseManager {
     * Start a {@link HandlerThread} that handles advertising operations.
     * Start a {@link HandlerThread} that handles advertising operations.
     */
     */
    void start() {
    void start() {
        initializeNative();
        mNativeInterface.init(this);
        HandlerThread thread = new HandlerThread("BluetoothAdvertiseManager");
        HandlerThread thread = new HandlerThread("BluetoothAdvertiseManager");
        thread.start();
        thread.start();
        mHandler = new Handler(thread.getLooper());
        mHandler = new Handler(thread.getLooper());
@@ -83,7 +86,7 @@ public class AdvertiseManager {
        if (DBG) {
        if (DBG) {
            Log.d(TAG, "cleanup()");
            Log.d(TAG, "cleanup()");
        }
        }
        cleanupNative();
        mNativeInterface.cleanup();
        mAdvertisers.clear();
        mAdvertisers.clear();
        sTempRegistrationId = -1;
        sTempRegistrationId = -1;


@@ -157,7 +160,7 @@ public class AdvertiseManager {
        if (entry == null) {
        if (entry == null) {
            Log.i(TAG, "onAdvertisingSetStarted() - no callback found for regId " + regId);
            Log.i(TAG, "onAdvertisingSetStarted() - no callback found for regId " + regId);
            // Advertising set was stopped before it was properly registered.
            // Advertising set was stopped before it was properly registered.
            stopAdvertisingSetNative(advertiserId);
            mNativeInterface.stopAdvertisingSet(advertiserId);
            return;
            return;
        }
        }


@@ -252,8 +255,15 @@ public class AdvertiseManager {
            mAdvertiserMap.recordAdvertiseStart(cbId, parameters, advertiseData,
            mAdvertiserMap.recordAdvertiseStart(cbId, parameters, advertiseData,
                    scanResponse, periodicParameters, periodicData, duration, maxExtAdvEvents);
                    scanResponse, periodicParameters, periodicData, duration, maxExtAdvEvents);


            startAdvertisingSetNative(parameters, advDataBytes, scanResponseBytes,
            mNativeInterface.startAdvertisingSet(
                    periodicParameters, periodicDataBytes, duration, maxExtAdvEvents, cbId,
                    parameters,
                    advDataBytes,
                    scanResponseBytes,
                    periodicParameters,
                    periodicDataBytes,
                    duration,
                    maxExtAdvEvents,
                    cbId,
                    serverIf);
                    serverIf);


        } catch (IllegalArgumentException e) {
        } catch (IllegalArgumentException e) {
@@ -289,7 +299,7 @@ public class AdvertiseManager {
            Log.w(TAG, "getOwnAddress() - bad advertiserId " + advertiserId);
            Log.w(TAG, "getOwnAddress() - bad advertiserId " + advertiserId);
            return;
            return;
        }
        }
        getOwnAddressNative(advertiserId);
        mNativeInterface.getOwnAddress(advertiserId);
    }
    }


    void stopAdvertisingSet(IAdvertisingSetCallback callback) {
    void stopAdvertisingSet(IAdvertisingSetCallback callback) {
@@ -313,7 +323,7 @@ public class AdvertiseManager {
            return;
            return;
        }
        }


        stopAdvertisingSetNative(advertiserId);
        mNativeInterface.stopAdvertisingSet(advertiserId);


        try {
        try {
            callback.onAdvertisingSetStopped(advertiserId);
            callback.onAdvertisingSetStopped(advertiserId);
@@ -330,7 +340,7 @@ public class AdvertiseManager {
            Log.w(TAG, "enableAdvertisingSet() - bad advertiserId " + advertiserId);
            Log.w(TAG, "enableAdvertisingSet() - bad advertiserId " + advertiserId);
            return;
            return;
        }
        }
        enableAdvertisingSetNative(advertiserId, enable, duration, maxExtAdvEvents);
        mNativeInterface.enableAdvertisingSet(advertiserId, enable, duration, maxExtAdvEvents);


        mAdvertiserMap.enableAdvertisingSet(advertiserId,
        mAdvertiserMap.enableAdvertisingSet(advertiserId,
                enable, duration, maxExtAdvEvents);
                enable, duration, maxExtAdvEvents);
@@ -344,8 +354,8 @@ public class AdvertiseManager {
        }
        }
        String deviceName = AdapterService.getAdapterService().getName();
        String deviceName = AdapterService.getAdapterService().getName();
        try {
        try {
            setAdvertisingDataNative(advertiserId,
            mNativeInterface.setAdvertisingData(
                    AdvertiseHelper.advertiseDataToBytes(data, deviceName));
                    advertiserId, AdvertiseHelper.advertiseDataToBytes(data, deviceName));


            mAdvertiserMap.setAdvertisingData(advertiserId, data);
            mAdvertiserMap.setAdvertisingData(advertiserId, data);
        } catch (IllegalArgumentException e) {
        } catch (IllegalArgumentException e) {
@@ -366,8 +376,8 @@ public class AdvertiseManager {
        }
        }
        String deviceName = AdapterService.getAdapterService().getName();
        String deviceName = AdapterService.getAdapterService().getName();
        try {
        try {
            setScanResponseDataNative(advertiserId,
            mNativeInterface.setScanResponseData(
                    AdvertiseHelper.advertiseDataToBytes(data, deviceName));
                    advertiserId, AdvertiseHelper.advertiseDataToBytes(data, deviceName));


            mAdvertiserMap.setScanResponseData(advertiserId, data);
            mAdvertiserMap.setScanResponseData(advertiserId, data);
        } catch (IllegalArgumentException e) {
        } catch (IllegalArgumentException e) {
@@ -386,7 +396,7 @@ public class AdvertiseManager {
            Log.w(TAG, "setAdvertisingParameters() - bad advertiserId " + advertiserId);
            Log.w(TAG, "setAdvertisingParameters() - bad advertiserId " + advertiserId);
            return;
            return;
        }
        }
        setAdvertisingParametersNative(advertiserId, parameters);
        mNativeInterface.setAdvertisingParameters(advertiserId, parameters);


        mAdvertiserMap.setAdvertisingParameters(advertiserId, parameters);
        mAdvertiserMap.setAdvertisingParameters(advertiserId, parameters);
    }
    }
@@ -398,7 +408,7 @@ public class AdvertiseManager {
            Log.w(TAG, "setPeriodicAdvertisingParameters() - bad advertiserId " + advertiserId);
            Log.w(TAG, "setPeriodicAdvertisingParameters() - bad advertiserId " + advertiserId);
            return;
            return;
        }
        }
        setPeriodicAdvertisingParametersNative(advertiserId, parameters);
        mNativeInterface.setPeriodicAdvertisingParameters(advertiserId, parameters);


        mAdvertiserMap.setPeriodicAdvertisingParameters(advertiserId, parameters);
        mAdvertiserMap.setPeriodicAdvertisingParameters(advertiserId, parameters);
    }
    }
@@ -411,8 +421,8 @@ public class AdvertiseManager {
        }
        }
        String deviceName = AdapterService.getAdapterService().getName();
        String deviceName = AdapterService.getAdapterService().getName();
        try {
        try {
            setPeriodicAdvertisingDataNative(advertiserId,
            mNativeInterface.setPeriodicAdvertisingData(
                    AdvertiseHelper.advertiseDataToBytes(data, deviceName));
                    advertiserId, AdvertiseHelper.advertiseDataToBytes(data, deviceName));


            mAdvertiserMap.setPeriodicAdvertisingData(advertiserId, data);
            mAdvertiserMap.setPeriodicAdvertisingData(advertiserId, data);
        } catch (IllegalArgumentException e) {
        } catch (IllegalArgumentException e) {
@@ -431,7 +441,7 @@ public class AdvertiseManager {
            Log.w(TAG, "setPeriodicAdvertisingEnable() - bad advertiserId " + advertiserId);
            Log.w(TAG, "setPeriodicAdvertisingEnable() - bad advertiserId " + advertiserId);
            return;
            return;
        }
        }
        setPeriodicAdvertisingEnableNative(advertiserId, enable);
        mNativeInterface.setPeriodicAdvertisingEnable(advertiserId, enable);
    }
    }


    void onAdvertisingDataSet(int advertiserId, int status) throws Exception {
    void onAdvertisingDataSet(int advertiserId, int status) throws Exception {
@@ -538,40 +548,4 @@ public class AdvertiseManager {
            stats.onPeriodicAdvertiseEnabled(enable);
            stats.onPeriodicAdvertiseEnabled(enable);
        }
        }
    }
    }

    static {
        classInitNative();
    }

    private static native void classInitNative();

    private native void initializeNative();

    private native void cleanupNative();

    private native void startAdvertisingSetNative(AdvertisingSetParameters parameters,
            byte[] advertiseData, byte[] scanResponse,
            PeriodicAdvertisingParameters periodicParameters, byte[] periodicData, int duration,
            int maxExtAdvEvents, int regId, int serverIf);

    private native void getOwnAddressNative(int advertiserId);

    private native void stopAdvertisingSetNative(int advertiserId);

    private native void enableAdvertisingSetNative(int advertiserId, boolean enable, int duration,
            int maxExtAdvEvents);

    private native void setAdvertisingDataNative(int advertiserId, byte[] data);

    private native void setScanResponseDataNative(int advertiserId, byte[] data);

    private native void setAdvertisingParametersNative(int advertiserId,
            AdvertisingSetParameters parameters);

    private native void setPeriodicAdvertisingParametersNative(int advertiserId,
            PeriodicAdvertisingParameters parameters);

    private native void setPeriodicAdvertisingDataNative(int advertiserId, byte[] data);

    private native void setPeriodicAdvertisingEnableNative(int advertiserId, boolean enable);
}
}
+178 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.bluetooth.gatt;

import android.bluetooth.le.AdvertisingSetParameters;
import android.bluetooth.le.PeriodicAdvertisingParameters;

import androidx.annotation.VisibleForTesting;

/** Native interface for AdvertiseManager */
@VisibleForTesting
public class AdvertiseManagerNativeInterface {
    AdvertiseManager mManager;

    void init(AdvertiseManager manager) {
        mManager = manager;
        initializeNative();
    }

    void cleanup() {
        cleanupNative();
        mManager = null;
    }

    void startAdvertisingSet(
            AdvertisingSetParameters parameters,
            byte[] advertiseDataBytes,
            byte[] scanResponseBytes,
            PeriodicAdvertisingParameters periodicParameters,
            byte[] periodicDataBytes,
            int duration,
            int maxExtAdvEvents,
            int cbId,
            int serverIf) {
        startAdvertisingSetNative(
                parameters,
                advertiseDataBytes,
                scanResponseBytes,
                periodicParameters,
                periodicDataBytes,
                duration,
                maxExtAdvEvents,
                cbId,
                serverIf);
    }

    void stopAdvertisingSet(int advertiserId) {
        stopAdvertisingSetNative(advertiserId);
    }

    void getOwnAddress(int advertiserId) {
        getOwnAddressNative(advertiserId);
    }

    void enableAdvertisingSet(int advertiserId, boolean enable, int duration, int maxExtAdvEvents) {
        enableAdvertisingSetNative(advertiserId, enable, duration, maxExtAdvEvents);
    }

    void setAdvertisingData(int advertiserId, byte[] advertiseDataBytes) {
        setAdvertisingDataNative(advertiserId, advertiseDataBytes);
    }

    void setScanResponseData(int advertiserId, byte[] advertiseDataBytes) {
        setScanResponseDataNative(advertiserId, advertiseDataBytes);
    }

    void setAdvertisingParameters(int advertiserId, AdvertisingSetParameters parameters) {
        setAdvertisingParametersNative(advertiserId, parameters);
    }

    void setPeriodicAdvertisingParameters(
            int advertiserId, PeriodicAdvertisingParameters parameters) {
        setPeriodicAdvertisingParametersNative(advertiserId, parameters);
    }

    void setPeriodicAdvertisingData(int advertiserId, byte[] advertiseDataBytes) {
        setPeriodicAdvertisingDataNative(advertiserId, advertiseDataBytes);
    }

    void setPeriodicAdvertisingEnable(int advertiserId, boolean enable) {
        setPeriodicAdvertisingEnableNative(advertiserId, enable);
    }

    static {
        classInitNative();
    }

    void onAdvertisingSetStarted(int regId, int advertiserId, int txPower, int status)
            throws Exception {
        mManager.onAdvertisingSetStarted(regId, advertiserId, txPower, status);
    }

    void onOwnAddressRead(int advertiserId, int addressType, String address) throws Exception {
        mManager.onOwnAddressRead(advertiserId, addressType, address);
    }

    void onAdvertisingEnabled(int advertiserId, boolean enable, int status) throws Exception {
        mManager.onAdvertisingEnabled(advertiserId, enable, status);
    }

    void onAdvertisingDataSet(int advertiserId, int status) throws Exception {
        mManager.onAdvertisingDataSet(advertiserId, status);
    }

    void onScanResponseDataSet(int advertiserId, int status) throws Exception {
        mManager.onScanResponseDataSet(advertiserId, status);
    }

    void onAdvertisingParametersUpdated(int advertiserId, int txPower, int status)
            throws Exception {
        mManager.onAdvertisingParametersUpdated(advertiserId, txPower, status);
    }

    void onPeriodicAdvertisingParametersUpdated(int advertiserId, int status) throws Exception {
        mManager.onPeriodicAdvertisingParametersUpdated(advertiserId, status);
    }

    void onPeriodicAdvertisingDataSet(int advertiserId, int status) throws Exception {
        mManager.onPeriodicAdvertisingDataSet(advertiserId, status);
    }

    void onPeriodicAdvertisingEnabled(int advertiserId, boolean enable, int status)
            throws Exception {
        mManager.onPeriodicAdvertisingEnabled(advertiserId, enable, status);
    }

    private static native void classInitNative();

    private native void initializeNative();

    private native void cleanupNative();

    private native void startAdvertisingSetNative(
            AdvertisingSetParameters parameters,
            byte[] advertiseData,
            byte[] scanResponse,
            PeriodicAdvertisingParameters periodicParameters,
            byte[] periodicData,
            int duration,
            int maxExtAdvEvents,
            int regId,
            int serverIf);

    private native void stopAdvertisingSetNative(int advertiserId);

    private native void getOwnAddressNative(int advertiserId);

    private native void enableAdvertisingSetNative(
            int advertiserId, boolean enable, int duration, int maxExtAdvEvents);

    private native void setAdvertisingDataNative(int advertiserId, byte[] data);

    private native void setScanResponseDataNative(int advertiserId, byte[] data);

    private native void setAdvertisingParametersNative(
            int advertiserId, AdvertisingSetParameters parameters);

    private native void setPeriodicAdvertisingParametersNative(
            int advertiserId, PeriodicAdvertisingParameters parameters);

    private native void setPeriodicAdvertisingDataNative(int advertiserId, byte[] data);

    private native void setPeriodicAdvertisingEnableNative(int advertiserId, boolean enable);
}
+6 −1
Original line number Original line Diff line number Diff line
@@ -341,7 +341,12 @@ public class GattService extends ProfileService {
        mBluetoothAdapterProxy = BluetoothAdapterProxy.getInstance();
        mBluetoothAdapterProxy = BluetoothAdapterProxy.getInstance();
        mCompanionManager = getSystemService(CompanionDeviceManager.class);
        mCompanionManager = getSystemService(CompanionDeviceManager.class);
        mAppOps = getSystemService(AppOpsManager.class);
        mAppOps = getSystemService(AppOpsManager.class);
        mAdvertiseManager = new AdvertiseManager(this, mAdapterService, mAdvertiserMap);
        mAdvertiseManager =
                new AdvertiseManager(
                        this,
                        new AdvertiseManagerNativeInterface(),
                        mAdapterService,
                        mAdvertiserMap);
        mAdvertiseManager.start();
        mAdvertiseManager.start();


        mScanManager = GattObjectsFactory.getInstance()
        mScanManager = GattObjectsFactory.getInstance()
+5 −2
Original line number Original line Diff line number Diff line
@@ -16,7 +16,6 @@


package com.android.bluetooth.gatt;
package com.android.bluetooth.gatt;


import static com.google.common.truth.Truth.assertThat;


import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.eq;
@@ -59,6 +58,8 @@ public class AdvertiseManagerTest {
    @Mock
    @Mock
    private GattService.AdvertiserMap mAdvertiserMap;
    private GattService.AdvertiserMap mAdvertiserMap;


    @Mock private AdvertiseManagerNativeInterface mNativeInterface;

    @Mock
    @Mock
    private IAdvertisingSetCallback mCallback;
    private IAdvertisingSetCallback mCallback;


@@ -74,7 +75,9 @@ public class AdvertiseManagerTest {


        TestUtils.setAdapterService(mAdapterService);
        TestUtils.setAdapterService(mAdapterService);


        mAdvertiseManager = new AdvertiseManager(mService, mAdapterService, mAdvertiserMap);
        mAdvertiseManager =
                new AdvertiseManager(mService, mNativeInterface, mAdapterService, mAdvertiserMap);

        AdvertisingSetParameters parameters = new AdvertisingSetParameters.Builder().build();
        AdvertisingSetParameters parameters = new AdvertisingSetParameters.Builder().build();
        AdvertiseData advertiseData = new AdvertiseData.Builder().build();
        AdvertiseData advertiseData = new AdvertiseData.Builder().build();
        AdvertiseData scanResponse = new AdvertiseData.Builder().build();
        AdvertiseData scanResponse = new AdvertiseData.Builder().build();