blob: 61be77781dee61e410d9fc0822e9987e82265a7a [file] [log] [blame]
#/usr/bin/env python3.4
#
# Copyright (C) 2016 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 script to automate the Bluetooth Audio Funhaus.
"""
from acts.keys import Config
from acts.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest
from acts.test_utils.bt.bt_test_utils import bluetooth_enabled_check
from acts.utils import create_dir
from acts.utils import exe_cmd
from acts.utils import sync_device_time
from queue import Empty
import json
import time
import os
class BtFunhausTest(BluetoothBaseTest):
music_file_to_play = ""
device_fails_to_connect_list = []
def __init__(self, controllers):
BluetoothBaseTest.__init__(self, controllers)
def on_fail(self, test_name, begin_time):
self._collect_bluetooth_manager_dumpsys_logs(self.android_devices)
super(BluetoothBaseTest, self).on_fail(test_name, begin_time)
def setup_class(self):
for ad in self.android_devices:
sync_device_time(ad)
# Disable Bluetooth HCI Snoop Logs for audio tests
ad.droid.bluetoothConfigHciSnoopLog(False)
if not "bt_config" in self.user_params.keys():
self.log.error("Missing mandatory user config \"bt_config\"!")
return False
bt_config_map_file = self.user_params["bt_config"]
return self._setup_bt_config(bt_config_map_file)
def _setup_bt_config(self, bt_config_map_file):
bt_config_map = {}
bt_conf_path = "/data/misc/bluedroid/bt_config.conf"
if not os.path.isfile(bt_config_map_file):
bt_config_map_file = os.path.join(
self.user_params[Config.key_config_path], bt_config_map_file)
if not os.path.isfile(bt_config_map_file):
self.log.error("Unable to load bt_config file {}.".format(
bt_config_map_file))
return False
try:
f = open(bt_config_map_file, 'r')
bt_config_map = json.load(f)
f.close()
except FileNotFoundError:
self.log.error("File not found: {}.".format(bt_config_map_file))
return False
for ad in self.android_devices:
serial = ad.serial
# Verify serial number in bt_config_map
if serial not in bt_config_map.keys():
self.log.error(
"Missing android device serial {} in bt_config.".format(
serial))
return False
# Push the bt_config.conf file to Android device
config_path = bt_config_map[serial]["config_path"]
if not os.path.isfile(config_path):
config_path = os.path.join(
self.user_params[Config.key_config_path], config_path)
if not os.path.isfile(config_path):
self.log.error("Unable to load bt_config file {}.".format(
config_path))
return False
ad.adb.push("{} {}".format(config_path, bt_conf_path))
# Add music to the Android device
music_path_str = "music_path"
android_music_path = "/sdcard/Music/"
if music_path_str not in self.user_params:
self.log.error("Need music for audio testcases...")
return False
music_path = self.user_params[music_path_str]
if not os.path.isdir(music_path):
music_path = os.path.join(
self.user_params[Config.key_config_path], music_path)
if not os.path.isdir(music_path):
self.log.error("Unable to find music directory {}.".format(
music_path))
return False
self._add_music_to_primary_android_device(ad, music_path,
android_music_path)
ad.reboot()
# Verify Bluetooth is enabled
if not bluetooth_enabled_check(ad):
self.log.error("Failed to toggle on Bluetooth on device {}".
format(serial))
return False
# Verify Bluetooth device is connected
self.log.info(
"Waiting up to 10 seconds for device to reconnect...")
connected_devices = ad.droid.bluetoothGetConnectedDevices()
start_time = time.time()
wait_time = 10
result = False
while time.time() < start_time + wait_time:
connected_devices = ad.droid.bluetoothGetConnectedDevices()
if len(connected_devices) > 0:
if bt_config_map[serial]["peripheral_info"]["address"] in {
d['address']
for d in connected_devices
}:
result = True
break
if not result:
self.log.error(
"Failed to connect to peripheral name: {}, address: {}".
format(bt_config_map[serial]["peripheral_info"]["name"],
bt_config_map[serial]["peripheral_info"][
"address"]))
self.device_fails_to_connect_list.append("{}:{}".format(
serial, bt_config_map[serial]["peripheral_info"]["name"]))
if len(self.device_fails_to_connect_list) == len(self.android_devices):
self.log.error("All devices failed to reconnect.")
return False
return True
def _add_music_to_primary_android_device(self, ad, music_path,
android_music_path):
for dirname, dirnames, filenames in os.walk(music_path):
for filename in filenames:
self.music_file_to_play = filename
file = os.path.join(dirname, filename)
#TODO: Handle file paths with spaces
ad.adb.push("{} {}".format(file, android_music_path))
return True
def _collect_bluetooth_manager_dumpsys_logs(self, ads):
for ad in ads:
serial = ad.serial
out_name = "{}_{}".format(serial, "bluetooth_dumpsys.txt")
dumpsys_path = ''.join((ad.log_path, "/BluetoothDumpsys"))
create_dir(dumpsys_path)
cmd = ''.join(
("adb -s ", serial, " shell dumpsys bluetooth_manager > ",
dumpsys_path, "/", out_name))
exe_cmd(cmd)
@BluetoothBaseTest.bt_test_wrap
def test_run_bt_audio_12_hours(self):
"""Test audio quality over 12 hours.
This test is designed to run Bluetooth audio for 12 hours
and collect relavant logs. If all devices disconnect during
the test or Bluetooth is off on all devices, then fail the
test.
Steps:
1. For each Android device connected run steps 2-5.
2. Open and play media file of music pushed to device
3. Set media to loop indefintely.
4. After 12 hours collect bluetooth_manager dumpsys information
5. Stop media player
Expected Result:
Audio plays for 12 hours over Bluetooth
Returns:
Pass if True
Fail if False
TAGS: Classic, A2DP
Priority: 1
"""
for ad in self.android_devices:
ad.droid.mediaPlayOpen("file:///sdcard/Music/{}".format(
self.music_file_to_play))
ad.droid.mediaPlaySetLooping(True)
self.log.info("Music is now playing on device {}".format(
ad.serial))
sleep_interval = 120
twelve_hours_in_seconds = 43200
twelve_hours_in_seconds = 500
end_time = time.time() + twelve_hours_in_seconds
test_result = True
bluetooth_off_list = []
device_not_connected_list = []
while time.time() < end_time:
for ad in self.android_devices:
serial = ad.serial
if (not ad.droid.bluetoothCheckState() and
serial not in bluetooth_off_list):
self.log.error(
"Device {}'s Bluetooth state is off.".format(serial))
bluetooth_off_list.append(serial)
if (ad.droid.bluetoothGetConnectedDevices() == 0 and
serial not in device_not_connected_list):
self.log.error(
"Device {} not connected to any Bluetooth devices.".
format(serial))
device_not_connected_list.append(serial)
if len(bluetooth_off_list) == len(self.android_devices):
self.log.error(
"Bluetooth off on all Android devices. Ending Test")
return False
if len(device_not_connected_list) == len(self.android_devices):
self.log.error(
"Every Android device has no device connected.")
return False
time.sleep(sleep_interval)
self._collect_bluetooth_manager_dumpsys_logs(self.android_devices)
for ad in self.android_devices:
ad.droid.mediaPlayStopAll()
if len(device_not_connected_list) > 0 or len(bluetooth_off_list) > 0:
self.log.info("Devices reported as not connected: {}".format(
device_not_connected_list))
self.log.info("Devices reported with Bluetooth state off: {}".
format(bluetooth_off_list))
return False
return True
def test_setup_fail_if_devices_not_connected(self):
"""Test for devices connected or not during setup.
This test is designed to fail if the number of devices having
connection issues at time of setup is greater than 0. This lets
the test runner know of the stability of the testbed.
Steps:
1. Check lenght of self.device_fails_to_connect_list
Expected Result:
No device should be in a disconnected state.
Returns:
Pass if True
Fail if False
TAGS: None
Priority: 1
"""
if len(self.device_fails_to_connect_list) > 0:
self.log.error("Devices failed to reconnect:\n{}".format(
self.device_fails_to_connect_list))
return False
return True