最近RK3326项目上遇到个问题,OTA升级完重启后需要去/cache/recovery目录下读取一个文件,last_flag,读取过程中报错,提示没有权限,很奇怪,我的明明是系统应用,也加了权限还是报错,所以写个脚本在读取文件之前先设置一下文件的权限,这样就能读取到文件里面的内容。
首先建立一个脚本 rp_update_file.sh ,内容很简单,就是修改下文件权限如下
#!/system/bin/sh
su
chmod 777 /cache/recovery/last_flag
文件放在device/rockchip/rk3326目录下,然后在init.rk3326.rc中添加一个服务,
#for rp file update
service rp_update_file /system/bin/sh /system/etc/rp_update_file.sh
class main
user root
group root
disabled
oneshot
seclabel u:r:shell:s0
再增加一个变量来控制这个服务
on property:persist.rpfileupdate.enable=1
start rp_update_file
on property:persist.rpfileupdate.enable=0
stop rp_update_file
设置一个property,当persist.rpfileupdate.enable=1 时就会去执行这个脚本。
当然还需要给这个脚本添加权限,在system/core/libcutilsfs_config.cpp 目录中增加
diff --git a/core/libcutils/fs_config.cpp b/core/libcutils/fs_config.cpp
old mode 100644
new mode 100755
index cc96ff8..9399694
--- a/core/libcutils/fs_config.cpp
+++ b/core/libcutils/fs_config.cpp
@@ -162,6 +162,8 @@ static const struct fs_path_config android_files[] = {
{ 00600, AID_ROOT, AID_ROOT, 0, "vendor/default.prop" },
{ 00444, AID_ROOT, AID_ROOT, 0, ven_conf_dir + 1 },
{ 00444, AID_ROOT, AID_ROOT, 0, ven_conf_file + 1 },
+
+ { 00755, AID_ROOT, AID_ROOT, 0, "system/etc/rp_update_file.sh" },
// the following two files are INTENTIONALLY set-uid, but they
// are NOT included on user builds.
OK这样脚本就加好了,然后在android代码中读取文件之前设置一下property,代码如下
package com.rp.rpreceiver;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
import android.os.RecoverySystem;
import android.os.storage.StorageManager;
import android.provider.Settings;
import android.util.Log;
import android.view.WindowManager;
import android.widget.Toast;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.GeneralSecurityException;
import java.util.List;
public class UsbReceiver extends BroadcastReceiver {
private static Boolean isBootComplete = false;
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
private static File RECOVERY_DIR = new File("/cache/recovery");
private static File UPDATE_FLAG_FILE = new File(RECOVERY_DIR, "last_flag");
private final String SUCCESS="success";
private final String FAILED="fail";
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.i("gyx", "UsbReceiver action=" + action);
Log.i("gyx","isBootComplete="+isBootComplete);
if (action.equals("android.intent.action.BOOT_COMPLETED")) {
setProperty("persist.rpfileupdate.enable","1");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
int start_ota_upgrade = Settings.System.getInt(context.getContentResolver(), "start_ota_upgrade", 0);
Log.i("gyx","start_ota_upgrade="+start_ota_upgrade);
String command = readFlagCommand();
if(start_ota_upgrade==1){
Settings.System.putInt(context.getContentResolver(),"start_ota_upgrade",0);
if(command!=null ){
if (command.startsWith("success")) {
Log.i("gyx","update success");
} else if (command.startsWith("updating")) {
Log.i("gyx","update failed");
}
}else {
Log.i("gyx","command =null update failed");
}
}
setProperty("persist.rpfileupdate.enable","0");
isBootComplete = true;
}else if (action.equals("android.intent.action.MEDIA_MOUNTED") && isBootComplete) {
String sdCardPath = getSdCardPath(context);
String path = FindFileOnUSB("update.zip");
if (path.equals("")) {
Log.i("gyx","update.zip not found");
} else {
Log.i("gyx","update system");
systemUpdate(context, sdCardPath + "/update.zip");
}
}
}
public static void setProperty(String key, String value) {
try {
Class> c = Class.forName("android.os.SystemProperties");
Method set = c.getMethod("set", String.class, String.class);
set.invoke(c, key, value);
} catch (Exception e) {
e.printStackTrace();
}
}
public String getSdCardPath(Context context) {
int TYPE_PUBLIC = 0;
File file = null;
String path = null;
StorageManager mStorageManager = context.getSystemService(StorageManager.class);
Class> mVolumeInfo = null;
try {
mVolumeInfo = Class.forName("android.os.storage.VolumeInfo");
Method getVolumes = mStorageManager.getClass().getMethod(
"getVolumes");
Method volType = mVolumeInfo.getMethod("getType");
Method isMount = mVolumeInfo.getMethod("isMountedReadable");
Method getPath = mVolumeInfo.getMethod("getPath");
Field internalPath = mVolumeInfo.getDeclaredField("internalPath");
List
这样就大功告成了