blob: 0eace2be1db5b3c0338f065043d58a9eebfb01a9 [file] [log] [blame]
# Copyright (c) 2021 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import dbus
import logging
import re
import time
import subprocess
from autotest_lib.client.bin import test
from autotest_lib.client.common_lib import error
from autotest_lib.client.cros import upstart
from autotest_lib.client.cros.cellular import cellular_logging
from autotest_lib.client.cros.cellular import hermes_constants
from autotest_lib.client.cros.cellular import hermes_utils
from autotest_lib.client.cros.cellular import mm1_constants
from autotest_lib.client.cros.networking import mm1_proxy
log = cellular_logging.SetupCellularLogging('HermesRestartSlotSwitchTest')
class cellular_Hermes_Restart_SlotSwitch(test.test):
"""
This test restarts hermes or switches slots in between hermes
operations.
The test fails if any of the hermes operations fail.
Prerequisites
1) For test CI:
Before running this test on test CI, a profile needs to be created on
go/stork-profile. The profile needs to be linked to the EID of the dut.
Profiles with class=operational and type=Android GTS test are known to work
well with this test.
We rely on the SMDS event to find the activation code for the test.
There is a limit of 99 downloads before the profile needs to be deleted and
recreated.(b/181723689)
2) For prod CI:
Install a production profile before running the test.
"""
version = 1
def restart_hermes(self):
""" Restarts Hermes daemon """
logging.info('->restart_hermes start')
upstart.restart_job('hermes')
# hermes takes 15+ sec to load all apis, wait on hermes dbus not enough
time.sleep(hermes_constants.HERMES_RESTART_WAIT_SECONDS)
self.hermes_manager = hermes_utils.connect_to_hermes()
euicc = self.hermes_manager.get_euicc(self.euicc_path)
if not euicc:
raise error.TestFail('restart_hermes operation failed - no euicc')
euicc.use_test_certs(not self.is_prod_ci)
logging.info('restart_hermes done')
if not self.hermes_manager:
logging.error('restart_hermes failed, no hermes daemon')
raise error.TestFail('restart_hermes operation failed')
def qmi_get_active_slot(self):
"""
Gets current active slot
@return parse qmicli slot status result and return active slot number
sample slot status:
[qrtr://0] Successfully got slots status
[qrtr://0] 2 physical slots found:
Physical slot 1:
Card status: present
Slot status: inactive
Logical slot: 1
ICCID: unknown
Protocol: uicc
Num apps: 3
Is eUICC: yes
EID: 89033023425120000000001236712288
Physical slot 2:
Card status: present
Slot status: active
ICCID: unknown
Protocol: uicc
Num apps: 0
Is eUICC: yes
EID: 89033023425120000000000024200260
"""
# Read qmi slot status and parse to return current active slot no
status_cmd = 'qmicli -p -d qrtr://0 --uim-get-slot-status'
slot_status = subprocess.check_output(status_cmd, shell=True)
slot_status_list = re.findall('.*active.*', slot_status, re.I)
for slot_num, status in enumerate(slot_status_list):
if "inactive" not in status:
logging.info('active slot is %d', slot_num+1)
return slot_num+1
def qmi_switch_slot(self, slot):
"""
Perform switch slot using qmicli commands
Command usage:
localhost ~ # qmicli -d qrtr://0 --uim-switch-slot 1
error: couldn't switch slots: QMI protocol error (26): 'NoEffect'
localhost ~ # echo $?
1
localhost ~ # qmicli -d qrtr://0 --uim-switch-slot 2
[qrtr://0] Successfully switched slots
localhost ~ # echo $?
0
"""
# switch to given slot using qmicli command
switch_cmd = 'qmicli -d qrtr://0 --uim-switch-slot ' + str(slot)
if (self.qmi_get_active_slot() == slot):
logging.info('slot switch not needed, same slot %d is active', slot)
return
logging.info('call qmicli cmd to switch to:%s cmd:%s', slot, switch_cmd)
ret = subprocess.call(switch_cmd, shell=True)
# As we are not testing slot switching here, timeout is to make sure all
# euiic's are powered up. allowing modem FW to switch slots and load euiccs.
time.sleep(8)
logging.info(switch_cmd + ':return value is %d', ret)
if ret is not 0:
raise error.TestFail('qmi switch slot failed:', slot)
def hermes_operations_test(self):
"""
Perform hermes operations with restart, slotswitch in between
Do Install, Enable, Disable, Uninstall operations combined with
operations hermes restart, sim slot switch
@return Fails the test if any operation fails
"""
try:
logging.info('hermes_operations_test start')
for slot in range(1,3):
# Do restart, slotswitch and install, enable, disable, uninstall
self.qmi_switch_slot(slot)
self.restart_hermes()
logging.info('Iteration on slot %d', slot)
if not self.is_prod_ci:
installed_iccid = None
logging.info('INSTALL:\n')
installed_iccid = hermes_utils.install_profile(
self.euicc_path, self.hermes_manager, self.is_prod_ci)
else:
installed_iccid = hermes_utils.get_iccid_of_disabled_profile(
self.euicc_path, self.hermes_manager, self.is_prod_ci)
self.qmi_switch_slot(slot)
self.restart_hermes()
logging.info('ENABLE:\n')
hermes_utils.enable_or_disable_profile_test(
self.euicc_path, self.hermes_manager, installed_iccid, True)
self.qmi_switch_slot(slot)
self.restart_hermes()
logging.info('DISABLE:\n')
hermes_utils.enable_or_disable_profile_test(
self.euicc_path, self.hermes_manager, installed_iccid, False)
if not self.is_prod_ci:
self.qmi_switch_slot(slot)
self.restart_hermes()
logging.info('UNINSTALL:\n')
hermes_utils.uninstall_profile_test(
self.euicc_path, self.hermes_manager, installed_iccid)
logging.info('===hermes_operations_test succeeded===\n')
except dbus.DBusException as e:
logging.error('hermes_operations failed')
raise error.TestFail('hermes_operations_test failed', e)
def run_once(self, test_env, is_prod_ci=False):
"""
Perform hermes ops with hermes restart and sim slot switch
"""
self.test_env = test_env
self.is_prod_ci = is_prod_ci
self.mm_proxy, self.hermes_manager, self.euicc_path = \
hermes_utils.initialize_test(is_prod_ci)
self.hermes_operations_test()
logging.info('HermesRestartSlotSwitchTest Completed')