rk3368 Android9.0 HIDL调试记录

rk3368_android9.0添加launcher备份功能 阅读详情

rk3368 Android9.0 HIDL调试记录

Platform: RK3368
OS: Android 9.0
Kernel: 4.4.194


在Android 8.0以后,低层已重新编写以采用更加模块化的新架构。必须支持使用 HIDL 语言编写的 HAL,下面列出了一些例外情况。这些 HAL 可以是绑定式 HAL 也可以是直通式 HAL.

绑定式 HAL 以 HAL 接口定义语言 (HIDL) 或 Android 接口定义语言 (AIDL) 表示的 HAL。这些 HAL 取代了早期 Android 版本中使用的传统 HAL 和旧版 HAL。在绑定式 HAL 中,Android 框架和 HAL 之间通过 Binder 进程间通信 (IPC) 调用进行通信。所有在推出时即搭载了 Android 8.0 或更高版本的设备都必须只支持绑定式 HAL。

直通式 HAL 以 HIDL 封装的传统 HAL 或旧版 HAL。这些 HAL 封装了现有的 HAL,可在绑定模式和 Same-Process(直通)模式下使用。升级到 Android 8.0 的设备可以使用直通式 HAL。

此调试记录为绑定式 HAL;

1. 使用hidl-gen工具生成接口

1.1 hidl-gen使用方法

$ hidl-gen -h
usage: hidl-gen [-p <root path>] -o <output path> -L <language> [-O <owner>] (-r <interface root>)+ [-v] [-d <depfile>] FQNAME...

Process FQNAME, PACKAGE(.SUBPACKAGE)*@[0-9]+.[0-9]+(::TYPE)?, to create output.

         -h: Prints this menu.
         -L <language>: The following options are available:
            check           : Parses the interface to see if valid but doesn't write any files.
            c++             : (internal) (deprecated) Generates C++ interface files for talking to HIDL interfaces.
            c++-headers     : (internal) Generates C++ headers for interface files for talking to HIDL interfaces.
            c++-sources     : (internal) Generates C++ sources for interface files for talking to HIDL interfaces.
            export-header   : Generates a header file from @export enumerations to help maintain legacy code.
            c++-impl        : Generates boilerplate implementation of a hidl interface in C++ (for convenience).
            c++-impl-headers: c++-impl but headers only
            c++-impl-sources: c++-impl but sources only
            c++-adapter     : Takes a x.(y+n) interface and mocks an x.y interface.
            c++-adapter-headers: c++-adapter but helper headers only
            c++-adapter-sources: c++-adapter but helper sources only
            c++-adapter-main: c++-adapter but the adapter binary source only
            java            : (internal) Generates Java library for talking to HIDL interfaces in Java.
            java-constants  : (internal) Like export-header but for Java (always created by -Lmakefile if @export exists).
            vts             : (internal) Generates vts proto files for use in vtsd.
            makefile        : (removed) Used to generate makefiles for -Ljava and -Ljava-constants.
            androidbp       : (internal) Generates Soong bp files for -Lc++-headers, -Lc++-sources, -Ljava, -Ljava-constants, and -Lc++-adapter.
            androidbp-impl  : Generates boilerplate bp files for implementation created with -Lc++-impl.
            hash            : Prints hashes of interface in `current.txt` format to standard out.
         -O <owner>: The owner of the module for -Landroidbp(-impl)?.
         -o <output path>: Location to output files.
         -p <root path>: Android build root, defaults to $ANDROID_BUILD_TOP or pwd.
         -r <package:path root>: E.g., android.hardware:hardware/interfaces.
         -v: verbose output.
         -d <depfile>: location of depfile to write to.

1.2 创建HIDL文件

  1. 新建目录vendor/sample/hardware/interfaces/helloworld/1.0
  2. 创建文件: IHelloWorld.hal IHelloWorldCallback.hal types.hal

不要直接在Android源码目录hardware/interfaces下面添加和修改接口,在API锁定分支中不允许更改VNDK库列表.

其中vendor/sample/hardware/interfaces就是hidl的root path了.

helloworld/1.0/IHelloWorld.hal

package sample.hardware.helloworld@1.0;

import IHelloWorldCallback;

interface IHelloWorld {
    initial();
    getInt() generates (int32_t i);
    setInt(int32_t val) generates (Result error);
    oneway setCallback(IHelloWorldCallback callback);
 };

helloworld/1.0/IHelloWorldCallback.hal

package sample.hardware.helloworld@1.0;

interface IHelloWorldCallback {
    oneway onEvent(Event event);
 };

helloworld/1.0/types.hal

package sample.hardware.helloworld@1.0;
enum Result : int32_t {
    OK,
    UNKNOWN,
    INVALID_ARGUMENTS,
};

