1#!/bin/bash 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 17usage() { 18 cat <<EOF 19Usage: launch_application package activity | parse_metrics --package <name> --timestamp <timestamp> [OPTIONS]... 20 21 Reads from stdin the result of 'am start' metrics. May also parse logcat 22 for additional metrics. 23 24 Output form: 25 26 MetricName_unit=numeric_value 27 MetricName2_unit=numeric_value2 28 29 This may block until all desired metrics are parsed from logcat. 30 To get a list of metrics without doing real parsing, use --simulate. 31 32 To add package-specific metrics, add a script called 'metrics/\$full_package_name' 33 that exposes additional metrics in same way as above. 34 35 (required) 36 -p, --package <name> package of the app that is being used 37 -ts, --timestamp <name> logcat timestamp [only looks at logcat entries after this timestamp]. 38 39 (optional) 40 -s, --simulate prints dummy values instead of real metrics 41 -a, --activity <name> activity to use (default: inferred) 42 -h, --help usage information (this) 43 -v, --verbose enable extra verbose printing 44 -t, --timeout <sec> how many seconds to timeout when trying to wait for logcat to change 45 -rfd, --reportfullydrawn wait for report fully drawn (default: off) 46EOF 47} 48 49DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 50source "$DIR/lib/common" 51 52report_fully_drawn="n" 53package="" 54activity="" 55timeout=5 56simulate="n" 57parse_arguments() { 58 while [[ $# -gt 0 ]]; do 59 case "$1" in 60 -h|--help) 61 usage 62 exit 0 63 ;; 64 -p|--package) 65 package="$2" 66 shift 67 ;; 68 -a|--activity) 69 activity="$2" 70 shift 71 ;; 72 -v|--verbose) 73 export verbose="y" 74 ;; 75 -t|--timeout) 76 timeout="$2" 77 shift 78 ;; 79 -ts|--timestamp) 80 timestamp="$2" 81 shift 82 ;; 83 -s|--simulate) 84 simulate="y" 85 ;; 86 -rfd|--reportfullydrawn) 87 report_fully_drawn="y" 88 ;; 89 90 91 *) 92 echo "Invalid argument: $1" >&2 93 exit 1 94 esac 95 shift 96 done 97} 98 99# Main entry point 100if [[ $# -eq 0 ]]; then 101 usage 102 exit 1 103else 104 parse_arguments "$@" 105 106 # if we do not have have package exit early with an error 107 [[ "$package" == "" ]] && echo "--package not specified" 1>&2 && exit 64 108 109 # ignore timestamp for --simulate. it's optional. 110 if [[ $simulate == y ]]; then 111 timestamp=0 112 fi 113 114 # if we do not have timestamp, exit early with an error 115 [[ "$timestamp" == "" ]] && echo "--timestamp not specified" 1>&2 && exit 64 116 117 if [[ "$activity" == "" ]] && [[ "$simulate" != "y" ]]; then 118 activity="$(get_activity_name "$package")" 119 if [[ "$activity" == "" ]]; then 120 echo "Activity name could not be found, invalid package name?" 1>&2 121 exit 64 122 else 123 verbose_print "Activity name inferred: " "$activity" 124 fi 125 fi 126fi 127 128parse_metric_from_logcat() { 129 local metric_name="$1" 130 local pattern="$2" 131 local re_pattern="$3" 132 local retcode 133 local result 134 local sec 135 local ms 136 137 # parse logcat for 'Displayed...' and that other one... 138 139 # 05-06 14:34:08.854 29460 29481 I ActivityTaskManager: Displayed com.google.android.dialer/.extensions.GoogleDialtactsActivity: +361ms 140 verbose_print "parse_metric_from_logcat: $re_pattern" 141 142 143 echo -ne "$metric_name=" 144 145 if [[ $simulate == y ]]; then 146 echo "-1" 147 return 0 148 fi 149 150 result="$(logcat_extract_pattern "$timeout" "$timestamp" "$pattern" "$re_pattern")" 151 retcode=$? 152 153 if [[ $retcode -ne 0 ]]; then 154 # Timed out before finding the pattern. Could also mean the pattern is wrong. 155 echo "Parse $re_pattern from logcat TIMED OUT after $timeout seconds." >&2 156 echo "-$?" 157 return $retcode 158 fi 159 160 # "10s123ms" -> "10s123" 161 result=${result/ms/} 162 if [[ $result =~ s ]]; then 163 ms=${result/*s/} 164 sec=${result/s*/} 165 else 166 sec=0 167 ms=$result 168 fi 169 ((result=sec*1000+ms)) 170 171 echo "$result" 172 return $retcode 173} 174 175 176total_time="-1" 177if [[ $simulate != y ]]; then 178 verbose_print 'logcat timestamp NOW: ' $(logcat_save_timestamp) 179 180 # parse stdin for 'am start' result 181 while read -t "$timeout" -r input_line; do 182 verbose_print 'stdin:' "$input_line" 183 if [[ $input_line == *TotalTime:* ]]; then 184 total_time="$(echo "$input_line" | sed 's/TotalTime: \([[:digit:]]\+\)/\1/g')" 185 # but keep reading the rest from stdin until <EOF> 186 fi 187 done 188fi 189 190echo "TotalTime_ms=$total_time" 191 192# parse logcat for 'Displayed...' and that other one... 193 194# 05-06 14:34:08.854 29460 29481 I ActivityTaskManager: Displayed com.google.android.dialer/.extensions.GoogleDialtactsActivity: +361ms 195pattern="ActivityTaskManager: Displayed ${package}" 196re_pattern='.*Displayed[[:blank:]]\+'"${package}"'[/][^[:blank:]]\+[[:blank:]]+\([[:digit:]]\+ms\|[[:digit:]]\+s[[:digit:]]\+ms\).*' 197 198parse_metric_from_logcat "Displayed_ms" "$pattern" "$re_pattern" 199 200# Only track ReportFullyDrawn with --reportfullydrawn/-rfd flags 201if [[ $report_fully_drawn == y ]]; then 202 # 01-16 17:31:44.550 11172 11204 I ActivityTaskManager: Fully drawn com.google.android.GoogleCamera/com.android.camera.CameraLauncher: +10s897ms 203 pattern="ActivityTaskManager: Fully drawn ${package}" 204 #re_pattern='.*Fully drawn[[:blank:]]\+'"${package}"'[/][^[:blank:]]\+[[:blank:]]+\([[:digit:]]\+\).*' 205 re_pattern='.*Fully drawn[[:blank:]]\+'"${package}"'[/][^[:blank:]]\+[[:blank:]]+\([[:digit:]]\+ms\|[[:digit:]]\+s[[:digit:]]\+ms\).*' 206 207 parse_metric_from_logcat "Fully_drawn_ms" "$pattern" "$re_pattern" 208fi 209 210# also call into package-specific scripts if there are additional metrics 211if [[ -x "$DIR/metrics/$package" ]]; then 212 source "$DIR/metrics/$package" "$timestamp" 213else 214 verbose_print parse_metrics: no per-package metrics script found at "$DIR/metrics/$package" 215fi 216