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 7dflttracecategories="gfx input view am rs power sched freq idle load memreclaim" 8dfltAppList="gmail hangouts chrome youtube camera photos play maps calendar earth calculator sheets docs home" 9generateActivities=0 10 11# default activities. Can dynamically generate with -g. 12gmailActivity='com.google.android.gm/com.google.android.gm.ConversationListActivityGmail' 13clockActivity='com.google.android.deskclock/com.android.deskclock.DeskClock' 14hangoutsActivity='com.google.android.talk/com.google.android.talk.SigningInActivity' 15chromeActivity='com.android.chrome/_not_used' 16contactsActivity='com.google.android.contacts/com.android.contacts.activities.PeopleActivity' 17youtubeActivity='com.google.android.youtube/com.google.android.apps.youtube.app.WatchWhileActivity' 18cameraActivity='com.google.android.GoogleCamera/com.android.camera.CameraActivity' 19playActivity='com.android.vending/com.google.android.finsky.activities.MainActivity' 20feedlyActivity='com.devhd.feedly/com.devhd.feedly.Main' 21photosActivity='com.google.android.apps.photos/com.google.android.apps.photos.home.HomeActivity' 22mapsActivity='com.google.android.apps.maps/com.google.android.maps.MapsActivity' 23calendarActivity='com.google.android.calendar/com.android.calendar.AllInOneActivity' 24earthActivity='com.google.earth/com.google.earth.EarthActivity' 25calculatorActivity='com.google.android.calculator/com.android.calculator2.Calculator' 26calculatorLActivity='com.android.calculator2/com.android.calculator2.Calculator' 27sheetsActivity='com.google.android.apps.docs.editors.sheets/com.google.android.apps.docs.app.NewMainProxyActivity' 28docsActivity='com.google.android.apps.docs.editors.docs/com.google.android.apps.docs.app.NewMainProxyActivity' 29operaActivity='com.opera.mini.native/com.opera.mini.android.Browser' 30firefoxActivity='org.mozilla.firefox/org.mozilla.firefox.App' 31suntempleActivity='com.BrueComputing.SunTemple/com.epicgames.ue4.GameActivity' 32homeActivity='com.google.android.googlequicksearchbox/com.google.android.launcher.GEL' 33 34function 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 46DEVICE=unknown 47 48# handle args 49while [ $# -gt 0 ] 50do 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 77done 78 79# check if running on a device 80if ls /etc/* 2>/dev/null | grep -q android.hardware; then 81 ADB="" 82 compress=0 83 isOnDevice=1 84else 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 104fi 105 106if [ $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 116fi 117 118# default values if not set by options or calling script 119appList=${appList:=$dfltAppList} 120savetmpfiles=${savetmpfiles:=0} 121stoponerror=${stoponerror:=0} 122verbose=${verbose:=0} 123compress=${compress:=1} 124iterations=${iterations:=5} 125tracecategories=${tracecategories:=$dflttracecategories} 126ADB=${ADB:=""} 127output=${output:="./out"} 128 129# clear the output file 130if [ -f $output ]; then 131 > $output 132fi 133 134# ADB commands 135AM_FORCE_START="${ADB}am start -W -S" 136AM_START="${ADB}am start -W" 137AM_START_NOWAIT="${ADB}am start" 138AM_STOP="${ADB}am force-stop" 139AM_LIST="${ADB}am stack list" 140WHO="${ADB}whoami" 141INPUT="${ADB}input" 142PS="${ADB}ps" 143 144function 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 152function 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 161function 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 181function 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 195function 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 [\(\)\[\] 203:] " ") 204 if [ -z "$s" ]; then 205 s=$(grep activityPause $traceout | head -1 2>/dev/null| tr [\(\)\[\] 206:] " ") 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 216function 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 [\(\)\[\] 223:] " ") 224 if [ -z "$f" ]; then 225 # Hmm. sf symbols may not be there... get the pid 226 pid=$(${ADB}pidof /system/bin/surfaceflinger | tr "[ 227]" "[ ]") 228 f=$(grep " <...>-$pid.*tracing_mark_write.*$_app" $traceout 2>/dev/null | 229 grep -v Starting | head -1 | tr [\(\)\[\] 230:] " ") 231 fi 232 vout ENDLOG: $f 233 log2msec $(findtimestamp $f) 234} 235 236function resetJankyFrames { 237 _gfxapp=$1 238 _gfxapp=${_gfxapp:="com.android.systemui"} 239 ${ADB}dumpsys gfxinfo $_gfxapp reset 2>&1 >/dev/null 240} 241 242function 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 274function 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 284function 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 306function 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 315function 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 345function getActivityName { 346 cmd="actName=\$${1}Activity" 347 eval $cmd 348 echo $actName 349} 350 351function getPackageName { 352 set -- $(getActivityName $1 | tr "[/]" "[ ]") 353 echo $1 354} 355 356function 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 367function 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 388function 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 399function 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 410function doSwipe { 411 vout ${ADB}input swipe $* 412 ${ADB}nice input swipe $* 413} 414 415function doText { 416 echo $* > ./tmpOutput 417 vout ${ADB}input text \"$*\" 418 ${ADB}input text "$(cat ./tmpOutput)" 419 rm -f ./tmpOutput 420} 421 422function doTap { 423 vout ${ADB}input tap $* 424 ${ADB}input tap $* 425} 426 427function doKeyevent { 428 vout $INPUT keyevent $* 429 $INPUT keyevent $* 430} 431 432function 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 441function 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 455function handleError { 456 echo Error: $* 457 stopAndDumpInstramentation 458 if [ $stoponerror -gt 0 ]; then 459 exit 1 460 fi 461} 462 463user=root 464if ${ADB}ls /data 2>/dev/null | grep -q "Permission denied"; then 465 user=shell 466fi 467vout User is $user 468 469if [ $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/ 479//' | head -1 | awk '{ print $2; }') 480 eval "${app}Activity=$act" 481 echo "ACTIVITY: $app --> $(getActivityName $app)" 482 done 483fi 484 485