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

Commit 7c81f3d7 authored by Jack He's avatar Jack He Committed by Gerrit Code Review
Browse files

Merge changes I4d330f03,I038d33c7 into main

* changes:
  Format bluetooth-test-util-lib code to meet PREUPLOAD conditions
  Cert: Defer unknown DCID in L2capTests
parents 7f0987bc a17c6ea2
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -20,9 +20,9 @@ java_library {
    name: "bluetooth-test-util-lib",
    defaults: ["cts_defaults"],
    static_libs: [
        "junit",
        "compatibility-device-util-axt",
        "PlatformProperties",
        "compatibility-device-util-axt",
        "junit",
    ],
    srcs: ["src/**/*.java"],
    sdk_version: "test_current",
+19 −31
Original line number Diff line number Diff line
@@ -32,9 +32,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Utility for controlling the Bluetooth adapter from CTS test.
 */
/** Utility for controlling the Bluetooth adapter from CTS test. */
public class BTAdapterUtils {
    private static final String TAG = "BTAdapterUtils";

@@ -51,6 +49,7 @@ public class BTAdapterUtils {
    public static final int STATE_BLE_TURNING_OFF = 16;

    private static final SparseIntArray sStateTimeouts = new SparseIntArray();

    static {
        sStateTimeouts.put(BluetoothAdapter.STATE_OFF, ADAPTER_DISABLE_TIMEOUT_MS);
        sStateTimeouts.put(BluetoothAdapter.STATE_TURNING_ON, ADAPTER_ENABLE_TIMEOUT_MS);
@@ -69,9 +68,7 @@ public class BTAdapterUtils {
    private static int sDesiredState;
    private static int sAdapterState;

    /**
     * Handles BluetoothAdapter state changes and signals when we have reached a desired state
     */
    /** Handles BluetoothAdapter state changes and signals when we have reached a desired state */
    private static class BluetoothAdapterReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
@@ -95,9 +92,7 @@ public class BTAdapterUtils {
        }
    }

    /**
     * Initialize all static state variables
     */
    /** Initialize all static state variables */
    private static void initAdapterStateVariables(Context context) {
        Log.d(TAG, "Initializing adapter state variables");
        sAdapterReceiver = new BluetoothAdapterReceiver();
@@ -113,7 +108,7 @@ public class BTAdapterUtils {
    /**
     * Wait for the bluetooth adapter to be in a given state
     *
     * Assumes all state variables are initialized. Assumes it's being run with
     * <p>Assumes all state variables are initialized. Assumes it's being run with
     * sBluetoothAdapterLock in the locked state.
     */
    private static boolean waitForAdapterStateLocked(int desiredState, BluetoothAdapter adapter)
@@ -136,8 +131,12 @@ public class BTAdapterUtils {
                    Log.d(TAG, "adapter isLeEnabled: " + adapter.isLeEnabled());
                    return adapter.isLeEnabled();
                }
                Log.e(TAG, "Timeout while waiting for Bluetooth adapter state " + desiredState
                        + " while current state is " + sAdapterState);
                Log.e(
                        TAG,
                        "Timeout while waiting for Bluetooth adapter state "
                                + desiredState
                                + " while current state is "
                                + sAdapterState);
                break;
            }
        }
@@ -147,9 +146,7 @@ public class BTAdapterUtils {
        return sAdapterState == desiredState;
    }

    /**
     * Utility method to wait on any specific adapter state
     */
    /** Utility method to wait on any specific adapter state */
    public static boolean waitForAdapterState(int desiredState, BluetoothAdapter adapter) {
        sBluetoothAdapterLock.lock();
        try {
@@ -162,9 +159,7 @@ public class BTAdapterUtils {
        return false;
    }

    /**
     * Enables Bluetooth to a Low Energy only mode
     */
    /** Enables Bluetooth to a Low Energy only mode */
    public static boolean enableBLE(BluetoothAdapter bluetoothAdapter, Context context) {
        if (!sAdapterVarsInitialized) {
            initAdapterStateVariables(context);
@@ -190,9 +185,7 @@ public class BTAdapterUtils {
        return false;
    }

    /**
     * Disable Bluetooth Low Energy mode
     */
    /** Disable Bluetooth Low Energy mode */
    public static boolean disableBLE(BluetoothAdapter bluetoothAdapter, Context context) {
        if (!sAdapterVarsInitialized) {
            initAdapterStateVariables(context);
@@ -215,9 +208,7 @@ public class BTAdapterUtils {
        return false;
    }

    /**
     * Enables the Bluetooth Adapter. Return true if it is already enabled or is enabled.
     */
    /** Enables the Bluetooth Adapter. Return true if it is already enabled or is enabled. */
    public static boolean enableAdapter(BluetoothAdapter bluetoothAdapter, Context context) {
        if (!sAdapterVarsInitialized) {
            initAdapterStateVariables(context);
@@ -247,9 +238,7 @@ public class BTAdapterUtils {
        return false;
    }

    /**
     * Disable the Bluetooth Adapter. Return true if it is already disabled or is disabled.
     */
    /** Disable the Bluetooth Adapter. Return true if it is already disabled or is disabled. */
    public static boolean disableAdapter(BluetoothAdapter bluetoothAdapter, Context context) {
        return disableAdapter(bluetoothAdapter, true, context);
    }
@@ -257,10 +246,10 @@ public class BTAdapterUtils {
    /**
     * Disable the Bluetooth Adapter with then option to persist the off state or not.
     *
     * Returns true if the adapter is already disabled or was disabled.
     * <p>Returns true if the adapter is already disabled or was disabled.
     */
    public static boolean disableAdapter(BluetoothAdapter bluetoothAdapter, boolean persist,
            Context context) {
    public static boolean disableAdapter(
            BluetoothAdapter bluetoothAdapter, boolean persist, Context context) {
        if (!sAdapterVarsInitialized) {
            initAdapterStateVariables(context);
        }
@@ -289,4 +278,3 @@ public class BTAdapterUtils {
        return false;
    }
}
+9 −7
Original line number Diff line number Diff line
@@ -34,8 +34,8 @@ import org.junit.runner.Description;
import org.junit.runners.model.Statement;

/**
 * This is a test rule that, when used in a test, will enable Bluetooth before the test starts.
 * When the test is done, Bluetooth will be disabled if and only if it was disabled before the test
 * This is a test rule that, when used in a test, will enable Bluetooth before the test starts. When
 * the test is done, Bluetooth will be disabled if and only if it was disabled before the test
 * started. If setTestMode is set to true, the Bluetooth scanner will return a hardcoded set of
 * Bluetooth scan results while the test runs .
 */
@@ -73,12 +73,14 @@ public class EnableBluetoothRule extends BeforeAfterRule {
    }

    private void enableBluetoothTestMode() {
        runShellCommandOrThrow("dumpsys activity service"
        runShellCommandOrThrow(
                "dumpsys activity service"
                        + " com.android.bluetooth.btservice.AdapterService set-test-mode enabled");
    }

    private void disableBluetoothTestMode() {
        runShellCommandOrThrow("dumpsys activity service"
        runShellCommandOrThrow(
                "dumpsys activity service"
                        + " com.android.bluetooth.btservice.AdapterService set-test-mode disabled");
    }

+79 −82
Original line number Diff line number Diff line
@@ -41,23 +41,19 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Utility class for Bluetooth CTS test.
 */
/** Utility class for Bluetooth CTS test. */
public class TestUtils {
    /**
     * Checks whether this device has Bluetooth feature
     *
     * @return true if this device has Bluetooth feature
     */
    public static boolean hasBluetooth() {
        Context context = InstrumentationRegistry.getInstrumentation().getContext();
        return context.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_BLUETOOTH);
        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH);
    }

    /**
     * Get the current enabled status of a given profile
     */
    /** Get the current enabled status of a given profile */
    public static boolean isProfileEnabled(int profile) {
        switch (profile) {
            case BluetoothProfile.A2DP:
@@ -129,18 +125,19 @@ public class TestUtils {

    /**
     * Adopt shell UID's permission via {@link android.app.UiAutomation}
     *
     * @param permission permission to adopt
     */
    public static void adoptPermissionAsShellUid(@Nullable String... permission) {
        InstrumentationRegistry.getInstrumentation().getUiAutomation()
        InstrumentationRegistry.getInstrumentation()
                .getUiAutomation()
                .adoptShellPermissionIdentity(permission);
    }

    /**
     * Drop all permissions adopted as shell UID
     */
    /** Drop all permissions adopted as shell UID */
    public static void dropPermissionAsShellUid() {
        InstrumentationRegistry.getInstrumentation().getUiAutomation()
        InstrumentationRegistry.getInstrumentation()
                .getUiAutomation()
                .dropShellPermissionIdentity();
    }

@@ -148,16 +145,19 @@ public class TestUtils {
     * @return permissions adopted from Shell
     */
    public static Set<String> getAdoptedShellPermissions() {
        return InstrumentationRegistry.getInstrumentation().getUiAutomation()
        return InstrumentationRegistry.getInstrumentation()
                .getUiAutomation()
                .getAdoptedShellPermissions();
    }

    /**
     * Get {@link BluetoothAdapter} via {@link android.bluetooth.BluetoothManager}
     * Fail the test if {@link BluetoothAdapter} is null
     * Get {@link BluetoothAdapter} via {@link android.bluetooth.BluetoothManager} Fail the test if
     * {@link BluetoothAdapter} is null
     *
     * @return instance of {@link BluetoothAdapter}
     */
    @NonNull public static BluetoothAdapter getBluetoothAdapterOrDie() {
    @NonNull
    public static BluetoothAdapter getBluetoothAdapterOrDie() {
        Context context = InstrumentationRegistry.getInstrumentation().getContext();
        BluetoothManager manager = context.getSystemService(BluetoothManager.class);
        assertNotNull(manager);
@@ -166,69 +166,63 @@ public class TestUtils {
        return adapter;
    }

    /**
     * Utility method to call hidden ScanRecord.parseFromBytes method.
     */
    /** Utility method to call hidden ScanRecord.parseFromBytes method. */
    public static ScanRecord parseScanRecord(byte[] bytes) {
        Class<?> scanRecordClass = ScanRecord.class;
        try {
            Method method = scanRecordClass.getDeclaredMethod("parseFromBytes", byte[].class);
            return (ScanRecord) method.invoke(null, bytes);
        } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException
        } catch (NoSuchMethodException
                | IllegalAccessException
                | IllegalArgumentException
                | InvocationTargetException e) {
            return null;
        }
    }

    /**
     * Assert two byte arrays are equal.
     */
    /** Assert two byte arrays are equal. */
    public static void assertArrayEquals(byte[] expected, byte[] actual) {
        if (!Arrays.equals(expected, actual)) {
            fail("expected:<" + Arrays.toString(expected)
                    + "> but was:<" + Arrays.toString(actual) + ">");
            fail(
                    "expected:<"
                            + Arrays.toString(expected)
                            + "> but was:<"
                            + Arrays.toString(actual)
                            + ">");
        }
    }

    /**
     * Get current location mode settings.
     */
    /** Get current location mode settings. */
    public static int getLocationMode(Context context) {
        return Settings.Secure.getInt(context.getContentResolver(),
                Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
        return Settings.Secure.getInt(
                context.getContentResolver(),
                Settings.Secure.LOCATION_MODE,
                Settings.Secure.LOCATION_MODE_OFF);
    }

    /**
     * Set location settings mode.
     */
    /** Set location settings mode. */
    public static void setLocationMode(Context context, int mode) {
        Settings.Secure.putInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE,
                mode);
        Settings.Secure.putInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE, mode);
    }

    /**
     * Return true if location is on.
     */
    /** Return true if location is on. */
    public static boolean isLocationOn(Context context) {
        return getLocationMode(context) != Settings.Secure.LOCATION_MODE_OFF;
    }

    /**
     * Enable location and set the mode to GPS only.
     */
    /** Enable location and set the mode to GPS only. */
    public static void enableLocation(Context context) {
        setLocationMode(context, Settings.Secure.LOCATION_MODE_SENSORS_ONLY);
    }

    /**
     * Disable location.
     */
    /** Disable location. */
    public static void disableLocation(Context context) {
        setLocationMode(context, Settings.Secure.LOCATION_MODE_OFF);
    }

    /**
     * Check if BLE is supported by this platform
     *
     * @param context current device context
     * @return true if BLE is supported, false otherwise
     */
@@ -238,6 +232,7 @@ public class TestUtils {

    /**
     * Check if this is an automotive device
     *
     * @param context current device context
     * @return true if this Android device is an automotive device, false otherwise
     */
@@ -247,6 +242,7 @@ public class TestUtils {

    /**
     * Check if this is a watch device
     *
     * @param context current device context
     * @return true if this Android device is a watch device, false otherwise
     */
@@ -256,6 +252,7 @@ public class TestUtils {

    /**
     * Check if this is a TV device
     *
     * @param context current device context
     * @return true if this Android device is a TV device, false otherwise
     */
@@ -267,6 +264,7 @@ public class TestUtils {

    /**
     * Put the current thread to sleep.
     *
     * @param sleepMillis number of milliseconds to sleep for
     */
    public static void sleep(int sleepMillis) {
@@ -277,9 +275,7 @@ public class TestUtils {
        }
    }

    /**
     * Boilerplate class for profile listener
     */
    /** Boilerplate class for profile listener */
    public static class BluetoothCtsServiceConnector {
        private static final int PROXY_CONNECTION_TIMEOUT_MS = 500; // ms timeout for Proxy Connect
        private BluetoothProfile mProfileProxy = null;
@@ -291,8 +287,9 @@ public class TestUtils {
        private final int mProfileId;
        private final BluetoothAdapter mAdapter;
        private final Context mContext;
        public BluetoothCtsServiceConnector(String logTag, int profileId, BluetoothAdapter adapter,
                Context context) {

        public BluetoothCtsServiceConnector(
                String logTag, int profileId, BluetoothAdapter adapter, Context context) {
            mLogTag = logTag;
            mProfileId = profileId;
            mAdapter = adapter;
+20 −7
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#   limitations under the License.

import logging
from queue import SimpleQueue

from blueberry.tests.gd.cert.behavior import IHasBehaviors, SingleArgumentBehavior, ReplyStage
from blueberry.tests.gd.cert.captures import L2capCaptures
@@ -151,7 +152,7 @@ class CertL2capControlChannelBehaviors(object):
        def _send_configuration_response(self, request, result=ConfigurationResponseResult.SUCCESS, options=None):
            dcid = request.GetDestinationCid()
            if dcid not in self.parent.scid_to_channel:
                logging.warning("Received config request with unknown dcid")
                logging.warning("_send_configuration_response with unknown dcid 0x{:X}".format(dcid))
                return
            self.parent.scid_to_channel[dcid].send_configuration_response(request, result, options)

@@ -172,6 +173,7 @@ class CertL2cap(Closable, IHasBehaviors):
            CommandCode.INFORMATION_REQUEST: self._on_information_request_default,
            CommandCode.INFORMATION_RESPONSE: self._on_information_response_default
        }
        self.pending_configuration_requests = SimpleQueue()

        self.scid_to_channel = {}

@@ -191,8 +193,12 @@ class CertL2cap(Closable, IHasBehaviors):
    def connect_acl(self, remote_addr):
        self._acl_manager.initiate_connection(remote_addr)
        self._acl = self._acl_manager.complete_outgoing_connection()
        self.control_channel = CertL2capChannel(
            self._device, 1, 1, self._acl.acl_stream, self._acl, control_channel=None)
        self.control_channel = CertL2capChannel(self._device,
                                                1,
                                                1,
                                                self._acl.acl_stream,
                                                self._acl,
                                                control_channel=None)
        self._acl.acl_stream.register_callback(self._handle_control_packet)

    def accept_incoming_connection(self):
@@ -208,11 +214,14 @@ class CertL2cap(Closable, IHasBehaviors):
                                   response.get().GetDestinationCid(), self._acl.acl_stream, self._acl,
                                   self.control_channel, fcs)
        self.scid_to_channel[scid] = channel
        while not self.pending_configuration_requests.empty():
            l2cap_control_view = self.pending_configuration_requests.get_nowait()
            logging.info("Handling deferred configuration requests")
            self._on_configuration_request_default(l2cap_control_view, defer_unknown_dcid=False)

        return channel

    def verify_and_respond_open_channel_from_remote(self, psm=0x33, scid=None, fcs=None):

        request = L2capCaptures.ConnectionRequest(psm)
        assertThat(self.control_channel).emits(request)

@@ -259,18 +268,22 @@ class CertL2cap(Closable, IHasBehaviors):
    def get_control_channel(self):
        return self.control_channel

    # Disable ERTM when exchange extened feature
    # Disable ERTM when exchange extended feature
    def claim_ertm_unsupported(self):
        self.support_ertm = False

    def _on_connection_response_default(self, l2cap_control_view):
        pass

    def _on_configuration_request_default(self, l2cap_control_view):
    def _on_configuration_request_default(self, l2cap_control_view, defer_unknown_dcid=True):
        request = l2cap_packets.ConfigurationRequestView(l2cap_control_view)
        dcid = request.GetDestinationCid()
        if dcid not in self.scid_to_channel:
            logging.warning("Received config request with unknown dcid")
            if defer_unknown_dcid:
                logging.info("Received config request with unknown dcid 0x{:X} deferring".format(dcid))
                self.pending_configuration_requests.put(l2cap_control_view)
            else:
                logging.warning("Received config request with unknown dcid 0x{:X}".format(dcid))
            return
        self._control_behaviors.on_config_req_behavior.run(request)