ZNDS智能电视网 推荐当贝市场

TV应用下载 / 资源分享区

软件下载 | 游戏 | 讨论 | 电视计算器

综合交流 / 评测 / 活动区

交流区 | 测硬件 | 网站活动 | Z币中心

新手入门 / 进阶 / 社区互助

新手 | 你问我答 | 免费刷机救砖 | ROM固件

查看: 8684|回复: 2
上一主题 下一主题
[分享]

android版的车机怎么升级 Android 7.1车机系统在线升级教程

[复制链接]
跳转到指定楼层
楼主
发表于 2024-5-24 15:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式 | 来自河南
今天,就为大家带来Android 7.1车机系统的在线升级教程。想要轻松升级你的车机系统吗?只需将安装包下载至/data/目录,即可一键升级,让驾驶体验更流畅!

最近按项目要求,需要做一个车机Android在线升级操作,但是cache内存太小了,最后只能寄存希望在 data/文件夹下,但是data/目录在6.0之后禁止recovery读取data文件.最后的解决方案是在/data/文件下创建一个系统app能够操作的文件夹,进行升级操作.

1、升级流程

Android自带升级流程 API  RecoverySystem.java  (framework/base/core/java/android/os/RecoverySystem.java)

调用如下代码就可以进行升级操作,对你没看错,就是一句代码,将你下载好的压缩包路径传过去就行.

   private void excuteUpdateZip(String local_path) {
        // TODO Auto-generated method stub
        try {
            RecoverySystem.installPackage(this, new File(local_path));
            //RecoverySystem.installPackage(this, new File(local_path));
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

但是 事情永远是比想象的麻烦, 因为我们的车机要求的是将压缩包放到 /data/目录下. 那放就放吧  先编译好一个全包 使用命令

adb root
adb remount
adb push  updata.zip /data/

使用模拟升级命令进行升级操作

adb shell "echo --update_package=/data/update.zip > /cache/recovery/command"

adb shell sync

adb reboot recovery

就这样成功进行了升级,what?完成了? 这么简单,原来这才是跳坑的开始,看到生面测试成功了之后,迫不及待的在自己的程序中将路径填写成  /data/update.zip ,开始了升级操作,结果失败了.开始检查原因

是不是AndroidManifest.xml中没有添加 如下权限

android:sharedUserId="android.uid.system"

查看添加了,是不是没有对自己的apk进行系统签名?发现也签名了(如何给APK系统签名),没有放到system/app/文件夹下?也放了,.那原因出在哪里那?不想了,先去看看log

Android机器中 /cache/recovery/的目录结构如下:

cache/        
└── recovery      
    ├── last_install
    ├── last_kmsg  #系统升级的时候的全log. 如果有last_kmsg.1
                   #那last_kmsg 永远是最后一次升级的log,所以每
                   #次只查看last_kmsg就行
    ├── last_locale
    └── last_log   #升级过程中的简log,能看到为何升级失败

在log中查看到的是  --update_package=@/cache/recovery/block.map 看到这个结果的时候,第一感觉就是apk没有安装成功,于是加了log 发现加的log 成功打印,吓了一跳,自己撞见鬼了?

抱着程序员不明原因不放弃的心态,看了一下RecoverySystem.java 中的 installPackage 方法,原来是 installpackage在代码中做了限制, 要是设置的路径是以 /data/ 开头强制更改@/cache/recovery/block.map  

  @SystemApi
    public static void installPackage(Context context, File packageFile, boolean processed)
            throws IOException {
        //省略代码......
       if (filename.startsWith("/data/")) {
                if (processed) {
                   //省略代码......
                } else {
                //省略代码......
                }
                //TODO 重点就是这句话,将路径强制求改
                filename = "@/cache/recovery/block.map";
            }
            final String filenameArg = "--update_package=" + filename + "\n";
            final String localeArg = "--locale=" + Locale.getDefault().toString() + "\n";
            final String securityArg = "--security\n";
            String command = filenameArg + localeArg;
            //省略代码......
        }
    }

看到这,挡了我的路,必定铲除,将代码很愉快的注掉了,重新编译进行测试.

激动的等待中.........

又失败了?难道还有拦路虎? 我的心要崩溃了,为什么还是失败,还是查看log发现 --update_package=data/update.zip . 这么看来已经能写到重启文件中了.

查看log提示是  --update_package=data/update.zip  Permission Denied 看来是datarecover没有权限读取/data目录啊

快速验证 是不是selinux问题 可以修改 BoardConfig.mk 添加如下代码 编译boot文件测试,如下代码是禁用selinux代码

BOARD_KERNEL_CMDLINE += androidboot.selinux=permissive

2、具体的recovery修改

bootable/recovery/Android.mk 修改 文件
bootable/recovery/recovery.cpp  修改 文件
bootable/recovery/usb.h 新增文件
bootable/usb.cpp 新增文件

bootable/recovery/Android.mk

diff --git a/recovery/Android.mk b/recovery/Android.mk
--- a/recovery/Android.mk
+++ b/recovery/Android.mk
@@ -41,6 +41,7 @@
     verifier.cpp \
     wear_ui.cpp \
     wear_touch.cpp \
+    usb.cpp

LOCAL_MODULE := recovery

    bootable/recovery/recovery.cpp

diff --git a/recovery/recovery.cpp b/recovery/recovery.cpp
--- a/recovery/recovery.cpp
+++ b/recovery/recovery.cpp
@@ -68,6 +68,7 @@
#include "ui.h"
#include "unique_fd.h"
#include "screen_ui.h"
+#include "usb.h"

#include <stdio.h>
#include <memory.h>
@@ -1466,59 +1467,7 @@
     }
}

