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