blob: dd58943ea1bd9857222a5a2dc990d5e8c32019c9 [file] [log] [blame]
#!/usr/bin/env python3.4
#
# Copyright 2017 - 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.
import logging
import time
SL4A_SERVICE_SETUP_TIME = 5
class OtaError(Exception):
"""Raised when an error in the OTA Update process occurs."""
class OtaRunner(object):
"""The base class for all OTA Update Runners."""
def __init__(self, ota_tool, android_device):
self.ota_tool = ota_tool
self.android_device = android_device
self.serial = self.android_device.serial
def _update(self):
logging.info('Stopping services.')
self.android_device.stop_services()
logging.info('Beginning tool.')
self.ota_tool.update(self)
logging.info('Tool finished. Waiting for boot completion.')
self.android_device.wait_for_boot_completion()
logging.info('Boot completed. Rooting adb.')
self.android_device.root_adb()
logging.info('Root complete. Installing new SL4A.')
output = self.android_device.adb.install('-r %s' % self.get_sl4a_apk)
logging.info('SL4A install output: %s' % output)
time.sleep(SL4A_SERVICE_SETUP_TIME)
logging.info('Starting services.')
self.android_device.start_services()
logging.info('Services started. Running ota tool cleanup.')
self.ota_tool.cleanup(self)
logging.info('Cleanup complete.')
def can_update(self):
"""Whether or not an update package is available for the device."""
return NotImplementedError()
def get_ota_package(self):
raise NotImplementedError()
def get_sl4a_apk(self):
raise NotImplementedError()
class SingleUseOtaRunner(OtaRunner):
"""A single use OtaRunner.
SingleUseOtaRunners can only be ran once. If a user attempts to run it more
than once, an error will be thrown. Users can avoid the error by checking
can_update() before calling update().
"""
def __init__(self, ota_tool, android_device, ota_package, sl4a_apk):
super(SingleUseOtaRunner, self).__init__(ota_tool, android_device)
self._ota_package = ota_package
self._sl4a_apk = sl4a_apk
self._called = False
def can_update(self):
return not self._called
def update(self):
"""Starts the update process."""
if not self.can_update():
raise OtaError('A SingleUseOtaTool instance cannot update a phone '
'multiple times.')
self._called = True
self._update()
def get_ota_package(self):
return self._ota_package
def get_sl4a_apk(self):
return self._sl4a_apk
class MultiUseOtaRunner(OtaRunner):
"""A multiple use OtaRunner.
MultiUseOtaRunner can only be ran for as many times as there have been
packages provided to them. If a user attempts to run it more than the number
of provided packages, an error will be thrown. Users can avoid the error by
checking can_update() before calling update().
"""
def __init__(self, ota_tool, android_device, ota_packages, sl4a_apks):
super(MultiUseOtaRunner, self).__init__(ota_tool, android_device)
self._ota_packages = ota_packages
self._sl4a_apks = sl4a_apks
self.current_update_number = 0
def can_update(self):
return not self.current_update_number == len(self._ota_packages)
def update(self):
"""Starts the update process."""
if not self.can_update():
raise OtaError('This MultiUseOtaRunner has already updated all '
'given packages onto the phone.')
self._update()
self.current_update_number += 1
def get_ota_package(self):
return self._ota_packages[self.current_update_number]
def get_sl4a_apk(self):
return self._sl4a_apks[self.current_update_number]