-static bool is_battery_ok() {
-    struct healthd_config healthd_config = {
-            .batteryStatusPath = android::String8(android::String8::kEmptyString),
-            .batteryHealthPath = android::String8(android::String8::kEmptyString),
-            .batteryPresentPath = android::String8(android::String8::kEmptyString),
-            .batteryCapacityPath = android::String8(android::String8::kEmptyString),
-            .batteryVoltagePath = android::String8(android::String8::kEmptyString),
-            .batteryTemperaturePath = android::String8(android::String8::kEmptyString),
-            .batteryTechnologyPath = android::String8(android::String8::kEmptyString),
-            .batteryCurrentNowPath = android::String8(android::String8::kEmptyString),
-            .batteryCurrentAvgPath = android::String8(android::String8::kEmptyString),
-            .batteryChargeCounterPath = android::String8(android::String8::kEmptyString),
-            .batteryFullChargePath = android::String8(android::String8::kEmptyString),
-            .batteryCycleCountPath = android::String8(android::String8::kEmptyString),
-            .energyCounter = NULL,
-            .boot_min_cap = 0,
-            .screen_on = NULL
-    };
-    healthd_board_init(&healthd_config);

-    android::BatteryMonitor monitor;
-    monitor.init(&healthd_config);
-
-    int wait_second = 0;
-    while (true) {
-        int charge_status = monitor.getChargeStatus();
-        // Treat unknown status as charged.
-        bool charged = (charge_status != android::BATTERY_STATUS_DISCHARGING &&
-                        charge_status != android::BATTERY_STATUS_NOT_CHARGING);
-        android::BatteryProperty capacity;
-        android::status_t status = monitor.getProperty(android::BATTERY_PROP_CAPACITY, &capacity);
-        ui_print("charge_status %d, charged %d, status %d, capacity %lld\n", charge_status,
-                 charged, status, capacity.valueInt64);
-        // At startup, the battery drivers in devices like N5X/N6P take some time to load
-        // the battery profile. Before the load finishes, it reports value 50 as a fake
-        // capacity. BATTERY_READ_TIMEOUT_IN_SEC is set that the battery drivers are expected
-        // to finish loading the battery profile earlier than 10 seconds after kernel startup.
-        if (status == 0 && capacity.valueInt64 == 50) {
-            if (wait_second < BATTERY_READ_TIMEOUT_IN_SEC) {
-                sleep(1);
-                wait_second++;
-                continue;
-            }
-        }
-        // If we can't read battery percentage, it may be a device without battery. In this
-        // situation, use 100 as a fake battery percentage.
-        if (status != 0) {
-            capacity.valueInt64 = 100;
-        }
-        return (charged && capacity.valueInt64 >= BATTERY_WITH_CHARGER_OK_PERCENTAGE) ||
-                (!charged && capacity.valueInt64 >= BATTERY_OK_PERCENTAGE);
-    }
-}