struct Event {
    uint32_t type;
    uint32_t code;
    uint32_t value;
};
  1. 指定HIDL包根目录
    添加文件vendor/sample/hardware/interfaces/Android.bp
hidl_package_root {
    name: "sample.hardware",
    path: "vendor/sample/hardware/interfaces",
}

如果不指定HIDL包根目录,编译会报错:Cannot find package root specification

interfaces: Cannot find package root specification for package root 'sample.hardware' needed for module 'sample.hardware.helloworld@1.0'. Either this is a mispelling of the package root, or a new hidl_package_root module needs to be added. For example, you can fix this error by adding the following to <some path>/Android.bp:

hidl_package_root {
    name: "sample.hardware",
    path: "<some path>",
}
  1. 生成HIDL哈希
    每个软件包根目录(即映射到 hardware/interfaces 的 android.hardware 或映射到 vendor/foo/hardware/interfaces 的 vendor.foo)都必须包含一个列出所有已发布 HIDL 接口文件的 current.txt 文件。
$ hidl-gen -Lhash -rsample.hardware:vendor/sample/hardware/interfaces -randroid.hidl:system/libhidl/transport sample.hardware.helloworld@1.0> vendor/sample/hardware/interfaces/current.txt

1.3 使用hidl-gen工具生成HIDL相关文件

  1. 使用hidl-gen生成C++文件
$ hidl-gen -o vendor/sample/hardware/interfaces/helloworld/1.0/default -Lc++-impl -rsample.hardware:vendor/sample/hardware/interfaces -randroid.hidl:system/libhidl/transport sample.hardware.helloworld@1.0

把生成的下面两个不用的文件删除:
helloworld/1.0/default/HelloWorldCallback.cpp
helloworld/1.0/default/HelloWorldCallback.h

  1. 使用hidl-gen生成helloworld/1.0/default/Android.bp
$ hidl-gen -o vendor/sample/hardware/interfaces/helloworld/1.0/default -Landroidbp-impl -rsample.hardware:vendor/sample/hardware/interfaces -randroid.hidl:system/libhidl/transport sample.hardware.helloworld@1.0
  1. 使用system/tools/hidl/update-makefiles-helper.sh生成helloworld/1.0/Android.bp
$ source $ANDROID_BUILD_TOP/system/tools/hidl/update-makefiles-helper.sh
$ do_makefiles_update sample.hardware:vendor/sample/hardware/interfaces android.hardware:hardware/interfaces android.hidl:system/libhidl/transport

helloworld/1.0/Android.bp内容如下:

// This file is autogenerated by hidl-gen -Landroidbp.

hidl_interface {
    name: "sample.hardware.helloworld@1.0",
    root: "sample.hardware",
    srcs: [
        "types.hal",
        "IHelloWorld.hal",
        "IHelloWorldCallback.hal",
    ],
    interfaces: [
        "android.hidl.base@1.0",
    ],
    types: [
        "Event",
        "Result",
    ],
    gen_java: true,
}
  1. 为device manifest添加hal接口
    由hwservicemanager去解析并将服务启动;
    device/rockchip/$TARGET_PRODUCT/manifest.xml
    <hal format="hidl">
        <name>sample.hardware.helloworld</name>
        <transport>hwbinder</transport>
        <version>1.0</version>
        <interface>
            <name>IHelloWorld</name>
            <instance>default</instance>
        </interface>
    </hal>

然后完整编译一下Android,更新manifest.xml文件:

out/target/product/$TARGET_PRODUCT/vendor/etc/vintf/manifest.xml

如果不更新device manifest,测试程序会找不到服务端,hwservicemanager会报以下错误:
W hwservicemanager: getTransport: Cannot find entry sample.hardware.helloworld@1.0::IHelloWorld/default in either framework or device manifest.

2. 修改代码

2.1 创建service代码

hardware/interfaces/sample/1.0/default/service.cpp

#define LOG_TAG "sample.hardware.helloworld@1.0-service"

#include <android-base/logging.h>
#include <hidl/HidlTransportSupport.h>

#include "HelloWorld.h"

using android::OK;
using android::sp;
using android::status_t;
using android::hardware::configureRpcThreadpool;
using android::hardware::joinRpcThreadpool;
using sample::hardware::helloworld::V1_0::IHelloWorld;
using sample::hardware::helloworld::V1_0::implementation::HelloWorld;

int main(int /* argc */, char ** /* argv */)
{
    ALOGD("HAL Service is starting.");
    sp<IHelloWorld> service = new HelloWorld();

    configureRpcThreadpool(1, true /*callerWillJoin*/);
    status_t status = service->registerAsService();
    if (status != OK)
    {
        LOG_ALWAYS_FATAL("Could not register service for HelloWorld HAL Iface (%d).", status);
        return -1;
    }

    ALOGD("Register as service ready.");

    joinRpcThreadpool();
    return 1; // joinRpcThreadpool shouldn't exit
}

