デバイスシェル コマンド

VTS テストでは、シェルコマンドを使用して、ターゲット側のテストバイナリの実行、プロパティ、環境変数、システム情報の取得と設定、Android フレームワークの起動と停止を行います。VTS デバイスシェル コマンドの実行には、adb shell コマンドを使用することも、デバイスで動作している VTS シェルドライバ(推奨)を使用することもできます。

ADB シェルの使用

テスト中に、USB ポートのシャットダウン、またはデバイスの再起動を必要とするテストでは、ADB シェルを使用する必要があります。これは、USB 接続が維持されないと VTS シェルドライバが使用できなくなるためです。ADB シェルは、Python テスト スクリプト内で AndroidDevice オブジェクトから呼び出せます。例:

  • Android デバイス オブジェクトを取得します。
        self.device = self.android_devices[0]
        
  • 単一のシェルコマンドを発行します。
        result = self.device.adb.shell(‘ls')
        

VTS シェルドライバの使用

VTS シェルドライバは、デバイス上で実行され、シェルコマンドを実行するエージェント バイナリです。デフォルトでは、デバイスでドライバが動作している場合、VTS はシェルドライバを使用します。この方が adb shell コマンドを使用するよりレイテンシが短くなるためです。

図 1: VTS シェルドライバ

VTS フレームワークはマルチデバイス テストをサポートし、各 Android デバイスはベースランナーの AndroidDevice オブジェクトとして表されます。デフォルトでは、VTS フレームワークは VTS エージェント バイナリと VTS シェルドライバ バイナリを各 Android デバイスに転送し、それらのデバイス上の VTS エージェントとの TCP 接続を確立します。

シェルコマンドを実行するために、ホスト側の Python スクリプトは、AndroidDevice オブジェクト内の ShellMirror オブジェクトに関数呼び出しを行います。ShellMirror オブジェクトはシェルコマンド テキストを protobuf メッセージにまとめて、(TCP チャネル経由で)Android デバイスの VTS エージェントに送信します。すると、デバイス上で実行されているエージェントは、Unix ソケットを使用してシェルコマンドを VTS シェルドライバに転送します。

VTS シェルドライバはシェルコマンドを受け取ると、デバイスシェルで nohup を使用してコマンドを実行し、ハングしないようにします。stdout、stderr、戻りコードが nohup から取得され、VTS エージェントに戻されます。最後に、エージェントはコマンドの結果を protobuf メッセージに入れてホストに返信します。

メリット

adb shell ではなく VTS シェルドライバを使用するメリットは、次のとおりです。

  • 信頼性: デフォルト設定で、VTS シェルドライバは nohup を使用してコマンドを実行します。VTS テストは主に下位レベルの HAL テストとカーネルテストであるため、nohup を使用してシェルコマンドが実行中にハングしないようにします。
  • パフォーマンス: adb shell コマンドは、一部の結果(ディレクトリ内のファイルのリストなど)をキャッシュに保存しますが、テストバイナリの実行などのタスクを実行する際に接続のオーバーヘッドが発生します。VTS シェルドライバはテスト中にアクティブな接続を維持するため、オーバーヘッドは USB の通信だけです。Google によるテストでは、VTS シェルドライバを使用して、空の gtest バイナリを 100 回呼び出すコマンドを実行すると、adb shell を使用するよりも約 20% 高速になっています。VTS シェルの通信では広範囲でログが記録されるため、実際の差はより大きくなります。
  • 状態の保持: VTS シェルドライバはターミナル名ごとにターミナル セッションを管理しています(デフォルトのターミナル名は default です)。あるターミナル セッションで設定された環境変数は、同じセッションの以降のコマンドでのみ使用できます。
  • 拡張可能: VTS フレームワークとデバイス ドライバ間のシェルコマンドの通信では、将来、圧縮、リモート処理、暗号化などを可能にするため protobuf でラップされています。他のパフォーマンス改善方法としては、通信のオーバーヘッドが結果文字列の解析のオーバーヘッドよりも大きくなった場合に、デバイス側で結果を解析する方法などがあります。

デメリット

adb shell ではなく VTS シェルドライバを使用するデメリットは、次のとおりです。

  • 追加のバイナリ: VTS エージェント ファイルをデバイスに転送し、テストの実行後にクリーンアップする必要があります。
  • アクティブな接続が必要: 意図的かどうかに関係なく、USB の切断、ポートのシャットダウン、デバイスのクラッシュなどにより、テスト中にホストとエージェント間の TCP 接続が失われた場合、VTS エージェントにシェルコマンドを送信できなくなります。adb shell への自動切り替えがあっても、切断前のコマンドの結果と状態は不明です。

以下に、VTS ホスト側の Python テスト スクリプトでのシェルコマンドの使用例を示します。

  • Android デバイス オブジェクトを取得します。
        self.device = self.android_devices[0]
        
  • 選択したデバイスのシェル オブジェクトを取得します。
        self.shell = self.device.shell
        
  • 単一のシェルコマンドを発行します。
        results = self.shell.Execute(‘ls')
        
  • シェルコマンドのリストを発行します。
        results = self.shell.Execute([‘cd /data/local/tmp', ‘ls'])
        

コマンドの結果オブジェクト

シェルコマンドの実行からの戻りオブジェクトは、キーを stdoutsstderrsreturn_codes とする辞書です。与えられたシェルコマンドが単一の文字列かコマンド文字列のリストかにかかわらず、結果の辞書の各値は常にリストです。

コマンドのリストの戻りコードを確認するには、テスト スクリプトで複数のインデックスを確認する必要があります。例:

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

スクリプトで各コマンドのインデックスを個別にチェックすることもできます。例:

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