static void set_retry_bootloader_message(int retry_count, int argc, char** argv) {
     bootloader_message boot = {};
@@ -1623,56 +1572,6 @@
     return __android_log_pmsg_file_write(logId, prio, name.c_str(), buf, len);
}

-
-static void setLine(int fd, int flags, int speed)
-{
-        struct termios t;
-        tcgetattr(fd, &t);
-        t.c_cflag = flags | CREAD | HUPCL | CLOCAL;
-        t.c_iflag = IGNBRK | IGNPAR;
-        t.c_oflag = 0;
-        t.c_lflag = 0;
-        t.c_cc[VMIN] = 1;
-        t.c_cc[VTIME] = 0;
-        cfsetispeed(&t, speed);
-        cfsetospeed(&t, speed);
-        tcsetattr(fd, TCSANOW, &t);
-}
-
-int tty_fd = -1;
-void *heartbeatfun(void __unused *argv)
-{
-    char boot[] = {0x80};
-    char heartbeat[] = {0x81};
-    char run[] = {0x95,0x01};
-
-    write(tty_fd, boot, sizeof(boot));
-        //usleep(100);
-//        write(tty_fd, heartbeat, sizeof(heartbeat));
-//        usleep(100);
-//        write(tty_fd, run, sizeof(run));
-    while(1)
-    {
-        write(tty_fd, heartbeat, sizeof(heartbeat));
-        usleep(500000);
-    }
-
-    return NULL;
-}
-
-void start_heartbeat_thread(void)
-{
-        pthread_t timerid;
-        int err = 0;
-
-        err = pthread_create(&timerid, NULL, heartbeatfun, NULL);
-        if (err) {
-                printf("can't creat heartbeatthread\n");
-        }
-}
-
-
-
int main(int argc, char **argv) {
     // Take last pmsg contents and rewrite it to the current pmsg session.
     static const char filter[] = "recovery/";
@@ -1700,30 +1599,6 @@

     time_t start = time(NULL);

-    tty_fd = open("/dev/ttyHSL1", O_RDWR, 0);
-        while(tty_fd < 0) {
-
-                fprintf(stdout,"open error=%d %s\n", errno, strerror(errno));
-                printf("deanji open ttyHSL1 failed \n");
-                tty_fd = open("/dev/ttyHSL1", O_RDWR, 0);
-                usleep(5000000);
-        }
-    fprintf(stdout, "update_package = 1  tty_fd=%d ...\n",tty_fd);
-      
-    if(tty_fd>0){
-       int ldisc = N_BHDLC;
-       int rc;
-       setLine(tty_fd, CS8, B115200);
-       rc = ioctl(tty_fd, TIOCSETD, &ldisc);
-        if(rc < 0) {
-                fprintf(stdout,"#####set line discipline error=%d %s\n",
-                       errno, strerror(errno));
-                return rc;
-        }
-       fcntl(tty_fd, F_SETFL, fcntl(tty_fd, F_GETFL) & ~O_NONBLOCK);
-       start_heartbeat_thread();
-    }
-
     // redirect_stdio should be called only in non-sideload mode. Otherwise
     // we may have two logger instances with different timestamps.
     redirect_stdio(TEMPORARY_LOG_FILE);
@@ -1852,24 +1727,33 @@
             else
                 printf("modified_path allocation failed\n");
         }
