bluetooth: Add test coverage for EIR name >48 bytes

This adds a new test, sa_eir_max_name_size_test, that applies a bluez
alias longer than the default EIR size, and validates that the data is
not truncated when registered with the controller. The new test was
confirmed to pass when the EIR max size is defined, and fails when the
EIR max size is not defined (defaults to 48 bytes) on kukui.

BUG=None
TEST=SAHealth batch, new test with and without config definition

Change-Id: I0cba70b5e56d0a112f724c50bd0c5dbe23235a44
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/autotest/+/2575055
Commit-Queue: Daniel Winkler <danielwinkler@google.com>
Tested-by: Daniel Winkler <danielwinkler@google.com>
Reviewed-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org>
diff --git a/client/cros/multimedia/bluetooth_facade_native.py b/client/cros/multimedia/bluetooth_facade_native.py
index 4cce4a9..6ba2039 100644
--- a/client/cros/multimedia/bluetooth_facade_native.py
+++ b/client/cros/multimedia/bluetooth_facade_native.py
@@ -1245,6 +1245,20 @@
         return True
 
     @xmlrpc_server.dbus_safe(False)
+    def set_adapter_alias(self, alias):
+        """Set the adapter alias.
+
+        @param alias: adapter alias to set with type String
+
+        @return True on success, False otherwise.
+        """
+        self._adapter.Set(self.BLUEZ_ADAPTER_IFACE,
+                          'Alias',
+                          dbus.String(alias),
+                          dbus_interface=dbus.PROPERTIES_IFACE)
+        return True
+
+    @xmlrpc_server.dbus_safe(False)
     def _get_adapter_properties(self):
         """Read the adapter properties from the Bluetooth Daemon.
 
diff --git a/server/cros/bluetooth/bluetooth_adapter_tests.py b/server/cros/bluetooth/bluetooth_adapter_tests.py
index 9edc326..6316f4a 100644
--- a/server/cros/bluetooth/bluetooth_adapter_tests.py
+++ b/server/cros/bluetooth/bluetooth_adapter_tests.py
@@ -1926,10 +1926,17 @@
 
         device_type = self.host.get_board_type().lower()
         alias_format = '%s_[a-z0-9]{4}' % device_type
-        if not re.match(alias_format, alias.lower()):
-            return False
 
-        return True
+        self.results = {}
+
+        alias_was_correct = True
+        if not re.match(alias_format, alias.lower()):
+            alias_was_correct = False
+            logging.info('unexpected alias %s found', alias)
+            self.results['alias_found'] = alias
+
+        self.results['alias_was_correct'] = alias_was_correct
+        return all(self.results.values())
 
 
     # -------------------------------------------------------------------
@@ -4293,6 +4300,43 @@
 
         return percentage > 0
 
+    def _apply_new_adapter_alias(self, alias):
+        """ Sets new system alias and applies discoverable setting
+
+        @param alias: string alias to be applied to Adapter->Alias property
+        """
+
+        # Set Adapter's Alias property
+        self.bluetooth_facade.set_adapter_alias(alias)
+
+        # Set discoverable setting on
+        self.bluetooth_facade.set_discoverable(True)
+
+    @test_retry_and_log(False)
+    def test_set_adapter_alias(self, alias):
+        """ Validates that a new adapter alias is applied correctly
+
+        @param alias: string alias to be applied to Adapter->Alias property
+
+        @returns: True if the applied alias is properly applied in btmon trace
+        """
+
+        orig_alias = self.get_adapter_properties()['Alias']
+        self.bluetooth_le_facade = self.bluetooth_facade
+
+        # 1. Capture btmon logs around alias set operation
+        self._get_btmon_log(lambda: self._apply_new_adapter_alias(alias))
+
+        # 2. Verify that name appears in btmon trace with the following format:
+        # "Name (complete): Chromebook_BA0E" as appears in EIR data set
+        expected_alias_str = 'Name (complete): ' + alias
+        alias_found = self.bluetooth_facade.btmon_find(expected_alias_str)
+
+        # 3. Re-apply previous bluez alias as other tests expect default
+        self.bluetooth_facade.set_adapter_alias(orig_alias)
+
+        self.results = {'alias_found': alias_found}
+        return all(self.results.values())
 
     # -------------------------------------------------------------------
     # Autotest methods
diff --git a/server/cros/bluetooth/bluetooth_device.py b/server/cros/bluetooth/bluetooth_device.py
index 9a0fd4c..be3fd03 100644
--- a/server/cros/bluetooth/bluetooth_device.py
+++ b/server/cros/bluetooth/bluetooth_device.py
@@ -422,6 +422,19 @@
         properties = self.get_adapter_properties()
         return properties.get('Pairable') == 1
 
+    @proxy_thread_safe
+    def set_adapter_alias(self, alias):
+        """Set the adapter alias.
+
+        A note on Alias property - providing an empty string ('') will reset the
+        Alias property to the system default
+
+        @param alias: adapter alias to set with type String
+
+        @return True on success, False otherwise.
+        """
+
+        return self._proxy.set_adapter_alias(alias)
 
     @proxy_thread_safe
     def get_adapter_properties(self):
diff --git a/server/site_tests/bluetooth_AdapterSAHealth/bluetooth_AdapterSAHealth.py b/server/site_tests/bluetooth_AdapterSAHealth/bluetooth_AdapterSAHealth.py
index 2b65f64..fa6ad78 100644
--- a/server/site_tests/bluetooth_AdapterSAHealth/bluetooth_AdapterSAHealth.py
+++ b/server/site_tests/bluetooth_AdapterSAHealth/bluetooth_AdapterSAHealth.py
@@ -219,6 +219,13 @@
         self.test_dbus_get_supported_capabilities_success()
         self.test_dbus_get_supported_capabilities_success_power_off()
 
+    @test_wrapper('EIR Max Alias Size test')
+    def sa_eir_max_name_size_test(self):
+        """ Verify that the non-default max eir name size is used """
+        EIR_80_char_name = ('1234567890123456789012345678901234567890'
+                            '1234567890123456789012345678901234567890')
+
+        self.test_set_adapter_alias(EIR_80_char_name)
 
 
     @batch_wrapper('Stand Alone Health')
diff --git a/server/site_tests/bluetooth_AdapterSAHealth/control.sa_eir_max_name_size_test b/server/site_tests/bluetooth_AdapterSAHealth/control.sa_eir_max_name_size_test
new file mode 100644
index 0000000..b39bc92
--- /dev/null
+++ b/server/site_tests/bluetooth_AdapterSAHealth/control.sa_eir_max_name_size_test
@@ -0,0 +1,30 @@
+# Copyright 2020 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+from autotest_lib.server import utils
+
+AUTHOR = 'chromeos-bluetooth'
+NAME = 'bluetooth_AdapterSAHealth.sa_eir_max_name_size_test'
+PURPOSE = ('Test that non-default EIR name length is applied')
+CRITERIA = 'Pass the test'
+ATTRIBUTES = 'suite:bluetooth_flaky'
+TIME = 'SHORT'
+TEST_CATEGORY = 'Functional'
+TEST_CLASS = 'bluetooth'
+TEST_TYPE = 'server'
+DEPENDENCIES = 'bluetooth'
+
+DOC = """
+    Tests that the bluetoothd dbus API can be used to set EIR name longer than
+    the default 48 bytes.
+    """
+
+args_dict = utils.args_to_dict(args)
+
+def run(machine):
+    host = hosts.create_host(machine)
+    job.run_test('bluetooth_AdapterSAHealth', host=host,
+                  num_iterations=1, test_name=NAME.split('.')[1])
+
+parallel_simple(run, machines)