1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.tradefed.targetprep; 18 19 import com.android.annotations.VisibleForTesting; 20 import com.android.tradefed.build.IBuildInfo; 21 import com.android.tradefed.build.IDeviceBuildInfo; 22 import com.android.tradefed.config.GlobalConfiguration; 23 import com.android.tradefed.config.IConfiguration; 24 import com.android.tradefed.config.IConfigurationReceiver; 25 import com.android.tradefed.config.IDeviceConfiguration; 26 import com.android.tradefed.config.Option; 27 import com.android.tradefed.device.DeviceNotAvailableException; 28 import com.android.tradefed.device.ITestDevice; 29 import com.android.tradefed.device.ITestDevice.RecoveryMode; 30 import com.android.tradefed.device.NullDevice; 31 import com.android.tradefed.device.SnapuserdWaitPhase; 32 import com.android.tradefed.device.TestDeviceState; 33 import com.android.tradefed.error.HarnessRuntimeException; 34 import com.android.tradefed.host.IHostOptions; 35 import com.android.tradefed.host.IHostOptions.PermitLimitType; 36 import com.android.tradefed.invoker.TestInformation; 37 import com.android.tradefed.invoker.logger.CurrentInvocation.IsolationGrade; 38 import com.android.tradefed.invoker.logger.InvocationMetricLogger; 39 import com.android.tradefed.invoker.logger.InvocationMetricLogger.InvocationMetricKey; 40 import com.android.tradefed.invoker.tracing.CloseableTraceScope; 41 import com.android.tradefed.log.LogUtil.CLog; 42 import com.android.tradefed.result.error.DeviceErrorIdentifier; 43 import com.android.tradefed.result.error.InfraErrorIdentifier; 44 import com.android.tradefed.retry.BaseRetryDecision; 45 import com.android.tradefed.targetprep.IDeviceFlasher.UserDataFlashOption; 46 import com.android.tradefed.util.CommandResult; 47 import com.android.tradefed.util.CommandStatus; 48 import com.android.tradefed.util.FileUtil; 49 import com.android.tradefed.util.IRunUtil; 50 import com.android.tradefed.util.RunUtil; 51 import com.android.tradefed.util.image.DeviceImageTracker; 52 import com.android.tradefed.util.image.IncrementalImageUtil; 53 54 import java.io.File; 55 import java.util.ArrayList; 56 import java.util.Collection; 57 import java.util.concurrent.TimeUnit; 58 59 /** A {@link ITargetPreparer} that flashes an image on physical Android hardware. */ 60 public abstract class DeviceFlashPreparer extends BaseTargetPreparer 61 implements IConfigurationReceiver { 62 63 private static final int BOOT_POLL_TIME_MS = 5 * 1000; 64 private static final long SNAPSHOT_CANCEL_TIMEOUT = 20000L; 65 66 @Option( 67 name = "device-boot-time", 68 description = "max time to wait for device to boot.", 69 isTimeVal = true 70 ) 71 private long mDeviceBootTime = 5 * 60 * 1000; 72 73 @Option(name = "userdata-flash", description = 74 "specify handling of userdata partition.") 75 private UserDataFlashOption mUserDataFlashOption = UserDataFlashOption.FLASH; 76 77 @Option(name = "force-system-flash", description = 78 "specify if system should always be flashed even if already running desired build.") 79 private boolean mForceSystemFlash = false; 80 81 /* 82 * A temporary workaround for special builds. Should be removed after changes from build team. 83 * Bug: 18078421 84 */ 85 @Deprecated 86 @Option( 87 name = "skip-post-flash-flavor-check", 88 description = "specify if system flavor should not be checked after flash") 89 private boolean mSkipPostFlashFlavorCheck = false; 90 91 /* 92 * Used for update testing 93 */ 94 @Option(name = "skip-post-flash-build-id-check", description = 95 "specify if build ID should not be checked after flash") 96 private boolean mSkipPostFlashBuildIdCheck = false; 97 98 @Option(name = "wipe-skip-list", description = 99 "list of /data subdirectories to NOT wipe when doing UserDataFlashOption.TESTS_ZIP") 100 private Collection<String> mDataWipeSkipList = new ArrayList<>(); 101 102 /** 103 * @deprecated use host-options:concurrent-flasher-limit. 104 */ 105 @Deprecated 106 @Option(name = "concurrent-flasher-limit", description = 107 "No-op, do not use. Left for backwards compatibility.") 108 private Integer mConcurrentFlasherLimit = null; 109 110 @Option(name = "skip-post-flashing-setup", 111 description = "whether or not to skip post-flashing setup steps") 112 private boolean mSkipPostFlashingSetup = false; 113 114 @Option(name = "wipe-timeout", 115 description = "the timeout for the command of wiping user data.", isTimeVal = true) 116 private long mWipeTimeout = 4 * 60 * 1000; 117 118 @Option( 119 name = "fastboot-flash-option", 120 description = "additional options to pass with fastboot flash/update command." 121 ) 122 private Collection<String> mFastbootFlashOptions = new ArrayList<>(); 123 124 @Option( 125 name = "flash-ramdisk", 126 description = 127 "flashes ramdisk (usually on boot partition) in addition to " 128 + "regular system image") 129 private boolean mShouldFlashRamdisk = false; 130 131 @Option( 132 name = "ramdisk-partition", 133 description = 134 "the partition (such as boot, vendor_boot) that ramdisk image " 135 + "should be flashed to") 136 private String mRamdiskPartition = "boot"; 137 138 @Option( 139 name = "cancel-ota-snapshot", 140 description = "In case an OTA snapshot is in progress, cancel it.") 141 private boolean mCancelSnapshot = false; 142 143 @Option( 144 name = "incremental-flashing", 145 description = "Leverage the incremental flashing feature for device update.") 146 private boolean mUseIncrementalFlashing = false; 147 148 @Option( 149 name = "force-disable-incremental-flashing", 150 description = "Ignore HostOptions and disable the feature if true.") 151 private boolean mForceDisableIncrementalFlashing = false; 152 153 @Option( 154 name = "create-snapshot-binary", 155 description = "Override the create_snapshot binary for incremental flashing.") 156 private File mCreateSnapshotBinary = null; 157 158 @Option( 159 name = "allow-incremental-same-build", 160 description = "Allow doing incremental update on same build.") 161 private boolean mAllowIncrementalOnSameBuild = false; 162 163 @Option( 164 name = "allow-incremental-cross-release", 165 description = "Allow doing incremental update across release build configs.") 166 private boolean mAllowIncrementalCrossRelease = false; 167 168 @Option( 169 name = "apply-snapshot", 170 description = 171 "Whether to apply the snapshot after mounting it. " 172 + "This changes the baseline and does require reverting.") 173 private boolean mApplySnapshot = false; 174 175 @Option( 176 name = "snapuserd-wait-phase", 177 description = 178 "Only applicable to apply-snapshot, blocks snapuserd until a specified phase.") 179 private SnapuserdWaitPhase mWaitPhase = SnapuserdWaitPhase.BLOCK_BEFORE_RELEASING; 180 181 @Option( 182 name = "allow-unzip-baseline", 183 description = "Whether to allow tracking the baseline as unzipped or not.") 184 private boolean mAllowUnzippedBaseline = false; 185 186 @Option( 187 name = "enforce-snapshot-completed", 188 description = "Test mode was snapshot to ensure the logic was used and throw if not.") 189 private boolean mEnforceSnapshotCompleted = false; 190 191 private IncrementalImageUtil mIncrementalImageUtil; 192 private IConfiguration mConfig; 193 194 @Override setConfiguration(IConfiguration configuration)195 public void setConfiguration(IConfiguration configuration) { 196 mConfig = configuration; 197 } 198 199 /** 200 * Sets the device boot time 201 * <p/> 202 * Exposed for unit testing 203 */ setDeviceBootTime(long bootTime)204 void setDeviceBootTime(long bootTime) { 205 mDeviceBootTime = bootTime; 206 } 207 208 /** Gets the device boot wait time */ getDeviceBootWaitTime()209 protected long getDeviceBootWaitTime() { 210 return mDeviceBootTime; 211 } 212 213 /** 214 * Gets the interval between device boot poll attempts. 215 * <p/> 216 * Exposed for unit testing 217 */ getDeviceBootPollTimeMs()218 int getDeviceBootPollTimeMs() { 219 return BOOT_POLL_TIME_MS; 220 } 221 222 /** 223 * Gets the {@link IRunUtil} instance to use. 224 * <p/> 225 * Exposed for unit testing 226 */ getRunUtil()227 IRunUtil getRunUtil() { 228 return RunUtil.getDefault(); 229 } 230 231 /** 232 * Gets the {@link IHostOptions} instance to use. 233 * <p/> 234 * Exposed for unit testing 235 */ getHostOptions()236 protected IHostOptions getHostOptions() { 237 return GlobalConfiguration.getInstance().getHostOptions(); 238 } 239 240 /** 241 * Set the userdata-flash option 242 * 243 * @param flashOption 244 */ setUserDataFlashOption(UserDataFlashOption flashOption)245 public void setUserDataFlashOption(UserDataFlashOption flashOption) { 246 mUserDataFlashOption = flashOption; 247 } 248 249 /** Wrap the getBuildInfo so we have a change to override it for specific scenarios. */ getBuild(TestInformation testInfo)250 public IBuildInfo getBuild(TestInformation testInfo) { 251 return testInfo.getBuildInfo(); 252 } 253 254 /** {@inheritDoc} */ 255 @Override setUp(TestInformation testInfo)256 public void setUp(TestInformation testInfo) 257 throws TargetSetupError, DeviceNotAvailableException, BuildError { 258 if (testInfo.getDevice().getIDevice() instanceof NullDevice) { 259 CLog.i("Skipping device flashing, this is a null-device."); 260 return; 261 } 262 ITestDevice device = testInfo.getDevice(); 263 IBuildInfo buildInfo = getBuild(testInfo); 264 CLog.i("Performing setup on %s", device.getSerialNumber()); 265 if (!(buildInfo instanceof IDeviceBuildInfo)) { 266 throw new IllegalArgumentException("Provided buildInfo is not a IDeviceBuildInfo"); 267 } 268 IDeviceBuildInfo deviceBuild = (IDeviceBuildInfo) buildInfo; 269 if (mShouldFlashRamdisk && deviceBuild.getRamdiskFile() == null) { 270 throw new HarnessRuntimeException( 271 "ramdisk flashing enabled but no ramdisk file was found in build info", 272 InfraErrorIdentifier.CONFIGURED_ARTIFACT_NOT_FOUND); 273 } 274 // For debugging: log the original build from the device 275 if (TestDeviceState.ONLINE.equals(testInfo.getDevice().getDeviceState())) { 276 buildInfo.addBuildAttribute( 277 "original_build_fingerprint", 278 device.getProperty("ro.product.build.fingerprint")); 279 } 280 281 long queueTime = -1; 282 long flashingTime = -1; 283 long start = -1; 284 // HostOptions can force the incremental flashing to true. 285 if (getHostOptions().isIncrementalFlashingEnabled()) { 286 mUseIncrementalFlashing = true; 287 } 288 if (getHostOptions().isOptOutOfIncrementalFlashing()) { 289 mUseIncrementalFlashing = false; 290 } 291 if (mConfig != null) { 292 for (IDeviceConfiguration deviceConfig : mConfig.getDeviceConfig()) { 293 for (ITargetPreparer p : deviceConfig.getTargetPreparers()) { 294 if (p instanceof GkiDeviceFlashPreparer 295 && !((GkiDeviceFlashPreparer) p).isDisabled() 296 && !mApplySnapshot) { 297 CLog.d( 298 "Force disabling incremental flashing due to" 299 + " GkiDeviceFlashPreparer."); 300 mForceDisableIncrementalFlashing = true; 301 } 302 } 303 } 304 } 305 if (mForceDisableIncrementalFlashing) { 306 // The local option disable the feature, and skip tracking baseline 307 // for this run to avoid tracking a potentially bad baseline. 308 mUseIncrementalFlashing = false; 309 // Do not keep a cache when we are about to override it 310 DeviceImageTracker.getDefaultCache().invalidateTracking(device.getSerialNumber()); 311 } 312 boolean useIncrementalFlashing = mUseIncrementalFlashing; 313 boolean reEntry = false; 314 if (useIncrementalFlashing) { 315 boolean isIsolated = false; 316 if (mConfig.getRetryDecision() instanceof BaseRetryDecision) { 317 isIsolated = 318 IsolationGrade.FULLY_ISOLATED.equals( 319 ((BaseRetryDecision) mConfig.getRetryDecision()) 320 .getIsolationGrade()); 321 } 322 if (mIncrementalImageUtil != null) { 323 // Re-entry can occur during reset isolation. 324 reEntry = true; 325 } else { 326 mIncrementalImageUtil = 327 IncrementalImageUtil.initialize( 328 device, 329 deviceBuild, 330 mCreateSnapshotBinary, 331 isIsolated, 332 mAllowIncrementalCrossRelease, 333 mApplySnapshot, 334 mWaitPhase); 335 if (mIncrementalImageUtil == null) { 336 useIncrementalFlashing = false; 337 } else { 338 if (mAllowIncrementalOnSameBuild) { 339 mIncrementalImageUtil.allowSameBuildFlashing(); 340 } 341 if (TestDeviceState.ONLINE.equals(device.getDeviceState())) { 342 // No need to reboot yet, it will happen later in the sequence 343 String verityOutput = device.executeAdbCommand("enable-verity"); 344 CLog.d("%s", verityOutput); 345 } 346 } 347 } 348 } 349 try { 350 checkDeviceProductType(device, deviceBuild); 351 device.setRecoveryMode(RecoveryMode.ONLINE); 352 IDeviceFlasher flasher = createFlasher(device); 353 flasher.setWipeTimeout(mWipeTimeout); 354 boolean tookPermit = false; 355 // only surround fastboot related operations with flashing permit restriction 356 try { 357 flasher.overrideDeviceOptions(device); 358 flasher.setUserDataFlashOption(mUserDataFlashOption); 359 flasher.setForceSystemFlash(mForceSystemFlash); 360 flasher.setDataWipeSkipList(mDataWipeSkipList); 361 flasher.setShouldFlashRamdisk(mShouldFlashRamdisk); 362 if (mShouldFlashRamdisk) { 363 flasher.setRamdiskPartition(mRamdiskPartition); 364 } 365 if (flasher instanceof FastbootDeviceFlasher) { 366 ((FastbootDeviceFlasher) flasher).setFlashOptions(mFastbootFlashOptions); 367 if (!reEntry) { 368 // Avoid using incremental during re-entry since it will just wipe 369 ((FastbootDeviceFlasher) flasher) 370 .setIncrementalFlashing(mIncrementalImageUtil); 371 } 372 } 373 start = System.currentTimeMillis(); 374 flasher.preFlashOperations(device, deviceBuild); 375 // After preFlashOperations device should be in bootloader 376 if (mCancelSnapshot && TestDeviceState.FASTBOOT.equals(device.getDeviceState())) { 377 CommandResult res = 378 device.executeFastbootCommand( 379 SNAPSHOT_CANCEL_TIMEOUT, "snapshot-update", "cancel"); 380 if (!CommandStatus.SUCCESS.equals(res.getStatus())) { 381 CLog.w( 382 "Failed to cancel snapshot: %s.\nstdout:%s\nstderr:%s", 383 res.getStatus(), res.getStdout(), res.getStderr()); 384 } 385 } 386 try (CloseableTraceScope ignored = 387 new CloseableTraceScope("wait_for_flashing_permit")) { 388 if (mIncrementalImageUtil == null) { 389 // Only #flash is included in the critical section 390 getHostOptions().takePermit(PermitLimitType.CONCURRENT_FLASHER); 391 tookPermit = true; 392 } 393 queueTime = System.currentTimeMillis() - start; 394 if (tookPermit) { 395 CLog.v( 396 "Flashing permit obtained after %ds", 397 TimeUnit.MILLISECONDS.toSeconds(queueTime)); 398 } 399 InvocationMetricLogger.addInvocationMetrics( 400 InvocationMetricKey.FLASHING_PERMIT_LATENCY, queueTime); 401 } 402 // Don't allow interruptions during flashing operations. 403 getRunUtil().allowInterrupt(false); 404 start = System.currentTimeMillis(); 405 // Set flashing method as unknown here as a fallback, in case it wasn't overwritten 406 // by subclass implementations 407 InvocationMetricLogger.addInvocationMetrics( 408 InvocationMetricKey.FLASHING_METHOD, 409 FlashingMethod.FASTBOOT_UNCATEGORIZED.toString()); 410 flasher.flash(device, deviceBuild); 411 } catch (DeviceNotAvailableException | TargetSetupError | RuntimeException e) { 412 // Clear tracking in case of error 413 DeviceImageTracker.getDefaultCache().invalidateTracking(device.getSerialNumber()); 414 throw e; 415 } finally { 416 flashingTime = System.currentTimeMillis() - start; 417 if (tookPermit) { 418 getHostOptions().returnPermit(PermitLimitType.CONCURRENT_FLASHER); 419 } 420 flasher.postFlashOperations(device, deviceBuild); 421 // report flashing status 422 CommandStatus status = flasher.getSystemFlashingStatus(); 423 if (status == null) { 424 CLog.i("Skipped reporting metrics because system partitions were not flashed."); 425 } else { 426 if (mIncrementalImageUtil != null) { 427 InvocationMetricLogger.addInvocationMetrics( 428 InvocationMetricKey.INCREMENTAL_FLASHING_TIME, flashingTime); 429 } 430 InvocationMetricLogger.addInvocationMetrics( 431 InvocationMetricKey.FLASHING_TIME, flashingTime); 432 reportFlashMetrics(buildInfo.getBuildBranch(), buildInfo.getBuildFlavor(), 433 buildInfo.getBuildId(), device.getSerialNumber(), queueTime, 434 flashingTime, status); 435 } 436 } 437 if (mIncrementalImageUtil == null) { 438 // only want logcat captured for current build, delete any accumulated log data 439 device.clearLogcat(); 440 } 441 // In case success with full flashing 442 if (!reEntry) { 443 moveBaseline(deviceBuild, device.getSerialNumber(), useIncrementalFlashing); 444 } 445 if (mSkipPostFlashingSetup) { 446 return; 447 } 448 // Temporary re-enable interruptable since the critical flashing operation is over. 449 getRunUtil().allowInterrupt(true); 450 device.waitForDeviceOnline(); 451 // device may lose date setting if wiped, update with host side date in case anything on 452 // device side malfunction with an invalid date 453 if (device.enableAdbRoot()) { 454 device.setDate(null); 455 } 456 // Disable interrupt for encryption operation. 457 getRunUtil().allowInterrupt(false); 458 checkBuild(device, deviceBuild); 459 // Once critical operation is done, we re-enable interruptable 460 getRunUtil().allowInterrupt(true); 461 try { 462 boolean available = device.waitForDeviceAvailableInRecoverPath(mDeviceBootTime); 463 if (!available) { 464 // Clear tracking in case of error 465 DeviceImageTracker.getDefaultCache() 466 .invalidateTracking(device.getSerialNumber()); 467 throw new DeviceFailedToBootError( 468 String.format( 469 "Device %s did not become available after flashing %s", 470 device.getSerialNumber(), deviceBuild.getDeviceBuildId()), 471 device.getDeviceDescriptor(), 472 DeviceErrorIdentifier.ERROR_AFTER_FLASHING); 473 } 474 } catch (DeviceNotAvailableException e) { 475 // Clear tracking in case of error 476 DeviceImageTracker.getDefaultCache().invalidateTracking(device.getSerialNumber()); 477 // Assume this is a build problem 478 throw new DeviceFailedToBootError( 479 String.format( 480 "Device %s did not become available after flashing %s", 481 device.getSerialNumber(), deviceBuild.getDeviceBuildId()), 482 device.getDeviceDescriptor(), 483 e, 484 DeviceErrorIdentifier.ERROR_AFTER_FLASHING); 485 } 486 device.postBootSetup(); 487 } finally { 488 device.setRecoveryMode(RecoveryMode.AVAILABLE); 489 // Allow interruption at the end no matter what. 490 getRunUtil().allowInterrupt(true); 491 if (mIncrementalImageUtil != null) { 492 mIncrementalImageUtil.cleanAfterSetup(); 493 } 494 } 495 } 496 moveBaseline( IDeviceBuildInfo deviceBuild, String serial, boolean useIncrementalFlashing)497 private void moveBaseline( 498 IDeviceBuildInfo deviceBuild, String serial, boolean useIncrementalFlashing) { 499 if (!getHostOptions().isOptOutOfIncrementalFlashing()) { 500 boolean moveBaseLine = true; 501 if (!mUseIncrementalFlashing || useIncrementalFlashing) { 502 // Do not move baseline if using incremental flashing 503 moveBaseLine = false; 504 } 505 if (mApplySnapshot) { 506 // Move baseline when going with incremental + apply update 507 moveBaseLine = true; 508 } 509 if (moveBaseLine) { 510 File deviceImage = deviceBuild.getDeviceImageFile(); 511 File tmpReference = null; 512 try { 513 if (mAllowUnzippedBaseline 514 && mIncrementalImageUtil != null 515 && mIncrementalImageUtil.getExtractedTargetDirectory() != null 516 && mIncrementalImageUtil.getExtractedTargetDirectory().isDirectory()) { 517 CLog.d( 518 "Using unzipped baseline: %s", 519 mIncrementalImageUtil.getExtractedTargetDirectory()); 520 tmpReference = mIncrementalImageUtil.getExtractedTargetDirectory(); 521 deviceImage = tmpReference; 522 } 523 DeviceImageTracker.getDefaultCache() 524 .trackUpdatedDeviceImage( 525 serial, 526 deviceImage, 527 deviceBuild.getBootloaderImageFile(), 528 deviceBuild.getBasebandImageFile(), 529 deviceBuild.getBuildId(), 530 deviceBuild.getBuildBranch(), 531 deviceBuild.getBuildFlavor()); 532 } finally { 533 FileUtil.recursiveDelete(tmpReference); 534 } 535 } 536 } 537 } 538 539 /** 540 * Possible check before flashing to ensure the device is as expected compare to the build info. 541 * 542 * @param device the {@link ITestDevice} to flash. 543 * @param deviceBuild the {@link IDeviceBuildInfo} used to flash. 544 * @throws BuildError 545 * @throws DeviceNotAvailableException 546 */ checkDeviceProductType(ITestDevice device, IDeviceBuildInfo deviceBuild)547 protected void checkDeviceProductType(ITestDevice device, IDeviceBuildInfo deviceBuild) 548 throws BuildError, DeviceNotAvailableException { 549 // empty of purpose 550 } 551 552 /** 553 * Verifies the expected build matches the actual build on device after flashing 554 * @throws DeviceNotAvailableException 555 */ checkBuild(ITestDevice device, IDeviceBuildInfo deviceBuild)556 private void checkBuild(ITestDevice device, IDeviceBuildInfo deviceBuild) 557 throws DeviceNotAvailableException { 558 // Need to use deviceBuild.getDeviceBuildId instead of getBuildId because the build info 559 // could be an AppBuildInfo and return app build id. Need to be more explicit that we 560 // check for the device build here. 561 if (!mSkipPostFlashBuildIdCheck) { 562 checkBuildAttribute(deviceBuild.getDeviceBuildId(), device.getBuildId(), 563 device.getSerialNumber()); 564 } 565 } 566 checkBuildAttribute(String expectedBuildAttr, String actualBuildAttr, String serial)567 private void checkBuildAttribute(String expectedBuildAttr, String actualBuildAttr, 568 String serial) throws DeviceNotAvailableException { 569 if (expectedBuildAttr == null || actualBuildAttr == null || 570 !expectedBuildAttr.equals(actualBuildAttr)) { 571 // throw DNAE - assume device hardware problem - we think flash was successful but 572 // device is not running right bits 573 throw new DeviceNotAvailableException( 574 String.format( 575 "Unexpected build after flashing. Expected %s, actual %s", 576 expectedBuildAttr, actualBuildAttr), 577 serial, 578 DeviceErrorIdentifier.ERROR_AFTER_FLASHING); 579 } 580 } 581 582 /** 583 * Create {@link IDeviceFlasher} to use. Subclasses can override 584 * @throws DeviceNotAvailableException 585 */ createFlasher(ITestDevice device)586 protected abstract IDeviceFlasher createFlasher(ITestDevice device) 587 throws DeviceNotAvailableException; 588 589 @Override tearDown(TestInformation testInfo, Throwable e)590 public void tearDown(TestInformation testInfo, Throwable e) throws DeviceNotAvailableException { 591 if (testInfo.getDevice().getIDevice() instanceof NullDevice) { 592 CLog.i("Skipping device flashing tearDown, this is a null-device."); 593 return; 594 } 595 if (mIncrementalImageUtil != null) { 596 CLog.d("Teardown related to incremental update."); 597 RecoveryMode mode = testInfo.getDevice().getRecoveryMode(); 598 try { 599 testInfo.getDevice().setRecoveryMode(RecoveryMode.NONE); 600 if (mAllowUnzippedBaseline) { 601 mIncrementalImageUtil.allowUnzipBaseline(); 602 } 603 mIncrementalImageUtil.teardownDevice(testInfo); 604 } finally { 605 testInfo.getDevice().setRecoveryMode(mode); 606 } 607 } 608 if (mEnforceSnapshotCompleted && e == null) { 609 if (mIncrementalImageUtil == null || !mIncrementalImageUtil.updateCompleted()) { 610 throw new RuntimeException( 611 "We expected incremental-flashing to be used but wasn't."); 612 } 613 } 614 } 615 616 /** 617 * Reports device flashing timing data to metrics backend 618 * @param branch the branch where the device build originated from 619 * @param buildFlavor the build flavor of the device build 620 * @param buildId the build number of the device build 621 * @param serial the serial number of device 622 * @param queueTime the time spent waiting for a flashing limit to become available 623 * @param flashingTime the time spent in flashing device image zip 624 * @param flashingStatus the execution status of flashing command 625 */ reportFlashMetrics(String branch, String buildFlavor, String buildId, String serial, long queueTime, long flashingTime, CommandStatus flashingStatus)626 protected void reportFlashMetrics(String branch, String buildFlavor, String buildId, 627 String serial, long queueTime, long flashingTime, CommandStatus flashingStatus) { 628 // no-op as default implementation 629 } 630 631 /** 632 * Sets the option for whether ramdisk should be flashed 633 * 634 * @param shouldFlashRamdisk 635 */ 636 @VisibleForTesting setShouldFlashRamdisk(boolean shouldFlashRamdisk)637 void setShouldFlashRamdisk(boolean shouldFlashRamdisk) { 638 mShouldFlashRamdisk = shouldFlashRamdisk; 639 } 640 setSkipPostFlashBuildIdCheck(boolean skipPostFlashBuildIdCheck)641 protected void setSkipPostFlashBuildIdCheck(boolean skipPostFlashBuildIdCheck) { 642 mSkipPostFlashBuildIdCheck = skipPostFlashBuildIdCheck; 643 } 644 setUseIncrementalFlashing(boolean incrementalFlashing)645 protected void setUseIncrementalFlashing(boolean incrementalFlashing) { 646 mUseIncrementalFlashing = incrementalFlashing; 647 } 648 isIncrementalFlashingEnabled()649 public boolean isIncrementalFlashingEnabled() { 650 return mUseIncrementalFlashing; 651 } 652 isIncrementalFlashingForceDisabled()653 public boolean isIncrementalFlashingForceDisabled() { 654 return mForceDisableIncrementalFlashing; 655 } 656 setAllowCrossReleaseFlashing(boolean allowCrossReleaseFlashing)657 public void setAllowCrossReleaseFlashing(boolean allowCrossReleaseFlashing) { 658 mAllowIncrementalCrossRelease = allowCrossReleaseFlashing; 659 } 660 setApplySnapshot(boolean applySnapshot)661 public void setApplySnapshot(boolean applySnapshot) { 662 mApplySnapshot = applySnapshot; 663 } 664 setAllowUnzipBaseline(boolean allowUnzipBaseline)665 public void setAllowUnzipBaseline(boolean allowUnzipBaseline) { 666 mAllowUnzippedBaseline = allowUnzipBaseline; 667 } 668 } 669