Android ADB Tool, 'fork' doesn't work - android

Environment
Android 5.0 # Samsung Galaxy 5
ADB # Windows (x64)
Native ADB Commandline tool
Use-case
An application that forks and immediately exit
Problem description
While fork returns a propper pid_t of the newly created process, no actual process is being created, ( 'adb -d shell ps | findstr shell' shows no new process )
Code snippet
__android_log_print(ANDROID_LOG_INFO, "ScreenCapSvc", "\n");
pid_t pid = fork();
__android_log_print(ANDROID_LOG_INFO, "ScreenCapSvc", "STARTED, pid = %d\n", pid);
if (0 != pid)
return S_OK;// Exits the parent process
HRESULT hr;
__android_log_print(ANDROID_LOG_INFO, "ScreenCapSvc", "Initializing\n");
if (FAILED(hr = Initialize(pBaseAddress, wPort, uiMaxMessageSize)))
return hr;
__android_log_print(ANDROID_LOG_INFO, "ScreenCapSvc", "Running modal loop\n");
hr = m_spIOCP->DoModal();
OnCleanup(hr);
__android_log_print(ANDROID_LOG_INFO, "ScreenCapSvc", "STOPPED, pid = %d\n", pid);
return S_OK;
Logcat output
I/ScreenCapSvc(29062):
I/ScreenCapSvc(29062): STARTED, pid = 29064
Additional info
If rather them immediately exiting the parent process I call eg. sleep(2) than the child process is properly forked, HOWEVER, While the parent process actually terminate, 'ADB -d shell' never exit ( stays hanging infinity ).
Related link: https://stackoverflow.com/questions/28277361/android-adb-tool-c11-stdthread-usage
What am I doing wrong? why does the process doesn't fork?

Related

Run a shell command via QProcess on Android Platform

I cannot run any command via QProcess on Android platform. I am using Qt library. Can anyone explain how to run shell commands from my application on Android platform ?
QProcess process();
process.execute("ls");
bool finished = process.waitForFinished(-1);
qDebug() << "End : " << finished << " Output : " << process.errorString();
The process doesn't finish if I don't specify timeout. process.waitForFinished() returns false when I specify timeout let's say 10000 ms.
Your example code is faulty and it will not work on ANY platform!
ls command is not an exactable! This command is build into a shell program for example bash.
Another bug in your code is that QProcess::execute is a static function.
So final line doesn't have impact on process you have tried to start.
So your code should look like this:
QProcess process;
process.start("bash", QStringList() << "-c" << "ls");
bool finished = process.waitForFinished(-1);
You are using QProcess::execute() which is a static function. Quoting Qt documentation: "Starts the program command in a new process, waits for it to finish".
So what could happen in your code is:
QProcess process();
process.execute("ls"); // Start "ls" and wait for it to finish
// "ls" has finished
bool finished = process.waitForFinished(-1); // Wait for the process to finish, but there is no process and you could get locked here forever...
There are 2 ways to fix your code:
QProcess process();
process.start("ls"); // Start "ls" and returns
bool finished = process.waitForFinished(-1);
qDebug() << "End : " << finished << " Output : " << process.errorString();
or
QProcess::execute("ls");

Obtain complete package name in android kernel mode

I am working on one project requires obtaining the complete app package name inside kernel mode. I realized the package name is also the process name inside kernel. However, the task_struct->comm (process name) can only give me 15 characters long.
Also, fs/proc/base.c proc_get_cmdline() can return the full process name but it is private function. I try to export proc_get_cmdline() to public and invoke from my loadable kernel module, but it always crash when I invoke the public proc_get_cmdline().
Is there any way I can get the complete package name inside kernel? Like read from proc/pid/cmdline, read from mm_struct, etc. Appreciate any code example.
You are not supposed to call proc_pid_cmdline().
It is a non-public function in fs/proc/base.c:
static int proc_pid_cmdline(struct seq_file *m, struct pid_namespace *ns,
struct pid *pid, struct task_struct *task)
However, what it does is simple:
get_cmdline(task, m->buf, PAGE_SIZE);
That is not likely to return the full path though and it will not be possible to determine the full path in every case. The arg[0] value may be overwritten, the file could be deleted or moved, etc. A process may exec() in a way which obscures the original command line, and all kinds of other maladies.
A scan of my opensuse 12.3 system /proc/*/cmdline turns up all kinds of less-than-useful results:
/proc/1/cmdline
/sbin/init showopts
/proc/10/cmdline
/proc/11/cmdline
/proc/1163/cmdline
/sbin/dhclient6 -6 -cf /var/lib/dhcp6/dhclient6.eth0.conf -lf /var/lib/dhcp6/dhclient6.eth0.lease -pf /var/run/dhclient6.eth0.pid -q eth0
/proc/12/cmdline
/proc/13/cmdline
/proc/14/cmdline
/proc/15/cmdline
/proc/16/cmdline
/proc/17/cmdline
/proc/1710/cmdline
/sbin/dhcpcd --netconfig -L -E -HHH -c /etc/sysconfig/network/scripts/dhcpcd-hook -t 0 -h del1-dhp-32429 eth0
/proc/172/cmdline
/proc/185/cmdline
/proc/186/cmdline
/proc/187/cmdline
/proc/19/cmdline
/proc/2/cmdline
/proc/20/cmdline
/proc/21/cmdline
/proc/22/cmdline
/proc/23/cmdline
/proc/25/cmdline
/proc/254/cmdline
/proc/255/cmdline
/proc/26/cmdline
/proc/2671/cmdline
/usr/lib/upower/upowerd
/proc/2674/cmdline
/usr/lib/polkit-1/polkitd --no-debug
/proc/27/cmdline
/proc/2727/cmdline
/usr/lib/udisks2/udisksd --no-debug
/proc/28/cmdline
/proc/285/cmdline
/usr/lib/systemd/systemd-journald
/proc/286/cmdline
/proc/288/cmdline
/proc/29/cmdline
/proc/2913/cmdline
/usr/sbin/cron -n
/proc/2924/cmdline
/usr/sbin/sshd -D
/proc/3/cmdline
/proc/3023/cmdline
/usr/lib/postfix/master
/proc/3090/cmdline
pickup -l -t fifo -u
/proc/3091/cmdline
qmgr -l -t fifo -u
/proc/31/cmdline
/proc/311/cmdline
/usr/lib/systemd/systemd-udevd
/proc/3132/cmdline
/usr/lib/vmware/bin/vmware-vmblock-fuse -o subtype=vmware-vmblock,default_permissions,allow_other /var/run/vmblock-fuse
/proc/3168/cmdline
/usr/sbin/vmware-authdlauncher
/proc/32/cmdline
Works for me in openSUSE 12.3:
for I in /proc/*/cmdline; do echo $I; cat $I | tr '\000' ' '; echo; done