-        if (!strncmp("/sdcard", update_package, 7)) {
-            //If this is a UFS device lets mount the sdcard ourselves.Depending
-            //on if the device is UFS or EMMC based the path to the sdcard
-            //device changes so we cannot rely on the block dev path from
-            //recovery.fstab
-            if (is_ufs_dev()) {
-                    if(do_sdcard_mount_for_ufs() != 0) {
-                            status = INSTALL_ERROR;
-                            goto error;
-                    }
-                    if (ensure_path_mounted("/cache") != 0 || ensure_path_mounted("/tmp") != 0) {
-                            ui->Print("\nFailed to mount tmp/cache partition\n");
-                            status = INSTALL_ERROR;
-                            goto error;
-                    }
-                    mount_required = false;
-            } else {
-                    ui->Print("Update via sdcard on EMMC dev. Using path from fstab\n");
+        else if (strncmp(update_package, "usb:", 4) == 0) {
+                printf("recovery from udisk\n");
+                char *absolutePath = (char*)malloc(PATH_MAX);
+                memset(absolutePath, 0, PATH_MAX);
+                                
+                char ota_name[128] = {'\0'};
+                strcpy(ota_name, update_package+4);
+                printf("ota_name=%s\n",ota_name);
+                // wait 3s , make sure usb mounted
+                sleep(3);
+                if (!search_file_in_usb(ota_name, absolutePath)) {
+                    update_package = absolutePath;
+                    printf("find update.zip in usb success!\n");
+                } else {
+                    printf("find update.zip in usb failed!\n");
+            }
+        }
+        else if (!strncmp("/data", update_package, 5)) {
+                        if (ensure_path_mounted(DATA_ROOT) != 0) {
+                 ui->Print("\n-- Couldn't mount %s.\n", DATA_ROOT);
+                                 status = INSTALL_ERROR;
+                                 goto error;
+            }
+            if (ensure_path_mounted("/cache") != 0 || ensure_path_mounted("/tmp") != 0) {
+                ui->Print("\nFailed to mount tmp/cache partition\n");
+                status = INSTALL_ERROR;
+                goto error;
             }
         }
     }
@@ -1884,14 +1768,7 @@
         // to log the update attempt since update_package is non-NULL.
         modified_flash = true;

-        if (!is_battery_ok()) {
-            ui->Print("battery capacity is not enough for installing package, needed is %d%%\n",
-                      BATTERY_OK_PERCENTAGE);
-            // Log the error code to last_install when installation skips due to
-            // low battery.
-            log_failure_code(kLowBattery, update_package);
-            status = INSTALL_SKIPPED;
-        } else if (bootreason_in_blacklist()) {
+        if (bootreason_in_blacklist()) {
             // Skip update-on-reboot when bootreason is kernel_panic or similar
             ui->Print("bootreason is in the blacklist; skip OTA installation\n");
             log_failure_code(kBootreasonInBlacklist, update_package);
@@ -1933,42 +1810,21 @@
                 }
             }
         }
-    } else if (should_wipe_data) {
+    }  if (should_wipe_data) {
         if (!wipe_data(false, device)) {
             status = INSTALL_ERROR;
         }
-    } else if (should_wipe_cache) {
+    } if (should_wipe_cache) {
         if (!wipe_cache(false, device)) {
             status = INSTALL_ERROR;
         }
-    } else if (should_wipe_ab) {
+    }  if (should_wipe_ab) {
         if (!wipe_ab_device(wipe_package_size)) {
             status = INSTALL_ERROR;
         }
-    } else if (sideload) {
-        // 'adb reboot sideload' acts the same as user presses key combinations
-        // to enter the sideload mode. When 'sideload-auto-reboot' is used, text
-        // display will NOT be turned on by default. And it will reboot after
-        // sideload finishes even if there are errors. Unless one turns on the
-        // text display during the installation. This is to enable automated
-        // testing.
-        if (!sideload_auto_reboot) {
-            ui->ShowText(true);
-        }
-        status = apply_from_adb(ui, &should_wipe_cache, TEMPORARY_INSTALL_FILE);
-        if (status == INSTALL_SUCCESS) {
-            ota_completed = true;
-        }
-        if (status == INSTALL_SUCCESS && should_wipe_cache) {
-            if (!wipe_cache(false, device)) {
-                status = INSTALL_ERROR;
-            }
-        }
-        ui->Print("\nInstall from ADB complete (status: %d).\n", status);
-        if (sideload_auto_reboot) {
-            ui->Print("Rebooting automatically.\n");
-        }
-    } else if (!just_exit) {
+    }
+
+    if (!just_exit) {
         status = INSTALL_NONE;  // No command specified
         ui->SetBackground(RecoveryUI::NO_COMMAND);

@@ -1984,7 +1840,8 @@
         copy_logs();
         ui->SetBackground(RecoveryUI::ERROR);
     }
