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