在本文中,我将详细介绍如何在 MTK 方案 Android 12 环境中,从初始配置到生成
[email protected]_intermediates/classes.jar
文件给应用调用INvram agent = INvram.getService();
的完整过程。
最开始想解决这个问题的原由,是因为想在AS里调用
INvram agent = INvram.getService();
,这个文件之前的版本是在,out\target\common\obj\JAVA_LIBRARIES\[email protected]_intermediates\classes.jar
,但是搜遍了out目录下没有,所以打算研究一下怎么生成。
1. 初始配置
首先,系统 NVRAM 源码在 vendor/mediatek/proprietary/hardware/interfaces/nvram/1.0
文件夹下有一个基本的 Android.bp
文件来描述 NVRAM 的 HAL 接口,并启用 Java 生成:
// This file is autogenerated by hidl-gen -Landroidbp.
hidl_interface {
name: "[email protected]",
root: "vendor.mediatek.hardware",
srcs: [
"INvram.hal",
],
interfaces: [
"[email protected]",
],
gen_java: true,
}
2. 生成 Java 文件
使用 hidl-gen
工具生成 Java 文件 INvram.java
:
hidl-gen -o ./gen -Ljava -r vendor.mediatek.hardware:vendor/mediatek/proprietary/hardware/interfaces [email protected]
执行上述命令后,生成的 Java 文件应位于 vendor/mediatek/proprietary/hardware/interfaces/nvram/1.0/gen/vendor/mediatek/hardware/nvram/V1_0
目录中。
3. 修改 Android.bp
文件
为确保生成的 Java 文件能够被打包成 JAR 文件,需要在 Android.bp
文件中添加 java_library
和 java_library_static
模块:
// 增加 java_library 的定义
java_library {
name: "[email protected]",
srcs: [
"gen/vendor/mediatek/hardware/nvram/V1_0/*.java",
],
sdk_version: "system_current",
static_libs: [
"android.hidl.base-V1.0-java",
"android.hidl.manager-V1.0-java",
],
}
// 增加 java_library_static 的定义
java_library_static {
name: "[email protected]",
srcs: [
"gen/vendor/mediatek/hardware/nvram/V1_0/*.java",
],
sdk_version: "system_current",
static_libs: [
"android.hidl.base-V1.0-java-static",
"android.hidl.manager-V1.0-java-static",
],
}
4. 编译
在修改完 Android.bp
文件后,清理编译环境并重新编译项目:
rm -rf out/target/common/obj/JAVA_LIBRARIES/[email protected]*
make [email protected]
make [email protected] // 不用编这个也可
5. 生成的输出
编译成功后,检查生成的 JAR 文件:
ls out/target/common/obj/JAVA_LIBRARIES/[email protected]_intermediates/classes.jar
ls out/soong/.intermediates/vendor/mediatek/proprietary/hardware/interfaces/nvram/1.0/[email protected]
输出目录中应包含以下内容:
[email protected] [email protected]
[email protected]_genc++ [email protected](新增)
[email protected]_genc++_headers [email protected](新增)
遇到的问题及解决方案
问题1
编译出 [email protected]_intermediates/classes.jar
后,放到 AS 准备调试接口时,遇到以下错误:
SNParamUtils.java:22: error: cannot access IHwInterface
INvram agent = INvram.getService();
^
class file for android.os.IHwInterface not found
提示找不到 IHwInterface.java
。在 Android 8.1 中,该文件位于 hwbinder_intermediates
目录中,而在 Android 12 中则使用 framework-minus-apex_intermediates
中的 classes.jar
。
解决方法
最开始的解决办法是,将 framework-minus-apex_intermediates
中的 classes.jar
和 [email protected]_intermediates
中的 classes.jar
同时拷入到 AS 项目中。后来决定将这些类打包成一个 classes.jar
,最终在 framework/base/Android.bp
增加一个名为 hwbinder
的 java_library
。
问题2
在编译 [email protected]
时,遇到以下错误:
make [email protected]
module [email protected] missing dependencies: android.hidl.base-V1.0-java-static
提示缺少 android.hidl.base-V1.0-java-static
依赖项。
解决方法
确保在 Android.bp
文件中正确引用并添加 android.hidl.base-V1.0-java-static
模块:
java_library_static {
name: "[email protected]",
srcs: [
"gen/vendor/mediatek/hardware/nvram/V1_0/*.java",
],
sdk_version: "system_current",
static_libs: [
"android.hidl.base-V1.0-java-static",
"android.hidl.manager-V1.0-java-static",
],
}
问题3
编译 hwbinder
模块时,遇到依赖文件缺失问题:
java_library {
name: "hwbinder",
srcs: [
"core/java/android/os/HidlSupport.java",
"core/java/android/annotation/NonNull.java",
"core/java/android/os/HwBinder.java",
"core/java/android/os/HwBlob.java",
"core/java/android/os/HwParcel.java",
"core/java/android/os/IHwBinder.java",
"core/java/android/os/IHwInterface.java",
"core/java/android/os/DeadObjectException.java",
"core/java/android/os/DeadSystemException.java",
"core/java/android/os/RemoteException.java",
"core/java/android/util/AndroidException.java",
],
sdk_version: "module_current", // 调整为 module_current
dxflags: ["--core-library"],
installable: false,
}
因为在编译名为 hwbinder
的 java_library
时,少了一些依赖文件导包,导致编译报错:
@NonNull
^
符号: 类 NonNull
位置: 类 RemoteException
frameworks/base/core/java/android/os/HwParcel.java:54: 错误: 找不到符号
@UnsupportedAppUsage
^
符号: 类 UnsupportedAppUsage
位置: 类 HwParcel
frameworks/base/core/java/android/os/HwParcel.java:141: 错误: 找不到符号
public native final void writeNativeHandle(@Nullable NativeHandle val);
^
符号: 类 Nullable
位置: 类 HwParcel
frameworks/base/core/java/android/os/HwParcel.java:314: 错误: 找不到符号
public final void writeNativeHandleVector(@NonNull ArrayList<NativeHandle> val) {
解决方法
找到这些文件,追加引用。假设 SystemApi.java
等文件位于 frameworks/libs/modules-utils/java/android/annotation/
目录中,设置相对路径。在 frameworks/base/Android.bp
文件中定义 hwbinder
模块:
// 在 frameworks/base/Android.bp 文件中定义 hwbinder 模块
java_library {
name: "hwbinder",
srcs: [
"core/java/android/os/HidlSupport.java",
"core/java/android/annotation/NonNull.java",
"core/java/android/os/HwBinder.java",
"core/java/android/os/HwBlob.java",
"core/java/android/os/HwParcel.java",
"core/java/android/os/IHwBinder.java",
"core/java/android/os/IHwInterface.java",
"core/java/android/os/DeadObjectException.java",
"core/java/android/os/DeadSystemException.java",
"core/java/android/os/RemoteException.java",
"core/java/android/util/AndroidException.java",
// 添加对 android.annotation 包的依赖
"../../libs/modules-utils/java/android/annotation/SystemApi.java",
"../../libs/modules-utils/java/android/annotation/NonNull.java",
"../../libs/modules-utils/java/android/annotation/Nullable.java",
"../../libs/modules-utils/java/android/compat/annotation/UnsupportedAppUsage.java",
],
sdk_version: "module_current",
dxflags: ["--core-library"],
installable: false,
}
继续编译,出现问题 4。
问题4
在编译过程中,遇到路径引用错误:
Path is outside directory: ../../libs/modules-utils/java/android/annotation/SystemApi.java
提示引用路径错误,路径不能在模块目录之外。
解决方法
使用 filegroup
来定义文件集合并引用这些文件:
-
在
frameworks/libs/modules-utils
中创建或更新Android.bp
filegroup { name: "modules-utils-annotation", srcs: [ "java/android/annotation/SystemApi.java", "java/android/annotation/NonNull.java", "java/android/annotation/Nullable.java", "java/android/annotation/IntDef.java", ], visibility: ["//frameworks/base"], // 设置可见性 }
-
更新
hwbinder
模块在
frameworks/base/Android.bp
文件中定义hwbinder
模块:java_library { name: "hwbinder", srcs: [ "core/java/android/os/HidlSupport.java", "core/java/android/os/HwBinder.java", "core/java/android/os/HwBlob.java", "core/java/android/os/HwParcel.java", "core/java/android/os/IHwBinder.java", "core/java/android/os/IHwInterface.java", "core/java/android/os/DeadObjectException.java", "core/java/android/os/DeadSystemException.java", "core/java/android/os/RemoteException.java", "core/java/android/util/AndroidException.java", ":modules-utils-annotation", // 引用 filegroup ], sdk_version: "module_current", dxflags: ["--core-library"], installable: false, }
继续编译,出现问题 5。
问题5
在编译过程中,遇到以下错误:
frameworks/base/core/java/android/os/HwBinder.java:20: 错误: 程序包 android.compat.annotation 不存在
import android.compat.annotation.UnsupportedAppUsage;
还需要创建一个包含 UnsupportedAppUsage
的 filegroup
并将其添加到 hwbinder
模块中来解决这个问题。但是文件位于 tools/platform-compat/java/android/compat/annotation/UnsupportedAppUsage.java
,只能在 tools/platform-compat/Android.mk
中增加一个名为 modules-utils-compat-annotation
的 java_library
。
解决方法
+++ b/tools/platform-compat/Android.mk
# 在 tools/platform-compat/Android.mk 文件中增加
LOCAL_PATH := $(call my-dir)
# 定义一个文件组
include $(CLEAR_VARS)
LOCAL_MODULE := modules-utils-compat-annotation
LOCAL_SRC_FILES := \
java/android/compat/annotation/UnsupportedAppUsage.java
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := JAVA_LIBRARIES
include $(BUILD_JAVA_LIBRARY)
问题6
在编译过程中,遇到以下错误:
tools/platform-compat/Android.mk: error: modules-utils-compat-annotation: Invalid LOCAL_SDK_VERSION 'module_current' Choices are: 10 11 12 13 14 15 16 17 18 19 20 21 22 23 system_23 24 25 26 27 28 system_28 29 system_29 test_29 30 system_30 test_30 31 system_31 test_31 4 5 6 7 8 9 core_current current system_current test_current
提示 LOCAL_SDK_VERSION
设置无效。
解决方法
确保在 Android.mk
文件中使用有效的 LOCAL_SDK_VERSION
。例如,可以使用 system_current
或其他有效值:
-
更新
Android.mk
文件# 在 tools/platform-compat/Android.mk 文件中 LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := modules-utils-compat-annotation LOCAL_SRC_FILES := \ java/android/compat/annotation/UnsupportedAppUsage.java LOCAL_MODULE_CLASS := JAVA_LIBRARIES LOCAL_SDK_VERSION := system_current include $(BUILD_JAVA_LIBRARY)
确保依赖模块的 sdk_version
一致,检查 modules-utils-compat-annotation
和 hwbinder
模块的 Android.bp
文件,确保它们的 sdk_version
与 hwbinder
一致。
问题7
在编译过程中遇到了一些问题,最终决定不使用 tools/platform-compat/Android.mk
添加 java_library
,而是引用现有的库。
解决方法
// 在 frameworks/base/Android.bp 文件中定义 hwbinder 模块
java_library {
name: "hwbinder",
srcs: [
"core/java/android/os/HidlSupport.java",
"core/java/android/os/HwBinder.java",
"core/java/android/os/HwBlob.java",
"core/java/android/os/HwParcel.java",
"core/java/android/os/IHwBinder.java",
"core/java/android/os/IHwInterface.java",
"core/java/android/os/DeadObjectException.java",
"core/java/android/os/DeadSystemException.java",
"core/java/android/os/RemoteException.java",
"core/java/android/util/AndroidException.java",
":modules-utils-annotation", // 引用 filegroup
// ":modules-utils-compat-annotation", // 引用新的 filegroup
],
libs: [
// 引用新的解决 UnsupportedAppUsage.java 报错问题
"app-compat-annotations",
"framework-updatable-stubs-module_libs_api",
"unsupportedappusage",
],
sdk_version: "module_current",
dxflags: ["--core-library"],
installable: false,
}
问题8
在调用 HAL 服务时遇到 NoSuchElementException
错误:
java.util.NoSuchElementException
at android.os.HwBinder.getService(Native Method)
at android.os.HwBinder.getService(HwBinder.java:81)
at vendor.mediatek.hardware.nvram.V1_0.INvram.getService(INvram.java:132)
提示未找到服务。
解决方法
单独编译了这些 JAR,放到 AS,但运行的系统没有更新到最新已包含这些 JAR 的固件系统,所以需要将系统升级到最新的固件。
总结
通过正确配置 Android.bp
文件,添加必要的依赖项,并清理和重新编译项目,成功生成了 [email protected]_intermediates/classes.jar
文件。这个文件可以提供给应用程序使用,从而实现与 NVRAM 相关的功能调用。这篇文章详细记录了从问题发现到解决的完整过程,希望对在 MTK Android 12 环境中进行类似开发的兄弟萌有所帮助。如果有更多问题,欢迎交流讨论。