1#!/usr/bin/env python3 2# 3# Copyright (C) 2016 The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); you may not 6# use this file except in compliance with the License. You may obtain a copy of 7# 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, WITHOUT 13# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 14# License for the specific language governing permissions and limitations under 15# the License. 16""" 17This test script exercises power test scenarios for GATT writing. 18This test script was designed with this setup in mind: 19Shield box one: Two Android Devices and Monsoon tool box 20""" 21 22import json 23import os 24import sys 25 26from acts.test_decorators import test_tracker_info 27from acts.test_utils.bt.BleEnum import ScanSettingsScanMode 28from acts.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest 29from acts.test_utils.bt.PowerBaseTest import PowerBaseTest 30from acts.test_utils.bt.bt_test_utils import bluetooth_enabled_check 31from acts.test_utils.bt.bt_test_utils import generate_ble_scan_objects 32from acts.utils import get_current_human_time 33from acts.utils import sync_device_time 34 35 36class GattPowerTest(PowerBaseTest): 37 """Class for Gatt Power Test""" 38 # Time to start GATT write 39 START_TIME = 30 40 # Repetitions 41 REPETITIONS_40 = 7 42 REPETITIONS_1 = 1 43 # Time for GATT writing 44 WRITE_TIME_60 = 60 45 WRITE_TIME_3600 = 600 46 # Time for idle 47 IDLE_TIME_30 = 30 48 IDLE_TIME_0 = 0 49 # Base commands for PMC 50 PMC_GATT_CMD = ("am broadcast -a com.android.pmc.GATT ") 51 GATT_SERVER_MSG = "%s--es GattServer 1" % (PMC_GATT_CMD) 52 53 def __init__(self, controllers): 54 PowerBaseTest.__init__(self, controllers) 55 56 self.cen_ad = self.android_devices[0] 57 self.per_ad = self.android_devices[1] 58 59 def setup_class(self): 60 super(GattPowerTest, self).setup_class() 61 if not bluetooth_enabled_check(self.per_ad): 62 self.log.error("Failed to turn on Bluetooth on peripheral") 63 64 # Start PMC app for peripheral here 65 # since base class has started PMC for central device 66 self.per_ad.adb.shell(PowerBaseTest.START_PMC_CMD) 67 self.per_ad.adb.shell(self.PMC_VERBOSE_CMD) 68 69 def _measure_power_for_gatt_n_log_data(self, write_time, idle_time, 70 repetitions, test_case): 71 """Utility function for power test with GATT write. 72 73 Steps: 74 1. Prepare adb shell command for GATT server 75 2. Send the adb shell command to PMC to startup GATT Server 76 3. Prepare adb shell command for GATT Client 77 4. Send the adb shell command to PMC to startup GATT Client 78 5. PMC will start first alarm on GATT Client to start 79 GATT write continuousely for "write_time" seconds 80 6. After finishing writing for write_time it will stop for 81 for "idle_time" seconds 82 7 Repeat the write/idle cycle for "repetitions" times 83 8. Save the power usage data into log file 84 85 Args: 86 write_time: time(sec) duration for writing GATT characteristic 87 idle_time: time(sec) of idle (not write) 88 repetitions: number of repetitions of writing cycles 89 90 Returns: 91 True if the average current is within the allowed tolerance; 92 False otherwise. 93 """ 94 95 if not self.disable_location_scanning(): 96 return False 97 98 # Verify Bluetooth is enabled on the companion phone. 99 if not bluetooth_enabled_check(self.android_devices[1]): 100 self.log.error("FAILED to enable Bluetooth on companion phone") 101 return False 102 103 # Send message to Gatt Server 104 self.per_ad.log.info("Send broadcast message to GATT Server: %s", 105 self.GATT_SERVER_MSG) 106 self.per_ad.adb.shell(self.GATT_SERVER_MSG) 107 108 # Send message to Gatt Client 109 first_part_msg = "%s--es StartTime %d --es WriteTime %d" % ( 110 self.PMC_GATT_CMD, self.START_TIME, write_time) 111 clientmsg = "%s --es IdleTime %d --es Repetitions %d" % ( 112 first_part_msg, idle_time, repetitions) 113 self.cen_ad.log.info("Send broadcast message to GATT Client: %s", 114 clientmsg) 115 self.cen_ad.adb.shell(clientmsg) 116 117 sample_time = (write_time + idle_time) * repetitions 118 # Start the power measurement 119 result = self.mon.measure_power(self.POWER_SAMPLING_RATE, sample_time, 120 self.current_test_name, self.START_TIME) 121 122 # Calculate average and save power data into a file 123 (current_avg, stdev) = self.save_logs_for_power_test( 124 result, write_time, idle_time) 125 # Take bug report for peripheral device 126 current_time = get_current_human_time() 127 self.per_ad.take_bug_report(self.current_test_name, current_time) 128 129 # perform watermark comparison numbers 130 self.log.info("==> CURRENT AVG from PMC Monsoon app: %s" % current_avg) 131 self.log.info( 132 "==> WATERMARK from config file: %s" % self.user_params[test_case]) 133 return self.check_test_pass(current_avg, self.user_params[test_case]) 134 135 @BluetoothBaseTest.bt_test_wrap 136 @test_tracker_info(uuid='f14cc28b-54f2-4a87-9fa9-68f39bf96701') 137 def test_power_for_60_sec_n_30_sec_idle_gatt_write(self): 138 """Test power usage when do 60 sec GATT write & 30 sec idle 139 140 Tests power usage when the test device do 60 sec GATT write 141 and 30 sec idle with max MTU bytes after being connected. 142 After each write GATT server will send a response 143 back to GATT client so GATT client can do another write. 144 145 Steps: 146 1. Prepare adb shell command for GATT server 147 2. Send the adb shell command to PMC to startup GATT Server 148 3. Prepare adb shell command for GATT Client 149 4. Send the adb shell command to PMC to startup GATT Client 150 5. PMC will start first alarm on GATT Client 151 6. Start power measurement 152 7. Alarm will be triggered to start GATT write for 60 second 153 8. Then it will be idle for 30 seconds 154 9. Reconnect after idle time 155 10. Repeat the cycles for 60 minutes 156 11. End power measurement 157 12. Save the power usage data into log file 158 159 Expected Result: 160 power consumption results 161 162 TAGS: LE, GATT, Power 163 Priority: 3 164 """ 165 current_test_case = func_name = sys._getframe().f_code.co_name 166 return self._measure_power_for_gatt_n_log_data( 167 self.WRITE_TIME_60, self.IDLE_TIME_30, self.REPETITIONS_40, 168 current_test_case) 169 170 @BluetoothBaseTest.bt_test_wrap 171 @test_tracker_info(uuid='41ca217e-161b-4899-a5b7-2d59d8dc7973') 172 def test_power_for_60_min_non_stop_gatt_write(self): 173 """Test power usage when do a single GATT write. 174 175 Tests power usage when the test device do 60 minutes of GATT write with 176 max MTU bytes after being connected. After each write GATT server will 177 send a response back to GATT client so GATT client can do another write. 178 179 Steps: 180 1. Prepare adb shell command for GATT server 181 2. Send the adb shell command to PMC to startup GATT Server 182 3. Prepare adb shell command for GATT Client 183 4. Send the adb shell command to PMC to startup GATT Client 184 5. PMC will start first alarm on GATT Client to start GATT write 185 6. Start power measurement 186 7. GATT server gets the write request after GATT Client sends a write 187 8. GATT server sends a response back to GATT Client 188 9. After GATT Client receive the response from GATT Server 189 it will check if time reaches 60 minutes. 190 if not it will write another characteristic 191 otherwise it will stop writing 192 10. Stop power measurement 193 11. Save the power usage data into log file 194 195 Expected Result: 196 power consumption results 197 198 TAGS: LE, GATT, Power 199 Priority: 3 200 """ 201 current_test_case = func_name = sys._getframe().f_code.co_name 202 return self._measure_power_for_gatt_n_log_data( 203 self.WRITE_TIME_3600, self.IDLE_TIME_0, self.REPETITIONS_1, 204 current_test_case) 205