| /* |
| * Copyright (C) 2012 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.IBuildInfo; |
| import com.android.tradefed.build.KernelDeviceBuildInfo; |
| import com.android.tradefed.device.DeviceNotAvailableException; |
| import com.android.tradefed.device.DeviceUnresponsiveException; |
| import com.android.tradefed.device.ITestDevice; |
| 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 java.io.File; |
| import java.io.IOException; |
| |
| /** |
| * A {@link ITargetPreparer} that flashes a kernel on the device. |
| */ |
| public class KernelFlashPreparer implements ITargetPreparer { |
| |
| /** |
| * {@inheritDoc} |
| * <p> |
| * Expects a {@link KernelDeviceBuildInfo} that returns non-null values for |
| * {@link KernelDeviceBuildInfo#getMkbootimgFile()} and |
| * {@link KernelDeviceBuildInfo#getRamdiskFile()}. |
| * </p> |
| */ |
| @Override |
| public void setUp(ITestDevice device, IBuildInfo buildInfo) throws TargetSetupError, |
| BuildError, DeviceNotAvailableException { |
| if (!(buildInfo instanceof KernelDeviceBuildInfo)) { |
| throw new IllegalArgumentException("Provided buildInfo is not a KernelDeviceBuildInfo"); |
| } |
| |
| KernelDeviceBuildInfo kernelBuildInfo = (KernelDeviceBuildInfo) buildInfo; |
| CLog.i("Flashing device %s running %s with kernel %s", device.getSerialNumber(), |
| device.getBuildId(), kernelBuildInfo.getSha1()); |
| |
| if (kernelBuildInfo.getRamdiskFile() == null) { |
| throw new TargetSetupError("Missing ramdisk file"); |
| } |
| if (kernelBuildInfo.getMkbootimgFile() == null) { |
| throw new TargetSetupError("Missing mkbootimg file"); |
| } |
| if (kernelBuildInfo.getKernelFile() == null) { |
| throw new TargetSetupError("Missing kernel file"); |
| } |
| |
| kernelBuildInfo.getMkbootimgFile().setExecutable(true); |
| |
| File boot = null; |
| try { |
| boot = createBootImage(kernelBuildInfo.getMkbootimgFile(), |
| kernelBuildInfo.getKernelFile(), kernelBuildInfo.getRamdiskFile()); |
| } catch (IOException e) { |
| throw new TargetSetupError("Could not create boot image", e); |
| } |
| |
| try { |
| device.rebootIntoBootloader(); |
| CLog.d("fastboot flash boot %s", boot.getAbsolutePath()); |
| device.executeFastbootCommand("flash", "boot", boot.getAbsolutePath()); |
| } finally { |
| FileUtil.deleteFile(boot); |
| } |
| |
| try { |
| device.reboot(); |
| } catch (DeviceUnresponsiveException e) { |
| // assume this is a build problem |
| throw new BuildError(String.format("Device %s did not become available after " + |
| "flashing kernel", device.getSerialNumber())); |
| } |
| device.postBootSetup(); |
| } |
| |
| /** |
| * Creates a boot.img file using mkbootimg, ramdisk, and kernel files. |
| * <p> |
| * Runs {@code mkbootimg --kernel (filename) --ramdisk (filename) -o (filename)} to create a |
| * boot.img image file. Exposed for unit testing. |
| * </p> |
| * |
| * @param mkbootimg the mkbootimg executable |
| * @param kernel the kernel file |
| * @param ramdisk the ramdisk file |
| * @return a boot.img {@link File} for the build and kernel build |
| * @throws IOException if there was an exception making the boot image |
| */ |
| File createBootImage(File mkbootimg, File kernel, File ramdisk) throws IOException { |
| CLog.d("Create boot.img from %s and %s", kernel.getAbsolutePath(), |
| ramdisk.getAbsolutePath()); |
| String bootPath = getBootImgPath(); |
| try { |
| String[] cmd = {mkbootimg.getAbsolutePath(), "--kernel", kernel.getAbsolutePath(), |
| "--ramdisk", ramdisk.getAbsolutePath(), "-o", bootPath}; |
| CommandResult result = getRunUtil().runTimedCmd(30 * 1000, cmd); |
| if (result.getStatus() != CommandStatus.SUCCESS) { |
| CLog.e("mkbootimg failed. Command status was %s", result.getStatus()); |
| FileUtil.deleteFile(new File(bootPath)); |
| throw new IOException(); |
| } |
| } catch (IOException e) { |
| FileUtil.deleteFile(new File(bootPath)); |
| throw e; |
| } catch (RuntimeException e) { |
| FileUtil.deleteFile(new File(bootPath)); |
| throw e; |
| } |
| return new File(bootPath); |
| } |
| |
| /** |
| * Get an {@link IRunUtil} instance. Exposed for unit testing. |
| */ |
| IRunUtil getRunUtil() { |
| return RunUtil.getDefault(); |
| } |
| |
| /** |
| * Create a path for the boot image using {@link FileUtil#createTempFile(String, String)}. |
| * Exposed for unit testing. |
| */ |
| String getBootImgPath() throws IOException { |
| File bootImg = FileUtil.createTempFile("boot", ".img"); |
| String bootImgPath = bootImg.getAbsolutePath(); |
| FileUtil.deleteFile(bootImg); |
| return bootImgPath; |
| } |
| } |