xref: /aosp_15_r20/kernel/tests/tools/flash_device.sh (revision 2f2c4c7ab4226c71756b9c31670392fdd6887c4f)
1#!/usr/bin/env bash
2# SPDX-License-Identifier: GPL-2.0
3
4# A handy tool to flash device with local build or remote build.
5
6# Constants
7FETCH_SCRIPT="fetch_artifact.sh"
8# Please see go/cl_flashstation
9FLASH_CLI=/google/bin/releases/android/flashstation/cl_flashstation
10LOCAL_FLASH_CLI=/google/bin/releases/android/flashstation/local_flashstation
11REMOTE_MIX_SCRIPT_PATH="DATA/local/tmp/build_mixed_kernels_ramdisk"
12FETCH_SCRIPT="kernel/tests/tools/fetch_artifact.sh"
13DOWNLOAD_PATH="/tmp/downloaded_images"
14KERNEL_TF_PREBUILT=prebuilts/tradefed/filegroups/tradefed/tradefed.sh
15PLATFORM_TF_PREBUILT=tools/tradefederation/prebuilts/filegroups/tradefed/tradefed.sh
16KERNEL_JDK_PATH=prebuilts/jdk/jdk11/linux-x86
17PLATFORM_JDK_PATH=prebuilts/jdk/jdk21/linux-x86
18LOCAL_JDK_PATH=/usr/local/buildtools/java/jdk11
19LOG_DIR=$PWD/out/test_logs/$(date +%Y%m%d_%H%M%S)
20# Color constants
21BOLD="$(tput bold)"
22END="$(tput sgr0)"
23GREEN="$(tput setaf 2)"
24RED="$(tput setaf 198)"
25YELLOW="$(tput setaf 3)"
26ORANGE="$(tput setaf 208)"
27BLUE=$(tput setaf 4)
28
29SKIP_BUILD=false
30GCOV=false
31DEBUG=false
32KASAN=false
33EXTRA_OPTIONS=()
34LOCAL_REPO=
35DEVICE_VARIANT="userdebug"
36
37BOARD=
38ABI=
39PRODUCT=
40BUILD_TYPE=
41DEVICE_KERNEL_STRING=
42DEVICE_KERNEL_VERSION=
43SYSTEM_DLKM_INFO=
44
45function print_help() {
46    echo "Usage: $0 [OPTIONS]"
47    echo ""
48    echo "This script will build images and flash a physical device."
49    echo ""
50    echo "Available options:"
51    echo "  -s <serial_number>, --serial=<serial_number>"
52    echo "                        [Mandatory] The serial number for device to be flashed with."
53    echo "  --skip-build          [Optional] Skip the image build step. Will build by default if in repo."
54    echo "  --gcov                [Optional] Build gcov enabled kernel"
55    echo "  --debug               [Optional] Build debug enabled kernel"
56    echo "  --kasan               [Optional] Build kasan enabled kernel"
57    echo "  -pb <platform_build>, --platform-build=<platform_build>"
58    echo "                        [Optional] The platform build path. Can be a local path or a remote build"
59    echo "                        as ab://<branch>/<build_target>/<build_id>."
60    echo "                        If not specified and the script is running from a platform repo,"
61    echo "                        it will use the platform build in the local repo."
62    echo "                        If string 'None' is set, no platform build will be flashed,"
63    echo "  -sb <system_build>, --system-build=<system_build>"
64    echo "                        [Optional] The system build path for GSI testing. Can be a local path or"
65    echo "                        remote build as ab://<branch>/<build_target>/<build_id>."
66    echo "                        If not specified, no system build will be used."
67    echo "  -kb <kernel_build>, --kernel-build=<kernel_build>"
68    echo "                        [Optional] The kernel build path. Can be a local path or a remote build"
69    echo "                        as ab://<branch>/<build_target>/<build_id>."
70    echo "                        If not specified and the script is running from an Android common kernel repo,"
71    echo "                        it will use the kernel in the local repo."
72    echo "  -vkb <vendor_kernel_build>, --vendor-kernel-build=<vendor_kernel_build>"
73    echo "                        [Optional] The vendor kernel build path. Can be a local path or a remote build"
74    echo "                        as ab://<branch>/<build_target>/<build_id>."
75    echo "                        If not specified, and the script is running from a vendor kernel repo, "
76    echo "                        it will use the kernel in the local repo."
77    echo "  -vkbt <vendor_kernel_build_target>, --vendor-kernel-build-target=<vendor_kernel_build_target>"
78    echo "                        [Optional] The vendor kernel build target to be used to build vendor kernel."
79    echo "                        If not specified, and the script is running from a vendor kernel repo, "
80    echo "                        it will try to find a local build target in the local repo."
81    echo "  --device-variant=<device_variant>"
82    echo "                        [Optional] Device variant such as userdebug, user, or eng."
83    echo "                        If not specified, will be userdebug by default."
84    echo "  -h, --help            Display this help message and exit"
85    echo ""
86    echo "Examples:"
87    echo "$0"
88    echo "$0 -s 1C141FDEE003FH"
89    echo "$0 -s 1C141FDEE003FH -pb ab://git_main/raven-userdebug/latest"
90    echo "$0 -s 1C141FDEE003FH -pb ~/aosp-main"
91    echo "$0 -s 1C141FDEE003FH -vkb ~/pixel-mainline -pb ab://git_main/raven-trunk_staging-userdebug/latest"
92    echo "$0 -s 1C141FDEE003FH -vkb ab://kernel-android-gs-pixel-mainline/kernel_raviole_kleaf/latest \
93-pb ab://git_trunk_pixel_kernel_61-release/raven-userdebug/latest \
94-kb ab://aosp_kernel-common-android-mainline/kernel_aarch64/latest"
95    echo ""
96    exit 0
97}
98
99function parse_arg() {
100    while test $# -gt 0; do
101        case "$1" in
102            -h|--help)
103                print_help
104                ;;
105            -s)
106                shift
107                if test $# -gt 0; then
108                    SERIAL_NUMBER=$1
109                else
110                    print_error "device serial is not specified"
111                fi
112                shift
113                ;;
114            --serial*)
115                SERIAL_NUMBER=$(echo $1 | sed -e "s/^[^=]*=//g")
116                shift
117                ;;
118            --skip-build)
119                SKIP_BUILD=true
120                shift
121                ;;
122            -pb)
123                shift
124                if test $# -gt 0; then
125                    PLATFORM_BUILD=$1
126                else
127                    print_error "platform build is not specified"
128                fi
129                shift
130                ;;
131            --platform-build=*)
132                PLATFORM_BUILD=$(echo $1 | sed -e "s/^[^=]*=//g")
133                shift
134                ;;
135            -sb)
136                shift
137                if test $# -gt 0; then
138                    SYSTEM_BUILD=$1
139                else
140                    print_error "system build is not specified"
141                fi
142                shift
143                ;;
144            --system-build=*)
145                SYSTEM_BUILD=$(echo $1 | sed -e "s/^[^=]*=//g")
146                shift
147                ;;
148            -kb)
149                shift
150                if test $# -gt 0; then
151                    KERNEL_BUILD=$1
152                else
153                    print_error "kernel build path is not specified"
154                fi
155                shift
156                ;;
157            --kernel-build=*)
158                KERNEL_BUILD=$(echo $1 | sed -e "s/^[^=]*=//g")
159                shift
160                ;;
161            -vkb)
162                shift
163                if test $# -gt 0; then
164                    VENDOR_KERNEL_BUILD=$1
165                else
166                    print_error "vendor kernel build path is not specified"
167                fi
168                shift
169                ;;
170            --vendor-kernel-build=*)
171                VENDOR_KERNEL_BUILD=$(echo $1 | sed -e "s/^[^=]*=//g")
172                shift
173                ;;
174            -vkbt)
175                shift
176                if test $# -gt 0; then
177                    VENDOR_KERNEL_BUILD_TARGET=$1
178                else
179                    print_error "vendor kernel build target is not specified"
180                fi
181                shift
182                ;;
183            --vendor-kernel-build-target=*)
184                VENDOR_KERNEL_BUILD_TARGET=$(echo $1 | sed -e "s/^[^=]*=//g")
185                shift
186                ;;
187            --device-variant=*)
188                DEVICE_VARIANT=$(echo $1 | sed -e "s/^[^=]*=//g")
189                shift
190                ;;
191            --gcov)
192                GCOV=true
193                shift
194                ;;
195            --debug)
196                DEBUG=true
197                shift
198                ;;
199            --kasan)
200                KASAN=true
201                shift
202                ;;
203            *)
204                print_error "Unsupported flag: $1" >&2
205                shift
206                ;;
207        esac
208    done
209}
210
211function adb_checker() {
212    if ! which adb &> /dev/null; then
213        print_error "adb not found!"
214    fi
215}
216
217function go_to_repo_root() {
218    current_dir="$1"
219    while [ ! -d ".repo" ] && [ "$current_dir" != "/" ]; do
220        current_dir=$(dirname "$current_dir")  # Go up one directory
221        cd "$current_dir"
222    done
223}
224
225function print_info() {
226    local log_prompt=$MY_NAME
227    if [ ! -z "$2" ]; then
228        log_prompt+=" line $2"
229    fi
230    echo "[$log_prompt]: ${GREEN}$1${END}"
231}
232
233function print_warn() {
234    local log_prompt=$MY_NAME
235    if [ ! -z "$2" ]; then
236        log_prompt+=" line $2"
237    fi
238    echo "[$log_prompt]: ${ORANGE}$1${END}"
239}
240
241function print_error() {
242    local log_prompt=$MY_NAME
243    if [ ! -z "$2" ]; then
244        log_prompt+=" line $2"
245    fi
246    echo -e "[$log_prompt]: ${RED}$1${END}"
247    cd $OLD_PWD
248    exit 1
249}
250
251function set_platform_repo () {
252    print_warn "Build environment target product '${TARGET_PRODUCT}' does not match expected $1. \
253    Reset build environment" "$LINENO"
254    local lunch_cli="source build/envsetup.sh && lunch $1"
255    if [ -f "build/release/release_configs/trunk_staging.textproto" ]; then
256        lunch_cli+="-trunk_staging-$DEVICE_VARIANT"
257    else
258        lunch_cli+="-$DEVICE_VARIANT"
259    fi
260    print_info "Setup build environment with: $lunch_cli" "$LINENO"
261    eval "$lunch_cli"
262    exit_code=$?
263    if [ $exit_code -eq 0 ]; then
264        print_info "$lunch_cli succeeded" "$LINENO"
265    else
266        print_error "$lunch_cli failed" "$LINENO"
267    fi
268}
269
270function find_repo () {
271    manifest_output=$(grep -e "superproject" -e "gs-pixel" -e "kernel/private/devices/google/common" \
272     -e "private/google-modules/soc/gs" -e "kernel/common" -e "common-modules/virtual-device" \
273     .repo/manifests/default.xml)
274    case "$manifest_output" in
275        *platform/superproject*)
276            PLATFORM_REPO_ROOT="$PWD"
277            PLATFORM_VERSION=$(grep -e "platform/superproject" .repo/manifests/default.xml | \
278            grep -oP 'revision="\K[^"]*')
279            print_info "PLATFORM_REPO_ROOT=$PLATFORM_REPO_ROOT, PLATFORM_VERSION=$PLATFORM_VERSION" "$LINENO"
280            if [ -z "$PLATFORM_BUILD" ]; then
281                PLATFORM_BUILD="$PLATFORM_REPO_ROOT"
282            elif [[ "$PLATFORM_BUILD" == "None" ]]; then
283                PLATFORM_BUILD=
284            fi
285            ;;
286        *kernel/private/devices/google/common*|*private/google-modules/soc/gs*)
287            VENDOR_KERNEL_REPO_ROOT="$PWD"
288            VENDOR_KERNEL_VERSION=$(grep -e "default revision" .repo/manifests/default.xml | \
289            grep -oP 'revision="\K[^"]*')
290            print_info "VENDOR_KERNEL_REPO_ROOT=$VENDOR_KERNEL_REPO_ROOT" "$LINENO"
291            print_info "VENDOR_KERNEL_VERSION=$VENDOR_KERNEL_VERSION" "$LINENO"
292            if [ -z "$VENDOR_KERNEL_BUILD" ]; then
293                VENDOR_KERNEL_BUILD="$VENDOR_KERNEL_REPO_ROOT"
294            fi
295            ;;
296        *common-modules/virtual-device*)
297            KERNEL_REPO_ROOT="$PWD"
298            KERNEL_VERSION=$(grep -e "kernel/superproject" \
299            .repo/manifests/default.xml | grep -oP 'revision="common-\K[^"]*')
300            print_info "KERNEL_REPO_ROOT=$KERNEL_REPO_ROOT, KERNEL_VERSION=$KERNEL_VERSION" "$LINENO"
301            if [ -z "$KERNEL_BUILD" ]; then
302                KERNEL_BUILD="$KERNEL_REPO_ROOT"
303            fi
304            ;;
305        *)
306            print_warn "Unknown manifest output. Could not determine repository type." "$LINENO"
307            ;;
308    esac
309}
310
311function build_platform () {
312    if [[ "$SKIP_BUILD" = true ]]; then
313        print_warn "--skip-build is set. Do not rebuild platform build" "$LINENO"
314        return
315    fi
316    build_cmd="m -j12 ; make otatools -j12 ; make dist -j12"
317    print_warn "Flag --skip-build is not set. Rebuilt images at $PWD with: $build_cmd" "$LINENO"
318    eval $build_cmd
319    exit_code=$?
320    if [ $exit_code -eq 1 ]; then
321        print_warn "$build_cmd returned exit_code $exit_code" "$LINENO"
322        print_error "$build_cmd failed" "$LINENO"
323    else
324        if [ -f "${ANDROID_PRODUCT_OUT}/system.img" ]; then
325            print_info "${ANDROID_PRODUCT_OUT}/system.img exist" "$LINENO"
326        else
327            print_error "${ANDROID_PRODUCT_OUT}/system.img doesn't exist" "$LINENO"
328        fi
329    fi
330}
331
332function build_ack () {
333    if [[ "$SKIP_BUILD" = true ]]; then
334        print_warn "--skip-build is set. Do not rebuild kernel" "$LINENO"
335        return
336    fi
337    build_cmd="tools/bazel run --config=fast"
338    if [ "$GCOV" = true ]; then
339        build_cmd+=" --gcov"
340    fi
341    if [ "$DEBUG" = true ]; then
342        build_cmd+=" --debug"
343    fi
344    if [ "$KASAN" = true ]; then
345        build_cmd+=" --kasan"
346    fi
347    build_cmd+=" //common:kernel_aarch64_dist"
348    print_warn "Flag --skip-build is not set. Rebuild the kernel with: $build_cmd." "$LINENO"
349    eval $build_cmd
350    exit_code=$?
351    if [ $exit_code -eq 0 ]; then
352        print_info "$build_cmd succeeded" "$LINENO"
353    else
354        print_error "$build_cmd failed" "$LINENO"
355    fi
356}
357
358function download_platform_build() {
359    print_info "Downloading $1 to $PWD" "$LINENO"
360    local build_info="$1"
361    local file_patterns=("*$PRODUCT-img-*.zip" "bootloader.img" "radio.img" "misc_info.txt" "otatools.zip")
362    if [[ "$1" == *"user/"* ]]; then
363        file_patterns+=("vendor_ramdisk-debug.img")
364    else
365        file_patterns+=("vendor_ramdisk.img")
366    fi
367
368    echo "Downloading ${file_patterns[@]} from $build_info"
369    for pattern in "${file_patterns[@]}"; do
370        download_file_name="$build_info/$pattern"
371        eval "$FETCH_SCRIPT $download_file_name"
372        exit_code=$?
373        if [ $exit_code -eq 0 ]; then
374            print_info "Download $download_file_name succeeded" "$LINENO"
375        else
376            print_error "Download $download_file_name failed" "$LINENO"
377        fi
378        if [[ "$pattern" == "vendor_ramdisk-debug.img" ]]; then
379            cp vendor_ramdisk-debug.img vendor_ramdisk.img
380        fi
381    done
382    echo ""
383}
384
385function download_gki_build() {
386    print_info "Downloading $1 to $PWD" "$LINENO"
387    local build_info="$1"
388    local file_patterns=("Image.lz4" "boot-lz4.img" "system_dlkm_staging_archive.tar.gz" "system_dlkm.flatten.ext4.img" "system_dlkm.flatten.erofs.img")
389
390    echo "Downloading ${file_patterns[@]} from $build_info"
391    for pattern in "${file_patterns[@]}"; do
392        download_file_name="$build_info/$pattern"
393        eval "$FETCH_SCRIPT $download_file_name"
394        exit_code=$?
395        if [ $exit_code -eq 0 ]; then
396            print_info "Download $download_file_name succeeded" "$LINENO"
397        else
398            print_error "Download $download_file_name failed" "$LINENO"
399        fi
400    done
401    echo ""
402}
403
404function download_vendor_kernel_build() {
405    print_info "Downloading $1 to $PWD" "$LINENO"
406    local build_info="$1"
407    local file_patterns=("vendor_dlkm_staging_archive.tar.gz" "Image.lz4" "dtbo.img" \
408    "initramfs.img" "vendor_dlkm.img" "boot.img" "vendor_dlkm.modules.blocklist" "vendor_dlkm.modules.load" )
409
410    if [[ "$VENDOR_KERNEL_VERSION" == *"6.6" ]]; then
411        file_patterns+=("*vendor_dev_nodes_fragment.img")
412    fi
413
414    case "$PRODUCT" in
415        oriole | raven | bluejay)
416            file_patterns+=( "gs101-a0.dtb" "gs101-b0.dtb")
417            ;;
418        *)
419            ;;
420    esac
421
422    echo "Downloading ${file_patterns[@]} from $build_info"
423    for pattern in "${file_patterns[@]}"; do
424        download_file_name="$build_info/$pattern"
425        eval "$FETCH_SCRIPT $download_file_name"
426        exit_code=$?
427        if [ $exit_code -eq 0 ]; then
428            print_info "Download $download_file_name succeeded" "$LINENO"
429        else
430            print_error "Download $download_file_name failed" "$LINENO"
431        fi
432    done
433    echo ""
434}
435
436function flash_gki_build() {
437    local boot_image_name
438    local system_dlkm_image_name
439
440    case "$PRODUCT" in
441        oriole | raven | bluejay)
442            boot_image_name="boot-lz4.img"
443            # no system_dlkm partition
444            ;;
445        eos | aurora | full_erd8835 | betty | kirkwood)
446            boot_image_name="boot.img"
447            if [[ "$PRODUCT" == "kirkwood" ]] && [[ ! "$KERNEL_VERSION" =~ ^android13 ]]; then  # Check if NOT android13
448                system_dlkm_image_name="system_dlkm.flatten.erofs.img"
449            # no system_dlkm for android12 & android13
450            elif [[ ! "$KERNEL_VERSION" =~ ^android12 ]] && [[ ! "$KERNEL_VERSION" =~ ^android13 ]]; then  # Check if NOT android12 AND NOT android13
451                system_dlkm_image_name="system_dlkm.flatten.erofs.img"
452            fi
453            ;;
454        k6985v1 | k6989v1)
455            boot_image_name="boot-gz.img"
456            # no system_dlkm for android12 & android13
457            if [[ ! "$KERNEL_VERSION" =~ ^android12 ]] && [[ ! "$KERNEL_VERSION" =~ ^android13 ]]; then  # Check if NOT android12 AND NOT android13
458                system_dlkm_image_name="system_dlkm.flatten.ext4.img"
459            fi
460            ;;
461        *)
462            boot_image_name="boot-lz4.img"
463            # no system_dlkm for android12 & android13
464            if [[ ! "$KERNEL_VERSION" =~ ^android12 ]] && [[ ! "$KERNEL_VERSION" =~ ^android13 ]]; then # Check if NOT android12 AND NOT android13
465                system_dlkm_image_name="system_dlkm.flatten.ext4.img"
466            fi
467            ;;
468    esac
469
470    if [ -z "$TRADEFED" ]; then
471        find_tradefed_bin
472    fi
473    if [ -d "$DOWNLOAD_PATH/tf_gki_kernel_dir" ]; then
474        rm -rf "$DOWNLOAD_PATH/tf_gki_kernel_dir"
475    fi
476    local kernel_dir="$DOWNLOAD_PATH/tf_gki_kernel_dir"
477    mkdir -p "$kernel_dir"
478    cd "$vendor_kernel_dir" || $(print_error "Fail to go to $gki_kernel_dir" "$LINENO")
479    cp "$KERNEL_BUILD/$boot_image_name" "$kernel_dir" || $(print_error "Fail to copy $KERNEL_BUILD/$boot_image_name" "$LINENO")
480    tf_cli="$TRADEFED \
481    run commandAndExit template/local_min --log-level-display VERBOSE \
482    --log-file-path=$LOG_DIR -s $SERIAL_NUMBER --disable-verity \
483    --template:map test=example/reboot --num-of-reboots 1 \
484    --template:map preparers=template/preparers/gki-device-flash-preparer \
485    --extra-file gki_boot.img=$kernel_dir/$boot_image_name"
486
487    # Check if system_dlkm_image_name is set before adding it to the command
488    if [ ! -z "$system_dlkm_image_name" ]; then
489        cp "$KERNEL_BUILD/$system_dlkm_image_name" "$kernel_dir" || $(print_error "Fail to copy $KERNEL_BUILD/$system_dlkm_image_name" "$LINENO")
490        tf_cli+=" --extra-file system_dlkm.img=$kernel_dir/$system_dlkm_image_name"
491    fi
492    print_info "Run $tf_cli" "$LINENO"
493    eval "$tf_cli" # Quote the variable expansion
494}
495
496function flash_vendor_kernel_build() {
497    if [ -z "$TRADEFED" ]; then
498        find_tradefed_bin
499    fi
500    local tf_cli="$TRADEFED run commandAndExit template/local_min --log-level-display VERBOSE \
501    --log-file-path=$LOG_DIR -s $SERIAL_NUMBER --disable-verity \
502    --template:map test=example/reboot --num-of-reboots 1 \
503    --template:map preparers=template/preparers/gki-device-flash-preparer"
504
505    if [ -d "$DOWNLOAD_PATH/tf_vendor_kernel_dir" ]; then
506        rm -rf "$DOWNLOAD_PATH/tf_vendor_kernel_dir"
507    fi
508    local vendor_kernel_dir="$DOWNLOAD_PATH/tf_vendor_kernel_dir"
509    mkdir -p "$vendor_kernel_dir"
510    local file_patterns=("boot.img" "initramfs.img" "dtbo.img" "vendor_dlkm.img")
511    for pattern in "${file_patterns[@]}"; do
512        if [ ! -f "$VENDOR_KERNEL_BUILD/$pattern" ]; then
513            print_error "$VENDOR_KERNEL_BUILD/$pattern doesn't exist" "$LINENO"
514        fi
515        cp "$VENDOR_KERNEL_BUILD/$pattern" "$vendor_kernel_dir"
516        if [[ "$pattern" == "boot.img" ]]; then
517            tf_cli+=" --extra-file gki_boot.img=$vendor_kernel_dir/boot.img"
518        else
519            tf_cli+=" --extra-file $pattern=$vendor_kernel_dir/$pattern"
520        fi
521    done
522    print_info "Run $tf_cli" "$LINENO"
523    eval $tf_cli
524}
525
526# Function to check and wait for an ADB device
527function wait_for_adb_device() {
528  local serial_number="$1"  # Optional serial number
529  local timeout_seconds="${2:-300}"  # Timeout in seconds (default 5 minutes)
530
531  local start_time=$(date +%s)
532  local end_time=$((start_time + timeout_seconds))
533
534  while (( $(date +%s) < end_time )); do
535    devices=$(adb devices | grep "$SERIAL_NUMBER" | wc -l)
536
537    if (( devices > 0 )); then
538      print_info "Device $SERIAL_NUMBER is connected with adb" "$LINENO"
539      return 0  # Success
540    fi
541    print_info "Waiting for device $SERIAL_NUMBER in adb devies" "$LINENO"
542    sleep 1
543  done
544
545  print_error "Timeout waiting for $SERIAL_NUMBER in adb devices" "$LINENO"
546}
547
548function flash_platform_build() {
549    if [[ "$PLATFORM_BUILD" == ab://* ]] && [ -x "$FLASH_CLI" ]; then
550        local flash_cmd="$FLASH_CLI --nointeractive --force_flash_partitions --disable_verity -w -s $SERIAL_NUMBER "
551        IFS='/' read -ra array <<< "$PLATFORM_BUILD"
552        if [ ! -z "${array[3]}" ]; then
553            local _build_type="${array[3]#*-}"
554            if [[ "$_build_type" == *userdebug ]]; then
555                flash_cmd+=" -t $_build_type"
556            elif [[ "$_build_type" == *user ]]; then
557                flash_cmd+=" -t $_build_type --force_debuggable"
558            fi
559        fi
560        if [ ! -z "${array[4]}" ] && [[ "${array[4]}" != latest* ]]; then
561            echo "Flash $SERIAL_NUMBER with platform build from branch $PLATFORM_BUILD..."
562            flash_cmd+=" --bid ${array[4]}"
563        else
564            echo "Flash $SERIAL_NUMBER with platform build $PLATFORM_BUILD..."
565            flash_cmd+=" -l ${array[2]}"
566        fi
567        print_info "Flash $SERIAL_NUMBER with flash station cli by: $flash_cmd" "$LINENO"
568        eval "$flash_cmd"
569        exit_code=$?
570        if [ $exit_code -eq 0 ]; then
571            echo "Flash platform succeeded"
572            wait_for_adb_device
573            return
574        else
575            echo "Flash platform build failed with exit code $exit_code"
576            exit 1
577        fi
578    fi
579
580    if [ ! -z "$PLATFORM_REPO_ROOT" ] && [[ "$PLATFORM_BUILD" == "$PLATFORM_REPO_ROOT/out/target/product/$PRODUCT" ]] && \
581    [ -x "$PLATFORM_REPO_ROOT/vendor/google/tools/flashall" ]; then
582        cd "$PLATFORM_REPO_ROOT"
583        print_info "Flash with vendor/google/tools/flashall" "$LINENO"
584        if [ -z "${TARGET_PRODUCT}" ] || [[ "${TARGET_PRODUCT}" != *"$PRODUCT" ]]; then
585            if [[ "$PLATFORM_VERSION" == aosp-* ]]; then
586                set_platform_repo "aosp_$PRODUCT"
587            else
588                set_platform_repo "$PRODUCT"
589            fi
590        fi
591        eval "vendor/google/tools/flashall  --nointeractive -w -s $SERIAL_NUMBER"
592        return
593    elif [ -x "${ANDROID_HOST_OUT}/bin/local_flashstation" ] || [ -x "$LOCAL_FLASH_CLI" ]; then
594        if [ -z "${TARGET_PRODUCT}" ]; then
595            export TARGET_PRODUCT="$PRODUCT"
596        fi
597        if [ -z "${TARGET_BUILD_VARIANT}" ]; then
598            export TARGET_BUILD_VARIANT="$DEVICE_VARIANT"
599        fi
600        if [ -z "${ANDROID_PRODUCT_OUT}" ] || [[ "${ANDROID_PRODUCT_OUT}" != "$PLATFORM_BUILD" ]] ; then
601            export ANDROID_PRODUCT_OUT="$PLATFORM_BUILD"
602        fi
603        if [ -z "${ANDROID_HOST_OUT}" ]; then
604            export ANDROID_HOST_OUT="$PLATFORM_BUILD"
605        fi
606        if [ ! -f "$PLATFORM_BUILD/system.img" ]; then
607            local device_image=$(find "$PLATFORM_BUILD" -maxdepth 1 -type f -name *-img*.zip)
608            unzip -j "$device_image" -d "$PLATFORM_BUILD"
609        fi
610
611        awk '! /baseband/' "$PLATFORM_BUILD"/android-info.txt > temp && mv temp "$PLATFORM_BUILD"/android-info.txt
612        awk '! /bootloader/' "$PLATFORM_BUILD"/android-info.txt > temp && mv temp "$PLATFORM_BUILD"/android-info.txt
613
614        flash_cmd="$LOCAL_FLASH_CLI"
615
616        if [ ! -x "$LOCAL_FLASH_CLI" ]; then
617            flash_cmd="${ANDROID_HOST_OUT}/bin/local_flashstation"
618        fi
619
620        flash_cmd+=" --nointeractive --force_flash_partitions --disable_verity --disable_verification  -w -s $SERIAL_NUMBER"
621        print_info "Flash device with: $flash_cmd" "$LINENO"
622        eval "$flash_cmd"
623        exit_code=$?
624        if [ $exit_code -eq 0 ]; then
625            echo "Flash platform succeeded"
626            wait_for_adb_device
627            return
628        else
629            echo "Flash platform build failed with exit code $exit_code"
630            exit 1
631        fi
632    fi
633
634}
635
636function get_mix_ramdisk_script() {
637    download_file_name="ab://git_main/aosp_cf_x86_64_only_phone-trunk_staging-userdebug/latest/*-tests-*.zip"
638    eval "$FETCH_SCRIPT $download_file_name"
639    exit_code=$?
640    if [ $exit_code -eq 0 ]; then
641        print_info "Download $download_file_name succeeded" "$LINENO"
642    else
643        print_error "Download $download_file_name failed" "$LINENO" "$LINENO"
644    fi
645    eval "unzip -j *-tests-* DATA/local/tmp/build_mixed_kernels_ramdisk"
646    echo ""
647}
648
649function mixing_build() {
650    if [ ! -z ${PLATFORM_REPO_ROOT_PATH} ] && [ -f "$PLATFORM_REPO_ROOT_PATH/vendor/google/tools/build_mixed_kernels_ramdisk"]; then
651        mix_kernel_cmd="$PLATFORM_REPO_ROOT_PATH/vendor/google/tools/build_mixed_kernels_ramdisk"
652    elif [ -f "$DOWNLOAD_PATH/build_mixed_kernels_ramdisk" ]; then
653        mix_kernel_cmd="$DOWNLOAD_PATH/build_mixed_kernels_ramdisk"
654    else
655        cd "$DOWNLOAD_PATH"
656        get_mix_ramdisk_script
657        mix_kernel_cmd="$PWD/build_mixed_kernels_ramdisk"
658    fi
659    if [ ! -f "$mix_kernel_cmd" ]; then
660        print_error "$mix_kernel_cmd doesn't exist or is not executable" "$LINENO"
661    elif [ ! -x "$mix_kernel_cmd" ]; then
662        print_error "$mix_kernel_cmd is not executable" "$LINENO"
663    fi
664    if [[ "$PLATFORM_BUILD" == ab://* ]]; then
665        print_info "Download platform build $PLATFORM_BUILD" "$LINENO"
666        if [ -d "$DOWNLOAD_PATH/device_dir" ]; then
667            rm -rf "$DOWNLOAD_PATH/device_dir"
668        fi
669        PLATFORM_DIR="$DOWNLOAD_PATH/device_dir"
670        mkdir -p "$PLATFORM_DIR"
671        cd "$PLATFORM_DIR" || $(print_error "Fail to go to $PLATFORM_DIR" "$LINENO")
672        download_platform_build "$PLATFORM_BUILD"
673        PLATFORM_BUILD="$PLATFORM_DIR"
674    elif [ ! -z "$PLATFORM_REPO_ROOT" ] && [[ "$PLATFORM_BUILD" == "$PLATFORM_REPO_ROOT"* ]]; then
675        print_info "Copy platform build $PLATFORM_BUILD to $DOWNLOAD_PATH/device_dir" "$LINENO"
676        PLATFORM_DIR="$DOWNLOAD_PATH/device_dir"
677        mkdir -p "$PLATFORM_DIR"
678        cd "$PLATFORM_DIR" || $(print_error "Fail to go to $PLATFORM_DIR" "$LINENO")
679        local device_image=$(find "$PLATFORM_BUILD" -maxdepth 1 -type f -name *-img.zip)
680        if [ ! -z "device_image" ]; then
681            cp "$device_image $PLATFORM_DIR/$PRODUCT-img-0.zip" "$PLATFORM_DIR"
682        else
683            device_image=$(find "$PLATFORM_BUILD" -maxdepth 1 -type f -name *-img-*.zip)
684            if [ ! -z "device_image" ]; then
685                cp "$device_image $PLATFORM_DIR/$PRODUCT-img-0.zip" "$PLATFORM_DIR"
686            else
687                print_error "Can't find $RPODUCT-img-*.zip in $PLATFORM_BUILD"
688            fi
689        fi
690        local file_patterns=("bootloader.img" "radio.img" "vendor_ramdisk.img" "misc_info.txt" "otatools.zip")
691        for pattern in "${file_patterns[@]}"; do
692            cp "$PLATFORM_BUILD/$pattern" "$PLATFORM_DIR/$pattern"
693            exit_code=$?
694            if [ $exit_code -eq 0 ]; then
695                print_info "Copied $PLATFORM_BUILD/$pattern to $PLATFORM_DIR" "$LINENO"
696            else
697                print_error "Failed to copy $PLATFORM_BUILD/$pattern to $PLATFORM_DIR" "$LINENO"
698            fi
699        done
700        PLATFORM_BUILD="$PLATFORM_DIR"
701    fi
702
703    local new_device_dir="$DOWNLOAD_PATH/new_device_dir"
704    if [ -d "$new_device_dir" ]; then
705        rm -rf "$new_device_dir"
706    fi
707    mkdir -p "$new_device_dir"
708    local mixed_build_cmd="$mix_kernel_cmd"
709    if [ -d "${KERNEL_BUILD}" ]; then
710        mixed_build_cmd+=" --gki_dir $KERNEL_BUILD"
711    fi
712    mixed_build_cmd+=" $PLATFORM_BUILD $VENDOR_KERNEL_BUILD $new_device_dir"
713    print_info "Run: $mixed_build_cmd" "$LINENO"
714    eval $mixed_build_cmd
715    device_image=$(ls $new_device_dir/*$PRODUCT-img*.zip)
716    if [ ! -f "$device_image" ]; then
717        print_error "New device image is not created in $new_device_dir" "$LINENO"
718    fi
719    cp "$PLATFORM_BUILD"/bootloader.img $new_device_dir/.
720    cp "$PLATFORM_BUILD"/radio.img $new_device_dir/.
721    PLATFORM_BUILD="$new_device_dir"
722}
723
724get_kernel_version_from_boot_image() {
725    local boot_image_path="$1"
726    local version_output
727
728    # Check for mainline kernel
729    version_output=$(strings "$boot_image_path" | grep mainline)
730    if [ ! -z "$version_output" ]; then
731        KERNEL_VERSION="android-mainline"
732        return  # Exit the function early if a match is found
733    fi
734
735    # Check for Android 15 6.6 kernel
736    version_output=$(strings "$boot_image_path" | grep "android15" | grep "6.6")
737    if [ ! -z "$version_output" ]; then
738        KERNEL_VERSION="android15-6.6"
739        return
740    fi
741
742    # Check for Android 14 6.1 kernel
743    version_output=$(strings "$boot_image_path" | grep "android14" | grep "6.1")
744    if [ ! -z "$version_output" ]; then
745        KERNEL_VERSION="android14-6.1"
746        return
747    fi
748
749    # Check for Android 14 5.15 kernel
750    version_output=$(strings "$boot_image_path" | grep "android14" | grep "5.15")
751    if [ ! -z "$version_output" ]; then
752        KERNEL_VERSION="android14-5.15"
753        return
754    fi
755
756    # Check for Android 13 5.15 kernel
757    version_output=$(strings "$boot_image_path" | grep "android13" | grep "5.15")
758    if [ ! -z "$version_output" ]; then
759        KERNEL_VERSION="android13-5.15"
760        return
761    fi
762
763    # Check for Android 13 5.10 kernel
764    version_output=$(strings "$boot_image_path" | grep "android13" | grep "5.10")
765    if [ ! -z "$version_output" ]; then
766        KERNEL_VERSION="android13-5.10"
767        return
768    fi
769
770    # Check for Android 12 5.10 kernel
771    version_output=$(strings "$boot_image_path" | grep "android12" | grep "5.10")
772    if [ ! -z "$version_output" ]; then
773        KERNEL_VERSION="android12-5.10"
774        return
775    fi
776}
777
778function gki_build_only_operation {
779    IFS='-' read -ra array <<< "$KERNEL_VERSION"
780    case "$KERNEL_VERSION" in
781        android-mainline | android15-6.6* | android14-6.1* | android14-5.15* )
782            if [[ "$KERNEL_VERSION" == "$DEVICE_KERNEL_VERSION"* ]] && [ ! -z "$SYSTEM_DLKM_INFO" ]; then
783                print_info "Device $SERIAL_NUMBER is with $KERNEL_VERSION kernel. Flash GKI directly" "$LINENO"
784                flash_gki_build
785            elif [ -z "$SYSTEM_DLKM_INFO" ]; then
786                print_warn "Device $SERIAL_NUMBER is $PRODUCT that doesn't have system_dlkm partition. Can't flash GKI directly. \
787Please add vendor kernel build for example by flag -vkb ab://kernel-${array[0]}-gs-pixel-${array[1]}/<kernel_target>/latest" "$LINENO"
788                print_error "Can not flash GKI to SERIAL_NUMBER without -vkb <vendor_kernel_build> been specified." "$LINENO"
789            elif [[ "$KERNEL_VERSION" != "$DEVICE_KERNEL_VERSION"* ]]; then
790                print_warn "Device $PRODUCT $SERIAL_NUMBER comes with $DEVICE_KERNEL_STRING kernel. Can't flash GKI directly. \
791Please add a platform build with $KERNEL_VERSION kernel or add vendor kernel build for example by flag \
792-vkb ab://kernel-${array[0]}-gs-pixel-${array[1]}/<kernel_target>/latest" "$LINENO"
793                print_error "Cannot flash $KERNEL_VERSION GKI to device directly $SERIAL_NUMBER." "$LINENO"
794            fi
795            ;;
796        android13-5.15* | android13-5.10* | android12-5.10* | android12-5.4* )
797            if [[ "$KERNEL_VERSION" == "$EVICE_KERNEL_VERSION"* ]]; then
798                print_info "Device $SERIAL_NUMBER is with android13-5.15 kernel. Flash GKI directly." "$LINENO"
799                flash_gki_build
800            else
801                print_warn "Device $SERIAL_NUMBER is $PRODUCT comes with $DEVICE_KERNEL_STRING kernel. Can't flash GKI directly. \
802Please add a platform build with $KERNEL_VERSION kernel or add vendor kernel build for example by flag \
803-vkb ab://kernel-${array[0]}-gs-pixel-${array[1]}/<kernel_target>/latest" "$LINENO"
804                print_error "Cannot flash $KERNEL_VERSION GKI to device directly $SERIAL_NUMBER." "$LINENO"
805            fi
806            ;;
807        *)
808            print_error "Unsupported KERNEL_VERSION: $KERNEL_VERSION" "$LINENO" "$LINENO"
809            ;;
810    esac
811}
812
813function extract_device_kernel_version() {
814    local kernel_string="$1"
815    # Check if the string contains '-android'
816    if [[ "$kernel_string" == *"-mainline"* ]]; then
817        DEVICE_KERNEL_VERSION="android-mainline"
818    elif [[ "$kernel_string" == *"-android"* ]]; then
819        # Extract the substring between the first hyphen and the second hyphen
820        DEVICE_KERNEL_VERSION=$(echo "$kernel_string" | awk -F '-' '{print $2"-"$1}' | cut -d '.' -f -2)
821    else
822       print_warn "Can not parse $kernel_string into kernel version" "$LINENO"
823    fi
824    print_info "Device kernel version is $DEVICE_KERNEL_VERSION" "$LINENO"
825}
826
827function get_device_info {
828    adb_count=$(adb devices | grep "$SERIAL_NUMBER" | wc -l)
829    if (( adb_count > 0 )); then
830        BOARD=$(adb -s "$SERIAL_NUMBER" shell getprop ro.product.board)
831        ABI=$(adb -s "$SERIAL_NUMBER" shell getprop ro.product.cpu.abi)
832        PRODUCT=$(adb -s "$SERIAL_NUMBER" shell getprop ro.build.product)
833        BUILD_TYPE=$(adb -s "$SERIAL_NUMBER" shell getprop ro.build.type)
834        DEVICE_KERNEL_STRING=$(adb -s "$SERIAL_NUMBER" shell uname -r)
835        extract_device_kernel_version "$DEVICE_KERNEL_STRING"
836        SYSTEM_DLKM_INFO=$(adb -s "$SERIAL_NUMBER" shell getprop dev.mnt.blk.system_dlkm)
837        print_info "device info: BOARD=$BOARD, ABI=$ABI, PRODUCT=$PRODUCT, BUILD_TYPE=$BUILD_TYPE" "$LINENO"
838        print_info "device info: SYSTEM_DLKM_INFO=$SYSTEM_DLKM_INFO, DEVICE_KERNEL_STRING=$DEVICE_KERNEL_STRING" "$LINENO"
839        return 0
840    fi
841    fastboot_count=$(fastboot devices | grep "$SERIAL_NUMBER" | wc -l)
842    if (( fastboot_count > 0 )); then
843        # try get product by fastboot command
844        local output=$(fastboot -s "$SERIAL_NUMBER" getvar product 2>&1)
845        PRODUCT=$(echo "$output" | grep -oP '^product:\s*\K.*' | cut -d' ' -f1)
846        print_info "$SERIAL_NUMBER is in fastboot with device info: PRODUCT=$PRODUCT" "$LINENO"
847        return 0
848    fi
849    print_error "$SERIAL_NUMBER is not connected with adb or fastboot"
850}
851
852function find_tradefed_bin {
853    cd "$REPO_ROOT_PATH"
854    if [ -f "${ANDROID_HOST_OUT}/bin/tradefed.sh" ] ; then
855        TRADEFED="${ANDROID_HOST_OUT}/bin/tradefed.sh"
856        print_info "Use the tradefed from the local built path $TRADEFED" "$LINENO"
857        return
858    elif [ -f "$PLATFORM_TF_PREBUILT" ]; then
859        TF_BIN="$PLATFORM_TF_PREBUILT"
860        print_info "Local Tradefed is not built yet. Use the prebuilt from $PLATFORM_TF_PREBUILT" "$LINENO"
861    elif [ -f "$KERNEL_TF_PREBUILT" ]; then
862        TF_BIN="$KERNEL_TF_PREBUILT"
863    elif [ -f "/tmp/tradefed/tradefed.sh" ]; then
864        TF_BIN=/tmp/tradefed/tradefed.sh
865    # No Tradefed found
866    else
867        mkdir -p "/tmp/tradefed"
868        cd /tmp/tradefed
869        eval "$FETCH_SCRIPT ab://tradefed/tradefed/latest/google-tradefed.zip"
870        exit_code=$?
871        if [ $exit_code -eq 0 ]; then
872            print_info "Download tradefed succeeded" "$LINENO"
873        else
874            print_error "Download tradefed failed" "$LINENO"
875        fi
876        echo ""
877        eval "unzip -oq google-tradefed.zip"
878        TF_BIN=/tmp/tradefed/tradefed.sh
879        cd "$REPO_ROOT_PATH"
880    fi
881    if [ -d "${ANDROID_JAVA_HOME}" ] ; then
882        JDK_PATH="${ANDROID_JAVA_HOME}"
883    elif [ -d "$PLATFORM_JDK_PATH" ] ; then
884        JDK_PATH="$PLATFORM_JDK_PATH"
885    elif [ -d "$KERNEL_JDK_PATH" ] ; then
886        JDK_PATH="$KERNEL_JDK_PATH"
887    elif [ -d "$LOCAL_JDK_PATH" ] ; then
888        JDK_PATH="$LOCAL_JDK_PATH"
889    else
890        print_error "Can't find JAVA JDK path" "$LINENO"
891    fi
892    TRADEFED="JAVA_HOME=$JDK_PATH PATH=$JDK_PATH/bin:$PATH $TF_BIN"
893}
894
895adb_checker
896
897LOCAL_REPO=
898
899OLD_PWD=$PWD
900MY_NAME=$0
901
902parse_arg "$@"
903
904if [ -z "$SERIAL_NUMBER" ]; then
905    print_error "Device serial is not provided with flag -s <serial_number>." "$LINENO"
906    exit 1
907fi
908
909get_device_info
910
911FULL_COMMAND_PATH=$(dirname "$PWD/$0")
912REPO_LIST_OUT=$(repo list 2>&1)
913if [[ "$REPO_LIST_OUT" == "error"* ]]; then
914    print_error "Current path $PWD is not in an Android repo. Change path to repo root." "$LINENO"
915    go_to_repo_root "$FULL_COMMAND_PATH"
916    print_info "Changed path to $PWD" "$LINENO"
917else
918    go_to_repo_root "$PWD"
919fi
920
921REPO_ROOT_PATH="$PWD"
922FETCH_SCRIPT="$REPO_ROOT_PATH/$FETCH_SCRIPT"
923
924find_repo
925
926if [ ! -d "$DOWNLOAD_PATH" ]; then
927    mkdir -p "$DOWNLOAD_PATH" || $(print_error "Fail to create directory $DOWNLOAD_PATH" "$LINENO")
928fi
929
930if [ ! -z "$PLATFORM_BUILD" ] && [[ "$PLATFORM_BUILD" != ab://* ]] && [ -d "$PLATFORM_BUILD" ]; then
931    # Check if PLATFORM_BUILD is an Android platform repo
932    cd "$PLATFORM_BUILD"
933    PLATFORM_REPO_LIST_OUT=$(repo list 2>&1)
934    if [[ "$PLATFORM_REPO_LIST_OUT" != "error"* ]]; then
935        go_to_repo_root "$PWD"
936        if [[ "$PWD" != "$REPO_ROOT_PATH" ]]; then
937            find_repo
938        fi
939        if [ "$SKIP_BUILD" = false ] && [[ "$PLATFORM_BUILD" != "ab://"* ]] && [[ ! -z "$PLATFORM_BUILD" ]]; then
940            if [ -z "${TARGET_PRODUCT}" ] || [[ "${TARGET_PRODUCT}" != *"$PRODUCT" ]]; then
941                if [[ "$PLATFORM_VERSION" == aosp-* ]]; then
942                    set_platform_repo "aosp_$PRODUCT"
943                else
944                    set_platform_repo "$PRODUCT"
945                fi
946            elif [[ "${TARGET_PRODUCT}" == *"$PRODUCT" ]]; then
947                echo "TARGET_PRODUCT=${TARGET_PRODUCT}, ANDROID_PRODUCT_OUT=${ANDROID_PRODUCT_OUT}"
948            fi
949            if [[ "${TARGET_PRODUCT}" == *"$PRODUCT" ]]; then
950                build_platform
951            else
952                print_error "Can not build platform build due to lunch build target failure" "$LINENO"
953            fi
954        fi
955        if [ -d "${PLATFORM_REPO_ROOT}" ] && [ -f "$PLATFORM_REPO_ROOT/out/target/product/$PRODUCT/otatools.zip" ]; then
956            PLATFORM_BUILD=$PLATFORM_REPO_ROOT/out/target/product/$PRODUCT
957        elif [ -d "${ANDROID_PRODUCT_OUT}" ] && [ -f "${ANDROID_PRODUCT_OUT}/otatools.zip" ]; then
958            PLATFORM_BUILD="${ANDROID_PRODUCT_OUT}"
959        else
960            PLATFORM_BUILD=
961        fi
962    fi
963fi
964
965if [[ "$SYSTEM_BUILD" == ab://* ]]; then
966    print_warn "System build is not supoort yet" "$LINENO"
967elif [ ! -z "$SYSTEM_BUILD" ] && [ -d "$SYSTEM_BUILD" ]; then
968    print_warn "System build is not supoort yet" "$LINENO"
969    # Get GSI build
970    cd "$SYSTEM_BUILD"
971    SYSTEM_REPO_LIST_OUT=$(repo list 2>&1)
972    if [[ "$SYSTEM_REPO_LIST_OUT" != "error"* ]]; then
973        go_to_repo_root "$PWD"
974        if [[ "$PWD" != "$REPO_ROOT_PATH" ]]; then
975            find_repo
976        fi
977        if [ -z "${TARGET_PRODUCT}" ] || [[ "${TARGET_PRODUCT}" != "_arm64" ]]; then
978            set_platform_repo "aosp_arm64"
979            if [ "$SKIP_BUILD" = false ] ; then
980                build_platform
981            fi
982            SYSTEM_BUILD="${ANDROID_PRODUCT_OUT}/system.img"
983        fi
984    fi
985fi
986
987if [[ "$KERNEL_BUILD" == ab://* ]]; then
988    IFS='/' read -ra array <<< "$KERNEL_BUILD"
989    KERNEL_VERSION=$(echo "${array[2]}" | sed "s/aosp_kernel-common-//g")
990    IFS='-' read -ra array <<< "$KERNEL_VERSION"
991    KERNEL_VERSION="${array[0]}-${array[1]}"
992    print_info "$KERNEL_BUILD is KERNEL_VERSION $KERNEL_VERSION" "$LINENO"
993    if [[ "$KERNEL_VERSION" != "$DEVICE_KERNEL_VERSION"* ]] && [ -z "$PLATFORM_BUILD" ] && [ -z "$VENDOR_KERNEL_BUILD" ]; then
994        print_warn "Device $PRODUCT $SERIAL_NUMBER comes with $DEVICE_KERNEL_STRING $DEVICE_KERNEL_VERSION kernel. \
995Can't flash $KERNEL_VERSION GKI directly. Please use a platform build with the $KERNEL_VERSION kernel \
996or use a vendor kernel build by flag -vkb, for example -vkb -vkb ab://kernel-${array[0]}-gs-pixel-${array[1]}/<kernel_target>/latest" "$LINENO"
997        print_error "Cannot flash $KERNEL_VERSION GKI to device $SERIAL_NUMBER directly." "$LINENO"
998    fi
999    print_info "Download kernel build $KERNEL_BUILD" "$LINENO"
1000    if [ -d "$DOWNLOAD_PATH/gki_dir" ]; then
1001        rm -rf "$DOWNLOAD_PATH/gki_dir"
1002    fi
1003    GKI_DIR="$DOWNLOAD_PATH/gki_dir"
1004    mkdir -p "$GKI_DIR"
1005    cd "$GKI_DIR" || $(print_error "Fail to go to $GKI_DIR" "$LINENO")
1006    download_gki_build $KERNEL_BUILD
1007    KERNEL_BUILD="$GKI_DIR"
1008elif [ ! -z "$KERNEL_BUILD" ] && [ -d "$KERNEL_BUILD" ]; then
1009    # Check if kernel repo is provided
1010    cd "$KERNEL_BUILD"
1011    KERNEL_REPO_LIST_OUT=$(repo list 2>&1)
1012    if [[ "$KERNEL_REPO_LIST_OUT" != "error"* ]]; then
1013        go_to_repo_root "$PWD"
1014        if [[ "$PWD" != "$REPO_ROOT_PATH" ]]; then
1015            find_repo
1016        fi
1017        if [ "$SKIP_BUILD" = false ] ; then
1018            if [ ! -f "common/BUILD.bazel" ]; then
1019                # TODO: Add build support to android12 and earlier kernels
1020                print_error "bazel build is not supported in $PWD" "$LINENO"
1021            else
1022                build_ack
1023            fi
1024        fi
1025        KERNEL_BUILD="$PWD/out/kernel_aarch64/dist"
1026    elif [ -f "$KERNEL_BUILD/boot*.img" ]; then
1027        get_kernel_version_from_boot_image "$KERNEL_BUILD/boot*.img"
1028    fi
1029fi
1030
1031if [[ "$VENDOR_KERNEL_BUILD" == ab://* ]]; then
1032    print_info "Download vendor kernel build $VENDOR_KERNEL_BUILD" "$LINENO"
1033    if [ -d "$DOWNLOAD_PATH/vendor_kernel_dir" ]; then
1034        rm -rf "$DOWNLOAD_PATH/vendor_kernel_dir"
1035    fi
1036    VENDOR_KERNEL_DIR="$DOWNLOAD_PATH/vendor_kernel_dir"
1037    mkdir -p "$VENDOR_KERNEL_DIR"
1038    cd "$VENDOR_KERNEL_DIR" || $(print_error "Fail to go to $VENDOR_KERNEL_DIR" "$LINENO")
1039    download_vendor_kernel_build $VENDOR_KERNEL_BUILD
1040    VENDOR_KERNEL_BUILD="$VENDOR_KERNEL_DIR"
1041elif [ ! -z "$VENDOR_KERNEL_BUILD" ] && [ -d "$VENDOR_KERNEL_BUILD" ]; then
1042    # Check if vendor kernel repo is provided
1043    cd "$VENDOR_KERNEL_BUILD"
1044    VENDOR_KERNEL_REPO_LIST_OUT=$(repo list 2>&1)
1045    if [[ "$VENDOR_KERNEL_REPO_LIST_OUT" != "error"* ]]; then
1046        go_to_repo_root "$PWD"
1047        if [[ "$PWD" != "$REPO_ROOT_PATH" ]]; then
1048            find_repo
1049        fi
1050        if [ -z "$VENDOR_KERNEL_BUILD_TARGET" ]; then
1051            kernel_build_target_count=$(ls build_*.sh | wc -w)
1052            if (( kernel_build_target_count == 1 )); then
1053                VENDOR_KERNEL_BUILD_TARGET=$(echo $(ls build_*.sh) | sed 's/build_\(.*\)\.sh/\1/')
1054            elif (( kernel_build_target_count > 1 )); then
1055                print_warn "There are multiple build_*.sh scripts in $PWD, Can't decide vendor kernel build target" "$LINENO"
1056                print_error "Please use -vkbt <value> or --vendor-kernel-build-target=<value> to specify a kernel build target" "$LINENO"
1057            else
1058                # TODO: Add build support to android12 and earlier kernels
1059                print_error "There is no build_*.sh script in $PWD" "$LINENO"
1060            fi
1061        fi
1062        if [ "$SKIP_BUILD" = false ] ; then
1063            build_cmd="./build_$VENDOR_KERNEL_BUILD_TARGET.sh"
1064            if [ "$GCOV" = true ]; then
1065                build_cmd+=" --gcov"
1066            fi
1067            if [ "$DEBUG" = true ]; then
1068                build_cmd+=" --debug"
1069            fi
1070            if [ "$KASAN" = true ]; then
1071                build_cmd+=" --kasan"
1072            fi
1073            print_info "Build vendor kernel with $build_cmd"
1074            eval "$build_cmd"
1075            exit_code=$?
1076            if [ $exit_code -eq 0 ]; then
1077                print_info "Build vendor kernel succeeded"
1078            else
1079                print_error "Build vendor kernel failed with exit code $exit_code"
1080                exit 1
1081            fi
1082        fi
1083        VENDOR_KERNEL_BUILD="$PWD/out/$VENDOR_KERNEL_BUILD_TARGET/dist"
1084    fi
1085fi
1086
1087if [ -z "$PLATFORM_BUILD" ]; then  # No platform build provided
1088    if [ -z "$KERNEL_BUILD" ] && [ -z "$VENDOR_KERNEL_BUILD" ]; then  # No kernel or vendor kernel build
1089        print_info "KERNEL_BUILD=$KERNEL_BUILD VENDOR_KERNEL_BUILD=$VENDOR_KERNEL_BUILD" "$LINENO"
1090        print_error "Nothing to flash" "$LINENO"
1091    elif [ -z "$KERNEL_BUILD" ] && [ ! -z "$VENDOR_KERNEL_BUILD" ]; then  # Only vendor kernel build
1092        print_info "Flash kernel from $VENDOR_KERNEL_BUILD" "$LINENO"
1093        flash_vendor_kernel_build
1094    elif [ ! -z "$KERNEL_BUILD" ] && [ ! -z "$VENDOR_KERNEL_BUILD" ]; then  # Both kernel and vendor kernel builds
1095        print_error "Mixing only GKI build & vendor kernel build is not supported. \
1096Please add platform build for example -pb ab://git_main/$PRODUCT-trunk_staging-userdebug/latest." "$LINENO"
1097    elif [ ! -z "$KERNEL_BUILD" ] && [ -z "$VENDOR_KERNEL_BUILD" ]; then  # Only GKI build
1098        gki_build_only_operation
1099    fi
1100else  # Platform build provided
1101    if [ -z "$KERNEL_BUILD" ] && [ -z "$VENDOR_KERNEL_BUILD" ]; then  # No kernel or vendor kernel build
1102        print_info "Flash platform build only"
1103        flash_platform_build
1104    elif [ -z "$KERNEL_BUILD" ] && [ ! -z "$VENDOR_KERNEL_BUILD" ]; then  # Vendor kernel build and platform build
1105        print_info "Mix vendor kernel and platform build"
1106        mixing_build
1107        flash_platform_build
1108    elif [ ! -z "$KERNEL_BUILD" ] && [ -z "$VENDOR_KERNEL_BUILD" ]; then # GKI build and platform build
1109        flash_platform_build
1110        get_device_info
1111        gki_build_only_operation
1112    elif [ ! -z "$KERNEL_BUILD" ] && [ ! -z "$VENDOR_KERNEL_BUILD" ]; then  # All three builds provided
1113        print_info "Mix GKI kernel, vendor kernel and platform build" "$LINENO"
1114        mixing_build
1115        flash_platform_build
1116    fi
1117fi
1118