Introducing XDA:DevCon – A Conference For Developers By Developers
XDA Developers Android and Mobile Development Forum
Forgot your password?
 
Post Reply+
Tip us?
 
Chainfire
Old
(Last edited by Chainfire; 23rd January 2013 at 01:32 PM.)
#1  
Chainfire's Avatar
Senior Moderator / Elite Recognized Developer - OP
Thanks Meter 31857
Posts: 8,032
Join Date: Oct 2007

 
DONATE TO ME
Default [2013.01.23][DEV GUIDE] How-To SU

Guidelines for problem-free su usage

How-To SU is my guide on using "su" in your own programs (to execute commands as root). The guide covers the major common pitfalls and also provides example code, as I have been asked by several developers to provide.

I also did a presentation on this stuff at the Big Android BBQ 2012, so if you're looking for the article and code promised there, here it is!

The text is too long to copy here, but you can find it here:

http://su.chainfire.eu/

Example code is located on GitHub:

https://github.com/Chainfire/libsuperuser

If you are not an app developer, you have no business posting in this thread. This thread is for developer discussion on the article/example code only. In fact, I do not expect many posts in this thread at all - it's all rather straightforward, and this is not a helpdesk.

Moderators: Do not move this thread to a development subsection, 0-posters need to be able to reply to it.
BLOG - G+(Chainfire) - G+(Personal) - TWITTER - IRC - DONATE

Android
HTC G1, Hero
Samsung i5800, i9000*2, P1000*2, P7100, i9100*2, N7000, P6800, i9300, N7100, i9505
Sony T LT30p, Z C6603
Nexus Galaxy*2, N7, N10

SuperSU, Mobile ODIN, TriangleAway, DSLR Controller, CF-Root, USB Host Diagnostics, ExynosAbuseAPK, Live dmesg+logcat, NoMoarPowah!, CF-Bench, Chainfire3D, CF.lumen, SGS2 SIM Unlocker, GingerBreakAPK, SuperPower, and more!

Windows Mobile 5/6
E-Mobile EM-ONE
HTC Wizard*2, Kaiser, Touch, Diamond, Pro, HD*2, Diamond 2, Pro 2*2, HD2*2
Samsung i780, i900*2, i8000*2, b7300, b7320, b7330, b7620*2, b6520

WMWifiRouter, KaiserTweak, FPUEnabler, WMLongLife, WMRegOptimizer, CFC+GUI, TF3D+v2 ports, Kaiser+Omnia2+Snapdragon 3D drivers, GfxBoost, and more!

Windows Phone 7
LG GW910

NOTICE: I do not respond to tech support questions through PM.
The Following 42 Users Say Thank You to Chainfire For This Useful Post: [ Click to Expand ]
 
franciscofranco
Old
#2  
franciscofranco's Avatar
Recognized Developer
Thanks Meter 45117
Posts: 10,389
Join Date: Dec 2010
Location: Mountain View, CA

 
DONATE TO ME
Awesome job man, I definitely learned some new stuff. I've done a little bit differently than your implementation: instead of doing AsyncTask -> run su code inside I did this in my Root class:

Code:
class BackgroundThread extends AsyncTask<String, Void, Void> {
		private String s;
		public BackgroundThread(String command) {
			s = command;
		}
		@Override
		protected Void doInBackground(String... command) {
			Process process = null;
			DataOutputStream os = null;
			try {
				process = Runtime.getRuntime().exec("su");
				os = new DataOutputStream(process.getOutputStream());
				os.writeBytes(s+"\n");
				os.writeBytes("exit\n");
				os.flush();
				process.waitFor();
			} catch (Exception e) {
			}
			finally {
				try {
					if (os != null)
						os.close();
					else
						process.destroy();
				} catch (Exception e) {

				}
			}
			return null;
		}
	}
And then receive the command in the parameter:

Code:
public void run(String command) {
		new BackgroundThread(command).doInBackground();
	}
Is this acceptable from your point of view?
franco.Kernel - Galaxy Nexus
franco.Kernel - Nexus 4
franco.Kernel - Nexus 7
franco.Kernel - Nexus 10


Google+ | Twitter | Portfolio

CruzerLite franco.Kernel case for the Nexus 4
CruzerLite franco.Kernel case for the Galaxy Nexus

You don't like my reply? Read this

However, if you put any trust in Quadrant scores you could use them to prove that dancing naked for 5 minutes in your garden affects device performance. By Chainfire
The Following 2 Users Say Thank You to franciscofranco For This Useful Post: [ Click to Expand ]
 
