/*
 * Copyright (C) 2020 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.
 */
package com.android.tradefed.targetprep;

import com.android.tradefed.build.IDeviceBuildInfo;
import com.android.tradefed.config.GlobalConfiguration;
import com.android.tradefed.config.Option;
import com.android.tradefed.config.OptionClass;
import com.android.tradefed.device.DeviceNotAvailableException;
import com.android.tradefed.device.DeviceUnresponsiveException;
import com.android.tradefed.device.IDeviceManager;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.device.ITestDevice.RecoveryMode;
import com.android.tradefed.invoker.TestInformation;
import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.util.CommandResult;
import com.android.tradefed.util.CommandStatus;
import com.android.tradefed.util.FileUtil;
import com.android.tradefed.util.IRunUtil;
import com.android.tradefed.util.RunUtil;
import com.android.tradefed.util.ZipUtil2;

import com.google.common.annotations.VisibleForTesting;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * A target preparer that flash the device with android common kernel generic image. Please see
 * https://source.android.com/devices/architecture/kernel/android-common for details.
 */
@OptionClass(alias = "gki-device-flash-preparer")
public class GkiDeviceFlashPreparer extends BaseTargetPreparer {

    private static final String GKI_BOOT_IMG = "gki_boot.img";
    private static final String MKBOOTIMG = "mkbootimg";
    private static final String OTATOOLS_ZIP = "otatools.zip";
    private static final String RAMDISK_RECOVERY_IMG = "ramdisk_recovery.img";
    private static final String KERNEL_IMAGE = "kernel_image"; // The Image.gz file key
    private static final String VENDOR_BOOT_IMG = "vendor_boot.img";
    private static final String DTBO_IMG = "dtbo.img";
    // Wait time for device state to stablize in millisecond
    private static final int STATE_STABLIZATION_WAIT_TIME = 60000;

    @Option(
            name = "device-boot-time",
            description = "max time to wait for device to boot. Set as 5 minutes by default",
            isTimeVal = true)
    private long mDeviceBootTime = 5 * 60 * 1000;

    // The temp directory for files generated by target preparer
    private File mPreparerTmpDir;

    /** {@inheritDoc} */
    @Override
    public void setUp(TestInformation testInfo)
            throws TargetSetupError, BuildError, DeviceNotAvailableException {
        ITestDevice device = testInfo.getDevice();
        IDeviceBuildInfo buildInfo = (IDeviceBuildInfo) testInfo.getBuildInfo();

        try {
            mPreparerTmpDir = FileUtil.createTempDir("gki_preparer_setup");
            validateGkiBootImg(device, buildInfo);
            flashGki(device, buildInfo);
        } catch (IOException ioe) {
            throw new TargetSetupError(ioe.getMessage(), ioe, device.getDeviceDescriptor());
        } finally {
            FileUtil.recursiveDelete(mPreparerTmpDir);
        }
        // Wait some time after flashing the image.
        getRunUtil().sleep(STATE_STABLIZATION_WAIT_TIME);
        device.rebootUntilOnline();
        if (device.enableAdbRoot()) {
            device.setDate(null);
        }
        try {
            device.setRecoveryMode(RecoveryMode.AVAILABLE);
            device.waitForDeviceAvailable(mDeviceBootTime);
        } catch (DeviceUnresponsiveException e) {
            // assume this is a build problem
            throw new DeviceFailedToBootError(
                    String.format(
                            "Device %s did not become available after flashing GKI. Exception: %s",
                            device.getSerialNumber(), e),
                    device.getDeviceDescriptor());
        }
        device.postBootSetup();
        CLog.i("Device update completed on %s", device.getDeviceDescriptor());
    }

    /**
     * Get a reference to the {@link IDeviceManager}
     *
     * @return the {@link IDeviceManager} to use
     */
    @VisibleForTesting
    IDeviceManager getDeviceManager() {
        return GlobalConfiguration.getDeviceManagerInstance();
    }

    /**
     * Get the {@link IRunUtil} instance to use.
     *
     * @return the {@link IRunUtil} to use
     */
    @VisibleForTesting
    protected IRunUtil getRunUtil() {
        return RunUtil.getDefault();
    }

