首頁 收藏 QQ群
 網(wǎng)站導航

ZNDS智能電視網(wǎng) 推薦當貝市場

TV應(yīng)用下載 / 資源分享區(qū)

軟件下載 | 游戲 | 討論 | 電視計算器

綜合交流 / 評測 / 活動區(qū)

交流區(qū) | 測硬件 | 網(wǎng)站活動 | Z幣中心

新手入門 / 進階 / 社區(qū)互助

新手 | 你問我答 | 免費刷機救磚 | ROM固件

查看: 37139|回復: 2
上一主題 下一主題
[分享]

android版的車機怎么升級 Android 7.1車機系統(tǒng)在線升級教程

[復制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2024-5-24 15:51 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式 | 來自河南
今天,就為大家?guī)鞟ndroid 7.1車機系統(tǒng)的在線升級教程。想要輕松升級你的車機系統(tǒng)嗎?只需將安裝包下載至/data/目錄,即可一鍵升級,讓駕駛體驗更流暢!

最近按項目要求,需要做一個車機Android在線升級操作,但是cache內(nèi)存太小了,最后只能寄存希望在 data/文件夾下,但是data/目錄在6.0之后禁止recovery讀取data文件.最后的解決方案是在/data/文件下創(chuàng)建一個系統(tǒng)app能夠操作的文件夾,進行升級操作.

1、升級流程

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

調(diào)用如下代碼就可以進行升級操作,對你沒看錯,就是一句代碼,將你下載好的壓縮包路徑傳過去就行.

   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 ,開始了升級操作,結(jié)果失敗了.開始檢查原因

是不是AndroidManifest.xml中沒有添加 如下權(quán)限

android:sharedUserId="android.uid.system"

查看添加了,是不是沒有對自己的apk進行系統(tǒng)簽名?發(fā)現(xiàn)也簽名了(如何給APK系統(tǒng)簽名),沒有放到system/app/文件夾下?也放了,.那原因出在哪里那?不想了,先去看看log

Android機器中 /cache/recovery/的目錄結(jié)構(gòu)如下:

cache/        
└── recovery      
    ├── last_install
    ├── last_kmsg  #系統(tǒng)升級的時候的全log. 如果有l(wèi)ast_kmsg.1
                   #那last_kmsg 永遠是最后一次升級的log,所以每
                   #次只查看last_kmsg就行
    ├── last_locale
    └── last_log   #升級過程中的簡log,能看到為何升級失敗

在log中查看到的是  --update_package=@/cache/recovery/block.map 看到這個結(jié)果的時候,第一感覺就是apk沒有安裝成功,于是加了log 發(fā)現(xiàn)加的log 成功打印,嚇了一跳,自己撞見鬼了?

抱著程序員不明原因不放棄的心態(tài),看了一下RecoverySystem.java 中的 installPackage 方法,原來是 installpackage在代碼中做了限制, 要是設(shè)置的路徑是以 /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發(fā)現(xiàn) --update_package=data/update.zip . 這么看來已經(jīng)能寫到重啟文件中了.

查看log提示是  --update_package=data/update.zip  Permission Denied 看來是datarecover沒有權(quán)限讀取/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權(quán)限問題

經(jīng)過一番調(diào)查 發(fā)現(xiàn) data的 type屬于 system_data_file類型的

在file_contexts中可以查看到

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

在recovery.te中發(fā)現(xiàn)了如下代碼

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中創(chuàng)建一個文件夾

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

創(chuàng)建完成之后需要app可以讀取因此 需要在 system_app.te 中增加對應(yīng)的權(quán)限

# 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 };

這樣的話 我們已經(jīng)創(chuàng)建了 文件夾,并且system app級別的應(yīng)用可以讀取.

那既然存儲好了之后是不是下面需要 recovery可以讀取到文件那?系統(tǒng)不允許讀取 recovery.te /data/路徑.那我們就自己創(chuàng)建一個文件類型,在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的權(quán)限

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 查看 最后一樣都會輸出失敗的權(quán)限原因

比如 :

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

這種權(quán)限只能報錯什么權(quán)限添加什么權(quán)限,我們可以遵循這個方法,從頭開始尋找關(guān)鍵對象,然后調(diào)整一下順序,生成一條語句,最后將該語句填寫到.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 ->[對應(yīng)權(quán)限] 順序擺放好即可  

例如:

allow recovery  download_data_file:tclass   open;

如果升級沒有錯誤,APP操作文件夾中的文件無效時,可以在操作的時候執(zhí)行如下命令,如果報了相關(guān)權(quán)限問題,加上即可,

adb shell dmesg | grep denied


相關(guān)閱讀:
車機怎么快速打開APP 車機側(cè)邊欄工具下載
酷我音樂車機版怎么下載 完整使用酷我音樂所有功能版本
電視盒子刷機工具有哪些 16款電視盒子刷機工具免費下載


上一篇:大佬們 mst786這個芯片用什么刷機包,拆機附圖
下一篇:【揭秘!】市面熱門導航設(shè)備工廠密碼大公開,速來圍觀!
沙發(fā)
發(fā)表于 2024-5-24 15:53 | 只看該作者 | 來自江西
感謝樓主的分享,寫的很清楚,分析的很透徹,樓主一定是大神級的人物吧
回復 支持 反對

使用道具 舉報

板凳
發(fā)表于 2024-5-30 10:25 | 只看該作者 | 來自上海
請問普拉多pz366-60122怎么刷機刷機升級?mt8125k 安卓4.4.2
回復 支持 反對

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

Archiver|新帖|標簽|軟件|Sitemap|ZNDS智能電視網(wǎng) ( 蘇ICP備2023012627號 )

網(wǎng)絡(luò)信息服務(wù)信用承諾書 | 增值電信業(yè)務(wù)經(jīng)營許可證:蘇B2-20221768 丨 蘇公網(wǎng)安備 32011402011373號

GMT+8, 2024-12-28 00:23 , Processed in 0.130336 second(s), 13 queries , Redis On.

Powered by Discuz!

監(jiān)督舉報:report#znds.com (請將#替換為@)

© 2007-2024 ZNDS.Com

快速回復 返回頂部 返回列表