1#!/bin/sh
2
3parseoptions() {
4    verbose=false
5    user_experience=false
6    little_cores_off=false
7    iterations=0
8    pagecached=false
9
10    while [ $# -gt 1 ]
11    do
12	case $1 in
13	    -a)
14		;;
15	    -b)
16		little_cores_off=true
17		;;
18	    -c)
19		pagecached=true
20		;;
21	    -h)
22		usage
23		;;
24	    -u)
25		user_experience=true
26		;;
27	    -v)
28		verbose=true
29		;;
30	    *)
31		usage
32		;;
33	    esac
34	shift
35    done
36
37    iterations=$1
38    if [ $iterations -lt 100 ]; then
39	usage
40    fi
41}
42
43getstats () {
44    infile=$1
45    app=$2
46    echo "Data for $app :"
47
48    # Activity Manager reports ThisTime and TotalTime. TotalTime seems to be
49    # a more measure of the launch from the users perspective. So using TotalTime
50    # as our metric for launch latency
51
52    # From Activity Manager
53    echo "Launch Time (TotalTime) :"
54    fgrep TotalTime $infile | awk '{print $2}' | computestats
55
56    # Data from simpleperf
57    echo "cpu-cycles :"
58    fgrep cpu-cycles $infile | awk '{print $1}' | sed s/,//g | computestats
59
60    # CPU util% Data from /proc/stat
61    echo "cpu-util% :"
62    fgrep 'Total CPU util' $infile | awk '{print $5}' | computestatsf
63    echo "user-cpu-util% :"
64    fgrep 'User CPU util' $infile | awk '{print $5}' | computestatsf
65    echo "sys-cpu-util% (incl hardirq/softirq) :"
66    fgrep 'Sys CPU util' $infile | awk '{print $5}' | computestatsf
67
68    if [ $verbose == true ]; then
69	echo "instructions : "
70	fgrep instructions $infile | awk '{print $1}' | sed s/,//g | computestats
71
72	echo "cycles per instruction : "
73	fgrep instructions $infile | awk '{print $4}' | sed s/,//g | computestatsf
74
75	echo "branch-misses : "
76	fgrep branch-misses $infile | awk '{print $1}' | sed s/,//g | computestats
77
78	echo "context-switches : "
79	fgrep context-switches $infile | awk '{print $1}' | sed s/,//g | computestats
80
81	echo "page-faults : "
82	fgrep page-faults $infile | awk '{print $1}' | sed s/,//g | computestats
83    fi
84
85    if [ $system_bdev_set == true ]; then
86	# (Storage) Data from /proc we've collected
87	echo "KB read for $system_block_device blkdev :"
88	fgrep KB $infile | grep system | awk '{print $5}' | computestats
89
90	echo "iowait% :"
91	fgrep IOwait $infile | awk '{print $3}' | computestatsf
92
93	echo "Device util% for $system_block_device blkdev :"
94	fgrep 'Device util' $infile | awk '{print $4}' | computestatsf
95    fi
96}
97
98cpufreq_volantis() {
99    echo "Setting Governor to performance"
100    if [ $little_cores_off == true ]; then
101        echo "Cannot turn off Little cores on $model"
102        exit 1
103    fi
104    i=0
105    num_cores=2
106    while [ $i -lt  $num_cores ]
107    do
108        adb shell "echo performance  > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_g\
109overnor"
110        adb shell "echo 2499000 > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_max_fr\
111eq"
112        i=`expr $i + 1`
113    done
114    # Lock the GPU frequencies
115    echo -n 852000000 > /d/clock/override.gbus/rate
116    echo -n 1 > /d/clock/override.gbus/state
117}
118
119cpufreq_fugu() {
120    echo "Setting Governor to performance"
121    if [ $little_cores_off == true ]; then
122	echo "Cannot turn off Little cores on $model"
123	exit 1
124    fi
125    i=0
126    num_cores=4
127    while [ $i -lt  $num_cores ]
128    do
129	adb shell "echo performance  > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_governor"
130	adb shell "echo 1833000 > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_max_freq"
131	i=`expr $i + 1`
132    done
133}
134
135cpufreq_marlin_sailfish () {
136    echo "Setting Governor to performance"
137    # GPU Governor and Frequency
138    adb shell 'echo performance > /sys/class/kgsl/kgsl-3d0/devfreq/governor'
139    adb shell 'echo 624000000 > /sys/class/kgsl/kgsl-3d0/devfreq/max_freq'
140    if [ $little_cores_off == true ]; then
141	# Disable Little Cores, force app to run on big cores
142	echo "Disabling Little Cores"
143	adb shell 'echo 0 > /sys/devices/system/cpu/cpu0/online'
144	adb shell 'echo 0 > /sys/devices/system/cpu/cpu1/online'
145    else
146	echo "Enabling All Cores"
147	adb shell 'echo 1 > /sys/devices/system/cpu/cpu0/online'
148	adb shell 'echo 1 > /sys/devices/system/cpu/cpu1/online'
149	adb shell 'echo performance > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor'
150	adb shell 'echo 1996800 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq'
151	# cpu1 needed ?
152	adb shell 'echo performance > /sys/devices/system/cpu/cpu1/cpufreq/scaling_governor'
153	adb shell 'echo 1996800 > /sys/devices/system/cpu/cpu1/cpufreq/scaling_max_freq'
154    fi
155    # Set Governor to performance, up scaling_max_frequency to highest
156    adb shell 'echo performance  > /sys/devices/system/cpu/cpu2/cpufreq/scaling_governor'
157    # Only necessary to set max_freq on cpu2, cpu3 is in same cluster and will
158    # automatically get the same settings
159    adb shell 'echo 2150400 > /sys/devices/system/cpu/cpu2/cpufreq/scaling_max_freq'
160}
161
162cpufreq_angler () {
163    echo "Setting Governor and Frequency"
164    # GPU Governor and Frequency
165    adb shell "echo performance > /sys/class/kgsl/kgsl-3d0/devfreq/governor"
166    adb shell "echo 0 > /sys/class/kgsl/kgsl-3d0/bus_split"
167    adb shell "echo 1 > /sys/class/kgsl/kgsl-3d0/force_clk_on"
168    adb shell "echo 10000 > /sys/class/kgsl/kgsl-3d0/idle_timer"
169    if [ $little_cores_off == true ]; then
170	# Disable Little Cores, force app to run on big cores
171	echo "Disabling Little Cores"
172	i=0
173	num_cores=4
174	while [ $i -lt $num_cores ]
175	do
176	    adb shell "echo 0 > /sys/devices/system/cpu/cpu$i/online"
177	    i=`expr $i + 1`
178	done
179    else
180	echo "Enabling All Cores"
181	# Enable Little cores here, set governor to performance
182	# Lock frequency of little cores
183	i=0
184	num_cores=4
185	while [ $i -lt $num_cores ]
186	do
187	    adb shell "echo 1 > /sys/devices/system/cpu/cpu$i/online"
188	    adb shell "echo performance > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_governor"
189	    # Lock frequency of little cores
190	    adb shell "echo 1555200 > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_max_freq"
191	    i=`expr $i + 1`
192	done
193    fi
194    i=4
195    num_cores=8
196    while [ $i -lt $num_cores ]
197    do
198	adb shell "echo performance > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_governor"
199	# Lock frequency of big cores
200	adb shell "echo 1958400 > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_max_freq"
201	i=`expr $i + 1`
202    done
203}
204
205#
206# This strange bit of logic is needed to get the underlying block devices for /system
207# for Marlin/Sailfish
208#
209get_marlin_sailfish_devnames () {
210    # This bit of code required to get the block dev for /system and /vendor
211    # Suffix can be _a or _b, depending on what the active /system partition is
212#    suffix=`adb shell getprop ro.boot.slot_suffix`
213    # Get the blockdevice using the suffix we got above
214#    system_block_device=`adb shell ls -l /dev/block/platform/soc/*ufs*/by-name/system$suffix | awk '{ print $10 }' `
215    # Vendor is more straightforward, but we don't use it right now
216#    vendor_block_device=`adb shell df /vendor | grep -v Filesystem | awk '{print $1}' `
217    # finally extract the last component of the absolute device pathname we got above
218#    system_block_device=`echo $system_block_device | awk 'BEGIN { FS ="/" } ; { print $4 }' `
219#    vendor_block_device=`echo $vendor_block_device | awk 'BEGIN { FS ="/" } ; { print $4 }' `
220    system_bdev_set=true
221#   For now, hardcode sda for Marlin/Sailfish block device
222#   XXX - We'll get stats for entire device
223    system_block_device=sda
224    echo Block Device $system_block_device
225}
226
227get_angler_devnames () {
228    # Get the underlying bdev from the "by-name" mapping
229    system_block_device=`adb shell 'find /dev/block/platform -name by-name | xargs ls -l' | grep system | awk '{ print $10 }' `
230    # extract the last component of the absolute device pathname we got above
231    system_block_device=`echo $system_block_device | awk 'BEGIN { FS ="/" } ; { print $4 }' `
232    # vendor is unused right now, but get the bdev anyway in case we decide to use it
233    # Get the underlying bdev from the "by-name" mapping
234    vendor_block_device=`adb shell 'find /dev/block/platform -name by-name | xargs ls -l' | grep vendor | awk '{ print $10 }' `
235    # extract the last component of the absolute device pathname we got above
236   vendor_block_device=`echo $vendor_block_device | awk 'BEGIN { FS ="/" } ; { print $4 }' `
237   system_bdev_set=true
238}
239
240get_fugu_devnames () {
241    system_block_device=`adb shell ls -l /dev/block/by-name/system | awk '{ print $10 }' `
242    system_block_device=`echo $system_block_device | awk 'BEGIN { FS ="/" } ; { print $4 }' `
243    system_bdev_set=true
244}
245
246get_volantis_devnames () {
247    # Hardcoding all of the mmcblk0 device for now
248    system_block_device=mmcblk0
249    system_bdev_set=true
250}
251
252system_stats_before() {
253    if [ $system_bdev_set == true ]; then
254	# Get BEFORE read stats for /system
255	adb shell 'cat /proc/diskstats' | grep -w $system_block_device > /tmp/$model-system
256	BEFORE_RD_IOS_SYSTEM=`awk '{ print $4 }' /tmp/$model-system`
257	BEFORE_RD_SECTORS_SYSTEM=`awk '{ print $6 }' /tmp/$model-system`
258	# iowait% computation
259	adb shell 'cat /proc/stat' | grep -w cpu > /tmp/procstat
260	user_ticks_before=`awk '{ print ($2 + $3) }' /tmp/procstat`
261	sys_ticks_before=`awk '{ print ($4 + $7 + $8) }' /tmp/procstat`
262	cpubusy_ticks_before=`awk '{ print ($2 + $3 + $4 + $7 + $8) }' /tmp/procstat`
263	iowait_ticks_before=`awk '{ print $6 }' /tmp/procstat`
264	total_ticks_before=`awk '{ print ($2 + $3 + $4 + $5 + $7 + $8) }' /tmp/procstat`
265	# Device util% computation
266	# Note hz=100, so multiplying uptime (in seconds) by 100, gives us
267	# the uptime in hz.
268	adb shell 'cat /proc/uptime' > /tmp/uptime
269	uptime_before_hz=`awk '{ print ($1 * 100) }' /tmp/uptime`
270	# Note that the device (busy) ticks is in ms. Since hz=100, dividing
271	# device (busy) ticks by 10, gives us this in the correct ticks units
272	device_util_before_hz=`awk '{ print ($13 / 10) }' /tmp/$model-system`
273    fi
274}
275
276system_stats_after() {
277    if [ $system_bdev_set == true ]; then
278	# Get AFTER read stats for /system
279	adb shell 'cat /proc/diskstats' | grep -w $system_block_device > /tmp/$model-system
280	AFTER_RD_IOS_SYSTEM=`awk '{ print $4 }' /tmp/$model-system`
281	AFTER_RD_SECTORS_SYSTEM=`awk '{ print $6 }' /tmp/$model-system`
282	# iowait% computation
283	adb shell 'cat /proc/stat' | grep -w cpu > /tmp/procstat
284	user_ticks_after=`awk '{ print ($2 + $3) }' /tmp/procstat`
285	sys_ticks_after=`awk '{ print ($4 + $7 + $8) }' /tmp/procstat`
286	cpubusy_ticks_after=`awk '{ print ($2 + $3 + $4 + $7 + $8) }' /tmp/procstat`
287	iowait_ticks_after=`awk '{ print $6 }' /tmp/procstat`
288	total_ticks_after=`awk '{ print ($2 + $3 + $4 + $5 + $7 + $8) }' /tmp/procstat`
289	# Device util% computation
290	# Note hz=100, so multiplying uptime (in seconds) by 100, gives us
291	# the uptime in hz.
292	adb shell 'cat /proc/uptime' > /tmp/uptime
293	uptime_after_hz=`awk '{ print ($1 * 100) }' /tmp/uptime`
294	# Note that the device (busy) ticks is in ms. Since hz=100, dividing
295	# device (busy) ticks by 10, gives us this in the correct ticks units
296	device_util_after_hz=`awk '{ print ($13 / 10) }' /tmp/$model-system`
297    fi
298}
299
300system_stats_delta() {
301    if [ $system_bdev_set == true ]; then
302	# Sectors to KB
303	READ_KB_SYSTEM=`expr $AFTER_RD_SECTORS_SYSTEM - $BEFORE_RD_SECTORS_SYSTEM`
304	READ_KB_SYSTEM=`expr $READ_KB_SYSTEM / 2`
305	echo Read IOs /system = `expr $AFTER_RD_IOS_SYSTEM - $BEFORE_RD_IOS_SYSTEM`
306	echo Read KB /system = $READ_KB_SYSTEM
307	echo $iowait_ticks_before $iowait_ticks_after $total_ticks_before $total_ticks_after | awk '{ printf "IOwait = %.2f\n", (($2 - $1) * 100.0) / ($4 - $3) }'
308	echo $device_util_before_hz $device_util_after_hz $uptime_before_hz $uptime_after_hz | awk '{ printf "Device util% = %.2f\n", (($2 - $1) * 100.0) / ($4 - $3) }'
309	echo $user_ticks_after $user_ticks_before $total_ticks_after $total_ticks_before | awk '{ printf "User CPU util% = %.2f\n", (($1 - $2) * 100.0) / ($3 - $4) }'
310	echo $sys_ticks_after $sys_ticks_before $total_ticks_after $total_ticks_before | awk '{ printf "Sys CPU util% = %.2f\n", (($1 - $2) * 100.0) / ($3 - $4) }'
311	echo $cpubusy_ticks_after $cpubusy_ticks_before $total_ticks_after $total_ticks_before | awk '{ printf "Total CPU util% = %.2f\n", (($1 - $2) * 100.0) / ($3 - $4) }'
312    fi
313}
314
315launch_app() {
316    package=$1
317    activity=$2
318    adb shell "am force-stop $package"
319    sleep 1
320
321    i=0
322    while [ $i -lt $iterations ]
323    do
324	if [ $pagecached == false ]; then
325	    adb shell 'echo 3 > /proc/sys/vm/drop_caches'
326	fi
327	# The -W argument to am start forces am start to wait till the launch completes.
328	# The -S argument forces it to kill any existing app that is running first
329	# eg. adb shell 'am start -W -S -n com.android.chrome/com.google.android.apps.chrome.Main'
330	system_stats_before
331	adb shell "simpleperf stat -a am start -W -n $package/$activity"
332	system_stats_after
333	system_stats_delta
334	sleep 1
335	adb shell "am force-stop $package"
336	sleep 1
337	i=`expr $i + 1`
338    done
339}
340
341launch_fugu_apps() {
342    launch_app com.google.android.youtube.tv com.google.android.apps.youtube.tv.activity.TvGuideActivity > youtube-$model
343    getstats youtube-$model YouTube
344    launch_app com.google.android.play.games com.google.android.gms.games.pano.activity.PanoGamesOnboardHostActivity > games-$model
345    getstats games-$model Games
346    launch_app com.google.android.music com.android.music.activitymanagement.TopLevelActivity > music-$model
347    getstats music-$model Music
348}
349
350launch_phone_apps() {
351    launch_app com.android.chrome com.google.android.apps.chrome.Main > chrome-$model
352    getstats chrome-$model Chrome
353    launch_app com.google.android.GoogleCamera com.android.camera.CameraActivity > camera-$model
354    getstats camera-$model Camera
355    launch_app com.google.android.apps.maps com.google.android.maps.MapsActivity > maps-$model
356    getstats maps-$model Maps
357    launch_app com.google.android.youtube com.google.android.apps.youtube.app.WatchWhileActivity > youtube-$model
358    getstats youtube-$model YouTube
359}
360
361usage() {
362    echo 'Usage: app-launcher [-c|-v] -a|-b|-u num-iterations'
363    echo 'where num-iterations >= 100'
364    echo '-v (optional) for verbose stats dump'
365    echo '-a|-b|-u required:'
366    echo '        -a:all cores'
367    echo '        -b:only big cores'
368    echo '        -c:pagecached. Do not drop pagecache before each launch (not default)'
369    echo '        -h:Dump this help menu'
370    echo '        -u:user experience, no change to cpu/gpu frequencies or governors'
371    echo '        -a/-b locks CPU/GPU freqs to max, performance governor, thermal/perfd off'
372    echo '        -u runs with default device configs, as users would see it'
373    exit 1
374}
375
376#
377# The main() part of the script follows :
378#
379
380if [ $# -lt 2 ]; then
381    usage
382fi
383
384which computestats > /dev/null
385if [ $? != 0 ]; then
386    echo "ERROR: Please add computestats utiliy to your PATH"
387    exit 1
388fi
389
390which computestatsf > /dev/null
391if [ $? != 0 ]; then
392    echo "Error: Please add computestatsf utility to your PATH"
393    exit 1
394fi
395
396parseoptions $@
397
398adb root && sleep 2
399
400if [ $user_experience == false ]; then
401    # Important to stop the thermal-engine to prevent throttling while test is running
402    # and stop perfd
403    adb shell 'stop thermal-engine'
404    adb shell 'stop perfd'
405else
406    echo "User Experience: Default Configs. No changes to cpufreq settings"
407fi
408
409model=`adb shell getprop ro.product.name`
410# Releases are inconsistent with various trailing characters, remove them all
411model=`echo $model | sed 's/[ \t\r\n]*$//' `
412
413echo Found $model Device
414
415system_bdev_set=false
416case $model in
417    marlin | sailfish)
418        if [ $user_experience == false ]; then
419            cpufreq_marlin_sailfish
420        fi
421	get_marlin_sailfish_devnames
422        ;;
423    angler)
424        if [ $user_experience == false ]; then
425            cpufreq_angler
426        fi
427        get_angler_devnames
428        ;;
429    fugu)
430        if [ $user_experience == false ]; then
431            cpufreq_fugu
432        fi
433        get_fugu_devnames
434        ;;
435    volantis | volantisg)
436        if [ $user_experience == false ]; then
437            cpufreq_volantis
438        fi
439        get_volantis_devnames
440        ;;
441    *)
442        echo Unknown Device $model
443        exit 1
444        ;;
445esac
446
447
448#
449# launch each app in turn
450#
451if [ $model == "fugu" ]; then
452    launch_fugu_apps
453else # Phone Apps
454    launch_phone_apps
455fi
456