Android应用程序获得root权限 && 基于NVidia平台Android应用修改cpu频率

来源:互联网 发布:js confirm返回值 编辑:程序博客网 时间:2024/05/20 19:19

http://blog.csdn.net/liushaogeng/article/details/6614416

问题和目标
      有时候希望在java应用程序中来使用root权限,如修改/system权限,亦或者如题。
思路和原理
      这里介绍2种我已经实现的方法,但是建议使用第2种,因为第2种适用于android各个版本,第一种仅适用android2.2及以下版本。
1,使用android提供的api来获取root权限,并完成自己想要的root权限的操作;
2,在init.rc中增加一个service,来帮助Android应用程序执行root权限的命令
实现步骤和例子
第一种思路因为直接使用android的api来实现,直接看代码:

使用root权限的函数:
public static boolean runRootCommand(String command) {
        Process process = null;
        DataOutputStream os = null;
        try {
            process = Runtime.getRuntime().exec("/system/xbin/su");
            os = new DataOutputStream(process.getOutputStream());
            
            os.writeBytes(command+"\n");
            Log.v(TAG, "execute " + command);
            os.writeBytes("exit\n");
            Log.v(TAG, "execute exit");
            os.flush();
            process.waitFor();
            int iret = process.exitValue();
        } catch (Exception e) {
            Log.d("*** DEBUG ***", "Unexpected error - Here is what I know: "+e.getMessage());
            return false;
        }finally {
            try {
                if (os != null) {
                   os.close();
                }
                process.destroy();
            } catch (Exception e) {
                    // nothing
            }
        }
        return true;
    }
main()函数中,执行如下:
if(runRootCommand("mkdir /data/aaa") == true)
            Log.v(TAG, "ls Sucess");
        else
            Log.v(TAG, "ls failure");
以上2步即可,但是这个方法局限与需要rooted的系统才可以,所以虽然步骤简单,但有局限性;
       第二种思路的实现步骤:
这里以nvidia平台下版本的android修改cpu频率为例,
1,首先定义一个执行修改cpu频率的脚本,我把它位于/vendor/compal/文件名为set_max_cpu.sh和set_min_cpu.sh,分别定义如下:
#!/system/bin/sh
busybox echo `getprop sys.cpufre` > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq

#!/system/bin/sh
busybox echo `getprop sys.cpufre` > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq
,同时加上可执行权限,chmod 744 /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq
2,在system/core/rootdir/init.rc中加入2个Service定义,定义如下:
service set_max_cpu /system/bin/set_max_cpu.sh
    user root
    group root
    disabled
    oneshot  
      
service set_min_cpu /system/bin/set_min_cpu.sh
    user root
    group root
    disabled
    oneshot
3,修改device/nvidia/ventana文件中 PRODUCT_COPY_FILES值,使编译时,可将脚本放入系统目录system/bin中,
    vendor/compal/set_max_cpu.sh:/system/bin/set_max_cpu.sh \
    vendor/compal/set_min_cpu.sh:/system/bin/set_min_cpu.sh
以上3步完成后需要来重新编译自己的android源码,来生成system.img 和boot.img,重新烧写img到开发板上。对于eng版本的img其实可以增加/system/bin下的脚本,但是它的拥有者无法改到shell用户下,这样当执行 setprop ctl.startset_min_cpu时,服务无法开启;
4,让自己的应用程序获得system权限,在AndroidManifest.xml中修改
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.setFrequenceFps"
      android:versionCode="1" android:sharedUserId="android.uid.system"
      android:versionName="1.0">
5,在自己应用程序中设置System系统属性“ctl.start”为“mount_nfs”,这样Android系统将会帮我们运行mount_nfs系统属性了。这里需要强调的是不能够调用System.getProperty,这个函数只是修改JVM中的系统属性。而不能修改Android的系统属性。可以调用 android.os.SystemProperties(Android 2.1 Eclair系统可以调用这个API),如果你的Android版本不能调用这个类,只能通过JNI,调用C/C++层的API property_get和property_set函数了。java代码如下:

    SystemProperties.set(“sys.cpufre”, "1000000");         
    SystemProperties.set("ctl.start", set_max_cpu);
    //服务之间需要间隔时间,否则第二个服务不能正常开启
    try {
                        Thread.sleep(mDelayMs);
                        } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                        }
    SystemProperties.set("ctl.start", set_min_cpu);
6,在自己应用程序中,读取“init.svc.set_max_cpu”和 “init.svc.set_min_cpu”Android系统Property,检查执行结果。    
代码如下:
 while(true)
 {
    mount_rt = SystemProperties.get("init.svc.set_max_cpu", "");
    if(mount_rt != null && mount_rt.equals("stopped"))
    {
        return true;
     }
   try
    {
        Thread.sleep(1000);
   }catch(Exception ex){
    Log.e(TAG, "Exception: " + ex.getMessage());
   }
 }
 init进程维护一个service的队列,所以我们需要轮训来查询service的执行结果。
 总结
 通过上文可以看出,在Android获得root权限还是需要一些前提的,比如:

 1、必须是Android系统开发人员,否则你无法修改init.rc等文件,需要重新编译生成img文件。

2、你的应用程序必须要获得system权限。

参考:http://my.unix-center.net/~Simon_fu/?p=951