Chainfire
Old
#3  
Chainfire's Avatar
Senior Moderator / Elite Recognized Developer - OP
Thanks Meter 31857
Posts: 8,032
Join Date: Oct 2007

 
DONATE TO ME
No it isn't acceptable, but the reason is not what you might think.

Using a generic AsyncTask derived class to run su calls can be a solution. As long as your code ends up running in the background, all is good. However, in my experience what usually happens is that you have to do a lot of things in the background.

For example, imagine that during your app's startup, you need to check some files, perform some su calls, check some more files, do some computations, etc. Those should all go in a single AsyncTask's doInBackground method. That way you can use onPreExecute and onPostExecute to show and dismiss a dialog that tells the user you are busy.

Furthermore, if you had 10 su commands to run, would you just call new BackgroundThread ... 10 times? As the call should return before the su command is finished executing, the order of the executions of those commands becomes semi-random, you can't depend on them being run in any specific order, it even differs between Android versions (some versions run AsyncTasks serially, others run X of them in parallel). Not to mention that you shouldn't create 10 separate su processes to run 10 commands unless you have a good reason. Batching commands together == much higher performance.

The above does depend on which commands you need to execute, the needs of your application, and how you use it. If you only have to execute a single su command, it can be done that way, but I think in general this is not an ideal solution.

Now, the reason why your solution is truly unacceptable is because you are calling doInBackground. This does not make the code run in the background. You override doInBackground and insert your code, but you call the execute method. You should call your code like this:

Code:
new BackgroundThread(command).execute();
Else you're still calling on the main thread !

If you really want to keep using this method, keep in mind that you can actually pass parameters to the execute() function that in turn will be passed to doInBackground. Look in the AsyncTask documentation ...
BLOG - G+(Chainfire) - G+(Personal) - TWITTER - IRC - DONATE

Android
HTC G1, Hero
Samsung i5800, i9000*2, P1000*2, P7100, i9100*2, N7000, P6800, i9300, N7100, i9505
Sony T LT30p, Z C6603
Nexus Galaxy*2, N7, N10

SuperSU, Mobile ODIN, TriangleAway, DSLR Controller, CF-Root, USB Host Diagnostics, ExynosAbuseAPK, Live dmesg+logcat, NoMoarPowah!, CF-Bench, Chainfire3D, CF.lumen, SGS2 SIM Unlocker, GingerBreakAPK, SuperPower, and more!

Windows Mobile 5/6
E-Mobile EM-ONE
HTC Wizard*2, Kaiser, Touch, Diamond, Pro, HD*2, Diamond 2, Pro 2*2, HD2*2
Samsung i780, i900*2, i8000*2, b7300, b7320, b7330, b7620*2, b6520

WMWifiRouter, KaiserTweak, FPUEnabler, WMLongLife, WMRegOptimizer, CFC+GUI, TF3D+v2 ports, Kaiser+Omnia2+Snapdragon 3D drivers, GfxBoost, and more!

Windows Phone 7
LG GW910

NOTICE: I do not respond to tech support questions through PM.
The Following 4 Users Say Thank You to Chainfire For This Useful Post: [ Click to Expand ]
 
meethere
Old
#4  
meethere's Avatar
Senior Member
Thanks Meter 82
Posts: 590
Join Date: Jan 2012
that's a nice read
thanks for the guide
am nooB, with lots of Pardon me.

Get exposure, submit your biz to business web directory
Latest Tech updates
 
franciscofranco
Old
(Last edited by franciscofranco; 7th November 2012 at 03:26 PM.)
#5  
franciscofranco's Avatar
Recognized Developer
Thanks Meter 45117
Posts: 10,389
Join Date: Dec 2010
Location: Mountain View, CA

 
DONATE TO ME
Quote:
Originally Posted by Chainfire View Post
No it isn't acceptable, but the reason is not what you might think.

Using a generic AsyncTask derived class to run su calls can be a solution. As long as your code ends up running in the background, all is good. However, in my experience what usually happens is that you have to do a lot of things in the background.

For example, imagine that during your app's startup, you need to check some files, perform some su calls, check some more files, do some computations, etc. Those should all go in a single AsyncTask's doInBackground method. That way you can use onPreExecute and onPostExecute to show and dismiss a dialog that tells the user you are busy.

Furthermore, if you had 10 su commands to run, would you just call new BackgroundThread ... 10 times? As the call should return before the su command is finished executing, the order of the executions of those commands becomes semi-random, you can't depend on them being run in any specific order, it even differs between Android versions (some versions run AsyncTasks serially, others run X of them in parallel). Not to mention that you shouldn't create 10 separate su processes to run 10 commands unless you have a good reason. Batching commands together == much higher performance.

