Android - Delay When Answering Calls Programmatically on Lollipop - android

I'm working on an app that can answer phone calls programmatically. Iv'e read much about it, and tried many methods to get it to work.
The only true solution that works for me in versions 5.0 and up is as followed -
Runtime.getRuntime().exec("input keyevent " + Integer.toString(KeyEvent.KEYCODE_HEADSETHOOK));
Although this method works, the actual answering time is delayed by 1.5 to 5 seconds. This delay is a real deal breaker, since my app needs to intercept all incoming calls, and I can't have it delaying the answering process.
Is there any other method that works faster?
Thanks

According to another answer[1] this depends on the Super user client used. Chainfire's SuperSU[2] is said to be faster than Superuser
[1] Need root to execute shell command "input keyevent <#>" through an app at runtime?
[2] https://play.google.com/store/apps/details?id=eu.chainfire.supersu

Depending on your situation, if only the root method works for you, one way is to keep the root shell open with your background service, and pipe the input keyevent command to it when needed. This would save the startup time of the process and the shell every time the call comes in. You can do this easily with libraries such as RootShell.

Related

How to obtain activity name through UIAutomator2?

I'm building some general testing tool for Android apps and trying to get the activity name (e.g. com.android.calculator/.Calculator, the com.android.calculator can be obtained through UiDevice.currentPackageName, the pain is from the second part) during the testing. This is to say that my tool may test other apps that are not in the same package as mine. For example, testing the stock calculator app.
Here is a list of attempts I have made:
the UiDevice.currentActivityName is deprecated and it does not provide the accurate information
InstrumentationRegistry.getInstrumentation().targetContext.getSystemService<ActivityManager>(), then access the ActivityManager.getRunningTasks(1).get(0).topActivity, which always returns the same value even though the view has switched (and this is deprecated too)
Similar to 2, I tried ActivityManager.getAppTasks().get(0).getTaskInfo().topActivity, but this keeps giving me null
ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(RESUMED). This gives me an empty collection
Application.ActivityLifecycleCallbacks. I registered it with the application, but no callback is received.
(Kinda works, but not perfect) using adb dumpsys activity then find it there. But this way I have to wait for some arbitrary time until the view is updated, otherwise the result is still inaccurate
So I am currently in a cul-de-sac now, and I appreciate any help on this issue. I try to avoid reflection, because as I know it does not work on newer devices. So any clue will be appreciated.
As there is no answer posted, I wanna share my current strategy, which is not perfect, but somewhat helpful.
So first of all, as UiDevice.getActivityName is deprecated, I can only obtain the activity name through adb. Specifically, I use adb shell dumpsys activity top for API lower than 28 and adb shell dumpsys activity activities otherwise.
Then I subscribed to AccessibilityEventListener callbacks. Specifically, I run the adb command whenever I receive callbacks with type AccessibilityEvent.TYPE_WINDOWS_CHANGED. You can set up AccessibilityEventListener using this method: setOnAccessibilityEventListener

Explain behavior of Unix sleep() function executed on Android

I am currently compiling and executing some C++ code on a rooted Android device. I use adb (adb shell). To compile my code, I don't use the NDK, but I cross-compile with CMake
I'm using the function sleep(seconds) of unistd.h.
I've experienced some curious behaviors with that function on Android: Basically, I have a for loop in which I std::cout something and then call sleep(x).
If I call sleep(1), the behavior is the one expected: The program waits 1 second, and then executes the next instructions.
If I call sleep(2), the behavior isn't the one expected. The program gets stuck on that instruction for ever.... until I hit a key on my PC keyboard (not the device's one), and then it gets stuck on the next sleep(2)... until I hit a key, etc...
This behavior happens only when the device screen is off. As soon as I click on the power button to turn the screen on, the program resumes and has the expected behavior.
N.B: The behavior is the same with usleep(useconds)
I have tried to see where the limit is between 1 and 2 seconds:
1.5s, 1.25s, 1.125s -> always stay blocked | 1.0625s -> ~50% chance of staying blocked.
Obviously, there is something that prevents a thread to wake up if it sleeps more than 1 seconds (at least 2).
So my question would be, does anyone have any idea of why this is happening, and has a detailed explanation of the process ?
Thank you !
Android puts applications in the background when they aren't doing any user interaction - unix sleep and java timers etc. won't wake them up. You have to use an android alarm or runnable postDelayed handler.

How to get CPU usage of certain function in android app?

