| #!/bin/bash |
| |
| # defines |
| FREQ=0 #percent |
| SERVICES=(perfd thermal-engine mpdecision) |
| DIR="/sys/devices/system/cpu" |
| |
| |
| ###################### SETUP ###################### |
| |
| # helper functions |
| fileexists() { |
| [ `adb shell "[ -f $1 ] && echo 1 || echo 0" | tr -d '\r'` -eq 1 ] |
| } |
| getprop() { |
| if fileexists $1; then |
| echo `adb shell cat $1 | tr -d '\r'` |
| else |
| echo "FILE $1 NOT FOUND" |
| fi |
| } |
| setprop() { |
| if fileexists $1; then |
| adb shell "echo -n $2 > $1" |
| else |
| echo "FILE $1 NOT FOUND" |
| fi |
| } |
| |
| # use passed in percent frequency |
| if [[ $# -eq 1 ]]; then |
| FREQ=$1 |
| fi |
| |
| # switch to root |
| if [[ "`adb shell id | tr -d '\r' | awk -F'[()]' '{print $2}'`" != "root" ]]; then |
| adb root |
| adb wait-for-device |
| fi |
| |
| # device name |
| echo Device: `adb shell getprop ro.product.model` |
| echo |
| |
| # collect all cores |
| cores=`adb shell ls /sys/devices/system/cpu/ | grep cpu[0-9].* | tr -d '\r'` |
| |
| # disable GPU |
| adb shell setprop debug.rs.default-CPU-driver 1 |
| |
| |
| ###################### CONFIGURE ###################### |
| |
| # freeze system |
| for service in ${SERVICES[@]}; do |
| adb shell stop $service |
| done |
| |
| # set frequencies |
| declare -A selectedFreq |
| for core in $cores; do |
| |
| # turn on core if possible |
| if fileexists $DIR/$core/online; then |
| adb shell "echo -n 1 > $DIR/$core/online" |
| fi |
| |
| # get available frequencies in sorted order |
| if fileexists $DIR/$core/cpufreq/scaling_available_frequencies; then |
| frequencies=(`getprop $DIR/$core/cpufreq/scaling_available_frequencies`) |
| elif fileexists $DIR/$core/cpufreq/stats/time_in_state; then |
| frequencies=(`adb shell cat $DIR/$core/cpufreq/stats/time_in_state | cut -f1 -d " " | tr -d '\r'`) |
| fi |
| frequencies=(`printf "%s\n" "${frequencies[@]}" | sort -n`) |
| |
| # find target frequency based on frequency percentage |
| minFreq=${frequencies[0]} |
| maxFreq=${frequencies[-1]} |
| targetFreq=$(( FREQ * ( maxFreq - minFreq ) / 100 + minFreq )) |
| |
| # find closest frequency |
| freq=`printf "%d\n" "${frequencies[@]}" | awk -v c=${frequencies[0]} -v t=$targetFreq 'BEGIN{d=$0-t;if(d<0)d=-d;l=d}{d=$0-t;if(d<0)d=-d;if(d<l){l=d;c=$0}}END{print c}'` |
| selectedFreq[$core]=$freq |
| |
| # set frequency |
| adb shell "echo -n $freq > $DIR/$core/cpufreq/scaling_min_freq" |
| adb shell "echo -n $freq > $DIR/$core/cpufreq/scaling_max_freq" |
| |
| done |
| |
| |
| # keep trying until the frequencies are properly set |
| while true; do |
| |
| # check to see if frequencies are correct |
| CORRECT=true |
| for core in $cores; do |
| if fileexists $DIR/$core/online && [ `getprop $DIR/$core/online` -eq 0 ]; then |
| echo "$core is offline" |
| CORRECT=false |
| else |
| if fileexists $DIR/$core/cpufreq/scaling_cur_freq; then |
| frequency=`getprop $DIR/$core/cpufreq/scaling_cur_freq` |
| if [ $frequency != ${selectedFreq[$core]} ]; then |
| echo "$core: $frequency != ${selectedFreq[$core]}" |
| CORRECT=false |
| fi |
| else |
| echo "$core is offline" |
| CORRECT=false |
| fi |
| fi |
| done |
| |
| # finished |
| if [ $CORRECT == "true" ]; then |
| break |
| fi |
| |
| # display |
| echo "Frequencies not properly set. Trying again..." |
| |
| # unfreeze system |
| for service in ${SERVICES[@]}; do |
| adb shell start $service |
| done |
| |
| # wait for changes to be made |
| sleep 1 |
| |
| # freeze system |
| for service in ${SERVICES[@]}; do |
| adb shell stop $service |
| done |
| |
| # try resetting the values (only really needed for Nexus 7 for some reason) |
| for core in $cores; do |
| if fileexists $DIR/$core/online; then |
| adb shell "echo -n 1 > $DIR/$core/online" |
| fi |
| adb shell "echo -n $freq > $DIR/$core/cpufreq/scaling_min_freq" |
| adb shell "echo -n $freq > $DIR/$core/cpufreq/scaling_max_freq" |
| done |
| |
| sleep 1 |
| |
| done |
| |
| # display |
| for core in $cores; do |
| echo "$core successfully set to ${selectedFreq[$core]}" |
| done |
| |
| |