Merge "[AWARE] Rename configuration variable with "aware" prefix" into oc-mr1-dev
diff --git a/acts/framework/acts/controllers/relay_lib/relay_rig.py b/acts/framework/acts/controllers/relay_lib/relay_rig.py
index 6a167a8..a88099d 100644
--- a/acts/framework/acts/controllers/relay_lib/relay_rig.py
+++ b/acts/framework/acts/controllers/relay_lib/relay_rig.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright 2016 - The Android Open Source Project
+# Copyright 2017 - 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.
@@ -18,6 +18,7 @@
from acts.controllers.relay_lib.sain_smart_board import SainSmartBoard
from acts.controllers.relay_lib.generic_relay_device import GenericRelayDevice
from acts.controllers.relay_lib.fugu_remote import FuguRemote
+from acts.controllers.relay_lib.sony_xb2_speaker import SonyXB2Speaker
class RelayRig:
@@ -48,6 +49,7 @@
_device_constructors = {
'GenericRelayDevice': lambda x, rig: GenericRelayDevice(x, rig),
'FuguRemote': lambda x, rig: FuguRemote(x, rig),
+ 'SonyXB2Speaker': lambda x, rig: SonyXB2Speaker(x, rig),
}
def __init__(self, config):
diff --git a/acts/framework/acts/controllers/relay_lib/sony_xb2_speaker.py b/acts/framework/acts/controllers/relay_lib/sony_xb2_speaker.py
new file mode 100644
index 0000000..2d01eca
--- /dev/null
+++ b/acts/framework/acts/controllers/relay_lib/sony_xb2_speaker.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+#
+# Copyright 2017 - 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.
+import time
+import enum
+import logging
+from acts.controllers.relay_lib.generic_relay_device import GenericRelayDevice
+from acts.controllers.relay_lib.relay import SynchronizeRelays
+from acts.controllers.relay_lib.errors import RelayConfigError
+from acts.controllers.relay_lib.helpers import validate_key
+
+PAIRING_MODE_WAIT_TIME = 5
+POWER_ON_WAIT_TIME = 2
+POWER_OFF_WAIT_TIME = 6
+MISSING_RELAY_MSG = 'Relay config for Sonxy XB2 "%s" missing relay "%s".'
+
+log = logging
+
+
+class Buttons(enum.Enum):
+ POWER = 'Power'
+ PAIR = 'Pair'
+
+
+class SonyXB2Speaker(GenericRelayDevice):
+ """A Sony XB2 Bluetooth Speaker.
+
+ Wraps the button presses, as well as the special features like pairing.
+ """
+
+ def __init__(self, config, relay_rig):
+ GenericRelayDevice.__init__(self, config, relay_rig)
+
+ self.mac_address = validate_key('mac_address', config, str, 'sony_xb2')
+
+ for button in Buttons:
+ self.ensure_config_contains_relay(button.value)
+
+ def ensure_config_contains_relay(self, relay_name):
+ """Throws an error if the relay does not exist."""
+ if relay_name not in self.relays:
+ raise RelayConfigError(MISSING_RELAY_MSG % (self.name, relay_name))
+
+ def _hold_button(self, button, seconds):
+ self.hold_down(button.value)
+ time.sleep(seconds)
+ self.release(button.value)
+
+ def power_on(self):
+ self._hold_button(Buttons.POWER, POWER_ON_WAIT_TIME)
+
+ def power_off(self):
+ self._hold_button(Buttons.POWER, POWER_OFF_WAIT_TIME)
+
+ def enter_pairing_mode(self):
+ self._hold_button(Buttons.PAIR, PAIRING_MODE_WAIT_TIME)
+
+ def setup(self):
+ """Sets all relays to their default state (off)."""
+ GenericRelayDevice.setup(self)
+
+ def clean_up(self):
+ """Sets all relays to their default state (off)."""
+ GenericRelayDevice.clean_up(self)
diff --git a/acts/tests/google/bt/SonyXB2PairingTest.py b/acts/tests/google/bt/SonyXB2PairingTest.py
new file mode 100644
index 0000000..3bb2ae7
--- /dev/null
+++ b/acts/tests/google/bt/SonyXB2PairingTest.py
@@ -0,0 +1,166 @@
+#!/usr/bin/env python
+#
+# Copyright 2017 - 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.
+"""
+Test pairing of an Android Device to a Sony XB2 Bluetooth speaker
+"""
+import logging
+import time
+
+from acts.controllers.relay_lib.relay import SynchronizeRelays
+from acts.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest
+
+log = logging
+
+
+class SonyXB2PairingTest(BluetoothBaseTest):
+ DISCOVERY_TIME = 5
+
+ def __init__(self, controllers):
+ BluetoothBaseTest.__init__(self, controllers)
+ self.dut = self.android_devices[0]
+ # Do factory reset and then do delay for 3-seconds
+ self.dut.droid.bluetoothFactoryReset()
+ time.sleep(3)
+ self.sony_xb2_speaker = self.relay_devices[0]
+
+ def setup_test(self):
+ super(BluetoothBaseTest, self).setup_test()
+ self.sony_xb2_speaker.setup()
+ self.sony_xb2_speaker.power_on()
+ # Wait for a moment between pushing buttons
+ time.sleep(0.25)
+ self.sony_xb2_speaker.enter_pairing_mode()
+
+ def teardown_test(self):
+ super(BluetoothBaseTest, self).teardown_test()
+ self.sony_xb2_speaker.power_off()
+ self.sony_xb2_speaker.clean_up()
+
+ def _perform_classic_discovery(self, scan_time=DISCOVERY_TIME):
+ self.dut.droid.bluetoothStartDiscovery()
+ time.sleep(scan_time)
+ self.dut.droid.bluetoothCancelDiscovery()
+ return self.dut.droid.bluetoothGetDiscoveredDevices()
+
+ @BluetoothBaseTest.bt_test_wrap
+ def test_speaker_on(self):
+ """Test if the Sony XB2 speaker is powered on.
+
+ Use scanning to determine if the speaker is powered on.
+
+ Steps:
+ 1. Put the speaker into pairing mode. (Hold the button)
+ 2. Perform a scan on the DUT
+ 3. Check the scan list for the device.
+
+ Expected Result:
+ Speaker is found.
+
+ Returns:
+ Pass if True
+ Fail if False
+
+ TAGS: ACTS_Relay
+ Priority: 1
+ """
+
+ for device in self._perform_classic_discovery():
+ if device['address'] == self.sony_xb2_speaker.mac_address:
+ self.dut.log.info("Desired device with MAC address %s found!",
+ self.sony_xb2_speaker.mac_address)
+ return True
+ return False
+
+ @BluetoothBaseTest.bt_test_wrap
+ def test_speaker_off(self):
+ """Test if the Sony XB2 speaker is powered off.
+
+ Use scanning to determine if the speaker is powered off.
+
+ Steps:
+ 1. Power down the speaker
+ 2. Put the speaker into pairing mode. (Hold the button)
+ 3. Perform a scan on the DUT
+ 4. Check the scan list for the device.
+
+ Expected Result:
+ Speaker is not found.
+
+ Returns:
+ Pass if True
+ Fail if False
+
+ TAGS: ACTS_Relay
+ Priority: 1
+ """
+ # Specific part of the test, turn off the speaker
+ self.sony_xb2_speaker.power_off()
+
+ device_not_found = True
+ for device in self._perform_classic_discovery():
+ if device['address'] == self.sony_xb2_speaker.mac_address:
+ self.dut.log.info("Undesired device with MAC address %s found!",
+ self.sony_xb2_speaker.mac_address)
+ device_not_found = False
+
+ # Set the speaker back to the normal for tear_down()
+ self.sony_xb2_speaker.power_on()
+ # Give the relay and speaker some time, before it is turned off.
+ time.sleep(5)
+ return device_not_found
+
+ @BluetoothBaseTest.bt_test_wrap
+ def test_pairing(self):
+ """Test pairing between a phone and Sony XB2 speaker.
+
+ Test the Sony XB2 speaker can be paired to phone.
+
+ Steps:
+ 1. Find the MAC address of remote controller from relay config file.
+ 2. Start the device paring process.
+ 3. Enable remote controller in pairing mode.
+ 4. Verify the remote is paired.
+
+ Expected Result:
+ Speaker is paired.
+
+ Returns:
+ Pass if True
+ Fail if False
+
+ TAGS: ACTS_Relay
+ Priority: 1
+ """
+
+ # BT scan activity
+ self._perform_classic_discovery()
+ self.dut.droid.bluetoothDiscoverAndBond(
+ self.sony_xb2_speaker.mac_address)
+
+ end_time = time.time() + 20
+ self.dut.log.info("Verifying devices are bonded")
+ while (time.time() < end_time):
+ bonded_devices = self.dut.droid.bluetoothGetBondedDevices()
+ for d in bonded_devices:
+ if d['address'] == self.sony_xb2_speaker.mac_address:
+ self.dut.log.info("Successfully bonded to device.")
+ self.log.info(
+ "XB2 Bonded devices:\n{}".format(bonded_devices))
+ return True
+ # Timed out trying to bond.
+ self.dut.log.info("Failed to bond devices.")
+
+ return False
diff --git a/acts/tests/google/bt/power/A2dpPowerTest.py b/acts/tests/google/bt/power/A2dpPowerTest.py
index 5b8d387..56b9850 100644
--- a/acts/tests/google/bt/power/A2dpPowerTest.py
+++ b/acts/tests/google/bt/power/A2dpPowerTest.py
@@ -35,6 +35,7 @@
from acts.test_utils.bt.PowerBaseTest import PowerBaseTest
from acts.test_utils.bt.bt_test_utils import bluetooth_enabled_check
from acts.test_utils.bt.bt_test_utils import disable_bluetooth
+from acts.controllers.relay_lib.sony_xb2_speaker import SonyXB2Speaker
def push_file_to_device(ad, file_path, device_path, config_path):
@@ -98,12 +99,8 @@
# LDAC playback quality constant for the codecs other than LDAC
LDACBT_NONE = 0
- def setup_class(self):
-
- self.ad = self.android_devices[0]
-
+ def _pair_by_config(self):
bt_device_address = self.user_params["bt_device_address"]
-
# Push the bt_config.conf file to Android device
# if it is specified in config file
# so it can pair and connect automatically.
@@ -123,32 +120,12 @@
if not push_file_to_device(
self.ad, bt_config_path, bt_conf_path_dut,
self.user_params[Config.key_config_path]):
- self.log.error("Unable to push file {} to DUT.".format(
- bt_config_path))
+ self.log.error(
+ "Unable to push file {} to DUT.".format(bt_config_path))
self.log.info("Reboot")
self.ad.reboot()
- # Add music files to the Android device
- music_path_dut = "/sdcard/Music/"
- self.cd_quality_music_file = self.user_params["cd_quality_music_file"]
- self.log.info("Push CD quality music file {}".format(
- self.cd_quality_music_file))
- if not push_file_to_device(self.ad, self.cd_quality_music_file,
- music_path_dut,
- self.user_params[Config.key_config_path]):
- self.log.error("Unable to push file {} to DUT.".format(
- self.cd_quality_music_file))
-
- self.hi_res_music_file = self.user_params["hi_res_music_file"]
- self.log.info("Push Hi Res quality music file {}".format(
- self.hi_res_music_file))
- if not push_file_to_device(self.ad, self.hi_res_music_file,
- music_path_dut,
- self.user_params[Config.key_config_path]):
- self.log.error("Unable to find file {}.".format(
- self.hi_res_music_file))
-
if not bluetooth_enabled_check(self.ad):
self.log.error("Failed to enable Bluetooth on DUT")
return False
@@ -165,21 +142,96 @@
break
try:
- self.ad.droid.bluetoothConnectBonded(self.user_params[
- "bt_device_address"])
+ self.ad.droid.bluetoothConnectBonded(
+ self.user_params["bt_device_address"])
except Exception as err:
self.log.error(
"Failed to connect bonded device. Err: {}".format(err))
- if not result:
+ if result is False:
self.log.error("No headset is connected")
return False
+ return True
+
+ def _discover_and_pair(self):
+ self.ad.droid.bluetoothStartDiscovery()
+ time.sleep(5)
+ self.ad.droid.bluetoothCancelDiscovery()
+ for device in self.ad.droid.bluetoothGetDiscoveredDevices():
+ if device['address'] == self.a2dp_speaker.mac_address:
+ self.ad.droid.bluetoothDiscoverAndBond(
+ self.a2dp_speaker.mac_address)
+ end_time = time.time() + 20
+ self.log.info("Verifying devices are bonded")
+ while (time.time() < end_time):
+ bonded_devices = self.ad.droid.bluetoothGetBondedDevices()
+ for d in bonded_devices:
+ if d['address'] == self.a2dp_speaker.mac_address:
+ self.log.info("Successfully bonded to device.")
+ self.log.info("XB2 Bonded devices:\n{}".format(
+ bonded_devices))
+ return True
+ return False
+
+ def setup_class(self):
+ self.ad = self.android_devices[0]
+ self.ad.droid.bluetoothFactoryReset()
+ # Factory reset requires a short delay to take effect
+ time.sleep(3)
+
+ # Determine if we have a relay-based device
+ self.a2dp_speaker = None
+ if self.relay_devices[0]:
+ self.a2dp_speaker = self.relay_devices[0]
+ self.a2dp_speaker.setup()
+ # The device may be on, enter pairing mode.
+ self.a2dp_speaker.enter_pairing_mode()
+ if self._discover_and_pair() is False:
+ # The device is probably off, turn it on
+ self.a2dp_speaker.power_on()
+ time.sleep(0.25)
+ self.a2dp_speaker.enter_pairing_mode()
+ if self._discover_and_pair() is False:
+ self.log.info("Unable to pair to relay based device.")
+ return False
+ if len(self.ad.droid.bluetoothGetConnectedDevices()) == 0:
+ self.log.info("Not connected to relay based device.")
+ return False
+ else:
+ # No relay-based device used config
+ if self._pair_by_config() is False:
+ return False
+
+ # Add music files to the Android device
+ music_path_dut = "/sdcard/Music/"
+ self.cd_quality_music_file = self.user_params["cd_quality_music_file"]
+ self.log.info(
+ "Push CD quality music file {}".format(self.cd_quality_music_file))
+ if not push_file_to_device(self.ad, self.cd_quality_music_file,
+ music_path_dut,
+ self.user_params[Config.key_config_path]):
+ self.log.error("Unable to push file {} to DUT.".format(
+ self.cd_quality_music_file))
+
+ self.hi_res_music_file = self.user_params["hi_res_music_file"]
+ self.log.info(
+ "Push Hi Res quality music file {}".format(self.hi_res_music_file))
+ if not push_file_to_device(self.ad, self.hi_res_music_file,
+ music_path_dut,
+ self.user_params[Config.key_config_path]):
+ self.log.error(
+ "Unable to find file {}.".format(self.hi_res_music_file))
# Then do other power testing setup in the base class
# including start PMC etc
super(A2dpPowerTest, self).setup_class()
return True
+ def teardown_class(self):
+ if self.a2dp_speaker is not None:
+ self.a2dp_speaker.power_off()
+ self.a2dp_speaker.clean_up()
+
def _main_power_test_function_for_codec(self,
codec_type,
sample_rate,
@@ -220,8 +272,8 @@
# Get the base name of music file
music_name = os.path.basename(music_file)
self.music_url = "file:///sdcard/Music/{}".format(music_name)
- play_time = self.MEASURE_TIME + self.DELAY_MEASURE_TIME
- +self.DELAY_STOP_TIME
+ play_time = (self.MEASURE_TIME + self.DELAY_MEASURE_TIME +
+ self.DELAY_STOP_TIME)
play_msg = "%s --es MusicURL %s --es PlayTime %d" % (
self.PMC_BASE_CMD, self.music_url, play_time)
@@ -234,7 +286,7 @@
bits_per_sample)
if codec_type == self.CODEC_LDAC:
msg = "%s --es LdacPlaybackQuality %d" % (
- play_msg, ldac_playback_quality)
+ codec_msg, ldac_playback_quality)
else:
msg = codec_msg