I'm trying to get CPU usage in some point of running app. I need something like i used for time measurement.
Before I called the function (witch I want to measure) I used System.currentTimeMillis() to get the start time and the difference with the same value after function ended.
Running time of this function could be from 1 to 1000ms.
Mine solutions:
I can use adb top command triggered every millisecond (but i don't think it is working properly) adb shell top -m 15 -d 0.001 > C:\something\something\results.txt
Or, I was thinking about to call this command from running app in another thread (if the function will end so the thread would). If you think this could be the right way, may I still send results of command to some file in phone?Or should I use adb shell top -m 15 -d 0.001 -n 1 and call it in while cycle until thread will end?
If by function you mean literally java function then why dont you measure CPU time of its execution (difference of end and start measurements)? You can use System.currentTimeMillis() but this will measure also time of other threads that got CPU quantum. So I believe you are after Debug.threadCpuTimeNanos() which will measure only time CPU was executing your function code, you can investigate how it works by looking into sources:
http://androidxref.com/5.1.0_r1/xref/art/runtime/utils.cc#177
I'm not sure if this is what you're looking for, I've been looking into Android debugging recently, but I haven't tried this myself.
Here's the link: Traceview War Story, from the Android Developer's blog.
It describes using the Traceview tool to analyze functions and how much time the system is devoting to each process within that function.

Android sendevent is really slow - how to speed it up?

I am doing some ui automation, and I am able to store screen touches using getevent, but when I try to send this using sendevent, it takes a really long time, making it hard to actually replay the inputs.
I have already trying loading the script onto the device and running the script locally on the device (a script with a bunch of sendevent commands). But this only imporved this slightly. Is there some other way to inject these commands in a quicker way?
The handler for touch is implemented differently across devices. You should cat /proc/bus/input/devices to see where the touch handler is implemented.
You can also do adb shell getevent, interact with the device and see the output for the interface name.
The reason why your replay takes a long time is because the sendevent binary opens the interface file, writes data to it and closes it for every call to sendevent. So in theory, if you have a bunch of sendevent commands, the binary is opening the interface file, writing data and closing it for every command.
The way I've solved this issue is by re-writing the sendevent.c file under /system/core/toolbox to open the file only once during replay, writing all the data and closing it at the end of the replay. It works perfectly for me!
OK.
Instead of using the getevent/sendevent you can try direct reading from the event interface
inside adb shell try:
dd if=/dev/input/event6 of=record1 # to record
dd if=./record1 of=/dev/input/event6 #to play
However, this may run too fast...

Android root poweroff

On my android app for root user, I perform a shutdown with
su reboot -p
It works ok, but I noticed that the phone is shutdown almost instantly (as opposed from showing the shutdown animation, and probably doing other stuff).
Is this the correct way to shutdown an android phone programmatically? Are there some critical code that requires to be executed before shutdown?
On Android 4.3 or later, there's probably a better way to shut the device down.
Your app doesn't need to be installed as a system app, but it must have root privileges. You can simply run this one command as root in order to shut the device down:
svc power shutdown
I thank Firelord for his answer elsewhere which inspired me to discover the existence of this shell command.
I think this will do a graceful shutdown, but I'm not sure. Maybe it will do an abrupt shutdown. Please test, and then edit this answer to clarify.
Also, the above shell command does not work in Android 4.2.2 or earlier. The help text doesn't mention it. svc rejects the command as invalid and shows some help text in order to try to be helpful.
If your app is rooted, then run the following as root:
am start -a android.intent.action.ACTION_REQUEST_SHUTDOWN
In the Android source code, you can find the following:
/**
* Low-level function turn the device off immediately, without trying
* to be clean. Most people should use
* {#link android.internal.app.ShutdownThread} for a clean shutdown.
*
* #deprecated
* #hide
*/
#Deprecated
public static native void shutdown();
I think that this native function corresponds to your su reboot -p. Moreover, you can see from the quoted code comment that you should use ShutdownThread to do a clean shutdown.
In ShutdownThread, Android does a bunch of things.
It shuts down ActivityManager. I think shutting down ActivityManager means that all activities will pass necessary lifecycle and, thus, the states of activities will be stored. But I'm not sure. I did not check.
Then, Android turns off the cellular radio interface.
After that, it turns off Bluetooth.
Finally, it tries to shut MountService down.
Thus, you can see that it's wrong to do su reboot -p.
See here:
http://developer.android.com/reference/android/os/PowerManager.html
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
pm.reboot("Because I want you to reboot!")
This should work.

Categories

Resources