diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/aapt/AaptAssets.cpp | 15 | ||||
-rw-r--r-- | tools/aapt/Bundle.h | 5 | ||||
-rw-r--r-- | tools/aapt/Command.cpp | 25 | ||||
-rw-r--r-- | tools/aapt/Main.cpp | 12 | ||||
-rw-r--r-- | tools/aapt/Resource.cpp | 66 | ||||
-rw-r--r-- | tools/aapt/ResourceTable.cpp | 35 | ||||
-rw-r--r-- | tools/aapt/XMLNode.cpp | 112 | ||||
-rw-r--r-- | tools/aapt/XMLNode.h | 1 | ||||
-rw-r--r-- | tools/aapt/ZipEntry.h | 10 | ||||
-rw-r--r-- | tools/layoutlib/Android.mk | 8 | ||||
-rw-r--r-- | tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java | 11 | ||||
-rw-r--r-- | tools/obbtool/Android.mk | 30 | ||||
-rw-r--r-- | tools/obbtool/Main.cpp | 224 |
13 files changed, 514 insertions, 40 deletions
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp index efc9619..e4f447e 100644 --- a/tools/aapt/AaptAssets.cpp +++ b/tools/aapt/AaptAssets.cpp @@ -766,6 +766,11 @@ bool AaptGroupEntry::getScreenLayoutSizeName(const char* name, (out->screenLayout&~ResTable_config::MASK_SCREENSIZE) | ResTable_config::SCREENSIZE_LARGE; return true; + } else if (strcmp(name, "xlarge") == 0) { + if (out) out->screenLayout = + (out->screenLayout&~ResTable_config::MASK_SCREENSIZE) + | ResTable_config::SCREENSIZE_XLARGE; + return true; } return false; @@ -1825,6 +1830,16 @@ ssize_t AaptAssets::slurpResourceTree(Bundle* bundle, const String8& srcDir) continue; } + if (bundle->getMaxResVersion() != NULL && group.version.length() != 0) { + int maxResInt = atoi(bundle->getMaxResVersion()); + const char *verString = group.version.string(); + int dirVersionInt = atoi(verString + 1); // skip 'v' in version name + if (dirVersionInt > maxResInt) { + fprintf(stderr, "max res %d, skipping %s\n", maxResInt, entry->d_name); + continue; + } + } + FileType type = getFileType(subdirName.string()); if (type == kFileTypeDirectory) { diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h index c198b0b..a1bc241 100644 --- a/tools/aapt/Bundle.h +++ b/tools/aapt/Bundle.h @@ -45,7 +45,7 @@ public: mRClassDir(NULL), mResourceIntermediatesDir(NULL), mManifestMinSdkVersion(NULL), mMinSdkVersion(NULL), mTargetSdkVersion(NULL), mMaxSdkVersion(NULL), mVersionCode(NULL), mVersionName(NULL), mCustomPackage(NULL), - mDebugMode(false), + mMaxResVersion(NULL), mDebugMode(false), mArgc(0), mArgv(NULL) {} ~Bundle(void) {} @@ -135,6 +135,8 @@ public: void setVersionName(const char* val) { mVersionName = val; } const char* getCustomPackage() const { return mCustomPackage; } void setCustomPackage(const char* val) { mCustomPackage = val; } + const char* getMaxResVersion() const { return mMaxResVersion; } + void setMaxResVersion(const char * val) { mMaxResVersion = val; } bool getDebugMode() { return mDebugMode; } void setDebugMode(bool val) { mDebugMode = val; } @@ -233,6 +235,7 @@ private: const char* mVersionCode; const char* mVersionName; const char* mCustomPackage; + const char* mMaxResVersion; bool mDebugMode; /* file specification */ diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp index 83057b8..f71ebb9 100644 --- a/tools/aapt/Command.cpp +++ b/tools/aapt/Command.cpp @@ -141,9 +141,9 @@ int doList(Bundle* bundle) if (bundle->getVerbose()) { printf("Archive: %s\n", zipFileName); printf( - " Length Method Size Ratio Date Time CRC-32 Name\n"); + " Length Method Size Ratio Offset Date Time CRC-32 Name\n"); printf( - "-------- ------ ------- ----- ---- ---- ------ ----\n"); + "-------- ------ ------- ----- ------- ---- ---- ------ ----\n"); } totalUncLen = totalCompLen = 0; @@ -159,12 +159,13 @@ int doList(Bundle* bundle) strftime(dateBuf, sizeof(dateBuf), "%m-%d-%y %H:%M", localtime(&when)); - printf("%8ld %-7.7s %7ld %3d%% %s %08lx %s\n", + printf("%8ld %-7.7s %7ld %3d%% %8zd %s %08lx %s\n", (long) entry->getUncompressedLen(), compressionName(entry->getCompressionMethod()), (long) entry->getCompressedLen(), calcPercent(entry->getUncompressedLen(), entry->getCompressedLen()), + (size_t) entry->getLFHOffset(), dateBuf, entry->getCRC32(), entry->getFileName()); @@ -336,6 +337,7 @@ enum { SMALL_SCREEN_ATTR = 0x01010284, NORMAL_SCREEN_ATTR = 0x01010285, LARGE_SCREEN_ATTR = 0x01010286, + XLARGE_SCREEN_ATTR = 0x010102bf, REQUIRED_ATTR = 0x0101028e, }; @@ -569,6 +571,7 @@ int doDump(Bundle* bundle) int smallScreen = 1; int normalScreen = 1; int largeScreen = 1; + int xlargeScreen = 1; String8 pkg; String8 activityName; String8 activityLabel; @@ -751,6 +754,8 @@ int doDump(Bundle* bundle) NORMAL_SCREEN_ATTR, NULL, 1); largeScreen = getIntegerAttribute(tree, LARGE_SCREEN_ATTR, NULL, 1); + xlargeScreen = getIntegerAttribute(tree, + XLARGE_SCREEN_ATTR, NULL, 1); } else if (tag == "uses-feature") { String8 name = getAttribute(tree, NAME_ATTR, &error); @@ -848,6 +853,15 @@ int doDump(Bundle* bundle) error.string()); goto bail; } + } else if (tag == "uses-package") { + String8 name = getAttribute(tree, NAME_ATTR, &error); + if (name != "" && error == "") { + printf("uses-package:'%s'\n", name.string()); + } else { + fprintf(stderr, "ERROR getting 'android:name' attribute: %s\n", + error.string()); + goto bail; + } } else if (tag == "original-package") { String8 name = getAttribute(tree, NAME_ATTR, &error); if (name != "" && error == "") { @@ -1079,10 +1093,15 @@ int doDump(Bundle* bundle) if (largeScreen > 0) { largeScreen = targetSdk >= 4 ? -1 : 0; } + if (xlargeScreen > 0) { + // Introduced in Honeycomb. + xlargeScreen = targetSdk >= 10 ? -1 : 0; + } printf("supports-screens:"); if (smallScreen != 0) printf(" 'small'"); if (normalScreen != 0) printf(" 'normal'"); if (largeScreen != 0) printf(" 'large'"); + if (xlargeScreen != 0) printf(" 'xlarge'"); printf("\n"); printf("locales:"); diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp index 229e13b..71c023d 100644 --- a/tools/aapt/Main.cpp +++ b/tools/aapt/Main.cpp @@ -62,6 +62,7 @@ void usage(void) " [--rename-manifest-package PACKAGE] \\\n" " [--rename-instrumentation-target-package PACKAGE] \\\n" " [--utf16] [--auto-add-overlay] \\\n" + " [--max-res-version VAL] \\\n" " [-I base-package [-I base-package ...]] \\\n" " [-A asset-source-dir] [-G class-list-file] [-P public-definitions-file] \\\n" " [-S resource-sources [-S resource-sources ...]] " @@ -131,6 +132,8 @@ void usage(void) " higher, the default encoding for resources will be in UTF-8.\n" " --target-sdk-version\n" " inserts android:targetSdkVersion in to manifest.\n" + " --max-res-version\n" + " ignores versioned resource directories above the given value.\n" " --values\n" " when used with \"dump resources\" also includes resource values.\n" " --version-code\n" @@ -421,6 +424,15 @@ int main(int argc, char* const argv[]) goto bail; } bundle.setMaxSdkVersion(argv[0]); + } else if (strcmp(cp, "-max-res-version") == 0) { + argc--; + argv++; + if (!argc) { + fprintf(stderr, "ERROR: No argument supplied for '--max-res-version' option\n"); + wantUsage = true; + goto bail; + } + bundle.setMaxResVersion(argv[0]); } else if (strcmp(cp, "-version-code") == 0) { argc--; argv++; diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp index 7ffd43b..c8ba904 100644 --- a/tools/aapt/Resource.cpp +++ b/tools/aapt/Resource.cpp @@ -1889,7 +1889,7 @@ addProguardKeepRule(ProguardKeepSet* keep, const String8& inClassName, className.append(inClassName); } } - + String8 rule("-keep class "); rule += className; rule += " { <init>(...); }"; @@ -1964,7 +1964,7 @@ writeProguardForAndroidManifest(ProguardKeepSet* keep, const sp<AaptAssets>& ass if (tag == "application") { inApplication = true; keepTag = true; - + String8 agent = getAttribute(tree, "http://schemas.android.com/apk/res/android", "backupAgent", &error); if (agent.length() > 0) { @@ -1997,9 +1997,17 @@ writeProguardForAndroidManifest(ProguardKeepSet* keep, const sp<AaptAssets>& ass return NO_ERROR; } +struct NamespaceAttributePair { + const char* ns; + const char* attr; + + NamespaceAttributePair(const char* n, const char* a) : ns(n), attr(a) {} + NamespaceAttributePair() : ns(NULL), attr(NULL) {} +}; + status_t writeProguardForXml(ProguardKeepSet* keep, const sp<AaptFile>& layoutFile, - const char* startTag, const char* altTag) + const char* startTag, const KeyedVector<String8, NamespaceAttributePair>* tagAttrPairs) { status_t err; ResXMLTree tree; @@ -2029,7 +2037,7 @@ writeProguardForXml(ProguardKeepSet* keep, const sp<AaptFile>& layoutFile, return NO_ERROR; } } - + while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) { if (code != ResXMLTree::START_TAG) { continue; @@ -2040,16 +2048,21 @@ writeProguardForXml(ProguardKeepSet* keep, const sp<AaptFile>& layoutFile, if (strchr(tag.string(), '.')) { addProguardKeepRule(keep, tag, NULL, layoutFile->getPrintableSource(), tree.getLineNumber()); - } else if (altTag != NULL && tag == altTag) { - ssize_t classIndex = tree.indexOfAttribute(NULL, "class"); - if (classIndex < 0) { - fprintf(stderr, "%s:%d: <view> does not have class attribute.\n", - layoutFile->getPrintableSource().string(), tree.getLineNumber()); - } else { - size_t len; - addProguardKeepRule(keep, - String8(tree.getAttributeStringValue(classIndex, &len)), NULL, - layoutFile->getPrintableSource(), tree.getLineNumber()); + } else if (tagAttrPairs != NULL) { + ssize_t tagIndex = tagAttrPairs->indexOfKey(tag); + if (tagIndex >= 0) { + const NamespaceAttributePair& nsAttr = tagAttrPairs->valueAt(tagIndex); + ssize_t attrIndex = tree.indexOfAttribute(nsAttr.ns, nsAttr.attr); + if (attrIndex < 0) { + // fprintf(stderr, "%s:%d: <%s> does not have attribute %s:%s.\n", + // layoutFile->getPrintableSource().string(), tree.getLineNumber(), + // tag.string(), nsAttr.ns, nsAttr.attr); + } else { + size_t len; + addProguardKeepRule(keep, + String8(tree.getAttributeStringValue(attrIndex, &len)), NULL, + layoutFile->getPrintableSource(), tree.getLineNumber()); + } } } } @@ -2057,25 +2070,42 @@ writeProguardForXml(ProguardKeepSet* keep, const sp<AaptFile>& layoutFile, return NO_ERROR; } +static void addTagAttrPair(KeyedVector<String8, NamespaceAttributePair>* dest, + const char* tag, const char* ns, const char* attr) { + dest->add(String8(tag), NamespaceAttributePair(ns, attr)); +} + status_t writeProguardForLayouts(ProguardKeepSet* keep, const sp<AaptAssets>& assets) { status_t err; + + // tag:attribute pairs that should be checked in layout files. + KeyedVector<String8, NamespaceAttributePair> kLayoutTagAttrPairs; + addTagAttrPair(&kLayoutTagAttrPairs, "view", NULL, "class"); + addTagAttrPair(&kLayoutTagAttrPairs, "fragment", RESOURCES_ANDROID_NAMESPACE, "name"); + + // tag:attribute pairs that should be checked in xml files. + KeyedVector<String8, NamespaceAttributePair> kXmlTagAttrPairs; + addTagAttrPair(&kXmlTagAttrPairs, "PreferenceScreen", RESOURCES_ANDROID_NAMESPACE, "fragment"); + addTagAttrPair(&kXmlTagAttrPairs, "Header", RESOURCES_ANDROID_NAMESPACE, "fragment"); + const Vector<sp<AaptDir> >& dirs = assets->resDirs(); const size_t K = dirs.size(); for (size_t k=0; k<K; k++) { const sp<AaptDir>& d = dirs.itemAt(k); const String8& dirName = d->getLeaf(); const char* startTag = NULL; - const char* altTag = NULL; + const KeyedVector<String8, NamespaceAttributePair>* tagAttrPairs = NULL; if ((dirName == String8("layout")) || (strncmp(dirName.string(), "layout-", 7) == 0)) { - altTag = "view"; + tagAttrPairs = &kLayoutTagAttrPairs; } else if ((dirName == String8("xml")) || (strncmp(dirName.string(), "xml-", 4) == 0)) { startTag = "PreferenceScreen"; + tagAttrPairs = &kXmlTagAttrPairs; } else { continue; } - + const KeyedVector<String8,sp<AaptGroup> > groups = d->getFiles(); const size_t N = groups.size(); for (size_t i=0; i<N; i++) { @@ -2083,7 +2113,7 @@ writeProguardForLayouts(ProguardKeepSet* keep, const sp<AaptAssets>& assets) const DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> >& files = group->getFiles(); const size_t M = files.size(); for (size_t j=0; j<M; j++) { - err = writeProguardForXml(keep, files.valueAt(j), startTag, altTag); + err = writeProguardForXml(keep, files.valueAt(j), startTag, tagAttrPairs); if (err < 0) { return err; } diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp index a2f085a..755b93b 100644 --- a/tools/aapt/ResourceTable.cpp +++ b/tools/aapt/ResourceTable.cpp @@ -573,6 +573,7 @@ status_t parseAndAddBag(Bundle* bundle, const String16& parentIdent, const String16& itemIdent, int32_t curFormat, + bool isFormatted, bool pseudolocalize, const bool overwrite, ResourceTable* outTable) @@ -583,7 +584,7 @@ status_t parseAndAddBag(Bundle* bundle, String16 str; Vector<StringPool::entry_style_span> spans; err = parseStyledString(bundle, in->getPrintableSource().string(), - block, item16, &str, &spans, + block, item16, &str, &spans, isFormatted, pseudolocalize); if (err != NO_ERROR) { return err; @@ -616,6 +617,7 @@ status_t parseAndAddEntry(Bundle* bundle, const String16& curTag, bool curIsStyled, int32_t curFormat, + bool isFormatted, bool pseudolocalize, const bool overwrite, ResourceTable* outTable) @@ -626,7 +628,7 @@ status_t parseAndAddEntry(Bundle* bundle, Vector<StringPool::entry_style_span> spans; err = parseStyledString(bundle, in->getPrintableSource().string(), block, curTag, &str, curIsStyled ? &spans : NULL, - pseudolocalize); + isFormatted, pseudolocalize); if (err < NO_ERROR) { return err; @@ -709,12 +711,18 @@ status_t compileResourceFile(Bundle* bundle, // useful attribute names and special values const String16 name16("name"); const String16 translatable16("translatable"); + const String16 formatted16("formatted"); const String16 false16("false"); const String16 myPackage(assets->getPackage()); bool hasErrors = false; - + + bool fileIsTranslatable = true; + if (strstr(in->getPrintableSource().string(), "donottranslate") != NULL) { + fileIsTranslatable = false; + } + DefaultKeyedVector<String16, uint32_t> nextPublicId(0); ResXMLTree::event_code_t code; @@ -751,6 +759,7 @@ status_t compileResourceFile(Bundle* bundle, bool curIsBagReplaceOnOverwrite = false; bool curIsStyled = false; bool curIsPseudolocalizable = false; + bool curIsFormatted = fileIsTranslatable; bool localHasErrors = false; if (strcmp16(block.getElementName(&len), skip16.string()) == 0) { @@ -1136,6 +1145,7 @@ status_t compileResourceFile(Bundle* bundle, String8 locale(rawLocale); String16 name; String16 translatable; + String16 formatted; size_t n = block.getAttributeCount(); for (size_t i = 0; i < n; i++) { @@ -1145,11 +1155,14 @@ status_t compileResourceFile(Bundle* bundle, name.setTo(block.getAttributeStringValue(i, &length)); } else if (strcmp16(attr, translatable16.string()) == 0) { translatable.setTo(block.getAttributeStringValue(i, &length)); + } else if (strcmp16(attr, formatted16.string()) == 0) { + formatted.setTo(block.getAttributeStringValue(i, &length)); } } if (name.size() > 0) { if (translatable == false16) { + curIsFormatted = false; // Untranslatable strings must only exist in the default [empty] locale if (locale.size() > 0) { fprintf(stderr, "aapt: warning: string '%s' in %s marked untranslatable but exists" @@ -1167,6 +1180,10 @@ status_t compileResourceFile(Bundle* bundle, } else { outTable->addLocalization(name, locale); } + + if (formatted == false16) { + curIsFormatted = false; + } } curTag = &string16; @@ -1356,7 +1373,7 @@ status_t compileResourceFile(Bundle* bundle, block.getPosition(&parserPosition); err = parseAndAddBag(bundle, in, &block, curParams, myPackage, curType, - ident, parentIdent, itemIdent, curFormat, + ident, parentIdent, itemIdent, curFormat, curIsFormatted, false, overwrite, outTable); if (err == NO_ERROR) { if (curIsPseudolocalizable && localeIsDefined(curParams) @@ -1365,8 +1382,8 @@ status_t compileResourceFile(Bundle* bundle, #if 1 block.setPosition(parserPosition); err = parseAndAddBag(bundle, in, &block, pseudoParams, myPackage, - curType, ident, parentIdent, itemIdent, curFormat, true, - overwrite, outTable); + curType, ident, parentIdent, itemIdent, curFormat, + curIsFormatted, true, overwrite, outTable); #endif } } @@ -1389,7 +1406,8 @@ status_t compileResourceFile(Bundle* bundle, block.getPosition(&parserPosition); err = parseAndAddEntry(bundle, in, &block, curParams, myPackage, curType, ident, - *curTag, curIsStyled, curFormat, false, overwrite, outTable); + *curTag, curIsStyled, curFormat, curIsFormatted, + false, overwrite, outTable); if (err < NO_ERROR) { // Why err < NO_ERROR instead of err != NO_ERROR? hasErrors = localHasErrors = true; @@ -1400,7 +1418,8 @@ status_t compileResourceFile(Bundle* bundle, // pseudolocalize here block.setPosition(parserPosition); err = parseAndAddEntry(bundle, in, &block, pseudoParams, myPackage, curType, - ident, *curTag, curIsStyled, curFormat, true, overwrite, outTable); + ident, *curTag, curIsStyled, curFormat, + curIsFormatted, true, overwrite, outTable); if (err != NO_ERROR) { hasErrors = localHasErrors = true; } diff --git a/tools/aapt/XMLNode.cpp b/tools/aapt/XMLNode.cpp index 4c59288..8551b0f 100644 --- a/tools/aapt/XMLNode.cpp +++ b/tools/aapt/XMLNode.cpp @@ -68,12 +68,118 @@ String16 getNamespaceResourcePackage(String16 namespaceUri, bool* outIsPublic) return String16(namespaceUri, namespaceUri.size()-prefixSize, prefixSize); } +status_t hasSubstitutionErrors(const char* fileName, + ResXMLTree* inXml, + String16 str16) +{ + const char16_t* str = str16.string(); + const char16_t* p = str; + const char16_t* end = str + str16.size(); + + bool nonpositional = false; + int argCount = 0; + + while (p < end) { + /* + * Look for the start of a Java-style substitution sequence. + */ + if (*p == '%' && p + 1 < end) { + p++; + + // A literal percent sign represented by %% + if (*p == '%') { + p++; + continue; + } + + argCount++; + + if (*p >= '0' && *p <= '9') { + do { + p++; + } while (*p >= '0' && *p <= '9'); + if (*p != '$') { + // This must be a size specification instead of position. + nonpositional = true; + } + } else if (*p == '<') { + // Reusing last argument; bad idea since it can be re-arranged. + nonpositional = true; + p++; + + // Optionally '$' can be specified at the end. + if (p < end && *p == '$') { + p++; + } + } else { + nonpositional = true; + } + + // Ignore flags and widths + while (p < end && (*p == '-' || + *p == '#' || + *p == '+' || + *p == ' ' || + *p == ',' || + *p == '(' || + (*p >= '0' && *p <= '9'))) { + p++; + } + + /* + * This is a shortcut to detect strings that are going to Time.format() + * instead of String.format() + * + * Comparison of String.format() and Time.format() args: + * + * String: ABC E GH ST X abcdefgh nost x + * Time: DEFGHKMS W Za d hkm s w yz + * + * Therefore we know it's definitely Time if we have: + * DFKMWZkmwyz + */ + if (p < end) { + switch (*p) { + case 'D': + case 'F': + case 'K': + case 'M': + case 'W': + case 'Z': + case 'k': + case 'm': + case 'w': + case 'y': + case 'z': + return NO_ERROR; + } + } + } + + p++; + } + + /* + * If we have more than one substitution in this string and any of them + * are not in positional form, give the user an error. + */ + if (argCount > 1 && nonpositional) { + SourcePos(String8(fileName), inXml->getLineNumber()).error( + "Multiple substitutions specified in non-positional format; " + "did you mean to add the formatted=\"false\" attribute?\n"); + return NOT_ENOUGH_DATA; + } + + return NO_ERROR; +} + status_t parseStyledString(Bundle* bundle, const char* fileName, ResXMLTree* inXml, const String16& endTag, String16* outString, Vector<StringPool::entry_style_span>* outSpans, + bool isFormatted, bool pseudolocalize) { Vector<StringPool::entry_style_span> spanStack; @@ -101,7 +207,11 @@ status_t parseStyledString(Bundle* bundle, std::string pseudo = pseudolocalize_string(orig); curString.append(String16(String8(pseudo.c_str()))); } else { - curString.append(text); + if (isFormatted && hasSubstitutionErrors(fileName, inXml, text) != NO_ERROR) { + return UNKNOWN_ERROR; + } else { + curString.append(text); + } } } else if (code == ResXMLTree::START_TAG) { const String16 element16(inXml->getElementName(&len)); diff --git a/tools/aapt/XMLNode.h b/tools/aapt/XMLNode.h index e9a263b..05624b7 100644 --- a/tools/aapt/XMLNode.h +++ b/tools/aapt/XMLNode.h @@ -25,6 +25,7 @@ status_t parseStyledString(Bundle* bundle, const String16& endTag, String16* outString, Vector<StringPool::entry_style_span>* outSpans, + bool isFormatted, bool isPseudolocalizable); void printXMLBlock(ResXMLTree* block); diff --git a/tools/aapt/ZipEntry.h b/tools/aapt/ZipEntry.h index 7f721b4..c2f3227 100644 --- a/tools/aapt/ZipEntry.h +++ b/tools/aapt/ZipEntry.h @@ -72,6 +72,11 @@ public: off_t getCompressedLen(void) const { return mCDE.mCompressedSize; } /* + * Return the offset of the local file header. + */ + off_t getLFHOffset(void) const { return mCDE.mLocalHeaderRelOffset; } + + /* * Return the absolute file offset of the start of the compressed or * uncompressed data. */ @@ -186,11 +191,6 @@ protected: void setModWhen(time_t when); /* - * Return the offset of the local file header. - */ - off_t getLFHOffset(void) const { return mCDE.mLocalHeaderRelOffset; } - - /* * Set the offset of the local file header, relative to the start of * the current file. */ diff --git a/tools/layoutlib/Android.mk b/tools/layoutlib/Android.mk index 6d606a9..135a633 100644 --- a/tools/layoutlib/Android.mk +++ b/tools/layoutlib/Android.mk @@ -52,13 +52,15 @@ include $(BUILD_SYSTEM)/base_rules.mk $(LOCAL_BUILT_MODULE): $(built_core_dep) \ $(built_framework_dep) \ $(built_layoutlib_create_jar) - @echo "host layoutlib_create: $@" - @mkdir -p $(dir $@) - @rm -f $@ + $(hide) echo "host layoutlib_create: $@" + $(hide) mkdir -p $(dir $@) + $(hide) rm -f $@ + $(hide) ls -l $(built_framework_classes) $(hide) java -jar $(built_layoutlib_create_jar) \ $@ \ $(built_core_classes) \ $(built_framework_classes) + $(hide) ls -l $(built_framework_classes) # 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 4201e80..f91f601 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java @@ -46,6 +46,7 @@ import android.os.RemoteException; import android.util.DisplayMetrics; import android.util.TypedValue; import android.view.BridgeInflater; +import android.view.InputChannel; import android.view.IWindow; import android.view.IWindowSession; import android.view.KeyEvent; @@ -990,13 +991,21 @@ public final class Bridge implements ILayoutBridge { private static final class WindowSession implements IWindowSession { @SuppressWarnings("unused") - public int add(IWindow arg0, LayoutParams arg1, int arg2, Rect arg3) + public int add(IWindow arg0, LayoutParams arg1, int arg2, Rect arg3, + InputChannel outInputchannel) throws RemoteException { // pass for now. return 0; } @SuppressWarnings("unused") + public int addWithoutInputChannel(IWindow arg0, LayoutParams arg1, int arg2, Rect arg3) + throws RemoteException { + // pass for now. + return 0; + } + + @SuppressWarnings("unused") public void finishDrawing(IWindow arg0) throws RemoteException { // pass for now. } diff --git a/tools/obbtool/Android.mk b/tools/obbtool/Android.mk new file mode 100644 index 0000000..b02c1cb --- /dev/null +++ b/tools/obbtool/Android.mk @@ -0,0 +1,30 @@ +# +# Copyright 2010 The Android Open Source Project +# +# Opaque Binary Blob (OBB) Tool +# + +# This tool is prebuilt if we're doing an app-only build. +ifeq ($(TARGET_BUILD_APPS),) + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + Main.cpp + +#LOCAL_C_INCLUDES += + +LOCAL_STATIC_LIBRARIES := \ + libutils \ + libcutils + +ifeq ($(HOST_OS),linux) +LOCAL_LDLIBS += -lpthread +endif + +LOCAL_MODULE := obbtool + +include $(BUILD_HOST_EXECUTABLE) + +endif # TARGET_BUILD_APPS diff --git a/tools/obbtool/Main.cpp b/tools/obbtool/Main.cpp new file mode 100644 index 0000000..49e077f --- /dev/null +++ b/tools/obbtool/Main.cpp @@ -0,0 +1,224 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <utils/ObbFile.h> +#include <utils/String8.h> + +#include <getopt.h> +#include <stdio.h> +#include <stdlib.h> + +using namespace android; + +static const char* gProgName = "obbtool"; +static const char* gProgVersion = "1.0"; + +static int wantUsage = 0; +static int wantVersion = 0; + +#define ADD_OPTS "n:v:o" +static const struct option longopts[] = { + {"help", no_argument, &wantUsage, 1}, + {"version", no_argument, &wantVersion, 1}, + + /* Args for "add" */ + {"name", required_argument, NULL, 'n'}, + {"version", required_argument, NULL, 'v'}, + {"overlay", optional_argument, NULL, 'o'}, + + {NULL, 0, NULL, '\0'} +}; + +struct package_info_t { + char* packageName; + int packageVersion; + bool overlay; +}; + +/* + * Print usage info. + */ +void usage(void) +{ + fprintf(stderr, "Opaque Binary Blob (OBB) Tool\n\n"); + fprintf(stderr, "Usage:\n"); + fprintf(stderr, + " %s a[dd] [ OPTIONS ] FILENAME\n" + " Adds an OBB signature to the file.\n\n", gProgName); + fprintf(stderr, + " %s r[emove] FILENAME\n" + " Removes the OBB signature from the file.\n\n", gProgName); + fprintf(stderr, + " %s i[nfo] FILENAME\n" + " Prints the OBB signature information of a file.\n\n", gProgName); +} + +void doAdd(const char* filename, struct package_info_t* info) { + ObbFile *obb = new ObbFile(); + if (obb->readFrom(filename)) { + fprintf(stderr, "ERROR: %s: OBB signature already present\n", filename); + return; + } + + obb->setPackageName(String8(info->packageName)); + obb->setVersion(info->packageVersion); + obb->setOverlay(info->overlay); + + if (!obb->writeTo(filename)) { + fprintf(stderr, "ERROR: %s: couldn't write OBB signature: %s\n", + filename, strerror(errno)); + return; + } + + fprintf(stderr, "OBB signature successfully written\n"); +} + +void doRemove(const char* filename) { + ObbFile *obb = new ObbFile(); + if (!obb->readFrom(filename)) { + fprintf(stderr, "ERROR: %s: no OBB signature present\n", filename); + return; + } + + if (!obb->removeFrom(filename)) { + fprintf(stderr, "ERROR: %s: couldn't remove OBB signature\n", filename); + return; + } + + fprintf(stderr, "OBB signature successfully removed\n"); +} + +void doInfo(const char* filename) { + ObbFile *obb = new ObbFile(); + if (!obb->readFrom(filename)) { + fprintf(stderr, "ERROR: %s: couldn't read OBB signature\n", filename); + return; + } + + printf("OBB info for '%s':\n", filename); + printf("Package name: %s\n", obb->getPackageName().string()); + printf(" Version: %d\n", obb->getVersion()); + printf(" Flags: 0x%08x\n", obb->getFlags()); + printf(" Overlay: %s\n", obb->isOverlay() ? "true" : "false"); +} + +/* + * Parse args. + */ +int main(int argc, char* const argv[]) +{ + const char *prog = argv[0]; + struct options *options; + int opt; + int option_index = 0; + struct package_info_t package_info; + + int result = 1; // pessimistically assume an error. + + if (argc < 2) { + wantUsage = 1; + goto bail; + } + + while ((opt = getopt_long(argc, argv, ADD_OPTS, longopts, &option_index)) != -1) { + switch (opt) { + case 0: + if (longopts[option_index].flag) + break; + fprintf(stderr, "'%s' requires an argument\n", longopts[option_index].name); + wantUsage = 1; + goto bail; + case 'n': + package_info.packageName = optarg; + break; + case 'v': { + char *end; + package_info.packageVersion = strtol(optarg, &end, 10); + if (*optarg == '\0' || *end != '\0') { + fprintf(stderr, "ERROR: invalid version; should be integer!\n\n"); + wantUsage = 1; + goto bail; + } + break; + } + case 'o': + package_info.overlay = true; + break; + case '?': + wantUsage = 1; + goto bail; + } + } + + if (wantVersion) { + fprintf(stderr, "%s %s\n", gProgName, gProgVersion); + } + + if (wantUsage) { + goto bail; + } + +#define CHECK_OP(name) \ + if (strncmp(op, name, opsize)) { \ + fprintf(stderr, "ERROR: unknown function '%s'!\n\n", op); \ + wantUsage = 1; \ + goto bail; \ + } + + if (optind < argc) { + const char* op = argv[optind++]; + const int opsize = strlen(op); + + if (optind >= argc) { + fprintf(stderr, "ERROR: filename required!\n\n"); + wantUsage = 1; + goto bail; + } + + const char* filename = argv[optind++]; + + switch (op[0]) { + case 'a': + CHECK_OP("add"); + if (package_info.packageName == NULL) { + fprintf(stderr, "ERROR: arguments required 'packageName' and 'version'\n"); + goto bail; + } + doAdd(filename, &package_info); + break; + case 'r': + CHECK_OP("remove"); + doRemove(filename); + break; + case 'i': + CHECK_OP("info"); + doInfo(filename); + break; + default: + fprintf(stderr, "ERROR: unknown command '%s'!\n\n", op); + wantUsage = 1; + goto bail; + } + } + +bail: + if (wantUsage) { + usage(); + result = 2; + } + + return result; +} |