Comandos del shell del dispositivo

Durante las pruebas de VTS, los comandos de shell se utilizan para ejecutar un binario de prueba del lado del destino, para obtener/establecer propiedades, variables de entorno e información del sistema, y ​​para iniciar/detener el marco de trabajo de Android. Puede ejecutar los comandos de shell del dispositivo VTS mediante el comando adb shell o el controlador de shell VTS que se ejecuta en el dispositivo (recomendado).

Usando el shell ADB

Las pruebas que requieren apagar el puerto USB o reiniciar el dispositivo durante la prueba deben usar el shell ADB ya que el controlador del shell VTS no está disponible sin una conexión USB persistente. Puede invocar el shell ADB desde el objeto AndroidDevice en el script de prueba de Python. Ejemplos:

  • Obtenga un objeto de dispositivo Android:
    self.device = self.android_devices[0]
    
  • Emita un solo comando de shell:
    result = self.device.adb.shell(‘ls')
    

Uso del controlador de shell VTS

El controlador de shell VTS es un agente binario que se ejecuta en el dispositivo y ejecuta comandos de shell. De manera predeterminada, VTS usa el controlador de shell si el controlador se ejecuta en el dispositivo porque este método tiene menos latencia que usar el comando de adb shell .

Figura 1. Controlador de shell VTS.

El marco VTS admite pruebas de dispositivos múltiples donde cada dispositivo Android se representa como un objeto AndroidDevice en el corredor base. De forma predeterminada, el marco de trabajo de VTS inserta los archivos binarios del controlador de shell de VTS y el agente de VTS en cada dispositivo Android y establece conexiones TCP con los agentes de VTS en esos dispositivos.

Para ejecutar un comando de shell, la secuencia de comandos de Python del lado del host realiza una llamada de función al objeto ShellMirror dentro del objeto AndroidDevice. El objeto ShellMirror empaqueta los textos del comando de shell en un mensaje protobuf y lo envía (a través del canal TCP) al agente VTS en el dispositivo Android. El agente que se ejecuta en el dispositivo reenvía el comando de shell al controlador de shell VTS a través del socket de Unix.

Cuando el controlador de shell VTS recibe un comando de shell, ejecuta el comando a través de nohup en el shell del dispositivo para evitar que se cuelgue. Luego, stdout, stderr y el código de retorno se recuperan de nohup y se envían de vuelta al agente VTS. Finalmente, el agente responde al host envolviendo los resultados del comando en un mensaje protobuf .

Ventajas

Las ventajas de usar el controlador de shell VTS en lugar de adb shell incluyen:

  • Fiabilidad. El controlador de shell VTS usa nohup para ejecutar comandos en la configuración predeterminada. Como las pruebas VTS son en su mayoría pruebas HAL y kernel de nivel inferior, nohup garantiza que los comandos de shell no se cuelguen durante la ejecución.
  • rendimiento Si bien el comando adb shell almacena en caché algunos resultados (como enumerar archivos en un directorio), tiene una sobrecarga de conexión cuando realiza tareas como ejecutar un binario de prueba. El controlador de shell VTS mantiene una conexión activa durante toda la prueba, por lo que la única sobrecarga es la comunicación USB. En nuestras pruebas, usar el controlador de shell VTS para ejecutar un comando con 100 llamadas a un binario gtest vacío es aproximadamente un 20 por ciento más rápido que usar adb shell ; la diferencia real es mayor ya que la comunicación de shell VTS tiene un registro extenso.
  • Mantenimiento del Estado . El controlador de shell VTS mantiene una sesión de terminal para cada nombre de terminal (el nombre de terminal predeterminado es default ). Las variables de entorno configuradas en una sesión de terminal solo están disponibles para los comandos subsiguientes en la misma sesión.
  • Extensible . Las comunicaciones de comandos de shell entre el marco de trabajo de VTS y el controlador de dispositivo están encapsuladas en protobuf para permitir la compresión, la comunicación remota, el cifrado, etc. en el futuro. También están disponibles otras posibilidades para mejorar el rendimiento, incluido el análisis de resultados del lado del dispositivo cuando la sobrecarga de comunicación se vuelve mayor que el análisis de cadenas de resultados.

Desventajas

Las desventajas de usar el controlador de shell VTS en lugar de adb shell incluyen:

  • Binarios adicionales . Los archivos del agente VTS deben enviarse al dispositivo y limpiarse después de la ejecución de la prueba.
  • Requiere conexión activa . Si la conexión TCP entre el host y el agente se pierde durante la prueba (debido a la desconexión del USB, el apagado del puerto, el bloqueo del dispositivo, etc.), ya sea intencionalmente o no, no se puede transmitir un comando de shell al agente VTS. Incluso con el cambio automático a adb shell , el resultado y el estado del comando antes de la desconexión serían desconocidos.

Ejemplos

Ejemplos del uso de comandos de shell en un script de prueba de Python del lado del host de VTS:

  • Obtener un objeto de dispositivo Android:
    self.device = self.android_devices[0]
    
  • Obtenga un objeto de shell para el dispositivo seleccionado:
    self.shell = self.device.shell
    
  • Emita un solo comando de shell:
    results = self.shell.Execute(‘ls')
    
  • Emita una lista de comandos de shell:
    results = self.shell.Execute([‘cd /data/local/tmp', ‘ls'])
    

Objeto de resultado de comando

El objeto de retorno de la ejecución del comando de shell es un diccionario que contiene las claves stdouts , stderrs y return_codes . Independientemente de si el comando de shell se proporciona como una sola cadena o como una lista de cadenas de comandos, cada valor del diccionario de resultados es siempre una lista.

Para verificar el código de retorno de una lista de comandos, el script de prueba debe verificar los índices. Ejemplo:

asserts.assertFalse(any(results[‘return_codes']), ‘some command failed.')

Alternativamente, el script puede verificar cada índice de comando individualmente. Ejemplo:

asserts.assertEqual(results[‘return_codes'][0], 0, ‘first command failed')
asserts.assertEqual(results[‘return_codes'][1], 0, ‘second command failed')