Loading framework/tests/metrics/device/android/bluetooth/BluetoothMetricsHelperTest.kt +34 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package android.bluetooth import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter import android.net.MacAddress Loading @@ -30,10 +32,12 @@ import io.grpc.okhttp.OkHttpChannelBuilder import java.util.concurrent.TimeUnit import kotlinx.coroutines.async import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest Loading @@ -46,6 +50,7 @@ import pandora.HostGrpc import pandora.HostProto.ConnectRequest import pandora.HostProto.DisconnectRequest @Suppress("DEPRECATION") @kotlinx.coroutines.ExperimentalCoroutinesApi @RunWith(AndroidJUnit4::class) class BluetoothMetricsHelperTest { Loading @@ -68,7 +73,23 @@ class BluetoothMetricsHelperTest { private val testDispatcher = UnconfinedTestDispatcher() private val testScope = TestScope(testDispatcher) private val context = InstrumentationRegistry.getInstrumentation().getContext() private val bluetoothAdapter = context.getSystemService(BluetoothManager::class.java)!!.adapter private val bluetoothAdapter: BluetoothAdapter = context.getSystemService(BluetoothManager::class.java)!!.adapter private val adapterState = MutableStateFlow(bluetoothAdapter.state) init { context.registerReceiver( object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { adapterState.tryEmit( intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR) ) } }, IntentFilter(BluetoothAdapter.ACTION_BLE_STATE_CHANGED) ) } @Before fun setUp() { Loading @@ -92,6 +113,10 @@ class BluetoothMetricsHelperTest { mHostBlockingStub = HostGrpc.newBlockingStub(mChannel) mHostStub = HostGrpc.newStub(mChannel) mHostBlockingStub.withWaitForReady()?.readLocalAddress(Empty.getDefaultInstance()) // Make sure the Adapter is on. bluetoothAdapter.enable() runBlocking { adapterState.first { it == BluetoothAdapter.STATE_ON } } } @After Loading Loading @@ -132,4 +157,12 @@ class BluetoothMetricsHelperTest { DisconnectRequest.newBuilder().setConnection(connectResponse.connection).build() mHostBlockingStub.disconnect(disconnectRequest) } @Test fun testBluetoothDisableEnable() = runTest { bluetoothAdapter.disable() adapterState.first { it == BluetoothAdapter.STATE_OFF } bluetoothAdapter.enable() adapterState.first { it == BluetoothAdapter.STATE_ON } } } framework/tests/metrics/host/Android.bp +4 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,10 @@ java_test_host { ":BluetoothMetricsTestApp", ], data_native_bins: [ "bumble_pandora_server", ], required: ["bumble_pandora_server"], test_suites: [ Loading framework/tests/metrics/host/AndroidTest.xml +3 −1 Original line number Diff line number Diff line Loading @@ -20,8 +20,10 @@ <target_preparer class="com.android.tradefed.targetprep.RunHostCommandTargetPreparer"> <option name="python-virtualenv" value="true"/> <option name="host-setup-command" value="adb -s $SERIAL reverse tcp:7999 tcp:7999" /> <option name="host-setup-command" value="adb -s $SERIAL forward tcp:6211 vsock:2:7300" /> <option name="host-teardown-command" value="adb -s $SERIAL forward --remove tcp:6211" /> <option name="host-background-command" value="$EXTRA_FILE(host_testcases)/bumble_pandora_server/x86_64/bumble_pandora_server"/> value="$EXTRA_FILE(host_testcases)/BluetoothMetricsTests/bumble_pandora_server --rootcanal-port 6211"/> <option name="host-teardown-command" value="adb -s $SERIAL reverse --remove tcp:7999" /> </target_preparer> <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" > Loading framework/tests/metrics/host/android/bluetooth/MetricsTest.kt +32 −17 Original line number Diff line number Diff line Loading @@ -20,10 +20,12 @@ import android.cts.statsdatom.lib.ConfigUtils import android.cts.statsdatom.lib.DeviceUtils import android.cts.statsdatom.lib.ReportUtils import com.android.os.AtomsProto import com.android.os.AtomsProto.BluetoothEnabledStateChanged import com.android.os.StatsLog import com.android.tradefed.testtype.DeviceJUnit4ClassRunner import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test import com.google.common.truth.Truth.assertThat import java.time.Duration import org.junit.Before import org.junit.Test import org.junit.runner.RunWith Loading @@ -44,25 +46,38 @@ class MetricsTest : BaseHostJUnit4Test() { } @Test fun aclMetricTest() { val data = uploadAtomConfigAndTriggerTest("incomingClassicConnectionTest") assertThat(data.size).isAtLeast(2) val atom1 = data.get(0).getAtom().getBluetoothAclConnectionStateChanged() assertThat(atom1.getState()).isEqualTo(ConnectionStateEnum.CONNECTION_STATE_CONNECTED) assertThat(atom1.getTransport()).isEqualTo(TransportTypeEnum.TRANSPORT_TYPE_BREDR) val atom2 = data.get(1).getAtom().getBluetoothAclConnectionStateChanged() assertThat(atom2.getState()).isEqualTo(ConnectionStateEnum.CONNECTION_STATE_DISCONNECTED) assertThat(atom2.getTransport()).isEqualTo(TransportTypeEnum.TRANSPORT_TYPE_BREDR) assertThat(atom2.getMetricId()).isEqualTo(atom1.getMetricId()) fun testBluetoothDisableEnable_shouldProduceEnabledStateChanged() { val data = uploadAtomConfigAndTriggerTest( "testBluetoothDisableEnable", intArrayOf(AtomsProto.Atom.BLUETOOTH_ENABLED_STATE_CHANGED_FIELD_NUMBER) ) // First atom might be the setup one. val offset = data[0].atom.bluetoothEnabledStateChanged.let { if (it.state == BluetoothEnabledStateChanged.State.ENABLED) { 1 } else { 0 } } data[offset].atom.bluetoothEnabledStateChanged.apply { assertThat(state).isEqualTo(BluetoothEnabledStateChanged.State.DISABLED) assertThat(previousState).isEqualTo(BluetoothEnabledStateChanged.State.ENABLED) assertThat(timeSinceLastChangedMillis).isGreaterThan(Duration.ofMillis(1).toMillis()) } data[offset + 1].atom.bluetoothEnabledStateChanged.apply { assertThat(state).isEqualTo(BluetoothEnabledStateChanged.State.ENABLED) assertThat(previousState).isEqualTo(BluetoothEnabledStateChanged.State.DISABLED) assertThat(timeSinceLastChangedMillis).isGreaterThan(Duration.ofMillis(1).toMillis()) } } private fun uploadAtomConfigAndTriggerTest(testName: String): List<StatsLog.EventMetricData> { val device = getDevice() ConfigUtils.uploadConfigForPushedAtoms( device, TEST_APP_PKG_NAME, intArrayOf(AtomsProto.Atom.BLUETOOTH_ACL_CONNECTION_STATE_CHANGED_FIELD_NUMBER) ) private fun uploadAtomConfigAndTriggerTest( testName: String, atoms: IntArray ): List<StatsLog.EventMetricData> { ConfigUtils.uploadConfigForPushedAtoms(device, TEST_APP_PKG_NAME, atoms) DeviceUtils.runDeviceTests(device, TEST_APP_PKG_NAME, TEST_APP_CLASS_NAME, testName) Loading service/src/com/android/server/bluetooth/BluetoothManagerService.java +26 −1 Original line number Diff line number Diff line Loading @@ -260,6 +260,14 @@ class BluetoothManagerService { + mPackageName; } long getTimestamp() { return mTimestamp; } boolean getEnable() { return mEnable; } void dump(ProtoOutputStream proto) { proto.write(BluetoothManagerServiceDumpProto.ActiveLog.TIMESTAMP_MS, mTimestamp); proto.write(BluetoothManagerServiceDumpProto.ActiveLog.ENABLE, mEnable); Loading Loading @@ -2175,6 +2183,7 @@ class BluetoothManagerService { } private void addActiveLog(int reason, String packageName, boolean enable) { ActiveLog lastActiveLog = mActiveLogs.peekLast(); synchronized (mActiveLogs) { if (mActiveLogs.size() > ACTIVE_LOG_MAX_SIZE) { mActiveLogs.remove(); Loading @@ -2186,13 +2195,29 @@ class BluetoothManagerService { ? BluetoothStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__ENABLED : BluetoothStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__DISABLED; int lastState; long timeSinceLastChanged; if (lastActiveLog == null) { lastState = BluetoothStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__UNKNOWN; timeSinceLastChanged = 0; } else { lastState = lastActiveLog.getEnable() ? BluetoothStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__ENABLED : BluetoothStatsLog .BLUETOOTH_ENABLED_STATE_CHANGED__STATE__DISABLED; timeSinceLastChanged = System.currentTimeMillis() - lastActiveLog.getTimestamp(); } BluetoothStatsLog.write_non_chained( BluetoothStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED, Binder.getCallingUid(), null, state, reason, packageName); packageName, lastState, timeSinceLastChanged); } } Loading Loading
framework/tests/metrics/device/android/bluetooth/BluetoothMetricsHelperTest.kt +34 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package android.bluetooth import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter import android.net.MacAddress Loading @@ -30,10 +32,12 @@ import io.grpc.okhttp.OkHttpChannelBuilder import java.util.concurrent.TimeUnit import kotlinx.coroutines.async import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest Loading @@ -46,6 +50,7 @@ import pandora.HostGrpc import pandora.HostProto.ConnectRequest import pandora.HostProto.DisconnectRequest @Suppress("DEPRECATION") @kotlinx.coroutines.ExperimentalCoroutinesApi @RunWith(AndroidJUnit4::class) class BluetoothMetricsHelperTest { Loading @@ -68,7 +73,23 @@ class BluetoothMetricsHelperTest { private val testDispatcher = UnconfinedTestDispatcher() private val testScope = TestScope(testDispatcher) private val context = InstrumentationRegistry.getInstrumentation().getContext() private val bluetoothAdapter = context.getSystemService(BluetoothManager::class.java)!!.adapter private val bluetoothAdapter: BluetoothAdapter = context.getSystemService(BluetoothManager::class.java)!!.adapter private val adapterState = MutableStateFlow(bluetoothAdapter.state) init { context.registerReceiver( object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { adapterState.tryEmit( intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR) ) } }, IntentFilter(BluetoothAdapter.ACTION_BLE_STATE_CHANGED) ) } @Before fun setUp() { Loading @@ -92,6 +113,10 @@ class BluetoothMetricsHelperTest { mHostBlockingStub = HostGrpc.newBlockingStub(mChannel) mHostStub = HostGrpc.newStub(mChannel) mHostBlockingStub.withWaitForReady()?.readLocalAddress(Empty.getDefaultInstance()) // Make sure the Adapter is on. bluetoothAdapter.enable() runBlocking { adapterState.first { it == BluetoothAdapter.STATE_ON } } } @After Loading Loading @@ -132,4 +157,12 @@ class BluetoothMetricsHelperTest { DisconnectRequest.newBuilder().setConnection(connectResponse.connection).build() mHostBlockingStub.disconnect(disconnectRequest) } @Test fun testBluetoothDisableEnable() = runTest { bluetoothAdapter.disable() adapterState.first { it == BluetoothAdapter.STATE_OFF } bluetoothAdapter.enable() adapterState.first { it == BluetoothAdapter.STATE_ON } } }
framework/tests/metrics/host/Android.bp +4 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,10 @@ java_test_host { ":BluetoothMetricsTestApp", ], data_native_bins: [ "bumble_pandora_server", ], required: ["bumble_pandora_server"], test_suites: [ Loading
framework/tests/metrics/host/AndroidTest.xml +3 −1 Original line number Diff line number Diff line Loading @@ -20,8 +20,10 @@ <target_preparer class="com.android.tradefed.targetprep.RunHostCommandTargetPreparer"> <option name="python-virtualenv" value="true"/> <option name="host-setup-command" value="adb -s $SERIAL reverse tcp:7999 tcp:7999" /> <option name="host-setup-command" value="adb -s $SERIAL forward tcp:6211 vsock:2:7300" /> <option name="host-teardown-command" value="adb -s $SERIAL forward --remove tcp:6211" /> <option name="host-background-command" value="$EXTRA_FILE(host_testcases)/bumble_pandora_server/x86_64/bumble_pandora_server"/> value="$EXTRA_FILE(host_testcases)/BluetoothMetricsTests/bumble_pandora_server --rootcanal-port 6211"/> <option name="host-teardown-command" value="adb -s $SERIAL reverse --remove tcp:7999" /> </target_preparer> <test class="com.android.compatibility.common.tradefed.testtype.JarHostTest" > Loading
framework/tests/metrics/host/android/bluetooth/MetricsTest.kt +32 −17 Original line number Diff line number Diff line Loading @@ -20,10 +20,12 @@ import android.cts.statsdatom.lib.ConfigUtils import android.cts.statsdatom.lib.DeviceUtils import android.cts.statsdatom.lib.ReportUtils import com.android.os.AtomsProto import com.android.os.AtomsProto.BluetoothEnabledStateChanged import com.android.os.StatsLog import com.android.tradefed.testtype.DeviceJUnit4ClassRunner import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test import com.google.common.truth.Truth.assertThat import java.time.Duration import org.junit.Before import org.junit.Test import org.junit.runner.RunWith Loading @@ -44,25 +46,38 @@ class MetricsTest : BaseHostJUnit4Test() { } @Test fun aclMetricTest() { val data = uploadAtomConfigAndTriggerTest("incomingClassicConnectionTest") assertThat(data.size).isAtLeast(2) val atom1 = data.get(0).getAtom().getBluetoothAclConnectionStateChanged() assertThat(atom1.getState()).isEqualTo(ConnectionStateEnum.CONNECTION_STATE_CONNECTED) assertThat(atom1.getTransport()).isEqualTo(TransportTypeEnum.TRANSPORT_TYPE_BREDR) val atom2 = data.get(1).getAtom().getBluetoothAclConnectionStateChanged() assertThat(atom2.getState()).isEqualTo(ConnectionStateEnum.CONNECTION_STATE_DISCONNECTED) assertThat(atom2.getTransport()).isEqualTo(TransportTypeEnum.TRANSPORT_TYPE_BREDR) assertThat(atom2.getMetricId()).isEqualTo(atom1.getMetricId()) fun testBluetoothDisableEnable_shouldProduceEnabledStateChanged() { val data = uploadAtomConfigAndTriggerTest( "testBluetoothDisableEnable", intArrayOf(AtomsProto.Atom.BLUETOOTH_ENABLED_STATE_CHANGED_FIELD_NUMBER) ) // First atom might be the setup one. val offset = data[0].atom.bluetoothEnabledStateChanged.let { if (it.state == BluetoothEnabledStateChanged.State.ENABLED) { 1 } else { 0 } } data[offset].atom.bluetoothEnabledStateChanged.apply { assertThat(state).isEqualTo(BluetoothEnabledStateChanged.State.DISABLED) assertThat(previousState).isEqualTo(BluetoothEnabledStateChanged.State.ENABLED) assertThat(timeSinceLastChangedMillis).isGreaterThan(Duration.ofMillis(1).toMillis()) } data[offset + 1].atom.bluetoothEnabledStateChanged.apply { assertThat(state).isEqualTo(BluetoothEnabledStateChanged.State.ENABLED) assertThat(previousState).isEqualTo(BluetoothEnabledStateChanged.State.DISABLED) assertThat(timeSinceLastChangedMillis).isGreaterThan(Duration.ofMillis(1).toMillis()) } } private fun uploadAtomConfigAndTriggerTest(testName: String): List<StatsLog.EventMetricData> { val device = getDevice() ConfigUtils.uploadConfigForPushedAtoms( device, TEST_APP_PKG_NAME, intArrayOf(AtomsProto.Atom.BLUETOOTH_ACL_CONNECTION_STATE_CHANGED_FIELD_NUMBER) ) private fun uploadAtomConfigAndTriggerTest( testName: String, atoms: IntArray ): List<StatsLog.EventMetricData> { ConfigUtils.uploadConfigForPushedAtoms(device, TEST_APP_PKG_NAME, atoms) DeviceUtils.runDeviceTests(device, TEST_APP_PKG_NAME, TEST_APP_CLASS_NAME, testName) Loading
service/src/com/android/server/bluetooth/BluetoothManagerService.java +26 −1 Original line number Diff line number Diff line Loading @@ -260,6 +260,14 @@ class BluetoothManagerService { + mPackageName; } long getTimestamp() { return mTimestamp; } boolean getEnable() { return mEnable; } void dump(ProtoOutputStream proto) { proto.write(BluetoothManagerServiceDumpProto.ActiveLog.TIMESTAMP_MS, mTimestamp); proto.write(BluetoothManagerServiceDumpProto.ActiveLog.ENABLE, mEnable); Loading Loading @@ -2175,6 +2183,7 @@ class BluetoothManagerService { } private void addActiveLog(int reason, String packageName, boolean enable) { ActiveLog lastActiveLog = mActiveLogs.peekLast(); synchronized (mActiveLogs) { if (mActiveLogs.size() > ACTIVE_LOG_MAX_SIZE) { mActiveLogs.remove(); Loading @@ -2186,13 +2195,29 @@ class BluetoothManagerService { ? BluetoothStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__ENABLED : BluetoothStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__DISABLED; int lastState; long timeSinceLastChanged; if (lastActiveLog == null) { lastState = BluetoothStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__UNKNOWN; timeSinceLastChanged = 0; } else { lastState = lastActiveLog.getEnable() ? BluetoothStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__ENABLED : BluetoothStatsLog .BLUETOOTH_ENABLED_STATE_CHANGED__STATE__DISABLED; timeSinceLastChanged = System.currentTimeMillis() - lastActiveLog.getTimestamp(); } BluetoothStatsLog.write_non_chained( BluetoothStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED, Binder.getCallingUid(), null, state, reason, packageName); packageName, lastState, timeSinceLastChanged); } } Loading