2.2 修改Android.bp添加编译service

hardware/interfaces/sample/1.0/default/Android.bp
将cc_library_shared节点proprietary: true改为vendor: true;
删除relative_install_path: “hw”,目的是将sample.hardware.helloworld@1.0-impl.so编译安装到vendor/lib64目录下面,如果vendor/lib64/hw下面,运行服务时因VNDK规则限制,会报以下错误:

F linker : CANNOT LINK EXECUTABLE “./vendor/bin/hw/sample.hardware.helloworld@1.0-service”: library “sample.hardware.helloworld@1.0-impl.so” not found

cc_library_shared {
    name: "sample.hardware.helloworld@1.0-impl",

    vendor: true,
    srcs: [
        "HelloWorld.cpp",
    ],
    shared_libs: [
        "liblog",
        "libhidlbase",
        "libhidltransport",
        "libutils",
        "sample.hardware.helloworld@1.0",
    ],
}

cc_binary {
    name: "sample.hardware.helloworld@1.0-service",
    defaults: ["hidl_defaults"],
    vendor: true,
    relative_install_path: "hw",
    init_rc: ["sample.hardware.helloworld@1.0-service.rc"],
    srcs: ["service.cpp"],

    shared_libs: [
        "libcutils",
        "libhidlbase",
        "libhidltransport",
        "liblog",
        "libutils",
        "libhardware",
        "sample.hardware.helloworld@1.0",
        "sample.hardware.helloworld@1.0-impl",
    ],
}

2.3 添加启动service的init.rc文件

hardware/interfaces/sample/1.0/default/android.hardware.sample@1.0-service.rc

service vendor.helloworld-1-0 /vendor/bin/hw/sample.hardware.helloworld@1.0-service
    class hal
    user system
    group system

2.4 修改生成的代码

helloworld/1.0/default/HelloWorld.h

#ifndef SAMPLE_HARDWARE_HELLOWORLD_V1_0_HELLOWORLD_H
#define SAMPLE_HARDWARE_HELLOWORLD_V1_0_HELLOWORLD_H

#include <sample/hardware/helloworld/1.0/IHelloWorld.h>
#include <hidl/MQDescriptor.h>
#include <hidl/Status.h>

namespace sample {
namespace hardware {
namespace helloworld {
namespace V1_0 {
namespace implementation {

using ::android::hardware::hidl_array;
using ::android::hardware::hidl_memory;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::sp;

struct HelloWorld : public IHelloWorld
{
    Return<void> initial() override;
    Return<int32_t> getInt() override;
    Return<::sample::hardware::helloworld::V1_0::Result> setInt(int32_t val) override;
    Return<void> setCallback(const sp<::sample::hardware::helloworld::V1_0::IHelloWorldCallback> &callback) override;

    static void *pollThreadWrapper(void *me);
    void pollThreadEntry();

private:
    pthread_mutex_t mLock = PTHREAD_MUTEX_INITIALIZER;
    pthread_t mPollThread;
    bool mRunning;
    std::vector<sp<IHelloWorldCallback>> mCallbacks;
};

}  // namespace implementation
}  // namespace V1_0
}  // namespace helloworld
}  // namespace hardware
}  // namespace sample

#endif  // SAMPLE_HARDWARE_HELLOWORLD_V1_0_HELLOWORLD_H

helloworld/1.0/default/HelloWorld.cpp

#define LOG_TAG "sample.hardware.helloworld@1.0-service"
#include <android-base/logging.h>
#include <log/log.h>

#include "HelloWorld.h"

