| #!/bin/bash |
| # |
| # Copyright 2019, 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. |
| |
| usage() { |
| cat <<EOF |
| Usage: launch_application package activity | parse_metrics --package <name> --timestamp <timestamp> [OPTIONS]... |
| |
| Reads from stdin the result of 'am start' metrics. May also parse logcat |
| for additional metrics. |
| |
| Output form: |
| |
| MetricName_unit=numeric_value |
| MetricName2_unit=numeric_value2 |
| |
| This may block until all desired metrics are parsed from logcat. |
| To get a list of metrics without doing real parsing, use --simulate. |
| |
| To add package-specific metrics, add a script called 'metrics/\$full_package_name' |
| that exposes additional metrics in same way as above. |
| |
| (required) |
| -p, --package <name> package of the app that is being used |
| -ts, --timestamp <name> logcat timestamp [only looks at logcat entries after this timestamp]. |
| |
| (optional) |
| -s, --simulate prints dummy values instead of real metrics |
| -a, --activity <name> activity to use (default: inferred) |
| -h, --help usage information (this) |
| -v, --verbose enable extra verbose printing |
| -t, --timeout <sec> how many seconds to timeout when trying to wait for logcat to change |
| -rfd, --reportfullydrawn wait for report fully drawn (default: off) |
| EOF |
| } |
| |
| DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" |
| source "$DIR/lib/common" |
| |
| report_fully_drawn="n" |
| package="" |
| activity="" |
| timeout=5 |
| simulate="n" |
| parse_arguments() { |
| while [[ $# -gt 0 ]]; do |
| case "$1" in |
| -h|--help) |
| usage |
| exit 0 |
| ;; |
| -p|--package) |
| package="$2" |
| shift |
| ;; |
| -a|--activity) |
| activity="$2" |
| shift |
| ;; |
| -v|--verbose) |
| export verbose="y" |
| ;; |
| -t|--timeout) |
| timeout="$2" |
| shift |
| ;; |
| -ts|--timestamp) |
| timestamp="$2" |
| shift |
| ;; |
| -s|--simulate) |
| simulate="y" |
| ;; |
| -rfd|--reportfullydrawn) |
| report_fully_drawn="y" |
| ;; |
| |
| |
| *) |
| echo "Invalid argument: $1" >&2 |
| exit 1 |
| esac |
| shift |
| done |
| } |
| |
| # Main entry point |
| if [[ $# -eq 0 ]]; then |
| usage |
| exit 1 |
| else |
| parse_arguments "$@" |
| |
| # if we do not have have package exit early with an error |
| [[ "$package" == "" ]] && echo "--package not specified" 1>&2 && exit 64 |
| |
| # ignore timestamp for --simulate. it's optional. |
| if [[ $simulate == y ]]; then |
| timestamp=0 |
| fi |
| |
| # if we do not have timestamp, exit early with an error |
| [[ "$timestamp" == "" ]] && echo "--timestamp not specified" 1>&2 && exit 64 |
| |
| if [[ "$activity" == "" ]] && [[ "$simulate" != "y" ]]; then |
| activity="$(get_activity_name "$package")" |
| if [[ "$activity" == "" ]]; then |
| echo "Activity name could not be found, invalid package name?" 1>&2 |
| exit 64 |
| else |
| verbose_print "Activity name inferred: " "$activity" |
| fi |
| fi |
| fi |
| |
| parse_metric_from_logcat() { |
| local metric_name="$1" |
| local pattern="$2" |
| local re_pattern="$3" |
| local retcode |
| local result |
| local sec |
| local ms |
| |
| # parse logcat for 'Displayed...' and that other one... |
| |
| # 05-06 14:34:08.854 29460 29481 I ActivityTaskManager: Displayed com.google.android.dialer/.extensions.GoogleDialtactsActivity: +361ms |
| verbose_print "parse_metric_from_logcat: $re_pattern" |
| |
| |
| echo -ne "$metric_name=" |
| |
| if [[ $simulate == y ]]; then |
| echo "-1" |
| return 0 |
| fi |
| |
| result="$(logcat_extract_pattern "$timeout" "$timestamp" "$pattern" "$re_pattern")" |
| retcode=$? |
| |
| if [[ $retcode -ne 0 ]]; then |
| # Timed out before finding the pattern. Could also mean the pattern is wrong. |
| echo "Parse $re_pattern from logcat TIMED OUT after $timeout seconds." >&2 |
| echo "-$?" |
| return $retcode |
| fi |
| |
| # "10s123ms" -> "10s123" |
| result=${result/ms/} |
| if [[ $result =~ s ]]; then |
| ms=${result/*s/} |
| sec=${result/s*/} |
| else |
| sec=0 |
| ms=$result |
| fi |
| ((result=sec*1000+ms)) |
| |
| echo "$result" |
| return $retcode |
| } |
| |
| |
| total_time="-1" |
| if [[ $simulate != y ]]; then |
| verbose_print 'logcat timestamp NOW: ' $(logcat_save_timestamp) |
| |
| # parse stdin for 'am start' result |
| while read -t "$timeout" -r input_line; do |
| verbose_print 'stdin:' "$input_line" |
| if [[ $input_line == *TotalTime:* ]]; then |
| total_time="$(echo "$input_line" | sed 's/TotalTime: \([[:digit:]]\+\)/\1/g')" |
| # but keep reading the rest from stdin until <EOF> |
| fi |
| done |
| fi |
| |
| echo "TotalTime_ms=$total_time" |
| |
| # parse logcat for 'Displayed...' and that other one... |
| |
| # 05-06 14:34:08.854 29460 29481 I ActivityTaskManager: Displayed com.google.android.dialer/.extensions.GoogleDialtactsActivity: +361ms |
| pattern="ActivityTaskManager: Displayed ${package}" |
| re_pattern='.*Displayed[[:blank:]]\+'"${package}"'[/][^[:blank:]]\+[[:blank:]]+\([[:digit:]]\+ms\|[[:digit:]]\+s[[:digit:]]\+ms\).*' |
| |
| parse_metric_from_logcat "Displayed_ms" "$pattern" "$re_pattern" |
| |
| # Only track ReportFullyDrawn with --reportfullydrawn/-rfd flags |
| if [[ $report_fully_drawn == y ]]; then |
| # 01-16 17:31:44.550 11172 11204 I ActivityTaskManager: Fully drawn com.google.android.GoogleCamera/com.android.camera.CameraLauncher: +10s897ms |
| pattern="ActivityTaskManager: Fully drawn ${package}" |
| #re_pattern='.*Fully drawn[[:blank:]]\+'"${package}"'[/][^[:blank:]]\+[[:blank:]]+\([[:digit:]]\+\).*' |
| re_pattern='.*Fully drawn[[:blank:]]\+'"${package}"'[/][^[:blank:]]\+[[:blank:]]+\([[:digit:]]\+ms\|[[:digit:]]\+s[[:digit:]]\+ms\).*' |
| |
| parse_metric_from_logcat "Fully_drawn_ms" "$pattern" "$re_pattern" |
| fi |
| |
| # also call into package-specific scripts if there are additional metrics |
| if [[ -x "$DIR/metrics/$package" ]]; then |
| source "$DIR/metrics/$package" "$timestamp" |
| else |
| verbose_print parse_metrics: no per-package metrics script found at "$DIR/metrics/$package" |
| fi |