@@ -6,6 +6,7 @@ Run Java (and Kotlin) code as root!
66- Access to all the classes in your projects
77- Access to Android classes
88- Easy Binder-based IPC/RPC
9+ - Debugging support
910
1011## License
1112
@@ -69,14 +70,6 @@ While this library was originally built to support Android 4.2+ devices,
6970it only officially supports 5.0+. The first public GitHub release was
7071tested specifically on 5.0, 7.0, 8.0, and 9.0.
7172
72- ## Debugging
73-
74- Debugging the code running as root is currently not supported. I made
75- some headway getting the jdwp server running, but I've not been able
76- to successfully connect jdb or AndroidStudio to it. If you want to take
77- a stab at it, there are some comments in
78- ``` RootJava.getLaunchString() ``` related to it.
79-
8073## Recommended reading
8174
8275I strongly recommend you read the library's source code in its entirety
@@ -270,6 +263,84 @@ non-root code.
270263(See the [ example project] ( ../librootjava_example ) for a more elaborate
271264example for this entire process)
272265
266+ #### Debugging
267+
268+ Debugging is supported since version 1.1.0, but disabled by default.
269+
270+ To enable debugging, first we must tell the non-root process to launch
271+ our root process with debug support enabled. We do this by calling
272+ ``` Debugger.setEnabled() ``` * before* calling
273+ ``` RootJava.getLaunchScript() ``` :
274+
275+ ```
276+ public class MyActivity {
277+ // ...
278+ private void launchRootProcess() {
279+ // ...
280+
281+ Debugger.setEnabled(BuildConfig.DEBUG);
282+ rootShell.addCommand(RootJava.getLaunchScript(this, RootMain.class, null, null, null, BuildConfig.APPLICATION_ID + ":root"));
283+ }
284+ }
285+ ```
286+
287+ We use ``` BuildConfig.DEBUG ``` instead of ``` true ``` to prevent
288+ potential issues with release builds.
289+
290+ In the code running as root, we then call ``` Debugger.waitFor() ```
291+ to pause execution (of the current thread) until a debugger is connected:
292+
293+ ```
294+ public class RootMain {
295+ public static void main(String[] args) {
296+ RootJava.restoreOriginalLdLibraryPath(); // call this first!
297+
298+ if (BuildConfig.DEBUG) {
299+ Debugger.waitFor(true); // wait for connection
300+ }
301+
302+ setYourBreakpointHere();
303+ }
304+ }
305+ ```
306+
307+ We wrap the call inside a ``` BuildConfig.DEBUG ``` check, again to prevent
308+ issues with release builds.
309+
310+ Note that for long-running processes (such as daemons) you may not want
311+ to explicitly wait for a debugger connection, in that case you can use
312+ the ``` Debugger.setName() ``` method instead. That method may also be
313+ called * before* ``` Debugger.waitFor() ``` to customize the debugger
314+ display name, as by default the process name is used.
315+
316+ Now that debugging is enabled, we still need to actually connect to
317+ the process. You can do this in Android Studio via the * Attach
318+ debugger to Android process* option in the * Run* menu. Once the root
319+ process is running, it will be listed in the popup window.
320+
321+ Note that you can debug * both* the non-root * and* root process at the
322+ same time. While Android Studio can only debug a single application
323+ * launched* in debug mode, you can * attach* to multiple processes. So
324+ you can simply run your application in debug mode, have it launch the
325+ root process, then * attach* to that root process, and debug both
326+ simultaneously.
327+
328+ Android Studio of course has no knowledge of the relation between the
329+ multiple processes being debugged, so stepping into an IPC call in one
330+ process will not automatically break on the implementation code in the
331+ other process. You will have to set those breakpoints manually.
332+
333+ #### BuildConfig
334+
335+ The example snippets and projects make extensive use of the BuildConfig
336+ class. This class is generated during the build process for every
337+ module, library, etc. Double check you are importing the correct
338+ BuildConfig class, the one from your application's package (unless you
339+ know exactly what you're doing). Note that this complicates putting this
340+ code inside libraries and modules, as you cannot reference the
341+ application's BuildConfig class from a library. Work-arounds are beyond
342+ the scope of this README.
343+
273344#### Daemonizing
274345
275346For some use-cases you may want to run your root process as a daemon,
@@ -348,7 +419,7 @@ an Android 10 preview comes out!
348419## Gradle
349420
350421```
351- implementation 'eu.chainfire:librootjava:1.0 .0'
422+ implementation 'eu.chainfire:librootjava:1.1 .0'
352423```
353424
354425## Notes
0 commit comments