-
+   
+    /*
     Device::BuiltinAction after = shutdown_after ? Device::SHUTDOWN : Device::REBOOT;
     if ((status != INSTALL_SUCCESS && status != INSTALL_SKIPPED && !sideload_auto_reboot) ||
             ui->IsTextVisible()) {
@@ -1993,10 +1850,16 @@
             after = temp;
         }
     }
+    */

     // Save logs and clean up before rebooting or shutting down.
     finish_recovery(send_intent);

+    // no matter what result  reboot
+    sleep(1);
+    property_set(ANDROID_RB_PROPERTY, "reboot,");
+
+    /*
     switch (after) {
         case Device::SHUTDOWN:
             ui->Print("Shutting down...\n");
@@ -2016,6 +1879,7 @@
     while (true) {
       pause();
     }
+    */
     // Should be unreachable.
     return EXIT_SUCCESS;
}

    bootable/recovery/usb.h

diff --git a/recovery/usb.h b/recovery/usb.h
--- /dev/null
+++ b/recovery/usb.h
@@ -0,0 +1,21 @@
+#ifndef USB_H_
+#define USB_H_
+
+#include "common.h"
+
+//return 0 if exists
+int check_file_exists(const char *path);
+
+//return 0 if the usb mounted success
+int ensure_dev_mounted(const char *devPath, const char *mountedPoint);
+
+//return 0 if the usb unmounted success
+int ensure_dev_unmounted(const char *mountedPoint);
+
+//search file in usbs,return 0 if success, then save its absolute path arg2.
+int search_file_in_usb(const char *file, char *absolutePath);
+
+int in_usb_device(const char *file);
+
+#endif  // USB_H_
+

bootable/usb.cpp

