File: prep_generic.sh

package info (click to toggle)
android-platform-frameworks-base 1%3A14~beta1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 326,092 kB
  • sloc: java: 2,032,373; xml: 343,016; cpp: 304,181; python: 3,683; ansic: 2,090; sh: 1,871; makefile: 117; sed: 19
file content (384 lines) | stat: -rwxr-xr-x 13,588 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
#
# Copyright (C) 2018 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

#################################################################
###
###  DO NOT MODIFY THIS FILE
###  This is a copy of androidx's benchmark/lockClocks.sh
###  Make changes there instead then copy here!
###
#################################################################

# This script can be used to lock device clocks to stable levels for comparing
# different versions of software.  Since the clock levels are not necessarily
# indicative of real world behavior, this should **never** be used to compare
# performance between different device models.

# Fun notes for maintaining this file:
#      $((arithmetic expressions)) can deal with ints > INT32_MAX, but if compares cannot. This is
#      why we use MHz.
#      $((arithmetic expressions)) can sometimes evaluate right-to-left. This is why we use parens.
#      Everything below the initial host-check isn't bash - Android uses mksh
#      mksh allows `\n` in an echo, bash doesn't
#      can't use `awk`
#      can't use `sed`
#      can't use `cut` on < L
#      can't use `expr` on < L

ARG_CORES=${1:-big}

CPU_TARGET_FREQ_PERCENT=50
GPU_TARGET_FREQ_PERCENT=50

if [ "`command -v getprop`" == "" ]; then
    if [ -n "`command -v adb`" ]; then
        echo ""
        echo "Pushing $0 and running it on device..."
        dest=/data/local/tmp/`basename $0`
        adb push $0 ${dest}
        adb shell ${dest} $@
        adb shell rm ${dest}
        exit
    else
        echo "Could not find adb. Options are:"
        echo "  1. Ensure adb is on your \$PATH"
        echo "  2. Use './gradlew lockClocks'"
        echo "  3. Manually adb push this script to your device, and run it there"
        exit -1
    fi
fi

# require root
if [[ `id` != "uid=0"* ]]; then
    echo "Not running as root, cannot lock clocks, aborting"
    exit -1
fi

DEVICE=`getprop ro.product.device`
MODEL=`getprop ro.product.model`

if [ "$ARG_CORES" == "big" ]; then
    CPU_IDEAL_START_FREQ_KHZ=0
elif [ "$ARG_CORES" == "little" ]; then
    CPU_IDEAL_START_FREQ_KHZ=100000000 ## finding min of max freqs, so start at 100M KHz (100 GHz)
else
    echo "Invalid argument \$1 for ARG_CORES, should be 'big' or 'little', but was $ARG_CORES"
    exit -1
fi

function_core_check() {
    if [ "$ARG_CORES" == "big" ]; then
        [ $1 -gt $2 ]
    elif [ "$ARG_CORES" == "little" ]; then
        [ $1 -lt $2 ]
    else
        echo "Invalid argument \$1 for ARG_CORES, should be 'big' or 'little', but was $ARG_CORES"
        exit -1
    fi
}

function_setup_go() {
    if [ -f /d/fpsgo/common/force_onoff ]; then
        # Disable fpsgo
        echo 0 > /d/fpsgo/common/force_onoff
        fpsgoState=`cat /d/fpsgo/common/force_onoff`
        if [ "$fpsgoState" != "0" ] && [ "$fpsgoState" != "force off" ]; then
            echo "Failed to disable fpsgo"
            exit -1
        fi
    fi
}

