mirror of
https://github.com/google/bumble.git
synced 2026-04-16 00:25:31 +00:00
add startupDelay and connectionPriority params to BtBench snippets
This commit is contained in:
@@ -28,7 +28,7 @@ class OneDeviceBenchTest(base_test.BaseTestClass):
|
||||
|
||||
def test_l2cap_client_ping(self):
|
||||
runner = self.dut.bench.runL2capClient(
|
||||
"ping", "4B:2A:67:76:2B:E3", 128, True, 100, 970, 100
|
||||
"ping", "4B:2A:67:76:2B:E3", 128, True, 100, 970, 100, "HIGH"
|
||||
)
|
||||
print("### Initial status:", runner)
|
||||
final_status = self.dut.bench.waitForRunnerCompletion(runner["id"])
|
||||
@@ -36,7 +36,15 @@ class OneDeviceBenchTest(base_test.BaseTestClass):
|
||||
|
||||
def test_l2cap_client_send(self):
|
||||
runner = self.dut.bench.runL2capClient(
|
||||
"send", "7E:90:D0:F2:7A:11", 131, True, 100, 970, 0
|
||||
"send",
|
||||
"F1:F1:F1:F1:F1:F1",
|
||||
128,
|
||||
True,
|
||||
100,
|
||||
970,
|
||||
0,
|
||||
"HIGH",
|
||||
10000,
|
||||
)
|
||||
print("### Initial status:", runner)
|
||||
final_status = self.dut.bench.waitForRunnerCompletion(runner["id"])
|
||||
|
||||
@@ -22,11 +22,13 @@ import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.google.android.mobly.snippet.Snippet;
|
||||
import com.google.android.mobly.snippet.rpc.Rpc;
|
||||
import com.google.android.mobly.snippet.rpc.RpcOptional;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.InvalidParameterException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.UUID;
|
||||
@@ -71,12 +73,15 @@ public class AutomationSnippet implements Snippet {
|
||||
private final Context mContext;
|
||||
private final ArrayList<Runner> mRunners = new ArrayList<>();
|
||||
|
||||
public AutomationSnippet() {
|
||||
public AutomationSnippet() throws IOException {
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
BluetoothManager bluetoothManager = mContext.getSystemService(BluetoothManager.class);
|
||||
mBluetoothAdapter = bluetoothManager.getAdapter();
|
||||
if (mBluetoothAdapter == null) {
|
||||
throw new RuntimeException("bluetooth not supported");
|
||||
throw new IOException("bluetooth not supported");
|
||||
}
|
||||
if (!mBluetoothAdapter.isEnabled()) {
|
||||
throw new IOException("bluetooth not enabled");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,32 +90,34 @@ public class AutomationSnippet implements Snippet {
|
||||
switch (mode) {
|
||||
case "rfcomm-client":
|
||||
runnable = new RfcommClient(model, mBluetoothAdapter,
|
||||
(PacketIO packetIO) -> createIoClient(model, scenario,
|
||||
packetIO));
|
||||
(PacketIO packetIO) -> createIoClient(model, scenario,
|
||||
packetIO));
|
||||
break;
|
||||
|
||||
case "rfcomm-server":
|
||||
runnable = new RfcommServer(model, mBluetoothAdapter,
|
||||
(PacketIO packetIO) -> createIoClient(model, scenario,
|
||||
packetIO));
|
||||
(PacketIO packetIO) -> createIoClient(model, scenario,
|
||||
packetIO));
|
||||
break;
|
||||
|
||||
case "l2cap-client":
|
||||
runnable = new L2capClient(model, mBluetoothAdapter, mContext,
|
||||
(PacketIO packetIO) -> createIoClient(model, scenario,
|
||||
packetIO));
|
||||
(PacketIO packetIO) -> createIoClient(model, scenario,
|
||||
packetIO));
|
||||
break;
|
||||
|
||||
case "l2cap-server":
|
||||
runnable = new L2capServer(model, mBluetoothAdapter,
|
||||
(PacketIO packetIO) -> createIoClient(model, scenario,
|
||||
packetIO));
|
||||
(PacketIO packetIO) -> createIoClient(model, scenario,
|
||||
packetIO));
|
||||
break;
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
||||
model.setMode(mode);
|
||||
model.setScenario(scenario);
|
||||
runnable.run();
|
||||
Runner runner = new Runner(runnable, mode, scenario, model);
|
||||
mRunners.add(runner);
|
||||
@@ -140,7 +147,21 @@ public class AutomationSnippet implements Snippet {
|
||||
JSONObject result = new JSONObject();
|
||||
result.put("status", model.getStatus());
|
||||
result.put("running", model.getRunning());
|
||||
result.put("peer_bluetooth_address", model.getPeerBluetoothAddress());
|
||||
result.put("mode", model.getMode());
|
||||
result.put("scenario", model.getScenario());
|
||||
result.put("sender_packet_size", model.getSenderPacketSize());
|
||||
result.put("sender_packet_count", model.getSenderPacketCount());
|
||||
result.put("sender_packet_interval", model.getSenderPacketInterval());
|
||||
result.put("packets_sent", model.getPacketsSent());
|
||||
result.put("packets_received", model.getPacketsReceived());
|
||||
result.put("l2cap_psm", model.getL2capPsm());
|
||||
result.put("use_2m_phy", model.getUse2mPhy());
|
||||
result.put("connection_priority", model.getConnectionPriority());
|
||||
result.put("mtu", model.getMtu());
|
||||
result.put("rx_phy", model.getRxPhy());
|
||||
result.put("tx_phy", model.getTxPhy());
|
||||
result.put("startup_delay", model.getStartupDelay());
|
||||
if (model.getStatus().equals("OK")) {
|
||||
JSONObject stats = new JSONObject();
|
||||
result.put("stats", stats);
|
||||
@@ -167,12 +188,12 @@ public class AutomationSnippet implements Snippet {
|
||||
|
||||
@Rpc(description = "Run a scenario in RFComm Client mode")
|
||||
public JSONObject runRfcommClient(String scenario, String peerBluetoothAddress, int packetCount,
|
||||
int packetSize, int packetInterval) throws JSONException {
|
||||
assert (mBluetoothAdapter != null);
|
||||
|
||||
int packetSize, int packetInterval,
|
||||
@RpcOptional Integer startupDelay) throws JSONException {
|
||||
// We only support "send" and "ping" for this mode for now
|
||||
if (!(scenario.equals("send") || scenario.equals("ping"))) {
|
||||
throw new InvalidParameterException("only 'send' and 'ping' are supported for this mode");
|
||||
throw new InvalidParameterException(
|
||||
"only 'send' and 'ping' are supported for this mode");
|
||||
}
|
||||
|
||||
AppViewModel model = new AppViewModel();
|
||||
@@ -180,6 +201,9 @@ public class AutomationSnippet implements Snippet {
|
||||
model.setSenderPacketCount(packetCount);
|
||||
model.setSenderPacketSize(packetSize);
|
||||
model.setSenderPacketInterval(packetInterval);
|
||||
if (startupDelay != null) {
|
||||
model.setStartupDelay(startupDelay);
|
||||
}
|
||||
|
||||
Runner runner = runScenario(model, "rfcomm-client", scenario);
|
||||
assert runner != null;
|
||||
@@ -187,15 +211,18 @@ public class AutomationSnippet implements Snippet {
|
||||
}
|
||||
|
||||
@Rpc(description = "Run a scenario in RFComm Server mode")
|
||||
public JSONObject runRfcommServer(String scenario) throws JSONException {
|
||||
assert (mBluetoothAdapter != null);
|
||||
|
||||
public JSONObject runRfcommServer(String scenario,
|
||||
@RpcOptional Integer startupDelay) throws JSONException {
|
||||
// We only support "receive" and "pong" for this mode for now
|
||||
if (!(scenario.equals("receive") || scenario.equals("pong"))) {
|
||||
throw new InvalidParameterException("only 'receive' and 'pong' are supported for this mode");
|
||||
throw new InvalidParameterException(
|
||||
"only 'receive' and 'pong' are supported for this mode");
|
||||
}
|
||||
|
||||
AppViewModel model = new AppViewModel();
|
||||
if (startupDelay != null) {
|
||||
model.setStartupDelay(startupDelay);
|
||||
}
|
||||
|
||||
Runner runner = runScenario(model, "rfcomm-server", scenario);
|
||||
assert runner != null;
|
||||
@@ -205,12 +232,12 @@ public class AutomationSnippet implements Snippet {
|
||||
@Rpc(description = "Run a scenario in L2CAP Client mode")
|
||||
public JSONObject runL2capClient(String scenario, String peerBluetoothAddress, int psm,
|
||||
boolean use_2m_phy, int packetCount, int packetSize,
|
||||
int packetInterval) throws JSONException {
|
||||
assert (mBluetoothAdapter != null);
|
||||
|
||||
int packetInterval, @RpcOptional String connectionPriority,
|
||||
@RpcOptional Integer startupDelay) throws JSONException {
|
||||
// We only support "send" and "ping" for this mode for now
|
||||
if (!(scenario.equals("send") || scenario.equals("ping"))) {
|
||||
throw new InvalidParameterException("only 'send' and 'ping' are supported for this mode");
|
||||
throw new InvalidParameterException(
|
||||
"only 'send' and 'ping' are supported for this mode");
|
||||
}
|
||||
|
||||
AppViewModel model = new AppViewModel();
|
||||
@@ -220,22 +247,30 @@ public class AutomationSnippet implements Snippet {
|
||||
model.setSenderPacketCount(packetCount);
|
||||
model.setSenderPacketSize(packetSize);
|
||||
model.setSenderPacketInterval(packetInterval);
|
||||
|
||||
if (connectionPriority != null) {
|
||||
model.setConnectionPriority(connectionPriority);
|
||||
}
|
||||
if (startupDelay != null) {
|
||||
model.setStartupDelay(startupDelay);
|
||||
}
|
||||
Runner runner = runScenario(model, "l2cap-client", scenario);
|
||||
assert runner != null;
|
||||
return runner.toJson();
|
||||
}
|
||||
|
||||
@Rpc(description = "Run a scenario in L2CAP Server mode")
|
||||
public JSONObject runL2capServer(String scenario) throws JSONException {
|
||||
assert (mBluetoothAdapter != null);
|
||||
|
||||
public JSONObject runL2capServer(String scenario,
|
||||
@RpcOptional Integer startupDelay) throws JSONException {
|
||||
// We only support "receive" and "pong" for this mode for now
|
||||
if (!(scenario.equals("receive") || scenario.equals("pong"))) {
|
||||
throw new InvalidParameterException("only 'receive' and 'pong' are supported for this mode");
|
||||
throw new InvalidParameterException(
|
||||
"only 'receive' and 'pong' are supported for this mode");
|
||||
}
|
||||
|
||||
AppViewModel model = new AppViewModel();
|
||||
if (startupDelay != null) {
|
||||
model.setStartupDelay(startupDelay);
|
||||
}
|
||||
|
||||
Runner runner = runScenario(model, "l2cap-server", scenario);
|
||||
assert runner != null;
|
||||
@@ -276,7 +311,7 @@ public class AutomationSnippet implements Snippet {
|
||||
JSONObject result = new JSONObject();
|
||||
JSONArray runners = new JSONArray();
|
||||
result.put("runners", runners);
|
||||
for (Runner runner: mRunners) {
|
||||
for (Runner runner : mRunners) {
|
||||
runners.put(runner.toJson());
|
||||
}
|
||||
|
||||
|
||||
@@ -90,6 +90,18 @@ class L2capClient(
|
||||
// Request an MTU update, even though we don't use GATT, because Android
|
||||
// won't request a larger link layer maximum data length otherwise.
|
||||
gatt.requestMtu(517)
|
||||
|
||||
// Request a specific connection priority
|
||||
val connectionPriority = when (viewModel.connectionPriority) {
|
||||
"BALANCED" -> BluetoothGatt.CONNECTION_PRIORITY_BALANCED
|
||||
"LOW_POWER" -> BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER
|
||||
"HIGH" -> BluetoothGatt.CONNECTION_PRIORITY_HIGH
|
||||
"DCK" -> BluetoothGatt.CONNECTION_PRIORITY_DCK
|
||||
else -> 0
|
||||
}
|
||||
if (!gatt.requestConnectionPriority(connectionPriority)) {
|
||||
Log.warning("requestConnectionPriority failed")
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -66,6 +66,7 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.github.google.bumble.btbench.ui.theme.BTBenchTheme
|
||||
import java.io.IOException
|
||||
import java.util.logging.Logger
|
||||
|
||||
private val Log = Logger.getLogger("bumble.main-activity")
|
||||
@@ -76,6 +77,7 @@ const val SENDER_PACKET_SIZE_PREF_KEY = "sender_packet_size"
|
||||
const val SENDER_PACKET_INTERVAL_PREF_KEY = "sender_packet_interval"
|
||||
const val SCENARIO_PREF_KEY = "scenario"
|
||||
const val MODE_PREF_KEY = "mode"
|
||||
const val CONNECTION_PRIORITY_PREF_KEY = "connection_priority"
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
private val appViewModel = AppViewModel()
|
||||
@@ -195,7 +197,7 @@ class MainActivity : ComponentActivity() {
|
||||
|
||||
private fun runScenario() {
|
||||
if (bluetoothAdapter == null) {
|
||||
return
|
||||
throw IOException("bluetooth not enabled")
|
||||
}
|
||||
|
||||
val runner = when (appViewModel.mode) {
|
||||
@@ -366,7 +368,35 @@ fun MainView(
|
||||
checked = appViewModel.use2mPhy,
|
||||
onCheckedChange = { appViewModel.use2mPhy = it }
|
||||
)
|
||||
|
||||
Column(Modifier.selectableGroup()) {
|
||||
listOf(
|
||||
"BALANCED",
|
||||
"LOW",
|
||||
"HIGH",
|
||||
"DCK"
|
||||
).forEach { text ->
|
||||
Row(
|
||||
Modifier
|
||||
.selectable(
|
||||
selected = (text == appViewModel.connectionPriority),
|
||||
onClick = { appViewModel.updateConnectionPriority(text) },
|
||||
role = Role.RadioButton
|
||||
)
|
||||
.padding(horizontal = 16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
RadioButton(
|
||||
selected = (text == appViewModel.connectionPriority),
|
||||
onClick = null
|
||||
)
|
||||
Text(
|
||||
text = text,
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
modifier = Modifier.padding(start = 16.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Row {
|
||||
Column(Modifier.selectableGroup()) {
|
||||
|
||||
@@ -25,6 +25,7 @@ import java.util.UUID
|
||||
|
||||
val DEFAULT_RFCOMM_UUID: UUID = UUID.fromString("E6D55659-C8B4-4B85-96BB-B1143AF6D3AE")
|
||||
const val DEFAULT_PEER_BLUETOOTH_ADDRESS = "AA:BB:CC:DD:EE:FF"
|
||||
const val DEFAULT_STARTUP_DELAY = 3000
|
||||
const val DEFAULT_SENDER_PACKET_COUNT = 100
|
||||
const val DEFAULT_SENDER_PACKET_SIZE = 1024
|
||||
const val DEFAULT_SENDER_PACKET_INTERVAL = 100
|
||||
@@ -47,8 +48,10 @@ class AppViewModel : ViewModel() {
|
||||
var mode by mutableStateOf(RFCOMM_SERVER_MODE)
|
||||
var scenario by mutableStateOf(RECEIVE_SCENARIO)
|
||||
var peerBluetoothAddress by mutableStateOf(DEFAULT_PEER_BLUETOOTH_ADDRESS)
|
||||
var startupDelay by mutableIntStateOf(DEFAULT_STARTUP_DELAY)
|
||||
var l2capPsm by mutableIntStateOf(DEFAULT_PSM)
|
||||
var use2mPhy by mutableStateOf(true)
|
||||
var connectionPriority by mutableStateOf("BALANCED")
|
||||
var mtu by mutableIntStateOf(0)
|
||||
var rxPhy by mutableIntStateOf(0)
|
||||
var txPhy by mutableIntStateOf(0)
|
||||
@@ -98,6 +101,11 @@ class AppViewModel : ViewModel() {
|
||||
if (savedScenario != null) {
|
||||
scenario = savedScenario
|
||||
}
|
||||
|
||||
val savedConnectionPriority = preferences.getString(CONNECTION_PRIORITY_PREF_KEY, null)
|
||||
if (savedConnectionPriority != null) {
|
||||
connectionPriority = savedConnectionPriority
|
||||
}
|
||||
}
|
||||
|
||||
fun updatePeerBluetoothAddress(peerBluetoothAddress: String) {
|
||||
@@ -220,6 +228,14 @@ class AppViewModel : ViewModel() {
|
||||
}
|
||||
}
|
||||
|
||||
fun updateConnectionPriority(connectionPriority: String) {
|
||||
this.connectionPriority = connectionPriority
|
||||
with(preferences!!.edit()) {
|
||||
putString(CONNECTION_PRIORITY_PREF_KEY, connectionPriority)
|
||||
apply()
|
||||
}
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
status = ""
|
||||
lastError = ""
|
||||
|
||||
@@ -19,8 +19,6 @@ import java.util.logging.Logger
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
import kotlin.time.TimeSource
|
||||
|
||||
private const val DEFAULT_STARTUP_DELAY = 3000
|
||||
|
||||
private val Log = Logger.getLogger("btbench.pinger")
|
||||
|
||||
class Pinger(private val viewModel: AppViewModel, private val packetIO: PacketIO) : IoClient,
|
||||
@@ -36,8 +34,8 @@ class Pinger(private val viewModel: AppViewModel, private val packetIO: PacketIO
|
||||
override fun run() {
|
||||
viewModel.clear()
|
||||
|
||||
Log.info("startup delay: $DEFAULT_STARTUP_DELAY")
|
||||
Thread.sleep(DEFAULT_STARTUP_DELAY.toLong());
|
||||
Log.info("startup delay: ${viewModel.startupDelay}")
|
||||
Thread.sleep(viewModel.startupDelay.toLong());
|
||||
Log.info("running")
|
||||
|
||||
Log.info("sending reset")
|
||||
|
||||
@@ -19,8 +19,6 @@ import java.util.logging.Logger
|
||||
import kotlin.time.DurationUnit
|
||||
import kotlin.time.TimeSource
|
||||
|
||||
private const val DEFAULT_STARTUP_DELAY = 3000
|
||||
|
||||
private val Log = Logger.getLogger("btbench.sender")
|
||||
|
||||
class Sender(private val viewModel: AppViewModel, private val packetIO: PacketIO) : IoClient,
|
||||
@@ -36,8 +34,8 @@ class Sender(private val viewModel: AppViewModel, private val packetIO: PacketIO
|
||||
override fun run() {
|
||||
viewModel.clear()
|
||||
|
||||
Log.info("startup delay: $DEFAULT_STARTUP_DELAY")
|
||||
Thread.sleep(DEFAULT_STARTUP_DELAY.toLong());
|
||||
Log.info("startup delay: ${viewModel.startupDelay}")
|
||||
Thread.sleep(viewModel.startupDelay.toLong());
|
||||
Log.info("running")
|
||||
|
||||
Log.info("sending reset")
|
||||
|
||||
Reference in New Issue
Block a user