Home | History | Annotate | Download | only in workloads
      1 # functions and definitions for workload automation scripts
      2 #
      3 # See recentfling.sh, systemapps.sh, and other scripts that use
      4 # these definitions.
      5 #
      6 
      7 dflttracecategories="gfx input view am rs power sched freq idle load memreclaim"
      8 dfltAppList="gmail hangouts chrome youtube camera photos play maps calendar earth calculator sheets docs home"
      9 generateActivities=0
     10 
     11 # default activities. Can dynamically generate with -g.
     12 gmailActivity='com.google.android.gm/com.google.android.gm.ConversationListActivityGmail'
     13 clockActivity='com.google.android.deskclock/com.android.deskclock.DeskClock'
     14 hangoutsActivity='com.google.android.talk/com.google.android.talk.SigningInActivity'
     15 chromeActivity='com.android.chrome/_not_used'
     16 contactsActivity='com.google.android.contacts/com.android.contacts.activities.PeopleActivity'
     17 youtubeActivity='com.google.android.youtube/com.google.android.apps.youtube.app.WatchWhileActivity'
     18 cameraActivity='com.google.android.GoogleCamera/com.android.camera.CameraActivity'
     19 playActivity='com.android.vending/com.google.android.finsky.activities.MainActivity'
     20 feedlyActivity='com.devhd.feedly/com.devhd.feedly.Main'
     21 photosActivity='com.google.android.apps.photos/com.google.android.apps.photos.home.HomeActivity'
     22 mapsActivity='com.google.android.apps.maps/com.google.android.maps.MapsActivity'
     23 calendarActivity='com.google.android.calendar/com.android.calendar.AllInOneActivity'
     24 earthActivity='com.google.earth/com.google.earth.EarthActivity'
     25 calculatorActivity='com.google.android.calculator/com.android.calculator2.Calculator'
     26 calculatorLActivity='com.android.calculator2/com.android.calculator2.Calculator'
     27 sheetsActivity='com.google.android.apps.docs.editors.sheets/com.google.android.apps.docs.app.NewMainProxyActivity'
     28 docsActivity='com.google.android.apps.docs.editors.docs/com.google.android.apps.docs.app.NewMainProxyActivity'
     29 operaActivity='com.opera.mini.native/com.opera.mini.android.Browser'
     30 firefoxActivity='org.mozilla.firefox/org.mozilla.firefox.App'
     31 suntempleActivity='com.BrueComputing.SunTemple/com.epicgames.ue4.GameActivity'
     32 homeActivity='com.google.android.googlequicksearchbox/com.google.android.launcher.GEL'
     33 
     34 function showUsage {
     35 	echo "$0: unrecognized option: $1"
     36 	echo; echo "Usage: $0 [options]"
     37 	echo "-e : stop on error"
     38 	echo "-i iterations"
     39 	echo "-n : keep trace files"
     40 	echo "-o output file"
     41 	echo "-s device : adb device"
     42 	echo "-t trace categories"
     43 	echo "-g : generate activity strings"
     44 }
     45 
     46 DEVICE=unknown
     47 
     48 # handle args
     49 while [ $# -gt 0 ]
     50 do
     51 	case "$1" in
     52 	(-d) DEVICE=$2; shift;;
     53 	(-e) stoponerror=1;;
     54 	(-n) savetmpfiles=1;;
     55 	(-t) tracecategories=$2; shift;;
     56 	(-i) iterations=$2; shift;;
     57 	(-o) output=$2; shift;;
     58 	(-v) verbose=1;;
     59 	(-nz) compress=0;;
     60 	(-s) deviceName=$2; shift;;
     61 	(-g) generateActivities=1;;
     62 	(--) ;;
     63 	(*)
     64 		chk1=$(functions 2>/dev/null)
     65 		chk2=$(typeset -F 2>/dev/null)
     66 
     67 		if echo $chk1 $chk2 | grep -q processLocalOption; then
     68 			if ! processLocalOption "$1" "$2"; then
     69 				shift
     70 			fi
     71 		else
     72 			showUsage $1
     73 			exit 1
     74 		fi;;
     75 	esac
     76 	shift
     77 done
     78 
     79 # check if running on a device
     80 if ls /etc/* 2>/dev/null | grep -q android.hardware; then
     81 	ADB=""
     82 	compress=0
     83 	isOnDevice=1
     84 else
     85 	# do a throw-away adb in case the server is out-of-date
     86 	adb devices -l 2>&1 >/dev/null
     87 
     88 	if [ -z "$deviceName" ]; then
     89 		devInfo=$(adb devices -l | grep -v ^List | head -1)
     90 	else
     91 		devInfo=$(adb devices -l | grep $deviceName)
     92 	fi
     93 	set -- $devInfo
     94 	if [ -z $1 ]; then
     95 		echo Error: could not find device $deviceName
     96 		exit 1
     97 	fi
     98 	deviceName=$1
     99 	ADB="adb -s $deviceName shell "
    100 	if [ "$DEVICE" = "" -o "$DEVICE" = unknown ]; then
    101 		DEVICE=$(echo $4 | sed 's/product://')
    102 	fi
    103 	isOnDevice=0
    104 fi
    105 
    106 if [ $isOnDevice -gt 0 ]; then
    107 	case "$DEVICE" in
    108 	(bullhead|angler)
    109 		if ! echo $$ > /dev/cpuset/background/tasks; then
    110 			echo Could not put PID $$ in background
    111 		fi
    112 		;;
    113 	(*)
    114 		;;
    115 	esac
    116 fi
    117 
    118 # default values if not set by options or calling script
    119 appList=${appList:=$dfltAppList}
    120 savetmpfiles=${savetmpfiles:=0}
    121 stoponerror=${stoponerror:=0}
    122 verbose=${verbose:=0}
    123 compress=${compress:=1}
    124 iterations=${iterations:=5}
    125 tracecategories=${tracecategories:=$dflttracecategories}
    126 ADB=${ADB:=""}
    127 output=${output:="./out"}
    128 
    129 # clear the output file
    130 if [ -f $output ]; then
    131 	> $output
    132 fi
    133 
    134 # ADB commands
    135 AM_FORCE_START="${ADB}am start -W -S"
    136 AM_START="${ADB}am start -W"
    137 AM_START_NOWAIT="${ADB}am start"
    138 AM_STOP="${ADB}am force-stop"
    139 AM_LIST="${ADB}am stack list"
    140 WHO="${ADB}whoami"
    141 INPUT="${ADB}input"
    142 PS="${ADB}ps"
    143 
    144 function vout {
    145 	# debug output enabled by -v
    146 	if [ $verbose -gt 0 ]; then
    147 	    echo DEBUG: $* >&2
    148 	    echo DEBUG: $* >&2 >> $output
    149 	fi
    150 }
    151 
    152 function findtimestamp {
    153 	# extract timestamp from atrace log entry
    154 	while [ "$2" != "" -a "$2" != "tracing_mark_write" ]
    155 	do
    156 		shift
    157 	done
    158 	echo $1
    159 }
    160 
    161 function computeTimeDiff {
    162 	# Compute time diff given: startSeconds startNs endSeconds endNS
    163 
    164 	# strip leading zeros
    165 	startS=$(expr 0 + $1)
    166 	endS=$(expr 0 + $3)
    167 	if [ "$2" = N ]; then
    168 		startNs=0
    169 		endNs=0
    170 	else
    171 		startNs=$(expr 0 + $2)
    172 		endNs=$(expr 0 + $4)
    173 	fi
    174 
    175 	((startMs=startS*1000 + startNs/1000000))
    176 	((endMs=endS*1000 + endNs/1000000))
    177 	((diff=endMs-startMs))
    178 	echo $diff
    179 }
    180 
    181 function log2msec {
    182 	in=$1
    183 	in=${in:=0.0}
    184 	set -- $(echo $in | tr . " ")
    185 
    186 	# shell addition via (( )) doesn't like leading zeroes in msecs
    187 	# field so remove leading zeroes
    188 	msecfield=$(expr 0 + $2)
    189 
    190 	((msec=$1*1000000+msecfield))
    191 	((msec=msec/1000))
    192 	echo $msec
    193 }
    194 
    195 function getStartTime {
    196 	# extract event indicating beginning of start sequence
    197 	# a) look for a "launching" event indicating start from scratch
    198 	# b) look for another activity getting a pause event
    199 	_app=$1
    200 	traceout=$2
    201 	ret=0
    202 	s=$(grep "Binder.*tracing_mark_write.*launching" $traceout 2>/dev/null | head -1| tr [\(\)\[\]
:] " ")
    204 	if [ -z "$s" ]; then
    205 		s=$(grep activityPause $traceout | head -1 2>/dev/null| tr [\(\)\[\]
:] " ")
    207 	else
    208 		vout $_app was restarted!
    209 		ret=1
    210 	fi
    211 	vout STARTLOG: $s
    212 	log2msec $(findtimestamp $s)
    213 	return $ret
    214 }
    215 
    216 function getEndTime {
    217 	# extract event indicating end of start sequence. We use the
    218 	# first surfaceflinger event associated with the target activity
    219 	_app=$1
    220 	traceout=$2
    221 	f=$(grep "surfaceflinger.*tracing_mark_write.*$_app" $traceout 2>/dev/null |
    222 		grep -v Starting | head -1 | tr [\(\)\[\]
:] " ")
    224 	if [ -z "$f" ]; then
    225 		# Hmm. sf symbols may not be there... get the pid
    226 		pid=$(${ADB}pidof /system/bin/surfaceflinger | tr "[
]" "[ ]")
    228 		f=$(grep "           <...>-$pid.*tracing_mark_write.*$_app" $traceout 2>/dev/null |
    229 			grep -v Starting | head -1 | tr [\(\)\[\]
:] " ")
    231 	fi
    232 	vout ENDLOG: $f
    233 	log2msec $(findtimestamp $f)
    234 }
    235 
    236 function resetJankyFrames {
    237 	_gfxapp=$1
    238 	_gfxapp=${_gfxapp:="com.android.systemui"}
    239 	${ADB}dumpsys gfxinfo $_gfxapp reset 2>&1 >/dev/null
    240 }
    241 
    242 function getJankyFrames {
    243 	_gfxapp=$1
    244 	_gfxapp=${_gfxapp:="com.android.systemui"}
    245 
    246 	# Note: no awk or sed on devices so have to do this
    247 	# purely with bash
    248 	total=0
    249 	janky=0
    250 	latency=0
    251 	${ADB}dumpsys gfxinfo $_gfxapp | tr "\r" " " | egrep "9[059]th| frames" | while read line
    252 	do
    253 		if echo $line | grep -q "Total frames"; then
    254 			set -- $line
    255 			total=$4
    256 		elif echo $line | grep -q "Janky frames"; then
    257 			set -- $line
    258 			janky=$3
    259 		elif echo $line | grep -q "90th"; then
    260 			set -- $(echo $line | tr m " ")
    261 			l90=$3
    262 		elif echo $line | grep -q "95th"; then
    263 			set -- $(echo $line | tr m " ")
    264 			l95=$3
    265 		elif echo $line | grep -q "99th"; then
    266 			set -- $(echo $line | tr m " ")
    267 			l99=$3
    268 			echo $total $janky $l90 $l95 $l99
    269 			break
    270 		fi
    271 	done
    272 }
    273 
    274 function checkForDirectReclaim {
    275 	# look for any reclaim events in atrace output
    276 	_app=$1
    277 	traceout=$2
    278 	if grep -qi reclaim $traceout; then
    279 	   return 1
    280 	fi
    281 	return 0
    282 }
    283 
    284 function startInstramentation {
    285 	_iter=$1
    286 	_iter=${_iter:=0}
    287 	enableAtrace=$2
    288 	enableAtrace=${enableAtrace:=1}
    289 	# Called at beginning of loop. Turn on instramentation like atrace
    290 	vout start instramentation $(date)
    291 	echo =============================== >> $output
    292 	echo Before iteration $_iter >> $output
    293 	echo =============================== >> $output
    294 	${ADB}cat /proc/meminfo 2>&1 >> $output
    295 	${ADB}dumpsys meminfo 2>&1 >> $output
    296 	if [ "$DEVICE" = volantis ]; then
    297 		${ADB}cat /d/nvmap/iovmm/procrank 2>&1 >> $output
    298 	fi
    299 	if [ "$user" = root -a $enableAtrace -gt 0 ]; then
    300 		vout ${ADB}atrace -b 32768 --async_start $tracecategories
    301 		${ADB}atrace -b 32768 --async_start $tracecategories >> $output
    302 		echo >> $output
    303 	fi
    304 }
    305 
    306 function stopInstramentation {
    307 	enableAtrace=$1
    308 	enableAtrace=${enableAtrace:=1}
    309 	if [ "$user" = root -a $enableAtrace -gt 0 ]; then
    310 		vout ${ADB}atrace --async_stop
    311 		${ADB}atrace --async_stop > /dev/null
    312 	fi
    313 }
    314 
    315 function stopAndDumpInstramentation {
    316 	vout stop instramentation $(date)
    317 	echo =============================== >> $output
    318 	echo After iteration >> $output
    319 	echo =============================== >> $output
    320 	${ADB}cat /proc/meminfo 2>&1 >> $output
    321 	${ADB}dumpsys meminfo 2>&1 >> $output
    322 	if [ "$user" = root ]; then
    323 		traceout=$1
    324 		traceout=${traceout:=$output}
    325 		echo =============================== >> $traceout
    326 		echo TRACE >> $traceout
    327 		echo =============================== >> $traceout
    328 		if [ $compress -gt 0 ]; then
    329 			tmpTrace=./tmptrace.$$
    330 			UNCOMPRESS=$CMDDIR/atrace-uncompress.py
    331 			> $tmpTrace
    332 			zarg="-z"
    333 			${ADB}atrace -z -b 32768 --async_dump >> $tmpTrace
    334 			python $UNCOMPRESS $tmpTrace >> $traceout
    335 			rm -f $tmpTrace
    336 		else
    337 			${ADB}atrace -b 32768 --async_dump > $traceout
    338 		fi
    339 		vout ${ADB}atrace $zarg -b 32768 --async_dump
    340 		vout ${ADB}atrace --async_stop
    341 		${ADB}atrace --async_stop > /dev/null
    342 	fi
    343 }
    344 
    345 function getActivityName {
    346 	cmd="actName=\$${1}Activity"
    347 	eval $cmd
    348 	echo $actName
    349 }
    350 
    351 function getPackageName {
    352 	set -- $(getActivityName $1 | tr "[/]" "[ ]")
    353 	echo $1
    354 }
    355 
    356 function startActivityFromPackage {
    357 	if [ "$1" = home ]; then
    358 		doKeyevent HOME
    359 		echo 0
    360 		return 0
    361 	fi
    362 	vout $AM_START_NOWAIT -p "$(getPackageName $1)" -c android.intent.category.LAUNCHER -a android.intent.action.MAIN
    363 	$AM_START_NOWAIT -p "$(getPackageName $1)" -c android.intent.category.LAUNCHER -a android.intent.action.MAIN 2>&1
    364 	echo 0
    365 }
    366 
    367 function startActivity {
    368 	if [ "$1" = home ]; then
    369 		doKeyevent HOME
    370 		echo 0
    371 		return 0
    372 	elif [ "$1" = chrome ]; then
    373 		if [ "$DEVICE" = volantis -o "$DEVICE" = ariel ]; then
    374 			vout $AM_START_NOWAIT -p "$(getPackageName $1)" http://www.theverge.com
    375 			$AM_START_NOWAIT -p "$(getPackageName $1)" http://www.theverge.com > /dev/null
    376 			set -- 0 0
    377 		else
    378 			vout $AM_START -p "$(getPackageName $1)" http://www.theverge.com
    379 			set -- $($AM_START -p "$(getPackageName $1)" http://www.theverge.com | grep ThisTime)
    380 		fi
    381 	else
    382 		vout $AM_START "$(getActivityName $1)"
    383 		set -- $($AM_START "$(getActivityName $1)" | grep ThisTime)
    384 	fi
    385 	echo $2 | tr "[\r]" "[\n]"
    386 }
    387 
    388 function forceStartActivity {
    389 	if [ "$1" = chrome ]; then
    390 		vout $AM_START -p "$(getPackageName $1)" http://www.theverge.com
    391 		set -- $($AM_FORCE_START -p "$(getPackageName $1)" http://www.theverge.com | grep ThisTime)
    392 	else
    393 		vout $AM_FORCE_START "$(getActivityName $1)"
    394 		set -- $($AM_FORCE_START "$(getActivityName $1)" | grep ThisTime)
    395 	fi
    396 	echo $2 | tr "[\r]" "[\n]"
    397 }
    398 
    399 function checkActivity {
    400 	# requires root
    401 	actName="$(getActivityName $1)"
    402 	$AM_LIST | grep $actName
    403 }
    404 
    405 #function stopActivity {
    406 #    vout $AM_STOP $(getActivityName $1)
    407 #    $AM_STOP $(getActivityName $1)
    408 #}
    409 
    410 function doSwipe {
    411 	vout ${ADB}input swipe $*
    412 	${ADB}nice input swipe $*
    413 }
    414 
    415 function doText {
    416 	echo $* > ./tmpOutput
    417 	vout ${ADB}input text \"$*\"
    418 	${ADB}input text "$(cat ./tmpOutput)"
    419 	rm -f ./tmpOutput
    420 }
    421 
    422 function doTap {
    423 	vout ${ADB}input tap $*
    424 	${ADB}input tap $*
    425 }
    426 
    427 function doKeyevent {
    428 	vout $INPUT keyevent $*
    429 	$INPUT keyevent $*
    430 }
    431 
    432 function checkIsRunning {
    433 	p=$1
    434 	shift
    435 	if ! $PS | grep $p | grep -qv grep; then
    436 	   handleError $*: $p is not running
    437 	   exit 1
    438 	fi
    439 }
    440 
    441 function checkStartTime {
    442 	vout checkStartTime $1 v $2
    443 	if [ -z "$2" ]; then
    444 	    echo false
    445 	    return 2
    446 	fi
    447 	if [ "$1" -gt "$2" ]; then
    448 	    echo false
    449 	    return 1
    450 	fi
    451 	echo true
    452 	return 0
    453 }
    454 
    455 function handleError {
    456 	echo Error: $*
    457 	stopAndDumpInstramentation
    458 	if [ $stoponerror -gt 0 ]; then
    459 		exit 1
    460 	fi
    461 }
    462 
    463 user=root
    464 if ${ADB}ls /data 2>/dev/null | grep -q "Permission denied"; then
    465 	user=shell
    466 fi
    467 vout User is $user
    468 
    469 if [ $generateActivities -gt 0  ]; then
    470 	if [ $isOnDevice -gt 0 ]; then
    471 		echo Error: cannot generate activity list when run on device
    472 		exit 1
    473 	fi
    474 	echo Generating activities...
    475 	for app in $appList
    476 	do
    477 		startActivityFromPackage $app 2>&1 > /dev/null
    478 		act=$(${ADB}am stack list | grep $(getPackageName $app) | sed -e 's/
//' | head -1 | awk '{ print $2; }')
    480 		eval "${app}Activity=$act"
    481 		echo "ACTIVITY: $app --> $(getActivityName $app)"
    482 	done
    483 fi
    484 
    485