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.
478 lines
12 KiB
478 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
|
|
|