添加系统级res资源包

<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 */
};

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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容