| /* |
| * Copyright (C) 2010 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.annotations.VisibleForTesting; |
| import com.android.tradefed.build.IBuildInfo; |
| import com.android.tradefed.build.IDeviceBuildInfo; |
| import com.android.tradefed.config.GlobalConfiguration; |
| import com.android.tradefed.config.IConfiguration; |
| import com.android.tradefed.config.IConfigurationReceiver; |
| import com.android.tradefed.config.IDeviceConfiguration; |
| import com.android.tradefed.config.Option; |
| import com.android.tradefed.device.DeviceNotAvailableException; |
| import com.android.tradefed.device.ITestDevice; |
| import com.android.tradefed.device.ITestDevice.RecoveryMode; |
| import com.android.tradefed.device.NullDevice; |
| import com.android.tradefed.device.SnapuserdWaitPhase; |
| import com.android.tradefed.device.TestDeviceState; |
| import com.android.tradefed.error.HarnessRuntimeException; |
| import com.android.tradefed.host.IHostOptions; |
| import com.android.tradefed.host.IHostOptions.PermitLimitType; |
| import com.android.tradefed.invoker.TestInformation; |
| import com.android.tradefed.invoker.logger.CurrentInvocation.IsolationGrade; |
| import com.android.tradefed.invoker.logger.InvocationMetricLogger; |
| import com.android.tradefed.invoker.logger.InvocationMetricLogger.InvocationMetricKey; |
| import com.android.tradefed.invoker.tracing.CloseableTraceScope; |
| import com.android.tradefed.log.LogUtil.CLog; |
| import com.android.tradefed.result.error.DeviceErrorIdentifier; |
| import com.android.tradefed.result.error.InfraErrorIdentifier; |
| import com.android.tradefed.retry.BaseRetryDecision; |
| import com.android.tradefed.targetprep.IDeviceFlasher.UserDataFlashOption; |
| 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.image.DeviceImageTracker; |
| import com.android.tradefed.util.image.IncrementalImageUtil; |
| |
| import java.io.File; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.concurrent.TimeUnit; |
| |
| /** A {@link ITargetPreparer} that flashes an image on physical Android hardware. */ |
| public abstract class DeviceFlashPreparer extends BaseTargetPreparer |
| implements IConfigurationReceiver { |
| |
| private static final int BOOT_POLL_TIME_MS = 5 * 1000; |
| private static final long SNAPSHOT_CANCEL_TIMEOUT = 20000L; |
| |
| @Option( |
| name = "device-boot-time", |
| description = "max time to wait for device to boot.", |
| isTimeVal = true |
| ) |
| private long mDeviceBootTime = 5 * 60 * 1000; |
| |
| @Option(name = "userdata-flash", description = |
| "specify handling of userdata partition.") |
| private UserDataFlashOption mUserDataFlashOption = UserDataFlashOption.FLASH; |
| |
| @Option(name = "force-system-flash", description = |
| "specify if system should always be flashed even if already running desired build.") |
| private boolean mForceSystemFlash = false; |
| |
| /* |
| * A temporary workaround for special builds. Should be removed after changes from build team. |
| * Bug: 18078421 |
| */ |
| @Deprecated |
| @Option( |
| name = "skip-post-flash-flavor-check", |
| description = "specify if system flavor should not be checked after flash") |
| private boolean mSkipPostFlashFlavorCheck = false; |
| |
| /* |
| * Used for update testing |
| */ |
| @Option(name = "skip-post-flash-build-id-check", description = |
| "specify if build ID should not be checked after flash") |
| private boolean mSkipPostFlashBuildIdCheck = false; |
| |
| @Option(name = "wipe-skip-list", description = |
| "list of /data subdirectories to NOT wipe when doing UserDataFlashOption.TESTS_ZIP") |
| private Collection<String> mDataWipeSkipList = new ArrayList<>(); |
| |
| /** |
| * @deprecated use host-options:concurrent-flasher-limit. |
| */ |
| @Deprecated |
| @Option(name = "concurrent-flasher-limit", description = |
| "No-op, do not use. Left for backwards compatibility.") |
| private Integer mConcurrentFlasherLimit = null; |
| |
| @Option(name = "skip-post-flashing-setup", |
| description = "whether or not to skip post-flashing setup steps") |
| private boolean mSkipPostFlashingSetup = false; |
| |
| @Option(name = "wipe-timeout", |
| description = "the timeout for the command of wiping user data.", isTimeVal = true) |
| private long mWipeTimeout = 4 * 60 * 1000; |
| |
| @Option( |
| name = "fastboot-flash-option", |
| description = "additional options to pass with fastboot flash/update command." |
| ) |
| private Collection<String> mFastbootFlashOptions = new ArrayList<>(); |
| |
| @Option( |
| name = "flash-ramdisk", |
| description = |
| "flashes ramdisk (usually on boot partition) in addition to " |
| + "regular system image") |
| private boolean mShouldFlashRamdisk = false; |
| |
| @Option( |
| name = "ramdisk-partition", |
| description = |
| "the partition (such as boot, vendor_boot) that ramdisk image " |
| + "should be flashed to") |
| private String mRamdiskPartition = "boot"; |
| |
| @Option( |
| name = "cancel-ota-snapshot", |
| description = "In case an OTA snapshot is in progress, cancel it.") |
| private boolean mCancelSnapshot = false; |
| |
| @Option( |
| name = "incremental-flashing", |
| description = "Leverage the incremental flashing feature for device update.") |
| private boolean mUseIncrementalFlashing = false; |
| |
| @Option( |
| name = "force-disable-incremental-flashing", |
| description = "Ignore HostOptions and disable the feature if true.") |
| private boolean mForceDisableIncrementalFlashing = false; |
| |
| @Option( |
| name = "create-snapshot-binary", |
| description = "Override the create_snapshot binary for incremental flashing.") |
| private File mCreateSnapshotBinary = null; |
| |
| @Option( |
| name = "allow-incremental-same-build", |
| description = "Allow doing incremental update on same build.") |
| private boolean mAllowIncrementalOnSameBuild = false; |
| |
| @Option( |
| name = "allow-incremental-cross-release", |
| description = "Allow doing incremental update across release build configs.") |
| private boolean mAllowIncrementalCrossRelease = false; |
| |
| @Option( |
| name = "apply-snapshot", |
| description = |
| "Whether to apply the snapshot after mounting it. " |
| + "This changes the baseline and does require reverting.") |
| private boolean mApplySnapshot = false; |
| |
| @Option( |
| name = "snapuserd-wait-phase", |
| description = |
| "Only applicable to apply-snapshot, blocks snapuserd until a specified phase.") |
| private SnapuserdWaitPhase mWaitPhase = SnapuserdWaitPhase.BLOCK_BEFORE_RELEASING; |
| |
| @Option( |
| name = "allow-unzip-baseline", |
| description = "Whether to allow tracking the baseline as unzipped or not.") |
| private boolean mAllowUnzippedBaseline = false; |
| |
| @Option( |
| name = "enforce-snapshot-completed", |
| description = "Test mode was snapshot to ensure the logic was used and throw if not.") |
| private boolean mEnforceSnapshotCompleted = false; |
| |
| private IncrementalImageUtil mIncrementalImageUtil; |
| private IConfiguration mConfig; |
| |
| @Override |
| public void setConfiguration(IConfiguration configuration) { |
| mConfig = configuration; |
| } |
| |
| /** |
| * Sets the device boot time |
| * <p/> |
| * Exposed for unit testing |
| */ |
| void setDeviceBootTime(long bootTime) { |
| mDeviceBootTime = bootTime; |
| } |
| |
| /** Gets the device boot wait time */ |
| protected long getDeviceBootWaitTime() { |
| return mDeviceBootTime; |
| } |
| |
| /** |
| * Gets the interval between device boot poll attempts. |
| * <p/> |
| * Exposed for unit testing |
| */ |
| int getDeviceBootPollTimeMs() { |
| return BOOT_POLL_TIME_MS; |
| } |
| |
| /** |
| * Gets the {@link IRunUtil} instance to use. |
| * <p/> |
| * Exposed for unit testing |
| */ |
| IRunUtil getRunUtil() { |
| return RunUtil.getDefault(); |
| } |
| |
| /** |
| * Gets the {@link IHostOptions} instance to use. |
| * <p/> |
| * Exposed for unit testing |
| */ |
| protected IHostOptions getHostOptions() { |
| return GlobalConfiguration.getInstance().getHostOptions(); |
| } |
| |
| /** |
| * Set the userdata-flash option |
| * |
| * @param flashOption |
| */ |
| public void setUserDataFlashOption(UserDataFlashOption flashOption) { |
| mUserDataFlashOption = flashOption; |
| } |
| |
| /** Wrap the getBuildInfo so we have a change to override it for specific scenarios. */ |
| public IBuildInfo getBuild(TestInformation testInfo) { |
| return testInfo.getBuildInfo(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public void setUp(TestInformation testInfo) |
| throws TargetSetupError, DeviceNotAvailableException, BuildError { |
| if (testInfo.getDevice().getIDevice() instanceof NullDevice) { |
| CLog.i("Skipping device flashing, this is a null-device."); |
| return; |
| } |
| ITestDevice device = testInfo.getDevice(); |
| IBuildInfo buildInfo = getBuild(testInfo); |
| CLog.i("Performing setup on %s", device.getSerialNumber()); |
| if (!(buildInfo instanceof IDeviceBuildInfo)) { |
| throw new IllegalArgumentException("Provided buildInfo is not a IDeviceBuildInfo"); |
| } |
| IDeviceBuildInfo deviceBuild = (IDeviceBuildInfo) buildInfo; |
| if (mShouldFlashRamdisk && deviceBuild.getRamdiskFile() == null) { |
| throw new HarnessRuntimeException( |
| "ramdisk flashing enabled but no ramdisk file was found in build info", |
| InfraErrorIdentifier.CONFIGURED_ARTIFACT_NOT_FOUND); |
| } |
| // For debugging: log the original build from the device |
| if (TestDeviceState.ONLINE.equals(testInfo.getDevice().getDeviceState())) { |
| buildInfo.addBuildAttribute( |
| "original_build_fingerprint", |
| device.getProperty("ro.product.build.fingerprint")); |
| } |
| |
| long queueTime = -1; |
| long flashingTime = -1; |
| long start = -1; |
| // HostOptions can force the incremental flashing to true. |
| if (getHostOptions().isIncrementalFlashingEnabled()) { |
| mUseIncrementalFlashing = true; |
| } |
| if (getHostOptions().isOptOutOfIncrementalFlashing()) { |
| mUseIncrementalFlashing = false; |
| } |
| if (mConfig != null) { |
| for (IDeviceConfiguration deviceConfig : mConfig.getDeviceConfig()) { |
| for (ITargetPreparer p : deviceConfig.getTargetPreparers()) { |
| if (p instanceof GkiDeviceFlashPreparer |
| && !((GkiDeviceFlashPreparer) p).isDisabled() |
| && !mApplySnapshot) { |
| CLog.d( |
| "Force disabling incremental flashing due to" |
| + " GkiDeviceFlashPreparer."); |
| mForceDisableIncrementalFlashing = true; |
| } |
| } |
| } |
| } |
| if (mForceDisableIncrementalFlashing) { |
| // The local option disable the feature, and skip tracking baseline |
| // for this run to avoid tracking a potentially bad baseline. |
| mUseIncrementalFlashing = false; |
| // Do not keep a cache when we are about to override it |
| DeviceImageTracker.getDefaultCache().invalidateTracking(device.getSerialNumber()); |
| } |
| boolean useIncrementalFlashing = mUseIncrementalFlashing; |
| boolean reEntry = false; |
| if (useIncrementalFlashing) { |
| boolean isIsolated = false; |
| if (mConfig.getRetryDecision() instanceof BaseRetryDecision) { |
| isIsolated = |
| IsolationGrade.FULLY_ISOLATED.equals( |
| ((BaseRetryDecision) mConfig.getRetryDecision()) |
| .getIsolationGrade()); |
| } |
| if (mIncrementalImageUtil != null) { |
| // Re-entry can occur during reset isolation. |
| reEntry = true; |
| } else { |
| mIncrementalImageUtil = |
| IncrementalImageUtil.initialize( |
| device, |
| deviceBuild, |
| mCreateSnapshotBinary, |
| isIsolated, |
| mAllowIncrementalCrossRelease, |
| mApplySnapshot, |
| mWaitPhase); |
| if (mIncrementalImageUtil == null) { |
| useIncrementalFlashing = false; |
| } else { |
| if (mAllowIncrementalOnSameBuild) { |
| mIncrementalImageUtil.allowSameBuildFlashing(); |
| } |
| if (TestDeviceState.ONLINE.equals(device.getDeviceState())) { |
| // No need to reboot yet, it will happen later in the sequence |
| String verityOutput = device.executeAdbCommand("enable-verity"); |
| CLog.d("%s", verityOutput); |
| } |
| } |
| } |
| } |
| try { |
| checkDeviceProductType(device, deviceBuild); |
| device.setRecoveryMode(RecoveryMode.ONLINE); |
| IDeviceFlasher flasher = createFlasher(device); |
| flasher.setWipeTimeout(mWipeTimeout); |
| boolean tookPermit = false; |
| // only surround fastboot related operations with flashing permit restriction |
| try { |
| flasher.overrideDeviceOptions(device); |
| flasher.setUserDataFlashOption(mUserDataFlashOption); |
| flasher.setForceSystemFlash(mForceSystemFlash); |
| flasher.setDataWipeSkipList(mDataWipeSkipList); |
| flasher.setShouldFlashRamdisk(mShouldFlashRamdisk); |
| if (mShouldFlashRamdisk) { |
| flasher.setRamdiskPartition(mRamdiskPartition); |
| } |
| if (flasher instanceof FastbootDeviceFlasher) { |
| ((FastbootDeviceFlasher) flasher).setFlashOptions(mFastbootFlashOptions); |
| if (!reEntry) { |
| // Avoid using incremental during re-entry since it will just wipe |
| ((FastbootDeviceFlasher) flasher) |
| .setIncrementalFlashing(mIncrementalImageUtil); |
| } |
| } |
| start = System.currentTimeMillis(); |
| flasher.preFlashOperations(device, deviceBuild); |
| // After preFlashOperations device should be in bootloader |
| if (mCancelSnapshot && TestDeviceState.FASTBOOT.equals(device.getDeviceState())) { |
| CommandResult res = |
| device.executeFastbootCommand( |
| SNAPSHOT_CANCEL_TIMEOUT, "snapshot-update", "cancel"); |
| if (!CommandStatus.SUCCESS.equals(res.getStatus())) { |
| CLog.w( |
| "Failed to cancel snapshot: %s.\nstdout:%s\nstderr:%s", |
| res.getStatus(), res.getStdout(), res.getStderr()); |
| } |
| } |
| try (CloseableTraceScope ignored = |
| new CloseableTraceScope("wait_for_flashing_permit")) { |
| if (mIncrementalImageUtil == null) { |
| // Only #flash is included in the critical section |
| getHostOptions().takePermit(PermitLimitType.CONCURRENT_FLASHER); |
| tookPermit = true; |
| } |
| queueTime = System.currentTimeMillis() - start; |
| if (tookPermit) { |
| CLog.v( |
| "Flashing permit obtained after %ds", |
| TimeUnit.MILLISECONDS.toSeconds(queueTime)); |
| } |
| InvocationMetricLogger.addInvocationMetrics( |
| InvocationMetricKey.FLASHING_PERMIT_LATENCY, queueTime); |
| } |
| // Don't allow interruptions during flashing operations. |
| getRunUtil().allowInterrupt(false); |
| start = System.currentTimeMillis(); |
| // Set flashing method as unknown here as a fallback, in case it wasn't overwritten |
| // by subclass implementations |
| InvocationMetricLogger.addInvocationMetrics( |
| InvocationMetricKey.FLASHING_METHOD, |
| FlashingMethod.FASTBOOT_UNCATEGORIZED.toString()); |
| flasher.flash(device, deviceBuild); |
| } catch (DeviceNotAvailableException | TargetSetupError | RuntimeException e) { |
| // Clear tracking in case of error |
| DeviceImageTracker.getDefaultCache().invalidateTracking(device.getSerialNumber()); |
| throw e; |
| } finally { |
| flashingTime = System.currentTimeMillis() - start; |
| if (tookPermit) { |
| getHostOptions().returnPermit(PermitLimitType.CONCURRENT_FLASHER); |
| } |
| flasher.postFlashOperations(device, deviceBuild); |
| // report flashing status |
| CommandStatus status = flasher.getSystemFlashingStatus(); |
| if (status == null) { |
| CLog.i("Skipped reporting metrics because system partitions were not flashed."); |
| } else { |
| if (mIncrementalImageUtil != null) { |
| InvocationMetricLogger.addInvocationMetrics( |
| InvocationMetricKey.INCREMENTAL_FLASHING_TIME, flashingTime); |
| } |
| InvocationMetricLogger.addInvocationMetrics( |
| InvocationMetricKey.FLASHING_TIME, flashingTime); |
| reportFlashMetrics(buildInfo.getBuildBranch(), buildInfo.getBuildFlavor(), |
| buildInfo.getBuildId(), device.getSerialNumber(), queueTime, |
| flashingTime, status); |
| } |
| } |
| if (mIncrementalImageUtil == null) { |
| // only want logcat captured for current build, delete any accumulated log data |
| device.clearLogcat(); |
| } |
| // In case success with full flashing |
| if (!reEntry) { |
| moveBaseline(deviceBuild, device.getSerialNumber(), useIncrementalFlashing); |
| } |
| if (mSkipPostFlashingSetup) { |
| return; |
| } |
| // Temporary re-enable interruptable since the critical flashing operation is over. |
| getRunUtil().allowInterrupt(true); |
| device.waitForDeviceOnline(); |
| // device may lose date setting if wiped, update with host side date in case anything on |
| // device side malfunction with an invalid date |
| if (device.enableAdbRoot()) { |
| device.setDate(null); |
| } |
| // Disable interrupt for encryption operation. |
| getRunUtil().allowInterrupt(false); |
| checkBuild(device, deviceBuild); |
| // Once critical operation is done, we re-enable interruptable |
| getRunUtil().allowInterrupt(true); |
| try { |
| boolean available = device.waitForDeviceAvailableInRecoverPath(mDeviceBootTime); |
| if (!available) { |
| // Clear tracking in case of error |
| DeviceImageTracker.getDefaultCache() |
| .invalidateTracking(device.getSerialNumber()); |
| throw new DeviceFailedToBootError( |
| String.format( |
| "Device %s did not become available after flashing %s", |
| device.getSerialNumber(), deviceBuild.getDeviceBuildId()), |
| device.getDeviceDescriptor(), |
| DeviceErrorIdentifier.ERROR_AFTER_FLASHING); |
| } |
| } catch (DeviceNotAvailableException e) { |
| // Clear tracking in case of error |
| DeviceImageTracker.getDefaultCache().invalidateTracking(device.getSerialNumber()); |
| // Assume this is a build problem |
| throw new DeviceFailedToBootError( |
| String.format( |
| "Device %s did not become available after flashing %s", |
| device.getSerialNumber(), deviceBuild.getDeviceBuildId()), |
| device.getDeviceDescriptor(), |
| e, |
| DeviceErrorIdentifier.ERROR_AFTER_FLASHING); |
| } |
| device.postBootSetup(); |
| } finally { |
| device.setRecoveryMode(RecoveryMode.AVAILABLE); |
| // Allow interruption at the end no matter what. |
| getRunUtil().allowInterrupt(true); |
| if (mIncrementalImageUtil != null) { |
| mIncrementalImageUtil.cleanAfterSetup(); |
| } |
| } |
| } |
| |
| private void moveBaseline( |
| IDeviceBuildInfo deviceBuild, String serial, boolean useIncrementalFlashing) { |
| if (!getHostOptions().isOptOutOfIncrementalFlashing()) { |
| boolean moveBaseLine = true; |
| if (!mUseIncrementalFlashing || useIncrementalFlashing) { |
| // Do not move baseline if using incremental flashing |
| moveBaseLine = false; |
| } |
| if (mApplySnapshot) { |
| // Move baseline when going with incremental + apply update |
| moveBaseLine = true; |
| } |
| if (moveBaseLine) { |
| File deviceImage = deviceBuild.getDeviceImageFile(); |
| File tmpReference = null; |
| try { |
| if (mAllowUnzippedBaseline |
| && mIncrementalImageUtil != null |
| && mIncrementalImageUtil.getExtractedTargetDirectory() != null |
| && mIncrementalImageUtil.getExtractedTargetDirectory().isDirectory()) { |
| CLog.d( |
| "Using unzipped baseline: %s", |
| mIncrementalImageUtil.getExtractedTargetDirectory()); |
| tmpReference = mIncrementalImageUtil.getExtractedTargetDirectory(); |
| deviceImage = tmpReference; |
| } |
| DeviceImageTracker.getDefaultCache() |
| .trackUpdatedDeviceImage( |
| serial, |
| deviceImage, |
| deviceBuild.getBootloaderImageFile(), |
| deviceBuild.getBasebandImageFile(), |
| deviceBuild.getBuildId(), |
| deviceBuild.getBuildBranch(), |
| deviceBuild.getBuildFlavor()); |
| } finally { |
| FileUtil.recursiveDelete(tmpReference); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Possible check before flashing to ensure the device is as expected compare to the build info. |
| * |
| * @param device the {@link ITestDevice} to flash. |
| * @param deviceBuild the {@link IDeviceBuildInfo} used to flash. |
| * @throws BuildError |
| * @throws DeviceNotAvailableException |
| */ |
| protected void checkDeviceProductType(ITestDevice device, IDeviceBuildInfo deviceBuild) |
| throws BuildError, DeviceNotAvailableException { |
| // empty of purpose |
| } |
| |
| /** |
| * Verifies the expected build matches the actual build on device after flashing |
| * @throws DeviceNotAvailableException |
| */ |
| private void checkBuild(ITestDevice device, IDeviceBuildInfo deviceBuild) |
| throws DeviceNotAvailableException { |
| // Need to use deviceBuild.getDeviceBuildId instead of getBuildId because the build info |
| // could be an AppBuildInfo and return app build id. Need to be more explicit that we |
| // check for the device build here. |
| if (!mSkipPostFlashBuildIdCheck) { |
| checkBuildAttribute(deviceBuild.getDeviceBuildId(), device.getBuildId(), |
| device.getSerialNumber()); |
| } |
| } |
| |
| private void checkBuildAttribute(String expectedBuildAttr, String actualBuildAttr, |
| String serial) throws DeviceNotAvailableException { |
| if (expectedBuildAttr == null || actualBuildAttr == null || |
| !expectedBuildAttr.equals(actualBuildAttr)) { |
| // throw DNAE - assume device hardware problem - we think flash was successful but |
| // device is not running right bits |
| throw new DeviceNotAvailableException( |
| String.format( |
| "Unexpected build after flashing. Expected %s, actual %s", |
| expectedBuildAttr, actualBuildAttr), |
| serial, |
| DeviceErrorIdentifier.ERROR_AFTER_FLASHING); |
| } |
| } |
| |
| /** |
| * Create {@link IDeviceFlasher} to use. Subclasses can override |
| * @throws DeviceNotAvailableException |
| */ |
| protected abstract IDeviceFlasher createFlasher(ITestDevice device) |
| throws DeviceNotAvailableException; |
| |
| @Override |
| public void tearDown(TestInformation testInfo, Throwable e) throws DeviceNotAvailableException { |
| if (testInfo.getDevice().getIDevice() instanceof NullDevice) { |
| CLog.i("Skipping device flashing tearDown, this is a null-device."); |
| return; |
| } |
| if (mIncrementalImageUtil != null) { |
| CLog.d("Teardown related to incremental update."); |
| RecoveryMode mode = testInfo.getDevice().getRecoveryMode(); |
| try { |
| testInfo.getDevice().setRecoveryMode(RecoveryMode.NONE); |
| if (mAllowUnzippedBaseline) { |
| mIncrementalImageUtil.allowUnzipBaseline(); |
| } |
| mIncrementalImageUtil.teardownDevice(testInfo); |
| } finally { |
| testInfo.getDevice().setRecoveryMode(mode); |
| } |
| } |
| if (mEnforceSnapshotCompleted && e == null) { |
| if (mIncrementalImageUtil == null || !mIncrementalImageUtil.updateCompleted()) { |
| throw new RuntimeException( |
| "We expected incremental-flashing to be used but wasn't."); |
| } |
| } |
| } |
| |
| /** |
| * Reports device flashing timing data to metrics backend |
| * @param branch the branch where the device build originated from |
| * @param buildFlavor the build flavor of the device build |
| * @param buildId the build number of the device build |
| * @param serial the serial number of device |
| * @param queueTime the time spent waiting for a flashing limit to become available |
| * @param flashingTime the time spent in flashing device image zip |
| * @param flashingStatus the execution status of flashing command |
| */ |
| protected void reportFlashMetrics(String branch, String buildFlavor, String buildId, |
| String serial, long queueTime, long flashingTime, CommandStatus flashingStatus) { |
| // no-op as default implementation |
| } |
| |
| /** |
| * Sets the option for whether ramdisk should be flashed |
| * |
| * @param shouldFlashRamdisk |
| */ |
| @VisibleForTesting |
| void setShouldFlashRamdisk(boolean shouldFlashRamdisk) { |
| mShouldFlashRamdisk = shouldFlashRamdisk; |
| } |
| |
| protected void setSkipPostFlashBuildIdCheck(boolean skipPostFlashBuildIdCheck) { |
| mSkipPostFlashBuildIdCheck = skipPostFlashBuildIdCheck; |
| } |
| |
| protected void setUseIncrementalFlashing(boolean incrementalFlashing) { |
| mUseIncrementalFlashing = incrementalFlashing; |
| } |
| |
| public boolean isIncrementalFlashingEnabled() { |
| return mUseIncrementalFlashing; |
| } |
| |
| public boolean isIncrementalFlashingForceDisabled() { |
| return mForceDisableIncrementalFlashing; |
| } |
| |
| public void setAllowCrossReleaseFlashing(boolean allowCrossReleaseFlashing) { |
| mAllowIncrementalCrossRelease = allowCrossReleaseFlashing; |
| } |
| |
| public void setApplySnapshot(boolean applySnapshot) { |
| mApplySnapshot = applySnapshot; |
| } |
| |
| public void setAllowUnzipBaseline(boolean allowUnzipBaseline) { |
| mAllowUnzippedBaseline = allowUnzipBaseline; |
| } |
| } |