The above does depend on which commands you need to execute, the needs of your application, and how you use it. If you only have to execute a single su command, it can be done that way, but I think in general this is not an ideal solution.

Now, the reason why your solution is truly unacceptable is because you are calling doInBackground. This does not make the code run in the background. You override doInBackground and insert your code, but you call the execute method. You should call your code like this:

Code:
new BackgroundThread(command).execute();
Else you're still calling on the main thread !

If you really want to keep using this method, keep in mind that you can actually pass parameters to the execute() function that in turn will be passed to doInBackground. Look in the AsyncTask documentation ...
Hmm... I thought calling new BackgroundThread(command).doInBackground(); was doing it in the background thread... if I call new BackgroundThread(command).execute; the commands won't be called at all until I close the application/activity.

I don't do X new calls, for example in the BootService I just batch commands together and execute it once.

I'll use your code and see how it works.
franco.Kernel - Galaxy Nexus
franco.Kernel - Nexus 4
franco.Kernel - Nexus 7
franco.Kernel - Nexus 10


Google+ | Twitter | Portfolio

CruzerLite franco.Kernel case for the Nexus 4
CruzerLite franco.Kernel case for the Galaxy Nexus

You don't like my reply? Read this

However, if you put any trust in Quadrant scores you could use them to prove that dancing naked for 5 minutes in your garden affects device performance. By Chainfire
 
pedja1
Old
#6  
pedja1's Avatar
Recognized Developer
Thanks Meter 1287
Posts: 1,113
Join Date: Oct 2011
Location: Zrenjanin

 
DONATE TO ME
Very nice reading. I always use AsyncTask for su commands, although I learned it the hard way
I remember few months back I couldn't figure out why supersu pops up when timeout is at 2-3 seconds

Sent from my HTC EVO 3D X515m using Tapatalk 2
Device: HTC Evo 3D GSM Hboot:Revolutionary S-OFF ROM:CM 10.1 Recovery: 4ext



Kernel Tuner - Take ctrl over your device

Kernel Tuner - Official Website



If you want to help, feel free to donate.
 
AdamOutler
Old
#7  
AdamOutler's Avatar
Elite Recognized Developer
Thanks Meter 8031
Posts: 4,745
Join Date: Feb 2011
Location: Louisiana

 
DONATE TO ME
I generally work with desktop apps. Is there a reason to not use Runnable?

