1#!/usr/bin/env python3.4
2#
3#   Copyright 2018 - The Android Open Source Project
4#
5#   Licensed under the Apache License, Version 2.0 (the 'License');
6#   you may not use this file except in compliance with the License.
7#   You may obtain a copy of the License at
8#
9#       http://www.apache.org/licenses/LICENSE-2.0
10#
11#   Unless required by applicable law or agreed to in writing, software
12#   distributed under the License is distributed on an 'AS IS' BASIS,
13#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14#   See the License for the specific language governing permissions and
15#   limitations under the License.
16
17import os
18import time
19import acts.test_utils.bt.bt_power_test_utils as btputils
20import acts.test_utils.bt.bt_test_utils as btutils
21import acts.test_utils.power.PowerBaseTest as PBT
22from acts.test_utils.abstract_devices.bluetooth_handsfree_abstract_device import BluetoothHandsfreeAbstractDeviceFactory as bt_factory
23from math import copysign
24
25BLE_LOCATION_SCAN_DISABLE = 'settings put secure location_mode 0'
26PHONE_MUSIC_FILE_DIRECTORY = '/sdcard/Music'
27INIT_ATTEN = [0]
28
29
30def ramp_attenuation(obj_atten, attenuation_target, attenuation_step_max=20,
31                    time_wait_in_between=5 ):
32    """Ramp the attenuation up or down for BT tests.
33
34    Ramp the attenuation slowly so it won't have dramatic signal drop to affect
35    Link.
36
37    Args:
38        obj_atten: attenuator object, a single port attenuator
39        attenuation_target: target attenuation level to reach to.
40        attenuation_step_max: max step for attenuation set
41        time_wait_in_between: wait time between attenuation changes
42    """
43    sign = lambda x: copysign(1, x)
44    attenuation_delta = obj_atten.get_atten() - attenuation_target
45    while abs(attenuation_delta) > attenuation_step_max:
46        attenuation_intermediate = obj_atten.get_atten(
47        ) - sign(attenuation_delta) * attenuation_step_max
48        obj_atten.set_atten(attenuation_intermediate)
49        time.sleep(time_wait_in_between)
50        attenuation_delta = obj_atten.get_atten() - attenuation_target
51    obj_atten.set_atten(attenuation_target)
52
53
54class PowerBTBaseTest(PBT.PowerBaseTest):
55    """Base class for BT power related tests.
56
57    Inherited from the PowerBaseTest class
58    """
59    def setup_class(self):
60
61        super().setup_class()
62        # Get music file and push it to the phone
63        music_files = self.user_params.get('music_files', [])
64        if music_files:
65            music_src = music_files[0]
66            music_dest = PHONE_MUSIC_FILE_DIRECTORY
67            success = self.dut.push_system_file(music_src, music_dest)
68            if success:
69                self.music_file = os.path.join(PHONE_MUSIC_FILE_DIRECTORY,
70                                               os.path.basename(music_src))
71            # Initialize media_control class
72            self.media = btputils.MediaControl(self.dut, self.music_file)
73        # Set Attenuator to the initial attenuation
74        if hasattr(self, 'attenuators'):
75            self.set_attenuation(INIT_ATTEN)
76            self.attenuator = self.attenuators[0]
77        # Create the BTOE(Bluetooth-Other-End) device object
78        bt_devices = self.user_params.get('bt_devices', [])
79        if bt_devices:
80            attr, idx = bt_devices.split(':')
81            self.bt_device_controller = getattr(self, attr)[int(idx)]
82            self.bt_device = bt_factory().generate(self.bt_device_controller)
83        else:
84            self.log.error('No BT devices config is provided!')
85        # Turn off screen as all tests will be screen off
86        self.dut.droid.goToSleepNow()
87
88    def setup_test(self):
89
90        super().setup_test()
91        self.unpack_userparams(volume=0.9)
92        # Reset BT to factory defaults
93        self.dut.droid.bluetoothFactoryReset()
94        self.bt_device.reset()
95        self.bt_device.power_on()
96        btutils.enable_bluetooth(self.dut.droid, self.dut.ed)
97
98    def teardown_test(self):
99        """Tear down necessary objects after test case is finished.
100
101        Bring down the AP interface, delete the bridge interface, stop the
102        packet sender, and reset the ethernet interface for the packet sender
103        """
104        super().teardown_test()
105        self.dut.droid.bluetoothFactoryReset()
106        self.dut.adb.shell(BLE_LOCATION_SCAN_DISABLE)
107        if hasattr(self, 'media'):
108            self.media.stop()
109        # Set Attenuator to the initial attenuation
110        if hasattr(self, 'attenuators'):
111            self.set_attenuation(INIT_ATTEN)
112        self.bt_device.reset()
113        self.bt_device.power_off()
114        btutils.disable_bluetooth(self.dut.droid)
115
116    def teardown_class(self):
117        """Clean up the test class after tests finish running
118
119        """
120        super().teardown_class()
121        self.dut.droid.bluetoothFactoryReset()
122        self.dut.adb.shell(BLE_LOCATION_SCAN_DISABLE)
123        self.bt_device.reset()
124        self.bt_device.power_off()
125        btutils.disable_bluetooth(self.dut.droid)
126