    /**
     * Flash GKI images.
     *
     * @param device the {@link ITestDevice}
     * @param buildInfo the {@link IDeviceBuildInfo} the device build info
     * @throws TargetSetupError, DeviceNotAvailableException, IOException
     */
    private void flashGki(ITestDevice device, IDeviceBuildInfo buildInfo)
            throws TargetSetupError, DeviceNotAvailableException {
        IDeviceManager deviceManager = getDeviceManager();
        device.waitForDeviceOnline();
        device.rebootIntoBootloader();
        long start = System.currentTimeMillis();
        deviceManager.takeFlashingPermit();
        CLog.v(
                "Flashing permit obtained after %ds",
                TimeUnit.MILLISECONDS.toSeconds((System.currentTimeMillis() - start)));
        // Don't allow interruptions during flashing operations.
        getRunUtil().allowInterrupt(false);
        try {
            if (buildInfo.getFile(VENDOR_BOOT_IMG) != null) {
                executeFastbootCmd(
                        device,
                        "flash",
                        "vendor_boot",
                        buildInfo.getFile(VENDOR_BOOT_IMG).getAbsolutePath());
            }
            if (buildInfo.getFile(DTBO_IMG) != null) {
                executeFastbootCmd(
                        device, "flash", "dtbo", buildInfo.getFile(DTBO_IMG).getAbsolutePath());
            }
            executeFastbootCmd(
                    device, "flash", "boot", buildInfo.getFile(GKI_BOOT_IMG).getAbsolutePath());
        } finally {
            deviceManager.returnFlashingPermit();
            // Allow interruption at the end no matter what.
            getRunUtil().allowInterrupt(true);
            CLog.v(
                    "Flashing permit returned after %ds",
                    TimeUnit.MILLISECONDS.toSeconds((System.currentTimeMillis() - start)));
        }
    }

    /**
     * Validate GKI boot image is expected. Throw exception if there is no valid boot.img.
     *
     * @param device the {@link ITestDevice}
     * @param buildInfo the {@link IDeviceBuildInfo} the device build info
     * @throws TargetSetupError, IOException if there is no valid gki boot.img
     */
    public void validateGkiBootImg(ITestDevice device, IDeviceBuildInfo buildInfo)
            throws TargetSetupError {
        if (buildInfo.getFile(GKI_BOOT_IMG) != null
                && buildInfo.getFile(GKI_BOOT_IMG).length() > 0) {
            return;
        }
        if (buildInfo.getFile(KERNEL_IMAGE) == null) {
            throw new TargetSetupError(
                    KERNEL_IMAGE + " is not provided. Can not generate GKI boot.img.",
                    device.getDeviceDescriptor());
        }
        if (buildInfo.getFile(RAMDISK_RECOVERY_IMG) == null) {
            throw new TargetSetupError(
                    RAMDISK_RECOVERY_IMG + " is not provided. Can not generate GKI boot.img.",
                    device.getDeviceDescriptor());
        }
        try {
            File mkbootimg = getRequestedFile(device, MKBOOTIMG, buildInfo.getFile(OTATOOLS_ZIP));
            File gkiBootImg = FileUtil.createTempFile("boot", ".img", mPreparerTmpDir);
            String cmd =
                    String.format(
                            "%s --kernel %s --header_version 3 --base 0x00000000 "
                                    + "--pagesize 4096 --ramdisk %s -o %s",
                            mkbootimg.getAbsolutePath(),
                            buildInfo.getFile(KERNEL_IMAGE),
                            buildInfo.getFile(RAMDISK_RECOVERY_IMG),
                            gkiBootImg.getAbsolutePath());
            executeHostCommand(device, cmd);
            CLog.i("The GKI boot.img is of size %d", gkiBootImg.length());
            if (gkiBootImg.length() > 0) {
                buildInfo.setFile(GKI_BOOT_IMG, gkiBootImg, "0");
            } else {
                throw new TargetSetupError(
                        "The mkbootimg tool didn't generate a valid boot.img.",
                        device.getDeviceDescriptor());
            }
        } catch (IOException e) {
            throw new TargetSetupError("Fail to get mkbootimg.", e, device.getDeviceDescriptor());
        }
    }

    /**
     * Flash device images.
     *
     * @param device the {@link ITestDevice}
     * @param buildInfo the {@link IDeviceBuildInfo} the device build info
     * @throws TargetSetupError, DeviceNotAvailableException
     */
    private void flashDeviceImage(ITestDevice device, IDeviceBuildInfo buildInfo)
            throws TargetSetupError, DeviceNotAvailableException {
        IDeviceManager deviceManager = getDeviceManager();
        long start = System.currentTimeMillis();
        deviceManager.takeFlashingPermit();
        CLog.v(
                "Flashing permit obtained after %ds",
                TimeUnit.MILLISECONDS.toSeconds((System.currentTimeMillis() - start)));
        // don't allow interruptions during flashing operations.
        getRunUtil().allowInterrupt(false);
        try {
            executeFastbootCmd(
                    device,
                    "--skip-reboot",
                    "--disable-verity",
                    "update",
                    buildInfo.getDeviceImageFile().getAbsolutePath());
        } finally {
            // Allow interruption at the end no matter what.
            getRunUtil().allowInterrupt(true);
            deviceManager.returnFlashingPermit();
            CLog.v(
                    "Flashing permit returned after %ds",
                    TimeUnit.MILLISECONDS.toSeconds((System.currentTimeMillis() - start)));
        }
    }

