Home | History | Annotate | Download | only in ota_runners
      1 #!/usr/bin/env python3.4
      2 #
      3 #   Copyright 2017 - The Android Open Source Project
      4 #
      5 #   Licensed under the Apache License, Version 2.0 (the "License");
      6 #   you may not use this file except in compliance with the License.
      7 #   You may obtain a copy of the License at
      8 #
      9 #       http://www.apache.org/licenses/LICENSE-2.0
     10 #
     11 #   Unless required by applicable law or agreed to in writing, software
     12 #   distributed under the License is distributed on an "AS IS" BASIS,
     13 #   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 #   See the License for the specific language governing permissions and
     15 #   limitations under the License.
     16 
     17 import time
     18 
     19 SL4A_SERVICE_SETUP_TIME = 5
     20 
     21 
     22 class OtaError(Exception):
     23     """Raised when an error in the OTA Update process occurs."""
     24 
     25 
     26 class OtaRunner(object):
     27     """The base class for all OTA Update Runners."""
     28 
     29     def __init__(self, ota_tool, android_device):
     30         self.ota_tool = ota_tool
     31         self.android_device = android_device
     32         self.serial = self.android_device.serial
     33 
     34     def _update(self):
     35         log = self.android_device.log
     36         old_info = self.android_device.adb.getprop('ro.build.fingerprint')
     37         log.info('Starting Update. Beginning build info: %s', old_info)
     38         log.info('Stopping services.')
     39         self.android_device.stop_services()
     40         log.info('Beginning tool.')
     41         self.ota_tool.update(self)
     42         log.info('Tool finished. Waiting for boot completion.')
     43         self.android_device.wait_for_boot_completion()
     44         new_info = self.android_device.adb.getprop('ro.build.fingerprint')
     45         if not old_info or old_info == new_info:
     46             raise OtaError('The device was not updated to a new build. '
     47                            'Previous build: %s. New build: %s' % (old_info,
     48                                                                   new_info))
     49         log.info('Boot completed. Rooting adb.')
     50         self.android_device.root_adb()
     51         log.info('Root complete.')
     52         if self.android_device.skip_sl4a:
     53             self.android_device.log.info('Skipping SL4A install.')
     54         else:
     55             for _ in range(3):
     56                 self.android_device.log.info('Re-installing SL4A from "%s".',
     57                                              self.get_sl4a_apk())
     58                 self.android_device.adb.install(
     59                     '-r -g %s' % self.get_sl4a_apk(), ignore_status=True)
     60                 time.sleep(SL4A_SERVICE_SETUP_TIME)
     61                 if self.android_device.is_sl4a_installed():
     62                     break
     63         log.info('Starting services.')
     64         self.android_device.start_services()
     65         log.info('Services started. Running ota tool cleanup.')
     66         self.ota_tool.cleanup(self)
     67         log.info('Cleanup complete.')
     68 
     69     def can_update(self):
     70         """Whether or not an update package is available for the device."""
     71         return NotImplementedError()
     72 
     73     def get_ota_package(self):
     74         raise NotImplementedError()
     75 
     76     def get_sl4a_apk(self):
     77         raise NotImplementedError()
     78 
     79 
     80 class SingleUseOtaRunner(OtaRunner):
     81     """A single use OtaRunner.
     82 
     83     SingleUseOtaRunners can only be ran once. If a user attempts to run it more
     84     than once, an error will be thrown. Users can avoid the error by checking
     85     can_update() before calling update().
     86     """
     87 
     88     def __init__(self, ota_tool, android_device, ota_package, sl4a_apk):
     89         super(SingleUseOtaRunner, self).__init__(ota_tool, android_device)
     90         self._ota_package = ota_package
     91         self._sl4a_apk = sl4a_apk
     92         self._called = False
     93 
     94     def can_update(self):
     95         return not self._called
     96 
     97     def update(self):
     98         """Starts the update process."""
     99         if not self.can_update():
    100             raise OtaError('A SingleUseOtaTool instance cannot update a phone '
    101                            'multiple times.')
    102         self._called = True
    103         self._update()
    104 
    105     def get_ota_package(self):
    106         return self._ota_package
    107 
    108     def get_sl4a_apk(self):
    109         return self._sl4a_apk
    110 
    111 
    112 class MultiUseOtaRunner(OtaRunner):
    113     """A multiple use OtaRunner.
    114 
    115     MultiUseOtaRunner can only be ran for as many times as there have been
    116     packages provided to them. If a user attempts to run it more than the number
    117     of provided packages, an error will be thrown. Users can avoid the error by
    118     checking can_update() before calling update().
    119     """
    120 
    121     def __init__(self, ota_tool, android_device, ota_packages, sl4a_apks):
    122         super(MultiUseOtaRunner, self).__init__(ota_tool, android_device)
    123         self._ota_packages = ota_packages
    124         self._sl4a_apks = sl4a_apks
    125         self.current_update_number = 0
    126 
    127     def can_update(self):
    128         return not self.current_update_number == len(self._ota_packages)
    129 
    130     def update(self):
    131         """Starts the update process."""
    132         if not self.can_update():
    133             raise OtaError('This MultiUseOtaRunner has already updated all '
    134                            'given packages onto the phone.')
    135         self._update()
    136         self.current_update_number += 1
    137 
    138     def get_ota_package(self):
    139         return self._ota_packages[self.current_update_number]
    140 
    141     def get_sl4a_apk(self):
    142         return self._sl4a_apks[self.current_update_number]
    143