How do I use async_start and async_stop in systrace/atrace for Android

I want to capture Systrace report on my Android phone while doing automated testing. It is unknown how long the testing will take, so I can't specify the --time period for the Systrace.
Digging deeper in to the systrace.py, I found out that systrace is using atrace to get the kernel logs.
I used adb shell atrace --help and got the following output:
usage: atrace [options] [categories...]
options include:
-a appname enable app-level tracing for a comma separated list of cmdlines
-b N use a trace buffer size of N KB
-c trace into a circular buffer
-k fname,... trace the listed kernel functions
-n ignore signals
-s N sleep for N seconds before tracing [default 0]
-t N trace for N seconds [defualt 5]
-z compress the trace dump
--async_start start circular trace and return immediatly
--async_dump dump the current contents of circular trace buffer
--async_stop stop tracing and dump the current contents of circular
trace buffer
--list_categories
list the available tracing categories
How can I use atrace to start tracing at the beginning of my automated testing, and stop the tracing and dumping the kernel log at the end of my automated testing?
I tried using the following commands, but I don't think it works properly. Only async_dump gives me some data in the log. async_stop dump doesn't have any content in the log. How do I properly start the trace, dump it, and then stop it?
adb shell atrace -b 10000 -c am shedgfx view --async_start > C:\Users\user1\Desktop\log.txt
adb shell atrace -b 10000 -c am shedgfx view --async_dump > C:\Users\user1\Desktop\log.txt
adb shell atrace -b 10000 -c am shedgfx view --async_stop > C:\Users\user1\Desktop\log.txt
schedgfx should probably be 2 separate calls: sched and gfx. See the output from your device when running:
$ adb shell atrace --list_categories
The categories should be the last part of the command line (in your commands, the categories are placed before the async_* options):
$ adb shell atrace --help
usage: atrace [options] [categories...]
options include:
-a appname enable app-level tracing for a comma separated list of cmdlines
-b N use a trace buffer size of N KB
-c trace into a circular buffer
-k fname,... trace the listed kernel functions
-n ignore signals
-s N sleep for N seconds before tracing [default 0]
-t N trace for N seconds [defualt 5]
-z compress the trace dump
--async_start start circular trace and return immediatly
--async_dump dump the current contents of circular trace buffer
--async_stop stop tracing and dump the current contents of circular
trace buffer
--list_categories
list the available tracing categories
The tool runs on a circular buffer, so each time you run the dump command, you'll only get whatever contents are in the buffer at that time. In the Espresso rules:0.5 package (assuming you are using Espresso), there is an AtraceLogger class that can help automate this for you as part of your test harness, by calling the atraceStart(...) method:
public void atraceStart(Set<String> traceCategoriesSet, int atraceBufferSize, int dumpIntervalSecs, File destDirectory, String traceFileName) throws IOException
You can do that by creating a #Rule or #ClassRule, or hook into it some other way such as with a TestRunner:
#Override
protected void before() throws Throwable {
mAtrace = AtraceLogger.getAtraceLoggerInstance(InstrumentationRegistry.getInstrumentation());
mAtrace.atraceStart(new HashSet<>(Arrays.asList("gfx", "sched", ...)),
1024 /* bufferSize */, 1 /* dump interval */,
RuleLoggingUtils.getTestRunDir(), "filename");
}
#Override
protected void after() {
try {
mAtrace.atraceStop();
} catch (IOException e) {
Log.w(TAG, "Failed to stop Atrace", e);
} catch (InterruptedException e) {
Log.w(TAG, "Failed to stop Atrace", e);
}
}
The RuleLoggingUtils.getTestRunDir() method will place the captured dump files into the external files path for your app, so you can pull those files after the test is finished, using:
$ adb pull /sdcard/Android/data/com.yourcompany.package/files/testdata/
And each atrace file can then be inspected using the systrace viewer by running systrace with the --from-file=<trace file> option.

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