diff options
author | Jean-Baptiste Queru <jbq@google.com> | 2009-07-21 11:16:54 -0700 |
---|---|---|
committer | Jean-Baptiste Queru <jbq@google.com> | 2009-07-21 11:16:54 -0700 |
commit | cf4550c3198d6b3d92cdc52707fe70d7cc0caa9f (patch) | |
tree | 6510f35ad004f1a4640b48264c290926e8596d7a /tools | |
parent | 4cf03d381b2dff908857fceff0bec445f8d44f36 (diff) | |
download | frameworks_base-cf4550c3198d6b3d92cdc52707fe70d7cc0caa9f.zip frameworks_base-cf4550c3198d6b3d92cdc52707fe70d7cc0caa9f.tar.gz frameworks_base-cf4550c3198d6b3d92cdc52707fe70d7cc0caa9f.tar.bz2 |
donut snapshot
Diffstat (limited to 'tools')
25 files changed, 940 insertions, 220 deletions
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp index 6bc1ee6..67af116 100644 --- a/tools/aapt/AaptAssets.cpp +++ b/tools/aapt/AaptAssets.cpp @@ -187,6 +187,13 @@ AaptGroupEntry::parseNamePart(const String8& part, int* axis, uint32_t* value) return 0; } + // screen layout + if (getScreenLayoutName(part.string(), &config)) { + *axis = AXIS_SCREENLAYOUT; + *value = config.screenLayout; + return 0; + } + // version if (getVersionName(part.string(), &config)) { *axis = AXIS_VERSION; @@ -202,7 +209,7 @@ AaptGroupEntry::initFromDirName(const char* dir, String8* resType) { Vector<String8> parts; - String8 mcc, mnc, loc, orient, den, touch, key, keysHidden, nav, size, vers; + String8 mcc, mnc, loc, orient, den, touch, key, keysHidden, nav, size, layout, vers; const char *p = dir; const char *q; @@ -378,6 +385,18 @@ AaptGroupEntry::initFromDirName(const char* dir, String8* resType) //printf("not screen size: %s\n", part.string()); } + if (getScreenLayoutName(part.string())) { + layout = part; + + index++; + if (index == N) { + goto success; + } + part = parts[index]; + } else { + //printf("not screen layout: %s\n", part.string()); + } + if (getVersionName(part.string())) { vers = part; @@ -404,6 +423,7 @@ success: this->keyboard = key; this->navigation = nav; this->screenSize = size; + this->screenLayout = layout; this->version = vers; // what is this anyway? @@ -435,6 +455,8 @@ AaptGroupEntry::toString() const s += ","; s += screenSize; s += ","; + s += screenLayout; + s += ","; s += version; return s; } @@ -483,6 +505,10 @@ AaptGroupEntry::toDirName(const String8& resType) const s += "-"; s += screenSize; } + if (this->screenLayout != "") { + s += "-"; + s += screenLayout; + } if (this->version != "") { s += "-"; s += version; @@ -786,6 +812,26 @@ bool AaptGroupEntry::getScreenSizeName(const char* name, return true; } +bool AaptGroupEntry::getScreenLayoutName(const char* name, + ResTable_config* out) +{ + if (strcmp(name, kWildcardName) == 0) { + if (out) out->screenLayout = out->SCREENLAYOUT_ANY; + return true; + } else if (strcmp(name, "smallscreen") == 0) { + if (out) out->screenLayout = out->SCREENLAYOUT_SMALL; + return true; + } else if (strcmp(name, "normalscreen") == 0) { + if (out) out->screenLayout = out->SCREENLAYOUT_NORMAL; + return true; + } else if (strcmp(name, "largescreen") == 0) { + if (out) out->screenLayout = out->SCREENLAYOUT_LARGE; + return true; + } + + return false; +} + bool AaptGroupEntry::getVersionName(const char* name, ResTable_config* out) { @@ -828,6 +874,7 @@ int AaptGroupEntry::compare(const AaptGroupEntry& o) const if (v == 0) v = keyboard.compare(o.keyboard); if (v == 0) v = navigation.compare(o.navigation); if (v == 0) v = screenSize.compare(o.screenSize); + if (v == 0) v = screenLayout.compare(o.screenLayout); if (v == 0) v = version.compare(o.version); return v; } @@ -846,6 +893,7 @@ ResTable_config AaptGroupEntry::toParams() const getKeyboardName(keyboard.string(), ¶ms); getNavigationName(navigation.string(), ¶ms); getScreenSizeName(screenSize.string(), ¶ms); + getScreenLayoutName(screenLayout.string(), ¶ms); getVersionName(version.string(), ¶ms); return params; } diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h index 01c8140..3b96412 100644 --- a/tools/aapt/AaptAssets.h +++ b/tools/aapt/AaptAssets.h @@ -37,6 +37,7 @@ enum { AXIS_KEYBOARD, AXIS_NAVIGATION, AXIS_SCREENSIZE, + AXIS_SCREENLAYOUT, AXIS_VERSION }; @@ -62,6 +63,7 @@ public: String8 keyboard; String8 navigation; String8 screenSize; + String8 screenLayout; String8 version; bool initFromDirName(const char* dir, String8* resType); @@ -78,6 +80,7 @@ public: static bool getKeyboardName(const char* name, ResTable_config* out = NULL); static bool getNavigationName(const char* name, ResTable_config* out = NULL); static bool getScreenSizeName(const char* name, ResTable_config* out = NULL); + static bool getScreenLayoutName(const char* name, ResTable_config* out = NULL); static bool getVersionName(const char* name, ResTable_config* out = NULL); int compare(const AaptGroupEntry& o) const; diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h index 2d8471b..a6fedf3 100644 --- a/tools/aapt/Bundle.h +++ b/tools/aapt/Bundle.h @@ -34,10 +34,13 @@ public: mForce(false), mGrayscaleTolerance(0), mMakePackageDirs(false), mUpdate(false), mExtending(false), mRequireLocalization(false), mPseudolocalize(false), + mValues(false), mCompressionMethod(0), mOutputAPKFile(NULL), mAssetSourceDir(NULL), mAndroidManifestFile(NULL), mPublicOutputFile(NULL), mRClassDir(NULL), mResourceIntermediatesDir(NULL), + mMinSdkVersion(NULL), mTargetSdkVersion(NULL), mMaxSdkVersion(NULL), + mVersionCode(NULL), mVersionName(NULL), mArgc(0), mArgv(NULL) {} ~Bundle(void) {} @@ -70,6 +73,8 @@ public: void setRequireLocalization(bool val) { mRequireLocalization = val; } bool getPseudolocalize(void) const { return mPseudolocalize; } void setPseudolocalize(bool val) { mPseudolocalize = val; } + bool getValues(void) const { return mValues; } + void setValues(bool val) { mValues = val; } int getCompressionMethod(void) const { return mCompressionMethod; } void setCompressionMethod(int val) { mCompressionMethod = val; } const char* getOutputAPKFile() const { return mOutputAPKFile; } @@ -99,6 +104,17 @@ public: const android::Vector<const char*>& getNoCompressExtensions() const { return mNoCompressExtensions; } void addNoCompressExtension(const char* ext) { mNoCompressExtensions.add(ext); } + const char* getMinSdkVersion() const { return mMinSdkVersion; } + void setMinSdkVersion(const char* val) { mMinSdkVersion = val; } + const char* getTargetSdkVersion() const { return mTargetSdkVersion; } + void setTargetSdkVersion(const char* val) { mTargetSdkVersion = val; } + const char* getMaxSdkVersion() const { return mMaxSdkVersion; } + void setMaxSdkVersion(const char* val) { mMaxSdkVersion = val; } + const char* getVersionCode() const { return mVersionCode; } + void setVersionCode(const char* val) { mVersionCode = val; } + const char* getVersionName() const { return mVersionName; } + void setVersionName(const char* val) { mVersionName = val; } + /* * Set and get the file specification. * @@ -138,6 +154,7 @@ private: bool mExtending; bool mRequireLocalization; bool mPseudolocalize; + bool mValues; int mCompressionMethod; const char* mOutputAPKFile; const char* mAssetSourceDir; @@ -151,6 +168,12 @@ private: android::Vector<const char*> mNoCompressExtensions; android::Vector<const char*> mResourceSourceDirs; + const char* mMinSdkVersion; + const char* mTargetSdkVersion; + const char* mMaxSdkVersion; + const char* mVersionCode; + const char* mVersionName; + /* file specification */ int mArgc; char* const* mArgv; diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp index 6f3461d..e04491d 100644 --- a/tools/aapt/Command.cpp +++ b/tools/aapt/Command.cpp @@ -196,7 +196,7 @@ int doList(Bundle* bundle) printf("\nNo resource table found.\n"); } else { printf("\nResource table:\n"); - res.print(); + res.print(false); } Asset* manifestAsset = assets.openNonAsset("AndroidManifest.xml", @@ -268,17 +268,19 @@ static String8 getAttribute(const ResXMLTree& tree, uint32_t attrRes, String8* o return str ? String8(str, len) : String8(); } -static int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes, String8* outError) +static int32_t getIntegerAttribute(const ResXMLTree& tree, uint32_t attrRes, + String8* outError, int32_t defValue = -1) { ssize_t idx = indexOfAttribute(tree, attrRes); if (idx < 0) { - return -1; + return defValue; } Res_value value; if (tree.getAttributeValue(idx, &value) != NO_ERROR) { - if (value.dataType != Res_value::TYPE_INT_DEC) { + if (value.dataType < Res_value::TYPE_FIRST_INT + || value.dataType > Res_value::TYPE_LAST_INT) { if (outError != NULL) *outError = "attribute is not an integer value"; - return -1; + return defValue; } } return value.data; @@ -318,7 +320,18 @@ enum { VERSION_NAME_ATTR = 0x0101021c, LABEL_ATTR = 0x01010001, ICON_ATTR = 0x01010002, - MIN_SDK_VERSION_ATTR = 0x0101020c + MIN_SDK_VERSION_ATTR = 0x0101020c, + REQ_TOUCH_SCREEN_ATTR = 0x01010227, + REQ_KEYBOARD_TYPE_ATTR = 0x01010228, + REQ_HARD_KEYBOARD_ATTR = 0x01010229, + REQ_NAVIGATION_ATTR = 0x0101022a, + REQ_FIVE_WAY_NAV_ATTR = 0x01010232, + TARGET_SDK_VERSION_ATTR = 0x01010270, + TEST_ONLY_ATTR = 0x01010272, + DENSITY_ATTR = 0x0101026c, + SMALL_SCREEN_ATTR = 0x01010284, + NORMAL_SCREEN_ATTR = 0x01010285, + LARGE_SCREEN_ATTR = 0x01010286, }; const char *getComponentName(String8 &pkgName, String8 &componentName) { @@ -357,7 +370,8 @@ int doDump(Bundle* bundle) const char* filename = bundle->getFileSpecEntry(1); AssetManager assets; - if (!assets.addAssetPath(String8(filename), NULL)) { + void* assetsCookie; + if (!assets.addAssetPath(String8(filename), &assetsCookie)) { fprintf(stderr, "ERROR: dump failed because assets could not be loaded\n"); return 1; } @@ -369,7 +383,7 @@ int doDump(Bundle* bundle) } if (strcmp("resources", option) == 0) { - res.print(); + res.print(bundle->getValues()); } else if (strcmp("xmltree", option) == 0) { if (bundle->getFileSpecCount() < 3) { @@ -488,6 +502,10 @@ int doDump(Bundle* bundle) bool isLauncherActivity = false; bool withinApplication = false; bool withinReceiver = false; + int targetSdk = 0; + int smallScreen = 1; + int normalScreen = 1; + int largeScreen = 1; String8 pkg; String8 activityName; String8 activityLabel; @@ -543,15 +561,90 @@ int doDump(Bundle* bundle) goto bail; } printf("icon='%s'\n", icon.string()); - } else if (tag == "uses-sdk") { - int32_t sdkVersion = getIntegerAttribute(tree, MIN_SDK_VERSION_ATTR, &error); + int32_t testOnly = getIntegerAttribute(tree, TEST_ONLY_ATTR, &error, 0); if (error != "") { - fprintf(stderr, "ERROR getting 'android:minSdkVersion' attribute: %s\n", error.string()); + fprintf(stderr, "ERROR getting 'android:testOnly' attribute: %s\n", error.string()); goto bail; } - if (sdkVersion != -1) { - printf("sdkVersion:'%d'\n", sdkVersion); + if (testOnly != 0) { + printf("testOnly='%d'\n", testOnly); + } + } else if (tag == "uses-sdk") { + int32_t code = getIntegerAttribute(tree, MIN_SDK_VERSION_ATTR, &error); + if (error != "") { + error = ""; + String8 name = getResolvedAttribute(&res, tree, MIN_SDK_VERSION_ATTR, &error); + if (error != "") { + fprintf(stderr, "ERROR getting 'android:minSdkVersion' attribute: %s\n", + error.string()); + goto bail; + } + if (name == "Donut") targetSdk = 4; + printf("sdkVersion:'%s'\n", name.string()); + } else if (code != -1) { + targetSdk = code; + printf("sdkVersion:'%d'\n", code); + } + code = getIntegerAttribute(tree, TARGET_SDK_VERSION_ATTR, &error); + if (error != "") { + error = ""; + String8 name = getResolvedAttribute(&res, tree, TARGET_SDK_VERSION_ATTR, &error); + if (error != "") { + fprintf(stderr, "ERROR getting 'android:targetSdkVersion' attribute: %s\n", + error.string()); + goto bail; + } + if (name == "Donut" && targetSdk < 4) targetSdk = 4; + printf("targetSdkVersion:'%s'\n", name.string()); + } else if (code != -1) { + if (targetSdk < code) { + targetSdk = code; + } + printf("targetSdkVersion:'%d'\n", code); + } + } else if (tag == "uses-configuration") { + int32_t reqTouchScreen = getIntegerAttribute(tree, + REQ_TOUCH_SCREEN_ATTR, NULL, 0); + int32_t reqKeyboardType = getIntegerAttribute(tree, + REQ_KEYBOARD_TYPE_ATTR, NULL, 0); + int32_t reqHardKeyboard = getIntegerAttribute(tree, + REQ_HARD_KEYBOARD_ATTR, NULL, 0); + int32_t reqNavigation = getIntegerAttribute(tree, + REQ_NAVIGATION_ATTR, NULL, 0); + int32_t reqFiveWayNav = getIntegerAttribute(tree, + REQ_FIVE_WAY_NAV_ATTR, NULL, 0); + printf("uses-configuation:"); + if (reqTouchScreen != 0) { + printf(" reqTouchScreen='%d'", reqTouchScreen); + } + if (reqKeyboardType != 0) { + printf(" reqKeyboardType='%d'", reqKeyboardType); + } + if (reqHardKeyboard != 0) { + printf(" reqHardKeyboard='%d'", reqHardKeyboard); + } + if (reqNavigation != 0) { + printf(" reqNavigation='%d'", reqNavigation); + } + if (reqFiveWayNav != 0) { + printf(" reqFiveWayNav='%d'", reqFiveWayNav); + } + printf("\n"); + } else if (tag == "supports-density") { + int32_t dens = getIntegerAttribute(tree, DENSITY_ATTR, &error); + if (error != "") { + fprintf(stderr, "ERROR getting 'android:density' attribute: %s\n", + error.string()); + goto bail; } + printf("supports-density:'%d'\n", dens); + } else if (tag == "supports-screens") { + smallScreen = getIntegerAttribute(tree, + SMALL_SCREEN_ATTR, NULL, 1); + normalScreen = getIntegerAttribute(tree, + NORMAL_SCREEN_ATTR, NULL, 1); + largeScreen = getIntegerAttribute(tree, + LARGE_SCREEN_ATTR, NULL, 1); } } else if (depth == 3 && withinApplication) { withinActivity = false; @@ -592,18 +685,18 @@ int doDump(Bundle* bundle) } } } else if (depth == 5) { - if (withinActivity) { - if (tag == "action") { - //printf("LOG: action tag\n"); - String8 action = getAttribute(tree, NAME_ATTR, &error); - if (error != "") { - fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", error.string()); - goto bail; - } - if (action == "android.intent.action.MAIN") { - isMainActivity = true; - //printf("LOG: isMainActivity==true\n"); - } + if (withinActivity) { + if (tag == "action") { + //printf("LOG: action tag\n"); + String8 action = getAttribute(tree, NAME_ATTR, &error); + if (error != "") { + fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", error.string()); + goto bail; + } + if (action == "android.intent.action.MAIN") { + isMainActivity = true; + //printf("LOG: isMainActivity==true\n"); + } } else if (tag == "category") { String8 category = getAttribute(tree, NAME_ATTR, &error); if (error != "") { @@ -659,11 +752,31 @@ int doDump(Bundle* bundle) activityIcon.string()); } } + + // Determine default values for any unspecified screen sizes, + // based on the target SDK of the package. As of 4 (donut) + // the screen size support was introduced, so all default to + // enabled. + if (smallScreen > 0) { + smallScreen = targetSdk >= 4 ? -1 : 0; + } + if (normalScreen > 0) { + normalScreen = -1; + } + if (largeScreen > 0) { + largeScreen = targetSdk >= 4 ? -1 : 0; + } + printf("supports-screens:"); + if (smallScreen != 0) printf(" 'small'"); + if (normalScreen != 0) printf(" 'normal'"); + if (largeScreen != 0) printf(" 'large'"); + printf("\n"); + printf("locales:"); Vector<String8> locales; res.getLocales(&locales); - const size_t N = locales.size(); - for (size_t i=0; i<N; i++) { + const size_t NL = locales.size(); + for (size_t i=0; i<NL; i++) { const char* localeStr = locales[i].string(); if (localeStr == NULL || strlen(localeStr) == 0) { localeStr = "--_--"; @@ -671,6 +784,35 @@ int doDump(Bundle* bundle) printf(" '%s'", localeStr); } printf("\n"); + + Vector<ResTable_config> configs; + res.getConfigurations(&configs); + SortedVector<int> densities; + const size_t NC = configs.size(); + for (size_t i=0; i<NC; i++) { + int dens = configs[i].density; + if (dens == 0) dens = 160; + densities.add(dens); + } + + printf("densities:"); + const size_t ND = densities.size(); + for (size_t i=0; i<ND; i++) { + printf(" '%d'", densities[i]); + } + printf("\n"); + + AssetDir* dir = assets.openNonAssetDir(assetsCookie, "lib"); + if (dir != NULL) { + if (dir->getFileCount() > 0) { + printf("native-code:"); + for (size_t i=0; i<dir->getFileCount(); i++) { + printf(" '%s'", dir->getFileName(i).string()); + } + printf("\n"); + } + delete dir; + } } else if (strcmp("configurations", option) == 0) { Vector<ResTable_config> configs; res.getConfigurations(&configs); diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp index 71b1a3c..12a0445 100644 --- a/tools/aapt/Main.cpp +++ b/tools/aapt/Main.cpp @@ -45,7 +45,7 @@ void usage(void) " %s l[ist] [-v] [-a] file.{zip,jar,apk}\n" " List contents of Zip-compatible archive.\n\n", gProgName); fprintf(stderr, - " %s d[ump] WHAT file.{apk} [asset [asset ...]]\n" + " %s d[ump] [--values] WHAT file.{apk} [asset [asset ...]]\n" " badging Print the label and icon for the app declared in APK.\n" " permissions Print the permissions from the APK.\n" " resources Print the resource table from the APK.\n" @@ -54,9 +54,10 @@ void usage(void) " xmlstrings Print the strings of the given compiled xml assets.\n\n", gProgName); fprintf(stderr, " %s p[ackage] [-d][-f][-m][-u][-v][-x][-z][-M AndroidManifest.xml] \\\n" - " [-0 extension [-0 extension ...]] \\\n" - " [-g tolerance] \\\n" - " [-j jarfile] \\\n" + " [-0 extension [-0 extension ...]] [-g tolerance] [-j jarfile] \\\n" + " [--min-sdk-version VAL] [--target-sdk-version VAL] \\\n" + " [--max-sdk-version VAL] [--app-version VAL] \\\n" + " [--app-version-name TEXT] \\\n" " [-I base-package [-I base-package ...]] \\\n" " [-A asset-source-dir] [-P public-definitions-file] \\\n" " [-S resource-sources [-S resource-sources ...]] " @@ -115,7 +116,19 @@ void usage(void) " and the first match found (left to right) will take precedence." " -0 specifies an additional extension for which such files will not\n" " be stored compressed in the .apk. An empty string means to not\n" - " compress any files at all.\n"); + " compress any files at all.\n" + " --min-sdk-version\n" + " inserts android:minSdkVersion in to manifest.\n" + " --target-sdk-version\n" + " inserts android:targetSdkVersion in to manifest.\n" + " --max-sdk-version\n" + " inserts android:maxSdkVersion in to manifest.\n" + " --values\n" + " when used with \"dump resources\" also includes resource values.\n" + " --version-code\n" + " inserts android:versionCode in to manifest.\n" + " --version-name\n" + " inserts android:versionName in to manifest.\n"); } /* @@ -339,6 +352,61 @@ int main(int argc, char* const argv[]) bundle.setCompressionMethod(ZipEntry::kCompressStored); } break; + case '-': + if (strcmp(cp, "-min-sdk-version") == 0) { + argc--; + argv++; + if (!argc) { + fprintf(stderr, "ERROR: No argument supplied for '--min-sdk-version' option\n"); + wantUsage = true; + goto bail; + } + bundle.setMinSdkVersion(argv[0]); + } else if (strcmp(cp, "-target-sdk-version") == 0) { + argc--; + argv++; + if (!argc) { + fprintf(stderr, "ERROR: No argument supplied for '--target-sdk-version' option\n"); + wantUsage = true; + goto bail; + } + bundle.setTargetSdkVersion(argv[0]); + } else if (strcmp(cp, "-max-sdk-version") == 0) { + argc--; + argv++; + if (!argc) { + fprintf(stderr, "ERROR: No argument supplied for '--max-sdk-version' option\n"); + wantUsage = true; + goto bail; + } + bundle.setMaxSdkVersion(argv[0]); + } else if (strcmp(cp, "-version-code") == 0) { + argc--; + argv++; + if (!argc) { + fprintf(stderr, "ERROR: No argument supplied for '--version-code' option\n"); + wantUsage = true; + goto bail; + } + bundle.setVersionCode(argv[0]); + } else if (strcmp(cp, "-version-name") == 0) { + argc--; + argv++; + if (!argc) { + fprintf(stderr, "ERROR: No argument supplied for '--version-name' option\n"); + wantUsage = true; + goto bail; + } + bundle.setVersionName(argv[0]); + } else if (strcmp(cp, "-values") == 0) { + bundle.setValues(true); + } else { + fprintf(stderr, "ERROR: Unknown option '-%s'\n", cp); + wantUsage = true; + goto bail; + } + cp += strlen(cp) - 1; + break; default: fprintf(stderr, "ERROR: Unknown flag '-%c'\n", *cp); wantUsage = true; diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp index b2bd9ff..027e3ab 100644 --- a/tools/aapt/Resource.cpp +++ b/tools/aapt/Resource.cpp @@ -433,7 +433,7 @@ static void checkForIds(const String8& path, ResXMLParser& parser) } } -static void applyFileOverlay(const sp<AaptAssets>& assets, +static bool applyFileOverlay(const sp<AaptAssets>& assets, const sp<ResourceTypeSet>& baseSet, const char *resType) { @@ -441,7 +441,7 @@ static void applyFileOverlay(const sp<AaptAssets>& assets, // Also add any found only in the overlay. sp<AaptAssets> overlay = assets->getOverlay(); String8 resTypeString(resType); - + // work through the linked list of overlays while (overlay.get()) { KeyedVector<String8, sp<ResourceTypeSet> >* overlayRes = overlay->getResources(); @@ -456,7 +456,7 @@ static void applyFileOverlay(const sp<AaptAssets>& assets, size_t overlayCount = overlaySet->size(); for (size_t overlayIndex=0; overlayIndex<overlayCount; overlayIndex++) { size_t baseIndex = baseSet->indexOfKey(overlaySet->keyAt(overlayIndex)); - if (baseIndex != UNKNOWN_ERROR) { + if (baseIndex < UNKNOWN_ERROR) { // look for same flavor. For a given file (strings.xml, for example) // there may be a locale specific or other flavors - we want to match // the same flavor. @@ -482,9 +482,10 @@ static void applyFileOverlay(const sp<AaptAssets>& assets, } } else { // this group doesn't exist (a file that's only in the overlay) - // add it - baseSet->add(overlaySet->keyAt(overlayIndex), - overlaySet->valueAt(overlayIndex)); + fprintf(stderr, "aapt: error: " + "*** Resource file '%s' exists only in an overlay\n", + overlaySet->keyAt(overlayIndex).string()); + return false; } } // this overlay didn't have resources for this type @@ -492,7 +493,59 @@ static void applyFileOverlay(const sp<AaptAssets>& assets, // try next overlay overlay = overlay->getOverlay(); } - return; + return true; +} + +void addTagAttribute(const sp<XMLNode>& node, const char* ns8, + const char* attr8, const char* value) +{ + if (value == NULL) { + return; + } + + const String16 ns(ns8); + const String16 attr(attr8); + + if (node->getAttribute(ns, attr) != NULL) { + fprintf(stderr, "Warning: AndroidManifest.xml already defines %s (in %s)\n", + String8(attr).string(), String8(ns).string()); + return; + } + + node->addAttribute(ns, attr, String16(value)); +} + +status_t massageManifest(Bundle* bundle, sp<XMLNode> root) +{ + root = root->searchElement(String16(), String16("manifest")); + if (root == NULL) { + fprintf(stderr, "No <manifest> tag.\n"); + return UNKNOWN_ERROR; + } + + addTagAttribute(root, RESOURCES_ANDROID_NAMESPACE, "versionCode", + bundle->getVersionCode()); + addTagAttribute(root, RESOURCES_ANDROID_NAMESPACE, "versionName", + bundle->getVersionName()); + + if (bundle->getMinSdkVersion() != NULL + || bundle->getTargetSdkVersion() != NULL + || bundle->getMaxSdkVersion() != NULL) { + sp<XMLNode> vers = root->getChildElement(String16(), String16("uses-sdk")); + if (vers == NULL) { + vers = XMLNode::newElement(root->getFilename(), String16(), String16("uses-sdk")); + root->insertChildAt(vers, 0); + } + + addTagAttribute(vers, RESOURCES_ANDROID_NAMESPACE, "minSdkVersion", + bundle->getMinSdkVersion()); + addTagAttribute(vers, RESOURCES_ANDROID_NAMESPACE, "targetSdkVersion", + bundle->getTargetSdkVersion()); + addTagAttribute(vers, RESOURCES_ANDROID_NAMESPACE, "maxSdkVersion", + bundle->getMaxSdkVersion()); + } + + return NO_ERROR; } #define ASSIGN_IT(n) \ @@ -566,13 +619,15 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets) current = current->getOverlay(); } // apply the overlay files to the base set - applyFileOverlay(assets, drawables, "drawable"); - applyFileOverlay(assets, layouts, "layout"); - applyFileOverlay(assets, anims, "anim"); - applyFileOverlay(assets, xmls, "xml"); - applyFileOverlay(assets, raws, "raw"); - applyFileOverlay(assets, colors, "color"); - applyFileOverlay(assets, menus, "menu"); + if (!applyFileOverlay(assets, drawables, "drawable") || + !applyFileOverlay(assets, layouts, "layout") || + !applyFileOverlay(assets, anims, "anim") || + !applyFileOverlay(assets, xmls, "xml") || + !applyFileOverlay(assets, raws, "raw") || + !applyFileOverlay(assets, colors, "color") || + !applyFileOverlay(assets, menus, "menu")) { + return UNKNOWN_ERROR; + } bool hasErrors = false; @@ -1013,7 +1068,15 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets) // Generate final compiled manifest file. manifestFile->clearData(); - err = compileXmlFile(assets, manifestFile, &table); + sp<XMLNode> manifestTree = XMLNode::parse(manifestFile); + if (manifestTree == NULL) { + return UNKNOWN_ERROR; + } + err = massageManifest(bundle, manifestTree); + if (err < NO_ERROR) { + return err; + } + err = compileXmlFile(assets, manifestTree, manifestFile, &table); if (err < NO_ERROR) { return err; } diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp index ef11a83..b004664 100644 --- a/tools/aapt/ResourceTable.cpp +++ b/tools/aapt/ResourceTable.cpp @@ -23,6 +23,16 @@ status_t compileXmlFile(const sp<AaptAssets>& assets, if (root == NULL) { return UNKNOWN_ERROR; } + + return compileXmlFile(assets, root, target, table, options); +} + +status_t compileXmlFile(const sp<AaptAssets>& assets, + const sp<XMLNode>& root, + const sp<AaptFile>& target, + ResourceTable* table, + int options) +{ if ((options&XML_COMPILE_STRIP_WHITESPACE) != 0) { root->removeWhitespace(true, NULL); } else if ((options&XML_COMPILE_COMPACT_WHITESPACE) != 0) { @@ -651,6 +661,7 @@ status_t compileResourceFile(Bundle* bundle, const String16 string_array16("string-array"); const String16 integer_array16("integer-array"); const String16 public16("public"); + const String16 public_padding16("public-padding"); const String16 private_symbols16("private-symbols"); const String16 skip16("skip"); const String16 eat_comment16("eat-comment"); @@ -685,7 +696,7 @@ status_t compileResourceFile(Bundle* bundle, bool hasErrors = false; - uint32_t nextPublicId = 0; + DefaultKeyedVector<String16, uint32_t> nextPublicId(0); ResXMLTree::event_code_t code; do { @@ -718,6 +729,7 @@ status_t compileResourceFile(Bundle* bundle, String16 curType; int32_t curFormat = ResTable_map::TYPE_ANY; bool curIsBag = false; + bool curIsBagReplaceOnOverwrite = false; bool curIsStyled = false; bool curIsPseudolocalizable = false; bool localHasErrors = false; @@ -774,15 +786,15 @@ status_t compileResourceFile(Bundle* bundle, hasErrors = localHasErrors = true; } else { ident = identValue.data; - nextPublicId = ident+1; + nextPublicId.replaceValueFor(type, ident+1); } - } else if (nextPublicId == 0) { + } else if (nextPublicId.indexOfKey(type) < 0) { srcPos.error("No 'id' attribute supplied <public>," " and no previous id defined in this file.\n"); hasErrors = localHasErrors = true; } else if (!localHasErrors) { - ident = nextPublicId; - nextPublicId++; + ident = nextPublicId.valueFor(type); + nextPublicId.replaceValueFor(type, ident+1); } if (!localHasErrors) { @@ -816,6 +828,116 @@ status_t compileResourceFile(Bundle* bundle, } continue; + } else if (strcmp16(block.getElementName(&len), public_padding16.string()) == 0) { + SourcePos srcPos(in->getPrintableSource(), block.getLineNumber()); + + String16 type; + ssize_t typeIdx = block.indexOfAttribute(NULL, "type"); + if (typeIdx < 0) { + srcPos.error("A 'type' attribute is required for <public-padding>\n"); + hasErrors = localHasErrors = true; + } + type = String16(block.getAttributeStringValue(typeIdx, &len)); + + String16 name; + ssize_t nameIdx = block.indexOfAttribute(NULL, "name"); + if (nameIdx < 0) { + srcPos.error("A 'name' attribute is required for <public-padding>\n"); + hasErrors = localHasErrors = true; + } + name = String16(block.getAttributeStringValue(nameIdx, &len)); + + uint32_t start = 0; + ssize_t startIdx = block.indexOfAttribute(NULL, "start"); + if (startIdx >= 0) { + const char16_t* startStr = block.getAttributeStringValue(startIdx, &len); + Res_value startValue; + if (!ResTable::stringToInt(startStr, len, &startValue)) { + srcPos.error("Given 'start' attribute is not an integer: %s\n", + String8(block.getAttributeStringValue(startIdx, &len)).string()); + hasErrors = localHasErrors = true; + } else { + start = startValue.data; + } + } else if (nextPublicId.indexOfKey(type) < 0) { + srcPos.error("No 'start' attribute supplied <public-padding>," + " and no previous id defined in this file.\n"); + hasErrors = localHasErrors = true; + } else if (!localHasErrors) { + start = nextPublicId.valueFor(type); + } + + uint32_t end = 0; + ssize_t endIdx = block.indexOfAttribute(NULL, "end"); + if (endIdx >= 0) { + const char16_t* endStr = block.getAttributeStringValue(endIdx, &len); + Res_value endValue; + if (!ResTable::stringToInt(endStr, len, &endValue)) { + srcPos.error("Given 'end' attribute is not an integer: %s\n", + String8(block.getAttributeStringValue(endIdx, &len)).string()); + hasErrors = localHasErrors = true; + } else { + end = endValue.data; + } + } else { + srcPos.error("No 'end' attribute supplied <public-padding>\n"); + hasErrors = localHasErrors = true; + } + + if (end >= start) { + nextPublicId.replaceValueFor(type, end+1); + } else { + srcPos.error("Padding start '%ul' is after end '%ul'\n", + start, end); + hasErrors = localHasErrors = true; + } + + String16 comment( + block.getComment(&len) ? block.getComment(&len) : nulStr); + for (uint32_t curIdent=start; curIdent<=end; curIdent++) { + if (localHasErrors) { + break; + } + String16 curName(name); + char buf[64]; + sprintf(buf, "%d", (int)(end-curIdent+1)); + curName.append(String16(buf)); + + err = outTable->addEntry(srcPos, myPackage, type, curName, + String16("padding"), NULL, &curParams, false, + ResTable_map::TYPE_STRING, overwrite); + if (err < NO_ERROR) { + hasErrors = localHasErrors = true; + break; + } + err = outTable->addPublic(srcPos, myPackage, type, + curName, curIdent); + if (err < NO_ERROR) { + hasErrors = localHasErrors = true; + break; + } + sp<AaptSymbols> symbols = assets->getSymbolsFor(String8("R")); + if (symbols != NULL) { + symbols = symbols->addNestedSymbol(String8(type), srcPos); + } + if (symbols != NULL) { + symbols->makeSymbolPublic(String8(curName), srcPos); + symbols->appendComment(String8(curName), comment, srcPos); + } else { + srcPos.error("Unable to create symbols!\n"); + hasErrors = localHasErrors = true; + } + } + + while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { + if (code == ResXMLTree::END_TAG) { + if (strcmp16(block.getElementName(&len), public_padding16.string()) == 0) { + break; + } + } + } + continue; + } else if (strcmp16(block.getElementName(&len), private_symbols16.string()) == 0) { String16 pkg; ssize_t pkgIdx = block.indexOfAttribute(NULL, "package"); @@ -1050,6 +1172,7 @@ status_t compileResourceFile(Bundle* bundle, curTag = &array16; curType = array16; curIsBag = true; + curIsBagReplaceOnOverwrite = true; ssize_t formatIdx = block.indexOfAttribute(NULL, "format"); if (formatIdx >= 0) { String16 formatStr = String16(block.getAttributeStringValue( @@ -1068,12 +1191,14 @@ status_t compileResourceFile(Bundle* bundle, curType = array16; curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_STRING; curIsBag = true; + curIsBagReplaceOnOverwrite = true; curIsPseudolocalizable = true; } else if (strcmp16(block.getElementName(&len), integer_array16.string()) == 0) { curTag = &integer_array16; curType = array16; curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_INTEGER; curIsBag = true; + curIsBagReplaceOnOverwrite = true; } else { SourcePos(in->getPrintableSource(), block.getLineNumber()).error( "Found tag %s where item is expected\n", @@ -1108,9 +1233,10 @@ status_t compileResourceFile(Bundle* bundle, } if (!localHasErrors) { - err = outTable->startBag(SourcePos(in->getPrintableSource(), block.getLineNumber()), - myPackage, curType, ident, parentIdent, &curParams, - overwrite); + err = outTable->startBag(SourcePos(in->getPrintableSource(), + block.getLineNumber()), myPackage, curType, ident, + parentIdent, &curParams, + overwrite, curIsBagReplaceOnOverwrite); if (err != NO_ERROR) { hasErrors = localHasErrors = true; } @@ -1307,7 +1433,7 @@ status_t ResourceTable::addIncludedResources(Bundle* bundle, const sp<AaptAssets } else if (id != 0) { if (id == 127) { if (mHaveAppPackage) { - fprintf(stderr, "Included resource have two application packages!\n"); + fprintf(stderr, "Included resources have two application packages!\n"); return UNKNOWN_ERROR; } mHaveAppPackage = true; @@ -1390,8 +1516,9 @@ status_t ResourceTable::addEntry(const SourcePos& sourcePos, String8(value).string()); } #endif - - sp<Entry> e = getEntry(package, type, name, sourcePos, params, doSetIndex); + + sp<Entry> e = getEntry(package, type, name, sourcePos, overwrite, + params, doSetIndex); if (e == NULL) { return UNKNOWN_ERROR; } @@ -1408,6 +1535,7 @@ status_t ResourceTable::startBag(const SourcePos& sourcePos, const String16& name, const String16& bagParent, const ResTable_config* params, + bool overlay, bool replace, bool isId) { status_t result = NO_ERROR; @@ -1428,8 +1556,12 @@ status_t ResourceTable::startBag(const SourcePos& sourcePos, sourcePos.file.striing(), sourcePos.line, String8(type).string()); } #endif - - sp<Entry> e = getEntry(package, type, name, sourcePos, params); + if (overlay && !hasBagOrEntry(package, type, name)) { + sourcePos.error("Can't add new bags in an overlay. See '%s'\n", + String8(name).string()); + return UNKNOWN_ERROR; + } + sp<Entry> e = getEntry(package, type, name, sourcePos, overlay, params); if (e == NULL) { return UNKNOWN_ERROR; } @@ -1450,7 +1582,7 @@ status_t ResourceTable::startBag(const SourcePos& sourcePos, return result; } - if (replace) { + if (overlay && replace) { return e->emptyBag(sourcePos); } return result; @@ -1483,8 +1615,7 @@ status_t ResourceTable::addBag(const SourcePos& sourcePos, sourcePos.file.striing(), sourcePos.line, String8(type).string()); } #endif - - sp<Entry> e = getEntry(package, type, name, sourcePos, params); + sp<Entry> e = getEntry(package, type, name, sourcePos, replace, params); if (e == NULL) { return UNKNOWN_ERROR; } @@ -2767,7 +2898,7 @@ status_t ResourceTable::Entry::setItem(const SourcePos& sourcePos, mItem.sourcePos.file.string(), mItem.sourcePos.line); return UNKNOWN_ERROR; } - + mType = TYPE_ITEM; mItem = item; mItemFormat = format; @@ -3087,11 +3218,17 @@ status_t ResourceTable::Type::addPublic(const SourcePos& sourcePos, sp<ResourceTable::Entry> ResourceTable::Type::getEntry(const String16& entry, const SourcePos& sourcePos, const ResTable_config* config, - bool doSetIndex) + bool doSetIndex, + bool overlay) { int pos = -1; sp<ConfigList> c = mConfigs.valueFor(entry); if (c == NULL) { + if (overlay == true) { + sourcePos.error("Resource %s appears in overlay but not" + " in the base package.\n", String8(entry).string()); + return NULL; + } c = new ConfigList(entry, sourcePos); mConfigs.add(entry, c); pos = (int)mOrderedConfigs.size(); @@ -3390,6 +3527,7 @@ sp<ResourceTable::Entry> ResourceTable::getEntry(const String16& package, const String16& type, const String16& name, const SourcePos& sourcePos, + bool overlay, const ResTable_config* config, bool doSetIndex) { @@ -3397,7 +3535,7 @@ sp<ResourceTable::Entry> ResourceTable::getEntry(const String16& package, if (t == NULL) { return NULL; } - return t->getEntry(name, sourcePos, config, doSetIndex); + return t->getEntry(name, sourcePos, config, doSetIndex, overlay); } sp<const ResourceTable::Entry> ResourceTable::getEntry(uint32_t resID, diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h index 74ba326..ec4331a 100644 --- a/tools/aapt/ResourceTable.h +++ b/tools/aapt/ResourceTable.h @@ -15,6 +15,7 @@ using namespace std; +class XMLNode; class ResourceTable; enum { @@ -34,6 +35,12 @@ status_t compileXmlFile(const sp<AaptAssets>& assets, ResourceTable* table, int options = XML_COMPILE_STANDARD_RESOURCE); +status_t compileXmlFile(const sp<AaptAssets>& assets, + const sp<XMLNode>& xmlTree, + const sp<AaptFile>& target, + ResourceTable* table, + int options = XML_COMPILE_STANDARD_RESOURCE); + status_t compileResourceFile(Bundle* bundle, const sp<AaptAssets>& assets, const sp<AaptFile>& in, @@ -89,6 +96,7 @@ public: const String16& name, const String16& bagParent, const ResTable_config* params = NULL, + bool overlay = false, bool replace = false, bool isId = false); @@ -410,7 +418,8 @@ public: sp<Entry> getEntry(const String16& entry, const SourcePos& pos, const ResTable_config* config = NULL, - bool doSetIndex = false); + bool doSetIndex = false, + bool overlay = false); const SourcePos& getFirstPublicSourcePos() const { return *mFirstPublicSourcePos; } @@ -494,6 +503,7 @@ private: const String16& type, const String16& name, const SourcePos& pos, + bool overlay, const ResTable_config* config = NULL, bool doSetIndex = false); sp<const Entry> getEntry(uint32_t resID, diff --git a/tools/aapt/XMLNode.cpp b/tools/aapt/XMLNode.cpp index d476567..2a85bc7 100644 --- a/tools/aapt/XMLNode.cpp +++ b/tools/aapt/XMLNode.cpp @@ -524,12 +524,30 @@ const Vector<sp<XMLNode> >& XMLNode::getChildren() const return mChildren; } +const String8& XMLNode::getFilename() const +{ + return mFilename; +} + const Vector<XMLNode::attribute_entry>& XMLNode::getAttributes() const { return mAttributes; } +const XMLNode::attribute_entry* XMLNode::getAttribute(const String16& ns, + const String16& name) const +{ + for (size_t i=0; i<mAttributes.size(); i++) { + const attribute_entry& ae(mAttributes.itemAt(i)); + if (ae.ns == ns && ae.name == name) { + return &ae; + } + } + + return NULL; +} + const String16& XMLNode::getCData() const { return mChars; @@ -550,6 +568,38 @@ int32_t XMLNode::getEndLineNumber() const return mEndLineNumber; } +sp<XMLNode> XMLNode::searchElement(const String16& tagNamespace, const String16& tagName) +{ + if (getType() == XMLNode::TYPE_ELEMENT + && mNamespaceUri == tagNamespace + && mElementName == tagName) { + return this; + } + + for (size_t i=0; i<mChildren.size(); i++) { + sp<XMLNode> found = mChildren.itemAt(i)->searchElement(tagNamespace, tagName); + if (found != NULL) { + return found; + } + } + + return NULL; +} + +sp<XMLNode> XMLNode::getChildElement(const String16& tagNamespace, const String16& tagName) +{ + for (size_t i=0; i<mChildren.size(); i++) { + sp<XMLNode> child = mChildren.itemAt(i); + if (child->getType() == XMLNode::TYPE_ELEMENT + && child->mNamespaceUri == tagNamespace + && child->mElementName == tagName) { + return child; + } + } + + return NULL; +} + status_t XMLNode::addChild(const sp<XMLNode>& child) { if (getType() == TYPE_CDATA) { @@ -561,6 +611,17 @@ status_t XMLNode::addChild(const sp<XMLNode>& child) return NO_ERROR; } +status_t XMLNode::insertChildAt(const sp<XMLNode>& child, size_t index) +{ + if (getType() == TYPE_CDATA) { + SourcePos(mFilename, child->getStartLineNumber()).error("Child to CDATA node."); + return UNKNOWN_ERROR; + } + //printf("Adding child %p to parent %p\n", child.get(), this); + mChildren.insertAt(child, index); + return NO_ERROR; +} + status_t XMLNode::addAttribute(const String16& ns, const String16& name, const String16& value) { diff --git a/tools/aapt/XMLNode.h b/tools/aapt/XMLNode.h index 86548a2..a9bea43 100644 --- a/tools/aapt/XMLNode.h +++ b/tools/aapt/XMLNode.h @@ -68,6 +68,8 @@ public: const String16& getElementName() const; const Vector<sp<XMLNode> >& getChildren() const; + const String8& getFilename() const; + struct attribute_entry { attribute_entry() : index(~(uint32_t)0), nameResId(0) { @@ -91,6 +93,8 @@ public: const Vector<attribute_entry>& getAttributes() const; + const attribute_entry* getAttribute(const String16& ns, const String16& name) const; + const String16& getCData() const; const String16& getComment() const; @@ -98,8 +102,14 @@ public: int32_t getStartLineNumber() const; int32_t getEndLineNumber() const; + sp<XMLNode> searchElement(const String16& tagNamespace, const String16& tagName); + + sp<XMLNode> getChildElement(const String16& tagNamespace, const String16& tagName); + status_t addChild(const sp<XMLNode>& child); + status_t insertChildAt(const sp<XMLNode>& child, size_t index); + status_t addAttribute(const String16& ns, const String16& name, const String16& value); diff --git a/tools/aidl/AST.h b/tools/aidl/AST.h index 1dedd04..aec2164 100755 --- a/tools/aidl/AST.h +++ b/tools/aidl/AST.h @@ -5,6 +5,7 @@ #include <vector> #include <set> #include <stdarg.h> +#include <stdio.h> using namespace std; diff --git a/tools/layoutlib/bridge/src/android/graphics/Matrix.java b/tools/layoutlib/bridge/src/android/graphics/Matrix.java index 3f9a993..18c0e17 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Matrix.java +++ b/tools/layoutlib/bridge/src/android/graphics/Matrix.java @@ -24,8 +24,8 @@ import java.awt.geom.AffineTransform; */ public class Matrix extends _Original_Matrix { - float mValues[] = new float[9]; - + float mValues[] = new float[9]; + /** * Create an identity matrix */ @@ -40,7 +40,7 @@ public class Matrix extends _Original_Matrix { public Matrix(Matrix src) { set(src); } - + /** * Creates a Matrix object from the float array. The array becomes the internal storage * of the object. @@ -50,14 +50,14 @@ public class Matrix extends _Original_Matrix { assert data.length != 9; mValues = data; } - + @Override public void finalize() throws Throwable { // pass } - + //---------- Custom Methods - + /** * Adds the given transformation to the current Matrix * <p/>This in effect does this = this*matrix @@ -65,17 +65,17 @@ public class Matrix extends _Original_Matrix { */ private void addTransform(float[] matrix) { float[] tmp = new float[9]; - - // first row + + // first row tmp[0] = matrix[0] * mValues[0] + matrix[1] * mValues[3] + matrix[2] * mValues[6]; tmp[1] = matrix[0] * mValues[1] + matrix[1] * mValues[4] + matrix[2] * mValues[7]; tmp[2] = matrix[0] * mValues[2] + matrix[1] * mValues[5] + matrix[2] * mValues[8]; - + // 2nd row tmp[3] = matrix[3] * mValues[0] + matrix[4] * mValues[3] + matrix[5] * mValues[6]; tmp[4] = matrix[3] * mValues[1] + matrix[4] * mValues[4] + matrix[5] * mValues[7]; tmp[5] = matrix[3] * mValues[2] + matrix[4] * mValues[5] + matrix[5] * mValues[8]; - + // 3rd row tmp[6] = matrix[6] * mValues[0] + matrix[7] * mValues[3] + matrix[8] * mValues[6]; tmp[7] = matrix[6] * mValues[1] + matrix[7] * mValues[4] + matrix[8] * mValues[7]; @@ -84,16 +84,16 @@ public class Matrix extends _Original_Matrix { // copy the result over to mValues mValues = tmp; } - + public AffineTransform getTransform() { return new AffineTransform(mValues[0], mValues[1], mValues[2], mValues[3], mValues[4], mValues[5]); } - + public boolean hasPerspective() { return (mValues[6] != 0 || mValues[7] != 0 || mValues[8] != 1); } - + //---------- /** @@ -109,7 +109,7 @@ public class Matrix extends _Original_Matrix { } } } - + return true; } @@ -122,7 +122,7 @@ public class Matrix extends _Original_Matrix { public boolean rectStaysRect() { return (computeTypeMask() & kRectStaysRect_Mask) != 0; } - + /** * (deep) copy the src matrix into this matrix. If src is null, reset this * matrix to the identity matrix. @@ -151,10 +151,10 @@ public class Matrix extends _Original_Matrix { return false; } } - + return true; } - + return false; } @@ -179,7 +179,7 @@ public class Matrix extends _Original_Matrix { mValues[5] = dy; mValues[6] = 0; mValues[7] = 0; - mValues[7] = 1; + mValues[8] = 1; } /** @@ -200,7 +200,7 @@ public class Matrix extends _Original_Matrix { mValues[5] = -py; mValues[6] = 0; mValues[7] = 0; - mValues[7] = 1; + mValues[8] = 1; // scale addTransform(new float[] { sx, 0, 0, 0, sy, 0, 0, 0, 1 }); @@ -219,7 +219,7 @@ public class Matrix extends _Original_Matrix { mValues[5] = 0; mValues[6] = 0; mValues[7] = 0; - mValues[7] = 1; + mValues[8] = 1; } /** @@ -240,13 +240,13 @@ public class Matrix extends _Original_Matrix { mValues[5] = -py; mValues[6] = 0; mValues[7] = 0; - mValues[7] = 1; + mValues[8] = 1; // scale double rad = Math.toRadians(degrees); float cos = (float)Math.cos(rad); float sin = (float)Math.sin(rad); - addTransform(new float[] { cos, -sin, 0, sin, cos, 0, 0, 0, 1 }); + addTransform(new float[] { cos, -sin, 0, sin, cos, 0, 0, 0, 1 }); // translate back the pivot addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 }); } @@ -268,7 +268,7 @@ public class Matrix extends _Original_Matrix { mValues[5] = 0; mValues[6] = 0; mValues[7] = 0; - mValues[7] = 1; + mValues[8] = 1; } /** @@ -289,10 +289,10 @@ public class Matrix extends _Original_Matrix { mValues[5] = -py; mValues[6] = 0; mValues[7] = 0; - mValues[7] = 1; + mValues[8] = 1; // scale - addTransform(new float[] { cosValue, -sinValue, 0, sinValue, cosValue, 0, 0, 0, 1 }); + addTransform(new float[] { cosValue, -sinValue, 0, sinValue, cosValue, 0, 0, 0, 1 }); // translate back the pivot addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 }); } @@ -308,7 +308,7 @@ public class Matrix extends _Original_Matrix { mValues[5] = 0; mValues[6] = 0; mValues[7] = 0; - mValues[7] = 1; + mValues[8] = 1; } /** @@ -329,7 +329,7 @@ public class Matrix extends _Original_Matrix { mValues[5] = -py; mValues[6] = 0; mValues[7] = 0; - mValues[7] = 1; + mValues[8] = 1; // scale addTransform(new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 }); @@ -348,7 +348,7 @@ public class Matrix extends _Original_Matrix { mValues[5] = 0; mValues[6] = 0; mValues[7] = 0; - mValues[7] = 1; + mValues[8] = 1; } /** @@ -366,10 +366,10 @@ public class Matrix extends _Original_Matrix { tmp.addTransform(a.mValues); set(tmp); } - + return true; } - + @Override public boolean setConcat(_Original_Matrix a, _Original_Matrix b) { throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); @@ -384,7 +384,7 @@ public class Matrix extends _Original_Matrix { // create a matrix that will be multiply by this Matrix m = new Matrix(new float[] { 1, 0, dx, 0, 1, dy, 0, 0, 1 }); m.addTransform(this.mValues); - + System.arraycopy(m.mValues, 0, mValues, 0, 9); return true; } @@ -399,7 +399,7 @@ public class Matrix extends _Original_Matrix { m.setScale(sx, sy, px, py); m.addTransform(mValues); set(m); - + return true; } @@ -413,7 +413,7 @@ public class Matrix extends _Original_Matrix { m.setScale(sx, sy); m.addTransform(mValues); set(m); - + return true; } @@ -427,7 +427,7 @@ public class Matrix extends _Original_Matrix { m.setRotate(degrees, px, py); m.addTransform(mValues); set(m); - + return true; } @@ -441,7 +441,7 @@ public class Matrix extends _Original_Matrix { m.setRotate(degrees); m.addTransform(mValues); set(m); - + return true; } @@ -455,7 +455,7 @@ public class Matrix extends _Original_Matrix { m.setSkew(kx, ky, px, py); m.addTransform(mValues); set(m); - + return true; } @@ -469,7 +469,7 @@ public class Matrix extends _Original_Matrix { m.setSkew(kx, ky); m.addTransform(mValues); set(m); - + return true; } @@ -481,10 +481,10 @@ public class Matrix extends _Original_Matrix { Matrix m = new Matrix(other); other.addTransform(mValues); set(m); - + return true; } - + @Override public boolean preConcat(_Original_Matrix other) { throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); @@ -513,7 +513,7 @@ public class Matrix extends _Original_Matrix { addTransform(new float[] { sx, 0, 0, 0, sy, 0, 0, 0, 1 }); // translate back the pivot addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 }); - + return true; } @@ -540,10 +540,10 @@ public class Matrix extends _Original_Matrix { double rad = Math.toRadians(degrees); float cos = (float)Math.cos(rad); float sin = (float)Math.sin(rad); - addTransform(new float[] { cos, -sin, 0, sin, cos, 0, 0, 0, 1 }); + addTransform(new float[] { cos, -sin, 0, sin, cos, 0, 0, 0, 1 }); // translate back the pivot addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 }); - + return true; } @@ -557,7 +557,7 @@ public class Matrix extends _Original_Matrix { float cos = (float)Math.cos(rad); float sin = (float)Math.sin(rad); addTransform(new float[] { cos, -sin, 0, sin, cos, 0, 0, 0, 1 }); - + return true; } @@ -574,7 +574,7 @@ public class Matrix extends _Original_Matrix { addTransform(new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 }); // translate back the pivot addTransform(new float[] { 1, 0, px, 0, 1, py, 0, 0, 1 }); - + return true; } @@ -585,7 +585,7 @@ public class Matrix extends _Original_Matrix { @Override public boolean postSkew(float kx, float ky) { addTransform(new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 }); - + return true; } @@ -595,7 +595,7 @@ public class Matrix extends _Original_Matrix { */ public boolean postConcat(Matrix other) { addTransform(other.mValues); - + return true; } @@ -603,7 +603,7 @@ public class Matrix extends _Original_Matrix { public boolean postConcat(_Original_Matrix other) { throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); } - + /** Controlls how the src rect should align into the dst rect for setRectToRect(). */ @@ -634,7 +634,7 @@ public class Matrix extends _Original_Matrix { */ END (3); - // the native values must match those in SkMatrix.h + // the native values must match those in SkMatrix.h ScaleToFit(int nativeInt) { this.nativeInt = nativeInt; } @@ -655,7 +655,7 @@ public class Matrix extends _Original_Matrix { if (dst == null || src == null) { throw new NullPointerException(); } - + if (src.isEmpty()) { reset(); return false; @@ -689,7 +689,7 @@ public class Matrix extends _Original_Matrix { } else { diff = dst.height() - src.height() * sy; } - + if (stf == ScaleToFit.CENTER) { diff = diff / 2; } @@ -712,12 +712,12 @@ public class Matrix extends _Original_Matrix { mValues[8] = 1; return true; } - + @Override public boolean setRectToRect(RectF src, RectF dst, _Original_Matrix.ScaleToFit stf) { throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); } - + /** * Set the matrix such that the specified src points would map to the * specified dst points. The "points" are represented as an array of floats, @@ -749,7 +749,7 @@ public class Matrix extends _Original_Matrix { public boolean invert(Matrix inverse) { throw new UnsupportedOperationException("STUB NEEDED"); } - + @Override public boolean invert(_Original_Matrix inverse) { throw new UnsupportedOperationException("CALL TO PARENT FORBIDDEN"); @@ -772,7 +772,7 @@ public class Matrix extends _Original_Matrix { checkPointArrays(src, srcIndex, dst, dstIndex, pointCount); throw new UnsupportedOperationException("STUB NEEDED"); } - + /** * Apply this matrix to the array of 2D vectors specified by src, and write * the transformed vectors into the array of vectors specified by dst. The @@ -790,7 +790,7 @@ public class Matrix extends _Original_Matrix { checkPointArrays(src, srcIndex, dst, dstIndex, vectorCount); throw new UnsupportedOperationException("STUB NEEDED"); } - + /** * Apply this matrix to the array of 2D points specified by src, and write * the transformed points into the array of points specified by dst. The @@ -883,7 +883,7 @@ public class Matrix extends _Original_Matrix { public float mapRadius(float radius) { throw new UnsupportedOperationException("STUB NEEDED"); } - + /** Copy 9 values from the matrix into the array. */ @Override @@ -907,7 +907,7 @@ public class Matrix extends _Original_Matrix { } System.arraycopy(values, 0, mValues, 0, mValues.length); } - + @SuppressWarnings("unused") private final static int kIdentity_Mask = 0; private final static int kTranslate_Mask = 0x01; //!< set if the matrix has translation @@ -917,7 +917,7 @@ public class Matrix extends _Original_Matrix { private final static int kRectStaysRect_Mask = 0x10; @SuppressWarnings("unused") private final static int kUnknown_Mask = 0x80; - + @SuppressWarnings("unused") private final static int kAllMasks = kTranslate_Mask | kScale_Mask | @@ -942,43 +942,43 @@ public class Matrix extends _Original_Matrix { if (mValues[6] != 0. || mValues[7] != 0. || mValues[8] != 1.) { mask |= kPerspective_Mask; } - + if (mValues[2] != 0. || mValues[5] != 0.) { mask |= kTranslate_Mask; } - + float m00 = mValues[0]; float m01 = mValues[1]; float m10 = mValues[3]; float m11 = mValues[4]; - + if (m01 != 0. || m10 != 0.) { mask |= kAffine_Mask; } - + if (m00 != 1. || m11 != 1.) { mask |= kScale_Mask; } - + if ((mask & kPerspective_Mask) == 0) { // map non-zero to 1 int im00 = m00 != 0 ? 1 : 0; int im01 = m01 != 0 ? 1 : 0; int im10 = m10 != 0 ? 1 : 0; int im11 = m11 != 0 ? 1 : 0; - + // record if the (p)rimary and (s)econdary diagonals are all 0 or // all non-zero (answer is 0 or 1) int dp0 = (im00 | im11) ^ 1; // true if both are 0 int dp1 = im00 & im11; // true if both are 1 int ds0 = (im01 | im10) ^ 1; // true if both are 0 int ds1 = im01 & im10; // true if both are 1 - + // return 1 if primary is 1 and secondary is 0 or // primary is 0 and secondary is 1 mask |= ((dp0 & ds1) | (dp1 & ds0)) << kRectStaysRect_Shift; } - + return mask; } } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java index 47a7ec0..d0a1c46 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java @@ -55,6 +55,8 @@ import android.view.View.AttachInfo; import android.view.View.MeasureSpec; import android.view.WindowManager.LayoutParams; import android.widget.FrameLayout; +import android.widget.TabHost; +import android.widget.TabWidget; import java.lang.ref.SoftReference; import java.lang.reflect.Field; @@ -69,10 +71,10 @@ import java.util.Map; * {@link #computeLayout(IXmlPullParser, Object, int, int, String, boolean, Map, Map, IProjectCallback, ILayoutLog)}. */ public final class Bridge implements ILayoutBridge { - + private static final int DEFAULT_TITLE_BAR_HEIGHT = 25; private static final int DEFAULT_STATUS_BAR_HEIGHT = 25; - + public static class StaticMethodNotImplementedException extends RuntimeException { private static final long serialVersionUID = 1L; @@ -82,19 +84,20 @@ public final class Bridge implements ILayoutBridge { } /** - * Maps from id to resource name/type. + * Maps from id to resource name/type. This is for android.R only. */ private final static Map<Integer, String[]> sRMap = new HashMap<Integer, String[]>(); /** - * Same as sRMap except for int[] instead of int resources. + * Same as sRMap except for int[] instead of int resources. This is for android.R only. */ private final static Map<int[], String> sRArrayMap = new HashMap<int[], String>(); /** - * Reverse map compared to sRMap, resource type -> (resource name -> id) + * Reverse map compared to sRMap, resource type -> (resource name -> id). + * This is for android.R only. */ private final static Map<String, Map<String, Integer>> sRFullMap = new HashMap<String, Map<String,Integer>>(); - + private final static Map<Object, Map<String, SoftReference<Bitmap>>> sProjectBitmapCache = new HashMap<Object, Map<String, SoftReference<Bitmap>>>(); private final static Map<Object, Map<String, SoftReference<NinePatch>>> sProject9PatchCache = @@ -104,7 +107,7 @@ public final class Bridge implements ILayoutBridge { new HashMap<String, SoftReference<Bitmap>>(); private final static Map<String, SoftReference<NinePatch>> sFramework9PatchCache = new HashMap<String, SoftReference<NinePatch>>(); - + private static Map<String, Map<String, Integer>> sEnumValueMap; /** @@ -156,14 +159,14 @@ public final class Bridge implements ILayoutBridge { return sinit(fontOsLocation, enumValueMap); } - + private static synchronized boolean sinit(String fontOsLocation, Map<String, Map<String, Integer>> enumValueMap) { // When DEBUG_LAYOUT is set and is not 0 or false, setup a default listener // on static (native) methods which prints the signature on the console and // throws an exception. - // This is useful when testing the rendering in ADT to identify static native + // This is useful when testing the rendering in ADT to identify static native // methods that are ignored -- layoutlib_create makes them returns 0/false/null // which is generally OK yet might be a problem, so this is how you'd find out. // @@ -214,7 +217,7 @@ public final class Bridge implements ILayoutBridge { } else { return false; } - + sEnumValueMap = enumValueMap; // now parse com.android.internal.R (and only this one as android.R is a subset of @@ -226,13 +229,13 @@ public final class Bridge implements ILayoutBridge { // int[] does not implement equals/hashCode, and if the parsing used a different class // loader for the R class, this would NOT work. Class<?> r = com.android.internal.R.class; - + for (Class<?> inner : r.getDeclaredClasses()) { String resType = inner.getSimpleName(); Map<String, Integer> fullMap = new HashMap<String, Integer>(); sRFullMap.put(resType, fullMap); - + for (Field f : inner.getDeclaredFields()) { // only process static final fields. Since the final attribute may have // been altered by layoutlib_create, we only check static @@ -243,7 +246,7 @@ public final class Bridge implements ILayoutBridge { // if the object is an int[] we put it in sRArrayMap sRArrayMap.put((int[]) f.get(null), f.getName()); } else if (type == int.class) { - Integer value = (Integer) f.get(null); + Integer value = (Integer) f.get(null); sRMap.put(value, new String[] { f.getName(), resType }); fullMap.put(f.getName(), value); } else { @@ -281,7 +284,7 @@ public final class Bridge implements ILayoutBridge { themeName = themeName.substring(1); isProjectTheme = true; } - + return computeLayout(layoutDescription, projectKey, screenWidth, screenHeight, DisplayMetrics.DEFAULT_DENSITY, DisplayMetrics.DEFAULT_DENSITY, DisplayMetrics.DEFAULT_DENSITY, @@ -294,6 +297,7 @@ public final class Bridge implements ILayoutBridge { * (non-Javadoc) * @see com.android.layoutlib.api.ILayoutBridge#computeLayout(com.android.layoutlib.api.IXmlPullParser, java.lang.Object, int, int, java.lang.String, boolean, java.util.Map, java.util.Map, com.android.layoutlib.api.IProjectCallback, com.android.layoutlib.api.ILayoutLog) */ + @Deprecated public ILayoutResult computeLayout(IXmlPullParser layoutDescription, Object projectKey, int screenWidth, int screenHeight, String themeName, boolean isProjectTheme, Map<String, Map<String, IResourceValue>> projectResources, @@ -319,7 +323,7 @@ public final class Bridge implements ILayoutBridge { if (logger == null) { logger = sDefaultLogger; } - + synchronized (sDefaultLogger) { sLogger = logger; } @@ -327,12 +331,12 @@ public final class Bridge implements ILayoutBridge { // find the current theme and compute the style inheritance map Map<IStyleResourceValue, IStyleResourceValue> styleParentMap = new HashMap<IStyleResourceValue, IStyleResourceValue>(); - + IStyleResourceValue currentTheme = computeStyleMaps(themeName, isProjectTheme, projectResources.get(BridgeConstants.RES_STYLE), frameworkResources.get(BridgeConstants.RES_STYLE), styleParentMap); - - BridgeContext context = null; + + BridgeContext context = null; try { // setup the display Metrics. DisplayMetrics metrics = new DisplayMetrics(); @@ -347,29 +351,32 @@ public final class Bridge implements ILayoutBridge { frameworkResources, styleParentMap, customViewLoader, logger); BridgeInflater inflater = new BridgeInflater(context, customViewLoader); context.setBridgeInflater(inflater); - + IResourceValue windowBackground = null; int screenOffset = 0; if (currentTheme != null) { windowBackground = context.findItemInStyle(currentTheme, "windowBackground"); windowBackground = context.resolveResValue(windowBackground); - + screenOffset = getScreenOffset(currentTheme, context); } - + // we need to make sure the Looper has been initialized for this thread. // this is required for View that creates Handler objects. if (Looper.myLooper() == null) { Looper.prepare(); } - + BridgeXmlBlockParser parser = new BridgeXmlBlockParser(layoutDescription, context, false /* platformResourceFlag */); - + ViewGroup root = new FrameLayout(context); - + View view = inflater.inflate(parser, root); - + + // post-inflate process. For now this supports TabHost/TabWidget + postInflateProcess(view, customViewLoader); + // set the AttachInfo on the root view. AttachInfo info = new AttachInfo(new WindowSession(), new Window(), new Handler(), null); @@ -392,16 +399,19 @@ public final class Bridge implements ILayoutBridge { // measure the views view.measure(w_spec, h_spec); view.layout(0, screenOffset, screenWidth, screenHeight); - + // draw them BridgeCanvas canvas = new BridgeCanvas(screenWidth, screenHeight - screenOffset, logger); - + root.draw(canvas); canvas.dispose(); - + return new LayoutResult(visit(((ViewGroup)view).getChildAt(0), context), canvas.getImage()); + } catch (PostInflateException e) { + return new LayoutResult(ILayoutResult.ERROR, "Error during post inflation process:\n" + + e.getMessage()); } catch (Throwable e) { // get the real cause of the exception. Throwable t = e; @@ -419,7 +429,7 @@ public final class Bridge implements ILayoutBridge { // Make sure to remove static references, otherwise we could not unload the lib BridgeResources.clearSystem(); BridgeAssetManager.clearSystem(); - + // Remove the global logger synchronized (sDefaultLogger) { sLogger = sDefaultLogger; @@ -437,18 +447,18 @@ public final class Bridge implements ILayoutBridge { sProject9PatchCache.remove(projectKey); } } - + /** * Returns details of a framework resource from its integer value. * @param value the integer value * @return an array of 2 strings containing the resource name and type, or null if the id - * does not match any resource. + * does not match any resource. */ public static String[] resolveResourceValue(int value) { return sRMap.get(value); - + } - + /** * Returns the name of a framework resource whose value is an int array. * @param array @@ -456,7 +466,7 @@ public final class Bridge implements ILayoutBridge { public static String resolveResourceValue(int[] array) { return sRArrayMap.get(array); } - + /** * Returns the integer id of a framework resource, from a given resource type and resource name. * @param type the type of the resource @@ -468,15 +478,15 @@ public final class Bridge implements ILayoutBridge { if (map != null) { return map.get(name); } - + return null; } - + static Map<String, Integer> getEnumValues(String attributeName) { if (sEnumValueMap != null) { return sEnumValueMap.get(attributeName); } - + return null; } @@ -507,13 +517,13 @@ public final class Bridge implements ILayoutBridge { return result; } - + /** * Compute style information from the given list of style for the project and framework. * @param themeName the name of the current theme. In order to differentiate project and * platform themes sharing the same name, all project themes must be prepended with * a '*' character. - * @param isProjectTheme Is this a project theme + * @param isProjectTheme Is this a project theme * @param inProjectStyleMap the project style map * @param inFrameworkStyleMap the framework style map * @param outInheritanceMap the map of style inheritance. This is filled by the method @@ -523,23 +533,23 @@ public final class Bridge implements ILayoutBridge { String themeName, boolean isProjectTheme, Map<String, IResourceValue> inProjectStyleMap, Map<String, IResourceValue> inFrameworkStyleMap, Map<IStyleResourceValue, IStyleResourceValue> outInheritanceMap) { - + if (inProjectStyleMap != null && inFrameworkStyleMap != null) { // first, get the theme IResourceValue theme = null; - + // project theme names have been prepended with a * if (isProjectTheme) { theme = inProjectStyleMap.get(themeName); } else { theme = inFrameworkStyleMap.get(themeName); } - + if (theme instanceof IStyleResourceValue) { // compute the inheritance map for both the project and framework styles computeStyleInheritance(inProjectStyleMap.values(), inProjectStyleMap, inFrameworkStyleMap, outInheritanceMap); - + // Compute the style inheritance for the framework styles/themes. // Since, for those, the style parent values do not contain 'android:' // we want to force looking in the framework style only to avoid using @@ -547,11 +557,11 @@ public final class Bridge implements ILayoutBridge { // To do this, we pass null in lieu of the project style map. computeStyleInheritance(inFrameworkStyleMap.values(), null /*inProjectStyleMap */, inFrameworkStyleMap, outInheritanceMap); - + return (IStyleResourceValue)theme; } } - + return null; } @@ -573,7 +583,7 @@ public final class Bridge implements ILayoutBridge { // first look for a specified parent. String parentName = style.getParentStyle(); - + // no specified parent? try to infer it from the name of the style. if (parentName == null) { parentName = getParentName(value.getName()); @@ -581,7 +591,7 @@ public final class Bridge implements ILayoutBridge { if (parentName != null) { parentStyle = getStyle(parentName, inProjectStyleMap, inFrameworkStyleMap); - + if (parentStyle != null) { outInheritanceMap.put(style, parentStyle); } @@ -589,7 +599,7 @@ public final class Bridge implements ILayoutBridge { } } } - + /** * Searches for and returns the {@link IStyleResourceValue} from a given name. * <p/>The format of the name can be: @@ -607,27 +617,27 @@ public final class Bridge implements ILayoutBridge { Map<String, IResourceValue> inProjectStyleMap, Map<String, IResourceValue> inFrameworkStyleMap) { boolean frameworkOnly = false; - + String name = parentName; - + // remove the useless @ if it's there if (name.startsWith(BridgeConstants.PREFIX_RESOURCE_REF)) { name = name.substring(BridgeConstants.PREFIX_RESOURCE_REF.length()); } - + // check for framework identifier. if (name.startsWith(BridgeConstants.PREFIX_ANDROID)) { frameworkOnly = true; name = name.substring(BridgeConstants.PREFIX_ANDROID.length()); } - + // at this point we could have the format style/<name>. we want only the name if (name.startsWith(BridgeConstants.REFERENCE_STYLE)) { name = name.substring(BridgeConstants.REFERENCE_STYLE.length()); } IResourceValue parent = null; - + // if allowed, search in the project resources. if (frameworkOnly == false && inProjectStyleMap != null) { parent = inProjectStyleMap.get(name); @@ -637,17 +647,17 @@ public final class Bridge implements ILayoutBridge { if (parent == null) { parent = inFrameworkStyleMap.get(name); } - + // make sure the result is the proper class type and return it. if (parent instanceof IStyleResourceValue) { return (IStyleResourceValue)parent; } - + sLogger.error(String.format("Unable to resolve parent style name: ", parentName)); - + return null; } - + /** * Computes the name of the parent style, or <code>null</code> if the style is a root style. */ @@ -656,10 +666,10 @@ public final class Bridge implements ILayoutBridge { if (index != -1) { return styleName.substring(0, index); } - + return null; } - + /** * Returns the top screen offset. This depends on whether the current theme defines the user * of the title and status bars. @@ -670,7 +680,7 @@ public final class Bridge implements ILayoutBridge { // get the title bar flag from the current theme. IResourceValue value = context.findItemInStyle(currentTheme, "windowNoTitle"); - + // because it may reference something else, we resolve it. value = context.resolveResValue(value); @@ -679,10 +689,10 @@ public final class Bridge implements ILayoutBridge { XmlUtils.convertValueToBoolean(value.getValue(), false /* defValue */) == false) { // get value from the theme. value = context.findItemInStyle(currentTheme, "windowTitleSize"); - + // resolve it value = context.resolveResValue(value); - + // default value offset = DEFAULT_TITLE_BAR_HEIGHT; @@ -690,17 +700,17 @@ public final class Bridge implements ILayoutBridge { if (value != null) { TypedValue typedValue = ResourceHelper.getValue(value.getValue()); if (typedValue != null) { - offset = (int)typedValue.getDimension(context.getResources().mMetrics); + offset = (int)typedValue.getDimension(context.getResources().mMetrics); } } } - + // get the fullscreen flag from the current theme. value = context.findItemInStyle(currentTheme, "windowFullscreen"); - + // because it may reference something else, we resolve it. value = context.resolveResValue(value); - + if (value == null || value.getValue() == null || XmlUtils.convertValueToBoolean(value.getValue(), false /* defValue */) == false) { // FIXME: Right now this is hard-coded in the platform, but once there's a constant, we'll need to use it. @@ -711,6 +721,94 @@ public final class Bridge implements ILayoutBridge { } /** + * Post process on a view hierachy that was just inflated. + * <p/>At the moment this only support TabHost: If {@link TabHost} is detected, look for the + * {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically + * based on the content of the {@link FrameLayout}. + * @param view the root view to process. + * @param projectCallback callback to the project. + */ + private void postInflateProcess(View view, IProjectCallback projectCallback) + throws PostInflateException { + if (view instanceof TabHost) { + setupTabHost((TabHost)view, projectCallback); + } else if (view instanceof ViewGroup) { + ViewGroup group = (ViewGroup)view; + final int count = group.getChildCount(); + for (int c = 0 ; c < count ; c++) { + View child = group.getChildAt(c); + postInflateProcess(child, projectCallback); + } + } + } + + /** + * Sets up a {@link TabHost} object. + * @param tabHost the TabHost to setup. + * @param projectCallback The project callback object to access the project R class. + * @throws PostInflateException + */ + private void setupTabHost(TabHost tabHost, IProjectCallback projectCallback) + throws PostInflateException { + // look for the TabWidget, and the FrameLayout. They have their own specific names + View v = tabHost.findViewById(android.R.id.tabs); + + if (v == null) { + throw new PostInflateException( + "TabHost requires a TabWidget with id \"android:id/tabs\".\n"); + } + + if ((v instanceof TabWidget) == false) { + throw new PostInflateException(String.format( + "TabHost requires a TabWidget with id \"android:id/tabs\".\n" + + "View found with id 'tabs' is '%s'", v.getClass().getCanonicalName())); + } + + v = tabHost.findViewById(android.R.id.tabcontent); + + if (v == null) { + // TODO: see if we can fake tabs even without the FrameLayout (same below when the framelayout is empty) + throw new PostInflateException( + "TabHost requires a FrameLayout with id \"android:id/tabcontent\"."); + } + + if ((v instanceof FrameLayout) == false) { + throw new PostInflateException(String.format( + "TabHost requires a FrameLayout with id \"android:id/tabcontent\".\n" + + "View found with id 'tabcontent' is '%s'", v.getClass().getCanonicalName())); + } + + FrameLayout content = (FrameLayout)v; + + // now process the content of the framelayout and dynamically create tabs for it. + final int count = content.getChildCount(); + + if (count == 0) { + throw new PostInflateException( + "The FrameLayout for the TabHost has no content. Rendering failed.\n"); + } + + // this must be called before addTab() so that the TabHost searches its TabWidget + // and FrameLayout. + tabHost.setup(); + + // for each child of the framelayout, add a new TabSpec + for (int i = 0 ; i < count ; i++) { + View child = content.getChildAt(i); + String tabSpec = String.format("tab_spec%d", i+1); + int id = child.getId(); + String[] resource = projectCallback.resolveResourceValue(id); + String name; + if (resource != null) { + name = resource[0]; // 0 is resource name, 1 is resource type. + } else { + name = String.format("Tab %d", i+1); // default name if id is unresolved. + } + tabHost.addTab(tabHost.newTabSpec(tabSpec).setIndicator(name).setContent(id)); + } + } + + /** * Returns the bitmap for a specific path, from a specific project cache, or from the * framework cache. * @param value the path of the bitmap @@ -750,7 +848,7 @@ public final class Bridge implements ILayoutBridge { map = new HashMap<String, SoftReference<Bitmap>>(); sProjectBitmapCache.put(projectKey, map); } - + map.put(value, new SoftReference<Bitmap>(bmp)); } else { sFrameworkBitmapCache.put(value, new SoftReference<Bitmap>(bmp)); @@ -767,7 +865,7 @@ public final class Bridge implements ILayoutBridge { static NinePatch getCached9Patch(String value, Object projectKey) { if (projectKey != null) { Map<String, SoftReference<NinePatch>> map = sProject9PatchCache.get(projectKey); - + if (map != null) { SoftReference<NinePatch> ref = map.get(value); if (ref != null) { @@ -780,7 +878,7 @@ public final class Bridge implements ILayoutBridge { return ref.get(); } } - + return null; } @@ -798,13 +896,21 @@ public final class Bridge implements ILayoutBridge { map = new HashMap<String, SoftReference<NinePatch>>(); sProject9PatchCache.put(projectKey, map); } - + map.put(value, new SoftReference<NinePatch>(ninePatch)); } else { sFramework9PatchCache.put(value, new SoftReference<NinePatch>(ninePatch)); } } + private static final class PostInflateException extends Exception { + private static final long serialVersionUID = 1L; + + public PostInflateException(String message) { + super(message); + } + } + /** * Implementation of {@link IWindowSession} so that mSession is not null in * the {@link SurfaceView}. @@ -839,7 +945,7 @@ public final class Bridge implements ILayoutBridge { // pass for now. return false; } - + @SuppressWarnings("unused") public MotionEvent getPendingPointerMove(IWindow arg0) throws RemoteException { // pass for now. @@ -863,7 +969,7 @@ public final class Bridge implements ILayoutBridge { public void getDisplayFrame(IWindow window, Rect outDisplayFrame) { // pass for now. } - + @SuppressWarnings("unused") public void remove(IWindow arg0) throws RemoteException { // pass for now. @@ -883,13 +989,13 @@ public final class Bridge implements ILayoutBridge { Rect visibleInsets) { // pass for now. } - + public IBinder asBinder() { // pass for now. return null; } } - + /** * Implementation of {@link IWindow} to pass to the {@link AttachInfo}. */ diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeAssetManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeAssetManager.java index 1fa11af..06dd96f 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeAssetManager.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeAssetManager.java @@ -59,7 +59,7 @@ public class BridgeAssetManager extends AssetManager { public void setConfiguration(int mcc, int mnc, String locale, int orientation, int touchscreen, int density, int keyboard, int keyboardHidden, int navigation, int screenWidth, int screenHeight, - int version) { + int screenLayout, int version) { Configuration c = new Configuration(); c.mcc = mcc; @@ -70,5 +70,6 @@ public class BridgeAssetManager extends AssetManager { c.keyboardHidden = keyboardHidden; c.navigation = navigation; c.orientation = orientation; + c.screenLayout = screenLayout; } } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java index f434e14..69f3d9c 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeContext.java @@ -29,6 +29,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.SharedPreferences; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.AssetManager; import android.content.res.Configuration; @@ -960,12 +961,24 @@ public final class BridgeContext extends Context { } @Override + public ApplicationInfo getApplicationInfo() { + // TODO Auto-generated method stub + return null; + } + + @Override public String getPackageResourcePath() { // TODO Auto-generated method stub return null; } @Override + public File getSharedPrefsFile(String name) { + // TODO Auto-generated method stub + return null; + } + + @Override public SharedPreferences getSharedPreferences(String arg0, int arg1) { // TODO Auto-generated method stub return null; @@ -1145,12 +1158,4 @@ public final class BridgeContext extends Context { public Context getApplicationContext() { throw new UnsupportedOperationException(); } - - /** - * @hide - */ - @Override - public float getApplicationScale() { - throw new UnsupportedOperationException(); - } } diff --git a/tools/localize/Android.mk b/tools/localize/Android.mk index 186177f..ab79f8d 100644 --- a/tools/localize/Android.mk +++ b/tools/localize/Android.mk @@ -53,4 +53,3 @@ ifeq (a,a) endif include $(BUILD_HOST_EXECUTABLE) - diff --git a/tools/localize/Perforce.cpp b/tools/localize/Perforce.cpp index 3425668..1c644ed 100644 --- a/tools/localize/Perforce.cpp +++ b/tools/localize/Perforce.cpp @@ -1,6 +1,7 @@ #include "Perforce.h" #include "log.h" #include <string.h> +#include <cstdio> #include <stdlib.h> #include <sstream> #include <sys/types.h> diff --git a/tools/localize/SourcePos.cpp b/tools/localize/SourcePos.cpp index 9d7c5c6..2533f0a 100644 --- a/tools/localize/SourcePos.cpp +++ b/tools/localize/SourcePos.cpp @@ -1,6 +1,7 @@ #include "SourcePos.h" #include <stdarg.h> +#include <cstdio> #include <set> using namespace std; diff --git a/tools/localize/Values.cpp b/tools/localize/Values.cpp index e396f8b..8623b97 100644 --- a/tools/localize/Values.cpp +++ b/tools/localize/Values.cpp @@ -1,5 +1,6 @@ #include "Values.h" #include <stdlib.h> +#include <cstdio> // ===================================================================================== diff --git a/tools/localize/XLIFFFile.cpp b/tools/localize/XLIFFFile.cpp index 51f81de..4e217d9 100644 --- a/tools/localize/XLIFFFile.cpp +++ b/tools/localize/XLIFFFile.cpp @@ -3,6 +3,7 @@ #include <algorithm> #include <sys/time.h> #include <time.h> +#include <cstdio> const char* const XLIFF_XMLNS = "urn:oasis:names:tc:xliff:document:1.2"; diff --git a/tools/localize/file_utils.cpp b/tools/localize/file_utils.cpp index bb82a9c..293e50e 100644 --- a/tools/localize/file_utils.cpp +++ b/tools/localize/file_utils.cpp @@ -1,14 +1,49 @@ #include <string.h> +#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include "file_utils.h" #include "Perforce.h" +#include <utils/String8.h> #include <sys/fcntl.h> #include <sys/stat.h> #include <errno.h> -#include <host/Directories.h> #include "log.h" +using namespace android; +using namespace std; + +static string +parent_dir(const string& path) +{ + return string(String8(path.c_str()).getPathDir().string()); +} + +static int +mkdirs(const char* last) +{ + String8 dest; + const char* s = last-1; + int err; + do { + s++; + if (s > last && (*s == '.' || *s == 0)) { + String8 part(last, s-last); + dest.appendPath(part); +#ifdef HAVE_MS_C_RUNTIME + err = _mkdir(dest.string()); +#else + err = mkdir(dest.string(), S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP); +#endif + if (err != 0) { + return err; + } + last = s+1; + } + } while (*s); + return 0; +} + string translated_file_name(const string& file, const string& locale) { diff --git a/tools/localize/localize_test.cpp b/tools/localize/localize_test.cpp index 63d904c..678cad8 100644 --- a/tools/localize/localize_test.cpp +++ b/tools/localize/localize_test.cpp @@ -1,6 +1,7 @@ #include "XLIFFFile.h" #include "ValuesFile.h" #include "localize.h" +#include <stdio.h> int pseudolocalize_xliff(XLIFFFile* xliff, bool expand); diff --git a/tools/localize/merge_res_and_xliff.cpp b/tools/localize/merge_res_and_xliff.cpp index 58a6554..1fdaa0e 100644 --- a/tools/localize/merge_res_and_xliff.cpp +++ b/tools/localize/merge_res_and_xliff.cpp @@ -3,6 +3,7 @@ #include "file_utils.h" #include "Perforce.h" #include "log.h" +#include <stdio.h> static set<StringResource>::const_iterator find_id(const set<StringResource>& s, const string& id, int index) diff --git a/tools/localize/merge_res_and_xliff_test.cpp b/tools/localize/merge_res_and_xliff_test.cpp index 5a2b0f4..e4ab562 100644 --- a/tools/localize/merge_res_and_xliff_test.cpp +++ b/tools/localize/merge_res_and_xliff_test.cpp @@ -1,5 +1,5 @@ #include "merge_res_and_xliff.h" - +#include <stdio.h> int merge_test() diff --git a/tools/localize/xmb.cpp b/tools/localize/xmb.cpp index 236705f..d8f6ff0 100644 --- a/tools/localize/xmb.cpp +++ b/tools/localize/xmb.cpp @@ -7,6 +7,7 @@ #include "XLIFFFile.h" #include <map> +#include <cstdio> using namespace std; |