namespace sample {
namespace hardware {
namespace helloworld {
namespace V1_0 {
namespace implementation {

Return<void> HelloWorld::initial()
{
    ALOGD("%s", __FUNCTION__);

    if (mRunning)
        return Void();

    mRunning = true;
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
    pthread_create(&mPollThread, &attr, pollThreadWrapper, this);
    pthread_attr_destroy(&attr);

    return Void();
}

Return<int32_t> HelloWorld::getInt()
{
    ALOGD("%s", __FUNCTION__);
    return int32_t{666};
}

Return<::sample::hardware::helloworld::V1_0::Result> HelloWorld::setInt(int32_t val)
{
    ALOGD("%s %d", __FUNCTION__, val);
    return ::sample::hardware::helloworld::V1_0::Result{};
}

void *HelloWorld::pollThreadWrapper(void *me)
{
    static_cast<HelloWorld *>(me)->pollThreadEntry();
    return NULL;
}

void HelloWorld::pollThreadEntry()
{
    mRunning = true;
    ALOGD("%s enter", __FUNCTION__);

    Event event;
    event.type = 0;
    event.code = 0;
    event.value = 0;
    while (mRunning)
    {
        event.code++;
        event.type++;
        event.value++;
        sleep(1);
        ALOGD("%s event %04x %04x %04x\n", __FUNCTION__, event.type, event.code, event.value);
        pthread_mutex_lock(&mLock);
        if (!mCallbacks.empty())
        {
            std::vector<sp<IHelloWorldCallback>>::iterator it;
            for (it = mCallbacks.begin(); it != mCallbacks.end();)
            {
                sp<IHelloWorldCallback> callback = *it;
                Return<void> ret = callback->onEvent(event);
                if (!ret.isOk())
                {
                    ALOGE("error %s", ret.description().c_str());
                    it = mCallbacks.erase(it);
                }
                else
                {
                    it++;
                }
            }
        }
        pthread_mutex_unlock(&mLock);
    }
    ALOGD("%s exit", __FUNCTION__);
}

Return<void> HelloWorld::setCallback(const sp<::sample::hardware::helloworld::V1_0::IHelloWorldCallback> &callback)
{
    ALOGD("%s", __FUNCTION__);
    pthread_mutex_lock(&mLock);

    if (callback != nullptr)
    {
        mCallbacks.push_back(callback);
    }

    pthread_mutex_unlock(&mLock);
    return Void();
}

}  // namespace implementation
}  // namespace V1_0
}  // namespace helloworld
}  // namespace hardware
}  // namespace sample

2.5 添加本地C++测试代码

helloworld/1.0/test/Android.bp

cc_binary {
    name: "sample.hardware.helloworld_hidl_hal_test",
    vendor: true,
    srcs: ["test.cpp"],

    shared_libs: [
        "libhidlbase",
        "libhidltransport",
        "liblog",
        "libutils",
        "libhardware",
        "sample.hardware.helloworld@1.0",
    ],
}

helloworld/1.0/test/test.cpp

#define LOG_TAG "sample.hardware.helloworld_hidl_hal_test"

#include <android-base/logging.h>
#include <hidl/HidlTransportSupport.h>
#include <log/log.h>
#include <sample/hardware/helloworld/1.0/IHelloWorld.h>
#include <sample/hardware/helloworld/1.0/types.h>

using ::android::sp;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::sample::hardware::helloworld::V1_0::Event;
using ::sample::hardware::helloworld::V1_0::IHelloWorld;
using ::sample::hardware::helloworld::V1_0::IHelloWorldCallback;
using ::sample::hardware::helloworld::V1_0::Result;

class HelloWorldCallback : public IHelloWorldCallback
{
public:
    HelloWorldCallback()
    {
        printf("%s\n", __FUNCTION__);
    }
    ~HelloWorldCallback()
    {
        printf("%s\n", __FUNCTION__);
    }

    Return<void> onEvent(const Event &event)
    {
        printf("%s %04x %04x %04x\n", __FUNCTION__, event.type, event.code, event.value);
        return Void();
    }
};

int main(int /* argc */, char ** /* argv */)
{
    sp<IHelloWorld> service = IHelloWorld::getService();
    if (service == nullptr)
    {
        printf("Failed to get service\n");
        return -1;
    }

    printf("initial\n");
    service->initial();

    int ret = service->getInt();
    printf("getInt %d\n", ret);

    Result result = service->setInt(888);
    printf("setInt result=%d\n", result);

    sp<IHelloWorldCallback> callback = new HelloWorldCallback();
    printf("setCallback\n");
    service->setCallback(callback);
    while (1)
    {
        sleep(1);
    }

    return 0;
}

3. 编译测试

3.1 mmm单独模块编译:

$ mmm vendor/sample/hardware/interfaces/helloworld/1.0/
  1. 编译hal文件生成的中间代码位于out/soong/.intermediates/vendor/sample/hardware/interfaces/helloworld/1.0/:
default
sample.hardware.helloworld@1.0
sample.hardware.helloworld@1.0-adapter
sample.hardware.helloworld@1.0-adapter_genc++
sample.hardware.helloworld@1.0-adapter-helper
sample.hardware.helloworld@1.0-adapter-helper_genc++
sample.hardware.helloworld@1.0-adapter-helper_genc++_headers
sample.hardware.helloworld@1.0_genc++
sample.hardware.helloworld@1.0_genc++_headers
sample.hardware.helloworld-V1.0-java
sample.hardware.helloworld-V1.0-java_gen_java
test