diff --git a/recovery/usb.cpp b/recovery/usb.cpp
--- /dev/null
+++ b/recovery/usb.cpp
@@ -0,0 +1,165 @@
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <string>
+#include <android/log.h>
+#include <log/logger.h>
+#include <private/android_logger.h>
+
+#include "usb.h"
+
+#define MAX_DISK 4
+#define MAX_PARTITION 8
+#define PATH_MAX 256
+#define TIME_OUT 6000000
+
+static const char *USB_ROOT = "/usb/";
+struct timeval tpstart,tpend;
+float timeuse = 0;
+
+#define MOUNT_EXFAT            "/system/bin/mount.exfat"
+
+void startTiming(){
+    gettimeofday(&tpstart, NULL);
+}
+
+void endTimming(){
+    gettimeofday(&tpend, NULL);
+    timeuse = 1000000 * (tpend.tv_sec - tpstart.tv_sec) +
+        (tpend.tv_usec - tpstart.tv_usec);
+    LOGD("spend Time %f\n", timeuse);
+}
+
+int check_file_exists(const char * path){
+    int ret = -1;
+        if(path == NULL){
+                return -1;
+        }
+    ret = access(path, F_OK);
+        return ret;
+}
+
+int ensure_dev_mounted(const char * devPath,const char * mountedPoint){
+    int ret;
+        if(devPath == NULL || mountedPoint == NULL){
+                return -1;
+        }
+    mkdir(mountedPoint, 0755);  //in case it doesn't already exist
+    startTiming();
+    ret = mount(devPath, mountedPoint, "vfat",
+        MS_NOATIME | MS_NODEV | MS_NODIRATIME, "");
+    endTimming();
+    if(ret == 0){
+        LOGD("mount %s with fs 'vfat' success\n", devPath);
+        return 0;
+    }else{
+        startTiming();
+        ret = mount(devPath, mountedPoint, "ntfs",
+            MS_NOATIME | MS_NODEV | MS_NODIRATIME, "");
+        endTimming();
+        if(ret == 0){
+            LOGD("mount %s with fs 'ntfs' success\n", devPath);
+            return 0;
+        }else{
+            startTiming();
+            ret = mount(devPath, mountedPoint, "ext4",
+                MS_NOATIME | MS_NODEV | MS_NODIRATIME, "");
+            endTimming();
+            if(ret == 0){
+                LOGD("mount %s with fs 'ext4' success\n", devPath);
+                return 0;
+            }
+        }
+        LOGD("failed to mount %s (%s)\n", devPath, strerror(errno));
+        return -1;
+    }
+}
+
+int search_file_in_dev(const char * file, char *absolutePath,
+        const char *devPath, const char *devName){
+    if(!check_file_exists(devPath)){
+        LOGD("dev %s exists\n", devPath);
+        char mountedPoint[32];
+        sprintf(mountedPoint, "%s%s", USB_ROOT, devName);
+        //if the dev exists, try to mount it
+        if(!ensure_dev_mounted(devPath, mountedPoint)){
+            LOGD("dev %s mounted in %s\n", devPath, mountedPoint);
+            char desFile[PATH_MAX];
+            sprintf(desFile, "%s/%s", mountedPoint, file);
+            //if mount success.search des file in it
+            if(!check_file_exists(desFile)){
+                //if find the file,return its absolute path
+                LOGD("file %s exist\n", desFile);
+                sprintf(absolutePath, "%s", desFile);
+                return 0;
+            }else{
+                ensure_dev_unmounted(mountedPoint);
+            }
+        }
+    }
+    return -1;
+}
+
+int search_file_in_usb(const char * file,char * absolutePath){
+    timeval now;
+    gettimeofday(&now, NULL);
+    int i = 0;
+    int j = 0;
+    timeval workTime;
+    long spends;
+    mkdir(USB_ROOT, 0755);  //in case dir USB_ROOT doesn't already exist
+    //do main work here
+    do{
+        LOGD("begin....\n");
+        for(i = 0; i < MAX_DISK; i++){
+            char devDisk[32];
+            char devPartition[32];
+            char devName[8];
+            char parName[8];
+            sprintf(devName, "sd%c", 'a' + i);
+            sprintf(devDisk, "/dev/block/%s", devName);
+            LOGD("check disk %s\n", devDisk);
+            if(check_file_exists(devDisk)){
+                LOGD("dev %s does not exists (%s),waiting ...\n", devDisk, strerror(errno));
+                continue;
+            }
+            for(j = 1; j <= MAX_PARTITION; j++){
+                sprintf(parName, "%s%d", devName, j);
+                sprintf(devPartition, "%s%d" ,devDisk, j);
+                if(!search_file_in_dev(file, absolutePath, devPartition, parName)){
+                    return 0;
+                }
+            }
+            if(j > MAX_PARTITION){
+                if(!search_file_in_dev(file, absolutePath, devDisk, devName)){
+                    return 0;
+                }
+            }
+        }
+        usleep(500000);
+        gettimeofday(&workTime, NULL);
+        spends = (workTime.tv_sec - now.tv_sec)*1000000 + (workTime.tv_usec - now.tv_usec);
+    }while(spends < TIME_OUT);
+    LOGD("Time to search %s is %ld\n", file, spends);
+    return -1;
+}
+
+
+
+int ensure_dev_unmounted(const char * mountedPoint){
+    int ret = umount(mountedPoint);
+    return ret;
+}
+
+int in_usb_device(const char * file){
+    int len = strlen(USB_ROOT);
+    if (strncmp(file, USB_ROOT, len) == 0){
+        return 0;
+    }
+    return -1;
+}

3.selinux权限问题

经过一番调查 发现 data的 type属于 system_data_file类型的

在file_contexts中可以查看到

/data(/.*)?                u:object_r:system_data_file:s0

在recovery.te中发现了如下代码

