You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
479 lines
12 KiB
479 lines
12 KiB
# functions and definitions for workload automation scripts
|
|
#
|
|
# See recentfling.sh, systemapps.sh, and other scripts that use
|
|
# these definitions.
|
|
#
|
|
|
|
dflttracecategories="gfx input view am rs power sched freq idle load memreclaim"
|
|
dfltAppList="gmail hangouts chrome youtube camera photos play maps calendar earth calculator sheets docs home"
|
|
generateActivities=0
|
|
|
|
# default activities. Can dynamically generate with -g.
|
|
gmailActivity='com.google.android.gm/com.google.android.gm.ConversationListActivityGmail'
|
|
clockActivity='com.google.android.deskclock/com.android.deskclock.DeskClock'
|
|
hangoutsActivity='com.google.android.talk/com.google.android.talk.SigningInActivity'
|
|
chromeActivity='com.android.chrome/_not_used'
|
|
contactsActivity='com.google.android.contacts/com.android.contacts.activities.PeopleActivity'
|
|
youtubeActivity='com.google.android.youtube/com.google.android.apps.youtube.app.WatchWhileActivity'
|
|
cameraActivity='com.google.android.GoogleCamera/com.android.camera.CameraActivity'
|
|
playActivity='com.android.vending/com.google.android.finsky.activities.MainActivity'
|
|
feedlyActivity='com.devhd.feedly/com.devhd.feedly.Main'
|
|
photosActivity='com.google.android.apps.photos/com.google.android.apps.photos.home.HomeActivity'
|
|
mapsActivity='com.google.android.apps.maps/com.google.android.maps.MapsActivity'
|
|
calendarActivity='com.google.android.calendar/com.android.calendar.AllInOneActivity'
|
|
earthActivity='com.google.earth/com.google.earth.EarthActivity'
|
|
calculatorActivity='com.google.android.calculator/com.android.calculator2.Calculator'
|
|
calculatorLActivity='com.android.calculator2/com.android.calculator2.Calculator'
|
|
sheetsActivity='com.google.android.apps.docs.editors.sheets/com.google.android.apps.docs.app.NewMainProxyActivity'
|
|
docsActivity='com.google.android.apps.docs.editors.docs/com.google.android.apps.docs.app.NewMainProxyActivity'
|
|
operaActivity='com.opera.mini.native/com.opera.mini.android.Browser'
|
|
firefoxActivity='org.mozilla.firefox/org.mozilla.firefox.App'
|
|
suntempleActivity='com.BrueComputing.SunTemple/com.epicgames.ue4.GameActivity'
|
|
homeActivity='com.google.android.googlequicksearchbox/com.google.android.launcher.GEL'
|
|
|
|
function showUsage {
|
|
echo "$0: unrecognized option: $1"
|
|
echo; echo "Usage: $0 [options]"
|
|
echo "-e : stop on error"
|
|
echo "-i iterations"
|
|
echo "-n : keep trace files"
|
|
echo "-o output file"
|
|
echo "-s device : adb device"
|
|
echo "-t trace categories"
|
|
echo "-g : generate activity strings"
|
|
}
|
|
|
|
DEVICE=unknown
|
|
|
|
# handle args
|
|
while [ $# -gt 0 ]
|
|
do
|
|
case "$1" in
|
|
(-d) DEVICE=$2; shift;;
|
|
(-e) stoponerror=1;;
|
|
(-n) savetmpfiles=1;;
|
|
(-t) tracecategories=$2; shift;;
|
|
(-i) iterations=$2; shift;;
|
|
(-o) output=$2; shift;;
|
|
(-v) verbose=1;;
|
|
(-nz) compress=0;;
|
|
(-s) deviceName=$2; shift;;
|
|
(-g) generateActivities=1;;
|
|
(--) ;;
|
|
(*)
|
|
chk1=$(functions 2>/dev/null)
|
|
chk2=$(typeset -F 2>/dev/null)
|
|
|
|
if echo $chk1 $chk2 | grep -q processLocalOption; then
|
|
if ! processLocalOption "$1" "$2"; then
|
|
shift
|
|
fi
|
|
else
|
|
showUsage $1
|
|
exit 1
|
|
fi;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
# check if running on a device
|
|
if ls /etc/* 2>/dev/null | grep -q android.hardware; then
|
|
ADB=""
|
|
compress=0
|
|
isOnDevice=1
|
|
else
|
|
# do a throw-away adb in case the server is out-of-date
|
|
adb devices -l 2>&1 >/dev/null
|
|
|
|
if [ -z "$deviceName" ]; then
|
|
devInfo=$(adb devices -l | grep -v ^List | head -1)
|
|
else
|
|
devInfo=$(adb devices -l | grep $deviceName)
|
|
fi
|
|
set -- $devInfo
|
|
if [ -z $1 ]; then
|
|
echo Error: could not find device $deviceName
|
|
exit 1
|
|
fi
|
|
deviceName=$1
|
|
ADB="adb -s $deviceName shell "
|
|
if [ "$DEVICE" = "" -o "$DEVICE" = unknown ]; then
|
|
DEVICE=$(echo $4 | sed 's/product://')
|
|
fi
|
|
isOnDevice=0
|
|
fi
|
|
|
|
if [ $isOnDevice -gt 0 ]; then
|
|
case "$DEVICE" in
|
|
(bullhead|angler)
|
|
if ! echo $$ > /dev/cpuset/background/tasks; then
|
|
echo Could not put PID $$ in background
|
|
fi
|
|
;;
|
|
(*)
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
# default values if not set by options or calling script
|
|
appList=${appList:=$dfltAppList}
|
|
savetmpfiles=${savetmpfiles:=0}
|
|
stoponerror=${stoponerror:=0}
|
|
verbose=${verbose:=0}
|
|
compress=${compress:=1}
|
|
iterations=${iterations:=5}
|
|
tracecategories=${tracecategories:=$dflttracecategories}
|
|
ADB=${ADB:=""}
|
|
output=${output:="./out"}
|
|
|
|
# clear the output file
|
|
if [ -f $output ]; then
|
|
> $output
|
|
fi
|
|
|
|
# ADB commands
|
|
AM_FORCE_START="${ADB}am start -W -S"
|
|
AM_START="${ADB}am start -W"
|
|
AM_START_NOWAIT="${ADB}am start"
|
|
AM_STOP="${ADB}am force-stop"
|
|
AM_LIST="${ADB}am stack list"
|
|
WHO="${ADB}whoami"
|
|
INPUT="${ADB}input"
|
|
PS="${ADB}ps"
|
|
|
|
function vout {
|
|
# debug output enabled by -v
|
|
if [ $verbose -gt 0 ]; then
|
|
echo DEBUG: $* >&2
|
|
echo DEBUG: $* >&2 >> $output
|
|
fi
|
|
}
|
|
|
|
function findtimestamp {
|
|
# extract timestamp from atrace log entry
|
|
while [ "$2" != "" -a "$2" != "tracing_mark_write" ]
|
|
do
|
|
shift
|
|
done
|
|
echo $1
|
|
}
|
|
|
|
function computeTimeDiff {
|
|
# Compute time diff given: startSeconds startNs endSeconds endNS
|
|
|
|
# strip leading zeros
|
|
startS=$(expr 0 + $1)
|
|
endS=$(expr 0 + $3)
|
|
if [ "$2" = N ]; then
|
|
startNs=0
|
|
endNs=0
|
|
else
|
|
startNs=$(expr 0 + $2)
|
|
endNs=$(expr 0 + $4)
|
|
fi
|
|
|
|
((startMs=startS*1000 + startNs/1000000))
|
|
((endMs=endS*1000 + endNs/1000000))
|
|
((diff=endMs-startMs))
|
|
echo $diff
|
|
}
|
|
|
|
function log2msec {
|
|
in=$1
|
|
in=${in:=0.0}
|
|
set -- $(echo $in | tr . " ")
|
|
|
|
# shell addition via (( )) doesn't like leading zeroes in msecs
|
|
# field so remove leading zeroes
|
|
msecfield=$(expr 0 + $2)
|
|
|
|
((msec=$1*1000000+msecfield))
|
|
((msec=msec/1000))
|
|
echo $msec
|
|
}
|
|
|
|
function getStartTime {
|
|
# extract event indicating beginning of start sequence
|
|
# a) look for a "launching" event indicating start from scratch
|
|
# b) look for another activity getting a pause event
|
|
_app=$1
|
|
traceout=$2
|
|
ret=0
|
|
s=$(grep "Binder.*tracing_mark_write.*launching" $traceout 2>/dev/null | head -1| tr [\(\)\[\]
|
|
:] " ")
|
|
if [ -z "$s" ]; then
|
|
s=$(grep activityPause $traceout | head -1 2>/dev/null| tr [\(\)\[\]
|
|
:] " ")
|
|
else
|
|
vout $_app was restarted!
|
|
ret=1
|
|
fi
|
|
vout STARTLOG: $s
|
|
log2msec $(findtimestamp $s)
|
|
return $ret
|
|
}
|
|
|
|
function getEndTime {
|
|
# extract event indicating end of start sequence. We use the
|
|
# first surfaceflinger event associated with the target activity
|
|
_app=$1
|
|
traceout=$2
|
|
f=$(grep "surfaceflinger.*tracing_mark_write.*$_app" $traceout 2>/dev/null |
|
|
grep -v Starting | head -1 | tr [\(\)\[\]
|
|
:] " ")
|
|
if [ -z "$f" ]; then
|
|
# Hmm. sf symbols may not be there... get the pid
|
|
pid=$(${ADB}pidof /system/bin/surfaceflinger | tr "[
|
|
]" "[ ]")
|
|
f=$(grep " <...>-$pid.*tracing_mark_write.*$_app" $traceout 2>/dev/null |
|
|
grep -v Starting | head -1 | tr [\(\)\[\]
|
|
:] " ")
|
|
fi
|
|
vout ENDLOG: $f
|
|
log2msec $(findtimestamp $f)
|
|
}
|
|
|
|
function resetJankyFrames {
|
|
_gfxapp=$1
|
|
_gfxapp=${_gfxapp:="com.android.systemui"}
|
|
${ADB}dumpsys gfxinfo $_gfxapp reset 2>&1 >/dev/null
|
|
}
|
|
|
|
function getJankyFrames {
|
|
_gfxapp=$1
|
|
_gfxapp=${_gfxapp:="com.android.systemui"}
|
|
|
|
# Note: no awk or sed on devices so have to do this
|
|
# purely with bash
|
|
total=0
|
|
janky=0
|
|
latency=0
|
|
${ADB}dumpsys gfxinfo $_gfxapp | tr "\r" " " | egrep "9[059]th| frames" | while read line
|
|
do
|
|
if echo $line | grep -q "Total frames"; then
|
|
set -- $line
|
|
total=$4
|
|
elif echo $line | grep -q "Janky frames"; then
|
|
set -- $line
|
|
janky=$3
|
|
elif echo $line | grep -q "90th"; then
|
|
set -- $(echo $line | tr m " ")
|
|
l90=$3
|
|
elif echo $line | grep -q "95th"; then
|
|
set -- $(echo $line | tr m " ")
|
|
l95=$3
|
|
elif echo $line | grep -q "99th"; then
|
|
set -- $(echo $line | tr m " ")
|
|
l99=$3
|
|
echo $total $janky $l90 $l95 $l99
|
|
break
|
|
fi
|
|
done
|
|
}
|
|
|
|
function checkForDirectReclaim {
|
|
# look for any reclaim events in atrace output
|
|
_app=$1
|
|
traceout=$2
|
|
if grep -qi reclaim $traceout; then
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
function startInstramentation {
|
|
_iter=$1
|
|
_iter=${_iter:=0}
|
|
enableAtrace=$2
|
|
enableAtrace=${enableAtrace:=1}
|
|
# Called at beginning of loop. Turn on instramentation like atrace
|
|
vout start instramentation $(date)
|
|
echo =============================== >> $output
|
|
echo Before iteration $_iter >> $output
|
|
echo =============================== >> $output
|
|
${ADB}cat /proc/meminfo 2>&1 >> $output
|
|
${ADB}dumpsys meminfo 2>&1 >> $output
|
|
if [ "$DEVICE" = volantis ]; then
|
|
${ADB}cat /d/nvmap/iovmm/procrank 2>&1 >> $output
|
|
fi
|
|
if [ "$user" = root -a $enableAtrace -gt 0 ]; then
|
|
vout ${ADB}atrace -b 32768 --async_start $tracecategories
|
|
${ADB}atrace -b 32768 --async_start $tracecategories >> $output
|
|
echo >> $output
|
|
fi
|
|
}
|
|
|
|
function stopInstramentation {
|
|
enableAtrace=$1
|
|
enableAtrace=${enableAtrace:=1}
|
|
if [ "$user" = root -a $enableAtrace -gt 0 ]; then
|
|
vout ${ADB}atrace --async_stop
|
|
${ADB}atrace --async_stop > /dev/null
|
|
fi
|
|
}
|
|
|
|
function stopAndDumpInstramentation {
|
|
vout stop instramentation $(date)
|
|
echo =============================== >> $output
|
|
echo After iteration >> $output
|
|
echo =============================== >> $output
|
|
${ADB}cat /proc/meminfo 2>&1 >> $output
|
|
${ADB}dumpsys meminfo 2>&1 >> $output
|
|
if [ "$user" = root ]; then
|
|
traceout=$1
|
|
traceout=${traceout:=$output}
|
|
echo =============================== >> $traceout
|
|
echo TRACE >> $traceout
|
|
echo =============================== >> $traceout
|
|
if [ $compress -gt 0 ]; then
|
|
tmpTrace=./tmptrace.$$
|
|
UNCOMPRESS=$CMDDIR/atrace-uncompress.py
|
|
> $tmpTrace
|
|
zarg="-z"
|
|
${ADB}atrace -z -b 32768 --async_dump >> $tmpTrace
|
|
python $UNCOMPRESS $tmpTrace >> $traceout
|
|
rm -f $tmpTrace
|
|
else
|
|
${ADB}atrace -b 32768 --async_dump > $traceout
|
|
fi
|
|
vout ${ADB}atrace $zarg -b 32768 --async_dump
|
|
vout ${ADB}atrace --async_stop
|
|
${ADB}atrace --async_stop > /dev/null
|
|
fi
|
|
}
|
|
|
|
function getActivityName {
|
|
cmd="actName=\$${1}Activity"
|
|
eval $cmd
|
|
echo $actName
|
|
}
|
|
|
|
function getPackageName {
|
|
set -- $(getActivityName $1 | tr "[/]" "[ ]")
|
|
echo $1
|
|
}
|
|
|
|
function startActivityFromPackage {
|
|
if [ "$1" = home ]; then
|
|
doKeyevent HOME
|
|
echo 0
|
|
return 0
|
|
fi
|
|
vout $AM_START_NOWAIT -p "$(getPackageName $1)" -c android.intent.category.LAUNCHER -a android.intent.action.MAIN
|
|
$AM_START_NOWAIT -p "$(getPackageName $1)" -c android.intent.category.LAUNCHER -a android.intent.action.MAIN 2>&1
|
|
echo 0
|
|
}
|
|
|
|
function startActivity {
|
|
if [ "$1" = home ]; then
|
|
doKeyevent HOME
|
|
echo 0
|
|
return 0
|
|
elif [ "$1" = chrome ]; then
|
|
if [ "$DEVICE" = volantis -o "$DEVICE" = ariel ]; then
|
|
vout $AM_START_NOWAIT -p "$(getPackageName $1)" http://www.theverge.com
|
|
$AM_START_NOWAIT -p "$(getPackageName $1)" http://www.theverge.com > /dev/null
|
|
set -- 0 0
|
|
else
|
|
vout $AM_START -p "$(getPackageName $1)" http://www.theverge.com
|
|
set -- $($AM_START -p "$(getPackageName $1)" http://www.theverge.com | grep ThisTime)
|
|
fi
|
|
else
|
|
vout $AM_START "$(getActivityName $1)"
|
|
set -- $($AM_START "$(getActivityName $1)" | grep ThisTime)
|
|
fi
|
|
echo $2 | tr "[\r]" "[\n]"
|
|
}
|
|
|
|
function forceStartActivity {
|
|
if [ "$1" = chrome ]; then
|
|
vout $AM_START -p "$(getPackageName $1)" http://www.theverge.com
|
|
set -- $($AM_FORCE_START -p "$(getPackageName $1)" http://www.theverge.com | grep ThisTime)
|
|
else
|
|
vout $AM_FORCE_START "$(getActivityName $1)"
|
|
set -- $($AM_FORCE_START "$(getActivityName $1)" | grep ThisTime)
|
|
fi
|
|
echo $2 | tr "[\r]" "[\n]"
|
|
}
|
|
|
|
function checkActivity {
|
|
# requires root
|
|
actName="$(getActivityName $1)"
|
|
$AM_LIST | grep $actName
|
|
}
|
|
|
|
#function stopActivity {
|
|
# vout $AM_STOP $(getActivityName $1)
|
|
# $AM_STOP $(getActivityName $1)
|
|
#}
|
|
|
|
function doSwipe {
|
|
vout ${ADB}input swipe $*
|
|
${ADB}nice input swipe $*
|
|
}
|
|
|
|
function doText {
|
|
echo $* > ./tmpOutput
|
|
vout ${ADB}input text \"$*\"
|
|
${ADB}input text "$(cat ./tmpOutput)"
|
|
rm -f ./tmpOutput
|
|
}
|
|
|
|
function doTap {
|
|
vout ${ADB}input tap $*
|
|
${ADB}input tap $*
|
|
}
|
|
|
|
function doKeyevent {
|
|
vout $INPUT keyevent $*
|
|
$INPUT keyevent $*
|
|
}
|
|
|
|
function checkIsRunning {
|
|
p=$1
|
|
shift
|
|
if ! $PS | grep $p | grep -qv grep; then
|
|
handleError $*: $p is not running
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
function checkStartTime {
|
|
vout checkStartTime $1 v $2
|
|
if [ -z "$2" ]; then
|
|
echo false
|
|
return 2
|
|
fi
|
|
if [ "$1" -gt "$2" ]; then
|
|
echo false
|
|
return 1
|
|
fi
|
|
echo true
|
|
return 0
|
|
}
|
|
|
|
function handleError {
|
|
echo Error: $*
|
|
stopAndDumpInstramentation
|
|
if [ $stoponerror -gt 0 ]; then
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
user=root
|
|
if ${ADB}ls /data 2>/dev/null | grep -q "Permission denied"; then
|
|
user=shell
|
|
fi
|
|
vout User is $user
|
|
|
|
if [ $generateActivities -gt 0 ]; then
|
|
if [ $isOnDevice -gt 0 ]; then
|
|
echo Error: cannot generate activity list when run on device
|
|
exit 1
|
|
fi
|
|
echo Generating activities...
|
|
for app in $appList
|
|
do
|
|
startActivityFromPackage $app 2>&1 > /dev/null
|
|
act=$(${ADB}am stack list | grep $(getPackageName $app) | sed -e 's/
|
|
//' | head -1 | awk '{ print $2; }')
|
|
eval "${app}Activity=$act"
|
|
echo "ACTIVITY: $app --> $(getActivityName $app)"
|
|
done
|
|
fi
|
|
|