# Find the min or max (little vs big) of CPU max frequency, and lock cores of the selected type to
# an available frequency that's >= $CPU_TARGET_FREQ_PERCENT% of max. Disable other cores.
function_lock_cpu() {
    CPU_BASE=/sys/devices/system/cpu
    GOV=cpufreq/scaling_governor

    # Options to make clock locking on go devices more sticky.
    function_setup_go

    # Find max CPU freq, and associated list of available freqs
    cpuIdealFreq=$CPU_IDEAL_START_FREQ_KHZ
    cpuAvailFreqCmpr=0
    cpuAvailFreq=0
    enableIndices=''
    disableIndices=''
    cpu=0
    while [ -d ${CPU_BASE}/cpu${cpu}/cpufreq ]; do
        # Try to enable core, so we can find its frequencies.
        # Note: In cases where the online file is inaccessible, it represents a
        # core which cannot be turned off, so we simply assume it is enabled if
        # this command fails.
        if [ -f "$CPU_BASE/cpu$cpu/online" ]; then
            echo 1 > ${CPU_BASE}/cpu${cpu}/online || true
        fi

        # set userspace governor on all CPUs to ensure freq scaling is disabled
        echo userspace > ${CPU_BASE}/cpu${cpu}/${GOV}

        maxFreq=`cat ${CPU_BASE}/cpu$cpu/cpufreq/cpuinfo_max_freq`
        availFreq=`cat ${CPU_BASE}/cpu$cpu/cpufreq/scaling_available_frequencies`
        availFreqCmpr=${availFreq// /-}

        if (function_core_check $maxFreq $cpuIdealFreq); then
            # new min/max of max freq, look for cpus with same max freq and same avail freq list
            cpuIdealFreq=${maxFreq}
            cpuAvailFreq=${availFreq}
            cpuAvailFreqCmpr=${availFreqCmpr}

            if [ -z "$disableIndices" ]; then
                disableIndices="$enableIndices"
            else
                disableIndices="$disableIndices $enableIndices"
            fi
            enableIndices=${cpu}
        elif [ ${maxFreq} == ${cpuIdealFreq} ] && [ ${availFreqCmpr} == ${cpuAvailFreqCmpr} ]; then
            enableIndices="$enableIndices $cpu"
        else
            if [ -z "$disableIndices" ]; then
                disableIndices="$cpu"
            else
                disableIndices="$disableIndices $cpu"
            fi
        fi

        cpu=$(($cpu + 1))
    done

    # check that some CPUs will be enabled
    if [ -z "$enableIndices" ]; then
        echo "Failed to find any $ARG_CORES cores to enable, aborting."
        exit -1
    fi

    # Chose a frequency to lock to that's >= $CPU_TARGET_FREQ_PERCENT% of max
    # (below, 100M = 1K for KHz->MHz * 100 for %)
    TARGET_FREQ_MHZ=$(( ($cpuIdealFreq * $CPU_TARGET_FREQ_PERCENT) / 100000 ))
    chosenFreq=0
    chosenFreqDiff=100000000
    for freq in ${cpuAvailFreq}; do
        freqMhz=$(( ${freq} / 1000 ))
        if [ ${freqMhz} -ge ${TARGET_FREQ_MHZ} ]; then
            newChosenFreqDiff=$(( $freq - $TARGET_FREQ_MHZ ))
            if [ $newChosenFreqDiff -lt $chosenFreqDiff ]; then
                chosenFreq=${freq}
                chosenFreqDiff=$(( $chosenFreq - $TARGET_FREQ_MHZ ))
            fi
        fi
    done

    # Lock wembley clocks using high-priority op code method.
    # This block depends on the shell utility awk, which is only available on API 27+
    if [ "$DEVICE" == "wembley" ]; then
        # Get list of available frequencies to lock to by parsing the op-code list.
        AVAIL_OP_FREQS=`cat /proc/cpufreq/MT_CPU_DVFS_LL/cpufreq_oppidx \
            | awk '{print $2}' \
            | tail -n +3 \
            | while read line; do
                echo "${line:1:${#line}-2}"
            done`

        # Compute the closest available frequency to the desired frequency, $chosenFreq.
        # This assumes the op codes listen in /proc/cpufreq/MT_CPU_DVFS_LL/cpufreq_oppidx are listed
        # in order and 0-indexed.
        opCode=-1
        opFreq=0
        currOpCode=-1
        for currOpFreq in $AVAIL_OP_FREQS; do
            currOpCode=$((currOpCode + 1))

            prevDiff=$((chosenFreq-opFreq))
            prevDiff=`function_abs $prevDiff`
            currDiff=$((chosenFreq-currOpFreq))
            currDiff=`function_abs $currDiff`
            if [ $currDiff -lt $prevDiff ]; then
                opCode="$currOpCode"
                opFreq="$currOpFreq"
            fi
        done

        echo "$opCode" > /proc/ppm/policy/ut_fix_freq_idx
    fi

    # enable 'big' CPUs
    for cpu in ${enableIndices}; do
        freq=${CPU_BASE}/cpu$cpu/cpufreq

        # Try to enable core, so we can find its frequencies.
        # Note: In cases where the online file is inaccessible, it represents a
        # core which cannot be turned off, so we simply assume it is enabled if
        # this command fails.
        if [ -f "$CPU_BASE/cpu$cpu/online" ]; then
            echo 1 > ${CPU_BASE}/cpu${cpu}/online || true
        fi

        # scaling_max_freq must be set before scaling_min_freq
        echo ${chosenFreq} > ${freq}/scaling_max_freq
        echo ${chosenFreq} > ${freq}/scaling_min_freq
        echo ${chosenFreq} > ${freq}/scaling_setspeed

        # Give system a bit of time to propagate the change to scaling_setspeed.
        sleep 0.1

        # validate setting the freq worked
        obsCur=`cat ${freq}/scaling_cur_freq`
        obsMin=`cat ${freq}/scaling_min_freq`
        obsMax=`cat ${freq}/scaling_max_freq`
        if [ "$obsCur" -ne "$chosenFreq" ] || [ "$obsMin" -ne "$chosenFreq" ] || [ "$obsMax" -ne "$chosenFreq" ]; then
            echo "Failed to set CPU$cpu to $chosenFreq Hz! Aborting..."
            echo "scaling_cur_freq = $obsCur"
            echo "scaling_min_freq = $obsMin"
            echo "scaling_max_freq = $obsMax"
            exit -1
        fi
    done

    # disable other CPUs (Note: important to enable big cores first!)
    for cpu in ${disableIndices}; do
      echo 0 > ${CPU_BASE}/cpu${cpu}/online
    done

    echo "=================================="
    echo "Locked CPUs ${enableIndices// /,} to $chosenFreq / $cpuIdealFreq KHz"
    echo "Disabled CPUs ${disableIndices// /,}"
    echo "=================================="
}

# Returns the absolute value of the first arg passed to this helper.
function_abs() {
    n=$1
    if [ $n -lt 0 ]; then
        echo "$((n * -1 ))"
    else
        echo "$n"
    fi
}

# If we have a Qualcomm GPU, find its max frequency, and lock to
# an available frequency that's >= GPU_TARGET_FREQ_PERCENT% of max.
function_lock_gpu_kgsl() {
    if [ ! -d /sys/class/kgsl/kgsl-3d0/ ]; then
        # not kgsl, abort
        echo "Currently don't support locking GPU clocks of $MODEL ($DEVICE)"
        return -1
    fi
    if [ ${DEVICE} == "walleye" ] || [ ${DEVICE} == "taimen" ]; then
        # Workaround crash
        echo "Unable to lock GPU clocks of $MODEL ($DEVICE)"
        return -1
    fi

    GPU_BASE=/sys/class/kgsl/kgsl-3d0

    gpuMaxFreq=0
    gpuAvailFreq=`cat $GPU_BASE/devfreq/available_frequencies`
    for freq in ${gpuAvailFreq}; do
        if [ ${freq} -gt ${gpuMaxFreq} ]; then
            gpuMaxFreq=${freq}
        fi
    done

    # (below, 100M = 1M for MHz * 100 for %)
    TARGET_FREQ_MHZ=$(( (${gpuMaxFreq} * ${GPU_TARGET_FREQ_PERCENT}) / 100000000 ))

    chosenFreq=${gpuMaxFreq}
    index=0
    chosenIndex=0
    for freq in ${gpuAvailFreq}; do
        freqMhz=$(( ${freq} / 1000000 ))
        if [ ${freqMhz} -ge ${TARGET_FREQ_MHZ} ] && [ ${chosenFreq} -ge ${freq} ]; then
            # note avail freq are generally in reverse order, so we don't break out of this loop
            chosenFreq=${freq}
            chosenIndex=${index}
        fi
        index=$(($index + 1))
    done
    lastIndex=$(($index - 1))

    firstFreq=`function_cut_first_from_space_seperated_list $gpuAvailFreq`

    if [ ${gpuMaxFreq} != ${firstFreq} ]; then
        # pwrlevel is index of desired freq among available frequencies, from highest to lowest.
        # If gpuAvailFreq appears to be in-order, reverse the index
        chosenIndex=$(($lastIndex - $chosenIndex))
    fi

    echo 0 > ${GPU_BASE}/bus_split
    echo 1 > ${GPU_BASE}/force_clk_on
    echo 10000 > ${GPU_BASE}/idle_timer

    echo performance > ${GPU_BASE}/devfreq/governor

    # NOTE: we store in min/max twice, because we don't know if we're increasing
    # or decreasing, and it's invalid to try and set min > max, or max < min
    echo ${chosenFreq} > ${GPU_BASE}/devfreq/min_freq
    echo ${chosenFreq} > ${GPU_BASE}/devfreq/max_freq
    echo ${chosenFreq} > ${GPU_BASE}/devfreq/min_freq
    echo ${chosenFreq} > ${GPU_BASE}/devfreq/max_freq
    echo ${chosenIndex} > ${GPU_BASE}/min_pwrlevel
    echo ${chosenIndex} > ${GPU_BASE}/max_pwrlevel
    echo ${chosenIndex} > ${GPU_BASE}/min_pwrlevel
    echo ${chosenIndex} > ${GPU_BASE}/max_pwrlevel

    obsCur=`cat ${GPU_BASE}/devfreq/cur_freq`
    obsMin=`cat ${GPU_BASE}/devfreq/min_freq`
    obsMax=`cat ${GPU_BASE}/devfreq/max_freq`
    if [ obsCur -ne ${chosenFreq} ] || [ obsMin -ne ${chosenFreq} ] || [ obsMax -ne ${chosenFreq} ]; then
        echo "Failed to set GPU to $chosenFreq Hz! Aborting..."
        echo "cur_freq = $obsCur"
        echo "min_freq = $obsMin"
        echo "max_freq = $obsMax"
        echo "index = $chosenIndex"
        exit -1
    fi
    echo "Locked GPU to $chosenFreq / $gpuMaxFreq Hz"
}

# cut is not available on some devices (Nexus 5 running LRX22C).
function_cut_first_from_space_seperated_list() {
    list=$1

    for freq in $list; do
        echo $freq
        break
    done
}

# kill processes that manage thermals / scaling
stop thermal-engine || true
stop perfd || true
stop vendor.thermal-engine || true
stop vendor.perfd || true
setprop vendor.powerhal.init 0 || true
setprop ctl.interface_restart android.hardware.power@1.0::IPower/default || true

function_lock_cpu

if [ "$DEVICE" -ne "wembley" ]; then
    function_lock_gpu_kgsl
else
    echo "Unable to lock gpu clocks of $MODEL ($DEVICE)."
fi

# Memory bus - hardcoded per-device for now
if [ ${DEVICE} == "marlin" ] || [ ${DEVICE} == "sailfish" ]; then
    echo 13763 > /sys/class/devfreq/soc:qcom,gpubw/max_freq
else
    echo "Unable to lock memory bus of $MODEL ($DEVICE)."
fi

echo "$DEVICE clocks have been locked - to reset, reboot the device"