美文网首页
添加系统级res资源包

添加系统级res资源包

作者: 大天使之剑 | 来源:发表于2017-07-24 10:51 被阅读0次

    <br />
    刚做完自定义res资源包的配置,这里做一下关于在配置过程中出现的问题和解决方法作一下记录。

    资源的引用格式为:

    @包名:资源类型/资源名
    

    以framework资源为例:

    @android:style/Theme.Holo.Light
    

    这次需要配置与framework同级的资源包,以包名为"custemer"为例,配置完成后资源引用:

    @custemer:style/Theme.Holo.Light
    
    一、新建自定义资源包
    1. 在framework/base/core/下新建名为“res_custemer”文件夹,结构如下:
    image.png
    1. 编写Android.mk文件
    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    
    # include apicheck.mk later, we need the build pass to prepare the first version
    # include $(LOCAL_PATH)/apicheck.mk
    LOCAL_PACKAGE_NAME := custemer-res
    LOCAL_CERTIFICATE := platform
    LOCAL_AAPT_FLAGS := -x3
    
    # Tell aapt to build resource in utf16(the ROM will be enlarged),
    # in order to save RAM size for string cache table
    ifeq (yes,strip$(MTK_GMO_RAM_OPTIMIZE))
    LOCAL_AAPT_FLAGS += --utf16
    endif
    
    
    LOCAL_NO_CUSTEMERRES := true
    LOCAL_MODULE_TAGS := optional
    # Install this alongside the libraries.
    LOCAL_MODULE_PATH := $(TARGET_OUT_JAVA_LIBRARIES)
    # Create package-export.apk, which other packages can use to get
    # PRODUCT-agnostic resource data like IDs and type definitions.
    LOCAL_EXPORT_PACKAGE_RESOURCES := true
    include $(BUILD_PACKAGE)
    
    # define a global intermediate target that other module may depend on.
    .PHONY: gome-res-package-target
    gome-res-package-target: $(LOCAL_BUILT_MODULE)
    

    "LOCAL_AAPT_FLAGS := -x3 " value 的定义需要与 "frameworks\base\libs\androidfw\ResourceTypes.cpp"中 所定义的resource ID 一致

    1. 编写AndroidManifest.xml文件
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="custemer" coreApp="true" android:sharedUserId="android.uid.system"
        android:sharedUserLabel="@null">
    
        <eat-comment />
        <protected-broadcast android:name="android.intent.action.SCREEN_OFF" />
    
        <permission android:name="android.permission.ADVANCED_WIDGET_API"
                android:protectionLevel="normal" />
        
        <application android:process="system"
                     android:persistent="true"
                     android:hasCode="false"
                     android:label="@null"
                     android:allowClearUserData="false"
                     android:killAfterRestore="false"
                     android:icon="@null">
    
        </application>
    
    </manifest>
    

    "custemer" 为资源包名

    二、添加编译依赖关系
    
    framework_custemer_res_package_export :=
    framework_custemer_res_package_export_deps :=
    
    ifneq ($(LOCAL_PACKAGE_NAME), mediatek-res)
        framework_custemer_res_package_export += \
            $(call intermediates-dir-for,APPS,mediatek-res,,COMMON)/package-export.apk
        framework_custemer_res_package_export_deps += \
            $(call intermediates-dir-for,APPS,mediatek-res,,COMMON)/src/R.stamp
    
        ifneq ($(LOCAL_PACKAGE_NAME),custemer-res)
            framework_custemer_res_package_export += \
                $(call intermediates-dir-for,APPS,gome-res,,COMMON)/package-export.apk
            framework_custemer_res_package_export_deps += \
                $(call intermediates-dir-for,APPS,gome-res,,COMMON)/src/R.stamp
        endif
    endif
    
      # FIXME: Cannot set in Android.mk due to base_rules.mk
      #ifneq ($(LOCAL_PACKAGE_NAME),mediatek-res)
      #   LOCAL_RES_LIBRARIES += mediatek-res
      #endif
    ....
    $(filter-out $(framework_gome_res_package_export),$(resource_export_package)): $(framework_custemer_res_package_export_deps )
    $(R_file_stamp): $(framework_custemer_res_package_export_deps )
    
    $(resource_export_package) $(R_file_stamp) $(LOCAL_BUILT_MODULE): $(all_library_res_package_export_deps)
    $(LOCAL_INTERMEDIATE_TARGETS): \
        PRIVATE_AAPT_INCLUDES := $(all_library_res_package_exports) $(framework_custemer_res_package_export )
    
    

    将 mediatek-res与自定义资源模块名定义在一起,否则编译时会出现circle dependence的错误;
    将 framework_gome_res_package_export 添加进 PRIVATE_AAPT_INCLUDES 中,否则应用运行会报找不到资源的错误。

    三、将资源路径添加进framework编译

    路径: frameworks/base/Android.mk

    framework_res_source_path := APPS/framework-res_intermediates/src
    # M:add mediatek resource path
    mediatek-res-source-path := APPS/mediatek-res_intermediates/src
    gome_custemer_source_path := APPS/custemer-res_intermediates/src
    ...
    LOCAL_INTERMEDIATE_SOURCES := \
                $(framework_res_source_path)/android/R.java \
                $(framework_res_source_path)/android/Manifest.java \
                $(framework_res_source_path)/com/android/internal/R.java
    # M:add mediatek resource R.java into framework,@{
    LOCAL_INTERMEDIATE_SOURCES += \
                $(mediatek-res-source-path)/com/mediatek/internal/R.java \
                $(mediatek-res-source-path)/com/mediatek/R.java \
                $(mediatek-res-source-path)/com/mediatek/Manifest.java
    # @}
    
    # M:add custemer resource R.java into framework,@{
    LOCAL_INTERMEDIATE_SOURCES += \
                $(custemer_res_source_path)/com/gome/internal/R.java \
                $(custemer_res_source_path)/com/gome/R.java \
                $(custemer_res_source_path)/com/gome/Manifest.java
    # @}
    
    
    LOCAL_MODULE := framework
    
    # Make sure that R.java and Manifest.java are built before we build
    # the source for this library.
    framework_res_R_stamp := \
        $(call intermediates-dir-for,APPS,framework-res,,COMMON)/src/R.stamp
    $(full_classes_compiled_jar): $(framework_res_R_stamp)
    $(built_dex_intermediate): $(framework_res_R_stamp)
    # M:add mediatek resource dependes framework->mediatek_res->framework_res,@{
    mediatek_res_R_stamp := \
        $(call intermediates-dir-for,APPS,mediatek-res,,COMMON)/src/R.stamp
    $(full_classes_compiled_jar): $(mediatek_res_R_stamp)
    $(built_dex_intermediate): $(mediatek_res_R_stamp)
    custemer_res_R_stamp := \
        $(call intermediates-dir-for,APPS,custemer-res,,COMMON)/src/R.stamp
    $(full_classes_compiled_jar): $(custemer_res_R_stamp)
    $(built_dex_intermediate): $(custemer_res_R_stamp)
    # @}
    
    四、修改 PackageManagerService

    路径:frameworks\base\services\core\java\com\android\server\pm\PackageManagerService.java

       ApplicationInfo mAndroidApplication;
        /// M: [CIP] Add application info for mediatek-res.apk
       ApplicationInfo mMediatekApplication;
       ApplicationInfo mCustemerApplication;
    
       private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg,
                final int policyFlags, final int scanFlags, long currentTime, UserHandle user)
                throws PackageManagerException {    
                 /** M: [CIP] skip duplicated mediatek-res.apk @{ */
            /// This will replace original resources with CIP resources
            if (pkg.packageName.equals("com.mediatek")) {
                synchronized (mPackages) {
                    if (mMediatekApplication != null) {
                        Slog.w(TAG, "*************************************************");
                        Slog.w(TAG, "Core mediatek package being redefined.  Skipping.");
                        Slog.w(TAG, " file=" + scanFile);
                        Slog.w(TAG, "*************************************************");
                        throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE,
                                "Core android package being redefined.  Skipping.");
                    }
                    mMediatekApplication = pkg.applicationInfo;
                }
            }
            /** @} */
            if (pkg.packageName.equals("custemer")) {
                synchronized (mPackages) {
                    if (mCustemerApplication != null) {
                        Slog.w(TAG, "*************************************************");
                        Slog.w(TAG, "Core gome package being redefined.  Skipping.");
                        Slog.w(TAG, " file=" + scanFile);
                        Slog.w(TAG, "*************************************************");
                        throw new PackageManagerException(INSTALL_FAILED_DUPLICATE_PACKAGE,
                                "Core android package being redefined.  Skipping.");
                    }
                    mCustemerApplication = pkg.applicationInfo;
                }
            }
      }
    
    五、预置自定义资源包

    目录:device/mediatek/common/device.mk

    # for mediatek-res
    PRODUCT_PACKAGES += mediatek-res
    
    # for custemer-res
    PRODUCT_PACKAGES += custemer-res
    
    六、修改资源管理器 Assetmanager.cpp

    目录:framework/base/libs/androidfw/AssetManager.cpp

    ///M:add the resource path
    static const char* kMediatekAssets = "/vendor/framework/mediatek-res/mediatek-res.apk";
    ///M:add the resource path
    static const char* kCustemerAssets = "framework/custemer-res/custemer-res.apk";
    
    bool AssetManager::addDefaultAssets()
    {
        const char* root = getenv("ANDROID_ROOT");
        LOG_ALWAYS_FATAL_IF(root == NULL, "ANDROID_ROOT not set");
    
        ...
        if((fp= fopen(pathCip,"w+"))!= NULL) {
           .....
           return isOK1;
        } else {
           //ALOGD("AssetManager-->addDefaultAssets CIP path not exsit!");
           String8 path(root);
           path.appendPath(kSystemAssets);
           ///M:add the new resource path into default path,so all the app can reference,@{
           bool isOK1 = addAssetPath(path, NULL, false /* appAsLib */, true /* isSystemAsset */);
           String8 path2(kMediatekAssets);
           bool isOK2 = addAssetPath(path2, NULL, false, false);
    
           String8 path3(root);
           path3.appendPath(kCustemerAssets);
           bool isOK3 =addAssetPath(path3, NULL, false, false);
           if(!isOK3){
                ALOGW("AssetManager-->addDefaultAssets isok3 is false");
           }else{
                ALOGW("AssetManager-->addDefaultAssets isok3 is true");
           }
    

    将自定义资源apk添加进系统资源管理器,当应用使用自定义资源id查找资源时,会通过AssetManager来查找。如果这里写错会导致会先各种问题。以字符串为例,当应用通过R.strings.xxx来查找字符串时,由于AssetManager无法返回正确的资源,默认会返回资源的id值。

    六、修改 ResourceTypes.cpp,添加对应的package id
    #define APP_PACKAGE_ID      0x7f
    #define SYS_MTK_PACKAGE_ID  0x08 /// M: 0x08 is mediatek-res.apk resource ID
    #define SYS_CUSTEMER_PACKAGE_ID  0x03 // 0x03 is gome-res.apk resource ID
    #define SYS_PACKAGE_ID      0x01
    
    bool ResTable::stringToValue(Res_value* outValue, String16* outString,
                                 const char16_t* s, size_t len,
                                 bool preserveSpaces, bool coerceType,
                                 uint32_t attrID,
                                 const String16* defType,
                                 const String16* defPackage,
                                 Accessor* accessor,
                                 void* accessorCookie,
                                 uint32_t attrType,
                                 bool enforcePrivate) const
    {
        if (*s == '@') {
            ....
          
        } else {
            if (rid != 0) {
                    uint32_t packageId = Res_GETPACKAGE(rid) + 1;
                    if (packageId != APP_PACKAGE_ID && packageId != SYS_PACKAGE_ID && packageId != SYS_MTK_PACKAGE_ID && packageId != SYS_CUSTEMER_PACKAGE_ID) {
                        outValue->dataType = Res_value::TYPE_DYNAMIC_REFERENCE;
                    }
                    outValue->data = rid;
                    return true;
                }
    
                if (accessor) {
                    uint32_t rid = accessor->getCustomResourceWithCreation(package, type, name,
                                                                           createIfNotFound);
                    if (rid != 0) {
                        if (kDebugTableNoisy) {
                            ALOGI("Pckg %s:%s/%s: 0x%08x\n",
                                    String8(package).string(), String8(type).string(),
                                    String8(name).string(), rid);
                        }
                        uint32_t packageId = Res_GETPACKAGE(rid) + 1;
                        if (packageId == 0x00) {
                            outValue->data = rid;
                            outValue->dataType = Res_value::TYPE_DYNAMIC_REFERENCE;
                            return true;
                        } else if (packageId == APP_PACKAGE_ID || packageId == SYS_PACKAGE_ID || packageId == SYS_MTK_PACKAGE_ID || packageId == SYS_CUSTEMER_PACKAGE_ID) {
                            // We accept packageId's generated as 0x01 in order to support
                            // building the android system resources
                            outValue->data = rid;
                            return true;
                        }
                    }
                }
        }
    
    DynamicRefTable::DynamicRefTable(uint8_t packageId, bool appAsLib)
        : mAssignedPackageId(packageId)
        , mAppAsLib(appAsLib)
    {
        memset(mLookupTable, 0, sizeof(mLookupTable));
    
        // Reserved package ids
        mLookupTable[APP_PACKAGE_ID] = APP_PACKAGE_ID;
        mLookupTable[SYS_PACKAGE_ID] = SYS_PACKAGE_ID;
        mLookupTable[SYS_MTK_PACKAGE_ID] = SYS_MTK_PACKAGE_ID;
        mLookupTable[SYS_CUSTEMER_PACKAGE_ID] = SYS_CUSTEMER_PACKAGE_ID;
    }
    
    }
    

    SYS_CUSTEMER_PACKAGE_ID 需要对应与自定义模块mk文件的 LOCAL_AAPT_FLAGS

    七、将资源apk路径添加进白名单

    路径:frameworks/base/core/jni

    static const char* kPathWhitelist[] = {
      "/dev/null",
      "/dev/socket/zygote",
      "/dev/socket/zygote_secondary",
      "/system/etc/event-log-tags",
      "/sys/kernel/debug/tracing/trace_marker",
      "/system/framework/framework-res.apk",
      "/dev/urandom",
      "/dev/ion",
      "/dev/dri/renderD129", // Fixes b/31172436
      "/proc/ged", // MTK add
      "/system/vendor/framework/mediatek-res/mediatek-res.apk", // MTK add
      "/system/framework/custemer-res/custemer-res.apk" /* XXX add */
    };
    

    修改的目的是为了通过开机的检查,否则无法开机。

    关于如何使用,就不作记录了。

    相关文章

      网友评论

          本文标题:添加系统级res资源包

          本文链接:https://www.haomeiwen.com/subject/athekxtx.html