Add multi-device tests for CDM.

Bug: 252817312
Test: atest CompanionDeviceManagerMultiDevicesTestCases
Change-Id: I8e5092d764c7e04de47029dfde15dfc4a04fafc4
diff --git a/tests/CompanionDeviceMultiDeviceTests/host/Android.bp b/tests/CompanionDeviceMultiDeviceTests/host/Android.bp
new file mode 100644
index 0000000..1167a3e
--- /dev/null
+++ b/tests/CompanionDeviceMultiDeviceTests/host/Android.bp
@@ -0,0 +1,51 @@
+// Copyright (C) 2022 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 {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+python_test_host {
+    name: "CompanionDeviceManagerMultiDeviceTestCases",
+    main: "cdm_transport_test.py",
+    srcs: ["*.py"],
+    libs: [
+        "mobly",
+    ],
+    test_suites: [
+        "general-tests",
+    ],
+    test_options: {
+        unit_test: false,
+        tags: ["mobly"],
+    },
+    data: [
+        ":cdm_snippet",
+        "requirements.txt",
+    ],
+    version: {
+        py2: {
+            enabled: false,
+        },
+        py3: {
+            enabled: true,
+            embedded_launcher: true,
+        },
+    },
+}
diff --git a/tests/CompanionDeviceMultiDeviceTests/host/AndroidTest.xml b/tests/CompanionDeviceMultiDeviceTests/host/AndroidTest.xml
new file mode 100644
index 0000000..9d1813f
--- /dev/null
+++ b/tests/CompanionDeviceMultiDeviceTests/host/AndroidTest.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 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.
+-->
+<configuration description="Config for CDM multi-device test cases">
+    <option name="test-tag" value="CompanionDeviceMultiDeviceTests" />
+    <option name="config-descriptor:metadata" key="component" value="framework" />
+    <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
+    <option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
+    <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+
+    <object class="com.android.tradefed.testtype.suite.module.DeviceFeatureModuleController"
+        type="module_controller">
+        <option name="required-feature" value="android.software.companion_device_setup" />
+    </object>
+
+    <device name="device1">
+        <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+            <option name="test-file-name" value="cdm_snippet.apk" />
+        </target_preparer>
+    </device>
+    <device name="device2">
+        <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+            <option name="test-file-name" value="cdm_snippet.apk" />
+        </target_preparer>
+    </device>
+
+    <test class="com.android.tradefed.testtype.mobly.MoblyBinaryHostTest">
+      <!-- The mobly-par-file-name should match the module name -->
+      <option name="mobly-par-file-name" value="CompanionDeviceManagerMultiDeviceTestCases" />
+      <!-- Timeout limit in milliseconds for all test cases of the python binary -->
+      <option name="mobly-test-timeout" value="60000" />
+    </test>
+</configuration>
diff --git a/tests/CompanionDeviceMultiDeviceTests/host/cdm_base_test.py b/tests/CompanionDeviceMultiDeviceTests/host/cdm_base_test.py
new file mode 100644
index 0000000..bb10658
--- /dev/null
+++ b/tests/CompanionDeviceMultiDeviceTests/host/cdm_base_test.py
@@ -0,0 +1,63 @@
+# Lint as: python3
+"""
+Base class for setting up devices for CDM functionalities.
+"""
+
+from mobly import base_test
+from mobly import utils
+from mobly.controllers import android_device
+
+CDM_SNIPPET_PACKAGE = 'android.companion.multidevices'
+
+
+class BaseTestClass(base_test.BaseTestClass):
+
+    def setup_class(self):
+        # Declare that two Android devices are needed.
+        self.sender, self.receiver = self.register_controller(
+            android_device, min_number=2)
+        self.sender_id = None
+        self.receiver_id = None
+
+        def _setup_device(device):
+            device.load_snippet('cdm', CDM_SNIPPET_PACKAGE)
+            device.adb.shell('input keyevent KEYCODE_WAKEUP')
+            device.adb.shell('input keyevent KEYCODE_MENU')
+            device.adb.shell('input keyevent KEYCODE_HOME')
+
+            # Clean up existing associations
+            device.cdm.disassociateAll()
+
+        # Sets up devices in parallel to save time.
+        utils.concurrent_exec(
+            _setup_device,
+            ((self.sender,), (self.receiver,)),
+            max_workers=2,
+            raise_on_exception=True)
+
+    def associate_devices(self) -> tuple[int, int]:
+        """Associate devices with each other and return association IDs for both"""
+        # If association already exists, don't need another
+        if self.sender_id and self.receiver_id:
+            return (self.sender_id, self.receiver_id)
+
+        receiver_name = self.receiver.cdm.becomeDiscoverable()
+        self.receiver_id = self.sender.cdm.associate(receiver_name)
+
+        sender_name = self.sender.cdm.becomeDiscoverable()
+        self.sender_id = self.receiver.cdm.associate(sender_name)
+
+        return (self.sender_id, self.receiver_id)
+
+    def attach_transports(self):
+        """Attach transports to both devices"""
+        self.associate_devices()
+
+        self.receiver.cdm.attachServerSocket(self.sender_id)
+        self.sender.cdm.attachClientSocket(self.receiver_id)
+
+    def teardown_class(self):
+        """Clean up the opened sockets"""
+        self.sender.cdm.closeAllSockets()
+        self.receiver.cdm.closeAllSockets()
+
diff --git a/tests/CompanionDeviceMultiDeviceTests/host/cdm_transport_test.py b/tests/CompanionDeviceMultiDeviceTests/host/cdm_transport_test.py
new file mode 100644
index 0000000..9cb2d10
--- /dev/null
+++ b/tests/CompanionDeviceMultiDeviceTests/host/cdm_transport_test.py
@@ -0,0 +1,36 @@
+# Lint as: python3
+"""
+Test E2E CDM functions on mobly.
+"""
+
+import cdm_base_test
+import sys
+
+from mobly import asserts
+from mobly import test_runner
+
+CDM_SNIPPET_PACKAGE = 'android.companion.multidevices'
+
+
+class TransportTestClass(cdm_base_test.BaseTestClass):
+
+    def test_permissions_sync(self):
+        """This tests permissions sync from one device to another."""
+
+        # associate and attach transports
+        self.attach_transports()
+
+        # start permissions sync
+        self.sender.cdm.startPermissionsSync(self.receiver_id)
+
+
+if __name__ == '__main__':
+    try:
+        # Take test args and remove standalone '--' from the list
+        index = sys.argv.index('--')
+        sys.argv = sys.argv[:1] + sys.argv[index + 1:]
+    except ValueError:
+        # Ignore if '--' is not in args
+        pass
+
+    test_runner.main()
\ No newline at end of file
diff --git a/tests/CompanionDeviceMultiDeviceTests/host/requirements.txt b/tests/CompanionDeviceMultiDeviceTests/host/requirements.txt
new file mode 100644
index 0000000..86a11aa
--- /dev/null
+++ b/tests/CompanionDeviceMultiDeviceTests/host/requirements.txt
@@ -0,0 +1 @@
+mobly==1.12.1