automating android CTS with python - android

I'm trying to automate the full CTS setup and execution with python & monkeyrunner on Ubuntu and most of it has gone very well. As the very final step, I try executing the following python command to start the CTS on a specific device:
cts_tradefed_script = "./android-cts/tools/cts-tradefed"
process = subprocess.Popen([cts_tradefed_script, "run", "cts", "-s", '"' + serialno + '"', "--plan", "CTS"], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
which is the equivalent of:
./android-cts/tools/cts-tradefed run cts -s "R32CB054TSZ" --plan CTS
in the command-line and I get:
Android CTS 4.2_r4
No commands for non-interactive mode; exiting.
06-17 17:32:32 I/: Detected new device R32CB054TSZ
Saved log to /tmp/tradefed_global_log_9173619073367947049.txt
06-17 17:32:32 I/CommandScheduler: All done
The CTS tests don't execute. Is there a command I'm forgetting or is this not possible using Python?

cts_tradefed_script = "./android-cts/tools/cts-tradefed"
process = subprocess.Popen([cts_tradefed_script + " " + serialno], shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
Edit: script was not necessary. Just enter everything as a concatenated String.

The problem with non-interactive is that you cannot run more than a command, so you should try to run in interactive mode.
To run in interactive mode this is one way:
#pip install paramiko
import paramiko
import time
def run_remote_command(channel, command):
channel.send(command)
whole_output = ""
while True:
if channel.recv_ready():
output = channel.recv(1024)
whole_output+=output
else:
time.sleep(0.5)
if not(channel.recv_ready()):
return whole_output
server ="fill you own here"
username = "fill you own here"
password = "fill you own here"
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(server, 22 ,username, password)
channel =ssh.get_transport().open_session()
channel.get_pty()
channel.invoke_shell()
run_1 =run_remote_command(channel,"~/android/out/host/linux-x86/cts/android-cts/tools/cts-tradefed list devices" + "\n")
print run_1
run_2 =run_remote_command(channel,"run cts" + "\n")
print run_2
run_3 =run_remote_command(channel,"l i" + "\n")
print run_3

Related

Unable to execute plink command using groovy script

I got stuck in a issue with plink command running on windows.Below is the command I am firing to drop iptable of remote android device.
plink.exe -v -ssh rauser#HOSTNAME -pw PASSWORD iptables -D INPUT -p tcp -m tcp --dport 5555 -j DROP
I am able to execute the command from command prompt manually but when I am executing command as a bat file from groovy script it throws me an error.I am sharing both with you.
Groovy Script
// enable ADB
commandsList.add(""
"enable-adb.bat "
"" + deviceip)
// run adb commands
commandsList.each {
def command = pathtoadb + it
log.info command
def proc = command.execute()
proc.waitFor() // Wait for the command to finish
// Obtain status and output
log.info "return code: ${ proc.exitValue()}" // "0" is success
//log.info "stderr: ${proc.err.text}"
log.info "stdout: ${proc.in.text}" // *out* from the external program is *in* for groovy
def error = proc.err.text;
// if the output contains "Bad rule" that means ADB is already enabled and we don't want the test to fail
if (!error.contains("Bad rule")) {
log.info " _______ There was a problem connecting to your device using SSH. Check if remote access is enabled on your device"
log.info("ERROR: " + error)
} else {
log.info " _______ return code is 1 because ADB was already enabled - this is not a failure"
log.info(" ******** ADB has been enabled on device --> " + deviceip)
}
Exeception Message
Server version: SSH-2.0-OpenSSH_5.9
Using SSH protocol version 2
We claim version: SSH-2.0-PuTTY_Release_0.62
Doing Diffie-Hellman group exchange
Server unexpectedly closed network connection
FATAL ERROR: Server unexpectedly closed network connection

Launch adb commands in python

I try launch adb commands in python without custom modules.
try:
process = subprocess.Popen('cmd.exe', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=None, shell=True)
process.stdin.write("adb shell uninstall com.q.q".encode("utf8"))
process.stdin.write("adb shell install C:\\...\\qwerty.apk".encode("utf8"))
but this not working. Code finish without results
cannot test with your exact commands but that works fine:
import subprocess
process = subprocess.Popen('cmd.exe', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=None, shell=True)
o,e = process.communicate(b"dir\n")
print(o)
(I get the contents of my directory)
so for your example, you're missing the line terminators when sending commands. The commands aren't issued to the cmd program, the pipe is broken before that.
That would work better:
import subprocess
process = subprocess.Popen('cmd.exe', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=None)
process.stdin.write(b"adb shell uninstall com.q.q\n")
process.stdin.write(b"adb shell install C:\\...\\qwerty.apk\n")
o,e = process.communicate()
but this is a very strange way to run commands. Just use check_call, with args split properly:
subprocess.check_call(["adb","shell","uninstall","com.q.q"])
subprocess.check_call(["adb","shell","install",r"C:\...\qwerty.apk"])

Popen shell commands and | pipe symbol

I have checked out numerous other threads with the same issue, but cannot get one that works for me.
I am trying to run a command using the | character on a Windows machine, with python and wx.python. Command I'm trying to run is: adb.exe logcat | findstr myApp (stored in pkgName)
I have tried the following with no success, nothing is written in 'progressBox': note: they weren't all tried at the same time ;)
logcat = subprocess.Popen(toolsDir + "\\adb.exe logcat", stdout=subprocess.PIPE)
findstr = subprocess.Popen("findstr '"+ pkgName+"'", stdin=logcat.stdout, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = findstr.communicate()
cmd = toolsDir+"\\adb.exe logcat | findstr " + pkgName
ps = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
stdout = ps.communicate()[0]
c_arg = 'logcat | findstr ' + pkgName
params = toolsDir + "\\adb.exe " + c_arg
p = Popen(params, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
They are all slightly different, but none append to my progressBox to print out the output.
self.progressBox.AppendText(stdout)
self.progressBox.AppendText(stderr)
I have myself faced issue numerous times using subprocess library to run system command. I would probably recommend using core os library, still i am not very sure if this will work on windows but you could give a try.
import os
cmd = "ls -la > output.txt"
os.system(cmd)
reader = open("output.txt")
print(reader.read())
PS: It is recommended to use subprocess module to run system command, you should use above code only when you are unable to find a solution and just want to run code urgently.

How to run adb commands in VB.NET

I am studying android and .NET
I would like to use VB.NET to execute adb command
For example, I would like to enable or disable airplane mode from PC to Android phone
such as
adb shell settings put global airplane_mode_on 1
adb shell am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true
Dim psi As New ProcessStartInfo
Dim psi2 As New ProcessStartInfo
psi.WorkingDirectory = "C:\ad\adsystem\adb file"
psi.Arguments = "adb shell settings put global airplane_mode_on 0"
psi.FileName = "adb"
psi.WindowStyle = ProcessWindowStyle.Hidden
Process.Start(psi)
psi2.WorkingDirectory = "C:\ad\adsystem\adb file"
psi2.Arguments = "adb shell am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false"
psi2.FileName = "adb"
psi2.WindowStyle = ProcessWindowStyle.Hidden
Process.Start(psi)
I tried to use example from
How to get Output of a Command Prompt Window line by line in Visual Basic?
Shell commands in VB
However, It didn't really work and i am not really sure why ....
is there anyway to run adb command from VB.NET?
thanks
You can use cmd.exe to communicate with adb commands see my code example.
Declaring new process and process info
Dim My_Process As New Process()
Dim My_Process_Info As New ProcessStartInfo()
Using cmd.exe as the filename of my process.
My_Process_Info.FileName = "cmd.exe"
in argument you can use adb commands like this.
My_Process_Info.Arguments = "/c adb devices"
/c Carries out the command specified by string and then terminates.
Now set WorkingDirectory for adb.exe in cmd.exe. Don't confuse, it is same as cd command. Setting our working Directory to where your adb.exe file exists.
My_Process_Info.WorkingDirectory = "Directory of your adb.exe file"
Now some necessary settings for process.
My_Process_Info.CreateNoWindow = True ' Show or hide the process Window
My_Process_Info.UseShellExecute = False ' Don't use system shell to execute the process
My_Process_Info.RedirectStandardOutput = True ' Redirect (1) Output
My_Process_Info.RedirectStandardError = True ' Redirect non (1) Output
My_Process.EnableRaisingEvents = True ' Raise events
My_Process.StartInfo = My_Process_Info
Setting completed, Now start the process.
My_Process.Start()
If you want to get the reply/result of your sended adb command you can use StandardOutput property of the process.
Dim Process_ErrorOutput As String = My_Process.StandardOutput.ReadToEnd() ' Stores the Error Output (If any)
Dim Process_StandardOutput As String = My_Process.StandardOutput.ReadToEnd() ' Stores the Standard Output (If any)
Example Function:
Function adb(ByVal Arguments As String) As String
Try
Dim My_Process As New Process()
Dim My_Process_Info As New ProcessStartInfo()
My_Process_Info.FileName = "cmd.exe" ' Process filename
My_Process_Info.Arguments = Arguments ' Process arguments
My_Process_Info.WorkingDirectory = "C:\Users\<Your User Name>\AppData\Local\Android\android-sdk\platform-tools" 'this directory can be different in your case.
My_Process_Info.CreateNoWindow = True ' Show or hide the process Window
My_Process_Info.UseShellExecute = False ' Don't use system shell to execute the process
My_Process_Info.RedirectStandardOutput = True ' Redirect (1) Output
My_Process_Info.RedirectStandardError = True ' Redirect non (1) Output
My_Process.EnableRaisingEvents = True ' Raise events
My_Process.StartInfo = My_Process_Info
My_Process.Start() ' Run the process NOW
Dim Process_ErrorOutput As String = My_Process.StandardOutput.ReadToEnd() ' Stores the Error Output (If any)
Dim Process_StandardOutput As String = My_Process.StandardOutput.ReadToEnd() ' Stores the Standard Output (If any)
' Return output by priority
If Process_ErrorOutput IsNot Nothing Then Return Process_ErrorOutput ' Returns the ErrorOutput (if any)
If Process_StandardOutput IsNot Nothing Then Return Process_StandardOutput ' Returns the StandardOutput (if any)
Catch ex As Exception
Return ex.Message
End Try
Return "OK"
End Function
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
'Usage:
'Get the list of connected devices.
MsgBox(adb("/c adb devices"))
'Connect your phone wirelessly using wifi (required phone I.P)
MsgBox(adb("/c adb disconnect 192.168.xx.xx:5555"))
'Get the list of connected devices.
MsgBox(adb("/c adb devices"))
'Put your phone on airplane mode.
MsgBox(adb("/c adb shell settings put global airplane_mode_on 1"))
End Sub

ADB Error codes

We have an android device and as part of testing I need to excute a console test application on the target device. If the test application detects an error it returns -1.
I can use adb shell to run the test applications remotely on the target but I can't find a way of getting back the return code. I need this so I that I can build this into an automated test suite.
I could try grepping the console output for some failure text but that is a bit grubby. Does anyone know of a more elegant solution?
This is a workaround to get the exit code:
adb shell '{your command here} > /dev/null 2>&1; echo $?'
This is a wrapper around adb in Ruby:
def adb(opt)
input = "#{adb_command} #{opt[:command]} #{opt[:params]}"
puts "Executing #{input}...\n"
output = nil
exit_code = 0
def wait_for(secs)
if secs
begin
Timeout::timeout(secs) { yield }
rescue
print 'execution expired'
end
else
yield
end
end
wait_for(opt[:timeout]) do
case opt[:command]
when :install, :push, :uninstall
output, exit_code = `#{input}`, $?.to_i
when :shell
input = "#{adb_command} shell \"#{opt[:params]}; echo \\$?\""
output = `#{input}`.split("\n")
exit_code = output.pop.to_i
output = output.join("\n")
else
raise 'Error: param command to adb not defined!'
end
end
return if opt[:ignore_fail] and output =~ /#{opt[:ignore_fail]}/
raise output unless exit_code == 0
end
You could use Facebook's fb-adb, a "A better shell for Android devices" which "propagates program exit status instead of always exiting with status 0".

Categories

Resources