1# Copyright (C) 2025 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15import logging 16import os 17import subprocess 18from mobly import base_test 19from mobly import test_runner 20from mobly import config_parser 21from mobly.controllers import android_device 22from devices import DeviceFactory 23from pathlib import Path 24from utilities.main_utils import common_main 25 26class AndroidFlashTest(base_test.BaseTestClass): 27 28 def setup_class(self): 29 # Setup required for the entire test class. 30 logging.info('Setting up test class.') 31 # Registers the android devices controllers with Mobly. 32 self.android_devices = self.register_controller(android_device) 33 # Retrieves the build path from the test configuration. 34 self.device = self.user_params['device'] 35 self.serial = self.user_params['serial'] 36 self.image_dir = Path(self.user_params['image_dir']) 37 self.wipe = self.user_params['wipe'] 38 self.hw_variant = self.user_params['hw_variant'] 39 self.b = self.user_params['b'] 40 self.diag = self.user_params['diag'] 41 self.preserve_keys = self.user_params['preserve_keys'] 42 self.total_flashes = self.user_params['total_flashes'] 43 44 def test_flash_device_stability(self): 45 # Check that there is at least one device available. 46 if not self.android_devices: 47 raise AssertionError('No Android devices are registered. Please make ' 48 'sure at least one device is connected and ' 49 'configured properly.') 50 ad = self.android_devices[0] # Get the first device object. 51 52 total_flashes = self.total_flashes 53 successful_flashes = 0 54 55 for i in range(total_flashes): 56 logging.info('Flash attempt #%d', i + 1) 57 58 # Get the build fingerprint before flashing. 59 before_flash_fingerprint = ad.adb.getprop('ro.build.fingerprint') 60 61 try: 62 63 Device = DeviceFactory.get_device(self.device) 64 flash_result = Device.flash(self.serial, self.image_dir, self.wipe, self.hw_variant, self.b, self.diag, self.preserve_keys) 65 # Reboot the device and wait for it to come back online. 66 ad.reboot() 67 ad.wait_for_boot_completion() 68 69 # Get the build fingerprint after flashing. 70 after_flash_fingerprint = ad.adb.getprop('ro.build.fingerprint') 71 72 # Check if the flash was successful by comparing fingerprints. 73 if before_flash_fingerprint == after_flash_fingerprint: 74 successful_flashes += 1 75 else: 76 logging.error('Flash attempt #%d failed: fingerprint did not change.', i + 1) 77 78 except subprocess.CalledProcessError as e: 79 logging.error('Flash attempt #%d failed with return code %s', i + 1, e.returncode) 80 81 # It's a good idea to have some delay between flashes to avoid overloading the device. 82 # You can add sleep here if needed. 83 84 # After the loop, log the results of the stability test. 85 logging.info('Completed %d flash attempts with %d successes.', total_flashes, successful_flashes) 86 87 # Optionally, assert that all flashes were successful to mark the test as passed. 88 assert successful_flashes == total_flashes, 'Not all flash attempts were successful.' 89 90if __name__ == '__main__': 91 common_main() 92 93