1#!/usr/bin/env python3 2# 3# Copyright 2019 - 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 errno 20 21DEVICE_CFG_FOLDER = "/data/vendor/radio/diag_logs/cfg/" 22DEVICE_DIAGMDLOG_FOLDER = "/data/vendor/radio/diag_logs/logs/" 23MDLOG_SETTLING_TIME = 2 24MDLOG_PROCESS_KILL_TIME = 3 25NOHUP_CMD = "nohup diag_mdlog -f {} -o {} -s 100 -c &> /dev/null &" 26DEVICE_GPSLOG_FOLDER = '/sdcard/Android/data/com.android.gpstool/files/' 27 28 29def find_device_qxdm_log_mask(ad, maskfile): 30 """Finds device's diagmd mask file 31 32 Args: 33 ad: the target android device, AndroidDevice object 34 maskfile: Device's mask file name 35 36 Return: 37 exists, if cfg file is present 38 39 Raises: 40 FileNotFoundError if maskfile is not present 41 """ 42 43 if ".cfg" not in maskfile: 44 # errno.ENOENT - No such file or directory 45 raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), 46 maskfile) 47 else: 48 cfg_path = os.path.join(DEVICE_CFG_FOLDER, maskfile) 49 device_mask_file = ad.adb.shell('test -e %s && echo exists' % cfg_path) 50 return device_mask_file 51 52 53def set_diagmdlog_command(ad, maskfile): 54 """Sets diagmdlog command to run in background 55 56 Args: 57 ad: the target android device, AndroidDevice object 58 maskfile: mask file name 59 60 """ 61 cfg_path = os.path.join(DEVICE_CFG_FOLDER, maskfile) 62 ad.adb.shell(NOHUP_CMD.format(cfg_path, DEVICE_DIAGMDLOG_FOLDER)) 63 ad.log.info("Running diag_mdlog in the background") 64 time.sleep(MDLOG_SETTLING_TIME) 65 66 67def verify_diagmd_folder_exists(ad): 68 """Verify diagmd folder existence in device 69 70 Args: 71 ad: the target android device, AndroidDevice object 72 73 """ 74 mask_folder_exists = ad.adb.shell( 75 'test -d %s && echo exists' % DEVICE_CFG_FOLDER) 76 diag_folder_exists = ad.adb.shell( 77 'test -d %s && echo exists' % DEVICE_DIAGMDLOG_FOLDER) 78 if not mask_folder_exists and diag_folder_exists: 79 ad.adb.shell("mkdir " + DEVICE_CFG_FOLDER) 80 ad.adb.shell("mkdir " + DEVICE_DIAGMDLOG_FOLDER) 81 82 83def start_diagmdlog_background(ad, maskfile="default.cfg", is_local=True): 84 """Runs diagmd_log in background 85 86 Args: 87 ad: the target android device, AndroidDevice object 88 maskfile: Local Mask file path or Device's mask file name 89 is_local: False, take cfgfile from config. 90 True, find cfgfile in device and run diagmdlog 91 92 Raises: 93 FileNotFoundError if maskfile is not present 94 ProcessLookupError if diagmdlog process not present 95 """ 96 if is_local: 97 find_device_qxdm_log_mask(ad, maskfile) 98 set_diagmdlog_command(ad, maskfile) 99 else: 100 if not os.path.isfile(maskfile): 101 # errno.ENOENT - No such file or directory 102 raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), 103 maskfile) 104 else: 105 cfgfilename = os.path.basename(maskfile) 106 verify_diagmd_folder_exists(ad) 107 ad.adb.push("{} {}".format(maskfile, DEVICE_CFG_FOLDER)) 108 set_diagmdlog_command(ad, cfgfilename) 109 output = ad.adb.shell("pgrep diag_mdlog") 110 ad.log.info("Checking diag_mdlog in process") 111 if not output: 112 # errno.ESRCH - No such process 113 raise ProcessLookupError(errno.ESRCH, os.strerror(errno.ESRCH), 114 "diag_mdlog") 115 116 117def stop_background_diagmdlog(ad, local_logpath, keep_logs=True): 118 """Stop diagmdlog and pulls diag_mdlog from android device 119 120 Args: 121 ad: the target android device, AndroidDevice object 122 local_logpath: Local file path to pull the diag_mdlog logs 123 keep_logs: False, delete log files from the diag_mdlog path 124 125 Raises: 126 ProcessLookupError if diagmdlog process not present 127 """ 128 ps_output = ad.adb.shell("pgrep diag_mdlog") 129 ad.log.info("Checking diag_mdlog in process") 130 if ps_output: 131 output = ad.adb.shell("diag_mdlog -k") 132 time.sleep(MDLOG_PROCESS_KILL_TIME) 133 if "stopping" in output: 134 ad.log.debug("Stopping diag_mdlog") 135 ad.adb.pull("{} {}".format(DEVICE_DIAGMDLOG_FOLDER, local_logpath)) 136 ad.log.debug("Pulling diag_logs from the device to local") 137 if not keep_logs: 138 ad.adb.shell("rm -rf " + DEVICE_DIAGMDLOG_FOLDER + "*.*") 139 ad.log.debug("diagmd logs are deleted from device") 140 else: 141 ad.log.debug("diagmd logs are not deleted from device") 142 else: 143 output = ad.adb.shell("pidof diag_mdlog") 144 if output: 145 ad.adb.shell("kill -9 {}".format(output)) 146 ad.log.debug("Kill the existing qxdm process") 147 ad.adb.pull("{} {}".format(DEVICE_DIAGMDLOG_FOLDER, 148 local_logpath)) 149 ad.log.debug("Pulling diag_logs from the device to local") 150 else: 151 # errno.ESRCH - No such process 152 raise ProcessLookupError(errno.ESRCH, os.strerror(errno.ESRCH), 153 "diag_mdlog") 154 else: 155 # errno.ESRCH - No such process 156 raise ProcessLookupError(errno.ESRCH, os.strerror(errno.ESRCH), 157 "diag_mdlog") 158 159 160def get_gpstool_logs(ad, local_logpath, keep_logs=True): 161 """ 162 163 Pulls gpstool Logs from android device 164 165 Args: 166 ad: the target android device, AndroidDevice object 167 local_logpath: Local file path to pull the gpstool logs 168 keep_logs: False, delete log files from the gpstool log path 169 """ 170 171 gps_log_path = os.path.join(local_logpath, 'GPSLogs') 172 ad.adb.pull("{} {}".format(DEVICE_GPSLOG_FOLDER, gps_log_path)) 173 ad.log.debug("gpstool logs are pulled from device") 174 175 if not keep_logs: 176 ad.adb.shell("rm -rf " + DEVICE_GPSLOG_FOLDER + "*.*") 177 ad.log.debug("gpstool logs are deleted from device")