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

Commit 10dd3913 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "[Metrics test] Init & Classic ACL" into main

parents 9ee9098a 3ec57f2b
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
# Bug component: 1099313
# Project owners
cncn@google.com
ahujapalash@google.com
+46 −0
Original line number Diff line number Diff line
package {
    // See: http://go/android-license-faq
    // A large-scale-change added 'default_applicable_licenses' to import
    // all of the 'license_kinds' from "system_bt_license"
    // to get the below license kinds:
    //   SPDX-license-identifier-Apache-2.0
    default_applicable_licenses: ["system_bt_license"],
}

android_test_helper_app {
    name: "BluetoothMetricsTestApp",

    min_sdk_version: "current",
    target_sdk_version: "current",
    libs: [
        "libprotobuf-java-micro",

        "framework",
        "framework-bluetooth.impl",
        "framework-res",
    ],

    static_libs: [
        "PandoraServerLib",
        "androidx.core_core",
        "androidx.test.ext.junit",
        "androidx.test.ext.truth",
        "androidx.test.rules",
        "grpc-java-lite",
        "grpc-java-okhttp-client-lite",
        "kotlinx_coroutines_test",
        "opencensus-java-contrib-grpc-metrics",
        "pandora_experimental-grpc-java",
        "pandora_experimental-proto-java",
    ],

    // Include all test java files.
    srcs: [
        "**/*.kt",
    ],

    platform_apis: true,
    test_suites: [
        "general-tests",
    ],
}
+13 −0
Original line number Diff line number Diff line
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="android.bluetooth" >

    <uses-permission android:name="android.permission.INTERNET" />

    <application>
        <uses-library android:name="android.test.runner" />
    </application>

    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
                     android:targetPackage="android.bluetooth"
                     android:label="Bluetooth Metrics Test"/>
</manifest>
+135 −0
Original line number 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 android.bluetooth

import android.content.Intent
import android.content.IntentFilter
import android.net.MacAddress
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.android.pandora.intentFlow
import com.google.common.truth.Truth.assertThat
import com.google.protobuf.ByteString
import com.google.protobuf.Empty
import io.grpc.ManagedChannel
import io.grpc.okhttp.OkHttpChannelBuilder
import java.util.concurrent.TimeUnit
import kotlinx.coroutines.async
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
import org.junit.After
import org.junit.Before
import org.junit.BeforeClass
import org.junit.Test
import org.junit.runner.RunWith
import pandora.HostGrpc
import pandora.HostProto.ConnectRequest
import pandora.HostProto.DisconnectRequest

@kotlinx.coroutines.ExperimentalCoroutinesApi
@RunWith(AndroidJUnit4::class)
class BluetoothMetricsHelperTest {

    companion object {
        private const val TAG = "BluetoothMetricsHelperTest"

        private lateinit var mChannel: ManagedChannel
        private lateinit var mHostBlockingStub: HostGrpc.HostBlockingStub
        private lateinit var mHostStub: HostGrpc.HostStub

        @BeforeClass
        fun setUpClass() {
            InstrumentationRegistry.getInstrumentation()
                .getUiAutomation()
                .adoptShellPermissionIdentity()
        }
    }

    private val testDispatcher = UnconfinedTestDispatcher()
    private val testScope = TestScope(testDispatcher)
    private val context = InstrumentationRegistry.getInstrumentation().getContext()
    private val bluetoothAdapter = context.getSystemService(BluetoothManager::class.java)!!.adapter

    @Before
    fun setUp() {
        val uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation()
        // Adopt all the permissions of the shell
        uiAutomation.adoptShellPermissionIdentity()

        // FactorReset is killing the server and restart
        // all channel created before the server restarted
        // cannot be reused
        val channel = OkHttpChannelBuilder.forAddress("localhost", 7999).usePlaintext().build()

        HostGrpc.newBlockingStub(channel).factoryReset(Empty.getDefaultInstance())

        // terminate the channel
        channel.shutdown().awaitTermination(1, TimeUnit.SECONDS)

        // Create a new channel for all successive grpc calls
        mChannel = OkHttpChannelBuilder.forAddress("localhost", 7999).usePlaintext().build()

        mHostBlockingStub = HostGrpc.newBlockingStub(mChannel)
        mHostStub = HostGrpc.newStub(mChannel)
        mHostBlockingStub.withWaitForReady()?.readLocalAddress(Empty.getDefaultInstance())
    }

    @After
    fun tearDown() {
        // terminate the channel
        mChannel.shutdown()?.awaitTermination(1, TimeUnit.SECONDS)
    }

    @Test
    fun incomingClassicConnectionTest() = runTest {
        val intentFilter = IntentFilter()
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED)
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED)
        val flow: Flow<Intent> =
            intentFlow(context, intentFilter, testScope).shareIn(testScope, SharingStarted.Eagerly)

        val incomingConnection = async {
            flow
                .filter { it.action == BluetoothDevice.ACTION_ACL_CONNECTED }
                .filter {
                    it.getIntExtra(BluetoothDevice.EXTRA_TRANSPORT, BluetoothDevice.ERROR) ==
                        BluetoothDevice.TRANSPORT_BREDR
                }
                .first()
        }

        val localMacAddress = MacAddress.fromString(bluetoothAdapter.getAddress())
        val connectRequest =
            ConnectRequest.newBuilder()
                .setAddress(ByteString.copyFrom(localMacAddress.toByteArray()))
                .build()
        val connectResponse = mHostBlockingStub.connect(connectRequest)
        assertThat(connectResponse).isNotNull()
        assertThat(connectResponse.hasConnection()).isTrue()
        incomingConnection.await()

        val disconnectRequest =
            DisconnectRequest.newBuilder().setConnection(connectResponse.connection).build()
        mHostBlockingStub.disconnect(disconnectRequest)
    }
}
+28 −0
Original line number Diff line number Diff line
// This empty test host is needed for building required host binary
// "bumble_pandora_server" and include it in test zip
java_test_host {
    name: "BluetoothMetricsTests",

    srcs: [
        "**/*.kt",
    ],

    static_libs: [
        "cts-statsd-atom-host-test-utils",
        "platformprotos",
    ],

    libs: [
        "tradefed",
    ],

    data: [
        ":BluetoothMetricsTestApp",
    ],

    required: ["bumble_pandora_server"],

    test_suites: [
        "general-tests",
    ],
}
Loading