Skip to content

Commit 18b92ca

Browse files
xaionaro@dx.centerxaionaro@dx.center
authored andcommitted
Add 19 missing E2E tests for aidlcli commands
Cover service methods/transact, location (GNSS year, last location), package manager (installer package name), telephony (country ISO), WiFi supplicant (add-network, disconnect, set-ssid, set-psk-passphrase, set-key-mgmt, enable), camera (characteristics, torch mode), audio (active microphones, microphone direction/dimension), and bluetooth (initialize, send-hci-command). Adds runAidlcliHALOrSkip helper to reduce boilerplate for HAL service tests that should skip when the service is unavailable on emulators.
1 parent d735450 commit 18b92ca

1 file changed

Lines changed: 340 additions & 0 deletions

File tree

tests/e2e/aidlcli_test.go

Lines changed: 340 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,3 +676,343 @@ func TestAidlcli_Bluetooth_Close(t *testing.T) {
676676
assert.Equal(t, "ok", val)
677677
t.Logf("bluetooth close: status=%s", val)
678678
}
679+
680+
// runAidlcliHALOrSkip runs aidlcli for a HAL service and skips the test
681+
// when the service is unavailable or returns any error.
682+
// HAL services are typically absent on emulators, so all errors are treated as skip-worthy.
683+
func runAidlcliHALOrSkip(
684+
t *testing.T,
685+
serviceName string,
686+
args ...string,
687+
) string {
688+
t.Helper()
689+
fullArgs := append([]string{serviceName}, args...)
690+
stdout, stderr, err := runAidlcli(fullArgs...)
691+
if err != nil {
692+
combined := stderr + stdout
693+
switch {
694+
case strings.Contains(combined, "not found"),
695+
strings.Contains(combined, "no service with descriptor"):
696+
t.Skipf("%s not available: %s", serviceName, strings.TrimSpace(combined))
697+
}
698+
t.Skipf("%s unavailable: %v\nstdout: %s\nstderr: %s", serviceName, err, stdout, stderr)
699+
}
700+
return stdout
701+
}
702+
703+
// --- Core service commands (additional) ---
704+
705+
func TestAidlcli_ServiceMethods(t *testing.T) {
706+
stdout := runAidlcliOrSkip(t, "service", "methods", "activity")
707+
708+
var envelope map[string]any
709+
require.NoError(t, json.Unmarshal([]byte(stdout), &envelope), "unmarshal response")
710+
711+
descriptor, ok := envelope["descriptor"].(string)
712+
require.True(t, ok, "response missing 'descriptor' string")
713+
assert.NotEmpty(t, descriptor, "descriptor should not be empty")
714+
715+
methods, ok := envelope["methods"].([]any)
716+
require.True(t, ok, "response missing 'methods' array")
717+
require.NotEmpty(t, methods, "expected at least one method")
718+
719+
// Verify the first method has a name field.
720+
firstMethod, ok := methods[0].(map[string]any)
721+
require.True(t, ok, "method entry should be an object")
722+
name, ok := firstMethod["name"].(string)
723+
require.True(t, ok, "method should have a 'name' string")
724+
assert.NotEmpty(t, name, "method name should not be empty")
725+
726+
t.Logf("activity interface %s has %d methods, first: %s", descriptor, len(methods), name)
727+
}
728+
729+
func TestAidlcli_ServiceTransact(t *testing.T) {
730+
// Transaction code 64 on SurfaceFlinger queries active color mode.
731+
stdout := runAidlcliOrSkip(t, "service", "transact", "SurfaceFlinger", "64")
732+
733+
var envelope map[string]any
734+
require.NoError(t, json.Unmarshal([]byte(stdout), &envelope), "unmarshal response")
735+
736+
replyHex, ok := envelope["reply_hex"].(string)
737+
require.True(t, ok, "response missing 'reply_hex' string")
738+
assert.NotEmpty(t, replyHex, "reply_hex should not be empty")
739+
740+
replySize, ok := envelope["reply_size"].(float64)
741+
require.True(t, ok, "response missing 'reply_size' number")
742+
assert.Greater(t, replySize, float64(0), "reply_size should be > 0")
743+
744+
t.Logf("transact SurfaceFlinger code=64: reply_size=%.0f reply_hex=%s", replySize, replyHex)
745+
}
746+
747+
// --- Location (additional) ---
748+
749+
func TestAidlcli_Location_GetGnssYearOfHardware(t *testing.T) {
750+
stdout, stderr, err := runAidlcli(
751+
"android.location.ILocationManager", "get-gnss-year-of-hardware",
752+
)
753+
if err != nil {
754+
combined := stderr + stdout
755+
switch {
756+
case strings.Contains(combined, "not found"),
757+
strings.Contains(combined, "no service with descriptor"):
758+
t.Skipf("location service not available: %s", strings.TrimSpace(combined))
759+
}
760+
// GNSS year might not be available on emulator.
761+
t.Skipf("GNSS year of hardware unavailable: %v\nstdout: %s\nstderr: %s", err, stdout, stderr)
762+
}
763+
764+
var envelope map[string]any
765+
require.NoError(t, json.Unmarshal([]byte(stdout), &envelope), "unmarshal response")
766+
767+
raw, ok := envelope["result"]
768+
require.True(t, ok, "response missing 'result' key")
769+
770+
val, ok := raw.(float64)
771+
require.True(t, ok, "result should be numeric, got %T", raw)
772+
773+
// Sanity check: year should be a reasonable value (0 means unknown, otherwise 2000+).
774+
year := int(val)
775+
if year != 0 {
776+
assert.GreaterOrEqual(t, year, 2000, "year should be >= 2000 if set")
777+
}
778+
t.Logf("getGnssYearOfHardware: %d", year)
779+
}
780+
781+
func TestAidlcli_Location_GetLastLocation(t *testing.T) {
782+
stdout, stderr, err := runAidlcli(
783+
"android.location.ILocationManager", "get-last-location",
784+
"--provider=gps",
785+
"--packageName=com.android.shell",
786+
"--attributionTag=none",
787+
)
788+
if err != nil {
789+
combined := stderr + stdout
790+
switch {
791+
case strings.Contains(combined, "not found"),
792+
strings.Contains(combined, "no service with descriptor"):
793+
t.Skipf("location service not available: %s", strings.TrimSpace(combined))
794+
case strings.Contains(combined, "NullPointer"),
795+
strings.Contains(combined, "null"):
796+
t.Skipf("no last location available (NullPointer): %s", strings.TrimSpace(combined))
797+
}
798+
t.Skipf("get-last-location unavailable: %v\nstdout: %s\nstderr: %s", err, stdout, stderr)
799+
}
800+
801+
var envelope map[string]any
802+
require.NoError(t, json.Unmarshal([]byte(stdout), &envelope), "unmarshal response")
803+
804+
// Result may be null if no location has been recorded.
805+
raw, ok := envelope["result"]
806+
require.True(t, ok, "response missing 'result' key")
807+
t.Logf("getLastLocation: %v", raw)
808+
}
809+
810+
// --- PackageManager (additional) ---
811+
812+
func TestAidlcli_PackageManager_GetInstallerPackageName(t *testing.T) {
813+
stdout := runAidlcliOrSkip(t,
814+
"android.content.pm.IPackageManager", "get-installer-package-name",
815+
"--packageName=com.android.settings",
816+
)
817+
818+
var envelope map[string]any
819+
require.NoError(t, json.Unmarshal([]byte(stdout), &envelope), "unmarshal response")
820+
821+
_, ok := envelope["result"]
822+
require.True(t, ok, "response missing 'result' key")
823+
824+
// The result may be null/empty if Settings was not installed via a store.
825+
t.Logf("getInstallerPackageName(com.android.settings): %v", envelope["result"])
826+
}
827+
828+
// --- Telephony (additional) ---
829+
830+
func TestAidlcli_Telephony_GetNetworkCountryIso(t *testing.T) {
831+
stdout, stderr, err := runAidlcli(
832+
"com.android.internal.telephony.ITelephony", "get-network-country-iso-for-phone",
833+
"--phoneId=0",
834+
"--callingPackage=com.android.shell",
835+
"--callingFeatureId=none",
836+
)
837+
if err != nil {
838+
combined := stderr + stdout
839+
switch {
840+
case strings.Contains(combined, "not found"),
841+
strings.Contains(combined, "no service with descriptor"):
842+
t.Skipf("telephony service not available: %s", strings.TrimSpace(combined))
843+
}
844+
t.Skipf("telephony unavailable: %v\nstdout: %s\nstderr: %s", err, stdout, stderr)
845+
}
846+
847+
var envelope map[string]any
848+
require.NoError(t, json.Unmarshal([]byte(stdout), &envelope), "unmarshal response")
849+
850+
raw, ok := envelope["result"]
851+
require.True(t, ok, "response missing 'result' key")
852+
853+
// Result should be a string (ISO country code, may be empty).
854+
val, ok := raw.(string)
855+
require.True(t, ok, "result should be string, got %T", raw)
856+
857+
if val != "" {
858+
assert.Len(t, val, 2, "country ISO should be a 2-letter code")
859+
}
860+
t.Logf("getNetworkCountryIsoForPhone(0): %q", val)
861+
}
862+
863+
// --- WiFi supplicant (additional) ---
864+
865+
func TestAidlcli_WiFi_AddNetwork(t *testing.T) {
866+
stdout := runAidlcliHALOrSkip(t,
867+
"android.hardware.wifi.supplicant.ISupplicantStaIface", "add-network",
868+
)
869+
870+
var envelope map[string]any
871+
require.NoError(t, json.Unmarshal([]byte(stdout), &envelope), "unmarshal response")
872+
t.Logf("addNetwork: %v", envelope)
873+
}
874+
875+
func TestAidlcli_WiFi_Disconnect(t *testing.T) {
876+
stdout := runAidlcliHALOrSkip(t,
877+
"android.hardware.wifi.supplicant.ISupplicantStaIface", "disconnect",
878+
)
879+
880+
var envelope map[string]any
881+
require.NoError(t, json.Unmarshal([]byte(stdout), &envelope), "unmarshal response")
882+
t.Logf("disconnect: %v", envelope)
883+
}
884+
885+
func TestAidlcli_WiFi_SetSsid(t *testing.T) {
886+
// "test" in hex = 74657374
887+
stdout := runAidlcliHALOrSkip(t,
888+
"android.hardware.wifi.supplicant.ISupplicantStaNetwork", "set-ssid",
889+
"--ssid=74657374",
890+
)
891+
892+
var envelope map[string]any
893+
require.NoError(t, json.Unmarshal([]byte(stdout), &envelope), "unmarshal response")
894+
t.Logf("setSsid: %v", envelope)
895+
}
896+
897+
func TestAidlcli_WiFi_SetPskPassphrase(t *testing.T) {
898+
stdout := runAidlcliHALOrSkip(t,
899+
"android.hardware.wifi.supplicant.ISupplicantStaNetwork", "set-psk-passphrase",
900+
"--psk=testpassphrase",
901+
)
902+
903+
var envelope map[string]any
904+
require.NoError(t, json.Unmarshal([]byte(stdout), &envelope), "unmarshal response")
905+
t.Logf("setPskPassphrase: %v", envelope)
906+
}
907+
908+
func TestAidlcli_WiFi_SetKeyMgmt(t *testing.T) {
909+
stdout := runAidlcliHALOrSkip(t,
910+
"android.hardware.wifi.supplicant.ISupplicantStaNetwork", "set-key-mgmt",
911+
"--keyMgmtMask=2",
912+
)
913+
914+
var envelope map[string]any
915+
require.NoError(t, json.Unmarshal([]byte(stdout), &envelope), "unmarshal response")
916+
t.Logf("setKeyMgmt: %v", envelope)
917+
}
918+
919+
func TestAidlcli_WiFi_Enable(t *testing.T) {
920+
stdout := runAidlcliHALOrSkip(t,
921+
"android.hardware.wifi.supplicant.ISupplicantStaNetwork", "enable",
922+
"--noConnect=false",
923+
)
924+
925+
var envelope map[string]any
926+
require.NoError(t, json.Unmarshal([]byte(stdout), &envelope), "unmarshal response")
927+
t.Logf("enable: %v", envelope)
928+
}
929+
930+
// --- Camera (additional) ---
931+
932+
func TestAidlcli_Camera_GetCameraCharacteristics(t *testing.T) {
933+
stdout := runAidlcliHALOrSkip(t,
934+
"android.hardware.camera.device.ICameraDevice", "get-camera-characteristics",
935+
)
936+
937+
var envelope map[string]any
938+
require.NoError(t, json.Unmarshal([]byte(stdout), &envelope), "unmarshal response")
939+
940+
_, ok := envelope["result"]
941+
require.True(t, ok, "response missing 'result' key")
942+
t.Logf("getCameraCharacteristics: result present")
943+
}
944+
945+
func TestAidlcli_Camera_SetTorchMode(t *testing.T) {
946+
stdout := runAidlcliHALOrSkip(t,
947+
"android.hardware.camera.provider.ICameraProvider", "set-torch-mode",
948+
"--cameraDeviceName=0",
949+
"--enabled=true",
950+
)
951+
952+
var envelope map[string]any
953+
require.NoError(t, json.Unmarshal([]byte(stdout), &envelope), "unmarshal response")
954+
t.Logf("setTorchMode: %v", envelope)
955+
}
956+
957+
// --- Audio (HAL) ---
958+
959+
func TestAidlcli_Audio_GetActiveMicrophones(t *testing.T) {
960+
stdout := runAidlcliHALOrSkip(t,
961+
"android.hardware.audio.core.IStreamIn", "get-active-microphones",
962+
)
963+
964+
var envelope map[string]any
965+
require.NoError(t, json.Unmarshal([]byte(stdout), &envelope), "unmarshal response")
966+
967+
_, ok := envelope["result"]
968+
require.True(t, ok, "response missing 'result' key")
969+
t.Logf("getActiveMicrophones: %v", envelope["result"])
970+
}
971+
972+
func TestAidlcli_Audio_SetMicrophoneDirection(t *testing.T) {
973+
// Direction: 1 = FRONT.
974+
stdout := runAidlcliHALOrSkip(t,
975+
"android.hardware.audio.core.IStreamIn", "set-microphone-direction",
976+
"--direction=1",
977+
)
978+
979+
var envelope map[string]any
980+
require.NoError(t, json.Unmarshal([]byte(stdout), &envelope), "unmarshal response")
981+
t.Logf("setMicrophoneDirection: %v", envelope)
982+
}
983+
984+
func TestAidlcli_Audio_SetMicrophoneFieldDimension(t *testing.T) {
985+
stdout := runAidlcliHALOrSkip(t,
986+
"android.hardware.audio.core.IStreamIn", "set-microphone-field-dimension",
987+
"--zoom=1.0",
988+
)
989+
990+
var envelope map[string]any
991+
require.NoError(t, json.Unmarshal([]byte(stdout), &envelope), "unmarshal response")
992+
t.Logf("setMicrophoneFieldDimension: %v", envelope)
993+
}
994+
995+
// --- Bluetooth (additional) ---
996+
997+
func TestAidlcli_Bluetooth_Initialize(t *testing.T) {
998+
stdout := runAidlcliHALOrSkip(t,
999+
"android.hardware.bluetooth.IBluetoothHci", "initialize",
1000+
)
1001+
1002+
var envelope map[string]any
1003+
require.NoError(t, json.Unmarshal([]byte(stdout), &envelope), "unmarshal response")
1004+
t.Logf("bluetooth initialize: %v", envelope)
1005+
}
1006+
1007+
func TestAidlcli_Bluetooth_SendHciCommand(t *testing.T) {
1008+
// HCI Reset command: OGF=0x03, OCF=0x0003 => opcode 0x0C03, param_len=0
1009+
// Wire bytes: 01 03 0c 00
1010+
stdout := runAidlcliHALOrSkip(t,
1011+
"android.hardware.bluetooth.IBluetoothHci", "send-hci-command",
1012+
"--command=01030c00",
1013+
)
1014+
1015+
var envelope map[string]any
1016+
require.NoError(t, json.Unmarshal([]byte(stdout), &envelope), "unmarshal response")
1017+
t.Logf("bluetooth sendHciCommand: %v", envelope)
1018+
}

0 commit comments

Comments
 (0)