1 # functions and definitions for workload automation scripts
3 # See recentfling.sh, systemapps.sh, and other scripts that use
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"
11 # default activities. Can dynamically generate with -g.
12 gmailActivity='com.google.android.gm/com.google.android.gm.ConversationListActivityGmail'
13 hangoutsActivity='com.google.android.talk/com.google.android.talk.SigningInActivity'
14 chromeActivity='com.android.chrome/_not_used'
15 youtubeActivity='com.google.android.youtube/com.google.android.apps.youtube.app.WatchWhileActivity'
16 cameraActivity='com.google.android.GoogleCamera/com.android.camera.CameraActivity'
17 playActivity='com.android.vending/com.google.android.finsky.activities.MainActivity'
18 feedlyActivity='com.devhd.feedly/com.devhd.feedly.Main'
19 photosActivity='com.google.android.apps.plus/com.google.android.apps.photos.phone.PhotosHomeActivity'
20 mapsActivity='com.google.android.apps.maps/com.google.android.maps.MapsActivity'
21 calendarActivity='com.google.android.calendar/com.android.calendar.AllInOneActivity'
22 earthActivity='com.google.earth/com.google.earth.EarthActivity'
23 calculatorActivity='com.android.calculator2/com.android.calculator2.Calculator'
24 sheetsActivity='com.google.android.apps.docs.editors.sheets/com.google.android.apps.docs.app.NewMainProxyActivity'
25 docsActivity='com.google.android.apps.docs.editors.docs/com.google.android.apps.docs.app.NewMainProxyActivity'
26 operaActivity='com.opera.mini.native/com.opera.mini.android.Browser'
27 firefoxActivity='org.mozilla.firefox/org.mozilla.firefox.App'
28 homeActivity='com.google.android.googlequicksearchbox/com.google.android.launcher.GEL'
31 echo "$0: unrecognized option: $1"
32 echo; echo "Usage: $0 [options]"
33 echo "-e : stop on error"
35 echo "-n : keep trace files"
37 echo "-s device : adb device"
38 echo "-t trace categories"
39 echo "-g : generate activity strings"
48 (-d) DEVICE=$2; shift;;
51 (-t) tracecategories=$2; shift;;
52 (-i) iterations=$2; shift;;
53 (-o) output=$2; shift;;
56 (-s) deviceName=$2; shift;;
57 (-g) generateActivities=1;;
60 chk1=$(functions 2>/dev/null)
61 chk2=$(typeset -F 2>/dev/null)
63 if echo $chk1 $chk2 | grep -q processLocalOption; then
64 if ! processLocalOption "$1" "$2"; then
75 # check if running on a device
76 if ls /etc/* 2>/dev/null | grep -q android.hardware; then
81 # do a throw-away adb in case the server is out-of-date
82 adb devices -l 2>&1 >/dev/null
84 if [ -z "$deviceName" ]; then
85 devInfo=$(adb devices -l | grep -v ^List | head -1)
87 devInfo=$(adb devices -l | grep $deviceName)
91 echo Error: could not find device $deviceName
95 ADB="adb -s $deviceName shell "
96 DEVICE=$(echo $4 | sed 's/product://')
100 # default values if not set by options or calling script
101 appList=${appList:=$dfltAppList}
102 savetmpfiles=${savetmpfiles:=0}
103 stoponerror=${stoponerror:=0}
104 verbose=${verbose:=0}
105 compress=${compress:=1}
106 iterations=${iterations:=5}
107 tracecategories=${tracecategories:=$dflttracecategories}
109 output=${output:="./out"}
111 # clear the output file
115 AM_FORCE_START="${ADB}am start -W -S"
116 AM_START="${ADB}am start -W"
117 AM_START_NOWAIT="${ADB}am start"
118 AM_STOP="${ADB}am force-stop"
119 AM_LIST="${ADB}am stack list"
125 # debug output enabled by -v
126 if [ $verbose -gt 0 ]; then
128 echo DEBUG: $* >&2 >> $output
132 function findtimestamp {
133 # extract timestamp from atrace log entry
134 while [ "$2" != "" -a "$2" != "tracing_mark_write" ]
141 function computeTimeDiff {
142 # Compute time diff given: startSeconds startNs endSeconds endNS
144 # strip leading zeros
145 startS=$(expr 0 + $1)
147 if [ "$2" = N ]; then
151 startNs=$(expr 0 + $2)
155 ((startMs=startS*1000 + startNs/1000000))
156 ((endMs=endS*1000 + endNs/1000000))
157 ((diff=endMs-startMs))
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)
169 ((msec=$1*1000000+msecfield))
174 function 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
181 s=$(grep "Binder.*tracing_mark_write.*launching" $traceout 2>/dev/null | head -1| tr [\(\)\[\]
\r:] " ")
183 s=$(grep activityPause $traceout | head -1 2>/dev/null| tr [\(\)\[\]
\r:] " ")
185 vout $_app was restarted!
189 log2msec $(findtimestamp $s)
193 function getEndTime {
194 # extract event indicating end of start sequence. We use the
195 # first surfaceflinger event associated with the target activity
198 f=$(grep "surfaceflinger.*tracing_mark_write.*$_app" $traceout 2>/dev/null |
199 grep -v Starting | head -1 | tr [\(\)\[\]
\r:] " ")
201 # Hmm. sf symbols may not be there... get the pid
202 pid=$(${ADB}pidof /system/bin/surfaceflinger | tr "[
\r]" "[ ]")
203 f=$(grep " <...>-$pid.*tracing_mark_write.*$_app" $traceout 2>/dev/null |
204 grep -v Starting | head -1 | tr [\(\)\[\]
\r:] " ")
207 log2msec $(findtimestamp $f)
210 function resetJankyFrames {
212 _gfxapp=${app:="com.android.systemui"}
213 ${ADB}dumpsys gfxinfo $_gfxapp reset 2>&1 >/dev/null
216 function getJankyFrames {
218 _gfxapp=${_gfxapp:="com.android.systemui"}
220 # Note: no awk or sed on devices so have to do this
225 ${ADB}dumpsys gfxinfo $_gfxapp | tr "\r" " " | egrep "9[059]th| frames" | while read line
227 if echo $line | grep -q "Total frames"; then
230 elif echo $line | grep -q "Janky frames"; then
233 elif echo $line | grep -q "90th"; then
234 set -- $(echo $line | tr m " ")
236 elif echo $line | grep -q "95th"; then
237 set -- $(echo $line | tr m " ")
239 elif echo $line | grep -q "99th"; then
240 set -- $(echo $line | tr m " ")
242 echo $total $janky $l90 $l95 $l99
248 function checkForDirectReclaim {
249 # look for any reclaim events in atrace output
252 if grep -qi reclaim $traceout; then
258 function startInstramentation {
259 # Called at beginning of loop. Turn on instramentation like atrace
260 vout start instramentation $(date)
261 echo =============================== >> $output
262 echo Before iteration >> $output
263 echo =============================== >> $output
264 ${ADB}cat /proc/meminfo 2>&1 >> $output
265 ${ADB}dumpsys meminfo 2>&1 >> $output
266 if [ "$user" = root ]; then
267 vout ${ADB}atrace -b 32768 --async_start $tracecategories
268 ${ADB}atrace -b 32768 --async_start $tracecategories >> $output
273 function stopInstramentation {
274 if [ "$user" = root ]; then
275 vout ${ADB}atrace --async_stop
276 ${ADB}atrace --async_stop > /dev/null
280 function stopAndDumpInstramentation {
281 # Called at beginning of loop. Turn on instramentation like atrace
282 vout stop instramentation $(date)
283 echo =============================== >> $output
284 echo After iteration >> $output
285 echo =============================== >> $output
286 ${ADB}cat /proc/meminfo 2>&1 >> $output
287 ${ADB}dumpsys meminfo 2>&1 >> $output
288 if [ "$user" = root ]; then
290 traceout=${traceout:=$output}
291 echo =============================== >> $traceout
292 echo TRACE >> $traceout
293 echo =============================== >> $traceout
294 if [ $compress -gt 0 ]; then
295 tmpTrace=./tmptrace.$$
296 UNCOMPRESS=$CMDDIR/atrace-uncompress.py
299 ${ADB}atrace -z -b 32768 --async_dump >> $tmpTrace
300 python $UNCOMPRESS $tmpTrace >> $traceout
303 ${ADB}atrace $zarg -b 32768 --async_dump >> $traceout
305 vout ${ADB}atrace $zarg --async_dump
306 vout ${ADB}atrace --async_stop
307 ${ADB}atrace --async_stop > /dev/null
311 function getActivityName {
312 cmd="actName=\$${1}Activity"
317 function getPackageName {
318 set -- $(getActivityName $1 | tr "[/]" "[ ]")
322 function startActivityFromPackage {
323 if [ "$1" = home ]; then
328 vout $AM_START_NOWAIT -p "$(getPackageName $1)" -c android.intent.category.LAUNCHER -a android.intent.action.MAIN
329 $AM_START_NOWAIT -p "$(getPackageName $1)" -c android.intent.category.LAUNCHER -a android.intent.action.MAIN 2>&1
333 function startActivity {
334 if [ "$1" = home ]; then
338 elif [ "$1" = chrome ]; then
339 if [ "$DEVICE" = volantis ]; then
340 vout $AM_START_NOWAIT -p "$(getPackageName $1)" http://www.theverge.com
341 $AM_START_NOWAIT -p "$(getPackageName $1)" http://www.theverge.com > /dev/null
344 vout $AM_START -p "$(getPackageName $1)" http://www.theverge.com
345 set -- $($AM_START -p "$(getPackageName $1)" http://www.theverge.com | grep ThisTime)
348 vout $AM_START "$(getActivityName $1)"
349 set -- $($AM_START "$(getActivityName $1)" | grep ThisTime)
351 echo $2 | tr "[\r]" "[\n]"
354 function forceStartActivity {
355 if [ "$1" = chrome ]; then
356 vout $AM_START -p "$(getPackageName $1)" http://www.theverge.com
357 set -- $($AM_FORCE_START -p "$(getPackageName $1)" http://www.theverge.com | grep ThisTime)
359 vout $AM_FORCE_START "$(getActivityName $1)"
360 set -- $($AM_FORCE_START "$(getActivityName $1)" | grep ThisTime)
362 echo $2 | tr "[\r]" "[\n]"
365 function checkActivity {
367 actName="$(getActivityName $1)"
368 $AM_LIST | grep $actName
371 #function stopActivity {
372 # vout $AM_STOP $(getActivityName $1)
373 # $AM_STOP $(getActivityName $1)
377 vout ${ADB}input swipe $*
382 vout ${ADB}input tap $*
386 function doKeyevent {
387 vout $INPUT keyevent $*
391 function checkIsRunning {
394 if ! $PS | grep $p | grep -qv grep; then
395 handleError $*: $p is not running
400 function checkStartTime {
401 vout checkStartTime $1 v $2
406 if [ "$1" -gt "$2" ]; then
414 function handleError {
416 stopAndDumpInstramentation
417 if [ $stoponerror -gt 0 ]; then
423 if ${ADB}ls /data 2>/dev/null | grep -q "Permission denied"; then
428 if [ $generateActivities -gt 0 ]; then
429 if [ $isOnDevice -gt 0 ]; then
430 echo Error: cannot generate activity list when run on device
433 echo Generating activities...
436 startActivityFromPackage $app 2>&1 > /dev/null
437 act=$(${ADB}am stack list | grep $(getPackageName $app) | sed -e 's/
\r//' | head -1 | awk '{ print $2; }')
438 eval "${app}Activity=$act"
439 echo "ACTIVITY: $app --> $(getActivityName $app)"