neverallow recovery data_file_type:file { no_w_file_perms no_x_file_perms };
neverallow recovery data_file_type:dir no_w_dir_perms;
allow recovery rootfs:dir rw_dir_perms;

也就是说明 recover.te何时都不能读取和操作/data/目录,那怎么办?当然是有办法的,我们可以新建一个文件夹 和自定义文件类型啊

首先是开机的时候要有一个文件夹

我们可以在init.rc 或者 init.qcom.rc中创建一个文件夹

#Create directory for download
mkdir /data/download 0771
chown system system /data/download

创建完成之后需要app可以读取因此 需要在 system_app.te 中增加对应的权限

# allow system_app to access /data/download
allow system_app download_data_file:dir { search write add_name getattr remove_name };
allow system_app download_data_file:file { create read write open getattr unlink rename };

这样的话 我们已经创建了 文件夹,并且system app级别的应用可以读取.

那既然存储好了之后是不是下面需要 recovery可以读取到文件那?系统不允许读取 recovery.te /data/路径.那我们就自己创建一个文件类型,在file_contexts 增加类型

/data/download(/.*)?           u:object_r:download_data_file:s0  

然后在file.te中定义download_data_file类型, 注意是只属于file_type类型的。

type download_data_file, file_type;   

然后在recovery.te中增加对download_data_file的权限

allow recovery download_data_file:dir { write search remove_name };
allow recovery download_data_file:file { read getattr open unlink };

因为data目录有可能需要进行加密处理,我们还需要在uncrypt.te中增加如下。

allow uncrypt download_data_file:dir { search getattr };  
allow uncrypt download_data_file:file { getattr read open };

以上就是完成了添加,我本地全编译,测试成功.

最后升级的过程中可能会看到Permission Denied 最后可以cat   last_kmsg 查看 最后一样都会输出失败的权限原因

比如 :

avc:  denied  { open } for  pid=381 comm="recovery"
path="/data/download/update.zip" dev="mmcblk0p51" ino=513074
scontext=u:r:recovery:s0 tcontext=u:object_r:download_data_file:s0
TCLass=file permissive=0

这种权限只能报错什么权限添加什么权限,我们可以遵循这个方法,从头开始寻找关键对象,然后调整一下顺序,生成一条语句,最后将该语句填写到.te中即可。

denied { open }            scontext=u:r:recovery:s0          tcontext=u:object_r:download_data_file:s0        tclass=file               

             A                                    B                                                             C                                                  D

上面的标记按照 allow -> B-> C -> D ->  A ->[对应权限] 顺序摆放好即可  

例如:

allow recovery  download_data_file:tclass   open;

如果升级没有错误,APP操作文件夹中的文件无效时,可以在操作的时候执行如下命令,如果报了相关权限问题,加上即可,

adb shell dmesg | grep denied


相关阅读:
车机怎么快速打开APP 车机侧边栏工具下载
酷我音乐车机版怎么下载 完整使用酷我音乐所有功能版本
电视盒子刷机工具有哪些 16款电视盒子刷机工具免费下载


上一篇:大佬们 mst786这个芯片用什么刷机包,拆机附图
下一篇:【揭秘!】市面热门导航设备工厂密码大公开,速来围观!
沙发
发表于 2024-5-24 15:53 | 只看该作者 | 来自江西
感谢楼主的分享,写的很清楚,分析的很透彻,楼主一定是大神级的人物吧
回复 支持 反对

使用道具 举报

板凳
发表于 2024-5-30 10:25 | 只看该作者 | 来自上海
请问普拉多pz366-60122怎么刷机刷机升级?mt8125k 安卓4.4.2
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|新帖|标签|软件|Sitemap|ZNDS智能电视网 ( 苏ICP备2023012627号 )

网络信息服务信用承诺书 | 增值电信业务经营许可证:苏B2-20221768 丨 苏公网安备 32011402011373号

GMT+8, 2024-6-17 05:41 , Processed in 0.078773 second(s), 13 queries , Redis On.

Powered by Discuz!

监督举报:report#znds.com (请将#替换为@)

© 2007-2024 ZNDS.Com

快速回复 返回顶部 返回列表