"sample.hardware.helloworld@1.0_genc++"目录里面可以发现hal文件转换成了C++源码 ,里面就包含Binder Bn端,Binder Bp端的代码.不用像非Project Treble项目那样需要自己写Binder Bn端,Binder Bp端的代码.体会到了谷歌的良苦用心.

  1. 编译最终会在out/target/product/$TARGET_PRODUCT/目录下面生成了以下文件:
out/target/product/$TARGET_PRODUCT/system/lib/sample.hardware.helloworld@1.0.so
out/target/product/$TARGET_PRODUCT/system/lib/sample.hardware.helloworld@1.0-adapter-helper.so
out/target/product/$TARGET_PRODUCT/system/lib64/sample.hardware.helloworld@1.0.so
out/target/product/$TARGET_PRODUCT/system/lib64/sample.hardware.helloworld@1.0-adapter-helper.so
out/target/product/$TARGET_PRODUCT/system/framework/sample.hardware.helloworld-V1.0-java.jar
out/target/product/$TARGET_PRODUCT/system/framework/oat/arm/sample.hardware.helloworld-V1.0-java.odex
out/target/product/$TARGET_PRODUCT/system/framework/oat/arm/sample.hardware.helloworld-V1.0-java.vdex
out/target/product/$TARGET_PRODUCT/system/framework/oat/arm64/sample.hardware.helloworld-V1.0-java.odex
out/target/product/$TARGET_PRODUCT/system/framework/oat/arm64/sample.hardware.helloworld-V1.0-java.vdex
out/target/product/$TARGET_PRODUCT/vendor/lib/sample.hardware.helloworld@1.0-impl.so
out/target/product/$TARGET_PRODUCT/vendor/lib/sample.hardware.helloworld@1.0.so
out/target/product/$TARGET_PRODUCT/vendor/lib/sample.hardware.helloworld@1.0-adapter-helper.so
out/target/product/$TARGET_PRODUCT/vendor/lib64/sample.hardware.helloworld@1.0-impl.so
out/target/product/$TARGET_PRODUCT/vendor/lib64/sample.hardware.helloworld@1.0.so
out/target/product/$TARGET_PRODUCT/vendor/lib64/sample.hardware.helloworld@1.0-adapter-helper.so
out/target/product/$TARGET_PRODUCT/vendor/bin/hw/sample.hardware.helloworld@1.0-service
out/target/product/$TARGET_PRODUCT/vendor/bin/sample.hardware.helloworld_hidl_hal_test
out/target/product/$TARGET_PRODUCT/vendor/etc/init/sample.hardware.helloworld@1.0-service.rc

3.2 Native测试

  1. 将编译好的库和bin文件复制到设备中:
$ adb root
$ adb remount
$ adb push  out/target/product/$TARGET_PRODUCT/vendor/lib64/sample.hardware.helloworld@1.0-impl.so /vendor/lib64/sample.hardware.helloworld@1.0-impl.so
$ adb push  out/target/product/$TARGET_PRODUCT/vendor/lib64/sample.hardware.helloworld@1.0.so /vendor/lib64/sample.hardware.helloworld@1.0.so
$ adb push  out/target/product/$TARGET_PRODUCT/vendor/bin/hw/sample.hardware.helloworld@1.0-service /vendor/bin/hw/sample.hardware.helloworld@1.0-service
$ adb push  out/target/product/$TARGET_PRODUCT/vendor/bin/sample.hardware.helloworld_hidl_hal_test /vendor/bin/sample.hardware.helloworld_hidl_hal_test
  1. 启动服务和测试
# ./vendor/bin/hw/sample.hardware.helloworld@1.0-service&
# sample.hardware.helloworld_hidl_hal_test                      
initial
getInt 666
setInt result=0
HelloWorldCallback
setCallback
onEvent 0001 0001 0001
onEvent 0002 0002 0002
onEvent 0003 0003 0003

3.3 Android APP java测试

Android Studio中将out/soong/.intermediates/vendor/sample/hardware/interfaces/helloworld/1.0/sample.hardware.helloworld-V1.0-java/android_common/combined/sample.hardware.helloworld-V1.0-java.jar 复制到APP工程的libs目录下面,然后将此jar包导入工程就可以使用了,java使用就是这么简单,连JNI都不用自己写了;
不要用/system/framework/sample.hardware.helloworld-V1.0-java.jar这个jar包,这是Dex优化剥离了class文件后的jar;

package com.example.helloworld;

import android.app.Activity;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;

import sample.hardware.helloworld.V1_0.Event;
import sample.hardware.helloworld.V1_0.IHelloWorld;
import sample.hardware.helloworld.V1_0.IHelloWorldCallback;

public class MainActivity extends Activity {