Code:
public void liveBackgroundShellCommand() {


        Runnable r = new Runnable() {

            public void run() {
                boolean LinkLaunched = false;
                try {
                    String[] params = (String[]) Statics.LiveSendCommand.toArray(new String[0]);
                    Process process = new ProcessBuilder(params).start();
                    BufferedReader STDOUT = new BufferedReader(new InputStreamReader(process.getInputStream()));
                    BufferedReader STDERR = new BufferedReader(new InputStreamReader(process.getErrorStream()));
This is how I set up a background shell. Then I just pass in the su -c command. Is there a disadvantage to this?
I ignore PMs with questions that could be answered by searching. If you PM me, I probly won't respond.
Check out my developer pages. Add me to your circles on Google Plus.
 
Chainfire
Old
#8  
Chainfire's Avatar
Senior Moderator / Elite Recognized Developer - OP
Thanks Meter 31857
Posts: 8,032
Join Date: Oct 2007

 
DONATE TO ME
Quote:
Originally Posted by AdamOutler View Post
I generally work with desktop apps. Is there a reason to not use Runnable?

Code:
public void liveBackgroundShellCommand() {


        Runnable r = new Runnable() {

            public void run() {
                boolean LinkLaunched = false;
                try {
                    String[] params = (String[]) Statics.LiveSendCommand.toArray(new String[0]);
                    Process process = new ProcessBuilder(params).start();
                    BufferedReader STDOUT = new BufferedReader(new InputStreamReader(process.getInputStream()));
                    BufferedReader STDERR = new BufferedReader(new InputStreamReader(process.getErrorStream()));
This is how I set up a background shell. Then I just pass in the su -c command. Is there a disadvantage to this?
If this is about desktop Java, then I don't know. I don't use desktop Java, but in most languages and frameworks it is generally frowning upon to block the UI thread, and the UI thread is usually the main/default/first thread.

If we're talking about Android, then this may be bad, depending on what you are doing. A Runnable by itself says nothing about threading or being in the background, a Runnable is just a generic way to define some code you want to run somewhere, sometime.

The code you pasted here does start the process, but it does not wait for the process to exit or read/write to the streams. As such, this piece of code does not block, and is fine. 9 out of 10 times however, a piece of code like this is going to be followed by something like process.waitFor() or reading from STDOUT/STDERR in which cases it does block, and is thus holding up your UI thread and thus bad.

Furthermore, as detailed in the article, calling "su -c" can be errorprone.
BLOG - G+(Chainfire) - G+(Personal) - TWITTER - IRC - DONATE

Android
HTC G1, Hero
Samsung i5800, i9000*2, P1000*2, P7100, i9100*2, N7000, P6800, i9300, N7100, i9505
Sony T LT30p, Z C6603
Nexus Galaxy*2, N7, N10

SuperSU, Mobile ODIN, TriangleAway, DSLR Controller, CF-Root, USB Host Diagnostics, ExynosAbuseAPK, Live dmesg+logcat, NoMoarPowah!, CF-Bench, Chainfire3D, CF.lumen, SGS2 SIM Unlocker, GingerBreakAPK, SuperPower, and more!

Windows Mobile 5/6
E-Mobile EM-ONE
HTC Wizard*2, Kaiser, Touch, Diamond, Pro, HD*2, Diamond 2, Pro 2*2, HD2*2
Samsung i780, i900*2, i8000*2, b7300, b7320, b7330, b7620*2, b6520

WMWifiRouter, KaiserTweak, FPUEnabler, WMLongLife, WMRegOptimizer, CFC+GUI, TF3D+v2 ports, Kaiser+Omnia2+Snapdragon 3D drivers, GfxBoost, and more!

Windows Phone 7
LG GW910

NOTICE: I do not respond to tech support questions through PM.
The Following User Says Thank You to Chainfire For This Useful Post: [ Click to Expand ]
 
AdamOutler
Old
#9  
AdamOutler's Avatar
Elite Recognized Developer
Thanks Meter 8031
Posts: 4,745
Join Date: Feb 2011
Location: Louisiana

 
DONATE TO ME
Right. I generally launch in a Thread T=new Thread(..). I'be never used AsyncTask. I'm just wondering what its all about.
I ignore PMs with questions that could be answered by searching. If you PM me, I probly won't respond.
Check out my developer pages. Add me to your circles on Google Plus.
 
Chainfire
Old
#10  
Chainfire's Avatar
Senior Moderator / Elite Recognized Developer - OP
Thanks Meter 31857
Posts: 8,032
Join Date: Oct 2007

 
DONATE TO ME
Quote:
Originally Posted by AdamOutler View Post
Right. I generally launch in a Thread T=new Thread(..). I'be never used AsyncTask. I'm just wondering what its all about.
Ok, yeah that's fine. AsyncTask is pretty much a Thread wrapper with handy utility functions (onPreExecute, onPostExecute, onProgressUpdate) that is specifically aimed at running a short-lived task away from the UI thread, often with UI feedback (it's brilliant for use with progress dialogs, for example).
BLOG - G+(Chainfire) - G+(Personal) - TWITTER - IRC - DONATE

Android
HTC G1, Hero
Samsung i5800, i9000*2, P1000*2, P7100, i9100*2, N7000, P6800, i9300, N7100, i9505
Sony T LT30p, Z C6603
Nexus Galaxy*2, N7, N10

SuperSU, Mobile ODIN, TriangleAway, DSLR Controller, CF-Root, USB Host Diagnostics, ExynosAbuseAPK, Live dmesg+logcat, NoMoarPowah!, CF-Bench, Chainfire3D, CF.lumen, SGS2 SIM Unlocker, GingerBreakAPK, SuperPower, and more!

Windows Mobile 5/6
E-Mobile EM-ONE
HTC Wizard*2, Kaiser, Touch, Diamond, Pro, HD*2, Diamond 2, Pro 2*2, HD2*2
Samsung i780, i900*2, i8000*2, b7300, b7320, b7330, b7620*2, b6520

WMWifiRouter, KaiserTweak, FPUEnabler, WMLongLife, WMRegOptimizer, CFC+GUI, TF3D+v2 ports, Kaiser+Omnia2+Snapdragon 3D drivers, GfxBoost, and more!

Windows Phone 7
LG GW910

NOTICE: I do not respond to tech support questions through PM.

The Following 2 Users Say Thank You to Chainfire For This Useful Post: [ Click to Expand ]
 
Post Reply+
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Go to top of page...