1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.snippet.connectivity
18 
19 import android.net.nsd.NsdManager
20 import android.net.nsd.NsdServiceInfo
21 import androidx.test.platform.app.InstrumentationRegistry
22 import com.android.testutils.NsdDiscoveryRecord
23 import com.android.testutils.NsdDiscoveryRecord.DiscoveryEvent.DiscoveryStopped
24 import com.android.testutils.NsdRegistrationRecord
25 import com.android.testutils.NsdRegistrationRecord.RegistrationEvent.ServiceRegistered
26 import com.android.testutils.NsdRegistrationRecord.RegistrationEvent.ServiceUnregistered
27 import com.android.testutils.NsdResolveRecord
28 import com.android.testutils.NsdResolveRecord.ResolveEvent.ServiceResolved
29 import com.google.android.mobly.snippet.Snippet
30 import com.google.android.mobly.snippet.rpc.Rpc
31 import kotlin.test.assertEquals
32 import org.junit.Assert.assertArrayEquals
33 
34 private const val SERVICE_NAME = "MultiDevicesTest"
35 private const val SERVICE_TYPE = "_multi_devices._tcp"
36 private const val SERVICE_ATTRIBUTES_KEY = "key"
37 private const val SERVICE_ATTRIBUTES_VALUE = "value"
38 private const val SERVICE_PORT = 12345
39 private const val REGISTRATION_TIMEOUT_MS = 10_000L
40 
41 class MdnsMultiDevicesSnippet : Snippet {
42     private val context = InstrumentationRegistry.getInstrumentation().getTargetContext()
43     private val nsdManager = context.getSystemService(NsdManager::class.java)!!
44     private val registrationRecord = NsdRegistrationRecord()
45     private val discoveryRecord = NsdDiscoveryRecord()
46     private val resolveRecord = NsdResolveRecord()
47 
48     @Rpc(description = "Register a mDns service")
registerMDnsServicenull49     fun registerMDnsService() {
50         val info = NsdServiceInfo()
51         info.setServiceName(SERVICE_NAME)
52         info.setServiceType(SERVICE_TYPE)
53         info.setPort(SERVICE_PORT)
54         info.setAttribute(SERVICE_ATTRIBUTES_KEY, SERVICE_ATTRIBUTES_VALUE)
55         nsdManager.registerService(info, NsdManager.PROTOCOL_DNS_SD, registrationRecord)
56         registrationRecord.expectCallback<ServiceRegistered>(REGISTRATION_TIMEOUT_MS)
57     }
58 
59     @Rpc(description = "Unregister a mDns service")
unregisterMDnsServicenull60     fun unregisterMDnsService() {
61         nsdManager.unregisterService(registrationRecord)
62         registrationRecord.expectCallback<ServiceUnregistered>()
63     }
64 
65     @Rpc(description = "Ensure the discovery and resolution of the mDNS service")
66     // Suppress the warning, as the NsdManager#resolveService() method is deprecated.
67     @Suppress("DEPRECATION")
ensureMDnsServiceDiscoveryAndResolutionnull68     fun ensureMDnsServiceDiscoveryAndResolution() {
69         // Discover a mDns service that matches the test service
70         nsdManager.discoverServices(SERVICE_TYPE, NsdManager.PROTOCOL_DNS_SD, discoveryRecord)
71         val info = discoveryRecord.waitForServiceDiscovered(SERVICE_NAME, SERVICE_TYPE)
72         // Resolve the retrieved mDns service.
73         nsdManager.resolveService(info, resolveRecord)
74         val serviceResolved = resolveRecord.expectCallbackEventually<ServiceResolved>()
75         serviceResolved.serviceInfo.let {
76             assertEquals(SERVICE_NAME, it.serviceName)
77             assertEquals(".$SERVICE_TYPE", it.serviceType)
78             assertEquals(SERVICE_PORT, it.port)
79             assertEquals(1, it.attributes.size)
80             assertArrayEquals(
81                     SERVICE_ATTRIBUTES_VALUE.encodeToByteArray(),
82                     it.attributes[SERVICE_ATTRIBUTES_KEY]
83             )
84         }
85     }
86 
87     @Rpc(description = "Stop discovery")
stopMDnsServiceDiscoverynull88     fun stopMDnsServiceDiscovery() {
89         nsdManager.stopServiceDiscovery(discoveryRecord)
90         discoveryRecord.expectCallbackEventually<DiscoveryStopped>()
91     }
92 }
93