    private static final String TAG = MainActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        try {
            IHelloWorld helloWorld = IHelloWorld.getService();
            helloWorld.initial();
            int ret = helloWorld.getInt();
            Log.d(TAG, "getInt=" + ret);
            helloWorld.setInt(888);
            helloWorld.setCallback(new HelloWorldCallback());
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    static class HelloWorldCallback extends IHelloWorldCallback.Stub {

        @Override
        public void onEvent(Event event) throws RemoteException {
            Log.d(TAG, "onEvent type=" + event.type + ", code=" + event.code + ", value=" + event.value);
        }
    }
}
android 里边添加hidl服务 笔者在Android 9 通过以下方式添加hidl服务,理论上对Android 8/9/10 都适用, 对于为何要有hidl这个东西以及如何添加hidl服务,google在https://source.android.google.cn/devices/architecture/hidl 里边有说明, 只是添加步骤不够详细,本人之前踩过一些坑折腾了好一会儿才添加成功,所以才想写这篇文章和同学们一起交流学习,本文目前只描述如何做不描述底层原理(底层也是用来binder),文章内容全部是基于android开源技 阅读详情

相关推荐

RK3288 RK3368 瑞芯微RK系列Android生成OTA差分升级包

一、OTA完整包生成方法 OTA完整包可用于T卡本地升级和OTA在线升级。OTA完整包包含完整的system、recovery. 和boot.img。 发布一个版本固件正确顺序: make -j4 make otapackage ./mkimage.sh ota 注意:发布固件必须使用./mkimage.sh ota,将boot与kernel打包,不需要单独烧kernel,如果量产固件是分开的,将...

performance 7148

rk3368 Android9.0 升级固件后,一直在recovery界面

升级固件后,一直在recovery界面 Platform: RK3368 OS: Android 9.0 Kernel: 4.4.194 文章目录升级固件后,一直在recovery界面升级固件后,一直在recovery界面 升级固件后,一直在recovery界面 串口日志: E:Failed to mount /cache: No such file or directory E:Failed to set BCB message: failed to stat /dev/block/by-name/m

dolphin的专栏 7597

告别变砖!RK3368盒子Android 9固件升级后救砖指南:修改DTB与firmware_android节点详解

本文详细解析了RK3368电视盒子在Android 9固件升级失败后的救砖方案,重点介绍了如何通过修改DTB和firmware_android节点恢复系统。从诊断变砖原因到DTB反编译、关键节点修改,再到固件刷写与验证,提供了一套完整的实战指南,帮助用户和开发者快速解决启动故障。

weixin_42525328的博客 518

RK3368固件烧写

前期需要准备的工具AndroidTool.exe如下图: 具体步骤: 1.打开烧录工具; 2.选择需要烧录的模块,如下图我只烧录kernel与Resource两部分,即在这两个前面对应打钩就可以; 3.选择对应的路径,点击下图红框区域,选择要烧录固件的位置,如下图 4.选择完成后,需要切换进入Loader模式,然后点击“执行”即可进行烧录; 烧录完成后,右边空白区域,会进行提示。 下面介绍一下进入loader模式的几种方法: 1.在链接设备后,打开烧录工具显示“发现...

it_rensheng的博客 1万+

rk3368_Android5.1隐藏“擦除SD”菜单选项

板子通过otg线连接电脑,打开电脑adb界面,打开logcat,然后开始点击“Erase SD card”选项,在点击“Erase SD card”选项的同时,观察logcat打印信息,找到定位关键词:MasterClear。决定隐藏掉“Erase SD card"选项,来避免这个问题,下面开始动手去操作怎么去隐藏。我们一个基于rk3368平台Android5.1系统的项目,因为我们的系统裁减了一些功能,修改编译后,即可隐藏擦除SD菜单选项。,如果在恢复出厂设置时。

daizhifeng123468的博客 427

RK3288/3399 Android Root包

本ROOT方法适用于RK3288/RK3399 的Android 32/64位系统

rk3368 Android9.0调试记录之系统分区调整

rk3368 Android9.0调试记录之系统分区 Platform: RK3368 OS: Android 9.0 Kernel: 4.4.194 文章目录rk3368 Android9.0调试记录之系统分区1. 升级固件后开机进recovery出错1.1. 调整分区表 1. 升级固件后开机进recovery出错 ensure_path_unmounted path is /data Volume is already unmounted ensure_path_unmounted path is

dolphin的专栏 2341

Update.ZIP_TWRP_RK3368_3.1.0-0_170318

Update.ZIP_TWRP_RK3368_3.1.0-0_170318 .zip是卡刷包,适用于RK3368芯片的TWRP 3.1.0

[Android][frameworks][HIDL]使用HIDL新建虚拟HAL以实现system_server与native进程双向通信(一)——服务端

前言 需求是这样的,system_server有一个LocalService,需要向一个具有root权限的native进程进行消息传递(下发请求指令,获取状态信息等) 评估 首先附上官方介绍:https://source.android.com/devices/architecture/hidl 此功能最早使用socket实现(参考lmkd的实现),但是由于如下几点原因,因此决定使用...

Ryan ZHENG的专栏 4842

RK系列开发刷机工具(单刷)

支持烧写一个或多个分区镜像,单独固件烧录,擦除FLASH。等

3328-3318_android9.0_ patch_v1.1_20190430.zip

RK3328 和RK3318 在安卓9.0的兼容性补丁

RK3368-android8.1-每天凌晨3点自动重启机器

RK3368-android8.1-每天凌晨3点自动重启机器

longmin96的博客 2093

深度学习入门:一文详解BP神经网络

在BP神经网络中,输入层和输出层的节点个数都是确定的,而隐含层节点个数不确定,那么应该设置为多少。实际上,隐含层节点个数的多少对神经网络的性能是有影响的,有一个经验公式可以确定隐含层。上面是对隐含层和输出层之间的权值和输出层的阀值计算调整量,而针对输入层和隐含层和隐含层的阀值调。在BP神经网络中,输入层节点没有阀值。神经网络,神经网络在机器学习中应用比较广泛,比如函数逼近,模式识别,分类,数据压缩,数据。要求输入模式要有足够的随机性,对输入模式的噪声比较敏感,即对于剧烈变化的输入模式,训。

Machine Learning with Tutors 4万+

折腾3368(6.0.1)固件

折腾3368(6.0.1)固件

weixin_41351911的博客 6544

跟着团子学SAP CO:揭秘结果分析码在项目结算中的实战应用(一)KKA2/CJ88

本文深入解析了SAP CO模块中结果分析码在项目结算中的核心作用。以KKA2(方法10)和事务代码CJ88为例,详细阐述了如何在项目完工后一次性确认收入的场景下,通过结果分析功能实现收入与成本的精准匹配,将项目成本暂估为在制品,确保各期利润的准确反映。

gamma的博客 685

统计信号处理基础 习题解答1-1

1-1:在雷达习题中,双程延时时间的估计量具有PDF τ0~Nτ0,στ02,其中τ0是真值。假如要估计距离请提出一种估计量R,并求它的PDF。然后,确定标准偏差στ0,使得距离估计值的99%在真值的100m以内,对电磁波传播速度取c=3×108m/s。 解答: 问题1: 由于电磁波传播速度c,信号可观察的双程传播延时τ0和双程传播距离τ0满足关系: R=cτ02 因此可采用如下估计量: R=cτ02 问题2: 由于τ0满足正态分布,且: Eτ0=τ0 varτ0=στ02 那么: E

weixin_43270276的博客 2805

Update.ZIP_TWRP_RK3368_3.1.0-0_170318:解锁RK3368设备新可能

Update.ZIP_TWRP_RK3368_3.1.0-0_170318:解锁RK3368设备新可能 【下载地址】Update.ZIP_TWRP_RK3368_3.1.0-0_170318资源文件介绍 该项目为RK3368芯片设备提供了一键刷机资源包,内含TWRP 3.1.0版本,专为卡刷设计。通过该包,用户可以轻松安...

gitblog_06721的博客 1373

KUKA机器人 - 从开机到自动运行

注1:本文仅代表本人对机器人使用的一些建议,在使用机器人前,还请详细阅读库卡机器人官方资料,道路千万条,安全第一条!!! 注2:技术有限,欢迎各位大大在阅读过程中发现各类问题,并且批评指正!!! 目录 一、准备工作 1. 机器人上电完成 2. 电脑安装Workvisual 二、学习手动移动机器人 三、项目配置 1. 设置机器人IP地址 2.电脑和机器人通过网线连接 3.查找并打开项目 4. 通讯配置 5. 项目上传 6. 检验IO配置 四、编程 1.新建程序 2. 程序...

yilunyao的博客 1万+

Android 12 S HIDL Service创建流程

HIDL 这个机制的目的,主要是为了把框架(framework)与 HAL 进行隔离,使得框架部分可以直接被覆盖、更新,而不需要重新对 HAL 进行编译。HAL 的部分将会放在设备的 /vendor 分区中,并且是由设备供应商(vendors)或 SOC 制造商来构建。这使得框架部分可以通过 OTA 方式更新,同时不需要重新编译 HAL。这种设计被称为Treble机制,从Android 8.0引入。

weixin_41028555的博客 6641

【ACP】2025-最新-疑难题解析- 练习二汇总

全球加速是优化公网访问的,负载均衡是分发流量的,公网 NAT 网关是处理公网 IP 的,高速通道是建私网连接但不直接提供固定私网地址功能。C 是客户端加密方式,D 是 ECS 云盘加密,都不属于 OSS 服务器端加密。某企业想使用云服务器 ECS + 负载均衡 SLB + 弹性伸缩 (Auto Scaling) 的架构搭建一个企业级门户网站,技术负责人对于负载均衡和弹性伸缩配合使用没有经验,于是将他理解的两种产品配合使用的一些技术细节列成了一个表单,并请作为架构师的您帮他做一下鉴别,以下哪些项是正确的?

jundao1997的专栏 293

拼多多笔试真题-多多送快递(C++/Py/Java /Js/Go)

拼多多技术岗笔试 8月2号真题,拼多多笔试第三题【多多送快递】,提供详细思路讲解以及Java、C++、Python、Go、JavaScript多语言代码实现。拼多多笔试真题【多多送快递】多语言题解。

qq_45776114的博客 291

创维E900-S-非高安-卡刷-刷机固件及教程

创维E900-S (3798MV100芯)非高安 卡刷 刷机固件及教程 固件特点: 1、不带ROOT权限,适用于电信E900-S 非高安版(CA)无线模块8188芯片 2、调出原厂固件屏蔽的wifi,开放原厂固件屏蔽的市场安装和u盘安装apk; 3、无开机广告,无系统更新,不在被强制升级;修改dns,三网通用; 4、大量精简内置的没用的软件,运行速度提升30%以上,多出大量的存储空间; 5、去除应用安装限制,实现自由安装软件; 6、固件压缩包有刷机教程,解压获取。 短接点提示:主芯

点我主页,可查看所有固件文章! 4万+

PMP第一章:引论介绍

PMP第一章:引论介绍 1.PMBOK指南概述和目的 项目管理标准 通用词汇 道德与专业行为规范 2.基本要素 项目 项目管理的重要性 项目、项目集、项目组合以及运营管理之间的关系 指南的组成部分 裁剪 项目管理商业文件 3.项目管理标准 标准是基于权威、惯例或共识而建立并用作模式或范例的文件。 标准确认了在大多数时候都被大多数项目视作良好实践的过程。 4.道德与专业行为规范 责任:对自己所做的决策或未做决策、所采取的行为或未采取行为,以及相应的后果,承担责任 尊重:对自己、他人和委托给自己的资源

zhengzaifeidelushang的博客 826

【android工具篇】Firefly-RK系列(eg:RK3288 RK3368)一键获取root权限工具RootUtils

问题描述 越来越多的智能设备使用到了Firefly的开发板(http://dev.t-firefly.com/forum.php),有时候android应用开发必须要获取root权限(如重启设备、静默升级app),一般厂家都会提供获取root权限的方式,但是总有人不知道如何获取root。 请尊重原创,转载需要注明出处,大力哥的博客:https://blog.csdn.net/qq1377...

大力哥的博客 1万+

微信小程序 - 实现人脸识别对比+人脸相似度数据,用户从相册选择或拍照上传两张图片进行人脸对比得到人脸相似度及判断是否是同一个人,微信小程序检测人脸相似度(免费纯前端方案+调用第三方API接口方案)

微信小程序实现人脸识别对比,微信小程序人脸对比 人脸对比识别 人脸对比相似度,实现获取手机摄像头权限,调用相机拍照实现人脸识别相似度对比,小程序人脸相似度对比,快速识别两张照片的相似程度(用百分比)图片相似度对比在线测试,图片相似度对比,微信小程序人脸相似度对比分析,计算两张人脸的相似度,从而判断是否同一个人,并给出相似度评分。小程序如何实现人脸相似度比对,小程序纯前端怎么对比两张图片的相似度,计算两幅图像的相似度,图像相似度对比方法,调用百度AI的人脸识别,微信小程序中实现人脸识别认证,实现人脸检测、人脸

🏆 前端领域优质创作者 4862

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Android IP路由策略和防火墙

ip route是用于配置路由器静态路由的命令,在Linux系统中,它是iproute2工具套件的一部分,用于操作路由表。ip route命令的功能非常强大,可以显示、添加、删除、修改路由,以及清除整个路由表或路由缓存。使用ip route时,可以对多达255个路由表中的任何一个进行操作,而route命令则主要在主路由表(表254)上运行。主要功能显示路由:通过命令可以查看当前的路由表信息。添加路由:使用命令可以添加新的路由条目。删除路由:通过命令可以删除路由表中的特定路由。修改路由。

dolphin的专栏 3万+

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

上一篇: rk3368 Android9.0 升级固件后,一直在recovery界面
下一篇: AP6236蓝牙BLE广播调试
D00PING
博客等级 码龄12年 96粉丝 48原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值