    /**
     * Helper method to execute host command.
     *
     * @param device the {@link ITestDevice}
     * @param command the command string
     * @throws TargetSetupError, DeviceNotAvailableException
     */
    private void executeHostCommand(ITestDevice device, final String command)
            throws TargetSetupError {
        final CommandResult result = getRunUtil().runTimedCmd(300000L, command.split("\\s+"));
        switch (result.getStatus()) {
            case SUCCESS:
                CLog.i(
                        "Command %s finished successfully, stdout = [%s].",
                        command, result.getStdout());
                break;
            case FAILED:
                throw new TargetSetupError(
                        String.format(
                                "Command %s failed, stdout = [%s], stderr = [%s].",
                                command, result.getStdout(), result.getStderr()),
                        device.getDeviceDescriptor());
            case TIMED_OUT:
                throw new TargetSetupError(
                        String.format("Command %s timed out.", command),
                        device.getDeviceDescriptor());
            case EXCEPTION:
                throw new TargetSetupError(
                        String.format("Exception occurred when running command %s.", command),
                        device.getDeviceDescriptor());
        }
    }

    /**
     * Get the requested file from the source file (zip or folder) by requested file name.
     *
     * <p>The provided source file can be a zip file. The method will unzip it to tempary directory
     * and find the requested file by the provided file name.
     *
     * <p>The provided source file can be a file folder. The method will find the requestd file by
     * the provided file name.
     *
     * @param device the {@link ITestDevice}
     * @param requestedFileName the requeste file name String
     * @param sourceFile the source file
     * @return the file that is specified by the requested file name
     * @throws TargetSetupError, IOException
     */
    private File getRequestedFile(ITestDevice device, String requestedFileName, File sourceFile)
            throws TargetSetupError, IOException {
        File requestedFile = null;
        if (sourceFile.getName().endsWith(".zip")) {
            File destDir =
                    FileUtil.createTempDir(
                            FileUtil.getBaseName(sourceFile.getName()), mPreparerTmpDir);
            ZipUtil2.extractZip(sourceFile, destDir);
            requestedFile = FileUtil.findFile(destDir, requestedFileName);
        } else if (sourceFile.isDirectory()) {
            requestedFile = FileUtil.findFile(sourceFile, requestedFileName);
        }
        if (requestedFile == null || !requestedFile.exists()) {
            throw new TargetSetupError(
                    String.format(
                            "Requested file with file_name %s does not exist in provided %s.",
                            requestedFileName, sourceFile),
                    device.getDeviceDescriptor());
        }
        return requestedFile;
    }

    /**
     * Helper method to execute a fastboot command.
     *
     * @param device the {@link ITestDevice} to execute command on
     * @param cmdArgs the arguments to provide to fastboot
     * @return String the stderr output from command if non-empty. Otherwise returns the stdout Some
     *     fastboot commands are weird in that they dump output to stderr on success case
     * @throws DeviceNotAvailableException if device is not available
     * @throws TargetSetupError if fastboot command fails
     */
    private String executeFastbootCmd(ITestDevice device, String... cmdArgs)
            throws DeviceNotAvailableException, TargetSetupError {
        CLog.i("Execute fastboot command %s on %s", cmdArgs, device.getSerialNumber());
        CommandResult result = device.executeLongFastbootCommand(cmdArgs);
        CLog.v("fastboot stdout: " + result.getStdout());
        CLog.v("fastboot stderr: " + result.getStderr());
        CommandStatus cmdStatus = result.getStatus();
        // fastboot command line output is in stderr even for successful run
        if (result.getStderr().contains("FAILED")) {
            // if output contains "FAILED", just override to failure
            cmdStatus = CommandStatus.FAILED;
        }
        if (cmdStatus != CommandStatus.SUCCESS) {
            throw new TargetSetupError(
                    String.format(
                            "fastboot command %s failed in device %s. stdout: %s, stderr: %s",
                            cmdArgs[0],
                            device.getSerialNumber(),
                            result.getStdout(),
                            result.getStderr()),
                    device.getDeviceDescriptor());
        }
        if (result.getStderr().length() > 0) {
            return result.getStderr();
        } else {
            return result.getStdout();
        }
    }
}
