blob: 3fa1462bc56ea827ed22de8036095362d261e19c [file] [log] [blame]
#!/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