I have a BroadcastReceiver that receives input from an outside source.
This receiver must then behave as a "mouse-like" program and send input events to the system. I have Root access and permissions.
My problem is that when I send a String such as "input tap 275 410"
, the program behaves correctly, if I even split the string such as "input" + " tap" + " 275" + " 410"
, it still works...
However, when I assemble the string as the desired:
"input " + CursorSystem.command + " " + coords[0] + " " + coords[1]
Then nothing happens... while debugging, all the watched Strings are exactly the same (minus the location):
value = {char[26]@830031306976} 0 = 'i' 105 1 = 'n' 110 2 = 'p' 112 3 = 'u' 117 4 = 't' 116 5 = ' ' 32 6 = 't' 116 7 = 'a' 97 8 = 'p' 112 9 = ' ' 32 10 = '2' 50 11 = '7' 55 12 = '5' 53 13 = ' ' 32 14 = '4' 52 15 = '1' 49 16 = '0' 48 17 = '\u0000' 0 18 = '\u0000' 0 19 = '\u0000' 0 20 = '\u0000' 0 21 = '\u0000' 0 22 = '\u0000' 0 23 = '\u0000' 0 24 = '\u0000' 0 25 = '\u0000' 0
I would like some guidance or a property to study, since my results are not being effective. As far as I can tell, this is not a permission issue, nor is it a thread issue, since Logs show the permission request (and the grant), an the thread lives for as long as the Receiver is being executed (but if I debug it for too long, then it gets killed after a while [30+ seconds])
The Receiver.onReceive:
public void onReceive(Context context, Intent intent) {
String command = intent.getStringExtra("command");
String touch = intent.getStringExtra("touch");
if (Executor.isRootAvailable()) {
Executor executor = new Executor();
ArrayList<String> commands = new ArrayList<>();
if (command != null) {
if (command.length() > 0) {
if (commands.add("input " + command)) {
executor.execute(commands);
}
}
} else if (touch != null) {
if (CursorSystem.isAlive) { // Always true for the executions
CursorSystem.doInput();
if (CursorSystem.state == CursorSystem.STATE) { // Always true for the executions
int[] coords = CursorSystem.coordinates;
if (coords != null) {
// This line is where (I guess) that the problem lies.
// CursorSystem.command is "tap", coords[0] and coords[1] is the result of (a view).getLocationOnScreen(coordinates)
// It results in a 2 positions int array with (x, y) coordinates, these values are always correct.
if (commands.add("input " + CursorSystem.command + " " + coords[0] + " " + coords[1])) {
executor.execute(commands);
CursorSystem.doInput();
} else {
// error...
}
} else {
// error...
}
} else {
// error...
}
} else {
error...
}
} else {
error...
}
} else {
error...
}
}
The Executor.execute:
public final boolean execute(ArrayList<String> commands) {
boolean resp = false;
try {
if (commands != null && commands.size() > 0) {
Process suProcess = Runtime.getRuntime().exec("su");
DataOutputStream dataOutputStream = new DataOutputStream(suProcess.getOutputStream());
for (String currCommand : commands) {
dataOutputStream.writeBytes(currCommand);
dataOutputStream.writeBytes("\n");
dataOutputStream.flush();
}
dataOutputStream.writeBytes("exit\n");
dataOutputStream.flush();
try {
int suProcessRetval = suProcess.waitFor();
return (suProcessRetval != 255); // Always yields 0
} catch (Exception ex) {
// errors...
}
} else {
// error...
}
} catch (IOException ex) {
Log.w(TAG, "IOException: ", ex);
} catch (SecurityException ex) {
Log.w(TAG, "SecurityException: ", ex);
} catch (Exception ex) {
Log.w(TAG, "Generic Exception: ", ex);
}
return resp;
}
Executor.execute
, you returnresp
which will always be false since you're not changing it anywhere. Is it how it's supposed to be? – LongshoremanCursorSystem
class is and format thevalue
line if it can be? I'm guessingCursorSystem
is your own class. It will be helpful to see its complete code. – Longshoremanreturn (suProcessRetval != 255);
that evaluates to true... Also,CursorSystem
class has over two thousand lines of code. The main variables used are always set (never null at least),CursorSystem.isAlive
is aboolean
always debugged astrue
, most of other codes shown are actually different, and have been simplified for the question... At the same time, no LogCat errors appear, noException
s are thrown, no failures.... and no response. – Centrovalue
line. Could you please explain it more and also could you confirm that it is an output? – LongshoremanCursorSystem
is aService
that keeps on running. theisAlive
(boolean) is a flag to indicate that the Service is executing correctly.doInput()
is a Static function that executes the currently present task inCursorSystem
, its triggered in several different areas of the application, but does not alter anything outside of CursorSystem.dataOutputStream
is never (during debugging sessions) null.... Finally, on theexecutor.execute
, its argument is an ArrayList of Strings. The Strings inside are always equivalent (meaning String (from run 0) equals String (from run 1)).... – CentroFile
). Finally its also worth noticing that the issue has been bypassed. Still, I want to know what could have happened that caused such a bug/issue. I personally believe it to be some "Guard" system that blocks commands, even in rooted devices. Or indirectwindows
used – Centrovalue = {char[26]@830031306976} 0 = 'i' 105 1 = 'n' 110 2 = 'p' 112 3 = 'u' 117 4 = 't' 116 5 = ' ' 32 6 = 't' 116 7 = 'a' 97 8 = 'p' 112 9 = ' ' 32 10 = '2' 50 11 = '7' 55 12 = '5' 53 13 = ' ' 32 14 = '4' 52 15 = '1' 49 16 = '0' 48 17 = '\u0000' 0 18 = '\u0000' 0 19 = '\u0000' 0 20 = '\u0000' 0 21 = '\u0000' 0 22 = '\u0000' 0 23 = '\u0000' 0 24 = '\u0000' 0 25 = '\u0000' 0
– Longshoremanvalue
is the debug position of thecommands
argument in theExecutor.execute
function. An ArrayList of Strings, with size 1, a String (Array of Char), with contents, 0....25 (default String allocation in that enviroment)...... While I understand that watching the code shown is likely to show some failure, I have some knowledge on what I am doing, and can pretty much tell that the issue is not inside my code, but rather in some indirect situation, or indirect activaton of Java Objects, that is blocking the processing somehow. While I studied this, some scenarios have been dropped – Centroreturn
s involved in the application. The onReceiver would merely "stack" more commands on the Executor. Also, theCursorSystem
is a Service, that is running correctly. I can tell that due to this "problem" some code has been changed, and the issue is no longer reproducible. I can however state that this Receiver and the Services involved did not change. – CentroExecutor
could send single commands, as well as batch commands, the argument is an ArrayList. I have directly sent String to that class, in order to test it. It works as expected. – Centro